UNIXworkcode

/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2013 Olaf Wintermann. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "common.h" #include "../daemon/httprequest.h" #include "../daemon/log.h" #include "../util/pblock.h" #include "../util/util.h" #include <cx/map.h> #include <cx/hash_map.h> static CxMap *var_names; enum SAFVarNames { COMMONSAF_INSERT_CLIENT = 1, COMMONSAF_INSERT_VARS, COMMONSAF_INSERT_REQPB, COMMONSAF_INSERT_HEADERS, COMMONSAF_INSERT_SRVHDRS, COMMONSAF_SET_CLIENT, COMMONSAF_SET_VARS, COMMONSAF_SET_REQPB, COMMONSAF_SET_HEADERS, COMMONSAF_SET_SRVHDRS, COMMONSAF_REMOVE_CLIENT, COMMONSAF_REMOVE_VARS, COMMONSAF_REMOVE_REQPB, COMMONSAF_REMOVE_HEADERS, COMMONSAF_REMOVE_SRVHDRS, COMMONSAF_ABORT, COMMONSAF_NOACTION, COMMONSAF_ERROR, COMMONSAF_ESCAPE, COMMONSAF_FIND_PATHINFO_FORWARD, COMMONSAF_HTTP_DOWNGRADE, COMMONSAF_HTTP_UPGRADE, COMMONSAF_KEEP_ALIVE, COMMONSAF_NAME, COMMONSAF_SENTHDRS, COMMONSAF_STOP, COMMONSAF_URL }; #define COMMONSAF_RET_DEF 0 #define COMMONSAF_RET_NOACTION 1 #define COMMONSAF_RET_STOP 2 #define COMMONSAF_REQ_ABORTED -1 #define COMMONSAF_RET_ERROR -2 void common_saf_init() { var_names = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 32); cxMapPut(var_names, cx_hash_key_str("insert-client"), (void*)(intptr_t)COMMONSAF_INSERT_CLIENT); cxMapPut(var_names, cx_hash_key_str("insert-vars"), (void*)(intptr_t)COMMONSAF_INSERT_VARS); cxMapPut(var_names, cx_hash_key_str("insert-reqpb"), (void*)(intptr_t)COMMONSAF_INSERT_REQPB); cxMapPut(var_names, cx_hash_key_str("insert-headers"), (void*)(intptr_t)COMMONSAF_INSERT_HEADERS); cxMapPut(var_names, cx_hash_key_str("insert-srvhdrs"), (void*)(intptr_t)COMMONSAF_INSERT_SRVHDRS); cxMapPut(var_names, cx_hash_key_str("set-client"), (void*)(intptr_t)COMMONSAF_SET_CLIENT); cxMapPut(var_names, cx_hash_key_str("set-vars"), (void*)(intptr_t)COMMONSAF_SET_VARS); cxMapPut(var_names, cx_hash_key_str("set-reqpb"), (void*)(intptr_t)COMMONSAF_SET_REQPB); cxMapPut(var_names, cx_hash_key_str("set-headers"), (void*)(intptr_t)COMMONSAF_SET_HEADERS); cxMapPut(var_names, cx_hash_key_str("set-srvhdrs"), (void*)(intptr_t)COMMONSAF_SET_SRVHDRS); cxMapPut(var_names, cx_hash_key_str("remove-client"), (void*)(intptr_t)COMMONSAF_REMOVE_CLIENT); cxMapPut(var_names, cx_hash_key_str("remove-vars"), (void*)(intptr_t)COMMONSAF_REMOVE_VARS); cxMapPut(var_names, cx_hash_key_str("remove-reqpb"), (void*)(intptr_t)COMMONSAF_REMOVE_REQPB); cxMapPut(var_names, cx_hash_key_str("remove-headers"), (void*)(intptr_t)COMMONSAF_REMOVE_HEADERS); cxMapPut(var_names, cx_hash_key_str("remove-srvhdrs"), (void*)(intptr_t)COMMONSAF_REMOVE_SRVHDRS); cxMapPut(var_names, cx_hash_key_str("abort"), (void*)(intptr_t)COMMONSAF_ABORT); cxMapPut(var_names, cx_hash_key_str("noaction"), (void*)(intptr_t)COMMONSAF_NOACTION); cxMapPut(var_names, cx_hash_key_str("error"), (void*)(intptr_t)COMMONSAF_ERROR); cxMapPut(var_names, cx_hash_key_str("escape"), (void*)(intptr_t)COMMONSAF_ESCAPE); cxMapPut(var_names, cx_hash_key_str("find-pathinfo-forward"), (void*)(intptr_t)COMMONSAF_FIND_PATHINFO_FORWARD); cxMapPut(var_names, cx_hash_key_str("http-downgrade"), (void*)(intptr_t)COMMONSAF_HTTP_DOWNGRADE); cxMapPut(var_names, cx_hash_key_str("http-upgrade"), (void*)(intptr_t)COMMONSAF_HTTP_UPGRADE); cxMapPut(var_names, cx_hash_key_str("keep-alive"), (void*)(intptr_t)COMMONSAF_KEEP_ALIVE); cxMapPut(var_names, cx_hash_key_str("name"), (void*)(intptr_t)COMMONSAF_NAME); } int print_message(pblock *pb, Session *sn, Request *rq) { char *msg = pblock_findval("msg", pb); if(msg) { log_ereport(LOG_INFORM, "%s", msg); } return REQ_NOACTION; } static void var_set(char *value, pblock *pb, WSBool insert) { cxstring n; cxstring v; v.ptr = NULL; n.ptr = value; int i; int len = strlen(value); for(i=1;i<len;i++) { if(value[i] == '=') { n.length = i; v = cx_strsubs(cx_strn(value, len), i + 1); break; } } if(!v.ptr || v.length == 0) { log_ereport( LOG_MISCONFIG, "set-variable: string ''%s'' has not name=value format", value); return; } if(!insert) { // TODO } pblock_nvlinsert(n.ptr, n.length, v.ptr, v.length, pb); } static int set_var(Session *sn, Request *rq, const char *var, char *value) { intptr_t v = (intptr_t)cxMapGet(var_names, cx_hash_key_str(var)); switch(v) { default: break; case COMMONSAF_INSERT_CLIENT: var_set(value, sn->client, TRUE); break; case COMMONSAF_INSERT_VARS: var_set(value, rq->vars, TRUE); break; case COMMONSAF_INSERT_REQPB: var_set(value, rq->reqpb, TRUE); break; case COMMONSAF_INSERT_HEADERS: var_set(value, rq->headers, TRUE); break; case COMMONSAF_INSERT_SRVHDRS: var_set(value, rq->srvhdrs, TRUE); break; case COMMONSAF_SET_CLIENT: var_set(value, sn->client, FALSE); break; case COMMONSAF_SET_VARS: var_set(value, rq->vars, FALSE); break; case COMMONSAF_SET_REQPB: var_set(value, rq->reqpb, FALSE); break; case COMMONSAF_SET_HEADERS: var_set(value, rq->headers, FALSE); break; case COMMONSAF_SET_SRVHDRS: var_set(value, rq->srvhdrs, FALSE); break; case COMMONSAF_REMOVE_CLIENT: pblock_remove(value, sn->client); break; case COMMONSAF_REMOVE_VARS: pblock_remove(value, rq->vars); break; case COMMONSAF_REMOVE_HEADERS: pblock_remove(value, rq->headers);break; case COMMONSAF_REMOVE_SRVHDRS: pblock_remove(value, rq->srvhdrs); break; case COMMONSAF_ABORT: return COMMONSAF_REQ_ABORTED; case COMMONSAF_NOACTION: return COMMONSAF_RET_NOACTION; case COMMONSAF_ERROR: { char *end; long status = strtol(value, &end, 10); if(status < 100 || status > 999) { log_ereport( LOG_MISCONFIG, "set-variable: error value must contain a 3-digit http status code"); protocol_status(sn, rq, 500, NULL); return COMMONSAF_RET_ERROR; } const char *msg = NULL; while(isspace(*end)) { end++; } if(*end != '\0') { msg = end; } protocol_status(sn, rq, (int)status, msg); return COMMONSAF_REQ_ABORTED; } case COMMONSAF_ESCAPE: break; case COMMONSAF_FIND_PATHINFO_FORWARD: break; case COMMONSAF_HTTP_DOWNGRADE: break; case COMMONSAF_HTTP_UPGRADE: break; case COMMONSAF_KEEP_ALIVE: { rq->rq_attr.keep_alive = util_getboolean(var, 0); break; } case COMMONSAF_NAME: { pblock_kvinsert(pb_key_name, value, strlen(value), rq->vars); break; } case COMMONSAF_SENTHDRS: break; case COMMONSAF_STOP: return COMMONSAF_RET_STOP; case COMMONSAF_URL: break; } return COMMONSAF_RET_DEF; } int set_variable(pblock *pb, Session *sn, Request *rq) { int ret = REQ_NOACTION; int set = 0; for(int i=0;i<pb->hsize;i++) { pb_entry *entry = pb->ht[i]; while(entry) { int r = set_var(sn, rq, entry->param->name, entry->param->value); switch(r) { default: case COMMONSAF_RET_DEF: break; case COMMONSAF_RET_NOACTION: set = 1; ret = REQ_NOACTION; break; case COMMONSAF_RET_STOP: set = 1; ret = REQ_PROCEED; break; case COMMONSAF_REQ_ABORTED: ret = set ? ret : REQ_ABORTED; break; case COMMONSAF_RET_ERROR: return REQ_ABORTED; } entry = entry->next; } } return ret; }