Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Dec 2005 01:21:43 +0100 (CET)
From:      Juergen Lock <nox@jelal.kn-bremen.de>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   ports/90317: buffer overflows in www/gnuinfo
Message-ID:  <200512130021.jBD0Lh3Q075056@saturn.kn-bremen.de>
Resent-Message-ID: <200512130030.jBD0U6em024794@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         90317
>Category:       ports
>Synopsis:       buffer overflows in www/gnuinfo
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          maintainer-update
>Submitter-Id:   current-users
>Arrival-Date:   Tue Dec 13 00:30:06 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Juergen Lock
>Release:        FreeBSD 5.3-RELEASE-p20 i386
>Organization:
me?  organized??
>Environment:
System: FreeBSD saturn 5.3-RELEASE-p20 FreeBSD 5.3-RELEASE-p20 #1: Fri Jul 29 14:59:03 CEST 2005 nox@saturn:/usr/home/nox/src5/usr/src/sys/i386/compile/NEPTUN i386


	
>Description:
	Per advice of kris@ I post the security patch, in the
hope that the port will be added to vuxml soon.  (I hope the
disappeared MASTER_SITE can be taken care of after that.)

Security: try to fix possible buffer overflows or similar.

>How-To-Repeat:
	hmm, look at the code? :)
>Fix:

New file: files/patch-security

Index: files/patch-security
@@ -0,0 +1,315 @@
+Index: convert.lex
+@@ -140,50 +140,66 @@
+ 
+ void print_longlink(char *link)
+ {
+-  char linknode[LINK_LENGTH];
++  char linknode[LINK_LENGTH * 3];
+   char linkfile[LINK_LENGTH];
+   char text[LINK_LENGTH];
+   char *h;
+ 
+   /* text */
+-  strcpy(text,link+(link[1]==' ' ? 2 : 6));
+-  *(strchr(text,':')) = '\0';
++  snprintf(text, sizeof text, "%s", link+(link[1]==' ' ? 2 : 6));
++  h = strchr(text,':');
++  if (h) *h = '\0';
+ 
+   /* link */
+   h = strchr(link,':');
+   do h++; while (*h == ' ');
+   if (*h == '(') {
+     /* we have a file */
+-    strcpy(linkfile,h+1);
+-    *(h=strchr(linkfile,')')) = '\0';
+-    do h++; while (*h == ' ');
++    if (strlen(h) > sizeof linkfile) {
++      snprintf(linkfile, sizeof linkfile, "%s", file);
++      h = NULL;
++    } else {
++      snprintf(linkfile, sizeof linkfile, "%s", h+1);
++      h=strchr(linkfile,')');
++      if (h) *h = '\0';
++    }
++    if (h) {
++      do h++; while (*h == ' ');
++    }
+     strcpy(linknode,"Top"); /* default node, may be overwritten later */
+   } else {
+-    strcpy(linkfile,file);
++    snprintf(linkfile, sizeof linkfile, "%s", file);
+   }
+-  if (*h != '.' && *h != ',') {
++  if (h && *h != '.' && *h != ',' && strlen(h) * 3 < sizeof linknode - 1) {
+     /* we have a node */
+-    quote(linknode,h);
++    quote(linknode, sizeof linknode, h);
+     h = strstr(linknode,"%2e"); /* quoted '.' */
+     if (!h)
+       h = strstr(linknode,"%2c"); /* quoted ',' */
+-    *h = '\0';
++    if (h) *h = '\0';
+   }
+   printf("<a href=\"%s/%s/%s\">*",whoami,linkfile,linknode);
+   if (link[1] != ' ') printf("note");
+   printf(" %s:</a>",text);
+   if (link[1] == ' ') printf(MENU_DESC);
+   h = strchr(link,':');
+-  do h++; while (*h == ' ');
+-  printf("%s",h); 
++  if (h) {
++    do h++; while (*h == ' ');
++    printf("%s",h); 
++  }
+ }
+ 
+ void print_shortlink(char *link)
+ {
+-  char linknode[LINK_LENGTH];
++  char linknode[LINK_LENGTH * 3], *h;
+ 
+-  quote(linknode,link+(link[1]==' ' ? 2 : 6));
+-  *(strstr(linknode,"%3a")) = '\0'; /* ':' -> "%3a" (URL-Quoting) */
++  if (strlen(link) * 3 > sizeof linknode - 1)
++    strcpy(linknode, "Top");
++  else {
++    quote(linknode, sizeof linknode, link+(link[1]==' ' ? 2 : 6));
++    h = strstr(linknode,"%3a");
++    if (h) *h = '\0'; /* ':' -> "%3a" (URL-Quoting) */
++  }
+ 
+   printf("<a href=\"%s/%s/%s\">",whoami,file,linknode);
+   printf("%s</a>",link); 
+Index: info2html.c
+@@ -22,12 +22,12 @@
+ 
+ /*-------------------------------------------------------------*/
+ 
+-void quote(char *dest, char *src)
++void quote(char *dest, size_t bufsize, char *src)
+ {
+   static const char lookup[16] = "0123456789abcdef";
+   int  i,j;
+   
+-  for (i=0, j=0; src[j] != '\0';) {
++  for (i=0, j=0; src[j] != '\0' && i < bufsize - 4 ;) {
+     if (isalnum(src[j])) {
+       dest[i++] = src[j++];
+     } else {
+@@ -41,12 +41,12 @@
+ }
+ 
+ /* copy string and convert the "%??" to normal char's */
+-void unquote(char *dest, char *src)
++void unquote(char *dest, size_t bufsize, char *src)
+ {
+   int  i,j,hex;
+   char nr[3];
+   
+-  for (i=0, j=0; src[j] != '?' && src[j] != '\0'; i++) {
++  for (i=0, j=0; src[j] != '?' && src[j] != '\0' && i < bufsize - 1 ; i++) {
+     if (src[j] == '%') {
+       nr[0] = src[j+1];
+       nr[1] = src[j+2];
+@@ -72,12 +72,12 @@
+   file[0] = 0;
+   node[0] = 0;
+   path = getenv("PATH_INFO");
+-  if (path && *path) {
+-    strcpy(file,path+1);
++  if (path && *path && strlen(path) < sizeof file) {
++    snprintf(file, sizeof file, "%s", path+1);
+     h = strchr(file,'/');
+     if (h) {
+       *(h++) = 0;
+-      if (*h) strcpy(node,h);
++      if (*h) snprintf(node, sizeof node, "%s", h);
+       /* workaround: Spinner appends a slash to the URL */
+       if (NULL != (h = strchr(node,'/'))) *h = 0;
+     }
+@@ -100,11 +100,13 @@
+       h++;
+     }
+   }
+-  strcpy(whoami,h);
++  if (strlen(h) >= sizeof whoami)
++    h = argv0;
++  snprintf(whoami, sizeof whoami, "%s", h);
+ }
+ 
+ /*-------------------------------------------------------------*/
+-
++ 
+ char infodirs[]=INFODIRS;
+ char *dirs[20];
+ 
+@@ -119,7 +121,7 @@
+   else
+     dirs[0] = infodirs;
+ 
+-  for (i = 0; dirs[i] != NULL ; i++) {
++  for (i = 0; dirs[i] != NULL && i < sizeof dirs - 1; i++) {
+     h = strchr(dirs[i],':');
+     if (h) {
+       *h = 0;
+@@ -135,7 +137,7 @@
+ /* open an infofile. The indir-parameter is for indirections */
+ FILE *open_infofile(int indir)
+ {
+-  char         filename[LINK_LENGTH],nr[10],last_modi[80];
++  char         *filename = NULL,nr[10],last_modi[80];
+   struct stat  st;
+   int          fd_pipe[2];
+   int          i,d,gzip;
+@@ -149,29 +151,29 @@
+     for (i = 0; i < 4 /* 8 */; i++) {
+       switch (i) {
+       case 0:
+-	gzip = FALSE;sprintf(filename,"%s/%s%s",dirs[d],file,nr);
++	gzip = FALSE;asprintf(&filename,"%s/%s%s",dirs[d],file,nr);
+ 	break;
+       case 1:
+-	gzip = FALSE;sprintf(filename,"%s/%s.info%s",dirs[d],file,nr);
++	gzip = FALSE;asprintf(&filename,"%s/%s.info%s",dirs[d],file,nr);
+ 	break;
+       case 2:
+-	gzip = TRUE; sprintf(filename,"%s/%s%s.gz",dirs[d],file,nr);
++	gzip = TRUE; asprintf(&filename,"%s/%s%s.gz",dirs[d],file,nr);
+ 	break;
+       case 3:
+-	gzip = TRUE; sprintf(filename,"%s/%s.info%s.gz",dirs[d],file,nr);
++	gzip = TRUE; asprintf(&filename,"%s/%s.info%s.gz",dirs[d],file,nr);
+ 	break;
+ /*
+       case 4:
+-	gzip = TRUE; sprintf(filename,"%s/%s%s.z",dirs[d],file,nr);
++	gzip = TRUE; asprintf(&filename,"%s/%s%s.z",dirs[d],file,nr);
+ 	break;
+       case 5:
+-	gzip = TRUE; sprintf(filename,"%s/%s.info%s.z",dirs[d],file,nr);
++	gzip = TRUE; asprintf(&filename,"%s/%s.info%s.z",dirs[d],file,nr);
+ 	break;
+       case 6:
+-	gzip = TRUE; sprintf(filename,"%s/%s%s.Z",dirs[d],file,nr);
++	gzip = TRUE; asprintf(&filename,"%s/%s%s.Z",dirs[d],file,nr);
+ 	break;
+       case 7:
+-	gzip = TRUE; sprintf(filename,"%s/%s.info%s.Z",dirs[d],file,nr);
++	gzip = TRUE; asprintf(&filename,"%s/%s.info%s.Z",dirs[d],file,nr);
+ 	break;
+ */
+       default: return NULL; /* keep compiler happy */
+@@ -191,6 +193,7 @@
+ 	  pipe(fd_pipe);
+ 	  switch (fork()) {
+ 	  case -1:
++	    if (filename) free(filename);
+ 	    return NULL;
+ 	  case 0:
+ 	    /* child */
+@@ -204,14 +207,20 @@
+ 	    dup2(fd_pipe[0],0);
+ 	    close(fd_pipe[0]);
+ 	    close(fd_pipe[1]);
++	    if (filename) free(filename);
+ 	    return stdin;
+ 	  }
+ 	} else {
+-	  return fopen(filename,"r");
++	  if (filename) {
++	    FILE *ret = fopen(filename,"r");
++	    free(filename);
++	    return ret;
++	  }
+ 	}
+       }
+     }
+   }
++  if (filename) free(filename);
+   return NULL;
+ }
+ 
+@@ -221,23 +230,25 @@
+ {
+   char text[LINK_LENGTH];
+   char linkfile[LINK_LENGTH];
+-  char linknode[LINK_LENGTH];
++  char linknode[LINK_LENGTH * 3];
+   char *h;
+ 
++  if (strlen(buf) >= LINK_LENGTH) return;
+   h = strstr(buf,what);
+   if (!h) return;
+   h += strlen(what);
+-  strcpy(text,h);
++  snprintf(text, sizeof text, "%s", h);
+   h = strchr(text,',' ); if (h) *h = '\0';
+   h = strchr(text,'\t'); if (h) *h = '\0';
+   h = strchr(text,'\n'); if (h) *h = '\0';
+   if (text[0] == '(') {
+-    strcpy(linkfile,text+1);
+-    *(strchr(linkfile,')')) = '\0';
++    snprintf(linkfile, sizeof linkfile, "%s", text+1);
++    h = strchr(linkfile,')');
++    if (h) *h = '\0';
+     strcpy(linknode,"Top");
+   } else {
+-    strcpy(linkfile,file);
+-    quote(linknode,text);
++    snprintf(linkfile, sizeof linkfile, "%s", file);
++    quote(linknode, sizeof linknode, text);
+   }
+   printf("%s <a href=\"%s/%s/%s\">%s</a> \n",
+ 	 what,whoami,linkfile,linknode,text);
+@@ -249,21 +260,22 @@
+ log_error(int node_failed)
+ {
+   time_t tm;
+-  char   timestr[64],from[256];
++  char   timestr[64], *from = strdup("");
+ 
+   time(&tm);
+   strftime(timestr,64,"%a %h %d %T %Y",
+ 	   localtime(&tm));
+-  if (getenv("HTTP_REFERER")) /* be sure we have a referer */
+-    sprintf(from," from %250s",getenv("HTTP_REFERER"));
+-  else
+-    from[0] = 0;
++  if (getenv("HTTP_REFERER")) { /* be sure we have a referer */
++    free(from);
++    asprintf(&from," from %250s",getenv("HTTP_REFERER"));
++  }
+   if (node_failed)
+     fprintf(stderr,"[%s] gnuinfo: access to node %s, info file %s failed%s\n",
+ 	    timestr,node,file,from);
+   else
+     fprintf(stderr,"[%s] gnuinfo: access to info file %s failed%s\n",
+ 	    timestr,file,from);
++  if (from) free(from);
+ }
+ 
+ /*-------------------------------------------------------------*/
+@@ -366,8 +378,11 @@
+     }
+ 
+     /* find out which file */
+-    h = strchr(buf,127); h++;
+-    line = atoi(h);
++    if ((h = strchr(buf,127))) {
++      h++;
++      line = atoi(h);
++    } else
++      line = 0;
+     for (i = 0; indir_table[i] != 0 && line >= indir_table[i] ; i++);
+ 
+     /* play it again... */
+Index: info2html.h
+@@ -17,5 +17,5 @@
+ extern FILE *yyin;
+ int yylex();
+ 
+-void quote(char*, char*);
+-void unquote(char* , char*);
++void quote(char*, size_t bufsize, char*);
++void unquote(char*, size_t bufsize, char*);
>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200512130021.jBD0Lh3Q075056>