diff options
-rw-r--r-- | Xtrans.c | 4 | ||||
-rw-r--r-- | Xtransint.h | 2 | ||||
-rw-r--r-- | Xtranssock.c | 2 | ||||
-rw-r--r-- | Xtransutil.c | 119 |
4 files changed, 103 insertions, 24 deletions
@@ -1,4 +1,4 @@ -/* $XdotOrg: xc/lib/xtrans/Xtrans.c,v 1.1.4.3.4.1 2004/03/04 17:47:15 eich Exp $ */ +/* $XdotOrg: xc/lib/xtrans/Xtrans.c,v 1.3 2004/07/17 01:13:31 alanc Exp $ */ /* $Xorg: Xtrans.c,v 1.4 2001/02/09 02:04:06 xorgcvs Exp $ */ /* @@ -1132,7 +1132,7 @@ TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret, *partial = (*count_ret < complete_network_count()); PRMSG (5, - "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n", + "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n", *partial, *count_ret, complete_network_count()); if (*count_ret > 0) diff --git a/Xtransint.h b/Xtransint.h index 166a889..dad0d8a 100644 --- a/Xtransint.h +++ b/Xtransint.h @@ -1,4 +1,4 @@ -/* $XdotOrg: xc/lib/xtrans/Xtransint.h,v 1.1.4.3.4.1 2004/03/04 17:47:15 eich Exp $ */ +/* $XdotOrg: xc/lib/xtrans/Xtransint.h,v 1.2 2004/04/23 18:44:27 eich Exp $ */ /* $Xorg: Xtransint.h,v 1.4 2001/02/09 02:04:06 xorgcvs Exp $ */ /* diff --git a/Xtranssock.c b/Xtranssock.c index 83a7b91..4c18324 100644 --- a/Xtranssock.c +++ b/Xtranssock.c @@ -1,4 +1,4 @@ -/* $XdotOrg: xc/lib/xtrans/Xtranssock.c,v 1.1.4.6.2.1 2004/03/04 17:47:15 eich Exp $ */ +/* $XdotOrg: xc/lib/xtrans/Xtranssock.c,v 1.2 2004/04/23 18:44:27 eich Exp $ */ /* $Xorg: Xtranssock.c,v 1.11 2001/02/09 02:04:06 xorgcvs Exp $ */ /* diff --git a/Xtransutil.c b/Xtransutil.c index 865c20f..2432ba7 100644 --- a/Xtransutil.c +++ b/Xtransutil.c @@ -190,7 +190,7 @@ TRANS(ConvertAddress)(int *familyp, int *addrlenp, Xtransaddr **addrp) *familyp=FamilyLocal; break; } -#endif /* defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN*/ +#endif /* defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)*/ default: @@ -501,31 +501,74 @@ is_numeric (char *str) #define lstat(a,b) stat(a,b) #endif +#define FAIL_IF_NOMODE 1 +#define FAIL_IF_NOT_ROOT 2 +#define WARN_NO_ACCESS 4 + +/* + * We make the assumption that when the 'sticky' (t) bit is requested + * it's not save if the directory has non-root ownership or the sticky + * bit cannot be set and fail. + */ static int trans_mkdir(char *path, int mode) { struct stat buf; - if (mkdir(path, mode) == 0) { - chmod(path, mode); - return 0; - } - /* If mkdir failed with EEXIST, test if it is a directory with - the right modes, else fail */ - if (errno == EEXIST) { - if (lstat(path, &buf) != 0) { - PRMSG(1, "mkdir: (l)stat failed for %s (%d)\n", + if (lstat(path, &buf) != 0) { + if (errno != ENOENT) { + PRMSG(1, "mkdir: ERROR: (l)stat failed for %s (%d)\n", path, errno, 0); return -1; } + /* Dir doesn't exist. Try to create it */ + + /* + * 'sticky' bit requested: assume application makes + * certain security implications. If effective user ID + * is != 0: fail as we may not be able to meet them. + */ + if (geteuid() != 0) { + if (mode & 01000) { + PRMSG(1, "mkdir: ERROR: euid != 0," + "directory %s will not be created.\n", + path, 0, 0); +#ifdef FAIL_HARD + return -1; +#endif + } else { + PRMSG(1, "mkdir: Cannot create %s with root ownership\n", + path, 0, 0); + } + } + + if (mkdir(path, mode) == 0) { + if (chmod(path, mode)) { + PRMSG(1, "mkdir: ERROR: Mode of %s should be set to %04o\n", + path, mode, 0); +#ifdef FAIL_HARD + return -1; +#endif + } + } else { + PRMSG(1, "mkdir: ERROR: Cannot create %s\n", + path, 0, 0); + return -1; + } + + return 0; + + } else { if (S_ISDIR(buf.st_mode)) { int updateOwner = 0; int updateMode = 0; int updatedOwner = 0; int updatedMode = 0; + int status = 0; /* Check if the directory's ownership is OK. */ if (buf.st_uid != 0) updateOwner = 1; + /* * Check if the directory's mode is OK. An exact match isn't * required, just a mode that isn't more permissive than the @@ -533,9 +576,29 @@ trans_mkdir(char *path, int mode) */ if ((~mode) & 0077 & buf.st_mode) updateMode = 1; - if ((mode & 01000) && - (buf.st_mode & 0002) && !(buf.st_mode & 01000)) + + /* + * If the directory is not writeable not everybody may + * be able to create sockets. Therefore warn if mode + * cannot be fixed. + */ + if ((~buf.st_mode) & 0022 & mode) { updateMode = 1; + status |= WARN_NO_ACCESS; + } + + /* + * If 'sticky' bit is requested fail if owner isn't root + * as we assume the caller makes certain security implications + */ + if (mode & 01000) { + status |= FAIL_IF_NOT_ROOT; + if (!(buf.st_mode & 01000)) { + status |= FAIL_IF_NOMODE; + updateMode = 1; + } + } + #ifdef HAS_FCHOWN /* * If fchown(2) and fchmod(2) are available, try to correct the @@ -547,7 +610,7 @@ trans_mkdir(char *path, int mode) struct stat fbuf; if ((fd = open(path, O_RDONLY)) != -1) { if (fstat(fd, &fbuf) == -1) { - PRMSG(1, "mkdir: fstat failed for %s (%d)\n", + PRMSG(1, "mkdir: ERROR: fstat failed for %s (%d)\n", path, errno, 0); return -1; } @@ -558,7 +621,7 @@ trans_mkdir(char *path, int mode) if (!S_ISDIR(fbuf.st_mode) || buf.st_dev != fbuf.st_dev || buf.st_ino != fbuf.st_ino) { - PRMSG(1, "mkdir: inode for %s changed\n", + PRMSG(1, "mkdir: ERROR: inode for %s changed\n", path, 0, 0); return -1; } @@ -570,23 +633,39 @@ trans_mkdir(char *path, int mode) } } #endif + if (updateOwner && !updatedOwner) { +#ifdef FAIL_HARD + if (status & FAIL_IF_NOT_ROOT) { + PRMSG(1, "mkdir: ERROR: Owner of %s must be set to root\n", + path, 0, 0); + return -1; + } +#endif PRMSG(1, "mkdir: Owner of %s should be set to root\n", path, 0, 0); -#if 0 && !defined(__CYGWIN__) && !defined(__DARWIN__) - sleep(5); -#endif } + if (updateMode && !updatedMode) { +#ifdef FAIL_HARD + if (status & FAIL_IF_NOMODE) { + PRMSG(1, "mkdir: ERROR: Mode of %s must be set to %04o\n", + path, mode, 0); + return -1; + } +#endif PRMSG(1, "mkdir: Mode of %s should be set to %04o\n", path, mode, 0); -#if 0 && !defined(__CYGWIN__) && !defined(__DARWIN__) - sleep(5); -#endif + if (status & WARN_NO_ACCESS) { + PRMSG(1, "mkdir: this may cause subsequent errors\n", + 0, 0, 0); + } } return 0; } + return -1; } + /* In all other cases, fail */ return -1; } |