Date: Sun, 28 Jun 1998 03:42:25 -0600 From: "Aaron D. Gifford" <agifford@infowest.com> To: <security@FreeBSD.ORG> Subject: UIDL overruns in qpopper Message-ID: <199806281925.NAA24567@infowest.com>
next in thread | raw e-mail | index | archive | help
When I first saw patches for pop_dropcopy.c that limit the uidl string length to 128, I couldn't see any overrun potential there. Then Miquel van Smoorenburg <miquels@CISTRON.NL> explained that the actual overrun occur in pop_uidl.c but can be prevented in pop_dropcopy.c. I looked at pop_uidl.c and sure enough, Miquel was correct. Further investigation revealed that another potential buffer overrun can occur in some cases where a huge From: header occurs and the EUIDL command is used by a POP client. The patch below constitute several changes I use on my FreeBSD boxen. It includes a fix for the signal 11 problem that some have reported after patch-ag is applied. It include a POP parameter limiting patch which you might want to avoid (it is the patch to the pop_parse.c file) -- I like it and it has been working on a 5,000-user system with no known problems yet -- but it might break something I don't know about or violate POP protocl. It includes a fix to the UIDL overrun by limiting the size of the UIDL data in pop_dropcopy.c. It also fixes another potentil UIDL overrun by reducing a buffer in pop_uidl.c. Finally, it also includes 2 cosmetic fixes that I like because my log files are more readable -- one change to pop_init.c and another to pop_auth.c. Whew! Please be aware that my mail software might wrap a line or two of the patch when I send this and cause it to break. Here goes: ========== diff -p work/qpopper2.41beta1/pop_auth.c work2/qpopper2.41beta1/pop_auth.c *** work/qpopper2.41beta1/pop_auth.c Wed Nov 19 14:20:38 1997 --- work2/qpopper2.41beta1/pop_auth.c Sat Jun 27 23:34:14 1998 *************** int pop_auth (p) *** 23,29 **** POP * p; { /* Tell the user that this command is not supported */ ! return (pop_msg(p,POP_FAILURE,"This command is not supported yet")); } --- 23,29 ---- POP * p; { /* Tell the user that this command is not supported */ ! return (pop_msg(p,POP_FAILURE,"The auth command is not supported yet")); } diff -p work/qpopper2.41beta1/pop_dropcopy.c work2/qpopper2.41beta1/pop_dropcopy.c *** work/qpopper2.41beta1/pop_dropcopy.c Sun Jun 28 12:58:14 1998 --- work2/qpopper2.41beta1/pop_dropcopy.c Sun Jun 28 13:07:47 1998 *************** POP *p; *** 489,495 **** /* Skip over header string */ cp = &buffer[7]; while (*cp && (*cp == ' ' || *cp == '\t')) cp++; ! if(strlen(cp) < DIG_SIZE) /* To account for the empty UIDL string */ { uidl_found--; /*roll over as though it hasn't seen anything*/ continue; --- 489,501 ---- /* Skip over header string */ cp = &buffer[7]; while (*cp && (*cp == ' ' || *cp == '\t')) cp++; ! /* ! * The UIDL digest SHOULD be approx. 32 chars long, ! * so reject/skip any X-UIDL: lines that don't fit ! * this profile. A new X-UIDL: line will be created ! * for any messages that don't have a valid one. ! */ ! if(strlen(cp) < DIG_SIZE || strlen(cp) > DIG_SIZE * 3) { uidl_found--; /*roll over as though it hasn't seen anything*/ continue; diff -p work/qpopper2.41beta1/pop_init.c work2/qpopper2.41beta1/pop_init.c *** work/qpopper2.41beta1/pop_init.c Wed Nov 19 14:20:38 1997 --- work2/qpopper2.41beta1/pop_init.c Sat Jun 27 23:38:54 1998 *************** char ** argmessage; *** 281,288 **** ch = gethostbyaddr((char *) &cs.sin_addr, sizeof(cs.sin_addr), AF_INET); if (ch == NULL){ pop_log(p,POP_PRIORITY, ! "(v%s) Unable to get canonical name of client, err = %d", ! VERSION, errno); p->client = p->ipaddr; } /* Save the cannonical name of the client host in --- 281,288 ---- ch = gethostbyaddr((char *) &cs.sin_addr, sizeof(cs.sin_addr), AF_INET); if (ch == NULL){ pop_log(p,POP_PRIORITY, ! "(v%s) Unable to get canonical name of client [%], err = %d", ! VERSION, p->ipaddr, errno); p->client = p->ipaddr; } /* Save the cannonical name of the client host in diff -p work/qpopper2.41beta1/pop_msg.c work2/qpopper2.41beta1/pop_msg.c *** work/qpopper2.41beta1/pop_msg.c Sun Jun 28 12:58:15 1998 --- work2/qpopper2.41beta1/pop_msg.c Sat Jun 27 23:25:59 1998 *************** va_dcl *** 61,67 **** /* Point past the POP status indicator in the message message */ l = strlen(mp); ! len -= l, mp += l; /* Append the message (formatted, if necessary) */ if (format) --- 61,74 ---- /* Point past the POP status indicator in the message message */ l = strlen(mp); ! mp += l; ! /* ! * Subtract an additional 2 from the remaining buffer length ! * so that after the vsnprintf()/snprintf() calls there will ! * still be enough buffer space to append a "\r\n" even in a ! * worst-case scenario. ! */ ! len -= l - 2; /* Append the message (formatted, if necessary) */ if (format) *************** va_dcl *** 90,97 **** (p->user ? p->user : "(null)"), p->client, message); /* Append the <CR><LF> */ ! len -= strlen(message); ! (void)strncat(message, len, "\r\n"); /* Send the message to the client */ (void)fputs(message,p->output); --- 97,104 ---- (p->user ? p->user : "(null)"), p->client, message); /* Append the <CR><LF> */ ! len -= strlen(mp); ! (void)strncat(message, "\r\n", len); /* Send the message to the client */ (void)fputs(message,p->output); diff -p work/qpopper2.41beta1/pop_parse.c work2/qpopper2.41beta1/pop_parse.c *** work/qpopper2.41beta1/pop_parse.c Wed Nov 19 14:20:38 1997 --- work2/qpopper2.41beta1/pop_parse.c Sat Jun 27 22:58:17 1998 *************** char * buf; /* Pointer *** 26,31 **** --- 26,32 ---- { char * mp; register int i; + register int parmlen; /* Loop through the POP command array */ for (mp = buf, i = 0; ; i++) { *************** char * buf; /* Pointer *** 45,52 **** /* Point to the start of the token */ p->pop_parm[i] = mp; /* Search for the first space character (end of the token) */ ! while (!isspace(*mp) && *mp) mp++; /* Delimit the token with a null */ if (*mp) *mp++ = 0; --- 46,75 ---- /* Point to the start of the token */ p->pop_parm[i] = mp; + /* Start counting the length of this token */ + parmlen = 0; + /* Search for the first space character (end of the token) */ ! while (!isspace(*mp) && *mp) { ! mp++; ! parmlen++; ! if (parmlen > MAXPARMLEN) { ! /* Truncate parameter to the max. allowable size */ ! *mp = '\0'; ! ! /* Fail with an appropriate message */ ! if (i == 0) { ! pop_msg(p,POP_FAILURE, ! "Command \"%s\" (truncated) exceedes maximum permitted size.", ! p->pop_command); ! } else { ! pop_msg(p,POP_FAILURE, ! "Argument %d \"%s\" (truncated) exceeds maximum permitted size.", ! i, p->pop_parm[i]); ! } ! return(-1); ! } ! } /* Delimit the token with a null */ if (*mp) *mp++ = 0; diff -p work/qpopper2.41beta1/pop_uidl.c work2/qpopper2.41beta1/pop_uidl.c *** work/qpopper2.41beta1/pop_uidl.c Wed Nov 19 14:20:38 1997 --- work2/qpopper2.41beta1/pop_uidl.c Sun Jun 28 13:09:56 1998 *************** from_hdr(p, mp) *** 101,107 **** POP *p; MsgInfoList *mp; { ! char buf[MAXLINELEN], *cp; fseek(p->drop, mp->offset, 0); while (fgets(buf, sizeof(buf), p->drop) != NULL) { --- 101,112 ---- POP *p; MsgInfoList *mp; { ! /* ! * Shorten this buffer so that an extra-long From: header ! * won't overflow the buffers in the pop_euidl() where ! * this function is called. 128 should be sufficient. ! */ ! static char buf[MAXLINELEN - 128], *cp; fseek(p->drop, mp->offset, 0); while (fgets(buf, sizeof(buf), p->drop) != NULL) { diff -p work/qpopper2.41beta1/popper.h work2/qpopper2.41beta1/popper.h *** work/qpopper2.41beta1/popper.h Sun Jun 28 12:58:15 1998 --- work2/qpopper2.41beta1/popper.h Sun Jun 28 11:56:10 1998 *************** *** 59,65 **** #define MAXMSGLINELEN MAXLINELEN #define MAXCMDLEN 4 #define MAXPARMCOUNT 5 ! #define MAXPARMLEN 10 #define ALLOC_MSGS 20 #ifndef OSF1 --- 59,65 ---- #define MAXMSGLINELEN MAXLINELEN #define MAXCMDLEN 4 #define MAXPARMCOUNT 5 ! #define MAXPARMLEN 32 /* Large enough for 32-byte APOP parm. */ #define ALLOC_MSGS 20 #ifndef OSF1 Have fun, but not too much! ;) Aaron out. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe security" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199806281925.NAA24567>