home *** CD-ROM | disk | FTP | other *** search
- /*
- * http_get.c: Handles things associated with GET
- *
- * All code contained herein is covered by the Copyright as distributed
- * in the README file in the main directory of the distribution of
- * NCSA HTTPD.
- *
- * Based on NCSA HTTPd 1.3 by Rob McCool
- *
- * 04-08-95 blong
- * Fixed security hole which allowed a trailing slash on CGI_MAGIC_TYPE
- * cgi anywhere scripts to send back the script contents. Now the
- * trailing slash is added to the PATH_INFO, and the script is run.
- * Oh yeah, and don't forget about directories.
- */
-
- #include "httpd.h"
-
-
- int header_only;
- int num_includes;
- int allow;
- char allow_options;
-
-
- void send_file(char *file, FILE *fd, struct stat *fi,
- char *path_args, char *args)
- {
- FILE *f;
-
- set_content_type(file);
-
- if((allow_options & OPT_INCLUDES) && (!content_encoding[0])) {
- #ifdef XBITHACK
- if((fi->st_mode & S_IXUSR) ||
- (!strcmp(content_type,INCLUDES_MAGIC_TYPE))) {
- #else
- if(!strcmp(content_type,INCLUDES_MAGIC_TYPE)) {
- #endif
- bytes_sent = 0;
- send_parsed_file(file,fd,path_args,args,
- allow_options & OPT_INCNOEXEC);
- log_transaction();
- return;
- }
- }
- if(!(f=fopen(file,"r"))) {
- log_reason("file permissions deny server access",file);
- unmunge_name(file);
- die(FORBIDDEN,file,fd); /* we've already established that it exists */
- }
- bytes_sent = 0;
- if(!assbackwards) {
- set_content_length(fi->st_size);
- if (set_last_modified(fi->st_mtime,fd)) {
- fclose(f);
- return;
- }
- send_http_header(fd);
- }
- num_includes=0;
- if(!header_only)
- send_fd(f,fd,NULL);
- log_transaction();
- fclose(f);
- }
-
- /* Almost exactly equalivalent to exec_cgi_script, but this one
- gets all of the path info passed to it, instead of calling get_path_info */
-
- void send_cgi(char *method, char *file, char *path_args, char *args,
- struct stat *finfo, int in, FILE *fd)
- {
- int m = M_GET;
- int stub_returns;
-
- if((!strcmp(method,"GET")) || (!strcmp(method,"HEAD")))
- m = M_GET;
- else if(!strcmp(method,"POST"))
- m = M_POST;
- else if(!strcmp(method,"PUT"))
- m = M_PUT;
- else if(!strcmp(method,"DELETE"))
- m = M_DELETE;
-
- evaluate_access(file,finfo,m,&allow,&allow_options,fd);
- if((!allow) || (!(allow_options & OPT_EXECCGI))) {
- log_reason("client denied by server configuration",file);
- unmunge_name(file);
- die(FORBIDDEN,file,fd);
- }
- if(!(in_headers_env = add_common_vars(in_headers_env,fd)))
- die(NO_MEMORY,"send_cgi",fd);
-
- bytes_sent = 0;
- stub_returns = cgi_stub(method,file,path_args,args,in_headers_env,finfo,in,fd);
- free_env(in_headers_env);
- in_headers_env = NULL;
-
- switch (stub_returns) {
- case REDIRECT_URL:
- die(REDIRECT,location,fd);
- break;
- case REDIRECT_LOCAL:
- break;
- default:
- log_transaction();
- break;
- }
- }
-
-
- void send_node(char *file, char *args, int in, FILE *fd)
- {
- struct stat finfo;
- char pa[MAX_STRING_LEN];
- int length = 0;
- register x = 0;
-
- /* Remove all of the trailing slashes from the filename in order
- to fix security hole. All trailing slashes are placed in the
- path alias (pa) array */
-
- length = strlen(file);
- while (length && (file[length-1] == '/') && (x < MAX_STRING_LEN)) {
- pa[x] = '/';
- x++;
- file[length-1] = '\0';
- length--;
- }
- pa[x] = '\0';
- if(stat(file,&finfo) == -1) {
- /* Look for script or include document */
- int n=count_dirs(file),i,l;
- char t[MAX_STRING_LEN];
-
- for(i=n;i;--i) {
- make_dirstr(file,i,t);
- probe_content_type(t);
- if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
- if(stat(t,&finfo) == -1)
- continue;
- if(!(S_ISREG(finfo.st_mode)))
- break;
- l=strlen(t);
- strncat(pa,&file[l],MAX_STRING_LEN - strlen(pa));
- file[l] = '\0';
- send_cgi("GET",file,pa,args,&finfo,in,fd);
- return;
- } else if(!strcmp(content_type,INCLUDES_MAGIC_TYPE)) {
- if(stat(t,&finfo) == -1)
- continue;
- l=strlen(t);
- strncat(pa,&file[l],MAX_STRING_LEN - strlen(pa));
- file[l] = '\0';
- goto send_regular;
- }
- }
- if(errno==ENOENT) {
- log_reason("file does not exist",file);
- unmunge_name(file);
- die(NOT_FOUND,file,fd);
- }
- else {
- log_reason("file permissions deny server access",file);
- unmunge_name(file);
- die(FORBIDDEN,file,fd);
- }
- }
- probe_content_type(file);
- if(S_ISREG(finfo.st_mode) && (!strcmp(content_type,CGI_MAGIC_TYPE))) {
- send_cgi("GET",file,pa,args,&finfo,in,fd);
- return;
- }
-
- send_regular: /* aaaaack */
- evaluate_access(file,&finfo,M_GET,&allow,&allow_options, fd);
- if(!allow) {
- log_reason("client denied by server configuration",file);
- unmunge_name(file);
- die(FORBIDDEN,file,fd);
- }
-
- if(S_ISDIR(finfo.st_mode)) {
- char ifile[HUGE_STRING_LEN];
-
- /* Path Alias (pa) array should now have the trailing slash */
- /* if(file[strlen(file) - 1] != '/') { */
- if (pa[0] != '/') {
- char url[HUGE_STRING_LEN];
- strcpy_dir(ifile,file);
- unmunge_name(ifile);
- construct_url(url,ifile);
- escape_url(url);
- die(REDIRECT,url,fd);
- }
- make_full_path(file,index_name,ifile);
- if(stat(ifile,&finfo) == -1) {
- if(allow_options & OPT_INDEXES)
- index_directory(file,fd);
- else {
- log_reason("file permissions deny server access",file);
- unmunge_name(file);
- die(FORBIDDEN,file,fd);
- }
- }
- else {
- probe_content_type(ifile);
- if(!strcmp(content_type,CGI_MAGIC_TYPE))
- send_cgi("GET",ifile,pa,args,&finfo,in,fd);
- else
- send_file(ifile,fd,&finfo,pa,args);
- }
- return;
- }
- if(S_ISREG(finfo.st_mode))
- send_file(file,fd,&finfo,pa,args);
- else {
- log_reason("improper file type",file);
- unmunge_name(file);
- die(FORBIDDEN,file,fd); /* device driver or pipe, no permission */
- }
- }
-
- void process_get(int in, FILE *out, char *m, char *url, char *args) {
- int s;
-
- if(assbackwards && header_only) {
- header_only = 0;
- die(BAD_REQUEST,"Invalid HTTP/0.9 method.",out);
- }
- s=translate_name(url,out);
- switch(s) {
- case STD_DOCUMENT:
- send_node(url,args,in,out);
- return;
- case REDIRECT_URL:
- die(REDIRECT,url,out);
- case SCRIPT_NCSA:
- exec_get_NCSA(url,args,in,out);
- return;
- case SCRIPT_CGI:
- exec_cgi_script(m,url,args,in,out);
- return;
- }
- }
-