OpenPKG CVS Repository
http://cvs.openpkg.org/
____________________________________________________________________________
Server: cvs.openpkg.org Name: Thomas Lotterer
Root: /e/openpkg/cvs Email: [EMAIL PROTECTED]
Module: openpkg-src openpkg-web Date: 05-Mar-2003 16:35:54
Branch: HEAD Handle: 2003030515355102
Added files:
openpkg-src/kerberos kerberos.patch
Modified files:
openpkg-src/kerberos kerberos.spec
openpkg-web news.txt
Log:
CAN-2003-0041
Summary:
Revision Changes Path
1.1 +305 -0 openpkg-src/kerberos/kerberos.patch
1.12 +3 -1 openpkg-src/kerberos/kerberos.spec
1.3550 +1 -0 openpkg-web/news.txt
____________________________________________________________________________
patch -p0 <<'@@ .'
Index: openpkg-src/kerberos/kerberos.patch
============================================================================
$ cvs diff -u -r0 -r1.1 kerberos.patch
--- /dev/null 2003-03-05 16:35:53.000000000 +0100
+++ kerberos.patch 2003-03-05 16:35:54.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.11 -r1.12 kerberos.spec
--- openpkg-src/kerberos/kerberos.spec 31 Jan 2003 12:25:57 -0000 1.11
+++ openpkg-src/kerberos/kerberos.spec 5 Mar 2003 15:35:53 -0000 1.12
@@ -33,10 +33,11 @@
Group: Cryptography
License: MIT
Version: 1.2.6
-Release: 20020923
+Release: 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
@@ .
patch -p0 <<'@@ .'
Index: openpkg-web/news.txt
============================================================================
$ cvs diff -u -r1.3549 -r1.3550 news.txt
--- openpkg-web/news.txt 5 Mar 2003 13:28:43 -0000 1.3549
+++ openpkg-web/news.txt 5 Mar 2003 15:35:51 -0000 1.3550
@@ -1,3 +1,4 @@
+05-Mar-2003: Upgraded package: P<kerberos-1.2.6-20030305>
05-Mar-2003: Upgraded package: P<qt-3.1.2-20030305>
05-Mar-2003: Upgraded package: P<bind-9.2.2-20030305>
05-Mar-2003: Upgraded package: P<bind-9.2.2-20030304>
@@ .
______________________________________________________________________
The OpenPKG Project www.openpkg.org
CVS Repository Commit List [EMAIL PROTECTED]