From c93e32331e20df7ccf0654c0f86fe9a10a219b25 Mon Sep 17 00:00:00 2001 From: Michiel Broek Date: Sat, 12 Jul 2003 20:34:04 +0000 Subject: [PATCH] Fixed a bug in rfcmsg when the Cc: header is empty --- ChangeLog | 2 + lib/common.h | 2 +- lib/rfcmsg.c | 221 ++++++++++++++++++++++----------------------------- 3 files changed, 97 insertions(+), 128 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5c5dbfa9..7cfd7def 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,6 +26,8 @@ v0.37.4 10-May-2003 5 years to find them! If you want to check, call 5:5/0 Fixed compiler warning in network code. printable function now escapes all non-printable characters. + In rfcmsg function the Cc: header is now treated as any other + header to prevent a SIGSEGV when the headerline is empty. mbcico: The binkp transmitter does now escape the unsafe filename diff --git a/lib/common.h b/lib/common.h index 30de3767..47a045ae 100644 --- a/lib/common.h +++ b/lib/common.h @@ -418,7 +418,7 @@ typedef struct _rfcmsg { rfcmsg *parsrfc(FILE *); void tidyrfc(rfcmsg *); -void dumpmsg(rfcmsg *,FILE *); + /* diff --git a/lib/rfcmsg.c b/lib/rfcmsg.c index fbc61b7a..7b3642bb 100644 --- a/lib/rfcmsg.c +++ b/lib/rfcmsg.c @@ -4,7 +4,7 @@ * Purpose ...............: RFC msg * ***************************************************************************** - * Copyright (C) 1997-2002 + * Copyright (C) 1997-2003 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -47,143 +47,110 @@ +/* + * Parse RFC message, extract headers and do some sanity checks. + */ rfcmsg *parsrfc(FILE *fp) { - int linecont=FALSE,newcont,firstline; - rfcmsg *start=NULL, *cur=NULL; - char buffer[BUFSIZ]; - char *p; + int linecont=FALSE,newcont,firstline; + rfcmsg *start=NULL, *cur=NULL; + char buffer[BUFSIZ], *p; - while (bgets(buffer, BUFSIZ-1, fp) && strcmp(buffer,"\n")) { - newcont = (buffer[strlen(buffer)-1] != '\n'); - Syslog('M', "Line read: \"%s\" - %s continued", buffer,newcont?"to be":"not to be"); - if (linecont) { - Syslog('M', "this is a continuation of a long line"); - cur->val=xstrcat(cur->val,buffer); - } else { - if (isspace(buffer[0])) { - if (strspn(buffer," \t\n") == strlen(buffer)) { - Syslog('M', "breaking with blank-only line"); - break; - } - Syslog('M', "this is a continuation line"); - if (!cur) { - Syslog('M', "Wrong first line: \"%s\"",buffer); - cur = (rfcmsg *)malloc(sizeof(rfcmsg)); - start = cur; - cur->next = NULL; - cur->key = xstrcpy((char *)"X-Body-Start"); - cur->val = xstrcpy(buffer); - break; - } else - cur->val = xstrcat(cur->val,buffer); - } else { -// Syslog('M', "this is a header line"); - if (cur) { - firstline=FALSE; - (cur->next) = (rfcmsg *)malloc(sizeof(rfcmsg)); - cur = cur->next; - } else { - firstline = TRUE; - cur = (rfcmsg *)malloc(sizeof(rfcmsg)); - start = cur; - } - cur->next = NULL; - cur->key = NULL; - cur->val = NULL; - if (firstline && !strncmp(buffer,"From ",5)) { - Syslog('M', "This is a uucpfrom line"); - cur->key=xstrcpy((char *)"X-UUCP-From"); - cur->val=xstrcpy(buffer+4); - } else if ( !strncasecmp(buffer,"Cc:",3)) { - Syslog('M', "Cc: line"); - if (strchr(buffer+3,'@')) { - cur->key = xstrcpy((char *)"Cc"); - cur->val = xstrcpy(buffer+3); - } else { - Syslog('M', "FTN Cc: line: \"%s\"", buffer); - cur->key = xstrcpy((char *)"X-Body-Start"); - cur->val = xstrcpy(buffer); - break; - } - } else if ((p=strchr(buffer,':')) && (p > buffer) && /* ':' isn't 1st chr */ - isspace(*(p+1)) && /* space past ':' */ - /* at least one non blank char */ - (strspn(p+2, " \t\n") < strlen(p+2)) && (strspn(buffer,KWDCHARS) == (p-buffer))) { - *p='\0'; -// Syslog('M', "This is a regular header"); - cur->key = xstrcpy(buffer); - cur->val = xstrcpy(p+1); - } else if ((p=strchr(buffer,':')) && (!strncasecmp(buffer, (char *)"X-MS-", 5))) { - /* - * It looks like M$ invented their own internet standard, these - * are header lines without a key. This one will be stored here - * and junked in the rfc2ftn function. - */ - cur->key = xstrcpy(buffer); - cur->val = xstrcpy((char *)" "); - } else if ((p=strchr(buffer,':')) && (p > buffer)) { - /* - * Header line without information, don't add this one. - */ - Syslog('!', "Header line %s without key value", buffer); - cur->key = xstrcpy(buffer); - cur->val = xstrcpy((char *)" "); - } else if ((p=strchr(buffer,':')) && (p > buffer) && isspace(*(p+1))) { /* space past ':' */ - Syslog('!', "Header line %s without key value (but with a Space)", buffer); - cur->key = xstrcpy(buffer); - cur->val = xstrcpy((char *)" "); - } else { - Syslog('M', "Non-header line: \"%s\"",buffer); - cur->key = xstrcpy((char *)"X-Body-Start"); - cur->val = xstrcpy(buffer); - break; - } - } + while (bgets(buffer, BUFSIZ-1, fp) && strcmp(buffer,"\n")) { + newcont = (buffer[strlen(buffer)-1] != '\n'); + Syslog('M', "Line read: \"%s\" - %s continued", buffer,newcont?"to be":"not to be"); + if (linecont) { + Syslog('M', "this is a continuation of a long line"); + cur->val=xstrcat(cur->val,buffer); + } else { + if (isspace(buffer[0])) { + if (strspn(buffer," \t\n") == strlen(buffer)) { + Syslog('M', "breaking with blank-only line"); + break; } - linecont = newcont; + Syslog('M', "this is a continuation line"); + if (!cur) { + Syslog('M', "Wrong first line: \"%s\"",buffer); + cur = (rfcmsg *)malloc(sizeof(rfcmsg)); + start = cur; + cur->next = NULL; + cur->key = xstrcpy((char *)"X-Body-Start"); + cur->val = xstrcpy(buffer); + break; + } else + cur->val = xstrcat(cur->val,buffer); + } else { +// Syslog('M', "this is a header line"); + if (cur) { + firstline=FALSE; + (cur->next) = (rfcmsg *)malloc(sizeof(rfcmsg)); + cur = cur->next; + } else { + firstline = TRUE; + cur = (rfcmsg *)malloc(sizeof(rfcmsg)); + start = cur; + } + cur->next = NULL; + cur->key = NULL; + cur->val = NULL; + if (firstline && !strncmp(buffer,"From ",5)) { + Syslog('M', "This is a uucpfrom line"); + cur->key=xstrcpy((char *)"X-UUCP-From"); + cur->val=xstrcpy(buffer+4); + } else if ((p=strchr(buffer,':')) && (p > buffer) && /* ':' isn't 1st chr */ + isspace(*(p+1)) && /* space past ':' */ + /* at least one non blank char */ + (strspn(p+2, " \t\n") < strlen(p+2)) && (strspn(buffer,KWDCHARS) == (p-buffer))) { + *p='\0'; +// Syslog('M', "This is a regular header"); + cur->key = xstrcpy(buffer); + cur->val = xstrcpy(p+1); + } else if ((p=strchr(buffer,':')) && (!strncasecmp(buffer, (char *)"X-MS-", 5))) { + /* + * It looks like M$ invented their own internet standard, these + * are header lines without a key. This one will be stored here + * and junked in the rfc2ftn function. + */ + cur->key = xstrcpy(buffer); + cur->val = xstrcpy((char *)" "); + } else if ((p=strchr(buffer,':')) && (p > buffer)) { + /* + * Header line without information, don't add this one but log. + */ + Syslog('!', "Header line \"%s\" without key value", buffer); + cur->key = xstrcpy(buffer); + cur->val = xstrcpy((char *)" "); + } else if ((p=strchr(buffer,':')) && (p > buffer) && isspace(*(p+1))) { /* space past ':' */ + Syslog('!', "Header line \"%s\" without key value (but with a Space)", buffer); + cur->key = xstrcpy(buffer); + cur->val = xstrcpy((char *)" "); + } else { + Syslog('M', "Non-header line: \"%s\"",buffer); + cur->key = xstrcpy((char *)"X-Body-Start"); + cur->val = xstrcpy(buffer); + break; + } + } } - return(start); + linecont = newcont; + } + return(start); } void tidyrfc(rfcmsg *msg) { - rfcmsg *nxt; + rfcmsg *nxt; - for (; msg; msg=nxt) { - nxt = msg->next; - if (msg->key) - free(msg->key); - if (msg->val) - free(msg->val); - free(msg); - } - return; + for (; msg; msg=nxt) { + nxt = msg->next; + if (msg->key) + free(msg->key); + if (msg->val) + free(msg->val); + free(msg); + } + return; } - - -void dumpmsg(rfcmsg *msg, FILE *fp) -{ - char *p; - - p = hdr((char *)"X-Body-Start",msg); - for (; msg; msg=msg->next) - if (strcasecmp(msg->key, "X-Body-Start")) { - if (!strcasecmp(msg->key, "X-UUCP-From")) - fputs("From", fp); - else { - fputs(msg->key,fp); - fputs(":",fp); - } - fputs(msg->val,fp); - } - fputs("\n",fp); - if (p) - fputs(p,fp); - return; -} - -