Saturday, February 12, 2005

How to get the user's home directory

Many programs need to access the user's home directory to look for files, specially configuration ones. To do that, they usually get the HOME environment variable's value and use it to construct the full path. However, if the application is security-sensible, this is probably inappropriate.

What happens if such application is run through sudo or with the setuid bit set? Let's see it:

[dawn jmmv] $ sudo /bin/sh -c 'id -un ; echo ${HOME}'
root
/home/jmmv

Oops! The application with extra privileges is getting the home directory of the unprivileged user! This is a serious problem, because the user could simply create a malicious configuration file (that exec's a third program, for example) and use it with more privileges than he has.

Fortunately, the user's home directory can be guessed using a safer method: that is, by reading its value from the /etc/passwd file. We only need to be careful to get the entry that matches the actual effective user (not the real one). How'd we do it?

struct passwd *p = getpwuid(geteuid());
(void)printf("Home directory is: \n", p->pw_dir);

If we now put the above in a little test program and run it, we get:

[dawn tmp] $ ./a.out
Home directory is: /home/jmmv
[dawn tmp] $ sudo ./a.out
Home directory is: /root

Well, I'm not completely sure this is the best way to go (i.e., if there is any way to still get a value decided by the user), but so far I think this is safer than just reading HOME's value. If anybody knows of any drawbacks, please share!

6 comments:

Anonymous said...

[Originally posted at 2005-02-12 03:16 pm UTC]

Thank you jmmv, your article has helped me to finish getpw*-related script that I had "dormant" till now :-) You're always an amazing source of valuable information ;-)

Julio M. Merino Vidal said...

[Originally posted at 2005-02-12 03:40 pm UTC]

You're welcome! Hmm... even I know who you are, it'd be nice if people signed their messages ;)

Anonymous said...

[Originally posted at 2005-02-24 10:53 am UTC]

Glib function g_get_home_dir does the same, read from /etc/passwd. Congrats for your journal.

Julio M. Merino Vidal said...

[Originally posted at 2005-02-24 05:34 pm UTC]

Oh, good to know. And you're welcome!

Anonymous said...

[Originally posted at 2005-11-11 10:05 am UTC]

Thanks jmmv,
I've got a little question.
Which "C header files" do we use to complie this code with gcc?

Julio M. Merino Vidal said...

You need: sys/types.h, stdio.h, pwd.h and unistd.h.