OpenPKG CVS Repository http://cvs.openpkg.org/ ____________________________________________________________________________
Server: cvs.openpkg.org Name: Thomas Lotterer Root: /e/openpkg/cvs Email: [EMAIL PROTECTED] Module: openpkg-src Date: 05-Mar-2003 16:38:17 Branch: OPENPKG_1_STABLE Handle: 2003030515381600 Added files: (Branch: OPENPKG_1_STABLE) openpkg-src/kerberos kerberos.patch Modified files: (Branch: OPENPKG_1_STABLE) openpkg-src/kerberos kerberos.spec Log: MFC: CAN-2003-0041 Summary: Revision Changes Path 1.1.2.1 +305 -0 openpkg-src/kerberos/kerberos.patch 1.10.2.2 +4 -2 openpkg-src/kerberos/kerberos.spec ____________________________________________________________________________ patch -p0 <<'@@ .' Index: openpkg-src/kerberos/kerberos.patch ============================================================================ $ cvs diff -u -r0 -r1.1.2.1 kerberos.patch --- /dev/null 2003-03-05 16:38:16.000000000 +0100 +++ kerberos.patch 2003-03-05 16:38:17.000000000 +0100 @@ -0,0 +1,305 @@ +# taken from http://updates.redhat.com/8.0/en/os/SRPMS/krb5-1.2.5-8.src.rpm +# Patch to add in missing protection against special characters and +# malicious servers, backported from netkit ftp 0.17 sources, (There are +# probably other security fixes that are missing from this old ftp +# source too). Mark Cox, [EMAIL PROTECTED], Jan 2003 +# http://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2003-0041 + +--- krb5-1.2.5/src/appl/gssftp/ftp/cmds.c.ORIG 2003-01-20 10:21:41.000000000 +0000 ++++ krb5-1.2.5/src/appl/gssftp/ftp/cmds.c 2003-01-20 11:03:40.000000000 +0000 +@@ -69,6 +69,7 @@ + extern char **ftpglob(); + extern char *home; + extern char *remglob(); ++static int checkglob(int fd, const char *pattern); + extern char *getenv(); + #ifndef HAVE_STRERROR + #define strerror(error) (sys_errlist[error]) +@@ -88,6 +89,64 @@ + extern int do_auth(); + + /* ++ * pipeprotect: protect against "special" local filenames by prepending ++ * "./". Special local filenames are "-" and "|..." AND "/...". ++ */ ++static char *pipeprotect(char *name) ++{ ++ char *nu; ++ if (strcmp(name, "-") && *name!='|' && *name!='/') { ++ return name; ++ } ++ ++ /* We're going to leak this memory. XXX. */ ++ nu = malloc(strlen(name)+3); ++ if (nu==NULL) { ++ perror("malloc"); ++ code = -1; ++ return NULL; ++ } ++ strcpy(nu, "."); ++ if (*name != '/') strcat(nu, "/"); ++ strcat(nu, name); ++ return nu; ++} ++ ++/* ++ * Look for embedded ".." in a pathname and change it to "!!", printing ++ * a warning. ++ */ ++static char *pathprotect(char *name) ++{ ++ int gotdots=0, i, len; ++ ++ /* Convert null terminator to trailing / to catch a trailing ".." */ ++ len = strlen(name)+1; ++ name[len-1] = '/'; ++ ++ /* ++ * State machine loop. gotdots is < 0 if not looking at dots, ++ * 0 if we just saw a / and thus might start getting dots, ++ * and the count of dots seen so far if we have seen some. ++ */ ++ for (i=0; i<len; i++) { ++ if (name[i]=='.' && gotdots>=0) gotdots++; ++ else if (name[i]=='/' && gotdots<0) gotdots=0; ++ else if (name[i]=='/' && gotdots==2) { ++ printf("Warning: embedded .. in %.*s (changing to !!)\n", ++ len-1, name); ++ name[i-1] = '!'; ++ name[i-2] = '!'; ++ gotdots = 0; ++ } ++ else if (name[i]=='/') gotdots = 0; ++ else gotdots = -1; ++ } ++ name[len-1] = 0; ++ return name; ++} ++ ++/* + * `Another' gets another argument, and stores the new argc and argv. + * It reverts to the top level (via main.c's intr()) on EOF/error. + * +@@ -832,7 +891,15 @@ + + if (argc == 2) { + argc++; +- argv[2] = argv[1]; ++ /* ++ * Protect the user from accidentally retrieving special ++ * local names. ++ */ ++ argv[2] = pipeprotect(argv[1]); ++ if (!argv[2]) { ++ code = -1; ++ return 0; ++ } + loc++; + } + if (argc < 2 && !another(&argc, &argv, "remote-file")) +@@ -1007,8 +1074,19 @@ + if (mapflag) { + tp = domap(tp); + } +- recvrequest("RETR", tp, cp, "w", +- tp != cp || !interactive); ++ /* Reject embedded ".." */ ++ tp = pathprotect(tp); ++ ++ /* Prepend ./ to "-" or "!*" or leading "/" */ ++ tp = pipeprotect(tp); ++ if (tp == NULL) { ++ /* hmm... how best to handle this? */ ++ mflag = 0; ++ } ++ else { ++ recvrequest("RETR", tp, cp, "w", ++ tp != cp || !interactive); ++ } + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; +@@ -1024,16 +1102,14 @@ + } + + char * +-remglob(argv,doswitch) +- char *argv[]; +- int doswitch; ++remglob(char *argv[], int doswitch) + { + char temp[16]; +- static char buf[MAXPATHLEN]; ++ static char buf[PATH_MAX]; + static FILE *ftemp = NULL; + static char **args; +- int oldverbose, oldhash; +- char *cp, *mode; ++ int oldverbose, oldhash, badglob = 0; ++ char *cp; + + if (!mflag) { + if (!doglob) { +@@ -1055,36 +1131,154 @@ + return (cp); + } + if (ftemp == NULL) { +- (void) strncpy(temp, _PATH_TMP, sizeof(temp) - 1); +- temp[sizeof(temp) - 1] = '\0'; +- (void) mktemp(temp); ++ int oldumask, fd; ++ (void) strcpy(temp, _PATH_TMP); ++ ++ /* libc 5.2.18 creates with mode 0666, which is dumb */ ++ oldumask = umask(077); ++ fd = mkstemp(temp); ++ umask(oldumask); ++ ++ if (fd<0) { ++ printf("Error creating temporary file, oops\n"); ++ return NULL; ++ } ++ + oldverbose = verbose, verbose = 0; + oldhash = hash, hash = 0; + if (doswitch) { + pswitch(!proxy); + } +- for (mode = "w"; *++argv != NULL; mode = "a") +- recvrequest ("NLST", temp, *argv, mode, 0); ++ while (*++argv != NULL) { ++ int dupfd = dup(fd); ++ ++ recvrequest ("NLST", temp, *argv, "a", 0); ++ if (!checkglob(dupfd, *argv)) { ++ badglob = 1; ++ break; ++ } ++ } ++ unlink(temp); ++ + if (doswitch) { + pswitch(!proxy); + } + verbose = oldverbose; hash = oldhash; +- ftemp = fopen(temp, "r"); +- (void) unlink(temp); ++ if (badglob) { ++ printf("Refusing to handle insecure file list\n"); ++ close(fd); ++ return NULL; ++ } ++ ftemp = fdopen(fd, "r"); + if (ftemp == NULL) { + printf("can't find list of remote files, oops\n"); + return (NULL); + } ++ rewind(ftemp); + } + if (fgets(buf, sizeof (buf), ftemp) == NULL) { + (void) fclose(ftemp), ftemp = NULL; + return (NULL); + } +- if ((cp = strchr(buf, '\n')) != NULL) ++ if ((cp = index(buf, '\n')) != NULL) + *cp = '\0'; + return (buf); + } + ++/* ++ * Check whether given pattern matches `..' ++ * We assume only a glob pattern starting with a dot will match ++ * dot entries on the server. ++ */ ++static int ++isdotdotglob(const char *pattern) ++{ ++ int havedot = 0; ++ char c; ++ ++ if (*pattern++ != '.') ++ return 0; ++ while ((c = *pattern++) != '\0' && c != '/') { ++ if (c == '*' || c == '?') ++ continue; ++ if (c == '.' && havedot++) ++ return 0; ++ } ++ return 1; ++} ++ ++/* ++ * This function makes sure the list of globbed files returned from ++ * the server doesn't contain anything dangerous such as ++ * /home/<yourname>/.forward, or ../.forward, ++ * or |mail [EMAIL PROTECTED] </etc/passwd, etc. ++ * Covered areas: ++ * - returned name starts with / but glob pattern doesn't ++ * - glob pattern starts with / but returned name doesn't ++ * - returned name starts with | ++ * - returned name contains .. in a position where glob ++ * pattern doesn't match .. ++ * I.e. foo/.* allows foo/../bar but not foo/.bar/../fly ++ * ++ * Note that globbed names starting with / should really be stored ++ * under the current working directory; this is handled in mget above. ++ * --okir ++ */ ++static int ++checkglob(int fd, const char *pattern) ++{ ++ const char *sp; ++ char buffer[MAXPATHLEN], dotdot[MAXPATHLEN]; ++ int okay = 1, nrslash, initial, nr; ++ FILE *fp; ++ ++ /* Find slashes in glob pattern, and verify whether component ++ * matches `..' ++ */ ++ initial = (pattern[0] == '/'); ++ for (sp = pattern, nrslash = 0; sp != 0; sp = strchr(sp, '/')) { ++ while (*sp == '/') ++ sp++; ++ if (nrslash >= MAXPATHLEN) { ++ printf("Incredible pattern: %s\n", pattern); ++ return 0; ++ } ++ dotdot[nrslash++] = isdotdotglob(sp); ++ } ++ ++ fp = fdopen(fd, "r"); ++ while (okay && fgets(buffer, sizeof(buffer), fp) != NULL) { ++ char *sp; ++ ++ if ((sp = strchr(buffer, '\n')) != 0) { ++ *sp = '\0'; ++ } else { ++ printf("Extremely long filename from server: %s", ++ buffer); ++ okay = 0; ++ break; ++ } ++ if (buffer[0] == '|' ++ || (buffer[0] != '/' && initial) ++ || (buffer[0] == '/' && !initial)) ++ okay = 0; ++ for (sp = buffer, nr = 0; sp; sp = strchr(sp, '/'), nr++) { ++ while (*sp == '/') ++ sp++; ++ if (sp[0] == '.' && !strncmp(sp, "../", 3) ++ && (nr >= nrslash || !dotdot[nr])) ++ okay = 0; ++ } ++ } ++ ++ if (!okay) ++ printf("Filename provided by server " ++ "doesn't match pattern `%s': %s\n", pattern, buffer); ++ ++ fclose(fp); ++ return okay; ++} ++ + char * + onoff(bool) + int bool; @@ . patch -p0 <<'@@ .' Index: openpkg-src/kerberos/kerberos.spec ============================================================================ $ cvs diff -u -r1.10.2.1 -r1.10.2.2 kerberos.spec --- openpkg-src/kerberos/kerberos.spec 18 Jan 2003 14:12:31 -0000 1.10.2.1 +++ openpkg-src/kerberos/kerberos.spec 5 Mar 2003 15:38:16 -0000 1.10.2.2 @@ -9,7 +9,7 @@ ## the above copyright notice and this permission notice appear in all ## copies. ## -## THIS SOFTWARE IS PROVIDED AS IS'' AND ANY EXPRESSED OR IMPLIED +## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR @@ -33,10 +33,11 @@ Group: Cryptography License: MIT Version: 1.2.6 -Release: 1.20020923 +Release: 1.20030305 # list of sources Source0: http://www.crypto-publish.org/dist/mit-kerberos5/krb5-%{version}.tar.gz +Patch0: kerberos.patch # build information Prefix: %{l_prefix} @@ -56,6 +57,7 @@ %prep %setup -q -n krb5-%{version} + %patch -p1 %build cd src @@ . ______________________________________________________________________ The OpenPKG Project www.openpkg.org CVS Repository Commit List [EMAIL PROTECTED]