コード例 #1
0
/*
 * Checks to see if actual access to the URL is permitted or not
 * stats the URI first, if failure returns FORBIDDEN, if allowed then
 * checks to see if it is a file, dir or LINK (TEST), and accordingly does more
 */
static int
can_access(request_rec * r)
{
    int rc;
    char *doc_root = (char *)DOCUMENT_ROOT(r);
    struct stat buf;
    char path[MAX_STRING_LEN];

    afsassert(r->uri);
    afsassert(doc_root);

    if (r->filename) {
	afslog(10, ("%s: Found r->filename:%s", module_name, r->filename));
	sprintf(path, "%s", r->filename);
    } else {
	afslog(10,
	       ("%s: Composing path from doc_root:%s and r->uri:%s",
		module_name, doc_root, r->uri));
	sprintf(path, "%s/%s", doc_root, r->uri);
	afslog(10, ("%s: Path:%s", module_name, path));
    }
    rc = stat(path, &buf);
    if (rc == -1) {
	afslog(2,
	       ("%s: pid:%d\tpath:%s\tstat error:%s", module_name, getpid(),
		path, strerror(errno)));

	/* 
	 * if the requested method is an HTTP PUT and the file does not
	 * exist then well, we'll get a stat error but we shouldn't return
	 * an error - we should try and open the file in append mode and then
	 * see if we get a permission denied error
	 */
	if ((strncmp(r->method, "PUT", 3) == 0) && (errno == ENOENT)) {
	    FILE *f = fopen(path, "a");
	    if (f == NULL) {
		if (errno == EACCES) {
		    afslog(2,
			   ("%s: Either AFS acls or other permissions forbid write"
			    " access to file %s for user %s", module_name,
			    path,
			    r->connection->user ? r->connection->
			    user : "******"));
		    return FORBIDDEN;
		} else {
		    log_reason
			("afs_module: Error checking file for PUT method",
			 r->uri, r);
		    return SERVER_ERROR;
		}
	    }
	} else if (errno == ENOTDIR) {
	    /* 
	     * maybe the special case of CGI PATH_INFO to be translated to 
	     * PATH_TRANSLATED - check each component of this path
	     * and stat it to see what portion of the url is actually 
	     * the path and discard the rest for our purposes.
	     */
	    rc = remove_path_info(r, path, &buf);
	    afslog(10,
		   ("%s:remove_path_info returned %d path:%s", module_name,
		    rc, path));
	    if (rc)
		return rc;
	} else {
	    return sort_stat_error(r);
	}
    }
    /* 
     * If we get here then we have something - either a file or a directory
     */
    else {
	if (S_IFREG == (buf.st_mode & S_IFMT)) {
	    /* regular file */
	    FILE *f;
	    char permissions[] = { 'r', '\0', '\0', '\0' };	/* room for +, etc... */

	    if ((strncmp(r->method, "PUT", 3) == 0)) {
		strcpy(permissions, "a");
	    }
	    if (!(f = fopen(path, permissions))) {
		if (errno == EACCES) {
		    afslog(2,
			   ("%s: Either AFS acls or other permissions"
			    " forbid access to file %s for user %s",
			    module_name, path,
			    r->connection->user ? r->connection->
			    user : "******"));
		    return FORBIDDEN;
		} else {
		    char error[ERRSTRLEN];
		    sprintf(error,
			    "%s: Error checking file %s for permissions:%s",
			    module_name, path, strerror(errno));
		    log_reason(error, r->uri, r);
		    return SERVER_ERROR;
		}
	    }
	    fclose(f);
	    return OK;
	}
	if (S_IFDIR == (buf.st_mode & S_IFMT)) {
	    /* path is a directory */

	    if (r->uri[strlen(r->uri) - 1] != '/') {
		/* if we don't have a trailing slash, return REDIRECT */
		char *ifile;
		if (r->args != NULL) {
		    ifile =
			PSTRCAT(r->pool, escape_uri(r->pool, r->uri), "/",
				"?", r->args, NULL);
		} else {
		    ifile =
			PSTRCAT(r->pool, escape_uri(r->pool, r->uri), "/",
				NULL);
		}
		TABLE_SET(r->headers_out, "Location", ifile);
		return REDIRECT;
	    } else {
		DIR *d;
		if (!(d = opendir(path))) {
		    if (errno == EACCES) {
			afslog(2,
			       ("%s: Error accessing dir %s - %s",
				module_name, path, strerror(errno)));
			return FORBIDDEN;
		    } else {
			char error[ERRSTRLEN];
			sprintf(error, "%s: opendir failed with Error:%s",
				module_name, strerror(errno));
			log_reason(error, r, r->uri);
			return SERVER_ERROR;
		    }
		}
		closedir(d);
		return OK;
	    }
	}
    }
}
コード例 #2
0
void send_node(per_request *reqInfo) 
{
    struct stat finfo;
    register x = 0;
    int allow;
    char allow_options;
    int ErrReturn = 0;

    exit_callback = NULL;

/* It is no longer necessary to move all but one of the trailing slashes
 * to the path_info string, since all multiple slashes are now compressed
 * to one as a security precaution.
 */

    if(stat(reqInfo->filename,&finfo) == -1) {
	ErrReturn = extract_path_info(reqInfo,&finfo);
    }
    evaluate_access(reqInfo,&finfo,&allow,&allow_options);
    if (ErrReturn) {
        if(ErrReturn == ENOENT) {
	  log_reason(reqInfo,"file does not exist",reqInfo->filename);
	  die(reqInfo,SC_NOT_FOUND,reqInfo->url);
/* Check for AFS/NFS problems, and send back an unavailable message instead
 * Larry Schwimmer ([email protected])
 */
        } else if ((ErrReturn == ETIMEDOUT) || (ErrReturn == ENODEV)) {
	  log_reason(reqInfo, "file temporarily unavailable",
	             reqInfo->filename);
	  die(reqInfo,SC_SERVICE_UNAVAIL,reqInfo->url);
	} else {
	  log_reason(reqInfo,"(3) file permissions deny server access",
		   reqInfo->filename);
	  die(reqInfo,SC_FORBIDDEN,reqInfo->url);
	}
    }
    if(!allow) {
        log_reason(reqInfo,"client denied by server configuration",
		   reqInfo->filename);
        die(reqInfo,SC_FORBIDDEN,reqInfo->url);
    }

    if (S_ISDIR(finfo.st_mode)) {
	send_dir(reqInfo,&finfo,allow_options);
    } else if (S_ISREG(finfo.st_mode)) {
	x = strlen(reqInfo->filename);
	/* Remove the trailing slash if its not a directory */
	if (reqInfo->filename[x-1] == '/') {
	  if (reqInfo->path_info[0] == '\0') {
	    reqInfo->path_info[0] = '/';
	    reqInfo->path_info[1] = '\0';
          }
	  reqInfo->filename[x-1] = '\0';
        }
	probe_content_type(reqInfo,reqInfo->filename);
	if (!strcmp(reqInfo->outh_content_type, CGI_MAGIC_TYPE))
	    send_cgi(reqInfo,&finfo,allow_options);
#ifdef IMAGEMAP_SUPPORT
	else if (!strcmp(reqInfo->outh_content_type, IMAGEMAP_MAGIC_TYPE))
	    send_imagemap(reqInfo,&finfo,allow_options);
#endif /* IMAGEMAP_SUPPORT */
#ifdef FCGI_SUPPORT
	else if (!strcmp(reqInfo->outh_content_type, FCGI_MAGIC_TYPE))
	    FastCgiHandler(reqInfo);
#endif /* FCGI_SUPPORT */
	else
	    send_file(reqInfo,&finfo,allow_options);
    } else {
	log_reason(reqInfo,"improper file type",reqInfo->filename);
	/* device driver or pipe, no permission */
	die(reqInfo,SC_FORBIDDEN,reqInfo->url); 
    }
}
コード例 #3
0
ファイル: imagemap.c プロジェクト: TooDumbForAName/ncsa-httpd
/* NCSA Imagemap files use: method URL coord1 coord2
 * CERN Imagemap files use: method (coord1) (coord2) URL
 * This version of imagemap will probably work with either in the same file,
 * as long as a full line is in one format or the other.
 */
int send_imagemap(per_request* reqInfo, struct stat* fi, char allow_options)
{
    char *input, *def, *szPoint, *url, *type;
    double testpoint[2], pointarray[MAXVERTS][2];
    int i, j, k;
    int error_num = 0;
    FILE *fp;
    char *t;
    double dist, mindist = -1;
    int sawpoint = 0;
    int sawparen = 0;
    int Found = 0;

    
    input = newString(HUGE_STRING_LEN,STR_TMP);
    def = newString(MAX_STRING_LEN,STR_TMP);
    szPoint = newString(MAX_STRING_LEN,STR_TMP);
    type = newString(MAX_STRING_LEN,STR_TMP);
    url = newString(MAX_STRING_LEN,STR_TMP);

    def[0] = '\0';
    strcpy(szPoint, reqInfo->args);

    if(!(t = strchr(szPoint,','))) {
        error_num = IMAP_ERR_INCORRECT_ARGS;
	goto imagemap_error;
    }

    *t++ = '\0';
    testpoint[X] = (double) atoi(szPoint);
    testpoint[Y] = (double) atoi(t);

    if(!(fp=FOpen(reqInfo->filename,"r"))){
	log_reason(reqInfo, "File permissions deny server access",
		   reqInfo->filename);
        freeString(input);
        freeString(def);
        freeString(szPoint);
        freeString(url);
        freeString(type);
	die(reqInfo, SC_FORBIDDEN, reqInfo->url);
    }

    while (!Found && fgets(input,HUGE_STRING_LEN,fp)) {
        char num[10];

        /* Skip lines with # as comments and blank lines */
        if((input[0] == '#') || (!input[0]))
            continue;

        type[0] = '\0';url[0] = '\0';

        /* Copy the shape keyword into type */
        for(i=0;!isspace(input[i]) && (input[i]);i++)
            type[i] = input[i];
        type[i] = '\0';

        /* Forward to next word */
        while(isspace(input[i])) ++i;

        /* If no coordinates, must be url for default, or NCSA format  */
	if (input[i] != '(') {
          for(j=0;input[i] && !isspace(input[i]);++i,++j)
            url[j] = input[i];
          url[j] = '\0';
        }

	/* Handle default keyword */
        if(!strcmp(type,"default") && !sawpoint) {
            strcpy(def,url);
            continue;
        }

        /* Looking for Coordinates */
        k=0;
        while (input[i]) {
	    /* Move over spaces and commas */
            while (isspace(input[i]) || input[i] == ',')
                i++;
	    
	    /* Under CERN, coordinates are in parenthesis */
            if (input[i] == '(') {
                sawparen = 1;
                while (isspace(input[++i]));
            }

            /* Copy digits into num array */
            j = 0;
            while (isdigit(input[i]))
                num[j++] = input[i++];

            num[j] = '\0';
            if (!j) break;
            pointarray[k][X] = (double) atoi(num);

            /* Skip to next digit */
            while (isspace(input[i]) || input[i] == ',')
                i++;
            /* Copy other number into num */
            j = 0;
            while (isdigit(input[i]))
                num[j++] = input[i++];
            num[j] = '\0';

            if (!j && !sawparen && k > 0) {
              pointarray[k++][Y] = -127;
              break;
            }
  
            if (j)
                pointarray[k++][Y] = (double) atoi(num);
            else {
		error_num = IMAP_ERR_INCORRECT_COORDS;
	        FClose(fp);
		goto imagemap_error;
            }
            
            /* End of parenthesis for coordinates under CERN */
            if (input[i] == ')') {
	      i++;
	      sawparen = 0;
	    } else if (sawparen) {
	      error_num = IMAP_ERR_CERN_MISSING_RIGHT_PAREN;
              FClose(fp);
              goto imagemap_error;	
	    }
        }
        if (url[0] == '\0' && input[i]) {
          while (isspace(input[i])) i++;
          for (j = 0; input[i] && !isspace(input[i]); ++i, ++j)
             url[j] = input[i];
          url[j] = '\0';
        }
        pointarray[k][X] = -1;
        if(!strncmp(type, "poly", 4))
            if(pointinpoly(testpoint,pointarray))
	       Found = 1;
        if(!strncmp(type, "circ", 4))
            if(pointincircle(testpoint,pointarray))
	      Found = 1;
        if(!strncmp(type, "rect", 4))
            if(pointinrect(testpoint,pointarray))
	      Found = 1;
        if(!strcmp(type,"point")) {
	    /* Don't need to take square root. */
	    dist = ((testpoint[X] - pointarray[0][X])
		    * (testpoint[X] - pointarray[0][X]))
		   + ((testpoint[Y] - pointarray[0][Y])
		      * (testpoint[Y] - pointarray[0][Y]));
	    /* If this is the first point, or the nearest, set the default. */
	    if ((! sawpoint) || (dist < mindist)) {
		mindist = dist;
	        strcpy(def,url);
	    }
	    sawpoint++;
	}
    }
    if(Found) {
      sendmesg(reqInfo, url, fp);
      goto imagemap_ok;
    } else {
      if(def[0]) {
        sendmesg(reqInfo, def, fp);
	goto imagemap_ok;
      }
    }
/* No reason to log each of these as an "error" */
/*    log_reason(reqInfo, "No default defined in imagemap.",
	       reqInfo->filename); */
    FClose(fp);
    freeString(input);
    freeString(def);
    freeString(szPoint);
    freeString(url);
    freeString(type);
    die(reqInfo, SC_NO_CONTENT, reqInfo->url);
    return 0;
 
 imagemap_ok:
    FClose(fp);
    freeString(input);
    freeString(def);
    freeString(szPoint);
    freeString(url);
    freeString(type);
    return 1;
 
 imagemap_error:
   freeString(input);
   freeString(def);
   freeString(szPoint);
   freeString(url);
   freeString(type);
   log_reason(reqInfo,imagemap_errors[error_num-1],reqInfo->filename);
   die(reqInfo,SC_BAD_IMAGEMAP,imagemap_errors[error_num-1]);
   return -1;
}
コード例 #4
0
void send_file(per_request *reqInfo, struct stat *fi, char allow_options) 
{
    FILE *f;
#ifdef BLACKOUT_CODE
    int isblack = FALSE;
#endif /* BLACKOUT_CODE */    

    if ((reqInfo->method != M_GET) && (reqInfo->method != M_HEAD)) {
	sprintf(error_msg,"%s to non-script",methods[reqInfo->method]);
	die(reqInfo,SC_NOT_IMPLEMENTED,error_msg);
    }
    set_content_type(reqInfo,reqInfo->filename);

    if((allow_options & OPT_INCLUDES) && (!reqInfo->outh_content_encoding[0])) {
#ifdef XBITHACK
        if((fi->st_mode & S_IXUSR) ||
           (!strcmp(reqInfo->outh_content_type,INCLUDES_MAGIC_TYPE))) {
#else
	if(!strcmp(reqInfo->outh_content_type,INCLUDES_MAGIC_TYPE)) {
#endif /* XBITHACK */
	    reqInfo->bytes_sent = 0;
	    send_parsed_file(reqInfo, allow_options & OPT_INCNOEXEC);
	    log_transaction(reqInfo);
	    return;
	}
    }
    if (reqInfo->path_info[0]) {
	strcat(reqInfo->filename,reqInfo->path_info);
	strcat(reqInfo->url,reqInfo->path_info);
	sprintf(error_msg,"No file matching URL: %s",reqInfo->url);
	log_reason(reqInfo, error_msg, reqInfo->filename);
	die(reqInfo,SC_NOT_FOUND,reqInfo->url);
    }
	
    if(!(f=FOpen(reqInfo->filename,"r"))) {
      if (errno == EACCES) {
	log_reason(reqInfo,"(1) file permissions deny server access",
		   reqInfo->filename);
	/* we've already established that it exists */
	die(reqInfo,SC_FORBIDDEN,reqInfo->url); 
      } else {
	/* We know an error occured, of an unexpected variety. 
	 * This could be due to no more file descriptors.  We have this
	 * child exit after this stage so that errors of state are 
	 * swept under the carpet.
	 */
	standalone = 0;
	sprintf(error_msg,"File Open error, errno=%d",errno);
	log_reason(reqInfo,error_msg,reqInfo->filename);
	die(reqInfo,SC_SERVER_ERROR,error_msg);
      }
    }
    reqInfo->bytes_sent = 0;

#ifdef BLACKOUT_CODE
    if (!strcmp(reqInfo->outh_content_type,BLACKOUT_MAGIC_TYPE)) {
      isblack = TRUE;
      strcpy(reqInfo->outh_content_type,"text/html");
    }
#endif /* BLACKOUT_CODE */

    if(reqInfo->http_version != P_HTTP_0_9) {
      /* No length dependent headers since black is parsed */
#ifdef BLACKOUT_CODE
      if (isblack == FALSE) { 
#endif /* BLACKOUT_CODE */
#ifdef CONTENT_MD5
	reqInfo->outh_content_md5 = (unsigned char *)md5digest(f);
#endif /* CONTENT_MD5 */
	set_content_length(reqInfo,fi->st_size);
	if (set_last_modified(reqInfo,fi->st_mtime)) {
	    FClose(f);
	    return;
	}
      }
      if (reqInfo->http_version != P_HTTP_0_9) {
           send_http_header(reqInfo);
      }
#ifdef BLACKOUT_CODE
    }
#endif /* BLACKOUT_CODE */

    if(reqInfo->method != M_HEAD) {
#ifdef BLACKOUT_CODE
      if (isblack == TRUE)
	send_fp_black(reqInfo,f,NULL);
       else
#endif /* BLACKOUT_CODE */
	send_fp(reqInfo,f,NULL);
    }
    log_transaction(reqInfo);
    FClose(f);
}


void send_dir(per_request *reqInfo,struct stat *finfo, char allow_options) {
  char *name_ptr, *end_ptr;
  char *ifile, *temp_name;

  ifile = newString(HUGE_STRING_LEN,STR_TMP);
  temp_name = newString(HUGE_STRING_LEN,STR_TMP);

/* Path Alias (pa) array should now have the trailing slash */
  /*  if (pa[0] != '/') { */
  if ((reqInfo->filename[strlen(reqInfo->filename) - 1] != '/') && 
      (reqInfo->path_info[0] != '/')) {
    strcpy_dir(ifile,reqInfo->url);
    construct_url(temp_name,reqInfo->hostInfo,ifile);
    escape_url(temp_name);
    die(reqInfo,SC_REDIRECT_PERM,temp_name);
  }

  /* Don't allow PATH_INFO to directory indexes as a compromise for 
     error messages for files which don't exist */

  if ((reqInfo->path_info[0] != '\0') || (strlen(reqInfo->path_info) > 1)) {
        strcat(reqInfo->filename,reqInfo->path_info);
        strcat(reqInfo->url,reqInfo->path_info);
        sprintf(error_msg,"No file matching URL: %s",reqInfo->url);
        log_reason(reqInfo, error_msg, reqInfo->filename);
	freeString(temp_name);
	freeString(ifile);
        die(reqInfo,SC_NOT_FOUND,reqInfo->url);
  }
    
  strncpy(temp_name, reqInfo->hostInfo->index_names, HUGE_STRING_LEN-1);
  end_ptr = name_ptr = temp_name;

  while (*name_ptr) {
    
    while (*name_ptr && isspace (*name_ptr)) ++name_ptr;
    end_ptr = name_ptr;
    if (strchr(end_ptr, ' ') ) {
      end_ptr = strchr(name_ptr, ' ');
      *end_ptr = '\0';
      end_ptr++;
    } else
      end_ptr += strlen(end_ptr);
    make_full_path(reqInfo->filename,name_ptr,ifile);
    if(stat(ifile,finfo) == -1) {
      if(! *end_ptr && (allow_options & OPT_INDEXES)) {
        if (reqInfo->path_info[0]) {
          strcat(reqInfo->filename,reqInfo->path_info);
	  strcat(reqInfo->url,reqInfo->path_info);
	  log_reason(reqInfo,"file does not exist",reqInfo->filename);
	  freeString(ifile);
	  freeString(temp_name);
	  die(reqInfo,SC_NOT_FOUND,reqInfo->url);
	}
	if ((reqInfo->method != M_GET) && (reqInfo->method != M_HEAD)) {
	  sprintf(error_msg,"%s to non-script",methods[reqInfo->method]);
	  freeString(ifile);
	  freeString(temp_name);
	  die(reqInfo,SC_NOT_IMPLEMENTED,error_msg);
	}	
	index_directory(reqInfo);
	freeString(ifile);
	freeString(temp_name);
	return;
      } else if (! *end_ptr) {
	log_reason(reqInfo,"(2) file permissions deny server access",
		   reqInfo->filename);
	freeString(ifile);
	freeString(temp_name);
	die(reqInfo,SC_FORBIDDEN,reqInfo->url);
      }
    } else {
      strcpy(reqInfo->filename,ifile);
      probe_content_type(reqInfo,reqInfo->filename);
      if(!strcmp(reqInfo->outh_content_type,CGI_MAGIC_TYPE))
	send_cgi(reqInfo,finfo,allow_options);
      else
	send_file(reqInfo,finfo,allow_options);
      freeString(ifile);
      freeString(temp_name);
      return;
    }
    name_ptr = end_ptr;
  }	 
}