Mon, 30 Jan 2017 20:54:20 +0100
fixes crash on broken urls
/* * 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 "../../ucx/map.h" static UcxMap *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 = ucx_map_new(32); ucx_map_cstr_put(var_names, "insert-client", (intptr_t)COMMONSAF_INSERT_CLIENT); ucx_map_cstr_put(var_names, "insert-vars", (intptr_t)COMMONSAF_INSERT_VARS); ucx_map_cstr_put(var_names, "insert-reqpb", (intptr_t)COMMONSAF_INSERT_REQPB); ucx_map_cstr_put(var_names, "insert-headers", (intptr_t)COMMONSAF_INSERT_HEADERS); ucx_map_cstr_put(var_names, "insert-srvhdrs", (intptr_t)COMMONSAF_INSERT_SRVHDRS); ucx_map_cstr_put(var_names, "set-client", (intptr_t)COMMONSAF_SET_CLIENT); ucx_map_cstr_put(var_names, "set-vars", (intptr_t)COMMONSAF_SET_VARS); ucx_map_cstr_put(var_names, "set-reqpb", (intptr_t)COMMONSAF_SET_REQPB); ucx_map_cstr_put(var_names, "set-headers", (intptr_t)COMMONSAF_SET_HEADERS); ucx_map_cstr_put(var_names, "set-srvhdrs", (intptr_t)COMMONSAF_SET_SRVHDRS); ucx_map_cstr_put(var_names, "remove-client", (intptr_t)COMMONSAF_REMOVE_CLIENT); ucx_map_cstr_put(var_names, "remove-vars", (intptr_t)COMMONSAF_REMOVE_VARS); ucx_map_cstr_put(var_names, "remove-reqpb", (intptr_t)COMMONSAF_REMOVE_REQPB); ucx_map_cstr_put(var_names, "remove-headers", (intptr_t)COMMONSAF_REMOVE_HEADERS); ucx_map_cstr_put(var_names, "remove-srvhdrs", (intptr_t)COMMONSAF_REMOVE_SRVHDRS); ucx_map_cstr_put(var_names, "abort", (intptr_t)COMMONSAF_ABORT); ucx_map_cstr_put(var_names, "noaction", (intptr_t)COMMONSAF_NOACTION); ucx_map_cstr_put(var_names, "error", (intptr_t)COMMONSAF_ERROR); ucx_map_cstr_put(var_names, "escape", (intptr_t)COMMONSAF_ESCAPE); ucx_map_cstr_put(var_names, "find-pathinfo-forward", (intptr_t)COMMONSAF_FIND_PATHINFO_FORWARD); ucx_map_cstr_put(var_names, "http-downgrade", (intptr_t)COMMONSAF_HTTP_DOWNGRADE); ucx_map_cstr_put(var_names, "http-upgrade", (intptr_t)COMMONSAF_HTTP_UPGRADE); ucx_map_cstr_put(var_names, "keep-alive", (intptr_t)COMMONSAF_KEEP_ALIVE); ucx_map_cstr_put(var_names, "name", (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) { sstr_t n; sstr_t 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 = sstrsubs(sstrn(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, char *var, char *value) { intptr_t v = (intptr_t)ucx_map_cstr_get(var_names, 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: { int len = strlen(value); WSBool isnum = TRUE; int i; for(i=0;i<len;i++) { if(!isdigit(value[i])) { isnum = FALSE; break; } } int64_t status; int ret = util_strtoint(value, &status); if(status < 100 || ret > 999 || !ret) { 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; } char *msg = isnum ? NULL : sstrtrim(sstr(value + i)).ptr; 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; }