int main(void) { struct req req; struct itimerval itimer; const char *path; const char *querystring; int i; /* Poor man's ReDoS mitigation. */ itimer.it_value.tv_sec = 2; itimer.it_value.tv_usec = 0; itimer.it_interval.tv_sec = 2; itimer.it_interval.tv_usec = 0; if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) { warn("setitimer"); pg_error_internal(); return EXIT_FAILURE; } /* * First we change directory into the MAN_DIR so that * subsequent scanning for manpath directories is rooted * relative to the same position. */ if (chdir(MAN_DIR) == -1) { warn("MAN_DIR: %s", MAN_DIR); pg_error_internal(); return EXIT_FAILURE; } memset(&req, 0, sizeof(struct req)); req.q.equal = 1; parse_manpath_conf(&req); /* Parse the path info and the query string. */ if ((path = getenv("PATH_INFO")) == NULL) path = ""; else if (*path == '/') path++; if (*path != '\0') { parse_path_info(&req, path); if (req.q.manpath == NULL || access(path, F_OK) == -1) path = ""; } else if ((querystring = getenv("QUERY_STRING")) != NULL) parse_query_string(&req, querystring); /* Validate parsed data and add defaults. */ if (req.q.manpath == NULL) req.q.manpath = mandoc_strdup(req.p[0]); else if ( ! validate_manpath(&req, req.q.manpath)) { pg_error_badrequest( "You specified an invalid manpath."); return EXIT_FAILURE; } if ( ! (NULL == req.q.arch || validate_urifrag(req.q.arch))) { pg_error_badrequest( "You specified an invalid architecture."); return EXIT_FAILURE; } /* Dispatch to the three different pages. */ if ('\0' != *path) pg_show(&req, path); else if (NULL != req.q.query) pg_search(&req); else pg_index(&req); free(req.q.manpath); free(req.q.arch); free(req.q.sec); free(req.q.query); for (i = 0; i < (int)req.psz; i++) free(req.p[i]); free(req.p); return EXIT_SUCCESS; }
int main(void) { struct req req; struct itimerval itimer; const char *path; const char *querystring; int i; /* Poor man's ReDoS mitigation. */ itimer.it_value.tv_sec = 2; itimer.it_value.tv_usec = 0; itimer.it_interval.tv_sec = 2; itimer.it_interval.tv_usec = 0; if (setitimer(ITIMER_VIRTUAL, &itimer, NULL) == -1) { fprintf(stderr, "setitimer: %s\n", strerror(errno)); pg_error_internal(); return(EXIT_FAILURE); } /* Scan our run-time environment. */ if (NULL == (scriptname = getenv("SCRIPT_NAME"))) scriptname = ""; if ( ! validate_urifrag(scriptname)) { fprintf(stderr, "unsafe SCRIPT_NAME \"%s\"\n", scriptname); pg_error_internal(); return(EXIT_FAILURE); } /* * First we change directory into the MAN_DIR so that * subsequent scanning for manpath directories is rooted * relative to the same position. */ if (-1 == chdir(MAN_DIR)) { fprintf(stderr, "MAN_DIR: %s: %s\n", MAN_DIR, strerror(errno)); pg_error_internal(); return(EXIT_FAILURE); } memset(&req, 0, sizeof(struct req)); pathgen(&req); /* Next parse out the query string. */ if (NULL != (querystring = getenv("QUERY_STRING"))) http_parse(&req, querystring); if (req.q.manpath == NULL) req.q.manpath = mandoc_strdup(req.p[0]); else if ( ! validate_manpath(&req, req.q.manpath)) { pg_error_badrequest( "You specified an invalid manpath."); return(EXIT_FAILURE); } if ( ! (NULL == req.q.arch || validate_urifrag(req.q.arch))) { pg_error_badrequest( "You specified an invalid architecture."); return(EXIT_FAILURE); } /* Dispatch to the three different pages. */ path = getenv("PATH_INFO"); if (NULL == path) path = ""; else if ('/' == *path) path++; if ('\0' != *path) pg_show(&req, path); else if (NULL != req.q.query) pg_search(&req); else pg_index(&req); free(req.q.manpath); free(req.q.arch); free(req.q.sec); free(req.q.query); for (i = 0; i < (int)req.psz; i++) free(req.p[i]); free(req.p); return(EXIT_SUCCESS); }
int main(void) { int i; char buf[PATH_MAX]; DIR *cwd; struct req req; char *p, *path, *subpath; /* Scan our run-time environment. */ if (NULL == (cache = getenv("CACHE_DIR"))) cache = "/cache/man.cgi"; if (NULL == (progname = getenv("SCRIPT_NAME"))) progname = ""; if (NULL == (css = getenv("CSS_DIR"))) css = ""; if (NULL == (host = getenv("HTTP_HOST"))) host = "localhost"; /* * First we change directory into the cache directory so that * subsequent scanning for manpath directories is rooted * relative to the same position. */ if (-1 == chdir(cache)) { perror(cache); resp_bad(); return(EXIT_FAILURE); } else if (NULL == (cwd = opendir(cache))) { perror(cache); resp_bad(); return(EXIT_FAILURE); } memset(&req, 0, sizeof(struct req)); strlcpy(buf, ".", PATH_MAX); pathgen(cwd, buf, &req); closedir(cwd); /* Next parse out the query string. */ if (NULL != (p = getenv("QUERY_STRING"))) http_parse(&req, p); /* * Now juggle paths to extract information. * We want to extract our filetype (the file suffix), the * initial path component, then the trailing component(s). * Start with leading subpath component. */ subpath = path = NULL; req.page = PAGE__MAX; if (NULL == (path = getenv("PATH_INFO")) || '\0' == *path) req.page = PAGE_INDEX; if (NULL != path && '/' == *path && '\0' == *++path) req.page = PAGE_INDEX; /* Strip file suffix. */ if (NULL != path && NULL != (p = strrchr(path, '.'))) if (NULL != p && NULL == strchr(p, '/')) *p++ = '\0'; /* Resolve subpath component. */ if (NULL != path && NULL != (subpath = strchr(path, '/'))) *subpath++ = '\0'; /* Map path into one we recognise. */ if (NULL != path && '\0' != *path) for (i = 0; i < (int)PAGE__MAX; i++) if (0 == strcmp(pages[i], path)) { req.page = (enum page)i; break; } /* Route pages. */ switch (req.page) { case (PAGE_INDEX): pg_index(&req, subpath); break; case (PAGE_SEARCH): pg_search(&req, subpath); break; case (PAGE_SHOW): pg_show(&req, subpath); break; default: resp_error404(path); break; } for (i = 0; i < (int)req.psz; i++) { free(req.p[i].path); free(req.p[i].name); } free(req.p); return(EXIT_SUCCESS); }