Jump to content

~/.klei/ Isn't The Correct Place To Store User Data On A Linux Machine


ssokolow

Recommended Posts

On a Linux box, applications are no longer supposed to store their preferences directly in the home folder. Instead, there's an analogue to the Windows %APPDATA% and %LOCALAPPDATA% folders and the OSX Library hierarchy.

 

The XDG Base Directory Specification says that files should go in one of four places, depending on what behaviour you expect from the operating system:

  • Data files (things like save files which must be backed up and should roam between machines) go in the directory specified by the $XDG_DATA_HOME environment variable. If that's not set, default to $HOME/.local/share
  • Config files (things which should be backed up and should not roam between machines) go in the directory specified by the $XDG_CONFIG_HOME environment variable. If that's not set, default to $HOME/.config
  • Cached files (things which should not be backed up and should not roam between machines) go in the directory specified by the $XDG_CACHE_HOME environment variable. If that's not set, default to $HOME/.cache
  • Runtime control files (Things which should be deleted when the user logs out, like lockfiles, named pipes, unix domain sockets, etc.) go in the directory specified by the $XDG_RUNTIME_DIR environment variable. If that's not set, it's up to you to decide where to put your runtime files. I advise using /tmp/klei-$USER based on common practice and the filesystem hierarchy standard. You should not put large files in it since $XDG_RUNTIME_DIR is sometimes backed by a RAM disk.

In all cases:

  • Treat them like you currently treat $HOME and create a klei folder inside to avoid cluttering them up.
  • If they contain a relative path, ignore it and fall back to the default value.

Here's how they relate to their Windows counterparts:

  • %APPDATA% mostly goes into $XDG_DATA_HOME but some of its contents might belong in $XDG_CONFIG_HOME if you were storing machine-specific stuff like settings.ini in there. (However, it's not a mortal sin to just throw everything from %APPDATA% into $XDG_DATA_HOME. You wouldn't be the first devs to do so.)
  • %LOCALAPPDATA% gets split between $XDG_CONFIG_HOME (stuff which shouldn't roam but should get backed up for easy recovery), $XDG_RUNTIME_HOME (any lockfiles you might have), and $XDG_CACHE_HOME (everything else). (Again, it's not a mortal sin to just toss everything but the config files into $XDG_CACHE_HOME. Especially among games, $XDG_RUNTIME_DIR doesn't see much use.)
Link to comment
Share on other sites

Very nice, as always.

I'm hoping your next one will be a tutorial about why Klei should just store a sha256 hash of our game keys, instead of saving it in plain text inside updater.json.

 

Unfortunately, I haven't looked at what they're sending over the wire and don't know what constraints they're operating under on the server side. For all I know, they could be storing the Steam key in the clear on the client side because they're passing it to something that expects it in the clear and would be prohibitively complicated to work around.

 

I agree that they shouldn't be doing that since they could just validate it once and then implement their own check (unless they're somehow letting Steam host their downloads and Steam itself requires an in-the-clear key) but I don't know how much work would be involved to achieve that.

Link to comment
Share on other sites

Unfortunately, I haven't looked at what they're sending over the wire and don't know what constraints they're operating under on the server side. For all I know, they could be storing the Steam key in the clear on the client side because they're passing it to something that expects it in the clear and would be prohibitively complicated to work around.

 

I agree that they shouldn't be doing that since they could just validate it once and then implement their own check (unless they're somehow letting Steam host their downloads and Steam itself requires an in-the-clear key) but I don't know how much work would be involved to achieve that.

Steam handles its own updates, this is done with the standalone updaters. But, well, I don't know who hosts those.

Link to comment
Share on other sites

...however, your hopes do make a good implicit point. My advice to Humble Bundle participants is starting to become a bit of a series so I should probably collect what I've already done into a proper, unified guide.

 

So far, it's mainly the two topics I've covered here plus a Linux analogue to dxdiag that grew out of my interest in automating Torchlight's instructions for reporting bugs. (Here's an example of what it currently outputs, in case you're curious.)

 

Assuming I can get caught up sufficiently on my coursework, I suppose I could add a quick primer on how to hash and transmit secrets like passwords and Steam keys properly.

 

I could also see myself writing some sort of guide on the pros and cons of various ways games can be packaged for Linux but, to really do that justice and go into the same level of detail I have for my existing posts, I'd have to do a lot of research on things like the proper compiler flags to use to build for older versions of glibc. (My primary areas of expertise are Linux system administration, UI/UX design, and writing terminal, GTK+, and web apps in higher-level programming languages like Python, PHP, and Javascript.)

Link to comment
Share on other sites

Assuming I can get caught up sufficiently on my coursework, I suppose I could add a quick primer on how to hash and transmit secrets like passwords and Steam keys properly.

I said that as a tongue-in-cheek statement. I'm sure the devs know how to do a cryptographic handshake, create a tunnel over TCP/IP using asymmetric cryptography and all that. I just can't wrap my head around that plain text game key.

 

I could also see myself writing some sort of guide on the pros and cons of various ways games can be packaged for Linux but, to really do that justice and go into the same level of detail I have for my existing posts, I'd have to do a lot of research on things like the proper compiler flags to use to build for older versions of glibc. (My primary areas of expertise are Linux system administration, UI/UX design, and writing terminal, GTK+, and web apps in higher-level programming languages like Python, PHP, and Javascript.)

Well, before you give this deeper thought, I feel I should make 2 remarks. Firstly, it's not Klei itself that does the Linux/Mac ports of their games, but Alternative Games. Secondly, Klei uses Python extensively for their utility scripts. The updaters are Python apps, for example (running the strings utility on them should convince you of that).

Link to comment
Share on other sites

I said that as a tongue-in-cheek statement. I'm sure the devs know how to do a cryptographic handshake, create a tunnel over TCP/IP using asymmetric cryptography and all that. I just can't wrap my head around that plain text game key.

 

Well, before you give this deeper thought, I feel I should make 2 remarks. Firstly, it's not Klei itself that does the Linux/Mac ports of their games, but Alternative Games. Secondly, Klei uses Python extensively for their utility scripts. The updaters are Python apps, for example (running the strings utility on them should convince you of that).

 

It was actually your mention of using SHA256 that made me think of it. A lot of people don't realize that, on their own, the SHA family of hashes are a poor choice for that kind of hashing because they're specifically designed to be quick to compute. Hence, it's good to get in the habit of hashing secrets using more secure approaches.

 

As far as the porting goes, I hadn't really gotten as far as thinking about who to explicitly send it to. I was more thinking about to act of collecting what I've already said to various people and making it available in one well-organized place.

 

Finally, the area I was specifically referring to needing to research was the solution to problems like this one:

 

http://forums.kleientertainment.com/index.php?/topic/27629-which-linux-distribution-can-run-this-game/

 

Regardless of what language is used, you're going to end up linking against C libraries eventually. (For things like Java and the system Python runtime, you're just trusting the user's package manager to handle that for you.)

Link to comment
Share on other sites

It was actually your mention of using SHA256 that made me think of it. A lot of people don't realize that, on their own, the SHA family of hashes are a poor choice for that kind of hashing because they're specifically designed to be quick to compute. Hence, it's good to get in the habit of hashing secrets using more secure approaches.

Oh, come on. SHA-2 is cryptographically secure. Cryptoanalysis hasn't revealed any significant flaws in it yet, and that's what matters. Being "fast to compute" is just a constant factor, which can be nullified (one-ified?) by increasing the number of iterations. I'd say it's not good to get in the habit of not using standard, thoroughly analyzed crypto-algorithms when the "issue" you mentioned is just a matter of composing it with itself a few more times.

 

http://forums.kleientertainment.com/index.php?/topic/27629-which-linux-distribution-can-run-this-game/

 

Regardless of what language is used, you're going to end up linking against C libraries eventually. (For things like Java and the system Python runtime, you're just trusting the user's package manager to handle that for you.)

The short answer is it should be linked to an old version of the library. Standard libraries are quite forward compatible, but not backwards due to ABI extensions, even if the API itself remains the same (or almost). There are a few more issues to keep in mind, such as changes in GNU ld itself, but the newer soname embedding and the ABI dependencies that follow are the main concern.

This site has some useful info on that, though I wouldn't go to such extremes as statically linking to glibc/glibcxx.

Link to comment
Share on other sites

Oh, come on. SHA-2 is cryptographically secure. Cryptoanalysis hasn't revealed any significant flaws in it yet, and that's what matters. Being "fast to compute" is just a constant factor, which can be nullified (one-ified?) by increasing the number of iterations. I'd say it's not good to get in the habit of not using standard, thoroughly analyzed crypto-algorithms when the "issue" you mentioned is just a matter of composing it with itself a few more times.

 

The short answer is it should be linked to an old version of the library. Standard libraries are quite forward compatible, but not backwards due to ABI extensions, even if the API itself remains the same (or almost). There are a few more issues to keep in mind, such as changes in GNU ld itself, but the newer soname embedding and the ABI dependencies that follow are the main concern.

This site has some useful info on that, though I wouldn't go to such extremes as statically linking to glibc/glibcxx.

 

Yeah, SHA-2 is secure when used properly but you'd be surprised how many people don't know how to do that and don't even know they're doing it wrong.

As for the linking, thanks for the page. I wouldn't go so far as to statically link glibc, but I'd want to provide a clear, detailed guideline for how to efficiently build packages for wide compatibility (my first impulse for the glibc part is to say "use apt-get/emerge/urpmi/yum/etc." to install debootstrap, use that to fire up a Debian stale stable chroot, and build your package in that.) and how best to determine which libraries should be bundled and which the system should be trusted to provide.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

×
  • Create New...