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; }
int otype_changetype (pblock *pb, Session *sn, Request *rq) { char * type = pblock_findval ("type", pb); rq->directive_is_cacheable = 1; if (type != NULL) { const char *if_type = pblock_findval ("if-type", pb); if (if_type != NULL) { const char *ct_type = pblock_findval ("content-type", rq -> srvhdrs); if (ct_type != NULL && !strcmp (if_type, ct_type)) { pblock_nvreplace ("content-type", type, rq -> srvhdrs); return REQ_PROCEED; } } else { pblock_nvreplace ("content-type", type, rq -> srvhdrs); return REQ_PROCEED; } } return REQ_NOACTION; }
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 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; }
int otype_imgswitch(pblock *pb, Session *sn, Request *rq) { char *ct, *ua, *pa, *npath, *t; struct stat fi; pb_param *pp; /* This routine might be cacheable. Lets check the objtype so * far to see if we are talking about an image file. If this path * is not an image, we can go ahead and cache. */ rq->directive_is_cacheable = 1; if(!(ct = pblock_findval("content-type", rq->srvhdrs))) return REQ_NOACTION; if(strncasecmp(ct, "image/", 6)) return REQ_NOACTION; /* This routine is still running, so it must be an image we are * dealing with. This is not cacheable since we need the user-agent * info to determine which file we return. */ rq->directive_is_cacheable=0; /* In the absence of a capabilities header, use user-agent */ if(request_header("user-agent", &ua, sn, rq) == REQ_ABORTED) return REQ_ABORTED; /* We want to be nice to proxies */ if(request_header("proxy-agent", &pa, sn, rq) == REQ_ABORTED) return REQ_ABORTED; if((!ua) || pa || strstr(ua, "roxy")) return REQ_NOACTION; /* Look for jpeg if we're talking to mozilla and image is .gif */ if((!strncasecmp(ua, "mozilla", 7)) && (!strcasecmp(ct, "image/gif"))) { npath = STRDUP(pblock_findval("path", rq->vars)); if(!(t = strstr(npath, ".gif"))) return REQ_NOACTION; t[1] = 'j'; t[2] = 'p'; t[3] = 'g'; if(stat(npath, &fi) == -1) { FREE(npath); return REQ_NOACTION; } pp = pblock_find("path", rq->vars); FREE(pp->value); pp->value = npath; /* don't check return; it should work. */ request_stat_path(npath, rq); pp = pblock_find("content-type", rq->srvhdrs); FREE(pp->value); pp->value = STRDUP("image/jpeg"); return REQ_PROCEED; } return REQ_NOACTION; }
/* Sigh. Another stupid pet trick that will get dropped on the floor */ int otype_htmlswitch(pblock *pb, Session *sn, Request *rq) { char *ct, *ua, *pa, *npath, *t; struct stat fi; pb_param *pp; /* This routine might be cacheable. Lets check the objtype so * far to see if we are talking about a text file. If this path * is not a text, we can go ahead and cache. */ rq->directive_is_cacheable = 1; if(!(ct = pblock_findval("content-type", rq->srvhdrs))) return REQ_NOACTION; if(strncasecmp(ct, "text/", 5)) return REQ_NOACTION; /* This is still running, so it must be a text file we are * dealing with. This is not cacheable since we need the user-agent * info to determine which file we return. */ rq->directive_is_cacheable = 0; /* In the absence of a capabilities header, use user-agent */ if(request_header("user-agent", &ua, sn, rq) == REQ_ABORTED) return REQ_ABORTED; /* We want to be nice to proxies */ if(request_header("proxy-agent", &pa, sn, rq) == REQ_ABORTED) return REQ_ABORTED; if((!ua) || pa || strstr(ua, "roxy")) return REQ_NOACTION; /* Look for html3 if we're talking to mozilla and find HTML */ if(util_is_mozilla(ua, "1", "1") && (!strcasecmp(ct, "text/html"))) { t = pblock_findval("path", rq->vars); npath = (char *) MALLOC(strlen(t) + 1 + 1); util_sprintf(npath, "%s3", t); if(stat(npath, &fi) == -1) { FREE(npath); return REQ_NOACTION; } pp = pblock_find("path", rq->vars); FREE(pp->value); pp->value = npath; /* don't check return; it should work. */ request_stat_path(npath, rq); 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; }
inline static void cpyhdr(const char *key,pblock *pb,HTTPRequest *req,const char *wokey) { const char *value = pblock_findval((char *)key, pb); if (value != NULL) req_addHeader(req, (wokey) ? wokey : key, value, 0); }
/** ************************************************************************** * 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; }
int nsapi_send(pblock *pb, Session *sn, Request *rq) { char *query_string; char buffer[sizeof(HEADERS) + 204800 + 1]; int filesize; unsigned int maxindex; unsigned int index; /* Get the query string, if any; check to see if an alternate * file size was specified. */ if ( !(query_string = pblock_findval("query", rq->reqpb)) ) filesize = FILE_SIZE; else { filesize = atoi(&(query_string[5])); } memcpy(&buffer, HEADERS, sizeof(HEADERS)-1); /* Generate the output */ maxindex = sizeof(HEADERS) + filesize; for (index=sizeof(HEADERS); index < (maxindex); index++) /* generate random characters from A-Z */ #ifdef IRIX buffer[index] = rand_r() % 26 + 63; #else buffer[index] = rand() %26 + 63; #endif /* Send the output */ if (net_write(sn->csd, buffer, sizeof(HEADERS)-1+filesize, 0) == IO_ERROR) return REQ_EXIT; return REQ_PROCEED; }
static char* find_document_root_directive(httpd_objset *objset) { // XXX Attempt to guess the document root by looking for the NameTrans // fn=document-root directive in obj.conf. Note that we use the last // document-root directive's root parameter; earlier directives may have // been in less-specific objects or enclosed in <Client> tags. int countObjects = objset_get_number_objects(objset); int iObject; for (iObject = countObjects - 1; iObject >= 0; iObject--) { const httpd_object* object = objset_get_object(objset, iObject); const dtable* dir_table = object_get_directive_table(object, NSAPINameTrans); int countDirectives = directive_table_get_num_directives(dir_table); int iDirective; for (iDirective = countDirectives - 1; iDirective >= 0; iDirective--) { const directive* dir = directive_table_get_directive(dir_table, iDirective); const FuncStruct* fs = directive_get_funcstruct(dir); if (fs && fs->name && !strcmp(fs->name, "document-root")) { char* docroot = pblock_findval("root", dir->param.pb); if (docroot) return docroot; } } } return NULL; }
static htaccess_context_s * _htaccess_newctxt(pblock *pb, Session *sn, Request *rq) { htaccess_context_s *ctxt = (htaccess_context_s *) MALLOC(sizeof(htaccess_context_s)); char *rhst = session_dns(sn); ctxt->pb = pb; ctxt->sn = sn; ctxt->rq = rq; ctxt->auth_type = NULL; ctxt->auth_name = NULL; ctxt->auth_pwfile = NULL; ctxt->auth_grpfile = NULL; ctxt->auth_authdb = 0; ctxt->auth_grplist = 0; ctxt->auth_grplfile = 0; ctxt->auth_grpllen = 0; ctxt->user_check_fn = NULL; ctxt->group_check_fn = NULL; #ifdef AUTHNSDBFILE ctxt->auth_uoptr = 0; ctxt->auth_nsdb = 0; #endif /* AUTHNSDBFILE */ ctxt->auth_line = pblock_findval("authorization", rq->headers); ctxt->num_sec = 0; ctxt->remote_host = rhst; ctxt->remote_ip = pblock_findval("ip", sn->client); ctxt->remote_name = rhst ? rhst : ctxt->remote_ip; ctxt->access_name = pblock_findval("filename", pb); if(!ctxt->access_name) ctxt->access_name = DEFAULT_ACCESS_FNAME; ctxt->user[0] = '\0'; ctxt->groupname[0] = '\0'; ctxt->sec = htaccess_newsec(); return ctxt; }
int otype_typebyexp(pblock *pb, Session *sn, Request *rq) { char *exp = pblock_findval("exp", pb); char *path = pblock_findval("path", rq->vars); rq->directive_is_cacheable = 1; if(!exp) { log_error(LOG_MISCONFIG, "type-by-exp", sn, rq, XP_GetAdminStr(DBT_ntwincgiError14)); return REQ_ABORTED; } if(!(WILDPAT_CMP(path, exp))) return otype_forcetype(pb, sn, rq); else { return REQ_NOACTION; } }
int htaccess_evaluate(pblock *pb, Session *sn, Request *rq) { char *p = pblock_findval("path", rq->vars); struct stat *finfo = request_stat_path(p, rq); int isdir = finfo && S_ISDIR(finfo->st_mode); /* some java servlets that are set in rules.properties don't set this */ if(!pblock_findval("ntrans-base", rq->vars)) return REQ_NOACTION; char *methstr = pblock_findval("method", rq->reqpb); int methnum; HttpMethodRegistry& registry = HttpMethodRegistry::GetRegistry(); /* treat HEAD as a GET */ if (!strcasecmp(methstr, "HEAD")) methnum = registry.HttpMethodRegistry::GetMethodIndex("GET"); else methnum = registry.HttpMethodRegistry::GetMethodIndex(methstr); /* if it isn't a method we support, don't allow access */ if (methnum == -1) { protocol_status(sn, rq, PROTOCOL_FORBIDDEN, NULL); return REQ_ABORTED; } switch(htaccess_evaluate_access(p, isdir, methnum, pb, sn, rq)) { case ACCESS_OK: return REQ_PROCEED; case ACCESS_FORBIDDEN: default: protocol_status(sn, rq, PROTOCOL_FORBIDDEN, NULL); log_error(LOG_SECURITY, "htaccess-find", sn, rq, "access of %s denied by server configuration.", p); /* fallthrough */ case ACCESS_AUTHFAIL: /* the data structures will be set up by http_auth.c */ return REQ_ABORTED; } }
int set_default_database (pblock *pb, Session *sn, Request *rq) { char *dbname = pblock_findval(ACL_ATTR_DBNAME, pb); NSErr_t *errp = 0; ACL_REG(ACL_DatabaseSetDefault(errp, dbname), "Failed to set default method \"%s\"", dbname); return REQ_PROCEED; }
int register_method (pblock *pb, Session *sn, Request *rq) { char *method = pblock_findval(ACL_ATTR_METHOD, pb); ACLMethod_t t; NSErr_t *errp = 0; ACL_REG(ACL_MethodRegister (errp, method, &t), "Failed to register method \"%s\"", method); return REQ_PROCEED; }
int set_default_method (pblock *pb, Session *sn, Request *rq) { char *method = pblock_findval(ACL_ATTR_METHOD, pb); NSErr_t *errp = 0; ACLMethod_t t; ACL_REG(ACL_MethodFind(errp, method, &t), "Method \"%s\" is not registered", method); ACL_MethodSetDefault(errp, t); return REQ_PROCEED; }
/** * 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; } }
/* * 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 register_module (pblock *pb, Session *sn, Request *rq) { char *module = pblock_findval(ACL_ATTR_MODULE, pb); char *funcStr = pblock_findval(ACL_ATTR_MODULEFUNC, pb); AclModuleInitFunc func; NSErr_t *errp = 0; if (!funcStr || !*funcStr) { ereport(LOG_SECURITY, XP_GetAdminStr(DBT_initereport1)); return REQ_ABORTED; } func = (AclModuleInitFunc)func_find(funcStr); if (!func) { ereport(LOG_SECURITY, XP_GetAdminStr(DBT_initereport2)); return REQ_ABORTED; } ACL_REG(ACL_ModuleRegister (errp, module, func), XP_GetAdminStr(DBT_initereport3), module); return REQ_PROCEED; }
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; }
am_status_t get_header_value(pblock *pb, const char *header_name, boolean_t isRequired, char **header_value, boolean_t needCopy, char **header_value_copy) { const char *thisfunc = "get_header_value()"; am_status_t status = AM_SUCCESS; // From NSAPI guide: // The pointer returned is a pointer into the pblock. // Do not FREE it. If you want to modify it, do a STRDUP // and modify the copy. *header_value = pblock_findval(header_name, pb); if ((*header_value != NULL) && (strlen(*header_value) > 0 )) { am_web_log_debug("%s: %s = %s", thisfunc, header_name, *header_value); } else { *header_value = NULL; if (isRequired == B_TRUE) { am_web_log_error("%s: Could not get a value for header %s.", thisfunc, header_name); status = AM_FAILURE; } else { am_web_log_debug("%s: %s =", thisfunc, header_name); } } // In case the header needs to be modified later in the code, // copy it in a variable that can be modified. This one must // be freed. if ((status == AM_SUCCESS) && (needCopy == B_TRUE) && (*header_value != NULL)) { *header_value_copy = strdup(*header_value); if (*header_value_copy == NULL) { am_web_log_debug("%s: Not enough memory to make " "a copy of the %s header.", thisfunc, header_name); status = AM_NO_MEMORY; } } return status; }
NSAPI_PUBLIC char *conf_findGlobal(char *name) { if (!conf_api_initialized) { log_ereport(LOG_VERBOSE, XP_GetAdminStr(DBT_confApiCallBeforeInit)); return NULL; } char *rv = NULL; char *d = _lowercase(name); if (d) { // Mark directive as accessed if (globalsUnaccessed) param_free(pblock_remove(d, globalsUnaccessed)); // Lookup directive rv = pblock_findval(d, conf_get_true_globals()->genericGlobals); FREE(d); } return rv; }
static am_status_t set_header_attr_as_cookie(const char *values, void **args) { Request *rq = NULL; am_status_t sts = AM_SUCCESS; char *cookie_header = NULL; char *new_cookie_header = NULL; if (args == NULL || args[0] == NULL || values == NULL || values[0] == '\0') { sts = AM_INVALID_ARGUMENT; } else { rq = (Request *)args[0]; cookie_header = pblock_findval("cookie", rq->headers); sts = am_web_set_cookie(cookie_header, values, &new_cookie_header); if (sts == AM_SUCCESS && new_cookie_header != NULL && new_cookie_header != cookie_header) { sts = set_header("cookie", new_cookie_header, args); free(new_cookie_header); } } return sts; }
/* * 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; }
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; }
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; }
NSAPI_PUBLIC int web_agent_init(pblock *param, Session *sn, Request *rq) { am_status_t status; int nsapi_status = REQ_PROCEED; char *temp_buf = NULL; char *agent_bootstrap_file = NULL; char *agent_config_file = NULL; initLock = crit_init(); temp_buf = pblock_findval(DSAME_CONF_DIR, param); if (temp_buf != NULL) { agent_bootstrap_file = system_malloc(strlen(temp_buf) + sizeof(AGENT_BOOTSTRAP_FILE)); agent_config_file = system_malloc(strlen(temp_buf) + sizeof(AGENT_CONFIG_FILE)); if (agent_bootstrap_file != NULL) { strcpy(agent_bootstrap_file, temp_buf); strcat(agent_bootstrap_file, AGENT_BOOTSTRAP_FILE); } else { log_error(LOG_FAILURE, "URL Access Agent: ", sn, rq, "web_agent_init() unable to allocate memory for bootstrap " "file name", DSAME_CONF_DIR); nsapi_status = REQ_ABORTED; } if (agent_config_file != NULL) { strcpy(agent_config_file, temp_buf); strcat(agent_config_file, AGENT_CONFIG_FILE); } else { log_error(LOG_FAILURE, "URL Access Agent: ", sn, rq, "web_agent_init() unable to allocate memory for local config " "file name", DSAME_CONF_DIR); nsapi_status = REQ_ABORTED; } status = am_properties_create(&agent_props.agent_bootstrap_props); if(status == AM_SUCCESS) { status = am_properties_load(agent_props.agent_bootstrap_props, agent_bootstrap_file); if(status == AM_SUCCESS) { //this is where the agent config info is passed from filter code //to amsdk. Not sure why agent_props is required. status = am_web_init(agent_bootstrap_file, agent_config_file); system_free(agent_bootstrap_file); system_free(agent_config_file); if (AM_SUCCESS != status) { log_error(LOG_FAILURE, "URL Access Agent: ", sn, rq, "Initialization of the agent failed: " "status = %s (%d)", am_status_to_string(status), status); nsapi_status = REQ_ABORTED; } } else { log_error(LOG_FAILURE, "web_agent_init():", sn, rq, "Error while creating properties object= %s", am_status_to_string(status)); nsapi_status = REQ_ABORTED; } } else { log_error(LOG_FAILURE, "web_agent_init():", sn, rq, "Error while creating properties object= %s", am_status_to_string(status)); nsapi_status = REQ_ABORTED; } } else { log_error(LOG_FAILURE, "URL Access Agent: ", sn, rq, "web_agent_init() %s variable not defined in magnus.conf", DSAME_CONF_DIR); nsapi_status = REQ_ABORTED; } if(nsapi_status == REQ_PROCEED) { daemon_atrestart(&agent_cleanup, NULL); } return nsapi_status; }