… | |
… | |
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" ); |
… | |
… | |
820 | send_response( hc, status, title, extraheads, form, arg ); |
824 | send_response( hc, status, title, extraheads, form, arg ); |
821 | |
825 | |
822 | #endif /* ERR_DIR */ |
826 | #endif /* ERR_DIR */ |
823 | } |
827 | } |
824 | |
828 | |
|
|
829 | void |
|
|
830 | httpd_send_err_blocked( httpd_conn* hc ) |
|
|
831 | { |
|
|
832 | #ifdef ERR_DIR |
|
|
833 | |
|
|
834 | char filename[1000]; |
|
|
835 | |
|
|
836 | /* Try virtual host error page. */ |
|
|
837 | if ( hc->hs->vhost && hc->hostdir[0] != '\0' ) |
|
|
838 | { |
|
|
839 | (void) my_snprintf( filename, sizeof(filename), |
|
|
840 | "%s/%s/err403blocked.html", hc->hostdir, ERR_DIR ); |
|
|
841 | if ( send_err_file( hc, 403, err403title, "", filename ) ) |
|
|
842 | return; |
|
|
843 | } |
|
|
844 | |
|
|
845 | /* Try server-wide error page. */ |
|
|
846 | (void) my_snprintf( filename, sizeof(filename), |
|
|
847 | "%s/err403blocked.html", ERR_DIR ); |
|
|
848 | if ( send_err_file( hc, 403, err403title, "", filename ) ) |
|
|
849 | return; |
|
|
850 | |
|
|
851 | /* Fall back on built-in error page. */ |
|
|
852 | send_response( hc, 403, err403title, "", err403form, "" ); |
|
|
853 | |
|
|
854 | #else /* ERR_DIR */ |
|
|
855 | |
|
|
856 | send_response( hc, 403, err403title, "", err403form, "" ); |
|
|
857 | |
|
|
858 | #endif /* ERR_DIR */ |
|
|
859 | } |
825 | |
860 | |
826 | #ifdef ERR_DIR |
861 | #ifdef ERR_DIR |
827 | static int |
862 | static int |
828 | send_err_file( httpd_conn* hc, int status, char* title, char* extraheads, char* filename ) |
863 | send_err_file( httpd_conn* hc, int status, char* title, char* extraheads, char* filename ) |
829 | { |
864 | { |
… | |
… | |
1434 | checked[0] = '\0'; |
1469 | checked[0] = '\0'; |
1435 | checkedlen = 0; |
1470 | checkedlen = 0; |
1436 | restlen = strlen( path ); |
1471 | restlen = strlen( path ); |
1437 | httpd_realloc_str( &rest, &maxrest, restlen ); |
1472 | httpd_realloc_str( &rest, &maxrest, restlen ); |
1438 | (void) strcpy( rest, path ); |
1473 | (void) strcpy( rest, path ); |
1439 | if ( rest[restlen - 1] == '/' ) |
|
|
1440 | rest[--restlen] = '\0'; /* trim trailing slash */ |
|
|
1441 | if ( ! tildemapped ) |
1474 | if ( ! tildemapped ) |
1442 | /* Remove any leading slashes. */ |
1475 | /* Remove any leading slashes. */ |
1443 | while ( rest[0] == '/' ) |
1476 | while ( rest[0] == '/' ) |
1444 | { |
1477 | { |
1445 | (void) strcpy( rest, &(rest[1]) ); |
1478 | (void) strcpy( rest, &(rest[1]) ); |
… | |
… | |
3141 | } |
3174 | } |
3142 | |
3175 | |
3143 | |
3176 | |
3144 | /* CGI child process. */ |
3177 | /* CGI child process. */ |
3145 | static void |
3178 | static void |
3146 | cgi_child( httpd_conn* hc ) |
3179 | cgi_child( httpd_conn* hc, char* exefilename ) |
3147 | { |
3180 | { |
3148 | int r; |
3181 | int r; |
3149 | char** argp; |
3182 | char** argp; |
3150 | char** envp; |
3183 | char** envp; |
3151 | char* binary; |
3184 | char* binary; |
… | |
… | |
3293 | |
3326 | |
3294 | /* Split the program into directory and binary, so we can chdir() |
3327 | /* Split the program into directory and binary, so we can chdir() |
3295 | ** to the program's own directory. This isn't in the CGI 1.1 |
3328 | ** to the program's own directory. This isn't in the CGI 1.1 |
3296 | ** spec, but it's what other HTTP servers do. |
3329 | ** spec, but it's what other HTTP servers do. |
3297 | */ |
3330 | */ |
3298 | directory = strdup( hc->expnfilename ); |
3331 | if (exefilename) |
3299 | if ( directory == (char*) 0 ) |
3332 | binary = exefilename; |
3300 | binary = hc->expnfilename; /* ignore errors */ |
|
|
3301 | else |
3333 | else |
3302 | { |
3334 | { |
|
|
3335 | directory = strdup( exefilename ? exefilename : hc->expnfilename ); |
|
|
3336 | if ( directory == (char*) 0 ) |
|
|
3337 | binary = exefilename; /* ignore errors */ |
|
|
3338 | else |
|
|
3339 | { |
3303 | binary = strrchr( directory, '/' ); |
3340 | binary = strrchr( directory, '/' ); |
3304 | if ( binary == (char*) 0 ) |
3341 | if ( binary == (char*) 0 ) |
3305 | binary = hc->expnfilename; |
3342 | binary = exefilename; |
3306 | else |
3343 | else |
3307 | { |
3344 | { |
3308 | *binary++ = '\0'; |
3345 | *binary++ = '\0'; |
3309 | (void) chdir( directory ); /* ignore errors */ |
3346 | (void) chdir( directory ); /* ignore errors */ |
|
|
3347 | } |
|
|
3348 | } |
3310 | } |
3349 | } |
3311 | } |
|
|
3312 | |
3350 | |
3313 | /* Default behavior for SIGPIPE. */ |
3351 | /* Default behavior for SIGPIPE. */ |
3314 | (void) signal( SIGPIPE, SIG_DFL ); |
3352 | (void) signal( SIGPIPE, SIG_DFL ); |
3315 | |
3353 | |
3316 | /* Run the program. */ |
3354 | /* Run the program. */ |
… | |
… | |
3322 | exit( 1 ); |
3360 | exit( 1 ); |
3323 | } |
3361 | } |
3324 | |
3362 | |
3325 | |
3363 | |
3326 | static off_t |
3364 | static off_t |
3327 | cgi( httpd_conn* hc ) |
3365 | cgi( httpd_conn* hc, char* exefilename ) |
3328 | { |
3366 | { |
3329 | int r; |
3367 | int r; |
3330 | ClientData client_data; |
3368 | ClientData client_data; |
3331 | |
3369 | |
3332 | if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) |
3370 | if ( hc->method == METHOD_GET || hc->method == METHOD_POST ) |
… | |
… | |
3340 | return -1; |
3378 | return -1; |
3341 | } |
3379 | } |
3342 | if ( r == 0 ) |
3380 | if ( r == 0 ) |
3343 | { |
3381 | { |
3344 | unlisten( hc->hs ); |
3382 | unlisten( hc->hs ); |
3345 | cgi_child( hc ); |
3383 | cgi_child( hc, exefilename ); |
3346 | } |
3384 | } |
3347 | |
3385 | |
3348 | /* Parent process. */ |
3386 | /* Parent process. */ |
3349 | syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename ); |
3387 | syslog( LOG_INFO, "spawned CGI process %d for file '%.200s'", r, hc->expnfilename ); |
3350 | #ifdef CGI_TIMELIMIT |
3388 | #ifdef CGI_TIMELIMIT |
… | |
… | |
3480 | #endif /* AUTH_FILE */ |
3518 | #endif /* AUTH_FILE */ |
3481 | /* Referer check. */ |
3519 | /* Referer check. */ |
3482 | if ( ! check_referer( hc ) ) |
3520 | if ( ! check_referer( hc ) ) |
3483 | return -1; |
3521 | return -1; |
3484 | /* Ok, generate an index. */ |
3522 | /* Ok, generate an index. */ |
3485 | return ls( hc ); |
3523 | return hc->hs->autoindex_prog ? cgi( hc, hc->hs->autoindex_prog) : ls( hc ); |
3486 | #else /* GENERATE_INDEXES */ |
3524 | #else /* GENERATE_INDEXES */ |
3487 | syslog( |
3525 | syslog( |
3488 | LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory", |
3526 | LOG_INFO, "%.80s URL \"%.80s\" tried to index a directory", |
3489 | httpd_ntoa( &hc->client_addr ), hc->encodedurl ); |
3527 | httpd_ntoa( &hc->client_addr ), hc->encodedurl ); |
3490 | httpd_send_err( |
3528 | httpd_send_err( |
… | |
… | |
3573 | |
3611 | |
3574 | /* Is it world-executable and in the CGI area? */ |
3612 | /* Is it world-executable and in the CGI area? */ |
3575 | if ( hc->hs->cgi_pattern != (char*) 0 && |
3613 | if ( hc->hs->cgi_pattern != (char*) 0 && |
3576 | ( hc->sb.st_mode & S_IXOTH ) && |
3614 | ( hc->sb.st_mode & S_IXOTH ) && |
3577 | match( hc->hs->cgi_pattern, hc->expnfilename ) ) |
3615 | match( hc->hs->cgi_pattern, hc->expnfilename ) ) |
3578 | return cgi( hc ); |
3616 | return cgi( hc, 0 ); |
3579 | |
3617 | |
3580 | /* It's not CGI. If it's executable or there's pathinfo, someone's |
3618 | /* It's not CGI. If it's executable or there's pathinfo, someone's |
3581 | ** trying to either serve or run a non-CGI file as CGI. Either case |
3619 | ** trying to either serve or run a non-CGI file as CGI. Either case |
3582 | ** is prohibited. |
3620 | ** is prohibited. |
3583 | */ |
3621 | */ |
… | |
… | |
3673 | char url[305]; |
3711 | char url[305]; |
3674 | char bytes[40]; |
3712 | char bytes[40]; |
3675 | |
3713 | |
3676 | if ( hc->hs->no_log ) |
3714 | if ( hc->hs->no_log ) |
3677 | return; |
3715 | return; |
|
|
3716 | |
|
|
3717 | /* don't log UNKNOWN protocol requests (blocks etc..) */ |
|
|
3718 | if ( !strcmp (hc->protocol, "UNKNOWN") ) |
|
|
3719 | return; |
3678 | |
3720 | |
3679 | /* This is straight CERN Combined Log Format - the only tweak |
3721 | /* This is straight CERN Combined Log Format - the only tweak |
3680 | ** being that if we're using syslog() we leave out the date, because |
3722 | ** being that if we're using syslog() we leave out the date, because |
3681 | ** syslogd puts it in. The included syslogtocern script turns the |
3723 | ** syslogd puts it in. The included syslogtocern script turns the |
3682 | ** results into true CERN format. |
3724 | ** results into true CERN format. |