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; } } } }
inline std::string escape_uri(boost::string_ref uri) { return escape_uri(std::string(uri.begin(), uri.end())); }