… | |
… | |
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" ); |
… | |
… | |
1471 | checked[0] = '\0'; |
1475 | checked[0] = '\0'; |
1472 | checkedlen = 0; |
1476 | checkedlen = 0; |
1473 | restlen = strlen( path ); |
1477 | restlen = strlen( path ); |
1474 | httpd_realloc_str( &rest, &maxrest, restlen ); |
1478 | httpd_realloc_str( &rest, &maxrest, restlen ); |
1475 | (void) strcpy( rest, path ); |
1479 | (void) strcpy( rest, path ); |
1476 | if ( rest[restlen - 1] == '/' ) |
|
|
1477 | rest[--restlen] = '\0'; /* trim trailing slash */ |
|
|
1478 | if ( ! tildemapped ) |
1480 | if ( ! tildemapped ) |
1479 | /* Remove any leading slashes. */ |
1481 | /* Remove any leading slashes. */ |
1480 | while ( rest[0] == '/' ) |
1482 | while ( rest[0] == '/' ) |
1481 | { |
1483 | { |
1482 | (void) strcpy( rest, &(rest[1]) ); |
1484 | (void) strcpy( rest, &(rest[1]) ); |
… | |
… | |
1738 | hc->init_byte_loc = 0; |
1740 | hc->init_byte_loc = 0; |
1739 | hc->end_byte_loc = -1; |
1741 | hc->end_byte_loc = -1; |
1740 | hc->keep_alive = 0; |
1742 | hc->keep_alive = 0; |
1741 | hc->should_linger = 0; |
1743 | hc->should_linger = 0; |
1742 | hc->file_address = (char*) 0; |
1744 | hc->file_address = (char*) 0; |
|
|
1745 | #ifdef MMAP_MAX |
|
|
1746 | hc->file_fd = -1; |
|
|
1747 | hc->write_buf = (char*) 0; |
|
|
1748 | #endif |
1743 | return GC_OK; |
1749 | return GC_OK; |
1744 | } |
1750 | } |
1745 | |
1751 | |
1746 | |
1752 | |
1747 | /* Checks hc->read_buf to see whether a complete request has been read so far; |
1753 | /* Checks hc->read_buf to see whether a complete request has been read so far; |
… | |
… | |
2388 | void |
2394 | void |
2389 | httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) |
2395 | httpd_close_conn( httpd_conn* hc, struct timeval* nowP ) |
2390 | { |
2396 | { |
2391 | make_log_entry( hc, nowP ); |
2397 | make_log_entry( hc, nowP ); |
2392 | |
2398 | |
|
|
2399 | #ifdef MMAP_MAX |
|
|
2400 | if ( hc->file_fd >= 0) |
|
|
2401 | { |
|
|
2402 | (void) close( hc->file_fd ); |
|
|
2403 | hc->file_fd = -1; |
|
|
2404 | } |
|
|
2405 | if ( hc->write_buf ) |
|
|
2406 | { |
|
|
2407 | (void) free (hc->write_buf); |
|
|
2408 | hc->write_buf = 0; |
|
|
2409 | } |
|
|
2410 | #endif |
2393 | if ( hc->file_address != (char*) 0 ) |
2411 | if ( hc->file_address != (char*) 0 ) |
2394 | { |
2412 | { |
2395 | mmc_unmap( hc->file_address, &(hc->sb), nowP ); |
2413 | mmc_unmap( hc->file_address, &(hc->sb), nowP ); |
2396 | hc->file_address = (char*) 0; |
2414 | hc->file_address = (char*) 0; |
2397 | } |
2415 | } |
… | |
… | |
2796 | exit( 0 ); |
2814 | exit( 0 ); |
2797 | } |
2815 | } |
2798 | |
2816 | |
2799 | /* Parent process. */ |
2817 | /* Parent process. */ |
2800 | closedir( dirp ); |
2818 | closedir( dirp ); |
2801 | syslog( LOG_INFO, "spawned indexing process %d for directory '%.200s'", r, hc->expnfilename ); |
2819 | /*syslog( LOG_INFO, "spawned indexing process %d for directory '%.200s'", r, hc->expnfilename );*/ |
2802 | #ifdef CGI_TIMELIMIT |
2820 | #ifdef CGI_TIMELIMIT |
2803 | /* Schedule a kill for the child process, in case it runs too long */ |
2821 | /* Schedule a kill for the child process, in case it runs too long */ |
2804 | client_data.i = r; |
2822 | client_data.i = r; |
2805 | if ( tmr_create( (struct timeval*) 0, cgi_kill, client_data, CGI_TIMELIMIT * 1000L, 0 ) == (Timer*) 0 ) |
2823 | if ( tmr_create( (struct timeval*) 0, cgi_kill, client_data, CGI_TIMELIMIT * 1000L, 0 ) == (Timer*) 0 ) |
2806 | { |
2824 | { |
… | |
… | |
3162 | } |
3180 | } |
3163 | |
3181 | |
3164 | |
3182 | |
3165 | /* CGI child process. */ |
3183 | /* CGI child process. */ |
3166 | static void |
3184 | static void |
3167 | cgi_child( httpd_conn* hc ) |
3185 | cgi_child( httpd_conn* hc, char* exefilename ) |
3168 | { |
3186 | { |
3169 | int r; |
3187 | int r; |
3170 | char** argp; |
3188 | char** argp; |
3171 | char** envp; |
3189 | char** envp; |
3172 | char* binary; |
3190 | char* binary; |
… | |
… | |
3314 | |
3332 | |
3315 | /* Split the program into directory and binary, so we can chdir() |
3333 | /* Split the program into directory and binary, so we can chdir() |
3316 | ** to the program's own directory. This isn't in the CGI 1.1 |
3334 | ** to the program's own directory. This isn't in the CGI 1.1 |
3317 | ** spec, but it's what other HTTP servers do. |
3335 | ** spec, but it's what other HTTP servers do. |
3318 | */ |
3336 | */ |
3319 | directory = strdup( hc->expnfilename ); |
3337 | if (exefilename) |
3320 | if ( directory == (char*) 0 ) |
3338 | binary = exefilename; |
3321 | binary = hc->expnfilename; /* ignore errors */ |
|
|
3322 | else |
3339 | else |
3323 | { |
3340 | { |
|
|
3341 | directory = strdup( exefilename ? exefilename : hc->expnfilename ); |
|
|
3342 | if ( directory == (char*) 0 ) |
|
|
3343 | binary = exefilename; /* ignore errors */ |
|
|
3344 | else |
|
|
3345 | { |
3324 | binary = strrchr( directory, '/' ); |
3346 | binary = strrchr( directory, '/' ); |
3325 | if ( binary == (char*) 0 ) |
3347 | if ( binary == (char*) 0 ) |
3326 | binary = hc->expnfilename; |
3348 | binary = exefilename; |
3327 | else |
3349 | else |
3328 | { |
3350 | { |
3329 | *binary++ = '\0'; |
3351 | *binary++ = '\0'; |
3330 | (void) chdir( directory ); /* ignore errors */ |
3352 | (void) chdir( directory ); /* ignore errors */ |
|
|
3353 | } |
|
|
3354 | } |
3331 | } |
3355 | } |
3332 | } |
|
|
3333 | |
3356 | |
3334 | /* Default behavior for SIGPIPE. */ |
3357 | /* Default behavior for SIGPIPE. */ |
3335 | (void) signal( SIGPIPE, SIG_DFL ); |
3358 | (void) signal( SIGPIPE, SIG_DFL ); |
3336 | |
3359 | |
3337 | /* Run the program. */ |
3360 | /* Run the program. */ |
… | |
… | |
3343 | exit( 1 ); |
3366 | exit( 1 ); |
3344 | } |
3367 | } |
3345 | |
3368 | |
3346 | |
3369 | |
3347 | static off_t |
3370 | static off_t |
3348 | cgi( httpd_conn* hc ) |
3371 | cgi( httpd_conn* hc, char* exefilename ) |
3349 | { |
3372 | { |
3350 | int r; |
3373 | int r; |
3351 | ClientData client_data; |
3374 | ClientData client_data; |
3352 | |
3375 | |
3353 | if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) |
3376 | if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) |
… | |
… | |
3361 | return -1; |
3384 | return -1; |
3362 | } |
3385 | } |
3363 | if ( r == 0 ) |
3386 | if ( r == 0 ) |
3364 | { |
3387 | { |
3365 | unlisten( hc->hs ); |
3388 | unlisten( hc->hs ); |
3366 | cgi_child( hc ); |
3389 | cgi_child( hc, exefilename ); |
3367 | } |
3390 | } |
3368 | |
3391 | |
3369 | /* Parent process. */ |
3392 | /* Parent process. */ |
3370 | syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename ); |
3393 | /*syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename );*/ |
3371 | #ifdef CGI_TIMELIMIT |
3394 | #ifdef CGI_TIMELIMIT |
3372 | /* Schedule a kill for the child process, in case it runs too long */ |
3395 | /* Schedule a kill for the child process, in case it runs too long */ |
3373 | client_data.i = r; |
3396 | client_data.i = r; |
3374 | if ( tmr_create( (struct timeval*) 0, cgi_kill, client_data, CGI_TIMELIMIT * 1000L, 0 ) == (Timer*) 0 ) |
3397 | if ( tmr_create( (struct timeval*) 0, cgi_kill, client_data, CGI_TIMELIMIT * 1000L, 0 ) == (Timer*) 0 ) |
3375 | { |
3398 | { |
… | |
… | |
3501 | #endif /* AUTH_FILE */ |
3524 | #endif /* AUTH_FILE */ |
3502 | /* Referer check. */ |
3525 | /* Referer check. */ |
3503 | if ( ! check_referer( hc ) ) |
3526 | if ( ! check_referer( hc ) ) |
3504 | return -1; |
3527 | return -1; |
3505 | /* Ok, generate an index. */ |
3528 | /* Ok, generate an index. */ |
3506 | return ls( hc ); |
3529 | return hc->hs->autoindex_prog ? cgi( hc, hc->hs->autoindex_prog) : ls( hc ); |
3507 | #else /* GENERATE_INDEXES */ |
3530 | #else /* GENERATE_INDEXES */ |
3508 | syslog( |
3531 | syslog( |
3509 | LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory", |
3532 | LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory", |
3510 | httpd_ntoa( &hc->client_addr ), hc->encodedurl ); |
3533 | httpd_ntoa( &hc->client_addr ), hc->encodedurl ); |
3511 | httpd_send_err( |
3534 | httpd_send_err( |
… | |
… | |
3594 | |
3617 | |
3595 | /* Is it world-executable and in the CGI area? */ |
3618 | /* Is it world-executable and in the CGI area? */ |
3596 | if ( hc->hs->cgi_pattern != (char*) 0 && |
3619 | if ( hc->hs->cgi_pattern != (char*) 0 && |
3597 | ( hc->sb.st_mode & S_IXOTH ) && |
3620 | ( hc->sb.st_mode & S_IXOTH ) && |
3598 | match( hc->hs->cgi_pattern, hc->expnfilename ) ) |
3621 | match( hc->hs->cgi_pattern, hc->expnfilename ) ) |
3599 | return cgi( hc ); |
3622 | return cgi( hc, 0 ); |
3600 | |
3623 | |
3601 | /* It's not CGI. If it's executable or there's pathinfo, someone's |
3624 | /* It's not CGI. If it's executable or there's pathinfo, someone's |
3602 | ** trying to either serve or run a non-CGI file as CGI. Either case |
3625 | ** trying to either serve or run a non-CGI file as CGI. Either case |
3603 | ** is prohibited. |
3626 | ** is prohibited. |
3604 | */ |
3627 | */ |
… | |
… | |
3646 | hc, 304, err304title, hc->encodings, "", hc->type, hc->sb.st_size, |
3669 | hc, 304, err304title, hc->encodings, "", hc->type, hc->sb.st_size, |
3647 | hc->sb.st_mtime ); |
3670 | hc->sb.st_mtime ); |
3648 | } |
3671 | } |
3649 | else |
3672 | else |
3650 | { |
3673 | { |
|
|
3674 | #ifdef MMAP_MAX |
|
|
3675 | if ( hc->sb.st_size < MMAP_MAX) |
|
|
3676 | #endif |
3651 | hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP ); |
3677 | hc->file_address = mmc_map( hc->expnfilename, &(hc->sb), nowP ); |
3652 | if ( hc->file_address == (char*) 0 ) |
3678 | if ( hc->file_address == (char*) 0 ) |
3653 | { |
3679 | { |
|
|
3680 | #ifdef MMAP_MAX |
|
|
3681 | hc->file_fd = open ( hc->expnfilename, O_RDONLY); |
|
|
3682 | hc->write_buf = malloc (WRITE_BUFFER); |
|
|
3683 | hc->write_ofs = WRITE_BUFFER; |
|
|
3684 | if ( hc->file_fd < 0 || !hc->write_buf ) |
|
|
3685 | #endif |
|
|
3686 | { |
3654 | httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); |
3687 | httpd_send_err( hc, 500, err500title, "", err500form, hc->encodedurl ); |
3655 | return -1; |
3688 | return -1; |
|
|
3689 | } |
3656 | } |
3690 | } |
3657 | send_mime( |
3691 | send_mime( |
3658 | hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, |
3692 | hc, 200, ok200title, hc->encodings, "", hc->type, hc->sb.st_size, |
3659 | hc->sb.st_mtime ); |
3693 | hc->sb.st_mtime ); |
3660 | } |
3694 | } |