… | |
… | |
155 | static char** make_envp( httpd_conn* hc ); |
155 | static char** make_envp( httpd_conn* hc ); |
156 | static char** make_argp( httpd_conn* hc ); |
156 | static char** make_argp( httpd_conn* hc ); |
157 | static void cgi_interpose_input( httpd_conn* hc, int wfd ); |
157 | static void cgi_interpose_input( httpd_conn* hc, int wfd ); |
158 | static void post_post_garbage_hack( httpd_conn* hc ); |
158 | static void post_post_garbage_hack( httpd_conn* hc ); |
159 | static void cgi_interpose_output( httpd_conn* hc, int rfd ); |
159 | static void cgi_interpose_output( httpd_conn* hc, int rfd ); |
160 | static void cgi_child( httpd_conn* hc ); |
160 | static void cgi_child( httpd_conn* hc, char* exefilename ); |
161 | static off_t cgi( httpd_conn* hc ); |
161 | static off_t cgi( httpd_conn* hc, char* exefilename ); |
162 | static int really_start_request( httpd_conn* hc, struct timeval* nowP ); |
162 | static int really_start_request( httpd_conn* hc, struct timeval* nowP ); |
163 | static void make_log_entry( httpd_conn* hc, struct timeval* nowP ); |
163 | static void make_log_entry( httpd_conn* hc, struct timeval* nowP ); |
164 | static int check_referer( httpd_conn* hc ); |
164 | static int check_referer( httpd_conn* hc ); |
165 | static int really_check_referer( httpd_conn* hc ); |
165 | static int really_check_referer( httpd_conn* hc ); |
166 | static int sockaddr_check( httpd_sockaddr* saP ); |
166 | static int sockaddr_check( httpd_sockaddr* saP ); |
… | |
… | |
238 | { |
238 | { |
239 | if ( hs->binding_hostname != (char*) 0 ) |
239 | if ( hs->binding_hostname != (char*) 0 ) |
240 | free( (void*) hs->binding_hostname ); |
240 | free( (void*) hs->binding_hostname ); |
241 | if ( hs->cwd != (char*) 0 ) |
241 | if ( hs->cwd != (char*) 0 ) |
242 | free( (void*) hs->cwd ); |
242 | free( (void*) hs->cwd ); |
|
|
243 | if ( hs->autoindex_prog != (char*) 0 ) |
|
|
244 | free( (void*) hs->autoindex_prog ); |
243 | if ( hs->cgi_pattern != (char*) 0 ) |
245 | if ( hs->cgi_pattern != (char*) 0 ) |
244 | free( (void*) hs->cgi_pattern ); |
246 | free( (void*) hs->cgi_pattern ); |
245 | if ( hs->charset != (char*) 0 ) |
247 | if ( hs->charset != (char*) 0 ) |
246 | free( (void*) hs->charset ); |
248 | free( (void*) hs->charset ); |
247 | if ( hs->url_pattern != (char*) 0 ) |
249 | if ( hs->url_pattern != (char*) 0 ) |
… | |
… | |
255 | httpd_server* |
257 | httpd_server* |
256 | httpd_initialize( |
258 | httpd_initialize( |
257 | char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port, |
259 | char* hostname, httpd_sockaddr* sa4P, httpd_sockaddr* sa6P, int port, |
258 | char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp, |
260 | char* cgi_pattern, char* charset, char* cwd, int no_log, FILE* logfp, |
259 | int no_symlink, int vhost, int global_passwd, char* url_pattern, |
261 | int no_symlink, int vhost, int global_passwd, char* url_pattern, |
260 | char* local_pattern, int no_empty_referers ) |
262 | char* local_pattern, int no_empty_referers, |
|
|
263 | char* autoindex_prog) |
261 | { |
264 | { |
262 | httpd_server* hs; |
265 | httpd_server* hs; |
263 | static char ghnbuf[256]; |
266 | static char ghnbuf[256]; |
264 | char* cp; |
267 | char* cp; |
265 | |
268 | |
… | |
… | |
327 | } |
330 | } |
328 | /* Nuke any leading slashes in the cgi pattern. */ |
331 | /* Nuke any leading slashes in the cgi pattern. */ |
329 | while ( ( cp = strstr( hs->cgi_pattern, "|/" ) ) != (char*) 0 ) |
332 | while ( ( cp = strstr( hs->cgi_pattern, "|/" ) ) != (char*) 0 ) |
330 | (void) strcpy( cp + 1, cp + 2 ); |
333 | (void) strcpy( cp + 1, cp + 2 ); |
331 | } |
334 | } |
|
|
335 | hs->autoindex_prog = autoindex_prog ? strdup( autoindex_prog ) : 0; |
332 | hs->charset = strdup( charset ); |
336 | hs->charset = strdup( charset ); |
333 | hs->cwd = strdup( cwd ); |
337 | hs->cwd = strdup( cwd ); |
334 | if ( hs->cwd == (char*) 0 ) |
338 | if ( hs->cwd == (char*) 0 ) |
335 | { |
339 | { |
336 | syslog( LOG_CRIT, "out of memory copying cwd" ); |
340 | syslog( LOG_CRIT, "out of memory copying cwd" ); |
… | |
… | |
1434 | checked[0] = '\0'; |
1438 | checked[0] = '\0'; |
1435 | checkedlen = 0; |
1439 | checkedlen = 0; |
1436 | restlen = strlen( path ); |
1440 | restlen = strlen( path ); |
1437 | httpd_realloc_str( &rest, &maxrest, restlen ); |
1441 | httpd_realloc_str( &rest, &maxrest, restlen ); |
1438 | (void) strcpy( rest, path ); |
1442 | (void) strcpy( rest, path ); |
1439 | if ( rest[restlen - 1] == '/' ) |
|
|
1440 | rest[--restlen] = '\0'; /* trim trailing slash */ |
|
|
1441 | if ( ! tildemapped ) |
1443 | if ( ! tildemapped ) |
1442 | /* Remove any leading slashes. */ |
1444 | /* Remove any leading slashes. */ |
1443 | while ( rest[0] == '/' ) |
1445 | while ( rest[0] == '/' ) |
1444 | { |
1446 | { |
1445 | (void) strcpy( rest, &(rest[1]) ); |
1447 | (void) strcpy( rest, &(rest[1]) ); |
… | |
… | |
3125 | } |
3127 | } |
3126 | |
3128 | |
3127 | |
3129 | |
3128 | /* CGI child process. */ |
3130 | /* CGI child process. */ |
3129 | static void |
3131 | static void |
3130 | cgi_child( httpd_conn* hc ) |
3132 | cgi_child( httpd_conn* hc, char* exefilename ) |
3131 | { |
3133 | { |
3132 | int r; |
3134 | int r; |
3133 | char** argp; |
3135 | char** argp; |
3134 | char** envp; |
3136 | char** envp; |
3135 | char* binary; |
3137 | char* binary; |
… | |
… | |
3277 | |
3279 | |
3278 | /* Split the program into directory and binary, so we can chdir() |
3280 | /* Split the program into directory and binary, so we can chdir() |
3279 | ** to the program's own directory. This isn't in the CGI 1.1 |
3281 | ** to the program's own directory. This isn't in the CGI 1.1 |
3280 | ** spec, but it's what other HTTP servers do. |
3282 | ** spec, but it's what other HTTP servers do. |
3281 | */ |
3283 | */ |
3282 | directory = strdup( hc->expnfilename ); |
3284 | if (exefilename) |
3283 | if ( directory == (char*) 0 ) |
3285 | binary = exefilename; |
3284 | binary = hc->expnfilename; /* ignore errors */ |
|
|
3285 | else |
3286 | else |
3286 | { |
3287 | { |
|
|
3288 | directory = strdup( exefilename ? exefilename : hc->expnfilename ); |
|
|
3289 | if ( directory == (char*) 0 ) |
|
|
3290 | binary = exefilename; /* ignore errors */ |
|
|
3291 | else |
|
|
3292 | { |
3287 | binary = strrchr( directory, '/' ); |
3293 | binary = strrchr( directory, '/' ); |
3288 | if ( binary == (char*) 0 ) |
3294 | if ( binary == (char*) 0 ) |
3289 | binary = hc->expnfilename; |
3295 | binary = exefilename; |
3290 | else |
3296 | else |
3291 | { |
3297 | { |
3292 | *binary++ = '\0'; |
3298 | *binary++ = '\0'; |
3293 | (void) chdir( directory ); /* ignore errors */ |
3299 | (void) chdir( directory ); /* ignore errors */ |
|
|
3300 | } |
|
|
3301 | } |
3294 | } |
3302 | } |
3295 | } |
|
|
3296 | |
3303 | |
3297 | /* Default behavior for SIGPIPE. */ |
3304 | /* Default behavior for SIGPIPE. */ |
3298 | (void) signal( SIGPIPE, SIG_DFL ); |
3305 | (void) signal( SIGPIPE, SIG_DFL ); |
3299 | |
3306 | |
3300 | /* Run the program. */ |
3307 | /* Run the program. */ |
… | |
… | |
3306 | exit( 1 ); |
3313 | exit( 1 ); |
3307 | } |
3314 | } |
3308 | |
3315 | |
3309 | |
3316 | |
3310 | static off_t |
3317 | static off_t |
3311 | cgi( httpd_conn* hc ) |
3318 | cgi( httpd_conn* hc, char* exefilename ) |
3312 | { |
3319 | { |
3313 | int r; |
3320 | int r; |
3314 | ClientData client_data; |
3321 | ClientData client_data; |
3315 | |
3322 | |
3316 | if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) |
3323 | if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) |
… | |
… | |
3324 | return -1; |
3331 | return -1; |
3325 | } |
3332 | } |
3326 | if ( r == 0 ) |
3333 | if ( r == 0 ) |
3327 | { |
3334 | { |
3328 | unlisten( hc->hs ); |
3335 | unlisten( hc->hs ); |
3329 | cgi_child( hc ); |
3336 | cgi_child( hc, exefilename ); |
3330 | } |
3337 | } |
3331 | |
3338 | |
3332 | /* Parent process. */ |
3339 | /* Parent process. */ |
3333 | syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename ); |
3340 | syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename ); |
3334 | #ifdef CGI_TIMELIMIT |
3341 | #ifdef CGI_TIMELIMIT |
… | |
… | |
3464 | #endif /* AUTH_FILE */ |
3471 | #endif /* AUTH_FILE */ |
3465 | /* Referer check. */ |
3472 | /* Referer check. */ |
3466 | if ( ! check_referer( hc ) ) |
3473 | if ( ! check_referer( hc ) ) |
3467 | return -1; |
3474 | return -1; |
3468 | /* Ok, generate an index. */ |
3475 | /* Ok, generate an index. */ |
3469 | return ls( hc ); |
3476 | return hc->hs->autoindex_prog ? cgi( hc, hc->hs->autoindex_prog) : ls( hc ); |
3470 | #else /* GENERATE_INDEXES */ |
3477 | #else /* GENERATE_INDEXES */ |
3471 | syslog( |
3478 | syslog( |
3472 | LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory", |
3479 | LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory", |
3473 | httpd_ntoa( &hc->client_addr ), hc->encodedurl ); |
3480 | httpd_ntoa( &hc->client_addr ), hc->encodedurl ); |
3474 | httpd_send_err( |
3481 | httpd_send_err( |
… | |
… | |
3557 | |
3564 | |
3558 | /* Is it world-executable and in the CGI area? */ |
3565 | /* Is it world-executable and in the CGI area? */ |
3559 | if ( hc->hs->cgi_pattern != (char*) 0 && |
3566 | if ( hc->hs->cgi_pattern != (char*) 0 && |
3560 | ( hc->sb.st_mode & S_IXOTH ) && |
3567 | ( hc->sb.st_mode & S_IXOTH ) && |
3561 | match( hc->hs->cgi_pattern, hc->expnfilename ) ) |
3568 | match( hc->hs->cgi_pattern, hc->expnfilename ) ) |
3562 | return cgi( hc ); |
3569 | return cgi( hc, 0 ); |
3563 | |
3570 | |
3564 | /* It's not CGI. If it's executable or there's pathinfo, someone's |
3571 | /* It's not CGI. If it's executable or there's pathinfo, someone's |
3565 | ** trying to either serve or run a non-CGI file as CGI. Either case |
3572 | ** trying to either serve or run a non-CGI file as CGI. Either case |
3566 | ** is prohibited. |
3573 | ** is prohibited. |
3567 | */ |
3574 | */ |