From owner-svn-ports-head@FreeBSD.ORG Sun Jan 18 12:01:20 2015 Return-Path: Delivered-To: svn-ports-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id B1D11C44; Sun, 18 Jan 2015 12:01:20 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9259E140; Sun, 18 Jan 2015 12:01:20 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0IC1KiO093948; Sun, 18 Jan 2015 12:01:20 GMT (envelope-from danfe@FreeBSD.org) Received: (from danfe@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0IC1JLq093944; Sun, 18 Jan 2015 12:01:19 GMT (envelope-from danfe@FreeBSD.org) Message-Id: <201501181201.t0IC1JLq093944@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: danfe set sender to danfe@FreeBSD.org using -f From: Alexey Dokuchaev Date: Sun, 18 Jan 2015 12:01:19 +0000 (UTC) To: ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org Subject: svn commit: r377324 - in head/www/thttpd: . files X-SVN-Group: ports-head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-ports-head@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the ports tree for head List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 18 Jan 2015 12:01:20 -0000 Author: danfe Date: Sun Jan 18 12:01:18 2015 New Revision: 377324 URL: https://svnweb.freebsd.org/changeset/ports/377324 QAT: https://qat.redports.org/buildarchive/r377324/ Log: Bring another several patches from Gentoo and Red Hat (also relevant to the upcoming 2.26): - Fix potential buffer overflow in expand_symlinks() function of libhttpd.c - Better handling of tempfile and additional input validation in htpasswd(1) - Make sure that the logfile is created or reopened as read/write by thttpd (www) user only (modified to allow group read access as well so web admin won't have to su(1) to super-user or "www" to be able to read logs) [1] Bump port revision to account for these and previous changes. Gentoo bug: 458896 [1] Security: CVE-2013-0348 [1] Added: head/www/thttpd/files/patch-extras_htpasswd.c (contents, props changed) Modified: head/www/thttpd/Makefile head/www/thttpd/files/patch-libhttpd.c head/www/thttpd/files/patch-thttpd.c Modified: head/www/thttpd/Makefile ============================================================================== --- head/www/thttpd/Makefile Sun Jan 18 11:40:01 2015 (r377323) +++ head/www/thttpd/Makefile Sun Jan 18 12:01:18 2015 (r377324) @@ -3,7 +3,7 @@ PORTNAME= thttpd PORTVERSION= 2.25b -PORTREVISION= 5 +PORTREVISION= 6 CATEGORIES= www ipv6 MASTER_SITES= http://www.acme.com/software/thttpd/ \ http://atreides.freenix.no/~anders/ Added: head/www/thttpd/files/patch-extras_htpasswd.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/www/thttpd/files/patch-extras_htpasswd.c Sun Jan 18 12:01:18 2015 (r377324) @@ -0,0 +1,201 @@ +--- extras/htpasswd.c.orig 2001-12-19 00:08:08 UTC ++++ extras/htpasswd.c +@@ -21,7 +21,12 @@ extern char *crypt(const char *key, cons + #define LF 10 + #define CR 13 + ++#define CPW_LEN 13 ++ ++/* ie 'string' + '\0' */ + #define MAX_STRING_LEN 256 ++/* ie 'maxstring' + ':' + cpassword */ ++#define MAX_LINE_LEN MAX_STRING_LEN+1+CPW_LEN + + int tfd; + char temp_template[] = "/tmp/htp.XXXXXX"; +@@ -137,8 +142,9 @@ add_password( char* user, FILE* f ) + } + + static void usage(void) { +- fprintf(stderr,"Usage: htpasswd [-c] passwordfile username\n"); +- fprintf(stderr,"The -c flag creates a new file.\n"); ++ fprintf(stderr,"Usage: htpasswd [-c] passwordfile username\n" ++ "The -c flag creates a new file.\n" ++ "Will prompt for password, unless given on stdin.\n"); + exit(1); + } + +@@ -151,51 +157,131 @@ void interrupted(int signo) { + int main(int argc, char *argv[]) { + FILE *tfp,*f; + char user[MAX_STRING_LEN]; +- char line[MAX_STRING_LEN]; +- char l[MAX_STRING_LEN]; ++ char pwfilename[MAX_STRING_LEN]; ++ char line[MAX_LINE_LEN]; ++ char l[MAX_LINE_LEN]; + char w[MAX_STRING_LEN]; + char command[MAX_STRING_LEN]; +- int found; ++ int found,u; + + tfd = -1; ++ u = 2; /* argv[u] is username, unless... */ + signal(SIGINT,(void (*)(int))interrupted); + if(argc == 4) { ++ u = 3; + if(strcmp(argv[1],"-c")) + usage(); ++ if((f=fopen(argv[2],"r")) != NULL) { ++ fclose(f); ++ fprintf(stderr, ++ "Password file %s already exists.\n" ++ "Delete it first, if you really want to overwrite it.\n", ++ argv[2]); ++ exit(1); ++ } ++ } else if(argc != 3) usage(); ++ /* check uname length; underlying system will take care of pwdfile ++ name too long */ ++ if (strlen(argv[u]) >= MAX_STRING_LEN) { ++ fprintf(stderr,"Username too long (max %i): %s\n", ++ MAX_STRING_LEN-1, argv[u]); ++ exit(1); ++ } ++ ++ if(argc == 4) { + if(!(tfp = fopen(argv[2],"w"))) { + fprintf(stderr,"Could not open passwd file %s for writing.\n", + argv[2]); + perror("fopen"); + exit(1); + } ++ if (strlen(argv[2]) > (sizeof(pwfilename) - 1)) { ++ fprintf(stderr, "%s: filename is too long\n", argv[0]); ++ exit(1); ++ } ++ if (((strchr(argv[2], ';')) != NULL) || ((strchr(argv[2], '>')) != NULL)) { ++ fprintf(stderr, "%s: filename contains an illegal character\n", ++ argv[0]); ++ exit(1); ++ } ++ if (strlen(argv[3]) > (sizeof(user) - 1)) { ++ fprintf(stderr, "%s: username is too long\n", argv[0], ++ sizeof(user) - 1); ++ exit(1); ++ } ++ if ((strchr(argv[3], ':')) != NULL) { ++ fprintf(stderr, "%s: username contains an illegal character\n", ++ argv[0]); ++ exit(1); ++ } + printf("Adding password for %s.\n",argv[3]); + add_password(argv[3],tfp); + fclose(tfp); + exit(0); +- } else if(argc != 3) usage(); ++ } + +- tfd = mkstemp(temp_template); +- if(!(tfp = fdopen(tfd,"w"))) { +- fprintf(stderr,"Could not open temp file.\n"); ++ if (strlen(argv[1]) > (sizeof(pwfilename) - 1)) { ++ fprintf(stderr, "%s: filename is too long\n", argv[0]); ++ exit(1); ++ } ++ if (((strchr(argv[1], ';')) != NULL) || ((strchr(argv[1], '>')) != NULL)) { ++ fprintf(stderr, "%s: filename contains an illegal character\n", ++ argv[0]); ++ exit(1); ++ } ++ if (strlen(argv[2]) > (sizeof(user) - 1)) { ++ fprintf(stderr, "%s: username is too long\n", argv[0], ++ sizeof(user) - 1); ++ exit(1); ++ } ++ if ((strchr(argv[2], ':')) != NULL) { ++ fprintf(stderr, "%s: username contains an illegal character\n", ++ argv[0]); + exit(1); + } +- + if(!(f = fopen(argv[1],"r"))) { + fprintf(stderr, + "Could not open passwd file %s for reading.\n",argv[1]); + fprintf(stderr,"Use -c option to create new one.\n"); + exit(1); + } ++ if(freopen(argv[1],"a",f) == NULL) { ++ fprintf(stderr, ++ "Could not open passwd file %s for writing!.\n" ++ "Changes would be lost.\n",argv[1]); ++ exit(1); ++ } ++ f = freopen(argv[1],"r",f); ++ ++ /* pwdfile is there, go on with tempfile now ... */ ++ tfd = mkstemp(temp_template); ++ if(!(tfp = fdopen(tfd,"w"))) { ++ fprintf(stderr,"Could not open temp file.\n"); ++ exit(1); ++ } ++ /* already checked for boflw ... */ + strcpy(user,argv[2]); + + found = 0; +- while(!(getline(line,MAX_STRING_LEN,f))) { ++ /* line we get is username:pwd, or possibly any other cruft */ ++ while(!(getline(line,MAX_LINE_LEN,f))) { ++ char *i; ++ + if(found || (line[0] == '#') || (!line[0])) { + putline(tfp,line); + continue; + } +- strcpy(l,line); +- getword(w,l,':'); ++ i = index(line,':'); ++ w[0] = '\0'; ++ /* actually, cpw is CPW_LEN chars and never null, hence ':' should ++ always be at line[strlen(line)-CPW_LEN-1] in a valid user:cpw line ++ Here though we may allow for pre-hancrafted pwdfile (!)... ++ But still need to check for length limits. ++ */ ++ if (i != 0 && i-line <= MAX_STRING_LEN-1) { ++ strcpy(l,line); ++ getword(w,l,':'); ++ } + if(strcmp(user,w)) { + putline(tfp,line); + continue; +@@ -210,10 +296,28 @@ int main(int argc, char *argv[]) { + printf("Adding user %s\n",user); + add_password(user,tfp); + } ++ /* close, rewind & copy */ ++ fclose(f); ++ fclose(tfp); ++ f = fopen(argv[1],"w"); ++ if(f==NULL) { ++ fprintf(stderr,"Failed re-opening %s!?\n",argv[1]); ++ exit(1); ++ } ++ tfp = fopen(temp_template,"r"); ++ if(tfp==NULL) { ++ fprintf(stderr,"Failed re-opening tempfile!?\n"); ++ exit(1); ++ } ++ { ++ int c; ++ while((c=fgetc(tfp))!=EOF && !feof(tfp)) { ++ fputc(c,f); ++ /* fputc(c,stderr); */ ++ } ++ } + fclose(f); + fclose(tfp); +- sprintf(command,"cp %s %s",temp_template,argv[1]); +- system(command); + unlink(temp_template); + exit(0); + } Modified: head/www/thttpd/files/patch-libhttpd.c ============================================================================== --- head/www/thttpd/files/patch-libhttpd.c Sun Jan 18 11:40:01 2015 (r377323) +++ head/www/thttpd/files/patch-libhttpd.c Sun Jan 18 12:01:18 2015 (r377324) @@ -1,6 +1,24 @@ --- libhttpd.c.orig Mon May 27 01:22:26 2002 +++ libhttpd.c Sun Oct 20 23:49:58 2002 -@@ -3816,6 +3816,9 @@ +@@ -1483,7 +1483,7 @@ + httpd_realloc_str( &checked, &maxchecked, checkedlen ); + (void) strcpy( checked, path ); + /* Trim trailing slashes. */ +- while ( checked[checkedlen - 1] == '/' ) ++ while ( checkedlen && checked[checkedlen - 1] == '/' ) + { + checked[checkedlen - 1] = '\0'; + --checkedlen; +@@ -1502,7 +1502,7 @@ + restlen = strlen( path ); + httpd_realloc_str( &rest, &maxrest, restlen ); + (void) strcpy( rest, path ); +- if ( rest[restlen - 1] == '/' ) ++ if ( restlen && rest[restlen - 1] == '/' ) + rest[--restlen] = '\0'; /* trim trailing slash */ + if ( ! tildemapped ) + /* Remove any leading slashes. */ +@@ -3889,6 +3889,9 @@ httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); return -1; } Modified: head/www/thttpd/files/patch-thttpd.c ============================================================================== --- head/www/thttpd/files/patch-thttpd.c Sun Jan 18 11:40:01 2015 (r377323) +++ head/www/thttpd/files/patch-thttpd.c Sun Jan 18 12:01:18 2015 (r377324) @@ -1,6 +1,42 @@ --- thttpd.c.orig Wed Jun 29 19:50:59 2005 +++ thttpd.c Sun Jun 17 21:30:11 2007 -@@ -1723,12 +1723,45 @@ +@@ -331,6 +331,7 @@ + re_open_logfile( void ) + { + FILE* logfp; ++ int retchmod; + + if ( no_log || hs == (httpd_server*) 0 ) + return; +@@ -340,7 +341,8 @@ + { + syslog( LOG_NOTICE, "re-opening logfile" ); + logfp = fopen( logfile, "a" ); +- if ( logfp == (FILE*) 0 ) ++ retchmod = chmod( logfile, S_IRUSR|S_IWUSR ); ++ if ( logfp == (FILE*) 0 || retchmod != 0 ) + { + syslog( LOG_CRIT, "re-opening %.80s - %m", logfile ); + return; +@@ -360,6 +362,7 @@ + gid_t gid = 32767; + char cwd[MAXPATHLEN+1]; + FILE* logfp; ++ int retchmod; + int num_ready; + int cnum; + connecttab* c; +@@ -429,7 +432,8 @@ + else + { + logfp = fopen( logfile, "a" ); +- if ( logfp == (FILE*) 0 ) ++ retchmod = chmod( logfile, S_IRUSR|S_IWUSR|S_IRGRP ); ++ if ( logfp == (FILE*) 0 || retchmod != 0 ) + { + syslog( LOG_CRIT, "%.80s - %m", logfile ); + perror( logfile ); +@@ -1714,12 +1718,45 @@ if ( hc->responselen == 0 ) { /* No, just write the file. */ @@ -46,7 +82,7 @@ /* Yes. We'll combine headers and file into a single writev(), ** hoping that this generates a single packet. */ -@@ -1739,6 +1772,7 @@ +@@ -1730,6 +1767,7 @@ iv[1].iov_base = &(hc->file_address[c->next_byte_index]); iv[1].iov_len = MIN( c->end_byte_index - c->next_byte_index, max_bytes ); sz = writev( hc->conn_fd, iv, 2 ); @@ -54,7 +90,7 @@ } if ( sz < 0 && errno == EINTR ) -@@ -1786,7 +1820,11 @@ +@@ -1777,7 +1815,11 @@ ** ** And ECONNRESET isn't interesting either. */