--- thttpd-2.23beta1/libhttpd.c Wed Sep 10 17:27:45 2003 +++ thttpd-2.23beta1.freebsd/libhttpd.c Wed Sep 10 15:54:44 2003 @@ -1016,7 +1016,7 @@ static int auth_check( httpd_conn* hc, char* dirname ) { - if ( hc->hs->global_passwd ) + if ( hc->hs->global_passwd == 1) { char* topdir; if ( hc->hs->vhost && hc->hostdir[0] != '\0' ) @@ -1046,6 +1046,7 @@ char* authpass; char* colon; int l; + int found = 0; FILE* fp; char line[500]; char* cryp; @@ -1060,12 +1061,53 @@ /* Construct auth filename. */ httpd_realloc_str( &authpath, &maxauthpath, strlen( dirname ) + 1 + sizeof(AUTH_FILE) ); - (void) my_snprintf( authpath, maxauthpath, "%s/%s", dirname, AUTH_FILE ); + if ( hc->hs->global_passwd == 2 ) + { + char* topdir; + char* currdir = strdup(dirname); + char* slash; + if ( hc->hs->vhost && hc->hostdir[0] != '\0' ) + topdir = hc->hostdir; + else + topdir = "."; + /* loop until we hit topdir. Doesn't check topdir itself - for this + ** use the global password option which is functionally equivalent. + */ + while( strcmp( topdir, currdir )) + { + (void) my_snprintf( authpath, maxauthpath, "%s/%s", + currdir, AUTH_FILE ); + + /* Does this directory have an auth file? */ + if ( stat( authpath, &sb ) == 0 ) + { + found = 1; + break; + } + /* Nope, try up a level. */ + slash = strrchr( currdir, '/' ); + if ( !slash ) + break; + *slash = 0; + } + if ( !found ) + { + free( currdir ); + return 0; + } + /* use this directory for the authentication */ + dirname = currdir; + } + else + { + (void) my_snprintf( authpath, maxauthpath, "%s/%s", + dirname, AUTH_FILE ); /* Does this directory have an auth file? */ if ( stat( authpath, &sb ) < 0 ) /* Nope, let the request go through. */ return 0; + } /* Does this request contain basic authorization info? */ if ( hc->authorization[0] == '\0' || @@ -1073,6 +1115,7 @@ { /* Nope, return a 401 Unauthorized. */ send_authenticate( hc, dirname ); + if ( found ) free( dirname ); return -1; } @@ -1087,6 +1130,7 @@ { /* No colon? Bogus auth info. */ send_authenticate( hc, dirname ); + if ( found ) free( dirname ); return -1; } *authpass++ = '\0'; @@ -1108,12 +1152,14 @@ httpd_realloc_str( &hc->remoteuser, &hc->maxremoteuser, strlen( authinfo ) ); (void) strcpy( hc->remoteuser, authinfo ); + if ( found ) free( dirname ); return 1; } else { /* No. */ send_authenticate( hc, dirname ); + if ( found ) free( dirname ); return -1; } } @@ -1130,6 +1176,7 @@ hc, 403, err403title, "", ERROR_FORM( err403form, "The requested URL '%.80s' is protected by an authentication file, but the authentication file cannot be opened.\n" ), hc->encodedurl ); + if ( found ) free( dirname ); return -1; } @@ -1167,12 +1214,14 @@ (void) strcpy( prevuser, authinfo ); httpd_realloc_str( &prevcryp, &maxprevcryp, strlen( cryp ) ); (void) strcpy( prevcryp, cryp ); + if ( found ) free( dirname ); return 1; } else { /* No. */ send_authenticate( hc, dirname ); + if ( found ) free( dirname ); return -1; } } @@ -1181,6 +1230,7 @@ /* Didn't find that user. Access denied. */ (void) fclose( fp ); send_authenticate( hc, dirname ); + if ( found ) free( dirname ); return -1; } --- thttpd-2.23beta1/thttpd.c Wed Sep 10 17:27:27 2003 +++ thttpd-2.23beta1.freebsd/thttpd.c Wed Sep 10 15:31:09 2003 @@ -756,6 +756,8 @@ do_global_passwd = 1; else if ( strcmp( argv[argn], "-nog" ) == 0 ) do_global_passwd = 0; + else if ( strcmp( argv[argn], "-R" ) == 0 ) + do_global_passwd = 2; else if ( strcmp( argv[argn], "-i" ) == 0 && argn + 1 < argc ) { ++argn; @@ -942,6 +944,11 @@ { no_value_required( name, value ); do_global_passwd = 0; + } + else if ( strcasecmp( name, "recurspasswd" ) == 0 ) + { + no_value_required( name, value ); + do_global_passwd = 2; } else if ( strcasecmp( name, "pidfile" ) == 0 ) { --- thttpd-2.23beta1/thttpd.8 Wed Apr 3 15:13:52 2002 +++ thttpd-2.23beta1.freebsd/thttpd.8 Wed Sep 10 17:46:31 2003 @@ -102,6 +102,14 @@ "noglobalpasswd", and the config.h option is ALWAYS_GLOBAL_PASSWD. .TP +.B -R +Use a recursive passwd file (the default behaviour for other webservers). +This means that a .htpasswd file will protect all the subdirectories and +files relative to the current directory. This may not be specified with +the [no]globalpasswd config or command-line options. The config-file +option for this flag is "recurspasswd". Default behaviour depends on the +global passwd file options described above. +.TP .B -u Specifies what user to switch to after initialization when started as root. The default is "nobody". @@ -258,7 +266,8 @@ called .htpasswd by default. 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 protection does not carry over to subdirectories unless the -R or +"recurspasswd" options are specified (see above). The utility program htpasswd(1) is included to help create and modify .htpasswd files. .PP