static int getSubstr( const char * pSource, const int *ovector, int matches, int i,
                          char * &pValue, int escape )
{
    if ( i < matches )
    {
        const int * pParam = ovector + ( i << 1 );
        if ( !escape )
        {
            pValue = (char *)pSource + *pParam;
            return *(pParam + 1) - *pParam;
        }
        else
        {
            char * pEnd = pValue;
            pEnd = escape_uri( pEnd, (char *)pSource + *pParam, *(pParam + 1) - *pParam );
            return pEnd - pValue;
        }
    }
    return 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;
	    }
	}
    }
}
Beispiel #3
0
 inline std::string escape_uri(boost::string_ref uri) {
     return escape_uri(std::string(uri.begin(), uri.end()));
 }