int request_post(FCGX_Stream *in, FCGX_Stream *out, FCGX_ParamArray *envp) { // have not test char *contentSplit; char *buffer = NULL; char *content_type = FCGX_GetParam("CONTENT_TYPE", *envp); contentSplit = strchr(content_type,'=')+1; char *content_length = FCGX_GetParam("CONTENT_LENGTH", *envp); int len = 0; if(content_length != NULL) { len = strtol(content_length, NULL, 10); if(len == 0) { FCGX_FPrintF(out, "No data posted\n"); }else { if(len > MAX_LEN) len = MAX_LEN; buffer = (char*)malloc(len); if(buffer) { for(int i=0;i<len;i++) { buffer[i] = FCGX_GetChar(in); } post_data_handle(buffer,len,contentSplit,out); free(buffer); } } } return 0; }
FrozenState::FrozenState(char** envp, const Request& req, const std::string& icicle) : m_icicle(icicle) , m_get(req.varDebugData()) , m_cookies(req.cookieDebugData()) , m_resource(FCGX_GetParam("REQUEST_URI", envp)) , m_server(FCGX_GetParam("SERVER_NAME", envp)) , m_remote_addr(FCGX_GetParam("REMOTE_ADDR", envp)) , m_remote_port(FCGX_GetParam("REMOTE_PORT", envp)) , m_now(tyme::now()) { for (; *envp; ++envp) { const char* eq = strchr(*envp, '='); std::string key, value; if (!eq) key = *envp; else if (eq != *envp) key.assign(*envp, eq - *envp); if (eq) { if (eq != *envp) ++eq; value = eq; } m_environment[key] = std::move(value); } }
const char *documentRoot() { static char path[MAXPATHLEN+1] = ""; if (path[0] == '\0') { #ifdef WIN32 WOReadKeyFromConfiguration(CGI_DOCUMENT_ROOT, path, MAXPATHLEN); #else const char *doc_root; /* Apache provides this as an environment variable straight */ if ((doc_root = FCGX_GetParam(CGI_DOCUMENT_ROOT, hdrp)) != NULL) { strncpy(path, doc_root, MAXPATHLEN); } else { const char *path_trans, *path_info; path_trans = FCGX_GetParam(PATH_TRANSLATED, hdrp); path_info = FCGX_GetParam(CGI_PATH_INFO, hdrp); if (path_trans && path_info) { char *e = strstr(path_trans,path_info); if (e) { strncpy(path,path_trans,e-path_trans); } } } #endif } if (path[0] != '\0') return path; else { WOLog(WO_ERR,"<FastCGI> Can't find document root in CGI variables"); return "/usr/local/apache/htdocs"; /* this is bad.... */ } }
/* * get_range_query * Parses the GET|POST request and extracts the 'range query' * string. * Args: * - FCGX_Request * (of the thread) * - char * (location where the 'range query' is written) * Returns: * - O (expand) * - 1 (list) */ static int get_range_query(FCGX_Request *rq, char *query) { char *method = FCGX_GetParam("REQUEST_METHOD", rq->envp); char *script_name = FCGX_GetParam("SCRIPT_NAME", rq->envp); int list = -1; /* list or expand? */ char *decoded_url; /* accept only GET && POST */ if(strcmp(method, "GET") != 0 && strcmp(method, "POST") != 0) { invalid_request(rq, "401", "Only GET || POST Request_Method Allowed"); } else if (strcmp(method, "GET") == 0) { decoded_url = curl_unescape(FCGX_GetParam("QUERY_STRING", rq->envp), 0); strcpy(query, decoded_url); curl_free(decoded_url); } else if (strcmp(method, "POST") == 0) { /* TODO: i might have to loop this in while and do a strcat + realloc if i need to increase string length at runtime */ FCGX_GetStr(query, QUERY_STR_SIZE, rq->in); } /* we have two cases here * - /range/list?(.*) * - /range/expand?(.*) * SCRIPT_NAME == /range/list || /range/expand * QUERY_STRING == (.*) (in our case query has it) * strtok() for SCRIPT_NAME and decide which kind it is, * for QUERY_STRING is passed as is. */ if (strlen(query) == 0) { invalid_request(rq, "402", "No Query String Found"); return 0; } /* list ? */ list = strcmp(script_name, "/range/list") == 0 ? 1 : -1; /* if not list, but is expand */ if (list != 1 && strcmp(script_name, "/range/expand") == 0) list = 0; /* neither list nor expand */ if (list == -1) { invalid_request(rq, "403", "Expects /range/list?... or /range/expand?..."); return 0; } /* FCGX_FPrintF(rq->out, "Content-type: text/plain\r\n" "foo: bar\r\n" "\r\n"); FCGX_FPrintF(rq->out, "List (%d) Query: (%s) Script: (%s)\n", list, query, script_name); */ return list; }
void Application::report(char** envp, const std::string& icicle) { ReqInfo info; info.icicle = icicle; info.resource = FCGX_GetParam("REQUEST_URI", envp); info.server = FCGX_GetParam("SERVER_NAME", envp); info.remote_addr = FCGX_GetParam("REMOTE_ADDR", envp); info.remote_port = FCGX_GetParam("REMOTE_PORT", envp); info.now = tyme::now(); m_requs.push_back(info); }
std::string fcgi_stream::getenv(const char *variable) { char const *p; if((p=FCGX_GetParam(variable,request.envp))!=NULL) return p; return ""; };
bool doRequest(FCGX_Request& request){ map<string, string> mapParam; string query_string = FCGX_GetParam("QUERY_STRING", request.envp); ParseParam(mapParam, query_string); map<string, string>::iterator itU = mapParam.find("uid"); if(itU == mapParam.end()){ return false; } int userId; try{ userId = boost::lexical_cast<int>((*itU).second); }catch(...){ return false; } TipPtr tp; try{ tp = QuestCacheAdapter::instance().showTip(userId); if(tp->id==-1) return false; }catch(...){ return false; } string res = "Content-type: text/html\r\n\r\n" + tp->content; FCGX_FPrintF(request.out, res.c_str()); FCGX_Finish_r(&request); return true; }
int64_t content_len(void) { const char *clen = FCGX_GetParam("CONTENT_LENGTH", envp); if(!clen) return 0; return atoll(clen); }
int request_get(FCGX_Stream *in, FCGX_Stream *out, FCGX_ParamArray *envp) { vector<key_value_t> kvs; char *query_string = FCGX_GetParam("QUERY_STRING", *envp); char *ip = FCGX_GetParam("REMOTE_ADDR", *envp); char query[1024] = {0}, remote_ip[20] = {0}; memcpy(query, query_string, strlen(query_string)); memcpy(remote_ip, ip, strlen(ip)); parse_get_query(query, kvs); char *result = http_query_proc(kvs, remote_ip); //const char *result = "ok"; FCGX_FPrintF(out, "Content-type: text/plain; charset=utf-8\r\n" "\r\n" "" "%s", result); return 0; }
int main() { FCGX_Stream *in, *out, *err; FCGX_ParamArray envp; redisContext *rc = faptime_redis_connect(); if (NULL == rc) { error_log("Unable to connect to Redis"); /* exit(1); */ } faptime_create_lookup_table(); /* int count = 0; */ int redis_errno = 0; long long id = 0; char *redirect_to, *req_uri; while (FCGX_Accept(&in, &out, &err, &envp) >= 0) { FAPTIME_REQ_INIT(); req_uri = FCGX_GetParam("REQUEST_URI", envp); error_log("This is an error mofo"); debug_log("== Begin Request =="); /* default_message(out, &envp, &count); */ /* continue; */ if (req_uri == NULL) { error_log("request_uri was NULL"); faptime_set_status(500); FAPTIME_REQ_FINISH(); continue; } if (valid_hash(req_uri) != FAPTIME_HASH_OK || !(id = faptime_decode(req_uri))) { debug_log("Request URI '%s' was not valid", req_uri); faptime_set_status(404); FAPTIME_REQ_FINISH(); continue; } if ((redirect_to = faptime_get_url(rc, id, &redis_errno)) == NULL) { assert(redirect_to == NULL); debug_log("Request hash %lld (%s) had no url", id, req_uri); faptime_set_status(404); FAPTIME_REQ_FINISH(); continue; } faptime_set_status(302); faptime_set_redirect(redirect_to); free(redirect_to); FAPTIME_REQ_FINISH(); } return 0; }
int default_message(FCGX_Stream *out, FCGX_ParamArray *envp, int *count) { int i; i = FCGX_FPrintF(out, "Content-type: text/html\r\n" "\r\n" "<title>FastCGI echo (fcgiapp version)</title>\n" "<h1>FastCGI echo (fcgiapp version)</h1>\n" "Request number %d, Process ID: %d<p>\n" "Requested url '%s'\n", ++(*count), getpid(), FCGX_GetParam("REQUEST_URI", *envp)); return i; }
static void *doit(void *a) { int rc, thread_id = (int)a; int i = 0; pid_t pid = getpid(); FCGX_Request request; char *server_name; FCGX_InitRequest(&request, 0, 0); for (;;) { static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t counts_mutex = PTHREAD_MUTEX_INITIALIZER; /* Some platforms require accept() serialization, some don't.. */ pthread_mutex_lock(&accept_mutex); rc = FCGX_Accept_r(&request); pthread_mutex_unlock(&accept_mutex); if (rc < 0) break; server_name = FCGX_GetParam("SERVER_NAME", request.envp); FCGX_FPrintF( request.out, "Content-type: text/html\r\n" "\r\n" "<title>FastCGI Hello! (multi-threaded C, fcgiapp library)</title>" "<h1>FastCGI Hello! (multi-threaded C, fcgiapp library)</h1>" "Thread %d, Process %ld<p>" "Request counts for %d threads running on host <i>%s</i><p><code>", thread_id, pid, THREAD_COUNT, server_name ? server_name : "?" ); //sleep(2); pthread_mutex_lock(&counts_mutex); ++counts[thread_id]; i++; FCGX_FPrintF( request.out, "%5d ", i ); //for (i = 0; i < THREAD_COUNT; i++) // FCGX_FPrintF(request.out, "%5d " , counts[i]); pthread_mutex_unlock(&counts_mutex); FCGX_Finish_r(&request); } return NULL; }
virtual RequestPtr Create(FCGX_Request * r) { char * path = FCGX_GetParam("SCRIPT_NAME", r->envp); if (path) { if (strcmp(path, "/union/getall.html") == 0) return new GetAllRequest(r); if (strcmp(path, "/union/getone.html") == 0) return new GetOneRequest(r); if (strcmp(path, "/union/update.html") == 0) return new UpdateRequest(r); if (strcmp(path, "/union/save.html") == 0) return new SaveRequest(r); if (strcmp(path, "/union/reload.html") == 0) return new ReloadRequest(r); } return NULL; }
int main(int argc, char *argv[]) { if(argc > 1){ if(argc == 3){ // as normal program, not cgi now printf("update dns, domain: %s, host: %s\n", argv[1], argv[2]); int ret = dns_update(argv[1], argv[2]); if(ret < 0){ printf("Internal error.\n"); }else if(ret == 1){ printf("Recorde can't find.\n"); }else if(ret == 2){ printf("Recorde still fresh.\n"); }else if(ret == 0){ printf("Recorde refreshed.\n"); }else{ printf("Unknown error.\n"); } }else{ printf("Usage: %s <domain> <host>\n", argv[0]); } return 0; } FCGX_Stream *in; FCGX_Stream *out; FCGX_Stream *err; FCGX_ParamArray envp; char *method = NULL; while(FCGX_Accept(&in, &out, &err, &envp) >= 0) { method = FCGX_GetParam("REQUEST_METHOD", envp); if(strcmp(method, "POST") == 0){ //request_post(in, out, &envp); }else if(strcmp(method, "GET") == 0){ request_get(in, out, &envp); } } FCGX_Finish(); //test(); return 0; }
int main () { FCGX_Stream *in, *out, *err; FCGX_ParamArray envp; int count = 0; while (FCGX_Accept(&in, &out, &err, &envp) >= 0) { char *contentLength = FCGX_GetParam("CONTENT_LENGTH", envp); int len = 0; FCGX_FPrintF(out, "Content-type: text/html\r\n" "\r\n" "<title>FastCGI echo (fcgiapp version)</title>" "<h1>FastCGI echo (fcgiapp version)</h1>\n" "Request number %d, Process ID: %d<p>\n", ++count, getpid()); if (contentLength != NULL) len = strtol(contentLength, NULL, 10); if (len <= 0) { FCGX_FPrintF(out, "No data from standard input.<p>\n"); } else { int i, ch; FCGX_FPrintF(out, "Standard input:<br>\n<pre>\n"); for (i = 0; i < len; i++) { if ((ch = FCGX_GetChar(in)) < 0) { FCGX_FPrintF(out, "Error: Not enough bytes received on standard input<p>\n"); break; } FCGX_PutChar(ch, out); } FCGX_FPrintF(out, "\n</pre><p>\n"); } PrintEnv(out, "Request environment", envp); PrintEnv(out, "Initial environment", environ); } /* while */ return 0; }
int lsp::lua_get_in_header(lua_State *L) { FCGX_Request* r = (FCGX_Request*)luaL_lsp_get_io_ctx(L); const char* s1=luaL_checkstring(L,1); std::string str = "HTTP_"; str += s1; std::transform(str.begin(), str.end(),str.begin(), ::toupper); const char* s2=FCGX_GetParam(str.c_str(), r->envp); //log(LOG_INFO, "get_in_header %s", s2); if(!s2) s2=""; lua_pushstring(L,s2); return 1; }
int main(void) { FCGX_Init(); int socket = FCGX_OpenSocket(SOCKET_PATH, 0); char* remote_addr; FCGX_Request request; if (FCGX_InitRequest(&request, socket, 0) != 0) return 1; while (1) { FCGX_Accept_r(&request); remote_addr = FCGX_GetParam("REMOTE_ADDR", request.envp); FCGX_PutS("Content-type: text/plain\n\n", request.out); FCGX_PutS(remote_addr, request.out); FCGX_PutS("\n", request.out); FCGX_Finish_r(&request); } }
/* * read CONTENT_LENGTH input and return as string */ int clip_FCGI_READ(ClipMachine *mp) { char *clen; int len; if (!inited) return EG_ARG; clen = FCGX_GetParam("CONTENT_LENGTH", envp); /*clen = getenv("CONTENT_LENGTH");*/ if (clen) len = strtol(clen, NULL, 10); else len = 0; if(len) { OutBuf buf; int i, ch, l; init_Buf(&buf); for (i = 0; i < len; i++) { if ((ch = FCGX_GetChar(in)) < 0) /*if ((ch = FCGI_fgetc(FCGI_stdin)) < 0)*/ break; putByte_Buf(&buf, ch); } l = buf.ptr - buf.buf; putByte_Buf(&buf, 0); _clip_retcn_m(mp, buf.buf, l); } else _clip_retc(mp, ""); return 0; }
static void *doit(void *a){ FCGX_Request request; int rc; char *filename; UNUSED(a); FCGX_InitRequest(&request, 0, /* FCGI_FAIL_ACCEPT_ON_INTR */ 0); while(1){ int fd; //Some platforms require accept() serialization, some don't. The documentation claims it to be thread safe // static pthread_mutex_t accept_mutex = PTHREAD_MUTEX_INITIALIZER; // pthread_mutex_lock(&accept_mutex); rc = FCGX_Accept_r(&request); // pthread_mutex_unlock(&accept_mutex); if(rc < 0) break; //get the filename if((filename = FCGX_GetParam("SCRIPT_FILENAME", request.envp)) == NULL){ FORBIDDEN(request.out); //don't try to open directories }else if(filename[strlen(filename)-1] == '/'){ FORBIDDEN(request.out); //open the file }else if((fd = open(filename, O_RDONLY)) == -1){ NOTFOUND(request.out, filename); //no error, serve it }else{ SENDFILE(request.out, filename); close(fd); } FCGX_Finish_r(&request); } return NULL; }
PyObject *smisk_Response_send_file(smisk_Response* self, PyObject *filename) { log_trace("ENTER"); PyObject *s = NULL; char *server = NULL; if (!filename || !SMISK_STRING_CHECK(filename)) return PyErr_Format(PyExc_TypeError, "first argument must be a string"); if (self->has_begun == Py_True) return PyErr_Format(PyExc_EnvironmentError, "output has already begun"); if (smisk_Application_current) server = FCGX_GetParam("SERVER_SOFTWARE", smisk_Application_current->request->envp); if (server == NULL) server = "unknown server software"; if (strstr(server, "lighttpd/1.4")) { s = PyBytes_FromString("X-LIGHTTPD-send-file: "); log_debug("Adding \"X-LIGHTTPD-send-file: %s\" header for Lighttpd <=1.4", PyBytes_AsString(filename)); } else if (strstr(server, "lighttpd/") || strstr(server, "Apache/2")) { s = PyBytes_FromString("X-Sendfile: "); log_debug("Adding \"X-Sendfile: %s\" header for Lighttpd >=1.5 | Apache >=2", PyBytes_AsString(filename)); } else if (strstr(server, "nginx/")) { s = PyBytes_FromString("X-Accel-Redirect: "); log_debug("Adding \"X-Accel-Redirect: %s\" header for Nginx", PyBytes_AsString(filename)); } else { return PyErr_Format(PyExc_EnvironmentError, "sendfile not supported by host server ('%s')", server); } // Make sure self->headers is initialized ENSURE_BY_GETTER(self->headers, smisk_Response_get_headers(self), return NULL; );
int clip_FCGI_GETENV(ClipMachine *mp) { ClipVar *rp; char *str = _clip_parc(mp, 1); int i = 0; if (!inited) return EG_ARG; if (str) { _clip_retc(mp, FCGX_GetParam(str, envp)); /*_clip_retc(mp, getenv(str));*/ } else { rp = RETPTR(mp); _clip_map(mp, rp); while (envp[i]) { int l; char *s = envp[i]; char *e; /*char *s = environ[i];*/ l = strcspn(s, "="); if (s[l]=='=') e = s+l+1; else e = ""; _clip_mputc(mp, rp, _clip_casehashbytes(0, s, l), e, strlen(e)); i++; } } return 0; }
int bridge_request_getinput(bridge_request_t *self, char **data) { char *contentLength; char *buffer; int len = 0; if ((contentLength = FCGX_GetParam("CONTENT_LENGTH", self->request.envp)) != 0) len = strtol(contentLength, NULL, 10); if (len <= 0) return EINVAL; if ((buffer = malloc((size_t)len+1)) == 0) { FCGX_PutS("out of memory!", self->request.err); return ENOMEM; } if (FCGX_GetStr(buffer, len, self->request.in) != len) { FCGX_PutS("Got less data than expected.", self->request.err); return EINVAL; } buffer[len] = '\0'; *data = buffer; return 0; }
int lsp::read_request_data(lua_State *L) { FCGX_Request* r = (FCGX_Request*)luaL_lsp_get_io_ctx(L); const char* p=FCGX_GetParam("CONTENT_LENGTH", r->envp); int content_length = p? atoi(p) : -1; if(content_length < 0) return 411;//HTTP_LENGTH_REQUIRED; // TODO: for max post? if(content_length > 4096) return 400;//HTTP_BAD_REQUEST; int retval = 0; luaL_Buffer buf; luaL_buffinit(L,&buf); //if(ap_should_client_block(apr)) { char *tmp = new char[1024]; int len = 0; while(len<content_length) { int n = content_length - len; //n = ap_get_client_block(apr,tmp,n>sizeof(tmp)?sizeof(tmp):n); n = FCGX_GetStr(tmp, n > 1024 ? 1024 : n, r->in); if(n <= 0) break; len += n; luaL_addlstring(&buf,tmp,n); } if(len!=content_length) retval = -1;//HTTP_REQUEST_TIME_OUT; delete[] tmp; } const char* content_type = FCGX_GetParam("CONTENT_TYPE", r->envp); int n = lua_gettop(L); if(content_type && !strcmp(content_type,"application/x-www-form-urlencoded")) { lua_getglobal(L,"args_decode"); luaL_pushresult(&buf); if(lua_isfunction(L,-2) && !lua_pcall(L,1,1,0)) lua_setglobal(L,"args_post"); } else { lua_getfield(L,LUA_GLOBALSINDEX,"env"); luaL_pushresult(&buf); if(lua_istable(L,-2)) lua_setfield(L,-2,"content"); } lua_pop(L,lua_gettop(L)-n); return retval; }
int lsp::luabag_run(LUABAG* luabag, FCGX_Request* r) { int handler_type = handler_type_unknown; char* handler = FCGX_GetParam("SCRIPT_NAME", r->envp); if(handler) { handler=strrchr(handler,'.'); if(!handler) { log(LOG_ERR, "%s", "Script name has no extension name"); return -1; } if(!strcmp(handler,".lsp") || !strcmp(handler,".lp") ) handler_type = handler_type_lsp; else if(!strcmp(handler,".lua")) { handler_type = handler_type_lua; log(LOG_ERR, "%s", "lua handler"); } else { log(LOG_ERR, "%s:%s", "Not correct extension name, valid extension are lp, lsp, lua", handler); return -1; } } else { log(LOG_ERR, "%s", "Not script name"); return -1; } lsp_io lio={r, lputs:io_def_puts, lputc:io_def_putc, lwrite:io_def_write}; luaL_lsp_set_io(luabag->L,&lio); char* p = FCGX_GetParam("REQUEST_METHOD", r->envp); if(p && !strcmp(p,"POST")) { int rc = read_request_data(luabag->L); if(rc!= 0) return rc; } p = FCGX_GetParam("QUERY_STRING", r->envp); luaL_lsp_setargs(luabag->L, p, p ? strlen(p) : 0); lua_getfield(luabag->L,LUA_GLOBALSINDEX,"env"); //luaL_lsp_setfield(luabag->L,"server_admin",r->server->server_admin); luaL_lsp_setfield(luabag->L,"server_hostname", FCGX_GetParam("SERVER_NAME", r->envp)); luaL_lsp_setfield(luabag->L,"remote_ip",FCGX_GetParam("REMOTE_ADDR", r->envp)); luaL_lsp_setfield(luabag->L,"remote_host",FCGX_GetParam("REMOTE_ADDR", r->envp)); luaL_lsp_setfield(luabag->L,"remote_port",FCGX_GetParam("REMOTE_PORT", r->envp)); luaL_lsp_setfield(luabag->L,"local_ip", FCGX_GetParam("SERVER_ADDR", r->envp)); luaL_lsp_setfield(luabag->L,"local_host",FCGX_GetParam("SERVER_NAME", r->envp)); luaL_lsp_setfield(luabag->L,"local_port",FCGX_GetParam("SERVER_PORT", r->envp)); char hostname[256]; if (0 == gethostname(hostname, 256)) { luaL_lsp_setfield(luabag->L,"local_host", hostname); luaL_lsp_setfield(luabag->L,"hostname", hostname); } luaL_lsp_setfield(luabag->L,"method", FCGX_GetParam("REQUEST_METHOD", r->envp)); luaL_lsp_setfield(luabag->L,"handler", handler); luaL_lsp_setfield(luabag->L,"uri", FCGX_GetParam("REQUEST_URI", r->envp)); luaL_lsp_setfield(luabag->L,"doc_uri", FCGX_GetParam("DOCUMENT_URI", r->envp)); luaL_lsp_setfield(luabag->L,"doc_root", FCGX_GetParam("DOCUMENT_ROOT", r->envp)); char* filename = FCGX_GetParam("SCRIPT_FILENAME", r->envp); luaL_lsp_setfield(luabag->L,"filename", filename); luaL_lsp_setfield(luabag->L,"accept_lang", FCGX_GetParam("HTTP_ACCEPT_LANGUAGE", r->envp)); lua_pop(luabag->L,1); luaL_lsp_chdir_to_file(luabag->L, filename); luaL_lsp_session_init(luabag->L, !g_conf->cookie_name.empty() ? g_conf->cookie_name.c_str() : "LSPSESSID", g_conf->cookie_days > 0 ? g_conf->cookie_days : 7, !g_conf->cookie_path.empty() ? g_conf->cookie_path.c_str() : "/"); int status=0; switch(handler_type) { case handler_type_lsp: status=luaL_load_lsp_file(luabag->L, filename); header_table_set(r, "CONTENT-TYPE", "text/html"); break; case handler_type_lua: status=luaL_loadfile(luabag->L, filename); header_table_set(r, "CONTENT-TYPE", "text/plain"); break; } if(status) { const char* e=lua_tostring(luabag->L,-1); FCGX_PutS(e, r->err); log(LOG_ERR, "%s", e); lua_pop(luabag->L,1); luaL_lsp_chdir_restore(luabag->L); return 500; } status=lua_pcall(luabag->L,0,LUA_MULTRET,0); // won't return other than 0, as the code has been excuted with outputs if(status) { const char* e=lua_tostring(luabag->L,-1); log(LOG_ERR, "%s", e); FCGX_PutS(e, r->err); if(g_conf->show_exception) // if not 0 FCGX_PutS(e, r->err); lua_pop(luabag->L,1); } int rnum=lua_gettop(luabag->L); int result = 0; if(rnum>0) { result = lua_tointeger(luabag->L,-1); if(!result || result==200) result = 0; lua_pop(luabag->L,rnum); } luaL_lsp_chdir_restore(luabag->L); /* if(result == 0) FCGX_FFlush(r->out); else FCGX_FFlush(r->err); */ return result; }
std::string FcgiRequest::getParameter(const std::string & paramName) { return FCGX_GetParam(paramName.c_str(), request.envp); }
void handle_request(void) { const char *param; char *argp; unsigned int plen; msg_new_id(); verb = VERB_UNSUP; param = FCGX_GetParam("REQUEST_METHOD", envp); if(param) { plen = strlen(param); switch(plen) { case 3: if(!memcmp(param, "GET", 4)) verb = VERB_GET; else if(!memcmp(param, "PUT", 4)) verb = VERB_PUT; break; case 4: if(!memcmp(param, "HEAD", 5)) verb = VERB_HEAD; else if(!memcmp(param, "POST", 5)) verb = VERB_POST; break; case 6: if(!memcmp(param, "DELETE", 7)) verb = VERB_DELETE; break; case 7: if(!memcmp(param, "OPTIONS", 8)) { CGI_PUTS("Allow: GET,HEAD,OPTIONS,PUT,DELETE\r\nContent-Length: 0\r\n\r\n"); return; } break; } } if(verb == VERB_UNSUP) quit_errmsg(405, "Method Not Allowed"); if(content_len()<0 || (verb != VERB_PUT && content_len())) quit_errmsg(400, "Invalid Content-Length: must be positive and method must be PUT"); param = FCGX_GetParam("REQUEST_URI", envp); if(!param) quit_errmsg(400, "No URI provided"); plen = strlen(param); if(*param != '/') quit_errmsg(400, "URI must start with /"); if(plen > sizeof(reqbuf) - 1) quit_errmsg(414, "URL too long: request line must be <8k"); do { param++; plen--; } while(*param == '/'); memcpy(reqbuf, param, plen+1); argp = memchr(reqbuf, '?', plen); nargs = 0; if(argp) { unsigned int argslen = plen - (argp - reqbuf); plen = argp - reqbuf; do { *argp = '\0'; argp++; argslen--; } while(*argp == '?'); if(!argslen) argp = NULL; else { do { char *nextarg; if(nargs >= MAX_ARGS) quit_errmsg(414, "Too many parameters"); nextarg = memchr(argp, '&', argslen); if(nextarg) { do { *nextarg = '\0'; nextarg++; } while(*nextarg == '&'); } if(*argp) { if(!(args[nargs] = inplace_urldecode(argp, 0, 0, NULL))) quit_errmsg(400, "Invalid URL encoding"); if(utf8_validate_len(args[nargs]) < 0) quit_errmsg(400, "Parameters with invalid utf-8 encoding"); nargs++; } argslen -= nextarg - argp; argp = nextarg; } while (argp); } } while(plen && reqbuf[plen-1] == '/') { plen--; reqbuf[plen] = '\0'; } path = memchr(reqbuf, '/', plen); if(path) { do { *path = '\0'; path ++; } while(*path == '/'); if(!*path) path = NULL; } volume = *reqbuf ? reqbuf : NULL; int forbidden = 0; if((volume && !inplace_urldecode(volume, '/', 0, &forbidden)) || (path && !inplace_urldecode(path, '/', '/', &forbidden))) { if (forbidden) quit_errmsg(400, "Volume or path with forbidden %2f or %00"); else quit_errmsg(400, "Invalid URL encoding"); } int vlen = volume ? utf8_validate_len(volume) : 0; int flen = path ? utf8_validate_len(path) : 0; if (vlen < 0 || flen < 0) quit_errmsg(400, "URL with invalid utf-8 encoding"); if (is_reserved()) { /* No UTF8 used on reserved volumes, allow higher limit. * Otherwise we hit the 512 limit with batch requests already */ if (path && strlen(path) > SXLIMIT_MAX_FILENAME_LEN * 12) { msg_set_reason("Path too long: filename must be <%d characters (%ld)", SXLIMIT_MAX_FILENAME_LEN*12+ 1, strlen(path)); quit_errmsg(414, msg_get_reason()); } } else { if (flen > SXLIMIT_MAX_FILENAME_LEN) { msg_set_reason("Path too long: filename must be <%d UTF8 characters (%d)", SXLIMIT_MAX_FILENAME_LEN + 1, flen); quit_errmsg(414, msg_get_reason()); } } if (volume && strlen(volume) > SXLIMIT_MAX_VOLNAME_LEN) { msg_set_reason("Volume name too long: must be <= %d bytes", SXLIMIT_MAX_VOLNAME_LEN); quit_errmsg(414, msg_get_reason()); } if(!EVP_DigestInit(&body_ctx, EVP_sha1())) quit_errmsg(500, "Failed to initialize crypto engine"); HMAC_CTX_init(&hmac_ctx); authed = AUTH_NOTAUTH; role = PRIV_NONE; auth_begin(); if(has_priv(PRIV_CLUSTER) && sx_hashfs_uses_secure_proto(hashfs) != is_https() && !sx_storage_is_bare(hashfs)) { /* programmed nodes: must obey cluster SSL mode * unprogrammed nodes: can use SSL instead of non-SSL, * it is the cluster's responsibility to initiate programming via SSL, * as the unprogrammed node would accept both * * */ WARN("hashfs use-ssl: %d, https: %d, is_bare: %d", sx_hashfs_uses_secure_proto(hashfs), is_https(), sx_storage_is_bare(hashfs)); quit_errmsg(403, sx_hashfs_uses_secure_proto(hashfs) ? "Cluster operations require SECURE mode" : "Cluster operations require INSECURE mode"); } int dc = sx_hashfs_distcheck(hashfs); if(dc < 0) { CRIT("Failed to reload distribution"); /* MODHDIST: should die here */ } if(!volume) cluster_ops(); else if(!path) volume_ops(); else file_ops(); if(authed == AUTH_BODYCHECKING) WARN("FIXME: Security fail"); HMAC_CTX_cleanup(&hmac_ctx); EVP_MD_CTX_cleanup(&body_ctx); }
int is_http_10(void) { const char *proto = FCGX_GetParam("SERVER_PROTOCOL", envp); return strcmp(proto, "HTTP/1.0") == 0; }
int is_sky(void) { const char *param = FCGX_GetParam("HTTP_AUTHORIZATION", envp); return (param && strlen(param) == 4 + 56 && !strncmp(param, "SKY ", 4)); }
int main() { #ifdef PROFILE int i; #endif const char *config_url, *username, *password, *config_options; strtbl *options = NULL; int exit_status = 0; // install SIGUSR1, SIGPIPE, SIGTERM handler signal(SIGTERM, sig_handler); signal(SIGUSR1, sig_handler); signal(SIGPIPE, sig_handler); /* Provide a hook via an environment variable to define the config URL */ config_url = getenv(WO_CONFIG_URL); if (!config_url) { /* Flat file URL */ /* config_url = "file:///Local/Library/WebObjects/Configuration/WOConfig.xml"; */ /* Local wotaskd */ /* config_url = "http://localhost:1085"; */ /* Multicast URL */ config_url = CONFIG_URL; /* Actually "webobjects://239.128.14.2:1085"; */ } WOLog(WO_INFO,"<FastCGI> config url is %s", config_url); options = st_new(8); st_add(options, WOCONFIG, config_url, 0); /* * If your webserver is configured to pass these environment variables, we use them to * protect WOAdaptorInfo output. */ username = getenv(WO_ADAPTOR_INFO_USERNAME); if (username && strlen(username) != 0) { st_add(options, WOUSERNAME, username, 0); password = getenv(WO_ADAPTOR_INFO_PASSWORD); if(password && strlen(password) != 0) { st_add(options, WOPASSWORD, password, 0); } } config_options = getenv(WO_CONFIG_OPTIONS); if (config_options) st_add(options, WOOPTIONS, config_options, 0); /* * SECURITY ALERT * * To disable WOAdaptorInfo, uncomment the next line. * st_add(options, WOUSERNAME, "disabled", 0); * * To specify an WOAdaptorInfo username and password, uncomment the next two lines. * st_add(options, WOUSERNAME, "joe", 0); * st_add(options, WOPASSWORD, "secret", 0); * */ if (init_adaptor(options)) { WOLog( WO_ERR, "<FastCGI> Adaptor initialization failed."); exit(-1); } WOLog( WO_INFO,"<FastCGI> process started" ); while (!should_terminate) { HTTPRequest *req; HTTPResponse *resp = NULL; WOURLComponents wc = WOURLComponents_Initializer; const char *qs; unsigned int qs_len; char *url; const char *script_name, *path_info; const char *reqerr; WOURLError urlerr; FCGX_ParamArray hdrp_org; exit_status = FCGX_Accept(&in, &out, &err, &hdrp ); if ( exit_status < 0 ) { break; } #ifdef PROFILE for (i=0; i < 50000; i++) { #endif WOLog( WO_INFO,"<FastCGI> request accepted" ); #ifdef WIN32 _setmode(_fileno(stdout), _O_BINARY); _setmode(_fileno(stdin), _O_BINAR1Y); #endif script_name = FCGX_GetParam( CGI_SCRIPT_NAME, hdrp); path_info = FCGX_GetParam( CGI_PATH_INFO, hdrp); WOLog( WO_INFO,"<FastCGI> CGI_SCRIPT_NAME = %s", script_name ); WOLog( WO_INFO,"<FastCGI> CGI_PATH_INFO = %s", path_info ); if (script_name == NULL) { prepareAndSendErrorResponse(INV_SCRIPT, HTTP_NOT_FOUND); break; } else if (path_info == NULL) { path_info = "/"; } /* * extract WebObjects application name from URI */ url = WOMALLOC(strlen(path_info) + strlen(script_name) + 1); strcpy(url, script_name); strcat(url, path_info); WOLog(WO_INFO,"<FastCGI> new request: %s",url); urlerr = WOParseApplicationName(&wc, url); if (urlerr != WOURLOK) { const char *_urlerr; _urlerr = WOURLstrerror(urlerr); WOLog(WO_INFO,"<FastCGI> URL Parsing Error: %s", _urlerr); if (urlerr == WOURLInvalidApplicationName) { if (ac_authorizeAppListing(&wc)) { resp = WOAdaptorInfo(NULL, &wc); sendErrorResponse(resp); } else { prepareAndSendErrorResponse(_urlerr, HTTP_NOT_FOUND); } WOFREE(url); break; } prepareAndSendErrorResponse(_urlerr, HTTP_BAD_REQUEST); WOFREE(url); break; } /* * build the request... */ req = req_new( FCGX_GetParam("REQUEST_METHOD", hdrp), NULL); /* * validate the method */ reqerr = req_validateMethod(req); if (reqerr) { prepareAndSendErrorResponse(reqerr, HTTP_BAD_REQUEST); WOFREE(url); break; } /* * copy the headers. This looks wierd... all we're doing is copying * *every* environment variable into our headers. It may be beyond * the spec, but more information probably won't hurt. */ hdrp_org=hdrp; while (hdrp && *hdrp) { char *key, *value; /* copy env. line. */ key = WOSTRDUP(*hdrp); for (value = key; *value && !isspace((int)*value) && (*value != '='); value++) {} if (*value) { *value++ = '\0'; /* null terminate 'key' */ } while (*value && (isspace((int)*value) || (*value == '='))) { value++; } /* BEGIN Support for getting the client's certificate. */ if (strcmp((const char *)key, "SSL_CLIENT_CERTIFICATE") == 0 || strcmp((const char *)key, "SSL_SERVER_CERTIFICATE") == 0 ) { value = 0; WOLog(WO_INFO,"<FastCGI> DROPPING ENV VAR (DUPLICATE) = %s", key); } if (strcmp((const char *)key, "SSL_CLIENT_CERT") == 0 || strcmp((const char *)key, "SSL_SERVER_CERT") == 0) { value = make_cert_one_line(value); //WOLog(WO_INFO,"<FastCGI> PASSING %s = %s", key, value); } /* END Support for getting the client's certificate */ if (key && *key && value && *value) { /* must specify copy key and value because key translation might replace this key, and value lives in the same buffer */ req_addHeader(req, key, value, STR_COPYKEY|STR_COPYVALUE); } /* BEGIN Support for getting the client's certificate */ if (freeValueNeeded ) { free(value); freeValueNeeded=0; } /* END Support for getting the client's certificate */ WOFREE(key); hdrp++; /* next env variable */ } hdrp=hdrp_org; /* * get form data if any * assume that POSTs with content length will be reformatted to GETs later */ WOLog ( WO_INFO, "Getting request data, length: %d",req->content_length ); if (req->content_length > 0) { req_allocateContent(req, req->content_length, 1); req->getMoreContent = (req_getMoreContentCallback)readContentData; WOLog ( WO_INFO, "content_buffer_size: %d",req->content_buffer_size ); if (req->content_buffer_size == 0) { prepareAndSendErrorResponse(ALLOCATION_FAILURE, HTTP_SERVER_ERROR); WOFREE(url); break; } if (readContentData(req, req->content, req->content_buffer_size, 1) == -1) { prepareAndSendErrorResponse(WOURLstrerror(WOURLInvalidPostData), HTTP_BAD_REQUEST); WOFREE(url); break; } } /* Always get the query string */ qs = FCGX_GetParam("QUERY_STRING", hdrp); if (qs) { qs_len = strlen(qs); } else { qs_len = 0; } if (qs_len > 0) { wc.queryString.start = qs; wc.queryString.length = qs_len; WOLog(WO_INFO,"<FastCGI> new request with Query String: %s", qs); } /* * message the application & collect the response */ resp = tr_handleRequest(req, url, &wc, FCGX_GetParam(CGI_SERVER_PROTOCOL, hdrp), documentRoot()); if (resp != NULL) { sendResponse(resp); resp_free(resp); /* dump the response */ } WOFREE(url); req_free(req); #if defined(FINDLEAKS) showleaks(); #endif } #ifdef PROFILE } #endif st_free(options); WOLog( WO_INFO,"<FastCGI> process exiting" ); return exit_status; }
void handle_request(worker_type_t wtype) { const char *param, *p_method, *p_uri; char *argp; unsigned int plen; int cluster_readonly = 0, s2sreq = 0; if(sx_hashfs_cluster_get_mode(hashfs, &cluster_readonly)) { CRIT("Failed to get cluster operating mode"); quit_errmsg(500, "Internal error: failed to check cluster operating mode"); } if(sx_hashfs_distcheck(hashfs) < 0) { CRIT("Failed to reload distribution"); quit_errmsg(503, "Internal error: failed to load distribution"); } if(sx_hashfs_is_orphan(hashfs)) quit_errmsg(410, "This node is no longer a cluster member"); msg_new_id(); verb = VERB_UNSUP; p_method = FCGX_GetParam("REQUEST_METHOD", envp); if(p_method) { plen = strlen(p_method); switch(plen) { case 3: if(!memcmp(p_method, "GET", 4)) verb = VERB_GET; else if(!memcmp(p_method, "PUT", 4)) verb = VERB_PUT; break; case 4: if(!memcmp(p_method, "HEAD", 5)) verb = VERB_HEAD; else if(!memcmp(p_method, "POST", 5)) verb = VERB_POST; break; case 6: if(!memcmp(p_method, "DELETE", 7)) verb = VERB_DELETE; break; case 7: if(!memcmp(p_method, "OPTIONS", 8)) { CGI_PUTS("Allow: GET,HEAD,OPTIONS,PUT,DELETE\r\nContent-Length: 0\r\n\r\n"); return; } break; } } if(verb == VERB_UNSUP) quit_errmsg(405, "Method Not Allowed"); if(content_len()<0 || (verb != VERB_PUT && content_len())) quit_errmsg(400, "Invalid Content-Length: must be positive and method must be PUT"); p_uri = param = FCGX_GetParam("REQUEST_URI", envp); if(!p_uri) quit_errmsg(400, "No URI provided"); plen = strlen(p_uri); if(*p_uri != '/') quit_errmsg(400, "URI must start with /"); if(plen > sizeof(reqbuf) - 1) quit_errmsg(414, "URL too long: request line must be <8k"); do { param++; plen--; } while(*param == '/'); if(!strncmp(param, ".s2s/", lenof(".s2s/"))) { param += lenof(".s2s/"); plen -= lenof(".s2s/"); while(*param == '/') { param++; plen--; } s2sreq = 1; } if(wtype == WORKER_S2S && !s2sreq) WARN("Misconfiguration detected. Please make sure your restricted-socket config option is properly set."); /* FIXME: we could detect the opposite kind of mismatch * at the cost of extra complications in the wtype definition * I prefer to privilege simplicity at this point */ memcpy(reqbuf, param, plen+1); argp = memchr(reqbuf, '?', plen); nargs = 0; if(argp) { unsigned int argslen = plen - (argp - reqbuf); plen = argp - reqbuf; do { *argp = '\0'; argp++; argslen--; } while(*argp == '?'); if(!argslen) argp = NULL; else { do { char *nextarg; if(nargs >= MAX_ARGS) quit_errmsg(414, "Too many parameters"); nextarg = memchr(argp, '&', argslen); if(nextarg) { do { *nextarg = '\0'; nextarg++; } while(*nextarg == '&'); } if(*argp) { if(!(args[nargs] = inplace_urldecode(argp, 0, 0, NULL, 1))) quit_errmsg(400, "Invalid URL encoding"); if(sxi_utf8_validate_len(args[nargs]) < 0) quit_errmsg(400, "Parameters with invalid utf-8 encoding"); nargs++; } argslen -= nextarg - argp; argp = nextarg; } while (argp); } } while(plen && reqbuf[plen-1] == '/') { plen--; reqbuf[plen] = '\0'; } path = memchr(reqbuf, '/', plen); if(path) { do { *path = '\0'; path ++; } while(*path == '/'); if(!*path) path = NULL; } volume = *reqbuf ? reqbuf : NULL; int forbidden = 0; if((volume && !inplace_urldecode(volume, '/', 0, &forbidden, 0)) || (path && !inplace_urldecode(path, '/', '/', &forbidden, 0))) { if (forbidden) quit_errmsg(400, "Volume or path with forbidden %2f or %00"); else quit_errmsg(400, "Invalid URL encoding"); } int vlen = volume ? sxi_utf8_validate_len(volume) : 0; int flen = path ? strlen(path) : 0; if (vlen < 0 || flen < 0) quit_errmsg(400, "URL with invalid utf-8 encoding"); if (is_reserved()) { /* No UTF8/url-encoding used on reserved volumes, allow higher limit. * Otherwise we hit the 1024 limit with batch requests already */ if (path && strlen(path) > SXLIMIT_MAX_FILENAME_LEN * 3) { msg_set_reason("Path too long: filename must be <%d bytes (%ld)", SXLIMIT_MAX_FILENAME_LEN*3+ 1, strlen(path)); quit_errmsg(414, msg_get_reason()); } } else { if (flen > SXLIMIT_MAX_FILENAME_LEN) { msg_set_reason("Path too long: filename must be <%d bytes (%d)", SXLIMIT_MAX_FILENAME_LEN + 1, flen); quit_errmsg(414, msg_get_reason()); } } if (volume && strlen(volume) > SXLIMIT_MAX_VOLNAME_LEN) { msg_set_reason("Volume name too long: must be <= %d bytes", SXLIMIT_MAX_VOLNAME_LEN); quit_errmsg(414, msg_get_reason()); } body_ctx = sxi_md_init(); if (!body_ctx || !sxi_sha1_init(body_ctx)) quit_errmsg(500, "Failed to initialize crypto engine"); hmac_ctx = sxi_hmac_sha1_init(); if (!hmac_ctx) quit_errmsg(503, "Cannot initialize crypto library"); authed = AUTH_NOTAUTH; role = PRIV_NONE; /* Begin auth check */ uint8_t buf[AUTHTOK_BIN_LEN], key[AUTH_KEY_LEN]; unsigned int blen = sizeof(buf); time_t reqdate, now; param = FCGX_GetParam("HTTP_AUTHORIZATION", envp); if(!param || strlen(param) != lenof("SKY ") + AUTHTOK_ASCII_LEN || strncmp(param, "SKY ", 4)) { if(volume) { send_authreq(); return; } quit_home(); } if(sxi_b64_dec_core(param+4, buf, &blen) || blen != sizeof(buf)) { send_authreq(); return; } memcpy(user, buf, sizeof(user)); memcpy(rhmac, buf+20, sizeof(rhmac)); if(sx_hashfs_get_user_info(hashfs, user, &uid, key, &role, NULL, &user_quota) != OK) /* no such user */ { DEBUG("No such user: %s", param+4); send_authreq(); return; } DEBUG("Request from uid %lld", (long long)uid); if(cluster_readonly && (verb == VERB_PUT || verb == VERB_DELETE) && !has_priv(PRIV_CLUSTER) && !has_priv(PRIV_ADMIN)) quit_errmsg(503, "Cluster is in read-only mode"); if(s2sreq && !has_priv(PRIV_CLUSTER)) { send_authreq(); return; } if(!sxi_hmac_sha1_init_ex(hmac_ctx, key, sizeof(key))) { WARN("hmac_init failed"); quit_errmsg(500, "Failed to initialize crypto engine"); } if(!sxi_hmac_sha1_update_str(hmac_ctx, p_method)) quit_errmsg(500, "Crypto error authenticating the request"); if(!sxi_hmac_sha1_update_str(hmac_ctx, p_uri+1)) quit_errmsg(500, "Crypto error authenticating the request"); param = FCGX_GetParam("HTTP_DATE", envp); if(!param) quit_errmsg(400, "Missing Date: header"); if(httpdate_to_time_t(param, &reqdate)) quit_errmsg(400, "Date header in wrong format"); now = time(NULL); if(reqdate < now - MAX_CLOCK_DRIFT * 60 || reqdate > now + MAX_CLOCK_DRIFT * 60) { CGI_PUTS("WWW-Authenticate: SKY realm=\"SXCLOCK\"\r\n"); quit_errmsg(401, "Client clock drifted more than "STRIFY(MAX_CLOCK_DRIFT)" minutes"); } if(!sxi_hmac_sha1_update_str(hmac_ctx, param)) quit_errmsg(500, "Crypto error authenticating the request"); if(!content_len()) { /* If no body is present, complete authentication now */ uint8_t chmac[20]; unsigned int chmac_len = 20; if(!sxi_hmac_sha1_update_str(hmac_ctx, "da39a3ee5e6b4b0d3255bfef95601890afd80709")) quit_errmsg(500, "Crypto error authenticating the request"); if(!sxi_hmac_sha1_final(hmac_ctx, chmac, &chmac_len)) quit_errmsg(500, "Crypto error authenticating the request"); if(!hmac_compare(chmac, rhmac, sizeof(rhmac))) { authed = AUTH_OK; } else { /* WARN("auth mismatch"); */ send_authreq(); return; } } else /* Otherwise set it as pending */ authed = AUTH_BODYCHECK; if(has_priv(PRIV_CLUSTER) && sx_hashfs_uses_secure_proto(hashfs) != is_https() && !sx_storage_is_bare(hashfs)) { /* programmed nodes: must obey cluster SSL mode * unprogrammed nodes: can use SSL instead of non-SSL, * it is the cluster's responsibility to initiate programming via SSL, * as the unprogrammed node would accept both * * */ WARN("hashfs use-ssl: %d, https: %d, is_bare: %d", sx_hashfs_uses_secure_proto(hashfs), is_https(), sx_storage_is_bare(hashfs)); quit_errmsg(403, sx_hashfs_uses_secure_proto(hashfs) ? "Cluster operations require SECURE mode" : "Cluster operations require INSECURE mode"); } if(!volume) cluster_ops(); else if(!path) volume_ops(); else file_ops(); if(authed == AUTH_BODYCHECKING) DEBUG("Bad request signature"); sxi_hmac_sha1_cleanup(&hmac_ctx); sxi_md_cleanup(&body_ctx); }