]> arthur.barton.de Git - netdata.git/commitdiff
registry now verifies the browser support cookies - to protect its database from...
authorCosta Tsaousis <costa@tsaousis.gr>
Thu, 2 Jun 2016 13:27:05 +0000 (16:27 +0300)
committerCosta Tsaousis <costa@tsaousis.gr>
Thu, 2 Jun 2016 13:27:05 +0000 (16:27 +0300)
src/registry.c
src/registry.h
src/web_client.c

index a81ab955eca43e95ef915c95529ec8534c78e63c..ad38163a73d4e4616810d45de3bf754b39835cda 100644 (file)
@@ -89,6 +89,7 @@ struct registry {
        char *hostname;
        char *registry_to_announce;
        time_t persons_expiration; // seconds to expire idle persons
+       int verify_cookies_redirects;
 
        size_t max_url_length;
        size_t max_name_length;
@@ -1011,16 +1012,28 @@ MACHINE *registry_request_machine(char *person_guid, char *machine_guid, char *u
 #define REGISTRY_STATUS_FAILED "failed"
 #define REGISTRY_STATUS_DISABLED "disabled"
 
-static inline void registry_set_person_cookie(struct web_client *w, PERSON *p) {
+int registry_verify_cookies_redirects(void) {
+       return registry.verify_cookies_redirects;
+}
+
+const char *registry_to_announce(void) {
+       return registry.registry_to_announce;
+}
+
+void registry_set_cookie(struct web_client *w, const char *guid) {
        char edate[100];
        time_t et = time(NULL) + registry.persons_expiration;
        struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf);
        strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm);
 
-       snprintfz(w->cookie1, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s", p->guid, edate);
+       snprintfz(w->cookie1, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s", guid, edate);
 
        if(registry.registry_domain && registry.registry_domain[0])
-               snprintfz(w->cookie2, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Domain=%s; Expires=%s", p->guid, registry.registry_domain, edate);
+               snprintfz(w->cookie2, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Domain=%s; Expires=%s", guid, registry.registry_domain, edate);
+}
+
+static inline void registry_set_person_cookie(struct web_client *w, PERSON *p) {
+       registry_set_cookie(w, p->guid);
 }
 
 static inline void registry_json_header(struct web_client *w, const char *action, const char *status) {
@@ -1653,9 +1666,23 @@ int registry_init(void) {
        registry.registry_to_announce = config_get("registry", "registry to announce", "https://registry.my-netdata.io");
        registry.hostname = config_get("registry", "registry hostname", config_get("global", "hostname", hostname));
 
+       registry.verify_cookies_redirects = config_get_number("registry", "verify browser cookies support max redirects", 2);
+       if(registry.verify_cookies_redirects < 0) {
+               registry.verify_cookies_redirects = 0;
+               config_set_number("registry", "verify browser cookies support max redirects", registry.verify_cookies_redirects);
+       }
+
        registry.max_url_length = config_get_number("registry", "max URL length", 1024);
-       registry.max_name_length = config_get_number("registry", "max URL name length", 50);
+       if(registry.max_url_length < 10) {
+               registry.max_url_length = 10;
+               config_set_number("registry", "max URL length", registry.max_url_length);
+       }
 
+       registry.max_name_length = config_get_number("registry", "max URL name length", 50);
+       if(registry.max_name_length < 10) {
+               registry.max_name_length = 10;
+               config_set_number("registry", "max URL name length", registry.max_name_length);
+       }
 
        // initialize entries counters
        registry.persons_count = 0;
index d95383b5df5dc5fc5d59ab368cbace52ded1c094..9e7a13ecbf80168edf179dd957017170fc876fcb 100644 (file)
@@ -5,6 +5,10 @@
 
 #define NETDATA_REGISTRY_COOKIE_NAME "netdata_registry_id"
 
+extern void registry_set_cookie(struct web_client *w, const char *guid);
+extern const char *registry_to_announce(void);
+extern int registry_verify_cookies_redirects(void);
+
 extern int registry_request_access_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when);
 extern int registry_request_delete_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when);
 extern int registry_request_search_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when);
index bc1071ea0e7344e23fca5e4a7605ae050d3f9f8e..9e8071137626a248783987324bcfc804b756d5d8 100644 (file)
@@ -862,7 +862,7 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
 {
        static uint32_t hash_action = 0, hash_access = 0, hash_hello = 0, hash_delete = 0, hash_search = 0,
                        hash_switch = 0, hash_machine = 0, hash_url = 0, hash_name = 0, hash_delete_url = 0, hash_for = 0,
-                       hash_to = 0;
+                       hash_to = 0, hash_redirects = 0;
 
        if(unlikely(!hash_action)) {
                hash_action = simple_hash("action");
@@ -877,6 +877,7 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
                hash_delete_url = simple_hash("delete_url");
                hash_for = simple_hash("for");
                hash_to = simple_hash("to");
+               hash_redirects = simple_hash("redirects");
        }
 
        char person_guid[36 + 1] = "";
@@ -886,9 +887,9 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
        // FIXME
        // The browser may send multiple cookies with our id
        
-       char *cookie = strstr(w->response.data->buffer, " " NETDATA_REGISTRY_COOKIE_NAME "=");
+       char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "=");
        if(cookie)
-               strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME) + 1], 36);
+               strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], 36);
 
        char action = '\0';
        char *machine_guid = NULL,
@@ -897,6 +898,7 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
                        *search_machine_guid = NULL,
                        *delete_url = NULL,
                        *to_person_guid = NULL;
+       int redirects = 0;
 
        while(url) {
                char *value = mystrsep(&url, "?&[]");
@@ -918,7 +920,13 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
                        else if(vhash == hash_delete && !strcmp(value, "delete")) action = 'D';
                        else if(vhash == hash_search && !strcmp(value, "search")) action = 'S';
                        else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W';
+#ifdef NETDATA_INTERNAL_CHECKS
+            else error("unknown registry action '%s'", value);
+#endif /* NETDATA_INTERNAL_CHECKS */
                }
+               else if(hash == hash_redirects && !strcmp(name, "redirects"))
+                       redirects = atoi(value);
+
                else if(hash == hash_machine && !strcmp(name, "machine"))
                        machine_guid = value;
 
@@ -941,6 +949,9 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
                        if(hash == hash_to && !strcmp(name, "to"))
                                to_person_guid = value;
                }
+#ifdef NETDATA_INTERNAL_CHECKS
+               else error("unused registry URL parameter '%s' with value '%s'", name, value);
+#endif /* NETDATA_INTERNAL_CHECKS */
        }
 
        if(action == 'A' && (!machine_guid || !machine_url || !url_name)) {
@@ -970,6 +981,45 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
 
        switch(action) {
                case 'A':
+                       if(registry_verify_cookies_redirects() > 0 && (!cookie || !person_guid[0])) {
+                               buffer_flush(w->response.data);
+
+                               if(redirects > registry_verify_cookies_redirects()) {
+                                       buffer_sprintf(w->response.data, "Your browser does not support cookies");
+                                       return 400;
+                               }
+
+                               redirects++;
+
+                               char *encoded_url = url_encode(machine_url);
+                               if(!encoded_url) {
+                                       error("%llu: Cannot URL encode string '%s'", w->id, machine_url);
+                                       return 500;
+                               }
+
+                               char *encoded_name = url_encode(url_name);
+                               if(!encoded_name) {
+                                       free(encoded_url);
+                                       error("%llu: Cannot URL encode string '%s'", w->id, url_name);
+                                       return 500;
+                               }
+
+                               char *encoded_guid = url_encode(machine_guid);
+                               if(!encoded_guid) {
+                                       free(encoded_url);
+                                       free(encoded_name);
+                                       error("%llu: Cannot URL encode string '%s'", w->id, machine_guid);
+                                       return 500;
+                               }
+
+                               registry_set_cookie(w, "give-me-back-this-cookie-please");
+                               buffer_sprintf(w->response.header, "Location: %s/api/v1/registry?action=access&machine=%s&name=%s&url=%s&redirects=%d\r\n",
+                                                          registry_to_announce(), encoded_guid, encoded_name, encoded_url, redirects);
+                               free(encoded_guid);
+                               free(encoded_name);
+                               free(encoded_url);
+                               return 307;
+                       }
                        return registry_request_access_json(w, person_guid, machine_guid, machine_url, url_name, time(NULL));
 
                case 'D':