This patch comes from the Debian thttpd package. Many thanks to Daniel Baumann for all the recent changes. --- thttpd-2.23beta1.orig/extras/htpasswd.1 +++ thttpd-2.23beta1/extras/htpasswd.1 @@ -1,8 +1,8 @@ -.TH htpasswd 1 "05 May 1998" +.TH thtpasswd 1 "05 May 1998" .SH NAME -htpasswd - manipulate HTTP-server password files +thtpasswd - manipulate HTTP-server password files .SH SYNOPSIS -.B htpasswd +.B thtpasswd .RB [ -c ] .I passwordfile .I username --- thttpd-2.23beta1.orig/extras/htpasswd.c +++ thttpd-2.23beta1/extras/htpasswd.c @@ -21,7 +21,12 @@ #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 @@ } 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,17 +157,37 @@ 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 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]); @@ -172,12 +198,6 @@ 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"); - exit(1); } if(!(f = fopen(argv[1],"r"))) { @@ -186,16 +206,43 @@ 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 +257,28 @@ 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); } --- thttpd-2.23beta1.orig/extras/makeweb.1 +++ thttpd-2.23beta1/extras/makeweb.1 @@ -2,11 +2,17 @@ .SH NAME makeweb - create user web directory .SH SYNOPSIS -.B makeweb +.B makeweb +[\fI -d webdir \fR] .SH DESCRIPTION .PP This program allows users to create their own web subdirectories off of the main web directory. +.PP +.TP +\fB\-d\fR +Specify the root directory for new user directories. The default directory +is /var/www .SH "SEE ALSO thttpd(8) .SH AUTHOR --- thttpd-2.23beta1.orig/extras/makeweb.c +++ thttpd-2.23beta1/extras/makeweb.c @@ -47,6 +47,10 @@ static char* argv0; +void usage(void) +{ + printf("usage: %s [-d webdir] \n",argv0); +} static void check_room( int size, int len ) @@ -120,28 +124,44 @@ int main( int argc, char** argv ) { + extern char *optarg; char* webdir; char* prefix; struct passwd* pwd; char* username; char* homedir; + int opts; + char dirname[5000]; char linkname[5000]; char linkbuf[5000]; struct stat sb; - + argv0 = argv[0]; - if ( argc != 1 ) + +#ifndef TILDE_MAP_2 + webdir = WEBDIR; +#endif /* TILDE_MAP_2 */ + + if ( (opts = getopt(argc, argv, "d:h")) != EOF ) + { + switch (opts) { - (void) fprintf( stderr, "usage: %s\n", argv0 ); - exit( 1 ); - } + case 'd': webdir = strdup(optarg); break; + case 'h': usage(); return 1; break; + default: + usage(); + return 1; + break; + } + + } pwd = getpwuid( getuid() ); if ( pwd == (struct passwd*) 0 ) { (void) fprintf( stderr, "%s: can't find your username\n", argv0 ); - exit( 1 ); + exit ( 1 ); } username = pwd->pw_name; homedir = pwd->pw_dir; @@ -158,11 +178,9 @@ (void) strcat( dirname, TILDE_MAP_2 ); check_dir( dirname, pwd->pw_uid, pwd->pw_gid ); - + #else /* TILDE_MAP_2 */ - /* Gather the pieces. */ - webdir = WEBDIR; #ifdef TILDE_MAP_1 prefix = TILDE_MAP_1; #else /* TILDE_MAP_1 */ --- thttpd-2.23beta1.orig/thttpd.8 +++ thttpd-2.23beta1/thttpd.8 @@ -259,7 +259,7 @@ This file is formatted as the familiar colon-separated username/encrypted-password pair, records delimited by newlines. The protection does not carry over to subdirectories. -The utility program htpasswd(1) is included to help create and +The utility program thtpasswd(1) is included to help create and modify .htpasswd files. .PP Relevant config.h option: AUTH_FILE @@ -534,7 +534,7 @@ Currently the best alternative for log rotation is to send a USR1 signal, shutting down thttpd altogether, and then restart it. .SH "SEE ALSO" -redirect(8), ssi(8), makeweb(1), htpasswd(1), syslogtocern(8), weblog_parse(1), http_get(1) +thtpasswd(1), syslogtocern(8) .SH THANKS .PP Many thanks to contributors, reviewers, testers: