Posts for December 2017

2017-12-16: Saving window position in Xfce session

TLDR: If you're having problems saving window position in your Xfce session, enable save on logout and then log out and back in. This will probably fix the problem (permanently, if you like keeping the same session and turn saving back off again). See below for the details.

I've been using Xfce for my desktop for some years now, and have had a recurring problem with saved sessions after a reboot. After logging in, all the applications from my saved session would be started, but all the workspace and window positioning data would be lost, so they'd just pile onto the default workspace like a train wreck.

Various other people on-line have reported this over the years (there are open bugs in Ubuntu, Xfce, and Red Hat bug trackers), and there was apparently a related bug fixed in Xfce 4.10, but I'm using 4.12. I would have given up (and have several times in the past), except that on one of my systems this works correctly. All the windows go back to their proper positions.

Today, I dug into the difference and finally solved it. Here it is, in case someone else stumbles across it.

Some up-front caveats that are or may be related:

  1. I rarely log out of my Xfce session, since this is a single-user laptop. I hibernate and keep restoring until I decide to do a reboot for kernel patches, or (and this is somewhat more likely) some change to the system invalidates the hibernate image and the system hangs on restore from hibernate and I force-reboot it. I also only sometimes use the Xfce toolbar to do a reboot; often, I just run reboot.

  2. I use xterm and Emacs, which are not horribly sophisticated X applications and which don't remember their own window positioning.

Xfce stores sessions in .cache/sessions in your home directory. The key discovery on close inspection is that there were two types of files in that directory on the working system, and only one on the non-working system.

The typical file will have a name like xfce4-session-hostname:0 and contains things like:

Client9_ClientId=2a654109b-e4d0-40e4-a910-e58717faa80b
Client9_Hostname=local/hostname
Client9_CloneCommand=xterm
Client9_RestartCommand=xterm,-xtsessionID,2a654109b-e4d0-40e4-a910-e58717faa80b
Client9_Program=xterm
Client9_UserId=user

This is the file that remembers all of the running applications. If you go into Settings -> Session and Startup and clear the session cache, files like this will be deleted. If you save your current session, a file like this will be created. This is how Xfce knows to start all of the same applications. But notice that nothing in the above preserves the positioning of the window. (I went down a rabbit hole thinking the session ID was somehow linking to that information elsewhere, but it's not.)

The working system had a second type of file in that directory named xfwm4-2d4c9d4cb-5f6b-41b4-b9d7-5cf7ac3d7e49.state. Looking in that file reveals entries like:

[CLIENT] 0x200000f
  [CLIENT_ID] 2a9e5b8ed-1851-4c11-82cf-e51710dcf733
  [CLIENT_LEADER] 0x200000f
  [RES_NAME] xterm
  [RES_CLASS] XTerm
  [WM_NAME] xterm
  [WM_COMMAND] (1) "xterm"
  [GEOMETRY] (860,35,817,1042)
  [GEOMETRY-MAXIMIZED] (860,35,817,1042)
  [SCREEN] 0
  [DESK] 2
  [FLAGS] 0x0

Notice the geometry and desk, which are exactly what we're looking for: the window location and the workspace it should be on. So the problem with window position not being saved was the absence of this file.

After some more digging, I discovered that while the first file is saved when you explicitly save your session, the second is not. However, it is saved on logout. So, I went to Settings -> Session and Startup and enabled automatically save session on logout in the General tab, logged out and back in again, and tada, the second file appeared. I then turned saving off again (since I set up my screens and then save them and don't want any subsequent changes saved unless I do so explicitly), and now my window position is reliably restored.

This also explains why some people see this and others don't: some people probably regularly use the Log Out button, and others ignore it and manually reboot (or just have their system crash).

Incidentally, this sort of problem, and the amount of digging that I had to do to solve it, is the reason why I'm in favor of writing man pages or some other documentation for every state file your software stores. Not only does it help people digging into weird problems, it helps you as the software author notice surprising oddities, like splitting session state across two separate state files, when you go to document them for the user.

2017-12-17: End of an FTP era

I just turned off anonymous FTP service on ftp.eyrie.org.

It's bittersweet, since I've been running an anonymous FTP server since some time around 1996 (longer than HTTP has been a widely-used thing), and at ftp.eyrie.org for nearly that long. The original service was wu-ftpd, as one did at the time, but it's been vsftpd for the past decade plus. (Amusingly, I now work for the author of vsftpd.)

All of the data is still there, at archives.eyrie.org as has been the case for more than a decade. I doubt anyone but me and a few people with ancient bookmarks will ever notice. The whole world switched over to HTTP many years ago, and about the only thing that ever connected to the anonymous FTP server was search engines. I was keeping it running out of nostalgia.

Explaining why I finally pulled the plug requires a bit of background on the FTP protocol. Many of those reading this may already be familiar, but I bet some people aren't, and it's somewhat interesting. The short version is that FTP is a very old protocol from a much different era of the Internet, and it does things in some very odd ways that are partly incompatible with modern networking.

FTP uses two separate network connections between the client and server: a control channel and a data channel. The client sends commands to the server (directory navigation and file upload and download commands, for example) over the control channel. Any data, including directory listings, is sent over the data channel, instead of in-line in the control channel the way almost every other protocol works.

One way to do the data transfer is for the client to send a PORT command to the server before initiating a data transfer, telling the server the local port on which the client was listening. The FTP server would then connect back to the client on that port, using a source port of 20, to send the data. This is called active mode.

This, of course, stopped working as soon as NAT and firewalls became part of networking and servers couldn't connect to clients. (It also has some security issues. Search for FTP bounce attack if you're curious.) Nearly the entire FTP world therefore switched to a different mechanism: passive mode. (This was in the protocol from very early on, but extremely old FTP servers sometimes didn't support it.) In this mode, the client would send the PASV command (EPSV in later versions with IPv6 support), and the server would respond with the ephemeral port on the server to use for data transfer. The client would then open a second connection to the server on that port for the data transfer.

Everything is now fine for the client: it just opens multiple connections to the same server on different ports. The problem is the server firewall. On the modern Internet, you don't want to allow any host on the Internet to open connections to arbitrary ports on the server, even ephemeral ports, for defense in depth against exposing some random service that happens to be running on that port. In standard FTP implementations, there's also no authentication binding between the ports, so some other client could race a client to its designated data port.

You therefore need some way to tell the firewall to allow a client to connect to its provided data port, but not any other port. With iptables, this is done by using the conntrack module and a related port rule. A good implementation has to look inside the contents of the control channel traffic and look for the reply to a PASV or EPSV command to extract the port number. The related port rule will then allow connections to that port from the client for as long as the main control channel lasts.

This has mostly worked for some time, but it's complicated, requires loading several other kernel modules to do this packet inspection, and requires using conntrack, which itself causes issues for some servers because it has to maintain a state table of open connections that has a limited size in the kernel. This conntrack approach also has other security issues around matching the wrong protocol (there's a ton of good information in this article), so modern Linux kernels require setting up special raw iptables rules to enable the correct conntrack helper. I got this working briefly in Debian squeeze with a separate ExecStartPre command for vsftpd to set up the iptables magic, but then it stopped working again for some reason that I never diagnosed.

I probably could get this working again by digging deeper into how the complex conntrack machinery works, but on further reflection, I decided to just turn the service off. It's had a good run, I don't think anyone uses it, and while this corner of Linux networking is moderately interesting, I don't have the time to invest in staying current. So I've updated all of my links to point to HTTP instead and shut the server down today.

Goodbye FTP! It's been a good run, and I'll always have a soft spot in my heart for you.

2017-12-23: Free software log (November 2017)

These are getting later and later despite the best of intentions, but I still have plans! Strategies! Intentions! Hopes! Next month's might be a bit closer to on time.

This month, I finally have some employer-sponsored free software work to report: overhauling the service account handling in Merou. Previously known as Grouper until I pointed out the Internet2 project of the same name, this is the system we use internally at Dropbox for privilege management. It's essentially an account and group management framework with a delegated privilege model for assigning, managing, and auditing privileges.

Everyone seems to have one of these, and they're generally not that reusable. This is ours, and... I'm not sure how reusable it is. But hopefully it will get better!

I did not write this, and haven't previously done much development work on it, but in November I got some dedicated time to rewrite how it represented service accounts (non-human accounts). The previous implementation was a bit of a hack, reusing the user and group concept in a weird merged hybrid to represent a managed user. The new version, which has been pushed to GitHub, elevates a service account to a separate object in the database with its own permissions, assigns ownership of service accounts to groups, and has a separate privilege delegation mechanism from groups to the service accounts they own.

We've not yet deployed the service account fixes at Dropbox due to long and boring stories about schemas and database migrations and running out of time, but hopefully will early in 2018. Merou as a project doesn't handle database migrations yet, but we're considering looking at that early next year too. It would be nice to stop scrambling to keep internal projects moving and be able to work on properly polishing things for external release.

BTW, Merou is probably not the name that will stick. I've been advocating Permeate for a while. We'll see if that sticks.

On my personal time, I didn't do much in November (but December will have a much better report). I just fixed some issues with the Usenet control message processor that I still run, all of which stemmed from the fact that the PGP used for Usenet control messages is thoroughly obsolete. I kind of want to tackle that as a personal project, but time for personal projects has been short on the ground.

2017-12-24: Retiring bundle

Way back in the early 1990s, people were already trying to come up with better systems for managing software and configuration on multiple servers. One of those tools was a program called Synctree, written at the University of Michigan. (There is a later LISA paper about version two of that system, from 1998, but here I'm talking about version one.) In the early 1990s, Stanford used Synctree with a configuration store in AFS to manage changes to some central servers.

Synctree was a bit complicated, including mechanisms to overlay multiple sets of configuration files. Stanford also ran it automatically, which caused a few problems when it interacted poorly with bugs in AFS and synced zero-length configuration files. I no longer recall the exact set of reasons that prompted him, but Roland Schemers wrote a much simpler version, called bundle, as a Perl script. Like Synctree, it installed configuration files onto machines from a specification; unlike Synctree, it had a much simpler configuration language (called bundle files) and was run on demand. This was sometime around or before 1994.

My recollection is that it took a few years, but we eventually used bundle as our configuration management for everything (ran manually). I adopted the script and largely rewrote it, and then enhanced it (along with others) with more support for variable substitution and the ability to do in-place edits of files. (You can see its final form in the bundle documentation.) Later, when local package managers became more of a thing, we supplemented it with shell scripts that would do package installation and other mostly one-time setup, but all the configuration files were still managed with bundle.

An amusing bit of trivia: bundle was used briefly in the very early days of Google to manage configuration on Google servers.

The major limitation of bundle was always its file-based view. It didn't manage packages or services, its conditionals were limited to complex in-line file edits and substitution variables, and it didn't have a templating system. We finally decided we needed something better, and after a survey of possibilities, selected Puppet in its very early days. But it took us several years to switch, and even when I left Stanford in 2014 we were still using bundle in a few places in our FAI install process.

I adopted bundle to manage my personal systems and never quite got around to switching when we moved to Puppet for servers. (You can see my old notes on managing systems with bundle, which I left up as a historical curiosity.) But this year I finally finished the migration, and today I moved bundle into my obsolete software list and dropped the Debian package from the unstable section of my Debian repository.

So long, bundle. It's been a long and good run, and this is still one of my best examples of how much life there is in a simple, understandable tool that does a small thing well.

2017-12-25: podlators 4.10

podlators is the source for Pod::Man and Pod::Text, which convert POD documentation to man pages and text documents.

This version includes a fairly significant formatting change for Pod::Man: man page links and function names (including auto-discovered function names) are now bold instead of italic.

I originally chose italics for both because that was the convention on Solaris, but Solaris is mostly dead at this point. Meanwhile, the Linux man page conventions say to use bold for function and man page references, and the mandoc .Fn macro uses bold. (.Xr appears to use normal type for references to other man pages, but I think some formatting is warranted.) I suspect there may be some grumbling about this change, but it brings the output of Pod::Man in line with other common conventions. Thank sgo Guillem Jover for writing the patch.

Also in this release are three warning fixes, including yet another attempt to get .IX handling correct. Thanks to Bjarni Ingi Gislason, Zefram, and Guillem Jover.

You can get the latest release from the podlators distribution page.

2017-12-26: Reducing obligations

At this year's DebConf, Enrico Zini gave a talk on consensually doing things together that has stuck with me ever since. I recommend watching it if you haven't. The core idea that I took away from it is that volunteer projects should be both voluntary and enjoyable to stay healthy, and an important component of this is for those involved to stop doing things they're not enjoying. (And for others to not pressure them or expect them to be heroes.)

I frequently have to tell myself that one cannot continuously add new obligations without occasionally setting aside existing ones, so this is something I needed to hear. I also have a hard time not responding to email or software contributions, even when I don't have the time or emotional energy to reply. I've therefore accumulated a lot of old email that I "should" respond to (that word is always a warning sign), or patches or ideas for software I maintain that I haven't implemented.

This is the time of the year when I try to step back, look over my life and my current goals and priorities, and decide if there's anything I want to change. My goal for this year is to put aside things that I'm not doing consensually, in Enrico's term, and refocus my time and effort on things that I'm truly enjoying. Or, in some cases, picking up things again that I had been enjoying but hadn't given enough energy to.

So, I'm not going away, from Debian or from free software or from replying to email, by any stretch! But I am giving myself permission to not feel obligated to do a bunch of things I was doing (or not doing but thinking I "should" do). I'm also going to remove myself from the Uploaders control field of more packages that I haven't worked on in some time, just for clarity and fewer things on my packages overview page.

I already orphaned the following packages upstream, but was still maintaining the corresponding Debian packages. I don't use any of this software at the moment, though, so that doesn't make much sense. I'm therefore going to orphan these Debian packages or put them for adoption. (In some cases, there are other possibly obvious maintainers, so I'll ask them first.)

I had not yet orphaned the following software for which I'm upstream, but I probably should have, and will fairly soon:

Finally, I have oodles of older mail messages from various people that I wish I'd had the energy and thoughtfulness to reply to at the time. At this point, many of them are years old, and everyone except me has probably forgotten about them. But I still had them saved to respond to, and they were sitting around radiating obligation. This week, I'm giving myself to go through and delete them unanswered. I'm sorry to all the people I didn't reply to! Sadly, energy is short, and even with conversations that I start, sometimes life happens.

Please feel free to try again if there's something you still wanted to talk to me about! I do manage to reply to most things.

2017-12-27: Tasker 0.4

As mentioned in my previous post, I'm orphaning this package and won't be working on it further. I doubt anyone cares about my little experiment in an extremely simple web task tracker with almost no features. But Julien ÉLIE sent me a few patches for it many years ago when he was experimenting with it, and it seemed like a shame to let those die in my inbox.

So this is a final release incorporating his fixes (including a few that had been languishing in Git). It has a variety of bug fixes to things like URL encoding, error checking, and non-ASCII group name support. I'm not using this any more, and must admit that I didn't even test this (and it's Python 2, and the coding style is poor, etc.), so this is just an "in case it's useful to someone" release.

You can get the latest version from the Tasker distribution page.

2017-12-30: C TAP Harness 4.2

The functional change in this release of my test framework for C programs is the addition of a new is_blob test function. This is equivalent to ok(memcmp(...)) but it reports where the two memory regions differ as a diagnostic. This was contributed by Daniel Collins.

Otherwise, the changes are warning fixes and machinery to more easily test with warnings. C TAP Harness now supports being built with warnings with either GCC or Clang.

You can get the latest version from the C TAP Harness distribution page.

2017-12-30: rra-c-util 7.0

This is my collection of utility libraries and support code for (mostly) C software.

The major version bump is due a backwards-incompatible change: dropping the SA_LEN macro from portable/socket.h, including all the Autoconf machinery to probe for it. This macro came from INN's old portability code when porting to IPv6, but INN turned out to not really need it and it's never caught on. It was causing some warnings with GCC 7 that would otherwise have been hard to fix, so it was time for it to go.

There are a couple of other changes to function signatures that shouldn't matter for backward compatibility: network_sockaddr_sprint now takes a socklen_t for better type compatibility with other networking functions, and bail_krb5 and diag_krb5 in the TAP add-ons take a long as the error code argument so that they can take either a krb5_error_code or a kadm5_ret_t.

The remaining changes are all about enabling more warnings. rra-c-util now builds with intensive warnings enabled in both GCC 7 and Clang, and the warning options have been refreshed against GCC 7. It also reports clean from the Clang static analyzer, which included changing reallocarray and the vector implementations to always allocate memory of at least the minimum size.

You can get the latest version from the rra-c-util distribution page.

2017-12-30: pam-krb5 4.8

This is the default Kerberos PAM module for Debian and Ubuntu systems, and supports both MIT Kerberos and Heimdal. I'm not sure how many people still use straight Kerberos PAM modules these days, with sssd taking off, but I'm still maintaining it.

This release fixes a somewhat obscure bug: if you configure the module to do expired password changes properly, it checks to see that the expired credentials can still get kadmin/changepw credentials to do the password change. However, it was setting credential options improperly on that call, which could cause it to spuriously fail if, say, krb5.conf is configured to request proxiable credentials but kadmin/changepw doesn't support proxiable credentials. Thanks to Florian Best for the excellent bug report.

The test suite in this version also works properly with Heimdal 7.0.1 and later, which changed a bunch of the messages (at the cost of skipping tests with earlier versions of Heimdal), and reports richer error messages on PKINIT failures with Heimdal. It also includes documentation fixes and lots of warning fixes, and now builds properly with tons of warnings enabled with GCC 7, Clang, and the Clang static analyzer.

You can get the latest version from the pam-krb5 distribution page.

2017-12-31: DocKnot 1.02

DocKnot is my current personal automation project: try to find some way to keep all the various documentation for my software projects in sync while reusing boilerplate that applies to multiple projects. I'm still figuring out how I want it to work, so I haven't written the sort of comprehensive documentation that would let someone else more easily use it. The current tentative plan is to do that for the 2.00 release, around the time I've switched all my active project documentation and all my software web pages over to it.

This release has all the incremental improvements I needed to handle the pam-krb5 documentation:

I'll probably redo how the license is named in the future, since right now I'm abusing copyright-format 1.0 syntax in a way that wasn't intended. (I use that format for the upstream license files of all of my software.)

Right now, this is all very, very specific to my software page styles and how I like to document software, and doesn't aspire to be more than that. That's why I've not uploaded it to Debian, although it is available on CPAN (as App::DockNot) if anyone wants.

You can get the latest version from the DocKnot distribution page.

Last spun 2024-01-01 from thread modified 2017-12-31