| File: | src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c |
| Location: | line 647, column 11 |
| Description: | Null pointer passed as an argument to a 'nonnull' parameter |
| 1 | /* | |||
| 2 | * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application | |||
| 3 | * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org> | |||
| 4 | * | |||
| 5 | * Version: MPL 1.1 | |||
| 6 | * | |||
| 7 | * The contents of this file are subject to the Mozilla Public License Version | |||
| 8 | * 1.1 (the "License"); you may not use this file except in compliance with | |||
| 9 | * the License. You may obtain a copy of the License at | |||
| 10 | * http://www.mozilla.org/MPL/ | |||
| 11 | * | |||
| 12 | * Software distributed under the License is distributed on an "AS IS" basis, | |||
| 13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License | |||
| 14 | * for the specific language governing rights and limitations under the | |||
| 15 | * License. | |||
| 16 | * | |||
| 17 | * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application | |||
| 18 | * | |||
| 19 | * The Initial Developer of the Original Code is | |||
| 20 | * Anthony Minessale II <anthm@freeswitch.org> | |||
| 21 | * Portions created by the Initial Developer are Copyright (C) | |||
| 22 | * the Initial Developer. All Rights Reserved. | |||
| 23 | * | |||
| 24 | * Contributor(s): | |||
| 25 | * | |||
| 26 | * Anthony Minessale II <anthm@freeswitch.org> | |||
| 27 | * John Wehle <john@feith.com> | |||
| 28 | * Garmt Boekholt <garmt@cimico.com> | |||
| 29 | * Seven Du <dujinfang@gmail.com> | |||
| 30 | * | |||
| 31 | * mod_xml_rpc.c -- XML RPC | |||
| 32 | * | |||
| 33 | * embedded webserver for FS | |||
| 34 | * exposes fs api to web (and ajax, javascript, ...) | |||
| 35 | * supports GET/POST requests (as defined below) | |||
| 36 | * and similar XMLRPC format /RPC2 freeswitch.api and management.api | |||
| 37 | * | |||
| 38 | * usage: | |||
| 39 | * (1) http:/host:port/[txt|web|xml]api/fsapicommand[?arg[ arg]*][ &key=value[+&key=value]*] | |||
| 40 | * e.g. http:/host:port/api/show?calls &refresh=5+&weather=nice | |||
| 41 | * (2) http:/host:port/filepath - serves files from conf/htdocs | |||
| 42 | * | |||
| 43 | * NB: | |||
| 44 | * ad (1) - key/value pairs are propagated as event headers | |||
| 45 | * - if &key=value is "&refresh=xx" - special feature: automatic refresh after xx sec (triggered by browser) | |||
| 46 | * note that refresh works only | |||
| 47 | * IF response content-type: text/html (i.e. "webapi" or "api") | |||
| 48 | * AND fs api command created an event header HTTP-REFRESH before the first write_stream | |||
| 49 | * NOTE if "api", fs api command has to overwrite content-type to be text/html i.s.o. text/plain (default) | |||
| 50 | * | |||
| 51 | * - if api format is "api" mod_xml_rpc will automatically assume plain/text (so webunaware fs commands are rendered apropriately) | |||
| 52 | * - xmlapi doesn't seem to be used, however if a fs api command renders xml, you can set the format type to xml | |||
| 53 | * txtapi-text/plain or webapi-text/html surround xml with <pre> xml <pre/> | |||
| 54 | * - typically fs api command arguments are encoded with UrlPathEncode (spaces -> %20), and k/v pairs are urlencoded (space -> +) | |||
| 55 | * | |||
| 56 | * ad (2) ms ie may show extra empty lines when serving large txt files as ie has problems rendering content-type "plain/text" | |||
| 57 | * | |||
| 58 | */ | |||
| 59 | #include <switch.h> | |||
| 60 | #ifdef _MSC_VER | |||
| 61 | #pragma warning(disable:4142) | |||
| 62 | #endif | |||
| 63 | ||||
| 64 | #include <xmlrpc-c/base.h> | |||
| 65 | #include <xmlrpc-c/abyss.h> | |||
| 66 | #include <xmlrpc-c/server.h> | |||
| 67 | #include <xmlrpc-c/server_abyss.h> | |||
| 68 | #include <xmlrpc-c/base64_int.h> | |||
| 69 | #include <../lib/abyss/src/token.h> | |||
| 70 | #include <../lib/abyss/src/http.h> | |||
| 71 | #include <../lib/abyss/src/session.h> | |||
| 72 | #include "ws.h" | |||
| 73 | ||||
| 74 | SWITCH_MODULE_LOAD_FUNCTION(mod_xml_rpc_load)switch_status_t mod_xml_rpc_load (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool); | |||
| 75 | SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_rpc_shutdown)switch_status_t mod_xml_rpc_shutdown (void); | |||
| 76 | SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime)switch_status_t mod_xml_rpc_runtime (void); | |||
| 77 | SWITCH_MODULE_DEFINITION(mod_xml_rpc, mod_xml_rpc_load, mod_xml_rpc_shutdown, mod_xml_rpc_runtime)static const char modname[] = "mod_xml_rpc" ; __attribute__(( visibility("default"))) switch_loadable_module_function_table_t mod_xml_rpc_module_interface = { 5, mod_xml_rpc_load, mod_xml_rpc_shutdown , mod_xml_rpc_runtime, SMODF_NONE }; | |||
| 78 | ||||
| 79 | static abyss_bool HTTPWrite(TSession * s, const char *buffer, const uint32_t len); | |||
| 80 | ||||
| 81 | static struct { | |||
| 82 | uint16_t port; | |||
| 83 | uint8_t running; | |||
| 84 | char *realm; | |||
| 85 | char *user; | |||
| 86 | char *pass; | |||
| 87 | char *default_domain; | |||
| 88 | switch_bool_t virtual_host; | |||
| 89 | TServer abyssServer; | |||
| 90 | xmlrpc_registry *registryP; | |||
| 91 | switch_bool_t enable_websocket; | |||
| 92 | char *commands_to_log; | |||
| 93 | } globals; | |||
| 94 | ||||
| 95 | SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_realm, globals.realm)static void set_global_realm(const char *string) { if (!string ) return; if (globals.realm) {free(globals.realm); globals.realm = ((void*)0);}globals.realm = (__extension__ (__builtin_constant_p (string) && ((size_t)(const void *)((string) + 1) - ( size_t)(const void *)(string) == 1) ? (((const char *) (string ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (string) + 1; char *__retval = (char * ) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, string, __len); __retval; })) : __strdup (string)));} static void set_global_realm(const char *string ); | |||
| 96 | SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_user, globals.user)static void set_global_user(const char *string) { if (!string ) return; if (globals.user) {free(globals.user); globals.user = ((void*)0);}globals.user = (__extension__ (__builtin_constant_p (string) && ((size_t)(const void *)((string) + 1) - ( size_t)(const void *)(string) == 1) ? (((const char *) (string ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (string) + 1; char *__retval = (char * ) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, string, __len); __retval; })) : __strdup (string)));} static void set_global_user(const char *string); | |||
| 97 | SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_pass, globals.pass)static void set_global_pass(const char *string) { if (!string ) return; if (globals.pass) {free(globals.pass); globals.pass = ((void*)0);}globals.pass = (__extension__ (__builtin_constant_p (string) && ((size_t)(const void *)((string) + 1) - ( size_t)(const void *)(string) == 1) ? (((const char *) (string ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (string) + 1; char *__retval = (char * ) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, string, __len); __retval; })) : __strdup (string)));} static void set_global_pass(const char *string); | |||
| 98 | SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_default_domain, globals.default_domain)static void set_global_default_domain(const char *string) { if (!string) return; if (globals.default_domain) {free(globals. default_domain); globals.default_domain = ((void*)0);}globals .default_domain = (__extension__ (__builtin_constant_p (string ) && ((size_t)(const void *)((string) + 1) - (size_t) (const void *)(string) == 1) ? (((const char *) (string))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (string) + 1; char *__retval = (char *) malloc (__len ); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval , string, __len); __retval; })) : __strdup (string)));} static void set_global_default_domain(const char *string); | |||
| 99 | ||||
| 100 | static switch_status_t do_config(void) | |||
| 101 | { | |||
| 102 | char *cf = "xml_rpc.conf"; | |||
| 103 | switch_xml_t cfg, xml, settings, param; | |||
| 104 | char *realm, *user, *pass, *default_domain; | |||
| 105 | ||||
| 106 | default_domain = realm = user = pass = NULL((void*)0); | |||
| 107 | globals.commands_to_log = NULL((void*)0); | |||
| 108 | ||||
| 109 | if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL((void*)0)))) { | |||
| 110 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 110, ((void*)0), SWITCH_LOG_ERROR, "Open of %s failed\n", cf); | |||
| 111 | return SWITCH_STATUS_TERM; | |||
| 112 | } | |||
| 113 | ||||
| 114 | globals.virtual_host = SWITCH_TRUE; | |||
| 115 | ||||
| 116 | if ((settings = switch_xml_child(cfg, "settings"))) { | |||
| 117 | for (param = switch_xml_child(settings, "param"); param; param = param->next) { | |||
| 118 | char *var = (char *) switch_xml_attr_soft(param, "name"); | |||
| 119 | char *val = (char *) switch_xml_attr_soft(param, "value"); | |||
| 120 | ||||
| 121 | if (!zstr(var)_zstr(var) && !zstr(val)_zstr(val)) { | |||
| 122 | if (!strcasecmp(var, "auth-realm")) { | |||
| 123 | realm = val; | |||
| 124 | } else if (!strcasecmp(var, "auth-user")) { | |||
| 125 | user = val; | |||
| 126 | } else if (!strcasecmp(var, "auth-pass")) { | |||
| 127 | pass = val; | |||
| 128 | } else if (!strcasecmp(var, "http-port")) { | |||
| 129 | globals.port = (uint16_t) atoi(val); | |||
| 130 | } else if (!strcasecmp(var, "default-domain")) { | |||
| 131 | default_domain = val; | |||
| 132 | } else if (!strcasecmp(var, "virtual-host")) { | |||
| 133 | globals.virtual_host = switch_true(val); | |||
| 134 | } else if (!strcasecmp(var, "enable-websocket")) { | |||
| 135 | globals.enable_websocket = switch_true(val); | |||
| 136 | } else if (!strcasecmp(var, "commands-to-log")) { | |||
| 137 | globals.commands_to_log = val; | |||
| 138 | } | |||
| 139 | } | |||
| 140 | } | |||
| 141 | } | |||
| 142 | ||||
| 143 | if (!globals.port) { | |||
| 144 | globals.port = 8080; | |||
| 145 | } | |||
| 146 | if (realm) { | |||
| 147 | set_global_realm(realm); | |||
| 148 | if (user && pass) { | |||
| 149 | set_global_user(user); | |||
| 150 | set_global_pass(pass); | |||
| 151 | } | |||
| 152 | } | |||
| 153 | if (default_domain) { | |||
| 154 | set_global_default_domain(default_domain); | |||
| 155 | } | |||
| 156 | switch_xml_free(xml); | |||
| 157 | ||||
| 158 | return SWITCH_STATUS_SUCCESS; | |||
| 159 | } | |||
| 160 | ||||
| 161 | SWITCH_MODULE_LOAD_FUNCTION(mod_xml_rpc_load)switch_status_t mod_xml_rpc_load (switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) | |||
| 162 | { | |||
| 163 | /* connect my internal structure to the blank pointer passed to me */ | |||
| 164 | *module_interface = switch_loadable_module_create_module_interface(pool, modname); | |||
| 165 | ||||
| 166 | memset(&globals, 0, sizeof(globals)); | |||
| 167 | ||||
| 168 | do_config(); | |||
| 169 | ||||
| 170 | /* indicate that the module should continue to be loaded */ | |||
| 171 | return SWITCH_STATUS_SUCCESS; | |||
| 172 | } | |||
| 173 | ||||
| 174 | static switch_status_t http_stream_raw_write(switch_stream_handle_t *handle, uint8_t *data, switch_size_t datalen) | |||
| 175 | { | |||
| 176 | TSession *r = (TSession *) handle->data; | |||
| 177 | ||||
| 178 | return HTTPWrite(r, (char *) data, (uint32_t) datalen) ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; | |||
| 179 | ||||
| 180 | } | |||
| 181 | ||||
| 182 | static switch_status_t http_stream_write(switch_stream_handle_t *handle, const char *fmt, ...) | |||
| 183 | { | |||
| 184 | TSession *r = (TSession *) handle->data; | |||
| 185 | int ret = 1; | |||
| 186 | char *data; | |||
| 187 | switch_event_t *evnt = handle->param_event; | |||
| 188 | va_list ap; | |||
| 189 | ||||
| 190 | va_start(ap, fmt)__builtin_va_start(ap, fmt); | |||
| 191 | ret = switch_vasprintf(&data, fmt, ap); | |||
| 192 | va_end(ap)__builtin_va_end(ap); | |||
| 193 | ||||
| 194 | if (data) { | |||
| 195 | /* Stream Content-Type (http header) to the xmlrpc (web) client, if fs api command did not do it yet. */ | |||
| 196 | /* If (Content-Type in event) then the header was already replied. */ | |||
| 197 | /* If fs api command is not "web aware", this will set the Content-Type to "text/plain". */ | |||
| 198 | const char *http_refresh = NULL((void*)0); | |||
| 199 | const char *ct = NULL((void*)0); | |||
| 200 | const char *refresh = NULL((void*)0); | |||
| 201 | if (evnt && !(ct = switch_event_get_header(evnt, "Content-Type")switch_event_get_header_idx(evnt, "Content-Type", -1))){ | |||
| 202 | const char *val = switch_stristr("Content-Type", data); | |||
| 203 | if (!val) { | |||
| 204 | val = "Content-Type: text/plain\r\n\r\n"; | |||
| 205 | ret = HTTPWrite(r, val, (uint32_t) strlen(val)); | |||
| 206 | } | |||
| 207 | /* flag to prevent running this more than once per http reply */ | |||
| 208 | switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", strstr(val,":")+2); | |||
| 209 | ct = switch_event_get_header(evnt, "Content-Type")switch_event_get_header_idx(evnt, "Content-Type", -1); | |||
| 210 | } | |||
| 211 | ||||
| 212 | if (ret) { | |||
| 213 | ret = HTTPWrite(r, data, (uint32_t) strlen(data)); | |||
| 214 | } | |||
| 215 | switch_safe_free(data)if (data) {free(data);data=((void*)0);}; | |||
| 216 | ||||
| 217 | /* e.g. "http://www.cluecon.fs/api/show?calls &refresh=5" */ | |||
| 218 | /* fs api command can set event header "HTTP-REFRESH" so that the web page will automagically refresh, if */ | |||
| 219 | /* "refresh=xxx" was part of the http query kv pairs */ | |||
| 220 | if (ret && ct && *ct && (http_refresh = switch_event_get_header(evnt, "HTTP-REFRESH")switch_event_get_header_idx(evnt, "HTTP-REFRESH", -1)) | |||
| 221 | && (refresh = switch_event_get_header(evnt, "refresh")switch_event_get_header_idx(evnt, "refresh", -1)) | |||
| 222 | && !strstr("text/html", ct) | |||
| 223 | && (atoi(refresh) > 0 )) { | |||
| 224 | const char *query = switch_event_get_header(evnt, "HTTP-QUERY")switch_event_get_header_idx(evnt, "HTTP-QUERY", -1); | |||
| 225 | const char *uri = switch_event_get_header(evnt, "HTTP-URI")switch_event_get_header_idx(evnt, "HTTP-URI", -1); | |||
| 226 | if (uri && query && *uri && *query) { | |||
| 227 | char *buf = switch_mprintf("<META HTTP-EQUIV=REFRESH CONTENT=\"%s; URL=%s?%s\">\n", refresh, uri, query); | |||
| 228 | ret = HTTPWrite(r, buf, (uint32_t) strlen(buf)); | |||
| 229 | switch_safe_free(buf)if (buf) {free(buf);buf=((void*)0);}; | |||
| 230 | } | |||
| 231 | } | |||
| 232 | ||||
| 233 | /* only one refresh meta header per reply */ | |||
| 234 | if (http_refresh) { | |||
| 235 | switch_event_del_header(evnt, "HTTP-REFRESH")switch_event_del_header_val(evnt, "HTTP-REFRESH", ((void*)0)); | |||
| 236 | } | |||
| 237 | } | |||
| 238 | ||||
| 239 | return ret ? SWITCH_STATUS_FALSE : SWITCH_STATUS_SUCCESS; | |||
| 240 | } | |||
| 241 | ||||
| 242 | static abyss_bool user_attributes(const char *user, const char *domain_name, | |||
| 243 | const char **ppasswd, const char **pvm_passwd, const char **palias, const char **pallowed_commands) | |||
| 244 | { | |||
| 245 | const char *passwd; | |||
| 246 | const char *vm_passwd; | |||
| 247 | const char *alias; | |||
| 248 | const char *allowed_commands; | |||
| 249 | switch_event_t *params; | |||
| 250 | switch_xml_t x_user, x_params, x_param; | |||
| 251 | ||||
| 252 | passwd = NULL((void*)0); | |||
| 253 | vm_passwd = NULL((void*)0); | |||
| 254 | alias = NULL((void*)0); | |||
| 255 | allowed_commands = NULL((void*)0); | |||
| 256 | ||||
| 257 | if (ppasswd) *ppasswd = NULL((void*)0); | |||
| 258 | if (pvm_passwd) *pvm_passwd = NULL((void*)0); | |||
| 259 | if (palias) *palias = NULL((void*)0); | |||
| 260 | if (pallowed_commands) *pallowed_commands = NULL((void*)0); | |||
| 261 | ||||
| 262 | params = NULL((void*)0); | |||
| 263 | ||||
| 264 | switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS)switch_event_create_subclass_detailed("mod_xml_rpc.c", (const char * )(const char *)__func__, 264, ¶ms, SWITCH_EVENT_REQUEST_PARAMS , ((void*)0)); | |||
| 265 | switch_assert(params)((params) ? (void) (0) : __assert_fail ("params", "mod_xml_rpc.c" , 265, __PRETTY_FUNCTION__)); | |||
| 266 | switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "number_alias", "check"); | |||
| 267 | ||||
| 268 | ||||
| 269 | if (switch_xml_locate_user_merged("id", user, domain_name, NULL((void*)0), &x_user, params) != SWITCH_STATUS_SUCCESS) { | |||
| 270 | switch_event_destroy(¶ms); | |||
| 271 | return FALSE0; | |||
| 272 | } | |||
| 273 | ||||
| 274 | switch_event_destroy(¶ms); | |||
| 275 | alias = switch_xml_attr(x_user, "number-alias"); | |||
| 276 | ||||
| 277 | if ((x_params = switch_xml_child(x_user, "params"))) { | |||
| 278 | for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) { | |||
| 279 | const char *var = switch_xml_attr_soft(x_param, "name"); | |||
| 280 | const char *val = switch_xml_attr_soft(x_param, "value"); | |||
| 281 | ||||
| 282 | if (!strcasecmp(var, "password")) { | |||
| 283 | passwd = val; | |||
| 284 | } else if (!strcasecmp(var, "vm-password")) { | |||
| 285 | vm_passwd = val; | |||
| 286 | } else if (!strcasecmp(var, "http-allowed-api")) { | |||
| 287 | allowed_commands = val; | |||
| 288 | } | |||
| 289 | } | |||
| 290 | } | |||
| 291 | ||||
| 292 | if (ppasswd && passwd) { | |||
| 293 | *ppasswd = strdup(passwd)(__extension__ (__builtin_constant_p (passwd) && ((size_t )(const void *)((passwd) + 1) - (size_t)(const void *)(passwd ) == 1) ? (((const char *) (passwd))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (passwd) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, passwd, __len ); __retval; })) : __strdup (passwd))); | |||
| 294 | } | |||
| 295 | ||||
| 296 | if (pvm_passwd && vm_passwd) { | |||
| 297 | *pvm_passwd = strdup(vm_passwd)(__extension__ (__builtin_constant_p (vm_passwd) && ( (size_t)(const void *)((vm_passwd) + 1) - (size_t)(const void *)(vm_passwd) == 1) ? (((const char *) (vm_passwd))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (vm_passwd) + 1; char *__retval = (char *) malloc ( __len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, vm_passwd, __len); __retval; })) : __strdup (vm_passwd ))); | |||
| 298 | } | |||
| 299 | ||||
| 300 | if (palias && alias) { | |||
| 301 | *palias = strdup(alias)(__extension__ (__builtin_constant_p (alias) && ((size_t )(const void *)((alias) + 1) - (size_t)(const void *)(alias) == 1) ? (((const char *) (alias))[0] == '\0' ? (char *) calloc ( (size_t) 1, (size_t) 1) : ({ size_t __len = strlen (alias) + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, alias, __len ); __retval; })) : __strdup (alias))); | |||
| 302 | } | |||
| 303 | ||||
| 304 | if (pallowed_commands && allowed_commands) { | |||
| 305 | *pallowed_commands = strdup(allowed_commands)(__extension__ (__builtin_constant_p (allowed_commands) && ((size_t)(const void *)((allowed_commands) + 1) - (size_t)(const void *)(allowed_commands) == 1) ? (((const char *) (allowed_commands ))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (allowed_commands) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, allowed_commands, __len); __retval ; })) : __strdup (allowed_commands))); | |||
| 306 | } | |||
| 307 | ||||
| 308 | if (x_user) { | |||
| 309 | switch_xml_free(x_user); | |||
| 310 | } | |||
| 311 | ||||
| 312 | return TRUE(!0); | |||
| 313 | } | |||
| 314 | ||||
| 315 | static abyss_bool is_authorized(const TSession * r, const char *command) | |||
| 316 | { | |||
| 317 | char *user = NULL((void*)0), *domain_name = NULL((void*)0); | |||
| 318 | char *allowed_commands = NULL((void*)0); | |||
| 319 | char *dp; | |||
| 320 | char *dup = NULL((void*)0); | |||
| 321 | char *argv[256] = { 0 }; | |||
| 322 | int argc = 0, i = 0, ok = 0; | |||
| 323 | unsigned int err = 403; | |||
| 324 | ||||
| 325 | if (!r) { | |||
| 326 | return FALSE0; | |||
| 327 | } | |||
| 328 | ||||
| 329 | if (zstr(globals.realm)_zstr(globals.realm) && zstr(globals.user)_zstr(globals.user)) { | |||
| 330 | return TRUE(!0); | |||
| 331 | } | |||
| 332 | ||||
| 333 | if (!r->requestInfo.user) { | |||
| 334 | return FALSE0; | |||
| 335 | } | |||
| 336 | ||||
| 337 | user = strdup(r->requestInfo.user)(__extension__ (__builtin_constant_p (r->requestInfo.user) && ((size_t)(const void *)((r->requestInfo.user) + 1) - (size_t)(const void *)(r->requestInfo.user) == 1) ? ( ((const char *) (r->requestInfo.user))[0] == '\0' ? (char * ) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( r->requestInfo.user) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, r->requestInfo.user, __len); __retval; })) : __strdup (r->requestInfo.user))); | |||
| 338 | ||||
| 339 | if ((dp = strchr(user, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p (user) && ('@') == '\0' ? (char *) __rawmemchr (user , '@') : __builtin_strchr (user, '@'))))) { | |||
| 340 | *dp++ = '\0'; | |||
| 341 | domain_name = dp; | |||
| 342 | } | |||
| 343 | ||||
| 344 | if (!zstr(globals.realm)_zstr(globals.realm) && !zstr(globals.user)_zstr(globals.user) && !strcmp(user, globals.user)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (user) && __builtin_constant_p (globals.user) && (__s1_len = __builtin_strlen (user), __s2_len = __builtin_strlen (globals.user), (!((size_t)(const void *)((user) + 1) - (size_t )(const void *)(user) == 1) || __s1_len >= 4) && ( !((size_t)(const void *)((globals.user) + 1) - (size_t)(const void *)(globals.user) == 1) || __s2_len >= 4)) ? __builtin_strcmp (user, globals.user) : (__builtin_constant_p (user) && ((size_t)(const void *)((user) + 1) - (size_t)(const void *) (user) == 1) && (__s1_len = __builtin_strlen (user), __s1_len < 4) ? (__builtin_constant_p (globals.user) && (( size_t)(const void *)((globals.user) + 1) - (size_t)(const void *)(globals.user) == 1) ? __builtin_strcmp (user, globals.user ) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (globals.user); int __result = (((const unsigned char *) (const char *) (user))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (user))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (user))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char * ) (const char *) (user))[3] - __s2[3]); } } __result; }))) : ( __builtin_constant_p (globals.user) && ((size_t)(const void *)((globals.user) + 1) - (size_t)(const void *)(globals .user) == 1) && (__s2_len = __builtin_strlen (globals .user), __s2_len < 4) ? (__builtin_constant_p (user) && ((size_t)(const void *)((user) + 1) - (size_t)(const void *) (user) == 1) ? __builtin_strcmp (user, globals.user) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (user); int __result = (((const unsigned char *) (const char *) (globals.user))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (globals.user))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (globals.user))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (globals.user))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (user, globals.user)))); })) { | |||
| 345 | ok = 1; | |||
| 346 | goto end; | |||
| 347 | } | |||
| 348 | ||||
| 349 | if (zstr(user)_zstr(user) || zstr(domain_name)_zstr(domain_name)) { | |||
| 350 | goto end; | |||
| 351 | } | |||
| 352 | ||||
| 353 | ||||
| 354 | err = 686; | |||
| 355 | ||||
| 356 | if (!user_attributes(user, domain_name, NULL((void*)0), NULL((void*)0), NULL((void*)0), &allowed_commands)) { | |||
| 357 | goto end; | |||
| 358 | } | |||
| 359 | ||||
| 360 | switch_safe_free(user)if (user) {free(user);user=((void*)0);}; | |||
| 361 | ||||
| 362 | if (!allowed_commands) { | |||
| 363 | goto end; | |||
| 364 | } | |||
| 365 | ||||
| 366 | if ((dup = allowed_commands)) { | |||
| 367 | argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))); | |||
| 368 | ||||
| 369 | for (i = 0; i < argc && argv[i]; i++) { | |||
| 370 | if (!strcasecmp(argv[i], command) || !strcasecmp(argv[i], "any")) { | |||
| 371 | ok = 1; | |||
| 372 | break; | |||
| 373 | } | |||
| 374 | } | |||
| 375 | } | |||
| 376 | ||||
| 377 | end: | |||
| 378 | ||||
| 379 | switch_safe_free(user)if (user) {free(user);user=((void*)0);}; | |||
| 380 | switch_safe_free(dup)if (dup) {free(dup);dup=((void*)0);}; | |||
| 381 | ||||
| 382 | if (!ok) { | |||
| 383 | ResponseStatus(r, (xmlrpc_uint16_t)err); | |||
| 384 | } | |||
| 385 | ||||
| 386 | ||||
| 387 | return ok ? TRUE(!0) : FALSE0; | |||
| 388 | } | |||
| 389 | ||||
| 390 | static abyss_bool http_directory_auth(TSession *r, char *domain_name) | |||
| 391 | { | |||
| 392 | char *p = NULL((void*)0); | |||
| 393 | char *x = NULL((void*)0); | |||
| 394 | char z[256] = "", t[80] = ""; | |||
| 395 | char user[512] = "" ; | |||
| 396 | char *pass = NULL((void*)0); | |||
| 397 | const char *mypass1 = NULL((void*)0), *mypass2 = NULL((void*)0); | |||
| 398 | const char *box = NULL((void*)0); | |||
| 399 | int at = 0; | |||
| 400 | char *dp = NULL((void*)0); | |||
| 401 | abyss_bool rval = FALSE0; | |||
| 402 | char *dup_domain = NULL((void*)0); | |||
| 403 | ||||
| 404 | p = RequestHeaderValue(r, "authorization"); | |||
| 405 | ||||
| 406 | if (p) { | |||
| 407 | NextToken((const char **const) &p); | |||
| 408 | x = GetToken(&p); | |||
| 409 | if (x) { | |||
| 410 | if (!strcasecmp(x, "basic")) { | |||
| 411 | NextToken((const char **const) &p); | |||
| 412 | switch_b64_decode(p, user, sizeof(user)); | |||
| 413 | if ((pass = strchr(user, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p (user) && (':') == '\0' ? (char *) __rawmemchr (user , ':') : __builtin_strchr (user, ':'))))) { | |||
| 414 | *pass++ = '\0'; | |||
| 415 | } | |||
| 416 | ||||
| 417 | if ((dp = strchr(user, '@')(__extension__ (__builtin_constant_p ('@') && !__builtin_constant_p (user) && ('@') == '\0' ? (char *) __rawmemchr (user , '@') : __builtin_strchr (user, '@'))))) { | |||
| 418 | *dp++ = '\0'; | |||
| 419 | domain_name = dp; | |||
| 420 | at++; | |||
| 421 | } | |||
| 422 | ||||
| 423 | if (!domain_name) { | |||
| 424 | if (globals.virtual_host) { | |||
| 425 | if ((domain_name = (char *) r->requestInfo.host)) { | |||
| 426 | if (!strncasecmp(domain_name, "www.", 3)) { | |||
| 427 | domain_name += 4; | |||
| 428 | } | |||
| 429 | } | |||
| 430 | } | |||
| 431 | if (!domain_name) { | |||
| 432 | if (globals.default_domain) { | |||
| 433 | domain_name = globals.default_domain; | |||
| 434 | } else { | |||
| 435 | if ((dup_domain = switch_core_get_domain(SWITCH_TRUE))) { | |||
| 436 | domain_name = dup_domain; | |||
| 437 | } | |||
| 438 | } | |||
| 439 | } | |||
| 440 | } | |||
| 441 | ||||
| 442 | if (zstr(user)_zstr(user) || zstr(domain_name)_zstr(domain_name)) { | |||
| 443 | goto fail; | |||
| 444 | } | |||
| 445 | ||||
| 446 | if (!zstr(globals.realm)_zstr(globals.realm) && !zstr(globals.user)_zstr(globals.user) && !zstr(globals.pass)_zstr(globals.pass)) { | |||
| 447 | if (at) { | |||
| 448 | switch_snprintf(z, sizeof(z), "%s@%s:%s", globals.user, globals.realm, globals.pass); | |||
| 449 | } else { | |||
| 450 | switch_snprintf(z, sizeof(z), "%s:%s", globals.user, globals.pass); | |||
| 451 | } | |||
| 452 | xmlrpc_base64Encode(z, t); | |||
| 453 | ||||
| 454 | if (!strcmp(p, t)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (p) && __builtin_constant_p (t) && (__s1_len = __builtin_strlen (p), __s2_len = __builtin_strlen (t), (!( (size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) || __s1_len >= 4) && (!((size_t)(const void *) ((t) + 1) - (size_t)(const void *)(t) == 1) || __s2_len >= 4)) ? __builtin_strcmp (p, t) : (__builtin_constant_p (p) && ((size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) && (__s1_len = __builtin_strlen (p), __s1_len < 4) ? (__builtin_constant_p (t) && ((size_t)(const void *)((t) + 1) - (size_t)(const void *)(t) == 1) ? __builtin_strcmp (p, t) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (t); int __result = (((const unsigned char *) (const char *) (p))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (p))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (p))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (p))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (t) && ((size_t)(const void *)((t) + 1) - (size_t)(const void *)(t) == 1) && (__s2_len = __builtin_strlen (t) , __s2_len < 4) ? (__builtin_constant_p (p) && ((size_t )(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) ? __builtin_strcmp (p, t) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (p); int __result = (((const unsigned char *) (const char *) (t))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (t))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (t))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (t))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (p, t)))); })) { | |||
| 455 | goto authed; | |||
| 456 | } | |||
| 457 | } | |||
| 458 | ||||
| 459 | if (!user_attributes(user, domain_name, &mypass1, &mypass2, &box, NULL((void*)0))) { | |||
| 460 | goto fail; | |||
| 461 | } | |||
| 462 | ||||
| 463 | ||||
| 464 | if (!zstr(mypass2)_zstr(mypass2) && !strcasecmp(mypass2, "user-choose")) { | |||
| 465 | switch_safe_free(mypass2)if (mypass2) {free(mypass2);mypass2=((void*)0);}; | |||
| 466 | } | |||
| 467 | ||||
| 468 | if (!mypass1) { | |||
| 469 | goto authed; | |||
| 470 | } else { | |||
| 471 | if (at) { | |||
| 472 | switch_snprintf(z, sizeof(z), "%s@%s:%s", user, domain_name, mypass1); | |||
| 473 | } else { | |||
| 474 | switch_snprintf(z, sizeof(z), "%s:%s", user, mypass1); | |||
| 475 | } | |||
| 476 | xmlrpc_base64Encode(z, t); | |||
| 477 | ||||
| 478 | if (!strcmp(p, t)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (p) && __builtin_constant_p (t) && (__s1_len = __builtin_strlen (p), __s2_len = __builtin_strlen (t), (!( (size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) || __s1_len >= 4) && (!((size_t)(const void *) ((t) + 1) - (size_t)(const void *)(t) == 1) || __s2_len >= 4)) ? __builtin_strcmp (p, t) : (__builtin_constant_p (p) && ((size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) && (__s1_len = __builtin_strlen (p), __s1_len < 4) ? (__builtin_constant_p (t) && ((size_t)(const void *)((t) + 1) - (size_t)(const void *)(t) == 1) ? __builtin_strcmp (p, t) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (t); int __result = (((const unsigned char *) (const char *) (p))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (p))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (p))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (p))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (t) && ((size_t)(const void *)((t) + 1) - (size_t)(const void *)(t) == 1) && (__s2_len = __builtin_strlen (t) , __s2_len < 4) ? (__builtin_constant_p (p) && ((size_t )(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) ? __builtin_strcmp (p, t) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (p); int __result = (((const unsigned char *) (const char *) (t))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (t))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (t))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (t))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (p, t)))); })) { | |||
| 479 | goto authed; | |||
| 480 | } | |||
| 481 | ||||
| 482 | if (mypass2) { | |||
| 483 | if (at) { | |||
| 484 | switch_snprintf(z, sizeof(z), "%s@%s:%s", user, domain_name, mypass2); | |||
| 485 | } else { | |||
| 486 | switch_snprintf(z, sizeof(z), "%s:%s", user, mypass2); | |||
| 487 | } | |||
| 488 | xmlrpc_base64Encode(z, t); | |||
| 489 | ||||
| 490 | if (!strcmp(p, t)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (p) && __builtin_constant_p (t) && (__s1_len = __builtin_strlen (p), __s2_len = __builtin_strlen (t), (!( (size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) || __s1_len >= 4) && (!((size_t)(const void *) ((t) + 1) - (size_t)(const void *)(t) == 1) || __s2_len >= 4)) ? __builtin_strcmp (p, t) : (__builtin_constant_p (p) && ((size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) && (__s1_len = __builtin_strlen (p), __s1_len < 4) ? (__builtin_constant_p (t) && ((size_t)(const void *)((t) + 1) - (size_t)(const void *)(t) == 1) ? __builtin_strcmp (p, t) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (t); int __result = (((const unsigned char *) (const char *) (p))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (p))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (p))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (p))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (t) && ((size_t)(const void *)((t) + 1) - (size_t)(const void *)(t) == 1) && (__s2_len = __builtin_strlen (t) , __s2_len < 4) ? (__builtin_constant_p (p) && ((size_t )(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) ? __builtin_strcmp (p, t) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (p); int __result = (((const unsigned char *) (const char *) (t))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (t))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (t))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (t))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (p, t)))); })) { | |||
| 491 | goto authed; | |||
| 492 | } | |||
| 493 | } | |||
| 494 | ||||
| 495 | if (box) { | |||
| 496 | if (at) { | |||
| 497 | switch_snprintf(z, sizeof(z), "%s@%s:%s", box, domain_name, mypass1); | |||
| 498 | } else { | |||
| 499 | switch_snprintf(z, sizeof(z), "%s:%s", box, mypass1); | |||
| 500 | } | |||
| 501 | xmlrpc_base64Encode(z, t); | |||
| 502 | ||||
| 503 | if (!strcmp(p, t)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (p) && __builtin_constant_p (t) && (__s1_len = __builtin_strlen (p), __s2_len = __builtin_strlen (t), (!( (size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) || __s1_len >= 4) && (!((size_t)(const void *) ((t) + 1) - (size_t)(const void *)(t) == 1) || __s2_len >= 4)) ? __builtin_strcmp (p, t) : (__builtin_constant_p (p) && ((size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) && (__s1_len = __builtin_strlen (p), __s1_len < 4) ? (__builtin_constant_p (t) && ((size_t)(const void *)((t) + 1) - (size_t)(const void *)(t) == 1) ? __builtin_strcmp (p, t) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (t); int __result = (((const unsigned char *) (const char *) (p))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (p))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (p))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (p))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (t) && ((size_t)(const void *)((t) + 1) - (size_t)(const void *)(t) == 1) && (__s2_len = __builtin_strlen (t) , __s2_len < 4) ? (__builtin_constant_p (p) && ((size_t )(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) ? __builtin_strcmp (p, t) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (p); int __result = (((const unsigned char *) (const char *) (t))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (t))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (t))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (t))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (p, t)))); })) { | |||
| 504 | goto authed; | |||
| 505 | } | |||
| 506 | ||||
| 507 | if (mypass2) { | |||
| 508 | if (at) { | |||
| 509 | switch_snprintf(z, sizeof(z), "%s@%s:%s", box, domain_name, mypass2); | |||
| 510 | } else { | |||
| 511 | switch_snprintf(z, sizeof(z), "%s:%s", box, mypass2); | |||
| 512 | } | |||
| 513 | ||||
| 514 | xmlrpc_base64Encode(z, t); | |||
| 515 | ||||
| 516 | if (!strcmp(p, t)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (p) && __builtin_constant_p (t) && (__s1_len = __builtin_strlen (p), __s2_len = __builtin_strlen (t), (!( (size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) || __s1_len >= 4) && (!((size_t)(const void *) ((t) + 1) - (size_t)(const void *)(t) == 1) || __s2_len >= 4)) ? __builtin_strcmp (p, t) : (__builtin_constant_p (p) && ((size_t)(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) && (__s1_len = __builtin_strlen (p), __s1_len < 4) ? (__builtin_constant_p (t) && ((size_t)(const void *)((t) + 1) - (size_t)(const void *)(t) == 1) ? __builtin_strcmp (p, t) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (t); int __result = (((const unsigned char *) (const char *) (p))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (p))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (p))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (p))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (t) && ((size_t)(const void *)((t) + 1) - (size_t)(const void *)(t) == 1) && (__s2_len = __builtin_strlen (t) , __s2_len < 4) ? (__builtin_constant_p (p) && ((size_t )(const void *)((p) + 1) - (size_t)(const void *)(p) == 1) ? __builtin_strcmp (p, t) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (p); int __result = (((const unsigned char *) (const char *) (t))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (t))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (t))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (t))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (p, t)))); })) { | |||
| 517 | goto authed; | |||
| 518 | } | |||
| 519 | } | |||
| 520 | } | |||
| 521 | } | |||
| 522 | goto fail; | |||
| 523 | ||||
| 524 | authed: | |||
| 525 | ||||
| 526 | switch_snprintf(z, sizeof(z), "%s@%s", (box ? box : user), domain_name); | |||
| 527 | r->requestInfo.user = strdup(z)(__extension__ (__builtin_constant_p (z) && ((size_t) (const void *)((z) + 1) - (size_t)(const void *)(z) == 1) ? ( ((const char *) (z))[0] == '\0' ? (char *) calloc ((size_t) 1 , (size_t) 1) : ({ size_t __len = strlen (z) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, z, __len); __retval; })) : __strdup (z))); | |||
| 528 | ||||
| 529 | ResponseAddField(r, "freeswitch-user", (box ? box : user)); | |||
| 530 | ResponseAddField(r, "freeswitch-domain", domain_name); | |||
| 531 | rval = TRUE(!0); | |||
| 532 | goto done; | |||
| 533 | } | |||
| 534 | } | |||
| 535 | } | |||
| 536 | ||||
| 537 | fail: | |||
| 538 | ||||
| 539 | switch_snprintf(z, sizeof(z), "Basic realm=\"%s\"", domain_name ? domain_name : globals.realm); | |||
| 540 | ResponseAddField(r, "WWW-Authenticate", z); | |||
| 541 | ResponseStatus(r, 401); | |||
| 542 | ||||
| 543 | done: | |||
| 544 | ||||
| 545 | switch_safe_free(mypass1)if (mypass1) {free(mypass1);mypass1=((void*)0);}; | |||
| 546 | switch_safe_free(mypass2)if (mypass2) {free(mypass2);mypass2=((void*)0);}; | |||
| 547 | switch_safe_free(box)if (box) {free(box);box=((void*)0);}; | |||
| 548 | switch_safe_free(dup_domain)if (dup_domain) {free(dup_domain);dup_domain=((void*)0);}; | |||
| 549 | ||||
| 550 | return rval; | |||
| 551 | } | |||
| 552 | ||||
| 553 | void stop_hook_event_handler(switch_event_t *event) { | |||
| 554 | wsh_t *wsh = (wsh_t *)event->bind_user_data; | |||
| 555 | ||||
| 556 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 556, ((void*)0), SWITCH_LOG_NOTICE, "got websocket::stophook, closing\n"); | |||
| 557 | wsh->down++; | |||
| 558 | } | |||
| 559 | ||||
| 560 | void event_handler(switch_event_t *event) { | |||
| 561 | char *json; | |||
| 562 | wsh_t *wsh = (wsh_t *)event->bind_user_data; | |||
| 563 | switch_event_serialize_json(event, &json); | |||
| 564 | ws_write_frame(wsh, WSOC_TEXT, json, strlen(json)); | |||
| 565 | free(json); | |||
| 566 | } | |||
| 567 | ||||
| 568 | #define MAX_EVENT_BIND_SLOTSSWITCH_EVENT_ALL SWITCH_EVENT_ALL | |||
| 569 | ||||
| 570 | abyss_bool websocket_hook(TSession *r) | |||
| 571 | { | |||
| 572 | wsh_t *wsh; | |||
| 573 | int ret; | |||
| 574 | int i; | |||
| 575 | ws_opcode_t opcode; | |||
| 576 | uint8_t *data; | |||
| 577 | switch_event_node_t *nodes[MAX_EVENT_BIND_SLOTSSWITCH_EVENT_ALL]; | |||
| 578 | int node_count = 0; | |||
| 579 | char *p; | |||
| 580 | char *key = NULL((void*)0); | |||
| 581 | char *version = NULL((void*)0); | |||
| 582 | char *proto = NULL((void*)0); | |||
| 583 | char *upgrade = NULL((void*)0); | |||
| 584 | ||||
| 585 | for (i = 0; i < r->requestHeaderFields.size; i++) { | |||
| ||||
| 586 | TTableItem * const item = &r->requestHeaderFields.item[i]; | |||
| 587 | ||||
| 588 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 588, ((void*)0), SWITCH_LOG_INFO, "headers %s: %s\n", item->name, item->value); | |||
| 589 | } | |||
| 590 | ||||
| 591 | key = RequestHeaderValue(r, "sec-websocket-key"); | |||
| 592 | version = RequestHeaderValue(r, "sec-websocket-version"); | |||
| 593 | proto = RequestHeaderValue(r, "sec-websocket-protocol"); | |||
| 594 | upgrade = RequestHeaderValue(r, "upgrade"); | |||
| 595 | ||||
| 596 | if (!key || !version || !proto || !upgrade) return FALSE0; | |||
| 597 | if (strncasecmp(upgrade, "websocket", 9) || strncasecmp(proto, "websocket", 9)) return FALSE0; | |||
| 598 | ||||
| 599 | wsh = ws_init(r); | |||
| 600 | if (!wsh) { | |||
| 601 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 601, ((void*)0), SWITCH_LOG_ERROR, "websocket memory error\n"); | |||
| 602 | return FALSE0; | |||
| 603 | } | |||
| 604 | ||||
| 605 | ret = ws_handshake_kvp(wsh, key, version, proto); | |||
| 606 | if (ret < 0) wsh->down = 1; | |||
| 607 | ||||
| 608 | if (ret != 0) { | |||
| 609 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 609, ((void*)0), SWITCH_LOG_ERROR, "handshake error %d\n", ret); | |||
| 610 | return FALSE0; | |||
| 611 | } | |||
| 612 | ||||
| 613 | if (switch_event_bind_removable("websocket", SWITCH_EVENT_CUSTOM, "websocket::stophook", stop_hook_event_handler, wsh, &nodes[node_count++]) != SWITCH_STATUS_SUCCESS) { | |||
| 614 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 614, ((void*)0), SWITCH_LOG_ERROR, "Can't bind!\n"); | |||
| 615 | node_count--; | |||
| 616 | } | |||
| 617 | ||||
| 618 | while (!wsh->down) { | |||
| 619 | int bytes = ws_read_frame(wsh, &opcode, &data); | |||
| 620 | ||||
| 621 | if (bytes < 0) { | |||
| 622 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 622, ((void*)0), SWITCH_LOG_INFO, "%d %s\n", opcode, (char *)data); | |||
| 623 | switch_yield(100000)switch_sleep(100000);; | |||
| 624 | continue; | |||
| 625 | } | |||
| 626 | ||||
| 627 | switch (opcode) { | |||
| 628 | case WSOC_CLOSE: | |||
| 629 | ws_close(wsh, 1000); | |||
| 630 | break; | |||
| 631 | case WSOC_CONTINUATION: | |||
| 632 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 632, ((void*)0), SWITCH_LOG_ERROR, "continue\n"); | |||
| 633 | continue; | |||
| 634 | case WSOC_TEXT: | |||
| 635 | p = data; | |||
| 636 | if (!p) continue; | |||
| 637 | if (!strncasecmp(data, "event ", 6)) { | |||
| 638 | switch_event_types_t type; | |||
| 639 | char *subclass; | |||
| 640 | ||||
| 641 | if (node_count == MAX_EVENT_BIND_SLOTSSWITCH_EVENT_ALL - 1) { | |||
| 642 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 642, ((void*)0), SWITCH_LOG_ERROR, "cannot subscribe more than %d events\n", node_count); | |||
| 643 | continue; | |||
| 644 | } | |||
| 645 | p += 6; | |||
| 646 | if (p = strchr(p, ' ')(__extension__ (__builtin_constant_p (' ') && !__builtin_constant_p (p) && (' ') == '\0' ? (char *) __rawmemchr (p, ' ') : __builtin_strchr (p, ' ')))) p++; | |||
| 647 | if (!strncasecmp(p, "json ", 5)) { | |||
| ||||
| 648 | p += 5; | |||
| 649 | } else if (!strncasecmp(p, "xml ", 4)) { | |||
| 650 | p += 4; | |||
| 651 | } else if (!strncasecmp(p, "plain ", 6)) { | |||
| 652 | p += 6; | |||
| 653 | } | |||
| 654 | if (!*p) { | |||
| 655 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 655, ((void*)0), SWITCH_LOG_WARNING, "missing event type in [%s]\n", data); | |||
| 656 | break; | |||
| 657 | } else { | |||
| 658 | } | |||
| 659 | if (subclass = strchr(p, ' ')(__extension__ (__builtin_constant_p (' ') && !__builtin_constant_p (p) && (' ') == '\0' ? (char *) __rawmemchr (p, ' ') : __builtin_strchr (p, ' ')))) { | |||
| 660 | *subclass++ = '\0'; | |||
| 661 | if (!*subclass) { | |||
| 662 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 662, ((void*)0), SWITCH_LOG_ERROR, "missing subclass\n"); | |||
| 663 | continue; | |||
| 664 | } | |||
| 665 | } else { | |||
| 666 | subclass = SWITCH_EVENT_SUBCLASS_ANY((void*)0); | |||
| 667 | } | |||
| 668 | ||||
| 669 | if (switch_name_event(p, &type) != SWITCH_STATUS_SUCCESS) { | |||
| 670 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 670, ((void*)0), SWITCH_LOG_ERROR, "Unknown event %s\n", p); | |||
| 671 | continue; | |||
| 672 | } | |||
| 673 | ||||
| 674 | if (switch_event_bind_removable("websocket", type, subclass, event_handler, wsh, &nodes[node_count++]) != SWITCH_STATUS_SUCCESS) { | |||
| 675 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 675, ((void*)0), SWITCH_LOG_ERROR, "Can't bind!\n"); | |||
| 676 | node_count--; | |||
| 677 | continue; | |||
| 678 | } else { | |||
| 679 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 679, ((void*)0), SWITCH_LOG_INFO, "Bind %s\n", data); | |||
| 680 | } | |||
| 681 | ||||
| 682 | } | |||
| 683 | break; | |||
| 684 | default: | |||
| 685 | break; | |||
| 686 | } | |||
| 687 | } | |||
| 688 | ||||
| 689 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 689, ((void*)0), SWITCH_LOG_ERROR, "wsh->down = %d, node_count = %d\n", wsh->down, node_count); | |||
| 690 | ||||
| 691 | switch_yield(2000)switch_sleep(2000);; | |||
| 692 | while (--node_count >= 0) switch_event_unbind(&nodes[node_count]); | |||
| 693 | ||||
| 694 | switch_safe_free(wsh)if (wsh) {free(wsh);wsh=((void*)0);}; | |||
| 695 | ||||
| 696 | return FALSE0; | |||
| 697 | } | |||
| 698 | ||||
| 699 | abyss_bool auth_hook(TSession * r) | |||
| 700 | { | |||
| 701 | char *domain_name, *e; | |||
| 702 | abyss_bool ret = FALSE0; | |||
| 703 | ||||
| 704 | if (globals.enable_websocket && !strncmp(r->requestInfo.uri, "/socket", 7)(__extension__ (__builtin_constant_p (7) && ((__builtin_constant_p (r->requestInfo.uri) && strlen (r->requestInfo .uri) < ((size_t) (7))) || (__builtin_constant_p ("/socket" ) && strlen ("/socket") < ((size_t) (7)))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (r->requestInfo .uri) && __builtin_constant_p ("/socket") && ( __s1_len = __builtin_strlen (r->requestInfo.uri), __s2_len = __builtin_strlen ("/socket"), (!((size_t)(const void *)((r ->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo .uri) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("/socket") + 1) - (size_t)(const void *)("/socket") == 1) || __s2_len >= 4)) ? __builtin_strcmp (r->requestInfo .uri, "/socket") : (__builtin_constant_p (r->requestInfo.uri ) && ((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo.uri) == 1) && (__s1_len = __builtin_strlen (r->requestInfo.uri), __s1_len < 4) ? (__builtin_constant_p ("/socket") && ((size_t )(const void *)(("/socket") + 1) - (size_t)(const void *)("/socket" ) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/socket") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("/socket"); int __result = (((const unsigned char *) (const char *) (r->requestInfo.uri))[0] - __s2[0] ); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (r->requestInfo. uri))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (r-> requestInfo.uri))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (r->requestInfo.uri))[3] - __s2[3]); } } __result; })) ) : (__builtin_constant_p ("/socket") && ((size_t)(const void *)(("/socket") + 1) - (size_t)(const void *)("/socket") == 1) && (__s2_len = __builtin_strlen ("/socket"), __s2_len < 4) ? (__builtin_constant_p (r->requestInfo.uri) && ((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t )(const void *)(r->requestInfo.uri) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/socket") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (r->requestInfo.uri); int __result = (((const unsigned char *) (const char *) ("/socket"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("/socket"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("/socket"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("/socket"))[3] - __s2[3]); } } __result; } )))) : __builtin_strcmp (r->requestInfo.uri, "/socket")))) ; }) : strncmp (r->requestInfo.uri, "/socket", 7)))) { | |||
| 705 | // Chrome has no Authorization support yet | |||
| 706 | // https://code.google.com/p/chromium/issues/detail?id=123862 | |||
| 707 | return websocket_hook(r); | |||
| 708 | } | |||
| 709 | ||||
| 710 | if (!strncmp(r->requestInfo.uri, "/portal", 7)(__extension__ (__builtin_constant_p (7) && ((__builtin_constant_p (r->requestInfo.uri) && strlen (r->requestInfo .uri) < ((size_t) (7))) || (__builtin_constant_p ("/portal" ) && strlen ("/portal") < ((size_t) (7)))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (r->requestInfo .uri) && __builtin_constant_p ("/portal") && ( __s1_len = __builtin_strlen (r->requestInfo.uri), __s2_len = __builtin_strlen ("/portal"), (!((size_t)(const void *)((r ->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo .uri) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("/portal") + 1) - (size_t)(const void *)("/portal") == 1) || __s2_len >= 4)) ? __builtin_strcmp (r->requestInfo .uri, "/portal") : (__builtin_constant_p (r->requestInfo.uri ) && ((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo.uri) == 1) && (__s1_len = __builtin_strlen (r->requestInfo.uri), __s1_len < 4) ? (__builtin_constant_p ("/portal") && ((size_t )(const void *)(("/portal") + 1) - (size_t)(const void *)("/portal" ) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/portal") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("/portal"); int __result = (((const unsigned char *) (const char *) (r->requestInfo.uri))[0] - __s2[0] ); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (r->requestInfo. uri))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (r-> requestInfo.uri))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (r->requestInfo.uri))[3] - __s2[3]); } } __result; })) ) : (__builtin_constant_p ("/portal") && ((size_t)(const void *)(("/portal") + 1) - (size_t)(const void *)("/portal") == 1) && (__s2_len = __builtin_strlen ("/portal"), __s2_len < 4) ? (__builtin_constant_p (r->requestInfo.uri) && ((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t )(const void *)(r->requestInfo.uri) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/portal") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (r->requestInfo.uri); int __result = (((const unsigned char *) (const char *) ("/portal"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("/portal"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("/portal"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("/portal"))[3] - __s2[3]); } } __result; } )))) : __builtin_strcmp (r->requestInfo.uri, "/portal")))) ; }) : strncmp (r->requestInfo.uri, "/portal", 7))) && strlen(r->requestInfo.uri) <= 8) { | |||
| 711 | ResponseAddField(r, "Location", "/portal/index.html"); | |||
| 712 | ResponseStatus(r, 302); | |||
| 713 | return TRUE(!0); | |||
| 714 | } | |||
| 715 | ||||
| 716 | if (!strncmp(r->requestInfo.uri, "/domains/", 9)(__extension__ (__builtin_constant_p (9) && ((__builtin_constant_p (r->requestInfo.uri) && strlen (r->requestInfo .uri) < ((size_t) (9))) || (__builtin_constant_p ("/domains/" ) && strlen ("/domains/") < ((size_t) (9)))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (r->requestInfo .uri) && __builtin_constant_p ("/domains/") && (__s1_len = __builtin_strlen (r->requestInfo.uri), __s2_len = __builtin_strlen ("/domains/"), (!((size_t)(const void *)( (r->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo .uri) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("/domains/") + 1) - (size_t)(const void *)("/domains/" ) == 1) || __s2_len >= 4)) ? __builtin_strcmp (r->requestInfo .uri, "/domains/") : (__builtin_constant_p (r->requestInfo .uri) && ((size_t)(const void *)((r->requestInfo.uri ) + 1) - (size_t)(const void *)(r->requestInfo.uri) == 1) && (__s1_len = __builtin_strlen (r->requestInfo.uri), __s1_len < 4) ? (__builtin_constant_p ("/domains/") && ((size_t )(const void *)(("/domains/") + 1) - (size_t)(const void *)("/domains/" ) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/domains/" ) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("/domains/"); int __result = (((const unsigned char *) (const char *) (r->requestInfo.uri))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (r->requestInfo .uri))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ( r->requestInfo.uri))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (r->requestInfo.uri))[3] - __s2[3]); } } __result; })) ) : (__builtin_constant_p ("/domains/") && ((size_t)( const void *)(("/domains/") + 1) - (size_t)(const void *)("/domains/" ) == 1) && (__s2_len = __builtin_strlen ("/domains/") , __s2_len < 4) ? (__builtin_constant_p (r->requestInfo .uri) && ((size_t)(const void *)((r->requestInfo.uri ) + 1) - (size_t)(const void *)(r->requestInfo.uri) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/domains/") : (- ( __extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (r->requestInfo.uri); int __result = (( (const unsigned char *) (const char *) ("/domains/"))[0] - __s2 [0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("/domains/"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("/domains/"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("/domains/"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (r->requestInfo .uri, "/domains/")))); }) : strncmp (r->requestInfo.uri, "/domains/" , 9)))) { | |||
| 717 | domain_name = strdup(r->requestInfo.uri + 9)(__extension__ (__builtin_constant_p (r->requestInfo.uri + 9) && ((size_t)(const void *)((r->requestInfo.uri + 9) + 1) - (size_t)(const void *)(r->requestInfo.uri + 9 ) == 1) ? (((const char *) (r->requestInfo.uri + 9))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (r->requestInfo.uri + 9) + 1; char *__retval = ( char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, r->requestInfo.uri + 9, __len) ; __retval; })) : __strdup (r->requestInfo.uri + 9))); | |||
| 718 | switch_assert(domain_name)((domain_name) ? (void) (0) : __assert_fail ("domain_name", "mod_xml_rpc.c" , 718, __PRETTY_FUNCTION__)); | |||
| 719 | ||||
| 720 | if ((e = strchr(domain_name, '/')(__extension__ (__builtin_constant_p ('/') && !__builtin_constant_p (domain_name) && ('/') == '\0' ? (char *) __rawmemchr (domain_name, '/') : __builtin_strchr (domain_name, '/'))))) { | |||
| 721 | *e++ = '\0'; | |||
| 722 | } | |||
| 723 | ||||
| 724 | if (!strcmp(domain_name, "this")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (domain_name) && __builtin_constant_p ("this") && (__s1_len = __builtin_strlen (domain_name), __s2_len = __builtin_strlen ("this"), (!((size_t)(const void *)((domain_name) + 1) - (size_t )(const void *)(domain_name) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("this") + 1) - (size_t)(const void *)("this") == 1) || __s2_len >= 4)) ? __builtin_strcmp (domain_name , "this") : (__builtin_constant_p (domain_name) && (( size_t)(const void *)((domain_name) + 1) - (size_t)(const void *)(domain_name) == 1) && (__s1_len = __builtin_strlen (domain_name), __s1_len < 4) ? (__builtin_constant_p ("this" ) && ((size_t)(const void *)(("this") + 1) - (size_t) (const void *)("this") == 1) ? __builtin_strcmp (domain_name, "this") : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("this"); int __result = ((( const unsigned char *) (const char *) (domain_name))[0] - __s2 [0]); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (domain_name))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (domain_name))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (domain_name))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("this" ) && ((size_t)(const void *)(("this") + 1) - (size_t) (const void *)("this") == 1) && (__s2_len = __builtin_strlen ("this"), __s2_len < 4) ? (__builtin_constant_p (domain_name ) && ((size_t)(const void *)((domain_name) + 1) - (size_t )(const void *)(domain_name) == 1) ? __builtin_strcmp (domain_name , "this") : (- (__extension__ ({ const unsigned char *__s2 = ( const unsigned char *) (const char *) (domain_name); int __result = (((const unsigned char *) (const char *) ("this"))[0] - __s2 [0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("this"))[1] - __s2 [1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("this"))[2] - __s2 [2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("this"))[3] - __s2 [3]); } } __result; })))) : __builtin_strcmp (domain_name, "this" )))); })) { | |||
| 725 | free(domain_name); | |||
| 726 | domain_name = strdup(r->requestInfo.host)(__extension__ (__builtin_constant_p (r->requestInfo.host) && ((size_t)(const void *)((r->requestInfo.host) + 1) - (size_t)(const void *)(r->requestInfo.host) == 1) ? ( ((const char *) (r->requestInfo.host))[0] == '\0' ? (char * ) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen ( r->requestInfo.host) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, r->requestInfo.host, __len); __retval; })) : __strdup (r->requestInfo.host))); | |||
| 727 | } | |||
| 728 | ||||
| 729 | ret = !http_directory_auth(r, domain_name); | |||
| 730 | ||||
| 731 | free(domain_name); | |||
| 732 | } else { | |||
| 733 | char tmp[512]; | |||
| 734 | const char *list[2] = { "index.html", "index.txt" }; | |||
| 735 | int x; | |||
| 736 | ||||
| 737 | if (!strncmp(r->requestInfo.uri, "/pub", 4)(__extension__ (__builtin_constant_p (4) && ((__builtin_constant_p (r->requestInfo.uri) && strlen (r->requestInfo .uri) < ((size_t) (4))) || (__builtin_constant_p ("/pub") && strlen ("/pub") < ((size_t) (4)))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (r->requestInfo .uri) && __builtin_constant_p ("/pub") && (__s1_len = __builtin_strlen (r->requestInfo.uri), __s2_len = __builtin_strlen ("/pub"), (!((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo.uri) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("/pub") + 1) - (size_t)(const void *)("/pub") == 1) || __s2_len >= 4)) ? __builtin_strcmp (r->requestInfo.uri, "/pub") : (__builtin_constant_p (r->requestInfo.uri) && ((size_t)(const void *)(( r->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo .uri) == 1) && (__s1_len = __builtin_strlen (r->requestInfo .uri), __s1_len < 4) ? (__builtin_constant_p ("/pub") && ((size_t)(const void *)(("/pub") + 1) - (size_t)(const void * )("/pub") == 1) ? __builtin_strcmp (r->requestInfo.uri, "/pub" ) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("/pub"); int __result = (((const unsigned char *) (const char *) (r->requestInfo.uri))[0] - __s2[0] ); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (r->requestInfo. uri))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (r-> requestInfo.uri))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (r->requestInfo.uri))[3] - __s2[3]); } } __result; })) ) : (__builtin_constant_p ("/pub") && ((size_t)(const void *)(("/pub") + 1) - (size_t)(const void *)("/pub") == 1) && (__s2_len = __builtin_strlen ("/pub"), __s2_len < 4) ? (__builtin_constant_p (r->requestInfo.uri) && ((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t )(const void *)(r->requestInfo.uri) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/pub") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (r->requestInfo.uri); int __result = (((const unsigned char *) (const char *) ("/pub"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("/pub"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("/pub"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("/pub"))[3] - __s2[3]); } } __result; })) )) : __builtin_strcmp (r->requestInfo.uri, "/pub")))); }) : strncmp (r->requestInfo.uri, "/pub", 4)))) { | |||
| 738 | char *p = (char *) r->requestInfo.uri; | |||
| 739 | char *new_uri = p + 4; | |||
| 740 | if (!new_uri) { | |||
| 741 | new_uri = "/"; | |||
| 742 | } | |||
| 743 | ||||
| 744 | switch_snprintf(tmp, sizeof(tmp), "%s%s", SWITCH_GLOBAL_dirs.htdocs_dir, new_uri); | |||
| 745 | ||||
| 746 | if (switch_directory_exists(tmp, NULL((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
| 747 | for (x = 0; x < 2; x++) { | |||
| 748 | switch_snprintf(tmp, sizeof(tmp), "%s%s%s%s", | |||
| 749 | SWITCH_GLOBAL_dirs.htdocs_dir, new_uri, end_of(new_uri)*(*new_uri == '\0' ? new_uri : new_uri + strlen(new_uri) - 1) == *SWITCH_PATH_SEPARATOR"/" ? "" : SWITCH_PATH_SEPARATOR"/", list[x] | |||
| 750 | ); | |||
| 751 | ||||
| 752 | if (switch_file_exists(tmp, NULL((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
| 753 | switch_snprintf(tmp, sizeof(tmp), "%s%s%s", new_uri, end_of(new_uri)*(*new_uri == '\0' ? new_uri : new_uri + strlen(new_uri) - 1) == '/' ? "" : "/", list[x] | |||
| 754 | ); | |||
| 755 | new_uri = tmp; | |||
| 756 | break; | |||
| 757 | } | |||
| 758 | } | |||
| 759 | } | |||
| 760 | ||||
| 761 | r->requestInfo.uri = strdup(new_uri)(__extension__ (__builtin_constant_p (new_uri) && ((size_t )(const void *)((new_uri) + 1) - (size_t)(const void *)(new_uri ) == 1) ? (((const char *) (new_uri))[0] == '\0' ? (char *) calloc ((size_t) 1, (size_t) 1) : ({ size_t __len = strlen (new_uri ) + 1; char *__retval = (char *) malloc (__len); if (__retval != ((void*)0)) __retval = (char *) memcpy (__retval, new_uri , __len); __retval; })) : __strdup (new_uri))); | |||
| 762 | free(p); | |||
| 763 | ||||
| 764 | } else { | |||
| 765 | if (globals.realm && strncmp(r->requestInfo.uri, "/pub", 4)(__extension__ (__builtin_constant_p (4) && ((__builtin_constant_p (r->requestInfo.uri) && strlen (r->requestInfo .uri) < ((size_t) (4))) || (__builtin_constant_p ("/pub") && strlen ("/pub") < ((size_t) (4)))) ? __extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (r->requestInfo .uri) && __builtin_constant_p ("/pub") && (__s1_len = __builtin_strlen (r->requestInfo.uri), __s2_len = __builtin_strlen ("/pub"), (!((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo.uri) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("/pub") + 1) - (size_t)(const void *)("/pub") == 1) || __s2_len >= 4)) ? __builtin_strcmp (r->requestInfo.uri, "/pub") : (__builtin_constant_p (r->requestInfo.uri) && ((size_t)(const void *)(( r->requestInfo.uri) + 1) - (size_t)(const void *)(r->requestInfo .uri) == 1) && (__s1_len = __builtin_strlen (r->requestInfo .uri), __s1_len < 4) ? (__builtin_constant_p ("/pub") && ((size_t)(const void *)(("/pub") + 1) - (size_t)(const void * )("/pub") == 1) ? __builtin_strcmp (r->requestInfo.uri, "/pub" ) : (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) ("/pub"); int __result = (((const unsigned char *) (const char *) (r->requestInfo.uri))[0] - __s2[0] ); if (__s1_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) (r->requestInfo. uri))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) (r-> requestInfo.uri))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) (r->requestInfo.uri))[3] - __s2[3]); } } __result; })) ) : (__builtin_constant_p ("/pub") && ((size_t)(const void *)(("/pub") + 1) - (size_t)(const void *)("/pub") == 1) && (__s2_len = __builtin_strlen ("/pub"), __s2_len < 4) ? (__builtin_constant_p (r->requestInfo.uri) && ((size_t)(const void *)((r->requestInfo.uri) + 1) - (size_t )(const void *)(r->requestInfo.uri) == 1) ? __builtin_strcmp (r->requestInfo.uri, "/pub") : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned char *) (const char *) (r->requestInfo.uri); int __result = (((const unsigned char *) (const char *) ("/pub"))[0] - __s2[0]); if (__s2_len > 0 && __result == 0) { __result = (((const unsigned char *) (const char *) ("/pub"))[1] - __s2[1]); if (__s2_len > 1 && __result == 0) { __result = (((const unsigned char *) (const char *) ("/pub"))[2] - __s2[2]); if (__s2_len > 2 && __result == 0) __result = (((const unsigned char *) (const char *) ("/pub"))[3] - __s2[3]); } } __result; })) )) : __builtin_strcmp (r->requestInfo.uri, "/pub")))); }) : strncmp (r->requestInfo.uri, "/pub", 4)))) { | |||
| 766 | ret = !http_directory_auth(r, NULL((void*)0)); | |||
| 767 | } | |||
| 768 | } | |||
| 769 | } | |||
| 770 | return ret; | |||
| 771 | } | |||
| 772 | ||||
| 773 | ||||
| 774 | static abyss_bool HTTPWrite(TSession * s, const char *buffer, const uint32_t len) | |||
| 775 | { | |||
| 776 | if (s->chunkedwrite && s->chunkedwritemode) { | |||
| 777 | char t[16]; | |||
| 778 | ||||
| 779 | if (ConnWrite(s->connP, t, sprintf(t, "%x" CRLF"\r\n", len))) | |||
| 780 | if (ConnWrite(s->connP, buffer, len)) | |||
| 781 | return ConnWrite(s->connP, CRLF"\r\n", 2); | |||
| 782 | ||||
| 783 | return FALSE0; | |||
| 784 | } | |||
| 785 | ||||
| 786 | return ConnWrite(s->connP, buffer, len); | |||
| 787 | } | |||
| 788 | ||||
| 789 | static abyss_bool HTTPWriteEnd(TSession * s) | |||
| 790 | { | |||
| 791 | if (!s->chunkedwritemode) | |||
| 792 | return TRUE(!0); | |||
| 793 | ||||
| 794 | if (s->chunkedwrite) { | |||
| 795 | /* May be one day trailer dumping will be added */ | |||
| 796 | s->chunkedwritemode = FALSE0; | |||
| 797 | return ConnWrite(s->connP, "0" CRLF"\r\n" CRLF"\r\n", 5); | |||
| 798 | } | |||
| 799 | ||||
| 800 | s->requestInfo.keepalive = FALSE0; | |||
| 801 | return TRUE(!0); | |||
| 802 | } | |||
| 803 | ||||
| 804 | abyss_bool handler_hook(TSession * r) | |||
| 805 | { | |||
| 806 | switch_stream_handle_t stream = { 0 }; | |||
| 807 | char *command; | |||
| 808 | char *full_command; | |||
| 809 | int i; | |||
| 810 | char *fs_user = NULL((void*)0), *fs_domain = NULL((void*)0); | |||
| 811 | char *path_info = NULL((void*)0); | |||
| 812 | abyss_bool ret = TRUE(!0); | |||
| 813 | int html = 0, text = 0, xml = 0, api = 0; | |||
| 814 | const char *api_str; | |||
| 815 | const char *uri = 0; | |||
| 816 | TRequestInfo *info = 0; | |||
| 817 | switch_event_t *evnt = 0; /* shortcut to stream.param_event */ | |||
| 818 | char v[256] = ""; | |||
| 819 | ||||
| 820 | if (!r || !(info = &r->requestInfo) || !(uri = info->uri)) { | |||
| 821 | return FALSE0; | |||
| 822 | } | |||
| 823 | ||||
| 824 | stream.data = r; | |||
| 825 | stream.write_function = http_stream_write; | |||
| 826 | stream.raw_write_function = http_stream_raw_write; | |||
| 827 | ||||
| 828 | if ((command = strstr(uri, "/api/"))) { | |||
| 829 | command += 5; | |||
| 830 | api++; | |||
| 831 | } else if ((command = strstr(uri, "/webapi/"))) { | |||
| 832 | command += 8; | |||
| 833 | html++; | |||
| 834 | } else if ((command = strstr(uri, "/txtapi/"))) { | |||
| 835 | command += 8; | |||
| 836 | text++; | |||
| 837 | } else if ((command = strstr(uri, "/xmlapi/"))) { | |||
| 838 | command += 8; | |||
| 839 | xml++; | |||
| 840 | } else { | |||
| 841 | return FALSE0; /* 404 */ | |||
| 842 | } | |||
| 843 | ||||
| 844 | if ((path_info = strchr(command, '/')(__extension__ (__builtin_constant_p ('/') && !__builtin_constant_p (command) && ('/') == '\0' ? (char *) __rawmemchr (command , '/') : __builtin_strchr (command, '/'))))) { | |||
| 845 | *path_info++ = '\0'; | |||
| 846 | } | |||
| 847 | ||||
| 848 | for (i = 0; i < r->responseHeaderFields.size; i++) { | |||
| 849 | TTableItem *ti = &r->responseHeaderFields.item[i]; | |||
| 850 | if (!strcasecmp(ti->name, "freeswitch-user")) { | |||
| 851 | fs_user = ti->value; | |||
| 852 | } else if (!strcasecmp(ti->name, "freeswitch-domain")) { | |||
| 853 | fs_domain = ti->value; | |||
| 854 | } | |||
| 855 | } | |||
| 856 | ||||
| 857 | if (!is_authorized(r, command)) { | |||
| 858 | ret = TRUE(!0); | |||
| 859 | goto end; | |||
| 860 | } | |||
| 861 | ||||
| 862 | /* auth: */ | |||
| 863 | ||||
| 864 | if (switch_event_create(&stream.param_event, SWITCH_EVENT_API)switch_event_create_subclass_detailed("mod_xml_rpc.c", (const char * )(const char *)__func__, 864, &stream.param_event , SWITCH_EVENT_API, ((void*)0)) == SWITCH_STATUS_SUCCESS) { | |||
| 865 | const char *const content_length = RequestHeaderValue(r, "content-length"); | |||
| 866 | evnt = stream.param_event; | |||
| 867 | ||||
| 868 | if (html) { | |||
| 869 | switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/html"); | |||
| 870 | } else if (text) { | |||
| 871 | switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/plain"); | |||
| 872 | } else if (xml) { | |||
| 873 | switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "Content-Type", "text/xml"); | |||
| 874 | } | |||
| 875 | if (api) { | |||
| 876 | switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-API", "api"); | |||
| 877 | } | |||
| 878 | if (fs_user) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-User", fs_user); | |||
| 879 | if (fs_domain) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "FreeSWITCH-Domain", fs_domain); | |||
| 880 | if (path_info) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-Path-Info", path_info); | |||
| 881 | ||||
| 882 | if (info->host) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-HOST", info->host); | |||
| 883 | if (info->from) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-FROM", info->from); | |||
| 884 | if (info->useragent) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER-AGENT", info->useragent); | |||
| 885 | if (info->referer) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REFERER", info->referer); | |||
| 886 | if (info->requestline) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-REQUESTLINE", info->requestline); | |||
| 887 | if (info->user) switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-USER", info->user); | |||
| 888 | if (info->port) switch_event_add_header(evnt, SWITCH_STACK_BOTTOM, "HTTP-PORT", "%u", info->port); | |||
| 889 | ||||
| 890 | { | |||
| 891 | char *q, *qd; | |||
| 892 | char *next; | |||
| 893 | char *query = (char *) info->query; | |||
| 894 | char *name, *val; | |||
| 895 | char qbuf[8192] = ""; | |||
| 896 | ||||
| 897 | /* first finish reading from the socket if post method was used*/ | |||
| 898 | if (info->method == m_post && content_length) { | |||
| 899 | int len = atoi(content_length); | |||
| 900 | int qlen = 0; | |||
| 901 | ||||
| 902 | if (len > 0) { | |||
| 903 | int succeeded = TRUE(!0); | |||
| 904 | char *qp = qbuf; | |||
| 905 | char *readError; | |||
| 906 | ||||
| 907 | do { | |||
| 908 | int blen = r->connP->buffersize - r->connP->bufferpos; | |||
| 909 | ||||
| 910 | if ((qlen + blen) > len) { | |||
| 911 | blen = len - qlen; | |||
| 912 | } | |||
| 913 | ||||
| 914 | qlen += blen; | |||
| 915 | ||||
| 916 | if (qlen > sizeof(qbuf)) { | |||
| 917 | break; | |||
| 918 | } | |||
| 919 | ||||
| 920 | memcpy(qp, r->connP->buffer.b + r->connP->bufferpos, blen); | |||
| 921 | qp += blen; | |||
| 922 | ||||
| 923 | if (qlen >= len) { | |||
| 924 | break; | |||
| 925 | } | |||
| 926 | ||||
| 927 | ConnRead(r->connP, 2000, NULL((void*)0), NULL((void*)0), &readError); | |||
| 928 | if (readError) { | |||
| 929 | succeeded = FALSE0; | |||
| 930 | free(readError); | |||
| 931 | } | |||
| 932 | ||||
| 933 | } while (succeeded); | |||
| 934 | ||||
| 935 | query = qbuf; | |||
| 936 | } | |||
| 937 | } | |||
| 938 | ||||
| 939 | /* parse query and add kv-pairs as event headers */ | |||
| 940 | /* a kv pair starts with '&', '+' or \0 mark the end */ | |||
| 941 | if (query) { | |||
| 942 | switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", query); | |||
| 943 | qd = strdup(query)(__extension__ (__builtin_constant_p (query) && ((size_t )(const void *)((query) + 1) - (size_t)(const void *)(query) == 1) ? (((const char *) (query))[0] == '\0' ? (char *) calloc ( (size_t) 1, (size_t) 1) : ({ size_t __len = strlen (query) + 1 ; char *__retval = (char *) malloc (__len); if (__retval != ( (void*)0)) __retval = (char *) memcpy (__retval, query, __len ); __retval; })) : __strdup (query))); | |||
| 944 | } else { | |||
| 945 | qd = strdup(uri)(__extension__ (__builtin_constant_p (uri) && ((size_t )(const void *)((uri) + 1) - (size_t)(const void *)(uri) == 1 ) ? (((const char *) (uri))[0] == '\0' ? (char *) calloc ((size_t ) 1, (size_t) 1) : ({ size_t __len = strlen (uri) + 1; char * __retval = (char *) malloc (__len); if (__retval != ((void*)0 )) __retval = (char *) memcpy (__retval, uri, __len); __retval ; })) : __strdup (uri))); | |||
| 946 | } | |||
| 947 | ||||
| 948 | switch_assert(qd != NULL)((qd != ((void*)0)) ? (void) (0) : __assert_fail ("qd != ((void*)0)" , "mod_xml_rpc.c", 948, __PRETTY_FUNCTION__)); | |||
| 949 | ||||
| 950 | q = qd; | |||
| 951 | next = q; | |||
| 952 | ||||
| 953 | do { | |||
| 954 | char *p; | |||
| 955 | ||||
| 956 | if (next = strchr(next, '&')(__extension__ (__builtin_constant_p ('&') && !__builtin_constant_p (next) && ('&') == '\0' ? (char *) __rawmemchr ( next, '&') : __builtin_strchr (next, '&')))) { | |||
| 957 | if (!query) { | |||
| 958 | /* pass kv pairs from uri to query */ | |||
| 959 | /* "?" is absent in url so parse uri */ | |||
| 960 | *((char *)uri + (next - q - 1)) = '\0'; | |||
| 961 | query = next; | |||
| 962 | switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-QUERY", next); | |||
| 963 | /* and strip uri */ | |||
| 964 | /* the start of first kv pair marks the end of uri */ | |||
| 965 | /* to prevent kv-pairs confusing fs api commands */ | |||
| 966 | /* that have arguments separated by space */ | |||
| 967 | } | |||
| 968 | *next++ = '\0'; | |||
| 969 | } | |||
| 970 | ||||
| 971 | for (p = q; p && *p; p++) { | |||
| 972 | if (*p == '+') { | |||
| 973 | *p = ' '; | |||
| 974 | } | |||
| 975 | } | |||
| 976 | /* hmmm, get method requests are already decoded ... */ | |||
| 977 | switch_url_decode(q); | |||
| 978 | ||||
| 979 | name = q; | |||
| 980 | if ((val = strchr(name, '=')(__extension__ (__builtin_constant_p ('=') && !__builtin_constant_p (name) && ('=') == '\0' ? (char *) __rawmemchr (name , '=') : __builtin_strchr (name, '='))))) { | |||
| 981 | *val++ = '\0'; | |||
| 982 | switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, name, val); | |||
| 983 | } | |||
| 984 | q = next; | |||
| 985 | } while (q != NULL((void*)0)); | |||
| 986 | ||||
| 987 | free(qd); | |||
| 988 | } | |||
| 989 | } | |||
| 990 | ||||
| 991 | switch_event_add_header_string(evnt, SWITCH_STACK_BOTTOM, "HTTP-URI", uri); | |||
| 992 | ||||
| 993 | /* We made it this far, always OK */ | |||
| 994 | if (!HTTPWrite(r, "HTTP/1.1 200 OK\r\n", (uint32_t) strlen("HTTP/1.1 200 OK\r\n"))) { | |||
| 995 | return TRUE(!0); | |||
| 996 | } | |||
| 997 | ||||
| 998 | ResponseAddField(r, "Connection", "close"); | |||
| 999 | ||||
| 1000 | /* generation of the date field */ | |||
| 1001 | if (evnt) | |||
| 1002 | { | |||
| 1003 | ResponseAddField(r, "Date", switch_event_get_header(evnt, "Event-Date-GMT")switch_event_get_header_idx(evnt, "Event-Date-GMT", -1)); | |||
| 1004 | } | |||
| 1005 | else { | |||
| 1006 | const char *dateValue; | |||
| 1007 | ||||
| 1008 | DateToString(r->date, &dateValue); | |||
| 1009 | if (dateValue) { | |||
| 1010 | ResponseAddField(r, "Date", dateValue); | |||
| 1011 | free((void *)dateValue); | |||
| 1012 | } | |||
| 1013 | } | |||
| 1014 | ||||
| 1015 | /* Generation of the server field */ | |||
| 1016 | switch_snprintf(v, sizeof(v), "FreeSWITCH-%s-mod_xml_rpc", switch_version_full()); | |||
| 1017 | ResponseAddField(r, "Server", v); | |||
| 1018 | ||||
| 1019 | if (html) { | |||
| 1020 | ResponseAddField(r, "Content-Type", "text/html"); | |||
| 1021 | } else if (text) { | |||
| 1022 | ResponseAddField(r, "Content-Type", "text/plain"); | |||
| 1023 | } else if (xml) { | |||
| 1024 | ResponseAddField(r, "Content-Type", "text/xml"); | |||
| 1025 | } | |||
| 1026 | ||||
| 1027 | for (i = 0; i < r->responseHeaderFields.size; i++) { | |||
| 1028 | TTableItem *ti = &r->responseHeaderFields.item[i]; | |||
| 1029 | char *header = switch_mprintf("%s: %s\r\n", ti->name, ti->value); | |||
| 1030 | if (!ConnWrite(r->connP, header, (uint32_t) strlen(header))) { | |||
| 1031 | switch_safe_free(header)if (header) {free(header);header=((void*)0);}; | |||
| 1032 | return TRUE(!0); | |||
| 1033 | } | |||
| 1034 | switch_safe_free(header)if (header) {free(header);header=((void*)0);}; | |||
| 1035 | } | |||
| 1036 | ||||
| 1037 | /* send end http header */ | |||
| 1038 | if (html||text||xml) { | |||
| 1039 | if (!ConnWrite(r->connP, CRLF"\r\n", 2)) { | |||
| 1040 | return TRUE(!0); | |||
| 1041 | } | |||
| 1042 | } | |||
| 1043 | else { | |||
| 1044 | /* content-type and end of http header will be streamed by fs api or http_stream_write */ | |||
| 1045 | } | |||
| 1046 | ||||
| 1047 | if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", info->query)) { | |||
| 1048 | command = "bgapi"; | |||
| 1049 | api_str = "unload mod_xml_rpc"; | |||
| 1050 | } else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", info->query)) { | |||
| 1051 | command = "bgapi"; | |||
| 1052 | api_str = "reload mod_xml_rpc"; | |||
| 1053 | } else { | |||
| 1054 | api_str = info->query; | |||
| 1055 | } | |||
| 1056 | ||||
| 1057 | /* TODO (maybe): take "refresh=xxx" out of query as to not confuse fs api commands */ | |||
| 1058 | ||||
| 1059 | /* execute actual fs api command */ | |||
| 1060 | /* fs api command will write to stream, calling http_stream_write / http_stream_raw_write */ | |||
| 1061 | /* switch_api_execute will stream INVALID COMMAND before it fails */ | |||
| 1062 | switch_api_execute(command, api_str, NULL((void*)0), &stream); | |||
| 1063 | ||||
| 1064 | if (globals.commands_to_log != NULL((void*)0)) { | |||
| 1065 | full_command = switch_mprintf("%s%s%s", command, (api_str==NULL((void*)0) ? "" : " "), api_str); | |||
| 1066 | ||||
| 1067 | if (switch_regex_match(full_command, globals.commands_to_log) == SWITCH_STATUS_SUCCESS) { | |||
| 1068 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 1068, ((void*)0), SWITCH_LOG_INFO, "Executed HTTP request command: [%s].\n", full_command); | |||
| 1069 | } | |||
| 1070 | ||||
| 1071 | switch_safe_free(full_command)if (full_command) {free(full_command);full_command=((void*)0) ;}; | |||
| 1072 | } | |||
| 1073 | ||||
| 1074 | r->responseStarted = TRUE(!0); | |||
| 1075 | ResponseStatus(r, 200); /* we don't want an assertion failure */ | |||
| 1076 | r->requestInfo.keepalive = 0; | |||
| 1077 | ||||
| 1078 | end: | |||
| 1079 | ||||
| 1080 | return ret; | |||
| 1081 | } | |||
| 1082 | ||||
| 1083 | static xmlrpc_value *freeswitch_api(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, void *const userData, void *const callInfo) | |||
| 1084 | { | |||
| 1085 | char *command = NULL((void*)0), *arg = NULL((void*)0); | |||
| 1086 | switch_stream_handle_t stream = { 0 }; | |||
| 1087 | xmlrpc_value *val = NULL((void*)0); | |||
| 1088 | switch_bool_t freed = 0; | |||
| 1089 | ||||
| 1090 | ||||
| 1091 | /* Parse our argument array. */ | |||
| 1092 | xmlrpc_decompose_value(envP, paramArrayP, "(ss)", &command, &arg); | |||
| 1093 | ||||
| 1094 | if (envP->fault_occurred) { | |||
| 1095 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 1095, ((void*)0), SWITCH_LOG_ERROR, "Invalid Request!\n"); | |||
| 1096 | return NULL((void*)0); | |||
| 1097 | } | |||
| 1098 | ||||
| 1099 | if (!is_authorized((const TSession *) callInfo, command)) { | |||
| 1100 | val = xmlrpc_build_value(envP, "s", "UNAUTHORIZED!"); | |||
| 1101 | goto end; | |||
| 1102 | } | |||
| 1103 | ||||
| 1104 | if (switch_stristr("unload", command) && switch_stristr("mod_xml_rpc", arg)) { | |||
| 1105 | switch_safe_free(command)if (command) {free(command);command=((void*)0);}; | |||
| 1106 | switch_safe_free(arg)if (arg) {free(arg);arg=((void*)0);}; | |||
| 1107 | freed = 1; | |||
| 1108 | command = "bgapi"; | |||
| 1109 | arg = "unload mod_xml_rpc"; | |||
| 1110 | } else if (switch_stristr("reload", command) && switch_stristr("mod_xml_rpc", arg)) { | |||
| 1111 | switch_safe_free(command)if (command) {free(command);command=((void*)0);}; | |||
| 1112 | switch_safe_free(arg)if (arg) {free(arg);arg=((void*)0);}; | |||
| 1113 | freed = 1; | |||
| 1114 | command = "bgapi"; | |||
| 1115 | arg = "reload mod_xml_rpc"; | |||
| 1116 | } | |||
| 1117 | ||||
| 1118 | SWITCH_STANDARD_STREAM(stream)memset(&stream, 0, sizeof(stream)); stream.data = malloc( 1024); ((stream.data) ? (void) (0) : __assert_fail ("stream.data" , "mod_xml_rpc.c", 1118, __PRETTY_FUNCTION__)); memset(stream .data, 0, 1024); stream.end = stream.data; stream.data_size = 1024; stream.write_function = switch_console_stream_write; stream .raw_write_function = switch_console_stream_raw_write; stream .alloc_len = 1024; stream.alloc_chunk = 1024; | |||
| 1119 | if (switch_api_execute(command, arg, NULL((void*)0), &stream) == SWITCH_STATUS_SUCCESS) { | |||
| 1120 | /* Return our result. */ | |||
| 1121 | val = xmlrpc_build_value(envP, "s", stream.data); | |||
| 1122 | free(stream.data); | |||
| 1123 | } else { | |||
| 1124 | val = xmlrpc_build_value(envP, "s", "ERROR!"); | |||
| 1125 | } | |||
| 1126 | ||||
| 1127 | end: | |||
| 1128 | ||||
| 1129 | /* xmlrpc-c requires us to free memory it malloced from xmlrpc_decompose_value */ | |||
| 1130 | if (!freed) { | |||
| 1131 | switch_safe_free(command)if (command) {free(command);command=((void*)0);}; | |||
| 1132 | switch_safe_free(arg)if (arg) {free(arg);arg=((void*)0);}; | |||
| 1133 | } | |||
| 1134 | ||||
| 1135 | return val; | |||
| 1136 | } | |||
| 1137 | ||||
| 1138 | static xmlrpc_value *freeswitch_man(xmlrpc_env * const envP, xmlrpc_value * const paramArrayP, void *const userData) | |||
| 1139 | { | |||
| 1140 | char *oid = NULL((void*)0), *relative_oid, *s_action = NULL((void*)0), *data = NULL((void*)0); | |||
| 1141 | char buf[SWITCH_MAX_MANAGEMENT_BUFFER_LEN1024 * 8] = ""; | |||
| 1142 | switch_management_action_t action = SMA_NONE; | |||
| 1143 | xmlrpc_value *val = NULL((void*)0); | |||
| 1144 | ||||
| 1145 | /* Parse our argument array. */ | |||
| 1146 | xmlrpc_decompose_value(envP, paramArrayP, "(sss)", &oid, &s_action, &data); | |||
| 1147 | if (envP->fault_occurred) { | |||
| 1148 | return NULL((void*)0); | |||
| 1149 | } | |||
| 1150 | ||||
| 1151 | if (!strncasecmp(oid, FREESWITCH_OID_PREFIX".1.3.6.1.4.1." "27880", strlen(FREESWITCH_OID_PREFIX".1.3.6.1.4.1." "27880"))) { | |||
| 1152 | relative_oid = oid + strlen(FREESWITCH_OID_PREFIX".1.3.6.1.4.1." "27880"); | |||
| 1153 | } else { | |||
| 1154 | relative_oid = oid; | |||
| 1155 | } | |||
| 1156 | ||||
| 1157 | if (!zstr(data)_zstr(data)) { | |||
| 1158 | switch_copy_string(buf, data, sizeof(buf)); | |||
| 1159 | } | |||
| 1160 | ||||
| 1161 | if (!strcasecmp(s_action, "get")) { | |||
| 1162 | action = SMA_GET; | |||
| 1163 | } else if (!strcasecmp(s_action, "set")) { | |||
| 1164 | action = SMA_SET; | |||
| 1165 | } | |||
| 1166 | ||||
| 1167 | if (action) { | |||
| 1168 | if (switch_core_management_exec(relative_oid, action, buf, sizeof(buf)) == SWITCH_STATUS_SUCCESS) { | |||
| 1169 | if (action == SMA_SET) { | |||
| 1170 | if (*buf != '\0') { | |||
| 1171 | switch_snprintf(buf, sizeof(buf), "OK\n"); | |||
| 1172 | } | |||
| 1173 | } | |||
| 1174 | } else { | |||
| 1175 | if (*buf != '\0') { | |||
| 1176 | switch_snprintf(buf, sizeof(buf), "ERROR\n"); | |||
| 1177 | } | |||
| 1178 | } | |||
| 1179 | } else { | |||
| 1180 | switch_snprintf(buf, sizeof(buf), "Invalid Action %s\n", s_action); | |||
| 1181 | } | |||
| 1182 | ||||
| 1183 | /* Return our result. */ | |||
| 1184 | val = xmlrpc_build_value(envP, "s", buf); | |||
| 1185 | ||||
| 1186 | /* xmlrpc-c requires us to free memory it malloced from xmlrpc_decompose_value */ | |||
| 1187 | switch_safe_free(oid)if (oid) {free(oid);oid=((void*)0);}; | |||
| 1188 | switch_safe_free(s_action)if (s_action) {free(s_action);s_action=((void*)0);}; | |||
| 1189 | switch_safe_free(data)if (data) {free(data);data=((void*)0);}; | |||
| 1190 | return val; | |||
| 1191 | } | |||
| 1192 | ||||
| 1193 | SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime)switch_status_t mod_xml_rpc_runtime (void) | |||
| 1194 | { | |||
| 1195 | xmlrpc_env env; | |||
| 1196 | char logfile[512]; | |||
| 1197 | switch_hash_index_t *hi; | |||
| 1198 | const void *var; | |||
| 1199 | void *val; | |||
| 1200 | ||||
| 1201 | globals.running = 1; | |||
| 1202 | ||||
| 1203 | xmlrpc_env_init(&env); | |||
| 1204 | ||||
| 1205 | globals.registryP = xmlrpc_registry_new(&env); | |||
| 1206 | ||||
| 1207 | /* TODO why twice and why add_method for freeswitch.api and add_method2 for freeswitch.management ? */ | |||
| 1208 | xmlrpc_registry_add_method2(&env, globals.registryP, "freeswitch.api", &freeswitch_api, NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
| 1209 | xmlrpc_registry_add_method2(&env, globals.registryP, "freeswitch_api", &freeswitch_api, NULL((void*)0), NULL((void*)0), NULL((void*)0)); | |||
| 1210 | xmlrpc_registry_add_method(&env, globals.registryP, NULL((void*)0), "freeswitch.management", &freeswitch_man, NULL((void*)0)); | |||
| 1211 | xmlrpc_registry_add_method(&env, globals.registryP, NULL((void*)0), "freeswitch_management", &freeswitch_man, NULL((void*)0)); | |||
| 1212 | ||||
| 1213 | MIMETypeInit(); | |||
| 1214 | ||||
| 1215 | for (hi = switch_core_mime_index(); hi; hi = switch_core_hash_next(&hi)) { | |||
| 1216 | switch_core_hash_this(hi, &var, NULL((void*)0), &val); | |||
| 1217 | if (var && val) { | |||
| 1218 | MIMETypeAdd((char *) val, (char *) var); | |||
| 1219 | } | |||
| 1220 | } | |||
| 1221 | ||||
| 1222 | switch_snprintf(logfile, sizeof(logfile), "%s%s%s", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR"/", "freeswitch_http.log"); | |||
| 1223 | ServerCreate(&globals.abyssServer, "XmlRpcServer", globals.port, SWITCH_GLOBAL_dirs.htdocs_dir, logfile); | |||
| 1224 | ||||
| 1225 | xmlrpc_server_abyss_set_handler(&env, &globals.abyssServer, "/RPC2", globals.registryP); | |||
| 1226 | ||||
| 1227 | xmlrpc_env_clean(&env); | |||
| 1228 | ||||
| 1229 | if (ServerInit(&globals.abyssServer) != TRUE(!0)) { | |||
| 1230 | globals.running = 0; | |||
| 1231 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 1231, ((void*)0), SWITCH_LOG_ERROR, "Failed to start HTTP Port %d\n", globals.port); | |||
| 1232 | xmlrpc_registry_free(globals.registryP); | |||
| 1233 | MIMETypeTerm(); | |||
| 1234 | ||||
| 1235 | return SWITCH_STATUS_TERM; | |||
| 1236 | } | |||
| 1237 | ||||
| 1238 | ServerAddHandler(&globals.abyssServer, handler_hook); | |||
| 1239 | ServerAddHandler(&globals.abyssServer, auth_hook); | |||
| 1240 | ServerSetKeepaliveTimeout(&globals.abyssServer, 5); | |||
| 1241 | ||||
| 1242 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 1242, ((void*)0), SWITCH_LOG_NOTICE, "Starting HTTP Port %d, DocRoot [%s]%s\n", | |||
| 1243 | globals.port, SWITCH_GLOBAL_dirs.htdocs_dir, globals.enable_websocket ? " with websocket." : ""); | |||
| 1244 | ServerRun(&globals.abyssServer); | |||
| 1245 | ||||
| 1246 | switch_yield(1000000)switch_sleep(1000000);; | |||
| 1247 | ||||
| 1248 | globals.running = 0; | |||
| 1249 | ||||
| 1250 | return SWITCH_STATUS_TERM; | |||
| 1251 | } | |||
| 1252 | ||||
| 1253 | void stop_all_websockets() | |||
| 1254 | { | |||
| 1255 | switch_event_t *event; | |||
| 1256 | if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "websocket::stophook")switch_event_create_subclass_detailed("mod_xml_rpc.c", (const char * )(const char *)__func__, 1256, &event, SWITCH_EVENT_CUSTOM , "websocket::stophook") != SWITCH_STATUS_SUCCESS) { | |||
| 1257 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 1257, ((void*)0),SWITCH_LOG_ERROR, "Failed to create event!\n"); | |||
| 1258 | } | |||
| 1259 | switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "stop", "now"); | |||
| 1260 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 1260, ((void*)0), SWITCH_LOG_NOTICE, "stopping all websockets ...\n"); | |||
| 1261 | if (switch_event_fire(&event)switch_event_fire_detailed("mod_xml_rpc.c", (const char * )(const char *)__func__, 1261, &event, ((void*)0)) != SWITCH_STATUS_SUCCESS) { | |||
| 1262 | switch_log_printf(SWITCH_CHANNEL_LOGSWITCH_CHANNEL_ID_LOG, "mod_xml_rpc.c", (const char *)__func__ , 1262, ((void*)0),SWITCH_LOG_ERROR, "Failed to fire the event!\n"); | |||
| 1263 | switch_event_destroy(&event); | |||
| 1264 | } | |||
| 1265 | } | |||
| 1266 | ||||
| 1267 | /* upon module unload */ | |||
| 1268 | SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_rpc_shutdown)switch_status_t mod_xml_rpc_shutdown (void) | |||
| 1269 | { | |||
| 1270 | ||||
| 1271 | /* Cann't find a way to stop the websockets, use this for a workaround before finding the real one that works */ | |||
| 1272 | stop_all_websockets(); | |||
| 1273 | ||||
| 1274 | /* this makes the worker thread (ServerRun) stop */ | |||
| 1275 | ServerTerminate(&globals.abyssServer); | |||
| 1276 | ||||
| 1277 | do { | |||
| 1278 | switch_yield(100000)switch_sleep(100000);; | |||
| 1279 | } while (globals.running); | |||
| 1280 | ||||
| 1281 | ServerFree(&globals.abyssServer); | |||
| 1282 | xmlrpc_registry_free(globals.registryP); | |||
| 1283 | MIMETypeTerm(); | |||
| 1284 | ||||
| 1285 | switch_safe_free(globals.realm)if (globals.realm) {free(globals.realm);globals.realm=((void* )0);}; | |||
| 1286 | switch_safe_free(globals.user)if (globals.user) {free(globals.user);globals.user=((void*)0) ;}; | |||
| 1287 | switch_safe_free(globals.pass)if (globals.pass) {free(globals.pass);globals.pass=((void*)0) ;}; | |||
| 1288 | switch_safe_free(globals.default_domain)if (globals.default_domain) {free(globals.default_domain);globals .default_domain=((void*)0);}; | |||
| 1289 | ||||
| 1290 | return SWITCH_STATUS_SUCCESS; | |||
| 1291 | } | |||
| 1292 | ||||
| 1293 | /* For Emacs: | |||
| 1294 | * Local Variables: | |||
| 1295 | * mode:c | |||
| 1296 | * indent-tabs-mode:t | |||
| 1297 | * tab-width:4 | |||
| 1298 | * c-basic-offset:4 | |||
| 1299 | * End: | |||
| 1300 | * For VIM: | |||
| 1301 | * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet: | |||
| 1302 | */ |