@cryptotaxi247 / netdata-1 / commits / 452901c7a

registry now verifies the browser support cookies - to protect its database from being flooded with new persons

Costa Tsaousis committed Jun 2, 2016 at 16:27 UTC 452901c7a948022ee0a9d895377db0b27aa111bb
3 files changed +88 -7
src/registry.c
+31 -4
@@ -89,6 +89,7 @@ struct registry {
89 char *hostname;
90 char *registry_to_announce;
91 time_t persons_expiration; // seconds to expire idle persons
92 + int verify_cookies_redirects;
93
94 size_t max_url_length;
95 size_t max_name_length;
@@ -1011,16 +1012,28 @@ MACHINE *registry_request_machine(char *person_guid, char *machine_guid, char *u
1012 #define REGISTRY_STATUS_FAILED "failed"
1013 #define REGISTRY_STATUS_DISABLED "disabled"
1014
1014 -static inline void registry_set_person_cookie(struct web_client *w, PERSON *p) {
1015 +int registry_verify_cookies_redirects(void) {
1016 + return registry.verify_cookies_redirects;
1017 +}
1018 +
1019 +const char *registry_to_announce(void) {
1020 + return registry.registry_to_announce;
1021 +}
1022 +
1023 +void registry_set_cookie(struct web_client *w, const char *guid) {
1024 char edate[100];
1025 time_t et = time(NULL) + registry.persons_expiration;
1026 struct tm etmbuf, *etm = gmtime_r(&et, &etmbuf);
1027 strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", etm);
1028
1020 - snprintfz(w->cookie1, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s", p->guid, edate);
1029 + snprintfz(w->cookie1, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Expires=%s", guid, edate);
1030
1031 if(registry.registry_domain && registry.registry_domain[0])
1023 - snprintfz(w->cookie2, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Domain=%s; Expires=%s", p->guid, registry.registry_domain, edate);
1032 + snprintfz(w->cookie2, COOKIE_MAX, NETDATA_REGISTRY_COOKIE_NAME "=%s; Domain=%s; Expires=%s", guid, registry.registry_domain, edate);
1033 +}
1034 +
1035 +static inline void registry_set_person_cookie(struct web_client *w, PERSON *p) {
1036 + registry_set_cookie(w, p->guid);
1037 }
1038
1039 static inline void registry_json_header(struct web_client *w, const char *action, const char *status) {
@@ -1653,9 +1666,23 @@ int registry_init(void) {
1666 registry.registry_to_announce = config_get("registry", "registry to announce", "https://registry.my-netdata.io");
1667 registry.hostname = config_get("registry", "registry hostname", config_get("global", "hostname", hostname));
1668
1669 + registry.verify_cookies_redirects = config_get_number("registry", "verify browser cookies support max redirects", 2);
1670 + if(registry.verify_cookies_redirects < 0) {
1671 + registry.verify_cookies_redirects = 0;
1672 + config_set_number("registry", "verify browser cookies support max redirects", registry.verify_cookies_redirects);
1673 + }
1674 +
1675 registry.max_url_length = config_get_number("registry", "max URL length", 1024);
1657 - registry.max_name_length = config_get_number("registry", "max URL name length", 50);
1676 + if(registry.max_url_length < 10) {
1677 + registry.max_url_length = 10;
1678 + config_set_number("registry", "max URL length", registry.max_url_length);
1679 + }
1680
1681 + registry.max_name_length = config_get_number("registry", "max URL name length", 50);
1682 + if(registry.max_name_length < 10) {
1683 + registry.max_name_length = 10;
1684 + config_set_number("registry", "max URL name length", registry.max_name_length);
1685 + }
1686
1687 // initialize entries counters
1688 registry.persons_count = 0;
src/registry.h
+4
@@ -5,6 +5,10 @@
5
6 #define NETDATA_REGISTRY_COOKIE_NAME "netdata_registry_id"
7
8 +extern void registry_set_cookie(struct web_client *w, const char *guid);
9 +extern const char *registry_to_announce(void);
10 +extern int registry_verify_cookies_redirects(void);
11 +
12 extern int registry_request_access_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *name, time_t when);
13 extern int registry_request_delete_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *delete_url, time_t when);
14 extern int registry_request_search_json(struct web_client *w, char *person_guid, char *machine_guid, char *url, char *request_machine, time_t when);
src/web_client.c
+53 -3
@@ -862,7 +862,7 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
862 {
863 static uint32_t hash_action = 0, hash_access = 0, hash_hello = 0, hash_delete = 0, hash_search = 0,
864 hash_switch = 0, hash_machine = 0, hash_url = 0, hash_name = 0, hash_delete_url = 0, hash_for = 0,
865 - hash_to = 0;
865 + hash_to = 0, hash_redirects = 0;
866
867 if(unlikely(!hash_action)) {
868 hash_action = simple_hash("action");
@@ -877,6 +877,7 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
877 hash_delete_url = simple_hash("delete_url");
878 hash_for = simple_hash("for");
879 hash_to = simple_hash("to");
880 + hash_redirects = simple_hash("redirects");
881 }
882
883 char person_guid[36 + 1] = "";
@@ -886,9 +887,9 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
887 // FIXME
888 // The browser may send multiple cookies with our id
889
889 - char *cookie = strstr(w->response.data->buffer, " " NETDATA_REGISTRY_COOKIE_NAME "=");
890 + char *cookie = strstr(w->response.data->buffer, NETDATA_REGISTRY_COOKIE_NAME "=");
891 if(cookie)
891 - strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME) + 1], 36);
892 + strncpyz(person_guid, &cookie[sizeof(NETDATA_REGISTRY_COOKIE_NAME)], 36);
893
894 char action = '\0';
895 char *machine_guid = NULL,
@@ -897,6 +898,7 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
898 *search_machine_guid = NULL,
899 *delete_url = NULL,
900 *to_person_guid = NULL;
901 + int redirects = 0;
902
903 while(url) {
904 char *value = mystrsep(&url, "?&[]");
@@ -918,7 +920,13 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
920 else if(vhash == hash_delete && !strcmp(value, "delete")) action = 'D';
921 else if(vhash == hash_search && !strcmp(value, "search")) action = 'S';
922 else if(vhash == hash_switch && !strcmp(value, "switch")) action = 'W';
923 +#ifdef NETDATA_INTERNAL_CHECKS
924 + else error("unknown registry action '%s'", value);
925 +#endif /* NETDATA_INTERNAL_CHECKS */
926 }
927 + else if(hash == hash_redirects && !strcmp(name, "redirects"))
928 + redirects = atoi(value);
929 +
930 else if(hash == hash_machine && !strcmp(name, "machine"))
931 machine_guid = value;
932
@@ -941,6 +949,9 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
949 if(hash == hash_to && !strcmp(name, "to"))
950 to_person_guid = value;
951 }
952 +#ifdef NETDATA_INTERNAL_CHECKS
953 + else error("unused registry URL parameter '%s' with value '%s'", name, value);
954 +#endif /* NETDATA_INTERNAL_CHECKS */
955 }
956
957 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)
981
982 switch(action) {
983 case 'A':
984 + if(registry_verify_cookies_redirects() > 0 && (!cookie || !person_guid[0])) {
985 + buffer_flush(w->response.data);
986 +
987 + if(redirects > registry_verify_cookies_redirects()) {
988 + buffer_sprintf(w->response.data, "Your browser does not support cookies");
989 + return 400;
990 + }
991 +
992 + redirects++;
993 +
994 + char *encoded_url = url_encode(machine_url);
995 + if(!encoded_url) {
996 + error("%llu: Cannot URL encode string '%s'", w->id, machine_url);
997 + return 500;
998 + }
999 +
1000 + char *encoded_name = url_encode(url_name);
1001 + if(!encoded_name) {
1002 + free(encoded_url);
1003 + error("%llu: Cannot URL encode string '%s'", w->id, url_name);
1004 + return 500;
1005 + }
1006 +
1007 + char *encoded_guid = url_encode(machine_guid);
1008 + if(!encoded_guid) {
1009 + free(encoded_url);
1010 + free(encoded_name);
1011 + error("%llu: Cannot URL encode string '%s'", w->id, machine_guid);
1012 + return 500;
1013 + }
1014 +
1015 + registry_set_cookie(w, "give-me-back-this-cookie-please");
1016 + buffer_sprintf(w->response.header, "Location: %s/api/v1/registry?action=access&machine=%s&name=%s&url=%s&redirects=%d\r\n",
1017 + registry_to_announce(), encoded_guid, encoded_name, encoded_url, redirects);
1018 + free(encoded_guid);
1019 + free(encoded_name);
1020 + free(encoded_url);
1021 + return 307;
1022 + }
1023 return registry_request_access_json(w, person_guid, machine_guid, machine_url, url_name, time(NULL));
1024
1025 case 'D':