UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2013 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "common.h" 30 31 #include "../daemon/httprequest.h" 32 #include "../daemon/log.h" 33 34 #include "../util/pblock.h" 35 #include "../util/util.h" 36 #include <cx/map.h> 37 #include <cx/hash_map.h> 38 39 static CxMap *var_names; 40 41 enum SAFVarNames { 42 COMMONSAF_INSERT_CLIENT = 1, 43 COMMONSAF_INSERT_VARS, 44 COMMONSAF_INSERT_REQPB, 45 COMMONSAF_INSERT_HEADERS, 46 COMMONSAF_INSERT_SRVHDRS, 47 COMMONSAF_SET_CLIENT, 48 COMMONSAF_SET_VARS, 49 COMMONSAF_SET_REQPB, 50 COMMONSAF_SET_HEADERS, 51 COMMONSAF_SET_SRVHDRS, 52 COMMONSAF_REMOVE_CLIENT, 53 COMMONSAF_REMOVE_VARS, 54 COMMONSAF_REMOVE_REQPB, 55 COMMONSAF_REMOVE_HEADERS, 56 COMMONSAF_REMOVE_SRVHDRS, 57 COMMONSAF_ABORT, 58 COMMONSAF_NOACTION, 59 COMMONSAF_ERROR, 60 COMMONSAF_ESCAPE, 61 COMMONSAF_FIND_PATHINFO_FORWARD, 62 COMMONSAF_HTTP_DOWNGRADE, 63 COMMONSAF_HTTP_UPGRADE, 64 COMMONSAF_KEEP_ALIVE, 65 COMMONSAF_NAME, 66 COMMONSAF_SENTHDRS, 67 COMMONSAF_STOP, 68 COMMONSAF_URL 69 }; 70 71 #define COMMONSAF_RET_DEF 0 72 #define COMMONSAF_RET_NOACTION 1 73 #define COMMONSAF_RET_STOP 2 74 #define COMMONSAF_REQ_ABORTED -1 75 #define COMMONSAF_RET_ERROR -2 76 77 void common_saf_init() { 78 var_names = cxHashMapCreate(cxDefaultAllocator, CX_STORE_POINTERS, 32); 79 80 cxMapPut(var_names, cx_hash_key_str("insert-client"), (void*)(intptr_t)COMMONSAF_INSERT_CLIENT); 81 cxMapPut(var_names, cx_hash_key_str("insert-vars"), (void*)(intptr_t)COMMONSAF_INSERT_VARS); 82 cxMapPut(var_names, cx_hash_key_str("insert-reqpb"), (void*)(intptr_t)COMMONSAF_INSERT_REQPB); 83 cxMapPut(var_names, cx_hash_key_str("insert-headers"), (void*)(intptr_t)COMMONSAF_INSERT_HEADERS); 84 cxMapPut(var_names, cx_hash_key_str("insert-srvhdrs"), (void*)(intptr_t)COMMONSAF_INSERT_SRVHDRS); 85 86 cxMapPut(var_names, cx_hash_key_str("set-client"), (void*)(intptr_t)COMMONSAF_SET_CLIENT); 87 cxMapPut(var_names, cx_hash_key_str("set-vars"), (void*)(intptr_t)COMMONSAF_SET_VARS); 88 cxMapPut(var_names, cx_hash_key_str("set-reqpb"), (void*)(intptr_t)COMMONSAF_SET_REQPB); 89 cxMapPut(var_names, cx_hash_key_str("set-headers"), (void*)(intptr_t)COMMONSAF_SET_HEADERS); 90 cxMapPut(var_names, cx_hash_key_str("set-srvhdrs"), (void*)(intptr_t)COMMONSAF_SET_SRVHDRS); 91 92 cxMapPut(var_names, cx_hash_key_str("remove-client"), (void*)(intptr_t)COMMONSAF_REMOVE_CLIENT); 93 cxMapPut(var_names, cx_hash_key_str("remove-vars"), (void*)(intptr_t)COMMONSAF_REMOVE_VARS); 94 cxMapPut(var_names, cx_hash_key_str("remove-reqpb"), (void*)(intptr_t)COMMONSAF_REMOVE_REQPB); 95 cxMapPut(var_names, cx_hash_key_str("remove-headers"), (void*)(intptr_t)COMMONSAF_REMOVE_HEADERS); 96 cxMapPut(var_names, cx_hash_key_str("remove-srvhdrs"), (void*)(intptr_t)COMMONSAF_REMOVE_SRVHDRS); 97 98 cxMapPut(var_names, cx_hash_key_str("abort"), (void*)(intptr_t)COMMONSAF_ABORT); 99 cxMapPut(var_names, cx_hash_key_str("noaction"), (void*)(intptr_t)COMMONSAF_NOACTION); 100 cxMapPut(var_names, cx_hash_key_str("error"), (void*)(intptr_t)COMMONSAF_ERROR); 101 cxMapPut(var_names, cx_hash_key_str("escape"), (void*)(intptr_t)COMMONSAF_ESCAPE); 102 cxMapPut(var_names, cx_hash_key_str("find-pathinfo-forward"), (void*)(intptr_t)COMMONSAF_FIND_PATHINFO_FORWARD); 103 cxMapPut(var_names, cx_hash_key_str("http-downgrade"), (void*)(intptr_t)COMMONSAF_HTTP_DOWNGRADE); 104 cxMapPut(var_names, cx_hash_key_str("http-upgrade"), (void*)(intptr_t)COMMONSAF_HTTP_UPGRADE); 105 cxMapPut(var_names, cx_hash_key_str("keep-alive"), (void*)(intptr_t)COMMONSAF_KEEP_ALIVE); 106 cxMapPut(var_names, cx_hash_key_str("name"), (void*)(intptr_t)COMMONSAF_NAME); 107 } 108 109 int print_message(pblock *pb, Session *sn, Request *rq) { 110 char *msg = pblock_findval("msg", pb); 111 if(msg) { 112 log_ereport(LOG_INFORM, "%s", msg); 113 } 114 115 return REQ_NOACTION; 116 } 117 118 static void var_set(char *value, pblock *pb, WSBool insert) { 119 cxstring n; 120 cxstring v; 121 v.ptr = NULL; 122 123 n.ptr = value; 124 int i; 125 int len = strlen(value); 126 for(i=1;i<len;i++) { 127 if(value[i] == '=') { 128 n.length = i; 129 v = cx_strsubs(cx_strn(value, len), i + 1); 130 break; 131 } 132 } 133 if(!v.ptr || v.length == 0) { 134 log_ereport( 135 LOG_MISCONFIG, 136 "set-variable: string ''%s'' has not name=value format", 137 value); 138 return; 139 } 140 141 if(!insert) { 142 // TODO 143 } 144 pblock_nvlinsert(n.ptr, n.length, v.ptr, v.length, pb); 145 } 146 147 static int set_var(Session *sn, Request *rq, const char *var, char *value) { 148 intptr_t v = (intptr_t)cxMapGet(var_names, cx_hash_key_str(var)); 149 switch(v) { 150 default: break; 151 case COMMONSAF_INSERT_CLIENT: var_set(value, sn->client, TRUE); break; 152 case COMMONSAF_INSERT_VARS: var_set(value, rq->vars, TRUE); break; 153 case COMMONSAF_INSERT_REQPB: var_set(value, rq->reqpb, TRUE); break; 154 case COMMONSAF_INSERT_HEADERS: var_set(value, rq->headers, TRUE); break; 155 case COMMONSAF_INSERT_SRVHDRS: var_set(value, rq->srvhdrs, TRUE); break; 156 case COMMONSAF_SET_CLIENT: var_set(value, sn->client, FALSE); break; 157 case COMMONSAF_SET_VARS: var_set(value, rq->vars, FALSE); break; 158 case COMMONSAF_SET_REQPB: var_set(value, rq->reqpb, FALSE); break; 159 case COMMONSAF_SET_HEADERS: var_set(value, rq->headers, FALSE); break; 160 case COMMONSAF_SET_SRVHDRS: var_set(value, rq->srvhdrs, FALSE); break; 161 case COMMONSAF_REMOVE_CLIENT: pblock_remove(value, sn->client); break; 162 case COMMONSAF_REMOVE_VARS: pblock_remove(value, rq->vars); break; 163 case COMMONSAF_REMOVE_HEADERS: pblock_remove(value, rq->headers);break; 164 case COMMONSAF_REMOVE_SRVHDRS: pblock_remove(value, rq->srvhdrs); break; 165 case COMMONSAF_ABORT: return COMMONSAF_REQ_ABORTED; 166 case COMMONSAF_NOACTION: return COMMONSAF_RET_NOACTION; 167 case COMMONSAF_ERROR: { 168 char *end; 169 long status = strtol(value, &end, 10); 170 if(status < 100 || status > 999) { 171 log_ereport( 172 LOG_MISCONFIG, 173 "set-variable: error value must contain a 3-digit http status code"); 174 protocol_status(sn, rq, 500, NULL); 175 return COMMONSAF_RET_ERROR; 176 } 177 178 const char *msg = NULL; 179 while(isspace(*end)) { 180 end++; 181 } 182 if(*end != '\0') { 183 msg = end; 184 } 185 186 protocol_status(sn, rq, (int)status, msg); 187 188 return COMMONSAF_REQ_ABORTED; 189 } 190 case COMMONSAF_ESCAPE: break; 191 case COMMONSAF_FIND_PATHINFO_FORWARD: break; 192 case COMMONSAF_HTTP_DOWNGRADE: break; 193 case COMMONSAF_HTTP_UPGRADE: break; 194 case COMMONSAF_KEEP_ALIVE: { 195 rq->rq_attr.keep_alive = util_getboolean(var, 0); 196 break; 197 } 198 case COMMONSAF_NAME: { 199 pblock_kvinsert(pb_key_name, value, strlen(value), rq->vars); 200 break; 201 } 202 case COMMONSAF_SENTHDRS: break; 203 case COMMONSAF_STOP: return COMMONSAF_RET_STOP; 204 case COMMONSAF_URL: break; 205 } 206 return COMMONSAF_RET_DEF; 207 } 208 209 int set_variable(pblock *pb, Session *sn, Request *rq) { 210 int ret = REQ_NOACTION; 211 int set = 0; 212 213 for(int i=0;i<pb->hsize;i++) { 214 pb_entry *entry = pb->ht[i]; 215 while(entry) { 216 int r = set_var(sn, rq, entry->param->name, entry->param->value); 217 switch(r) { 218 default: 219 case COMMONSAF_RET_DEF: break; 220 case COMMONSAF_RET_NOACTION: set = 1; ret = REQ_NOACTION; break; 221 case COMMONSAF_RET_STOP: set = 1; ret = REQ_PROCEED; break; 222 case COMMONSAF_REQ_ABORTED: ret = set ? ret : REQ_ABORTED; break; 223 case COMMONSAF_RET_ERROR: return REQ_ABORTED; 224 } 225 entry = entry->next; 226 } 227 } 228 229 return ret; 230 } 231