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 "../../ucx/map.h" 37 38 static UcxMap *var_names; 39 40 enum SAFVarNames { 41 COMMONSAF_INSERT_CLIENT = 1, 42 COMMONSAF_INSERT_VARS, 43 COMMONSAF_INSERT_REQPB, 44 COMMONSAF_INSERT_HEADERS, 45 COMMONSAF_INSERT_SRVHDRS, 46 COMMONSAF_SET_CLIENT, 47 COMMONSAF_SET_VARS, 48 COMMONSAF_SET_REQPB, 49 COMMONSAF_SET_HEADERS, 50 COMMONSAF_SET_SRVHDRS, 51 COMMONSAF_REMOVE_CLIENT, 52 COMMONSAF_REMOVE_VARS, 53 COMMONSAF_REMOVE_REQPB, 54 COMMONSAF_REMOVE_HEADERS, 55 COMMONSAF_REMOVE_SRVHDRS, 56 COMMONSAF_ABORT, 57 COMMONSAF_NOACTION, 58 COMMONSAF_ERROR, 59 COMMONSAF_ESCAPE, 60 COMMONSAF_FIND_PATHINFO_FORWARD, 61 COMMONSAF_HTTP_DOWNGRADE, 62 COMMONSAF_HTTP_UPGRADE, 63 COMMONSAF_KEEP_ALIVE, 64 COMMONSAF_NAME, 65 COMMONSAF_SENTHDRS, 66 COMMONSAF_STOP, 67 COMMONSAF_URL 68 }; 69 70 #define COMMONSAF_RET_DEF 0 71 #define COMMONSAF_RET_NOACTION 1 72 #define COMMONSAF_RET_STOP 2 73 #define COMMONSAF_REQ_ABORTED -1 74 #define COMMONSAF_RET_ERROR -2 75 76 void common_saf_init() { 77 var_names = ucx_map_new(32); 78 79 ucx_map_cstr_put(var_names, "insert-client", (intptr_t)COMMONSAF_INSERT_CLIENT); 80 ucx_map_cstr_put(var_names, "insert-vars", (intptr_t)COMMONSAF_INSERT_VARS); 81 ucx_map_cstr_put(var_names, "insert-reqpb", (intptr_t)COMMONSAF_INSERT_REQPB); 82 ucx_map_cstr_put(var_names, "insert-headers", (intptr_t)COMMONSAF_INSERT_HEADERS); 83 ucx_map_cstr_put(var_names, "insert-srvhdrs", (intptr_t)COMMONSAF_INSERT_SRVHDRS); 84 85 ucx_map_cstr_put(var_names, "set-client", (intptr_t)COMMONSAF_SET_CLIENT); 86 ucx_map_cstr_put(var_names, "set-vars", (intptr_t)COMMONSAF_SET_VARS); 87 ucx_map_cstr_put(var_names, "set-reqpb", (intptr_t)COMMONSAF_SET_REQPB); 88 ucx_map_cstr_put(var_names, "set-headers", (intptr_t)COMMONSAF_SET_HEADERS); 89 ucx_map_cstr_put(var_names, "set-srvhdrs", (intptr_t)COMMONSAF_SET_SRVHDRS); 90 91 ucx_map_cstr_put(var_names, "remove-client", (intptr_t)COMMONSAF_REMOVE_CLIENT); 92 ucx_map_cstr_put(var_names, "remove-vars", (intptr_t)COMMONSAF_REMOVE_VARS); 93 ucx_map_cstr_put(var_names, "remove-reqpb", (intptr_t)COMMONSAF_REMOVE_REQPB); 94 ucx_map_cstr_put(var_names, "remove-headers", (intptr_t)COMMONSAF_REMOVE_HEADERS); 95 ucx_map_cstr_put(var_names, "remove-srvhdrs", (intptr_t)COMMONSAF_REMOVE_SRVHDRS); 96 97 ucx_map_cstr_put(var_names, "abort", (intptr_t)COMMONSAF_ABORT); 98 ucx_map_cstr_put(var_names, "noaction", (intptr_t)COMMONSAF_NOACTION); 99 ucx_map_cstr_put(var_names, "error", (intptr_t)COMMONSAF_ERROR); 100 ucx_map_cstr_put(var_names, "escape", (intptr_t)COMMONSAF_ESCAPE); 101 ucx_map_cstr_put(var_names, "find-pathinfo-forward", (intptr_t)COMMONSAF_FIND_PATHINFO_FORWARD); 102 ucx_map_cstr_put(var_names, "http-downgrade", (intptr_t)COMMONSAF_HTTP_DOWNGRADE); 103 ucx_map_cstr_put(var_names, "http-upgrade", (intptr_t)COMMONSAF_HTTP_UPGRADE); 104 ucx_map_cstr_put(var_names, "keep-alive", (intptr_t)COMMONSAF_KEEP_ALIVE); 105 ucx_map_cstr_put(var_names, "name", (intptr_t)COMMONSAF_NAME); 106 } 107 108 int print_message(pblock *pb, Session *sn, Request *rq) { 109 char *msg = pblock_findval("msg", pb); 110 if(msg) { 111 log_ereport(LOG_INFORM, "%s", msg); 112 } 113 114 return REQ_NOACTION; 115 } 116 117 static void var_set(char *value, pblock *pb, WSBool insert) { 118 sstr_t n; 119 sstr_t v; 120 v.ptr = NULL; 121 122 n.ptr = value; 123 int i; 124 int len = strlen(value); 125 for(i=1;i<len;i++) { 126 if(value[i] == '=') { 127 n.length = i; 128 v = sstrsubs(sstrn(value, len), i + 1); 129 break; 130 } 131 } 132 if(!v.ptr || v.length == 0) { 133 log_ereport( 134 LOG_MISCONFIG, 135 "set-variable: string ''%s'' has not name=value format", 136 value); 137 return; 138 } 139 140 if(!insert) { 141 // TODO 142 } 143 pblock_nvlinsert(n.ptr, n.length, v.ptr, v.length, pb); 144 } 145 146 static int set_var(Session *sn, Request *rq, char *var, char *value) { 147 intptr_t v = (intptr_t)ucx_map_cstr_get(var_names, var); 148 switch(v) { 149 default: break; 150 case COMMONSAF_INSERT_CLIENT: var_set(value, sn->client, TRUE); break; 151 case COMMONSAF_INSERT_VARS: var_set(value, rq->vars, TRUE); break; 152 case COMMONSAF_INSERT_REQPB: var_set(value, rq->reqpb, TRUE); break; 153 case COMMONSAF_INSERT_HEADERS: var_set(value, rq->headers, TRUE); break; 154 case COMMONSAF_INSERT_SRVHDRS: var_set(value, rq->srvhdrs, TRUE); break; 155 case COMMONSAF_SET_CLIENT: var_set(value, sn->client, FALSE); break; 156 case COMMONSAF_SET_VARS: var_set(value, rq->vars, FALSE); break; 157 case COMMONSAF_SET_REQPB: var_set(value, rq->reqpb, FALSE); break; 158 case COMMONSAF_SET_HEADERS: var_set(value, rq->headers, FALSE); break; 159 case COMMONSAF_SET_SRVHDRS: var_set(value, rq->srvhdrs, FALSE); break; 160 case COMMONSAF_REMOVE_CLIENT: pblock_remove(value, sn->client); break; 161 case COMMONSAF_REMOVE_VARS: pblock_remove(value, rq->vars); break; 162 case COMMONSAF_REMOVE_HEADERS: pblock_remove(value, rq->headers);break; 163 case COMMONSAF_REMOVE_SRVHDRS: pblock_remove(value, rq->srvhdrs); break; 164 case COMMONSAF_ABORT: return COMMONSAF_REQ_ABORTED; 165 case COMMONSAF_NOACTION: return COMMONSAF_RET_NOACTION; 166 case COMMONSAF_ERROR: { 167 int len = strlen(value); 168 WSBool isnum = TRUE; 169 int i; 170 for(i=0;i<len;i++) { 171 if(!isdigit(value[i])) { 172 isnum = FALSE; 173 break; 174 } 175 } 176 177 int64_t status; 178 int ret = util_strtoint(value, &status); 179 if(status < 100 || ret > 999 || !ret) { 180 log_ereport( 181 LOG_MISCONFIG, 182 "set-variable: error value must contain a 3-digit http status code"); 183 protocol_status(sn, rq, 500, NULL); 184 return COMMONSAF_RET_ERROR; 185 } 186 187 char *msg = isnum ? NULL : sstrtrim(sstr(value + i)).ptr; 188 protocol_status(sn, rq, (int)status, msg); 189 190 return COMMONSAF_REQ_ABORTED; 191 } 192 case COMMONSAF_ESCAPE: break; 193 case COMMONSAF_FIND_PATHINFO_FORWARD: break; 194 case COMMONSAF_HTTP_DOWNGRADE: break; 195 case COMMONSAF_HTTP_UPGRADE: break; 196 case COMMONSAF_KEEP_ALIVE: { 197 rq->rq_attr.keep_alive = util_getboolean(var, 0); 198 break; 199 } 200 case COMMONSAF_NAME: { 201 pblock_kvinsert(pb_key_name, value, strlen(value), rq->vars); 202 break; 203 } 204 case COMMONSAF_SENTHDRS: break; 205 case COMMONSAF_STOP: return COMMONSAF_RET_STOP; 206 case COMMONSAF_URL: break; 207 } 208 return COMMONSAF_RET_DEF; 209 } 210 211 int set_variable(pblock *pb, Session *sn, Request *rq) { 212 int ret = REQ_NOACTION; 213 int set = 0; 214 215 for(int i=0;i<pb->hsize;i++) { 216 pb_entry *entry = pb->ht[i]; 217 while(entry) { 218 int r = set_var(sn, rq, entry->param->name, entry->param->value); 219 switch(r) { 220 default: 221 case COMMONSAF_RET_DEF: break; 222 case COMMONSAF_RET_NOACTION: set = 1; ret = REQ_NOACTION; break; 223 case COMMONSAF_RET_STOP: set = 1; ret = REQ_PROCEED; break; 224 case COMMONSAF_REQ_ABORTED: ret = set ? ret : REQ_ABORTED; break; 225 case COMMONSAF_RET_ERROR: return REQ_ABORTED; 226 } 227 entry = entry->next; 228 } 229 } 230 231 return ret; 232 } 233