int register_database_type(pblock *pb, Session *sn, Request *rq) { char *dbtype_str = pblock_findval(ACL_ATTR_DBTYPE, pb); char *parseFuncStr = pblock_findval(ACL_ATTR_PARSEFN, pb); ACLDbType_t dbtype = ACL_DBTYPE_INVALID; DbParseFn_t parseFunc; char err[BIG_LINE]; NSErr_t *errp = 0; if (!dbtype_str || !*dbtype_str) { pblock_nvinsert("error", "dbtype is missing", pb); return REQ_ABORTED; } if (!parseFuncStr) { pblock_nvinsert("error", "parse function is missing", pb); return REQ_ABORTED; } parseFunc = (DbParseFn_t)func_find(parseFuncStr); if (!parseFunc) { sprintf(err, "Could map \"%s\" to a function", parseFunc); pblock_nvinsert("error", err, pb); return REQ_ABORTED; } ACL_REG(ACL_DbTypeRegister(errp, dbtype_str, parseFunc, &dbtype), "Failed to register database type \"%s\"", dbtype_str); return REQ_PROCEED; }
static int process_new_notification(pblock *param, Session *sn, Request *rq, void* agent_config) { handle_notification(sn, rq, agent_config); /* Use the protocol_status function to set the status of the * response before calling protocol_start_response. */ protocol_status(sn, rq, PROTOCOL_OK, NULL); /* Although we would expect the ObjectType stage to * set the content-type, set it here just to be * completely sure that it gets set to text/html. */ param_free(pblock_remove("content-type", rq->srvhdrs)); pblock_nvinsert("content-type", "text/html", rq->srvhdrs); pblock_nvinsert("content-length", "2", rq->srvhdrs); /* Send the headers to the client*/ protocol_start_response(sn, rq); /* Write the output using net_write*/ if (IO_ERROR == net_write(sn->csd, "OK", 2)) { return REQ_EXIT; } return REQ_PROCEED; }
int register_database_name(pblock *pb, Session *sn, Request *rq) { char *dbtype_str = pblock_findval(ACL_ATTR_DBTYPE, pb); char *dbname = pblock_findval(ACL_ATTR_DBNAME, pb); char *url = pblock_findval(ACL_ATTR_DATABASE_URL, pb); ACLDbType_t dbtype = ACL_DBTYPE_INVALID; NSErr_t *errp = 0; PList_t plist = PListCreate(NULL, ACL_ATTR_INDEX_MAX, NULL, NULL); if (!dbtype_str || !*dbtype_str) { pblock_nvinsert("error", "dbtype is missing", pb); return REQ_ABORTED; } if (!dbname || !*dbname) { pblock_nvinsert("error", "database name is missing", pb); return REQ_ABORTED; } if (!url || !*url) { pblock_nvinsert("error", "database url is missing", pb); return REQ_ABORTED; } ACL_REG(ACL_DbTypeFind(errp, dbtype_str, &dbtype), "Database type \"%s\" is not registered", dbtype_str); ACL_REG(ACL_DatabaseRegister(errp, dbtype, dbname, url, plist), "Failed to register database \"%s\"", dbname); return REQ_PROCEED; }
int send_data(const char *msg, Session *sn, Request *rq) { int len = msg != NULL?strlen(msg):0; int retVal = REQ_ABORTED; if(len > 0) { char buf[50]; buf[0] = '\0'; sprintf(buf, "%d", len); protocol_status(sn, rq, PROTOCOL_OK, NULL); param_free(pblock_remove("content-type", rq->srvhdrs)); pblock_nvinsert("content-type", "text/html", rq->srvhdrs); pblock_nvinsert("content-length", buf, rq->srvhdrs); /* Send the headers to the client*/ protocol_start_response(sn, rq); /* Write the output using net_write*/ if (IO_ERROR == net_write(sn->csd, (char *)msg, len)) { retVal = REQ_EXIT; } else { retVal = net_flush(sn->csd); } } return retVal; }
/** ************************************************************************** * Optional init. Can be used to set non-default value to purge_timeout. * Registered in netsite/lib/frame/httpd-fn.cpp * See: http://docs.sun.com/source/817-1835-10/npgmysaf.html#wp15421 * * magnus.conf: * Init fn="init-request-limits" timeout="300" * */ int init_request_limits(pblock *pb, Session *sn, Request *rq) { char * param = pblock_findval(PURGE_TIMEOUT, pb); if (reqlimit_crit == NULL || hashtable == NULL) { // "should never happen" pblock_nvinsert("error", "internal error", pb); return REQ_ABORTED; } if (!param) { pblock_nvinsert("error", XP_GetAdminStr(DBT_reqlimitNoTimeout), pb); return REQ_ABORTED; } purge_timeout = atoi(param); if (purge_timeout) { next_timeout = time(NULL) + purge_timeout; log_error(LOG_VERBOSE, "init-request-limits", sn, rq, "purge timeout set to %ds", purge_timeout); } else { log_error(LOG_VERBOSE, "init-request-limits", sn, rq, "purge timeout disabled."); } return REQ_PROCEED; }
/** * This function is used for sending a 302 redirect in the browser. */ static void do_url_redirect(Session *sn, Request *rq, char* redirect_url) { /* Set the return code to 302 Redirect */ protocol_status(sn, rq, PROTOCOL_REDIRECT, NULL); /* set the new URL to redirect */ pblock_nvinsert("escape", "no", rq->vars); param_free(pblock_remove("Location", rq->srvhdrs)); pblock_nvinsert("Location", redirect_url, rq->srvhdrs); protocol_start_response(sn, rq); }
static inline void otype_ciadd(const char *c, pblock *srvhdrs, const char *name) { if (c) { if (!pblock_find(name, srvhdrs)) pblock_nvinsert(name, c, srvhdrs); } }
int otype_shtmlhacks(pblock *pb, Session *sn, Request *rq) { char *path = pblock_findval("path", rq->vars); char *do_exec = pblock_findval("exec-hack", pb); int l; /* This is cachable- we always do the same thing based SOLELY * on the URI... */ rq->directive_is_cacheable = 1; l = strlen(path); if((!strcasecmp(&path[l-4],".htm")) || (!strcasecmp(&path[l-5],".html"))) { #ifdef XP_UNIX if(do_exec) { struct stat *fi = request_stat_path(NULL, rq); if(fi && (!(fi->st_mode & S_IXUSR))) return REQ_NOACTION; } #endif /* XP_UNIX */ param_free(pblock_remove("content-type", rq->srvhdrs)); pblock_nvinsert("content-type", "magnus-internal/parsed-html", rq->srvhdrs); return REQ_PROCEED; } return REQ_NOACTION; }
static int sendResponse(Session *sn, Request *rq, HTTPResponse *resp) { pb_param *pb_entry; /* * collect up the headers */ pb_entry = pblock_remove(CONTENT_TYPE,rq->srvhdrs); /* remove default */ param_free(pb_entry); /* aB. Need to free parameters we remove from pblocks !!! */ st_perform(resp->headers,gethdr,rq); /* * ensure a content length */ if (pblock_findval(CONTENT_LENGTH, rq->srvhdrs) == NULL) { char length[64]; util_itoa(resp->content_length,length); pblock_nvinsert(CONTENT_LENGTH,length, rq->srvhdrs); } protocol_status(sn, rq, resp->status, resp->statusMsg); if (protocol_start_response(sn, rq) == REQ_NOACTION) { WOLog(WO_ERR,"protocol_start_response() returned REQ_NOACTION (!?)"); return REQ_PROCEED; } if (resp->content_length) if (net_write(sn->csd, resp->content, resp->content_length) == IO_ERROR) { WOLog(WO_ERR,"Failed to send content to client"); return REQ_EXIT; } return REQ_PROCEED; }
/* cache_service_debug() * To force the creation of good debugging tools, all known caches must * have a debugging routine. The cache_service_debug() routine is a common * routine that can be inserted via NSAPI to view the status of all * known caches. This is a hidden entry point which can be enabled when * debugging is needed. * */ NSAPI_PUBLIC int cache_service_debug(pblock *pb, Session *sn, Request *rq) { cache_t *ptr; char buf[MAX_DEBUG_LINE]; int len; NS_ASSERT(cache_crit); param_free(pblock_removekey(pb_key_content_type, rq->srvhdrs)); pblock_nvinsert("content-type", "text/html", rq->srvhdrs); len = util_sprintf(buf, XP_GetClientStr(DBT_http10200OkNcontentTypeTextHtmlN_)); net_write(sn->csd, buf, len); len = util_sprintf(buf, XP_GetClientStr(DBT_H2NetscapeCacheStatusReportH2N_)); net_write(sn->csd, buf, len); crit_enter(cache_crit); if (cache_list) { len = util_sprintf(buf, "<HR>"); net_write(sn->csd, buf, len); for (ptr = cache_list; ptr; ptr = ptr->next) { if (ptr->virtual_fn->debug_fn) if ( ptr->virtual_fn->debug_fn(pb, sn, rq) == REQ_ABORTED ) return REQ_ABORTED; } } else { len = util_sprintf(buf, XP_GetClientStr(DBT_noCachesOnSystemP_)); net_write(sn->csd, buf, len); } crit_exit(cache_crit); return REQ_PROCEED; }
/* Sets "Link" header, if content manager is on */ NSAPI_PUBLIC void CM_set_link_header(Request *rq) { char link[CM_BUFF_LEN]; char *uri; if ( !CM_get_status() ) /* if cm is off. don't do anything */ return; uri = pblock_findkeyval(pb_key_uri, rq->reqpb); /* e.g. Link: <http://www.glyphica.com/index.html?services>; rel="services" */ if (pervs_vars()->Vsecurity_active) { if (pervs_vars()->Vport == 443) util_snprintf(link, CM_BUFF_LEN, "<https://%s%s?%s>; rel=\"%s\"", pervs_vars()->Vserver_hostname, uri, CM_SERVICES_NS,CM_SERVICES_NS ); else util_snprintf(link, CM_BUFF_LEN, "<https://%s:%d%s?%s>; rel=\"%s\"", pervs_vars()->Vserver_hostname, pervs_vars()->Vport, uri, CM_SERVICES_NS,CM_SERVICES_NS ); } else { if (pervs_vars()->Vport == 80) util_snprintf( link, CM_BUFF_LEN, "<http://%s%s?%s>; rel=\"%s\"", pervs_vars()->Vserver_hostname, uri, CM_SERVICES_NS,CM_SERVICES_NS ); else util_snprintf( link, CM_BUFF_LEN, "<http://%s:%d%s?%s>; rel=\"%s\"", pervs_vars()->Vserver_hostname, pervs_vars()->Vport, uri, CM_SERVICES_NS,CM_SERVICES_NS ); } pblock_nvinsert("Link", link, rq->srvhdrs); }
static inline void otype_add(pblock *pb, const pb_key *config, pblock *srvhdrs, const char *header) { char *value = pblock_findkeyval(config, pb); if (value) { if (!pblock_find(header, srvhdrs)) pblock_nvinsert(header, value, srvhdrs); } }
int service_dumpstats(pblock *pb, Session *sn, Request *rq) { char *refresh, *refresh_val = NULL; /* See if client asked for automatic refresh in query string */ if ((refresh = pblock_findval("query", rq->reqpb)) != NULL ) { if (!strncmp("refresh", refresh, 7)) { refresh_val = strchr(refresh, '='); if (refresh_val) refresh_val++; } } param_free(pblock_remove("content-type", rq->srvhdrs)); pblock_nvinsert("content-type", "text/plain", rq->srvhdrs); if (refresh_val) pblock_nvinsert("refresh", refresh_val, rq->srvhdrs); httpfilter_buffer_output(sn, rq, PR_TRUE); protocol_status(sn, rq, PROTOCOL_OK, NULL); protocol_start_response(sn,rq); PR_fprintf(sn->csd, PRODUCT_DAEMON_BIN" pid: %d\n", getpid()); StatsHeaderNode *hdr = StatsManager::getHeader(); if (!hdr) { PR_fprintf(sn->csd, "\nStatistics disabled\n"); return REQ_PROCEED; } int rv = REQ_PROCEED; #ifdef XP_WIN32 rv = write_stats_dump(sn->csd, hdr); #else if (hdr && (hdr->hdrStats.maxProcs == 1)) { rv = write_stats_dump(sn->csd, hdr); } else { StatsManager::serviceDumpStats(sn->csd, NULL); } #endif return rv; }
NSAPI_PUBLIC PRBool conf_setGlobal(char *name, char *value) { pblock *globals = conf_get_true_globals()->genericGlobals; char *d = _lowercase(name); if (pblock_find(d, globals)) { // Mark directive as multiply defined pblock_nvinsert(d, name, globalsMultiplyDefined); param_free(pblock_remove(d, globals)); } else { // Mark directive as unaccessed pblock_nvinsert(d, name, globalsUnaccessed); } PRBool rv = (pblock_nvinsert(d, value, globals) != NULL); FREE(d); return rv; }
/** * Migrate response status and headers from the subrequest to the * HttpServletResponse. */ static inline void j2eefilter_migrate_response(Request* sub_rq, J2EEFilterContext* context) { if (context->forward) { if (sub_rq != context->parent_rq && !context->parent_rq->senthdrs) { // Pass status_num to HttpServletResponse.setStatus // XXX In NSAPI, SAFs always set the status code, even on success. // In Java land, however, Servlets only explicitly set the status // code for non-200 responses. To preserve the original error code // on <error-page> RequestDispatcher.forward calls, never call // HttpServletResponse.setStatus(200). if (sub_rq->status_num != 0 && sub_rq->status_num != 200) { context->env->CallVoidMethod(context->response, _response_setStatus, sub_rq->status_num); j2eefilter_store_throwable(context); } // Pass the contents of srvhdrs to the HttpServletResponse pblock *seen = pblock_create(PARAMETER_HASH_SIZE); for (int i = 0; i < sub_rq->srvhdrs->hsize; i++) { for (pb_entry *p = sub_rq->srvhdrs->ht[i]; p; p = p->next) { // The NSAPI status code is stored in rq->srvhdrs but // shouldn't be passed to the HttpServletResponse if (!strcmp(p->param->name, "status")) continue; jstring jname = context->env->NewStringUTF(p->param->name); j2eefilter_store_throwable(context); jstring jvalue = context->env->NewStringUTF(p->param->value); j2eefilter_store_throwable(context); // Call setHeader for the first occurrence of a given name // and addHeader for each subsequent occurrence if (pblock_findval(p->param->name, seen)) { context->env->CallVoidMethod(context->response, _response_addHeader, jname, jvalue); } else { pblock_nvinsert(p->param->name, "1", seen); context->env->CallVoidMethod(context->response, _response_setHeader, jname, jvalue); } j2eefilter_store_throwable(context); if (jname != NULL) context->env->DeleteLocalRef(jname); if (jvalue != NULL) context->env->DeleteLocalRef(jvalue); } } pblock_free(seen); } context->forward = PR_FALSE; } }
static am_status_t set_cookie(const char *header, void **args) { am_status_t ret = AM_INVALID_ARGUMENT; if (header != NULL && args !=NULL) { Request *rq = (Request *)args[0]; if (rq == NULL) { am_web_log_error("in set_cookie: Invalid Request structure"); } else { pblock_nvinsert("set-cookie", header, rq->srvhdrs); ret = AM_SUCCESS; } } return ret; }
/* * NameTrans: * * format of obj.conf is: * NameTrans from="some-dir" fn=WebObjectsNameTrans dir="app-dir" name="obj-name" * * If 'some-dir' is found in the URI, then set the request's WebObjects * application root to 'app-dir' and let the WebObjects object process * the request. * */ NSAPI_PUBLIC int WebObjectsNameTrans(pblock *pb, Session *sn, Request *rq) { WOURLComponents wc; const char *from; const char *objName; const char *uripath; const char *approot; if (!adaptorEnabled) return REQ_NOACTION; dump_pb(pb,"nametrans.pb"); /* spew debug info */ dump_pb(rq->vars,"nametrans.rq->vars"); /* spew debug info */ from = pblock_findval(PATHTRANS,pb); uripath = pblock_findval("ppath",rq->vars); objName = pblock_findval(OBJECTNAME,pb); if ((from == NULL) || (uripath == NULL) || (objName == NULL)) return REQ_NOACTION; if (strncmp(from,uripath,strlen(from)) == 0) { /* * make sure this is a valid WebObjects(tm) URL */ wc = WOURLComponents_Initializer; if (WOParseApplicationName(&wc, uripath) != WOURLOK) /* bail now if something wierd */ return REQ_NOACTION; pblock_nvinsert(OBJECTNAME,(char *)objName,rq->vars); approot = pblock_findval(APPROOT,pb); if (approot) pblock_nvinsert(APPROOT,(char *)approot,rq->vars); return REQ_PROCEED; } else return REQ_NOACTION; }
char * get_post_assertion_data(Session *sn, Request *rq, char *url) { int i = 0; char *body = NULL; int cl = 0; char *cl_str = NULL; /** * content length and body * * note: memory allocated in here should be released by * other function such as: "policy_unregister_post" */ request_header("content-length", &cl_str, sn, rq); if(cl_str == NULL) cl_str = pblock_findval("content-length", rq->headers); if(cl_str == NULL) return body; if(PR_sscanf(cl_str, "%ld", &cl) == 1) { body = (char *)malloc(cl + 1); if(body != NULL){ for (i = 0; i < cl; i++) { int ch = netbuf_getc(sn->inbuf); if (ch==IO_ERROR || ch == IO_EOF) { break; } body[i] = ch; } body[i] = '\0'; } } else { am_web_log_error("Error reading POST content body"); } am_web_log_max_debug("Read POST content body : %s", body); /** * need to reset content length before redirect, * otherwise, web server will wait for serveral minutes * for non existant data */ param_free(pblock_remove("content-length", rq->headers)); pblock_nvinsert("content-length", "0", rq->headers); return body; }
int service_reconfig(pblock *pb, Session *sn, Request *rq) { param_free(pblock_remove("content-type", rq->srvhdrs)); pblock_nvinsert("content-type", "text/html", rq->srvhdrs); protocol_status(sn, rq, PROTOCOL_OK, NULL); protocol_start_response(sn, rq); PR_fprintf(sn->csd, "<html><head><title>" "Dynamic Reconfiguration" "</title></head><body>\n" "<H2>Dynamic Reconfiguration</H2>\n" "<p>pid: %d</p>\n", getpid()); // Asynchronous reconfiguration WebServer::RequestReconfiguration(); PR_fprintf(sn->csd, "</body></html>"); return REQ_PROCEED; }
static int do_redirect(Session *sn, Request *rq, am_status_t status, am_policy_result_t *policy_result, const char *original_url, const char* method, void* agent_config) { int retVal = REQ_ABORTED; char *redirect_url = NULL; const am_map_t advice_map = policy_result->advice_map; am_status_t ret = AM_SUCCESS; ret = am_web_get_url_to_redirect(status, advice_map, original_url, method, AM_RESERVED, &redirect_url, agent_config); if (ret == AM_SUCCESS && redirect_url != NULL) { char *advice_txt = NULL; if (B_FALSE == am_web_use_redirect_for_advice(agent_config) && policy_result->advice_string != NULL) { // Composite advice is sent as a POST ret = am_web_build_advice_response(policy_result, redirect_url, &advice_txt); am_web_log_debug("do_redirect(): policy status=%s,", "response[%s]", am_status_to_string(status), advice_txt); if (ret == AM_SUCCESS) { retVal = send_data(advice_txt, sn, rq); } else { am_web_log_error("do_redirect(): Error while building " "advice response body:%s", am_status_to_string(ret)); retVal = REQ_EXIT; } } else { // No composite advice or composite advice is redirected am_web_log_debug("do_redirect() policy status = %s, ", "redirection URL is %s", am_status_to_string(status), redirect_url); // we need to modify the redirect_url with the policy advice if (B_TRUE == am_web_use_redirect_for_advice(agent_config) && policy_result->advice_string != NULL) { char *redirect_url_with_advice = NULL; ret = am_web_build_advice_redirect_url(policy_result, redirect_url, &redirect_url_with_advice); if (ret == AM_SUCCESS) { redirect_url = redirect_url_with_advice; am_web_log_debug("do_redirect(): policy status=%s, " "redirect url with advice [%s]", am_status_to_string(status), redirect_url); } else { am_web_log_error("do_redirect(): Error while building " "the redirect url with advice:%s", am_status_to_string(ret)); } } /* redirection is enabled by the PathCheck directive */ /* Set the return code to 302 Redirect */ protocol_status(sn, rq, PROTOCOL_REDIRECT, NULL); /* set the new URL to redirect */ //pblock_nvinsert("url", redirect_url, rq->vars); pblock_nvinsert("escape", "no", rq->vars); param_free(pblock_remove("Location", rq->srvhdrs)); pblock_nvinsert("Location", redirect_url, rq->srvhdrs); protocol_start_response(sn, rq); am_web_free_memory(redirect_url); } } else if (ret == AM_NO_MEMORY) { /* Set the return code 500 Internal Server Error. */ protocol_status(sn, rq, PROTOCOL_SERVER_ERROR, NULL); am_web_log_error("do_redirect() Status code= %s.", am_status_to_string(status)); } else { /* Set the return code 403 Forbidden */ protocol_status(sn, rq, PROTOCOL_FORBIDDEN, NULL); am_web_log_info("do_redirect() Status code= %s.", am_status_to_string(status)); } return retVal; }
int register_attribute_getter (pblock *pb, Session *sn, Request *rq) { char *method_str = pblock_findval(ACL_ATTR_METHOD, pb); char *attr = pblock_findval(ACL_ATTR_ATTRIBUTE, pb); char *funcStr = pblock_findval(ACL_ATTR_GETTERFN, pb); char *dbtype_str = pblock_findval(ACL_ATTR_DBTYPE, pb); char *position_str = pblock_findval(ACL_ATTR_POSITION, pb); ACLDbType_t dbtype = ACL_DBTYPE_ANY; ACLMethod_t method = ACL_METHOD_ANY; ACLAttrGetterFn_t func; char err[BIG_LINE]; NSErr_t *errp = 0; int position = ACL_AT_END; if (method_str) { ACL_REG(ACL_MethodFind(errp, method_str, &method), "Method \"%s\" is not registered", method_str); } if (dbtype_str) { ACL_REG(ACL_DbTypeFind(errp, dbtype_str, &dbtype), "Database type \"%s\" is not registered", dbtype_str); } if (!attr || !*attr) { pblock_nvinsert("error", "Attribute name is missing", pb); return REQ_ABORTED; } if (!funcStr || !*funcStr) { pblock_nvinsert("error", "Attribute getter function name is missing", pb); return REQ_ABORTED; } if (!position_str) { if (!strcmp(position_str, "ACL_AT_FRONT")) position = ACL_AT_FRONT; else if (!strcmp(position_str, "ACL_AT_END")) position = ACL_AT_END; else if (!strcmp(position_str, "ACL_REPLACE_ALL")) position = ACL_REPLACE_ALL; else if (!strcmp(position_str, "ACL_REPLACE_MATCHING")) position = ACL_REPLACE_MATCHING; else { sprintf(err, "Position attribute \"%s\" is not valid", position_str); pblock_nvinsert("error", err, pb); return REQ_ABORTED; } } func = (ACLAttrGetterFn_t)func_find((char *)funcStr); if (!func) { sprintf(err, "Could not map \"%s\" to a function", funcStr); pblock_nvinsert("error", err, pb); return REQ_ABORTED; } ACL_REG(ACL_AttrGetterRegister(errp, attr, func, method, dbtype, position, NULL), "Failed to register attribute getter for %s", attr); return REQ_PROCEED; }
/* * callback - copy headers into rq */ static void gethdr(const char *key, const char *value, void *rq) { pblock_nvinsert((char *)key, (char *)value, ((Request *)rq)->srvhdrs); }
PRStatus FcgiParser::parseHttpHeader(CircularBuffer& to) { if(!waitingForDataParse) return PR_SUCCESS; const char *data = httpHeader.data(); int len = httpHeader.length(); PRUint8 flag = 0; while(len-- && flag < 2) { switch(*data) { case '\r': break; case '\n': flag++; break; default: flag = 0; break; } data++; } /* * Return (to be called later when we have more data) */ if(flag < 2) return PR_SUCCESS; waitingForDataParse = PR_FALSE; Request *rq = request->getOrigRequest(); pblock *authpb = NULL; if(fcgiRole == FCGI_AUTHORIZER) { authpb = pblock_create(rq->srvhdrs->hsize); } register int x ,y; register char c; int nh; char t[REQ_MAX_LINE]; PRBool headerEnd = PR_FALSE; char* statusHeader = pblock_findval("status", rq->srvhdrs); char *next = const_cast<char *>(httpHeader.data()); nh = 0; x = 0; y = -1; for(; !headerEnd;) { c = *(next++); switch(c) { case CR: // Silently ignore CRs break; case LF: if (x == 0) { headerEnd = PR_TRUE; break; } t[x] = '\0'; if(y == -1) { request->log(LOG_FAILURE, "name without value: got line \"%s\"", t); return PR_FAILURE; } while(t[y] && isspace(t[y])) ++y; // Do not change the status header to 200 if it was already set // This would happen only if it were a cgi error handler // and so the status had been already set on the request // originally if (!statusHeader || // If we don't already have a Status: header PL_strcmp(t, "status") || // or this isn't a Status: header PL_strncmp(&t[y], "200", 3)) // or this isn't "Status: 200" { if(!PL_strcmp(t, "content-type")) { pb_param* pParam = pblock_remove ( "content-type", rq->srvhdrs ); if ( pParam ) param_free ( pParam ); } if(fcgiRole == FCGI_AUTHORIZER) { pblock_nvinsert(t, &t[y], authpb); } else { pblock_nvinsert(t, &t[y], rq->srvhdrs); } // !FCGI_AUTHORIZER } x = 0; y = -1; ++nh; break; case ':': if(y == -1) { y = x+1; c = '\0'; } default: t[x++] = ((y == -1) && isupper(c) ? tolower(c) : c); } } // for if(fcgiRole == FCGI_AUTHORIZER) { if(parseAuthHeaders(authpb) != PR_SUCCESS) { pblock_free(authpb); return PR_FAILURE; } pblock_copy(authpb, rq->srvhdrs); pblock_free(authpb); } else { /* * We're done scanning the FCGI script's header output. Now * we have to write to the client: status, FCGI header, and * any over-read FCGI output. */ char *s; char *l = pblock_findval("location", rq->srvhdrs); if((s = pblock_findval("status", rq->srvhdrs))) { if((strlen(s) < 3) || (!isdigit(s[0]) || (!isdigit(s[1])) || (!isdigit(s[2])))) { s = NULL; } else { char ch = s[3]; s[3] = '\0'; int statusNum = atoi(s); s[3] = ch; rq->status_num = statusNum; } } if(!s) { if (l) pblock_nvinsert("url", l, rq->vars); protocol_status(request->getOrigSession(), request->getOrigRequest(), (l ? PROTOCOL_REDIRECT : PROTOCOL_OK), NULL); } } len = next - httpHeader.data(); len = httpHeader.length() - len; if(len < 0) return PR_FAILURE; /* * Only send the body for methods other than HEAD. */ if(!request->isHead()) { if(len > 0) { if(to.addData(next, len) != len) return PR_FAILURE; } } next = NULL; return PR_SUCCESS; }
PRStatus FcgiParser::parseAuthHeaders(pblock *pb) { Request *rq = request->getOrigRequest(); authHeaderPrefixLen = strlen(AUTH_HEADER_PREFIX); char *s; if(pb) { if((s = pblock_findval("status", pb))) { if((strlen(s) < 3) || (!isdigit(s[0]) || (!isdigit(s[1])) || (!isdigit(s[2])))) { s = NULL; } else { char ch = s[3]; s[3] = '\0'; int statusNum = atoi(s); s[3] = ch; rq->status_num = statusNum; if(statusNum == 200) authorized = PR_TRUE; } } if(!authorized) { protocol_status(request->getOrigSession(), request->getOrigRequest(), PROTOCOL_UNAUTHORIZED, NULL); } else { //retain only the headers starting with "Varaiable-" for (int i = 0; i < pb->hsize; i++) { pb_entry *p = pb->ht[i]; while (p) { const char *name = PL_strdup(p->param->name); const char *value = PL_strdup(p->param->value); if (*name == 'v' && (!PL_strcmp(name, "variable-"))) { pb_param *pparam = pblock_fr((char *)name, pb, PR_TRUE); param_free(pparam); name += authHeaderPrefixLen; // remove the prefix from name if(*name == 'r' && (!PL_strcmp(name, "remote_user"))) { pblock_nvinsert("auth-user", value, rq->vars); } if(*name == 'a' && (!PL_strcmp(name, "auth_type"))) { pblock_nvinsert("auth-type", value, rq->vars); } pblock_nvinsert(name, value, rq->headers); } PL_strfree((char *)name); PL_strfree((char *)value); p = p->next; } //while } //for } //if } else { lastError = INVALID_HTTP_HEADER; request->log(LOG_FAILURE, GetString(DBT_invalid_response)); return PR_FAILURE; } return PR_SUCCESS; }
/* * Function Name: validate_session_policy * This is the NSAPI directive funtion which gets called for each request * It does session validation and policy check for each request. * Input: As defined by a SAF * Output: As defined by a SAF */ NSAPI_PUBLIC int validate_session_policy(pblock *param, Session *sn, Request *rq) { const char *thisfunc = "validate_session_policy()"; char *dpro_cookie = NULL; am_status_t status = AM_SUCCESS; int requestResult = REQ_ABORTED; int notifResult = REQ_ABORTED; const char *ruser = NULL; am_map_t env_parameter_map = NULL; am_policy_result_t result = AM_POLICY_RESULT_INITIALIZER; void *args[] = { (void *)rq }; char *request_url = NULL; char *orig_req = NULL ; char *response = NULL; char *clf_req = NULL; char *server_protocol = NULL; void *agent_config = NULL; char *logout_url = NULL; char *uri_hdr = NULL; char *pathInfo_hdr = NULL; char *method_hdr = NULL; char *method = NULL; char *virtHost_hdr = NULL; char *query_hdr = NULL; char *query = NULL; char *protocol = "HTTP"; const char *clientIP_hdr_name = NULL; char *clientIP_hdr = NULL; char *clientIP = NULL; const char *clientHostname_hdr_name = NULL; char *clientHostname_hdr = NULL; char *clientHostname = NULL; am_status_t cdStatus = AM_FAILURE; // check if agent is initialized. // if not initialized, then call agent init function // This needs to be synchronized as only one time agent // initialization needs to be done. if(agentInitialized != B_TRUE){ //Start critical section crit_enter(initLock); if(agentInitialized != B_TRUE){ am_web_log_debug("%s: Will call init.", thisfunc); init_at_request(); if(agentInitialized != B_TRUE){ am_web_log_error("%s: Agent is still not intialized", thisfunc); //deny the access requestResult = do_deny(sn, rq, status); status = AM_FAILURE; } else { am_web_log_debug("%s: Agent intialized"); } } //end critical section crit_exit(initLock); } if (status == AM_SUCCESS) { // Get the agent configuration agent_config = am_web_get_agent_configuration(); // Dump the entire set of request headers if (am_web_is_max_debug_on()) { char *header_str = pblock_pblock2str(rq->reqpb, NULL); am_web_log_max_debug("%s: Headers: %s", thisfunc, header_str); system_free(header_str); } } // Get header values if (status == AM_SUCCESS) { status = get_header_value(rq->reqpb, REQUEST_URI, B_TRUE, &uri_hdr, B_FALSE, NULL); } if (status == AM_SUCCESS) { status = get_header_value(rq->vars, PATH_INFO, B_FALSE, &pathInfo_hdr, B_FALSE, NULL); } if (status == AM_SUCCESS) { status = get_header_value(rq->reqpb, REQUEST_METHOD, B_TRUE, &method_hdr, B_TRUE, &method); } if (status == AM_SUCCESS) { status = get_header_value(rq->headers, "ampxy_host", B_TRUE, &virtHost_hdr, B_FALSE, NULL); } if (status == AM_SUCCESS) { status = get_header_value(rq->reqpb, REQUEST_QUERY, B_FALSE, &query_hdr, B_TRUE, &query); } if (security_active) { protocol = "HTTPS"; } // Get the request URL if (status == AM_SUCCESS) { if (am_web_is_proxy_override_host_port_set(agent_config) == AM_FALSE) { status = am_web_get_request_url(virtHost_hdr, protocol, NULL, 0, uri_hdr, query, &request_url, agent_config); if(status == AM_SUCCESS) { am_web_log_debug("%s: Request_url: %s", thisfunc, request_url); } else { am_web_log_error("%s: Could not get the request URL. " "Failed with error: %s.", thisfunc, am_status_to_string(status)); } } } if (status == AM_SUCCESS) { if (am_web_is_proxy_override_host_port_set(agent_config) == AM_TRUE) { const char *agent_host = am_web_get_agent_server_host(agent_config); int agent_port = am_web_get_agent_server_port(agent_config); if (agent_host != NULL) { char *temp = NULL; temp = replace_host_port(request_url, agent_host, agent_port, agent_config); if (temp != NULL) { free(request_url); request_url = temp; } } am_web_log_debug("%s: Request_url after overriding " "host and port: %s", thisfunc, request_url); } } if (status == AM_SUCCESS) { // Check for magic notification URL if (B_TRUE == am_web_is_notification(request_url, agent_config)) { am_web_free_memory(request_url); am_web_delete_agent_configuration(agent_config); if(query != NULL) { free(query); query = NULL; } if(method != NULL) { free(method); method = NULL; } return REQ_PROCEED; } } // Check if the SSO token is in the cookie header if (status == AM_SUCCESS) { requestResult = getISCookie(pblock_findval(COOKIE_HDR, rq->headers), &dpro_cookie, agent_config); if (requestResult == REQ_ABORTED) { status = AM_FAILURE; } else if (dpro_cookie != NULL) { am_web_log_debug("%s: SSO token found in cookie header.", thisfunc); } } // Create the environment map if( status == AM_SUCCESS) { status = am_map_create(&env_parameter_map); if( status != AM_SUCCESS) { am_web_log_error("%s: Unable to create map, status = %s (%d)", thisfunc, am_status_to_string(status), status); } } // If there is a proxy in front of the agent, the user can set in the // properties file the name of the headers that the proxy uses to set // the real client IP and host name. In that case the agent needs // to use the value of these headers to process the request // // Get the client IP address header set by the proxy, if there is one if (status == AM_SUCCESS) { clientIP_hdr_name = am_web_get_client_ip_header_name(agent_config); if (clientIP_hdr_name != NULL) { status = get_header_value(rq->headers, clientIP_hdr_name, B_FALSE, &clientIP_hdr, B_FALSE, NULL); } } // Get the client host name header set by the proxy, if there is one if (status == AM_SUCCESS) { clientHostname_hdr_name = am_web_get_client_hostname_header_name(agent_config); if (clientHostname_hdr_name != NULL) { status = get_header_value(rq->headers, clientHostname_hdr_name, B_FALSE, &clientHostname_hdr, B_FALSE, NULL); } } // If the client IP and host name headers contain more than one // value, take the first value. if (status == AM_SUCCESS) { if ((clientIP_hdr != NULL) || (clientHostname_hdr != NULL)) { status = am_web_get_client_ip_host(clientIP_hdr, clientHostname_hdr, &clientIP, &clientHostname); } } // Set the IP address and host name in the environment map if ((status == AM_SUCCESS) && (clientIP != NULL)) { status = am_web_set_host_ip_in_env_map(clientIP, clientHostname, env_parameter_map, agent_config); } // If the client IP was not obtained previously, // get it from the REMOTE_ADDR header. if ((status == AM_SUCCESS) && (clientIP == NULL)) { status = get_header_value(sn->client, REQUEST_IP_ADDR, B_FALSE, &clientIP_hdr, B_TRUE, &clientIP); } // In CDSSO mode, check if the sso token is in the post data if( status == AM_SUCCESS) { if((am_web_is_cdsso_enabled(agent_config) == B_TRUE) && (strcmp(method, REQUEST_METHOD_POST) == 0)) { if((dpro_cookie == NULL) && (am_web_is_url_enforced(request_url, pathInfo_hdr, clientIP, agent_config) == B_TRUE)) { // Set original method to GET orig_req = strdup(REQUEST_METHOD_GET); if (orig_req != NULL) { am_web_log_debug("%s: Request method set to GET.", thisfunc); } else { am_web_log_error("%s: Not enough memory to ", "allocate orig_req.", thisfunc); status = AM_NO_MEMORY; } // Check if dpro_cookie is in post data if( status == AM_SUCCESS) { response = get_post_assertion_data(sn, rq, request_url); status = am_web_check_cookie_in_post(args, &dpro_cookie, &request_url, &orig_req, method, response, B_FALSE, set_cookie, set_method, agent_config); if( status == AM_SUCCESS) { am_web_log_debug("%s: SSO token found in " "assertion.",thisfunc); } else { am_web_log_debug("%s: SSO token not found in " "assertion. Redirecting to login page.", thisfunc); status = AM_INVALID_SESSION; } } // Set back the original clf-request attribute if (status == AM_SUCCESS) { int clf_reqSize = 0; if ((query != NULL) && (strlen(query) > 0)) { clf_reqSize = strlen(orig_req) + strlen(uri_hdr) + strlen (query) + strlen(protocol) + 4; } else { clf_reqSize = strlen(orig_req) + strlen(uri_hdr) + strlen(protocol) + 3; } clf_req = malloc(clf_reqSize); if (clf_req == NULL) { am_web_log_error("%s: Unable to allocate %i " "bytes for clf_req", thisfunc, clf_reqSize); status = AM_NO_MEMORY; } else { memset (clf_req,'\0',clf_reqSize); strcpy(clf_req, orig_req); strcat(clf_req, " "); strcat(clf_req, uri_hdr); if ((query != NULL) && (strlen(query) > 0)) { strcat(clf_req, "?"); strcat(clf_req, query); } strcat(clf_req, " "); strcat(clf_req, protocol); am_web_log_debug("%s: clf-request set to %s", thisfunc, clf_req); } pblock_nvinsert(REQUEST_CLF, clf_req, rq->reqpb); } } } } // Check if access is allowed. if( status == AM_SUCCESS) { if (dpro_cookie != NULL) { am_web_log_debug("%s: SSO token = %s", thisfunc, dpro_cookie); } else { am_web_log_debug("%s: SSO token not found.", thisfunc); } status = am_web_is_access_allowed(dpro_cookie, request_url, pathInfo_hdr, method, clientIP, env_parameter_map, &result, agent_config); am_map_destroy(env_parameter_map); } switch(status) { case AM_SUCCESS: // Set remote user and authentication type ruser = result.remote_user; if (ruser != NULL) { pb_param *pbuser = pblock_remove(AUTH_USER_VAR, rq->vars); pb_param *pbauth = pblock_remove(AUTH_TYPE_VAR, rq->vars); if (pbuser != NULL) { param_free(pbuser); } pblock_nvinsert(AUTH_USER_VAR, ruser, rq->vars); if (pbauth != NULL) { param_free(pbauth); } pblock_nvinsert(AUTH_TYPE_VAR, AM_WEB_AUTH_TYPE_VALUE, rq->vars); am_web_log_debug("%s: access allowed to %s", thisfunc, ruser); } else { am_web_log_debug("%s: Remote user not set, " "allowing access to the url as it is in not " "enforced list", thisfunc); } if (am_web_is_logout_url(request_url, agent_config) == B_TRUE) { (void)am_web_logout_cookies_reset(reset_cookie, args, agent_config); } // set LDAP user attributes to http header status = am_web_result_attr_map_set(&result, set_header, set_cookie_in_response, set_header_attr_as_cookie, get_cookie_sync, args, agent_config); if (status != AM_SUCCESS) { am_web_log_error("%s: am_web_result_attr_map_set failed, " "status = %s (%d)", thisfunc, am_status_to_string(status), status); requestResult = REQ_ABORTED; } else { requestResult = REQ_PROCEED; } break; case AM_ACCESS_DENIED: am_web_log_debug("%s: Access denied to %s", thisfunc, result.remote_user ? result.remote_user : "******"); requestResult = do_redirect(sn, rq, status, &result, request_url, method, agent_config); break; case AM_INVALID_SESSION: if (am_web_is_cdsso_enabled(agent_config) == B_TRUE) { cdStatus = am_web_do_cookie_domain_set(set_cookie, args, EMPTY_STRING, agent_config); if(cdStatus != AM_SUCCESS) { am_web_log_error("%s: CDSSO reset cookie failed", thisfunc); } } am_web_do_cookies_reset(reset_cookie, args, agent_config); requestResult = do_redirect(sn, rq, status, &result, request_url, method, agent_config); break; case AM_INVALID_FQDN_ACCESS: // Redirect to self with correct FQDN - no post preservation requestResult = do_redirect(sn, rq, status, &result, request_url, method, agent_config); break; case AM_REDIRECT_LOGOUT: status = am_web_get_logout_url(&logout_url, agent_config); if(status == AM_SUCCESS) { do_url_redirect(sn,rq,logout_url); } else { requestResult = REQ_ABORTED; am_web_log_debug("validate_session_policy(): " "am_web_get_logout_url failed. "); } break; case AM_INVALID_ARGUMENT: case AM_NO_MEMORY: default: am_web_log_error("validate_session_policy() Status: %s (%d)", am_status_to_string(status), status); requestResult = REQ_ABORTED; break; } // Cleaning am_web_clear_attributes_map(&result); am_policy_result_destroy(&result); am_web_free_memory(dpro_cookie); am_web_free_memory(request_url); am_web_free_memory(logout_url); am_web_delete_agent_configuration(agent_config); if (orig_req != NULL) { free(orig_req); orig_req = NULL; } if (response != NULL) { free(response); response = NULL; } if (clf_req != NULL) { free(clf_req); clf_req = NULL; } if(query != NULL) { free(query); query = NULL; } if(method != NULL) { free(method); method = NULL; } if(clientIP != NULL) { am_web_free_memory(clientIP); } if(clientHostname != NULL) { am_web_free_memory(clientHostname); } am_web_log_max_debug("%s: Completed handling request with status: %s.", thisfunc, am_status_to_string(status)); return requestResult; }
static am_status_t set_header(const char *key, const char *values, void **args) { Request *rq = (Request *)args[0]; pb_param *hdr_pp = pblock_find("full-headers", rq->reqpb); const char *the_key = key; if (hdr_pp != NULL) { if(values != NULL && *values != '\0') { //Added by bn152013 for 6739097 int append = 0; int length = strlen(the_key) + strlen(values) + 5; if (hdr_pp->value != NULL) { size_t len = strlen(hdr_pp->value); length += len; append = 1; hdr_pp->value = (char *) system_realloc(hdr_pp->value, length); hdr_pp->value[len] = '\0'; } else { hdr_pp->value = (char *) system_malloc(length); hdr_pp->value[0]='\0'; } if ( hdr_pp->value == NULL) { return (AM_NO_MEMORY); } if (append) strcat(hdr_pp->value, the_key); else strcpy(hdr_pp->value, the_key); strcat(hdr_pp->value, ": "); strcat(hdr_pp->value, values); strcat(hdr_pp->value, "\r\n"); } else { if(key[0] != '\0' && hdr_pp->value != NULL) { char *ptr = strstr(hdr_pp->value, the_key); if(ptr != NULL) { char *end_ptr = ptr + strlen(the_key); while(*end_ptr != '\r' && *end_ptr != '\n') ++end_ptr; end_ptr += 2; while(*end_ptr != '\0') { *ptr = *end_ptr; ptr += 1; end_ptr += 1; } *ptr = '\0'; } } } } if(values != NULL && *values != '\0') { //Added by bn152013 for 6739097 pblock_nvinsert(the_key, (char *)values, rq->headers); } else { param_free(pblock_remove(the_key, rq->headers)); } return (AM_SUCCESS); }
static void set_method(void ** args, char * orig_req){ Request *rq = (Request *)args[0]; if (rq != NULL) { pblock_nvinsert(REQUEST_METHOD, orig_req, rq->reqpb); } }