… | |
… | |
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" ); |
… | |
… | |
838 | return; |
842 | return; |
839 | } |
843 | } |
840 | |
844 | |
841 | /* Try server-wide error page. */ |
845 | /* Try server-wide error page. */ |
842 | (void) my_snprintf( filename, sizeof(filename), |
846 | (void) my_snprintf( filename, sizeof(filename), |
843 | "%s/err403blocked.html", ERR_DIR ); |
847 | "%s/errerr403blocked.html", ERR_DIR ); |
844 | if ( send_err_file( hc, 403, err403title, "", filename ) ) |
848 | if ( send_err_file( hc, 403, err403title, "", filename ) ) |
845 | return; |
849 | return; |
846 | |
850 | |
847 | /* Fall back on built-in error page. */ |
851 | /* Fall back on built-in error page. */ |
848 | send_response( hc, 403, err403title, "", err403form, "" ); |
852 | send_response( hc, 403, err403title, "", err403form, "" ); |
… | |
… | |
1465 | checked[0] = '\0'; |
1469 | checked[0] = '\0'; |
1466 | checkedlen = 0; |
1470 | checkedlen = 0; |
1467 | restlen = strlen( path ); |
1471 | restlen = strlen( path ); |
1468 | httpd_realloc_str( &rest, &maxrest, restlen ); |
1472 | httpd_realloc_str( &rest, &maxrest, restlen ); |
1469 | (void) strcpy( rest, path ); |
1473 | (void) strcpy( rest, path ); |
1470 | if ( rest[restlen - 1] == '/' ) |
|
|
1471 | rest[--restlen] = '\0'; /* trim trailing slash */ |
|
|
1472 | if ( ! tildemapped ) |
1474 | if ( ! tildemapped ) |
1473 | /* Remove any leading slashes. */ |
1475 | /* Remove any leading slashes. */ |
1474 | while ( rest[0] == '/' ) |
1476 | while ( rest[0] == '/' ) |
1475 | { |
1477 | { |
1476 | (void) strcpy( rest, &(rest[1]) ); |
1478 | (void) strcpy( rest, &(rest[1]) ); |
… | |
… | |
1732 | hc->init_byte_loc = 0; |
1734 | hc->init_byte_loc = 0; |
1733 | hc->end_byte_loc = -1; |
1735 | hc->end_byte_loc = -1; |
1734 | hc->keep_alive = 0; |
1736 | hc->keep_alive = 0; |
1735 | hc->should_linger = 0; |
1737 | hc->should_linger = 0; |
1736 | hc->file_address = (char*) 0; |
1738 | hc->file_address = (char*) 0; |
|
|
1739 | #ifdef MMAP_MAX |
|
|
1740 | hc->file_fd = -1; |
|
|
1741 | hc->write_buf = (char*) 0; |
|
|
1742 | #endif |
1737 | return GC_OK; |
1743 | return GC_OK; |
1738 | } |
1744 | } |
1739 | |
1745 | |
1740 | |
1746 | |
1741 | /* Checks hc->read_buf to see whether a complete request has been read so far; |
1747 | /* Checks hc->read_buf to see whether a complete request has been read so far; |
… | |
… | |
2382 | void |
2388 | void |
2383 | httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) |
2389 | httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) |
2384 | { |
2390 | { |
2385 | make_log_entry( hc, nowP ); |
2391 | make_log_entry( hc, nowP ); |
2386 | |
2392 | |
|
|
2393 | #ifdef MMAP_MAX |
|
|
2394 | if ( hc->file_fd >= 0) |
|
|
2395 | { |
|
|
2396 | (void) close( hc->file_fd ); |
|
|
2397 | hc->file_fd = -1; |
|
|
2398 | } |
|
|
2399 | if ( hc->write_buf ) |
|
|
2400 | (void) free (hc->write_buf); |
|
|
2401 | #endif |
2387 | if ( hc->file_address != (char*) 0 ) |
2402 | if ( hc->file_address != (char*) 0 ) |
2388 | { |
2403 | { |
2389 | mmc_unmap( hc->file_address, &(hc->sb), nowP ); |
2404 | mmc_unmap( hc->file_address, &(hc->sb), nowP ); |
2390 | hc->file_address = (char*) 0; |
2405 | hc->file_address = (char*) 0; |
2391 | } |
2406 | } |
… | |
… | |
3156 | } |
3171 | } |
3157 | |
3172 | |
3158 | |
3173 | |
3159 | /* CGI child process. */ |
3174 | /* CGI child process. */ |
3160 | static void |
3175 | static void |
3161 | cgi_child( httpd_conn* hc ) |
3176 | cgi_child( httpd_conn* hc, char* exefilename ) |
3162 | { |
3177 | { |
3163 | int r; |
3178 | int r; |
3164 | char** argp; |
3179 | char** argp; |
3165 | char** envp; |
3180 | char** envp; |
3166 | char* binary; |
3181 | char* binary; |
… | |
… | |
3308 | |
3323 | |
3309 | /* Split the program into directory and binary, so we can chdir() |
3324 | /* Split the program into directory and binary, so we can chdir() |
3310 | ** to the program's own directory. This isn't in the CGI 1.1 |
3325 | ** to the program's own directory. This isn't in the CGI 1.1 |
3311 | ** spec, but it's what other HTTP servers do. |
3326 | ** spec, but it's what other HTTP servers do. |
3312 | */ |
3327 | */ |
3313 | directory = strdup( hc->expnfilename ); |
3328 | if (exefilename) |
3314 | if ( directory == (char*) 0 ) |
3329 | binary = exefilename; |
3315 | binary = hc->expnfilename; /* ignore errors */ |
|
|
3316 | else |
3330 | else |
3317 | { |
3331 | { |
|
|
3332 | directory = strdup( exefilename ? exefilename : hc->expnfilename ); |
|
|
3333 | if ( directory == (char*) 0 ) |
|
|
3334 | binary = exefilename; /* ignore errors */ |
|
|
3335 | else |
|
|
3336 | { |
3318 | binary = strrchr( directory, '/' ); |
3337 | binary = strrchr( directory, '/' ); |
3319 | if ( binary == (char*) 0 ) |
3338 | if ( binary == (char*) 0 ) |
3320 | binary = hc->expnfilename; |
3339 | binary = exefilename; |
3321 | else |
3340 | else |
3322 | { |
3341 | { |
3323 | *binary++ = '\0'; |
3342 | *binary++ = '\0'; |
3324 | (void) chdir( directory ); /* ignore errors */ |
3343 | (void) chdir( directory ); /* ignore errors */ |
|
|
3344 | } |
|
|
3345 | } |
3325 | } |
3346 | } |
3326 | } |
|
|
3327 | |
3347 | |
3328 | /* Default behavior for SIGPIPE. */ |
3348 | /* Default behavior for SIGPIPE. */ |
3329 | (void) signal( SIGPIPE, SIG_DFL ); |
3349 | (void) signal( SIGPIPE, SIG_DFL ); |
3330 | |
3350 | |
3331 | /* Run the program. */ |
3351 | /* Run the program. */ |
… | |
… | |
3337 | exit( 1 ); |
3357 | exit( 1 ); |
3338 | } |
3358 | } |
3339 | |
3359 | |
3340 | |
3360 | |
3341 | static off_t |
3361 | static off_t |
3342 | cgi( httpd_conn* hc ) |
3362 | cgi( httpd_conn* hc, char* exefilename ) |
3343 | { |
3363 | { |
3344 | int r; |
3364 | int r; |
3345 | ClientData client_data; |
3365 | ClientData client_data; |
3346 | |
3366 | |
3347 | if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) |
3367 | if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) |
… | |
… | |
3355 | return -1; |
3375 | return -1; |
3356 | } |
3376 | } |
3357 | if ( r == 0 ) |
3377 | if ( r == 0 ) |
3358 | { |
3378 | { |
3359 | unlisten( hc->hs ); |
3379 | unlisten( hc->hs ); |
3360 | cgi_child( hc ); |
3380 | cgi_child( hc, exefilename ); |
3361 | } |
3381 | } |
3362 | |
3382 | |
3363 | /* Parent process. */ |
3383 | /* Parent process. */ |
3364 | syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename ); |
3384 | syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename ); |
3365 | #ifdef CGI_TIMELIMIT |
3385 | #ifdef CGI_TIMELIMIT |
… | |
… | |
3495 | #endif /* AUTH_FILE */ |
3515 | #endif /* AUTH_FILE */ |
3496 | /* Referer check. */ |
3516 | /* Referer check. */ |
3497 | if ( ! check_referer( hc ) ) |
3517 | if ( ! check_referer( hc ) ) |
3498 | return -1; |
3518 | return -1; |
3499 | /* Ok, generate an index. */ |
3519 | /* Ok, generate an index. */ |
3500 | return ls( hc ); |
3520 | return hc->hs->autoindex_prog ? cgi( hc, hc->hs->autoindex_prog) : ls( hc ); |
3501 | #else /* GENERATE_INDEXES */ |
3521 | #else /* GENERATE_INDEXES */ |
3502 | syslog( |
3522 | syslog( |
3503 | LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory", |
3523 | LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory", |
3504 | httpd_ntoa( &hc->client_addr ), hc->encodedurl ); |
3524 | httpd_ntoa( &hc->client_addr ), hc->encodedurl ); |
3505 | httpd_send_err( |
3525 | httpd_send_err( |
… | |
… | |
3588 | |
3608 | |
3589 | /* Is it world-executable and in the CGI area? */ |
3609 | /* Is it world-executable and in the CGI area? */ |
3590 | if ( hc->hs->cgi_pattern != (char*) 0 && |
3610 | if ( hc->hs->cgi_pattern != (char*) 0 && |
3591 | ( hc->sb.st_mode & S_IXOTH ) && |
3611 | ( hc->sb.st_mode & S_IXOTH ) && |
3592 | match( hc->hs->cgi_pattern, hc->expnfilename ) ) |
3612 | match( hc->hs->cgi_pattern, hc->expnfilename ) ) |
3593 | return cgi( hc ); |
3613 | return cgi( hc, 0 ); |
3594 | |
3614 | |
3595 | /* It's not CGI. If it's executable or there's pathinfo, someone's |
3615 | /* It's not CGI. If it's executable or there's pathinfo, someone's |
3596 | ** trying to either serve or run a non-CGI file as CGI. Either case |
3616 | ** trying to either serve or run a non-CGI file as CGI. Either case |
3597 | ** is prohibited. |
3617 | ** is prohibited. |
3598 | */ |
3618 | */ |
… | |
… | |
3640 | hc, 304, err304title, hc->encodings, "", hc->type, hc->sb.st_size, |
3660 | hc, 304, err304title, hc->encodings, "", hc->type, hc->sb.st_size, |
3641 | hc->sb.st_mtime ); |
3661 | hc->sb.st_mtime ); |
3642 | } |
3662 | } |
3643 | else |
3663 | else |
3644 | { |
3664 | { |
|
|
3665 | #ifdef MMAP_MAX |
|
|
3666 | if ( hc->sb.st_size < MMAP_MAX) |
|
|
3667 | #endif |
3645 | hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP ); |
3668 | hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP ); |
3646 | if ( hc->file_address == (char*) 0 ) |
3669 | if ( hc->file_address == (char*) 0 ) |
3647 | { |
3670 | { |
|
|
3671 | #ifdef MMAP_MAX |
|
|
3672 | hc->file_fd = open ( hc->expnfilename, O_RDONLY); |
|
|
3673 | hc->write_buf = malloc (WRITE_BUFFER); |
|
|
3674 | hc->write_ofs = WRITE_BUFFER; |
|
|
3675 | if ( hc->file_fd < 0 || !hc->write_buf ) |
|
|
3676 | #endif |
|
|
3677 | { |
3648 | httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); |
3678 | httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); |
3649 | return -1; |
3679 | return -1; |
|
|
3680 | } |
3650 | } |
3681 | } |
3651 | send_mime( |
3682 | send_mime( |
3652 | hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, |
3683 | hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, |
3653 | hc->sb.st_mtime ); |
3684 | hc->sb.st_mtime ); |
3654 | } |
3685 | } |