]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
improve http support
authorAnthony Minessale <anthony.minessale@gmail.com>
Tue, 27 Nov 2007 19:25:16 +0000 (19:25 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Tue, 27 Nov 2007 19:25:16 +0000 (19:25 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@6413 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/include/switch_utils.h
src/mod/endpoints/mod_alsa/mod_alsa.c
src/mod/endpoints/mod_portaudio/mod_portaudio.c
src/mod/xml_int/mod_xml_rpc/mod_xml_rpc.c
src/switch_utils.c
src/switch_xml.cpp

index 3caf62c222c3c01a79aab39ce912233bb6564e39..f79fb3eb3d7b25abd49626f6a93eb1886b4d2922 100644 (file)
@@ -56,6 +56,7 @@ SWITCH_BEGIN_EXTERN_C
 #endif
 
 SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size_t ilen, unsigned char *out, switch_size_t olen);
+SWITCH_DECLARE(switch_status_t) switch_b64_decode(char *in, char *out, switch_size_t olen);
 
 static inline switch_bool_t switch_is_digit_string(const char *s) {
 
index 0d20897d9c4efade4d7742c3a9f827b0a6a4caac..024866e74b9162b5b286bbe33189182d8688040e 100644 (file)
@@ -1566,6 +1566,8 @@ SWITCH_STANDARD_API(pa_cmd)
                stream->write_function(stream, "</pre>");
 #endif
 
+               stream->write_function(stream, "Content-type: text/html\n\n");
+
                wcmd = switch_str_nil(switch_event_get_header(stream->event, "wcmd"));
                action = switch_event_get_header(stream->event, "action");
 
index b46e636609b93dd1aa0aedfc196f2d4dddb83285..413ddd07653aec511cfc076f02a84de0a97f4906 100644 (file)
@@ -1673,6 +1673,8 @@ SWITCH_STANDARD_API(pa_cmd)
 
 
        if (http) {
+               stream->write_function(stream, "Content-type: text/html\n\n");
+
 #if 0
                switch_event_header_t *hp;
                stream->write_function(stream, "<pre>");
index de29b5ea640fbe3849a79e2da194d939d4bbab08..a5104b32116e1e1f7a2b07d4a9bf8d8213b5386c 100644 (file)
@@ -41,6 +41,7 @@
 #include <xmlrpc-c/abyss.h>
 #include <xmlrpc-c/server.h>
 #include <xmlrpc-c/server_abyss.h>
+#include "../../libs/xmlrpc-c/lib/abyss/src/token.h"
 
 SWITCH_MODULE_LOAD_FUNCTION(mod_xml_rpc_load);
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_xml_rpc_shutdown);
@@ -137,27 +138,187 @@ static switch_status_t http_stream_write(switch_stream_handle_t *handle, const c
 }
 
 
-abyss_bool HandleHook(TSession * r)
+static abyss_bool http_directory_auth(TSession *r, char *domain_name) 
 {
-       char *m = "text/html";
+    char *p, *x;
+    char z[80], t[80];
+       char user[512];
+       char *pass;
+       const char *mypass1 = NULL, *mypass2 = NULL;
+       switch_xml_t x_domain, x_domain_root = NULL, x_user, x_params, x_param;
+
+    p = RequestHeaderValue(r, "authorization");
+
+    if (p) {
+        NextToken(&p);
+        x = GetToken(&p);
+        if (x) {
+            if (!strcasecmp(x,"basic")) {
+
+
+                NextToken(&p);
+                               switch_b64_decode(p, user, sizeof(user));
+                               if ((pass = strchr(user, ':'))) {
+                                       *pass++ = '\0';
+                               }
+                               
+                               if (switch_xml_locate_user(user, domain_name, NULL, &x_domain_root, &x_domain, &x_user, NULL) != SWITCH_STATUS_SUCCESS) {
+                                       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain_name);
+                                       goto fail;
+                               }
+
+                               if (!(x_params = switch_xml_child(x_user, "params"))) {
+                                       goto authed;
+                }
+
+
+                for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
+                    const char *var = switch_xml_attr_soft(x_param, "name");
+                    const char *val = switch_xml_attr_soft(x_param, "value");
+                    
+                    if (!strcasecmp(var, "password")) {
+                        mypass1 = val;
+                    } else if (!strcasecmp(var, "vm-password")) {
+                        mypass2 = val;
+                    } else if (!strncasecmp(var, "http-", 5)) {
+                                               ResponseAddField(r, (char *)var, (char *)val);
+                    } 
+                               }
+
+                               sprintf(z, "%s:%s", user, mypass1);
+                Base64Encode(z, t);
+                               
+                               if (!strcmp(p, t)) {
+                    r->user=strdup(user);
+                                       goto authed;
+                               }
+
+                               sprintf(z, "%s:%s", user, mypass2);
+                Base64Encode(z, t);
+                               
+                               if (!strcmp(p, t)) {
+                    r->user=strdup(user);
+                                       goto authed;
+                               }
+                               
+                               goto fail;
+
+
+                       authed:
+                               
+                               if (x_domain_root) {
+                                       switch_xml_free(x_domain_root);
+                               }
+                               
+                               return TRUE;
+            }
+        }
+    }
+
+ fail:
+
+       if (x_domain_root) {
+               switch_xml_free(x_domain_root);
+       }
+
+    sprintf(z, "Basic realm=\"%s\"", domain_name);
+    ResponseAddField(r, "WWW-Authenticate", z);
+    ResponseStatus(r, 401);
+    return FALSE;
+}
+
+abyss_bool auth_hook(TSession * r)
+{
+       char *domain_name, *e;
+       abyss_bool ret = FALSE;
+
+
+
+       if (!strncmp(r->uri, "/domains/", 9)) {
+               domain_name = strdup(r->uri + 9);
+               assert(domain_name);
+               
+               if ((e = strchr(domain_name, '/'))) {
+                       *e++ = '\0';
+               }
+
+               ret = !http_directory_auth(r, domain_name);
+
+               free(domain_name);
+       } else {
+               if (globals.realm) {
+                       if (!RequestAuth(r, globals.realm, globals.user, globals.pass)) {
+                               ret = TRUE;
+                       }
+               }
+       }
+
+       return ret;
+}
+
+abyss_bool handler_hook(TSession * r)
+{
+       //char *mime = "text/html";
+       char buf[512] = "HTTP/1.1 200 OK\n";
        switch_stream_handle_t stream = { 0 };
        char *command;
+       int i, j = 0;
+       TTableItem *ti;
+       char *dup = NULL;
 
        stream.data = r;
        stream.write_function = http_stream_write;
 
-       if (globals.realm) {
-               if (!RequestAuth(r, globals.realm, globals.user, globals.pass)) {
-                       return TRUE;
-               }
+       if ((command = strstr(r->uri, "/api/"))) {
+               command += 5;
+       } else {
+               return FALSE;
        }
 
+       for (i=0;i<r->response_headers.size;i++) {
+               ti=&r->response_headers.item[i];
+               if (!strcasecmp(ti->name, "http-allowed-api")) {
+                       int argc, x;
+                       char *argv[256] = { 0 };
+                       j++;
+                       
+                       if (!strcasecmp(ti->value, "any")) {
+                               goto auth;
+                       }
 
+                       if (!strcasecmp(ti->value, "none")) {
+                               goto unauth;
+                       }
 
-       if (strncmp(r->uri, "/api/", 5)) {
-               return FALSE;
+                       dup = strdup(ti->value);
+                       argc = switch_separate_string(dup, ',', argv, (sizeof(argv) / sizeof(argv[0])));
+
+                       for (x = 0; x < argc; x++) {
+                               if (!strcasecmp(command, argv[x])) {
+                                       goto auth;
+                               }
+                       }
+
+                       goto unauth;
+               }
        }
 
+       if (r->user && !j) {
+               goto unauth;
+       }
+
+       goto auth;
+
+ unauth:
+       ResponseStatus(r, 403);
+       ResponseError(r);
+       switch_safe_free(dup);
+
+       return TRUE;
+
+ auth:
+
+
        if (switch_event_create(&stream.event, SWITCH_EVENT_API) == SWITCH_STATUS_SUCCESS) {
                const char * const content_length = RequestHeaderValue(r, "content-length");
                        
@@ -258,14 +419,40 @@ abyss_bool HandleHook(TSession * r)
                }
        }
 
-       command = r->uri + 5;
 
-       ResponseChunked(r);
-       ResponseStatus(r, 200);
-       ResponseContentType(r, m);
-       ResponseWrite(r);
-       switch_api_execute(command, r->query, NULL, &stream);
-       HTTPWriteEnd(r);
+
+       //ResponseChunked(r);
+       
+       //ResponseContentType(r, mime);
+       //ResponseWrite(r);
+
+       HTTPWrite(r, buf, (uint32_t) strlen(buf));
+
+       /* generation of the date field */
+       if (DateToString(&r->date, buf)) {
+               ResponseAddField(r,"Date", buf);
+       }
+       
+       /* Generation of the server field */
+       ResponseAddField(r,"Server", SERVER_HVERSION);
+
+       for (i=0;i<r->response_headers.size;i++) {
+               ti=&r->response_headers.item[i];
+               ConnWrite(r->conn,ti->name,strlen(ti->name));
+               ConnWrite(r->conn,": ",2);
+               ConnWrite(r->conn,ti->value,strlen(ti->value));
+               ConnWrite(r->conn,CRLF,2);
+       }
+
+       
+       if (switch_api_execute(command, r->query, NULL, &stream) == SWITCH_STATUS_SUCCESS) {
+               r->done = TRUE;
+       } else {
+               ResponseStatus(r, 404);
+               ResponseError(r);
+       } 
+       
+       //HTTPWriteEnd(r);
        return TRUE;
 }
 
@@ -387,8 +574,9 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_xml_rpc_runtime)
                return SWITCH_STATUS_TERM;
        }
 
-       ServerAddHandler(&abyssServer, HandleHook);
 
+       ServerAddHandler(&abyssServer, handler_hook);
+       ServerAddHandler(&abyssServer, auth_hook);
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Starting HTTP Port %d, DocRoot [%s]\n", globals.port, SWITCH_GLOBAL_dirs.htdocs_dir);
        while (globals.running) {
                ServerRunOnce2(&abyssServer, ABYSS_FOREGROUND);
index 52e7a8876e940e64a71effc14e89fe29344bf4ca..9274be47bc1d2bc9c9e4cadd66d0848ca0009341 100644 (file)
@@ -91,6 +91,46 @@ SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size
 }
 
 
+SWITCH_DECLARE(switch_status_t) switch_b64_decode(char *in, char *out, switch_size_t olen)
+{
+
+       char l64[256];
+       int b = 0, c, l = 0, i;
+       char *ip, *op = out;
+       size_t ol = 0;
+
+       for (i=0; i<256; i++) {
+               l64[i] = -1;
+       }
+
+       for (i=0; i<64; i++) {
+               l64[(int)switch_b64_table[i]] = i;
+       }
+
+       for (ip = in; ip && *ip; ip++) {
+               c = l64[(int)*ip];
+               if (c == -1) {
+                       continue;
+               }
+
+               b = (b << 6) + c;
+               l += 6;
+
+               while (l >= 8) {
+                       op[ol++] = (b >> (l -= 8)) % 256;
+                       if (ol >= olen -2) {
+                               goto end;
+                       }
+               }
+       }
+
+ end:
+
+       op[ol++] = '\0';
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
 
 static int write_buf(int fd, const char *buf)
 {
index 827e0b67573ac483d3413107983c32739142a1d0..6e5cad4f70deb6d508aacc6b873f4d5ac3c6c5d6 100644 (file)
@@ -1316,6 +1316,7 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate_user(const char *user_name,
        } else {
                snprintf(params, sizeof(params), "user=%s&domain=%s&ip=%s", 
                                 switch_str_nil(user_name), switch_str_nil(domain_name), switch_str_nil(ip));
+               xtra_params = "";
        }
        if ((status = switch_xml_locate_domain(domain_name, params, root, domain)) != SWITCH_STATUS_SUCCESS) {
                return status;
@@ -1328,11 +1329,17 @@ SWITCH_DECLARE(switch_status_t) switch_xml_locate_user(const char *user_name,
        } 
 
        if (user_name) {
-               if (!(*user = switch_xml_find_child(*domain, "user", "id", user_name)) && strstr(xtra_params, "mailbox") && 
-                       !(*user = switch_xml_find_child(*domain, "user", "mailbox", user_name))) {
-                       return SWITCH_STATUS_FALSE;
+               
+               if (strstr(xtra_params, "mailbox")) {
+                       if ((*user = switch_xml_find_child(*domain, "user", "mailbox", user_name))) {
+                               return SWITCH_STATUS_SUCCESS;
+                       }
                }
-               return SWITCH_STATUS_SUCCESS;
+
+               if ((*user = switch_xml_find_child(*domain, "user", "id", user_name))) {
+                       return SWITCH_STATUS_SUCCESS;
+               }
+               
        }
 
        return SWITCH_STATUS_FALSE;