diff --git a/unix/unix.h b/unix/unix.h index d43e0ae0..79a9fb3c 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -157,6 +157,7 @@ void cloexec(int); void noncloexec(int); int nonblock(int); int no_nonblock(int); +char *make_dir_and_check_ours(const char *dirname); /* * Exports from unicode.c. diff --git a/unix/uxmisc.c b/unix/uxmisc.c index 473aa94e..95133a03 100644 --- a/unix/uxmisc.c +++ b/unix/uxmisc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "putty.h" @@ -281,3 +282,34 @@ FontSpec *fontspec_deserialise(void *vdata, int maxsize, int *used) *used = end - data + 1; return fontspec_new(data); } + +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)); + + /* + * Now check that that directory is _owned by us_ and not writable + * by anybody else. This protects us 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 use our authenticated SSH sessions. + */ + 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; +} diff --git a/unix/uxshare.c b/unix/uxshare.c index 3da52def..9279a049 100644 --- a/unix/uxshare.c +++ b/unix/uxshare.c @@ -42,37 +42,6 @@ static char *make_parentdir_name(void) return parent; } -static 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)); - - /* - * Now check that that directory is _owned by us_ and not writable - * by anybody else. This protects us 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 use our authenticated SSH sessions. - */ - 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; -} - static char *make_dirname(const char *pi_name, char **logtext) { char *name, *parentdirname, *dirname, *err;