1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00
putty-source/unix/utils/make_dir_and_check_ours.c

61 lines
2.2 KiB
C
Raw Normal View History

/*
* Create a directory accessible only to us, and then check afterwards
* that we really did end up with a directory with the right ownership
* and permissions.
*
* The idea is that this is a directory in which we're about to create
* something sensitive, like a listening Unix-domain socket for SSH
* connection sharing or an SSH agent. We want to be protected against
* somebody else previously having created the directory in a way
* that's writable to us, and thus manipulating us into creating the
* actual socket in a directory they can see so that they can connect
* to it and (say) use our authenticated SSH sessions.
*
* NOTE: The strategy used in this function is not safe if the enemy
* has unrestricted write access to the containing directory. In that
* case, they could move our directory out of the way and make a new
* one, after this function returns and before we create our socket
* (or whatever) inside it.
*
* But this should be OK for temp directories (which modify the
* default world-write behaviour by also setting the 't' bit,
* preventing people from renaming or deleting things in there that
* they don't own). And of course it's also safe if the directory is
* writable only by our _own_ uid.
*/
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "putty.h"
char *make_dir_and_check_ours(const char *dirname)
{
struct stat st;
/*
* Create the directory. We might have created it before, so
* EEXIST is an OK error; but anything else is doom.
*/
if (mkdir(dirname, 0700) < 0 && errno != EEXIST)
return dupprintf("%s: mkdir: %s", dirname, strerror(errno));
/*
* Stat the directory and check its ownership and permissions.
*/
if (stat(dirname, &st) < 0)
return dupprintf("%s: stat: %s", dirname, strerror(errno));
if (st.st_uid != getuid())
return dupprintf("%s: directory owned by uid %d, not by us",
dirname, st.st_uid);
if ((st.st_mode & 077) != 0)
return dupprintf("%s: directory has overgenerous permissions %03o"
" (expected 700)", dirname, st.st_mode & 0777);
return NULL;
}