@cryptotaxi247 / netdata-1 / commits / ac54eeb19

prevented crashes in URL parsing where in several cases, error handling was not complete

Costa Tsaousis (ktsaou) committed Apr 10, 2016 at 18:45 UTC ac54eeb19e2f04426de9bfc711624a01ddd5e0b2
1 file changed +177 -128
src/web_client.c
+177 -128
@@ -781,36 +781,53 @@ int web_client_api_request_v1(struct web_client *w, char *url)
781 {
782 // get the command
783 char *tok = mystrsep(&url, "/?&");
784 - debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok);
785 -
786 - if(strcmp(tok, "data") == 0)
787 - return web_client_api_request_v1_data(w, url);
788 - else if(strcmp(tok, "chart") == 0)
789 - return web_client_api_request_v1_chart(w, url);
790 - else if(strcmp(tok, "charts") == 0)
791 - return web_client_api_request_v1_charts(w, url);
792 -
793 - buffer_flush(w->response.data);
794 - buffer_sprintf(w->response.data, "Unsupported v1 API command: %s", tok);
795 - return 404;
784 + if(tok && *tok) {
785 + debug(D_WEB_CLIENT, "%llu: Searching for API v1 command '%s'.", w->id, tok);
786 +
787 + if(strcmp(tok, "data") == 0)
788 + return web_client_api_request_v1_data(w, url);
789 + else if(strcmp(tok, "chart") == 0)
790 + return web_client_api_request_v1_chart(w, url);
791 + else if(strcmp(tok, "charts") == 0)
792 + return web_client_api_request_v1_charts(w, url);
793 + else {
794 + buffer_flush(w->response.data);
795 + buffer_sprintf(w->response.data, "Unsupported v1 API command: %s", tok);
796 + return 404;
797 + }
798 + }
799 + else {
800 + buffer_flush(w->response.data);
801 + buffer_sprintf(w->response.data, "API v1 command?");
802 + return 400;
803 + }
804 }
805
806 int web_client_api_request(struct web_client *w, char *url)
807 {
808 // get the api version
809 char *tok = mystrsep(&url, "/?&");
802 - debug(D_WEB_CLIENT, "%llu: Searching for API version '%s'.", w->id, tok);
803 -
804 - if(strcmp(tok, "v1") == 0)
805 - return web_client_api_request_v1(w, url);
806 -
807 - buffer_flush(w->response.data);
808 - buffer_sprintf(w->response.data, "Unsupported API version: %s", tok);
809 - return 404;
810 + if(tok && *tok) {
811 + debug(D_WEB_CLIENT, "%llu: Searching for API version '%s'.", w->id, tok);
812 + if(strcmp(tok, "v1") == 0)
813 + return web_client_api_request_v1(w, url);
814 + else {
815 + buffer_flush(w->response.data);
816 + buffer_sprintf(w->response.data, "Unsupported API version: %s", tok);
817 + return 404;
818 + }
819 + }
820 + else {
821 + buffer_flush(w->response.data);
822 + buffer_sprintf(w->response.data, "Which API version?");
823 + return 400;
824 + }
825 }
826
827 int web_client_data_request(struct web_client *w, char *url, int datasource_type)
828 {
829 + RRDSET *st = NULL;
830 +
831 char *args = strchr(url, '?');
832 if(args) {
833 *args='\0';
@@ -819,11 +836,14 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
836
837 // get the name of the data to show
838 char *tok = mystrsep(&url, "/");
822 - debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
839
840 // do we have such a data set?
825 - RRDSET *st = rrdset_find_byname(tok);
826 - if(!st) st = rrdset_find(tok);
841 + if(tok && *tok) {
842 + debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
843 + st = rrdset_find_byname(tok);
844 + if(!st) st = rrdset_find(tok);
845 + }
846 +
847 if(!st) {
848 // we don't have it
849 // try to send a file with that name
@@ -850,34 +870,36 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
870 if(url) {
871 // parse the group count required
872 tok = mystrsep(&url, "/");
853 - if(tok) group_count = atoi(tok);
873 + if(tok && *tok) group_count = atoi(tok);
874 if(group_count < 1) group_count = 1;
875 //if(group_count > save_history / 20) group_count = save_history / 20;
876 }
877 if(url) {
878 // parse the grouping method required
879 tok = mystrsep(&url, "/");
860 - if(strcmp(tok, "max") == 0) group_method = GROUP_MAX;
861 - else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE;
862 - else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM;
863 - else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok);
880 + if(tok && *tok) {
881 + if(strcmp(tok, "max") == 0) group_method = GROUP_MAX;
882 + else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE;
883 + else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM;
884 + else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok);
885 + }
886 }
887 if(url) {
888 // parse after time
889 tok = mystrsep(&url, "/");
868 - if(tok) after = strtoul(tok, NULL, 10);
890 + if(tok && *tok) after = strtoul(tok, NULL, 10);
891 if(after < 0) after = 0;
892 }
893 if(url) {
894 // parse before time
895 tok = mystrsep(&url, "/");
874 - if(tok) before = strtoul(tok, NULL, 10);
896 + if(tok && *tok) before = strtoul(tok, NULL, 10);
897 if(before < 0) before = 0;
898 }
899 if(url) {
900 // parse nonzero
901 tok = mystrsep(&url, "/");
880 - if(tok && strcmp(tok, "nonzero") == 0) nonzero = 1;
902 + if(tok && *tok && strcmp(tok, "nonzero") == 0) nonzero = 1;
903 }
904
905 w->response.data->contenttype = CT_APPLICATION_JSON;
@@ -896,9 +918,9 @@ int web_client_data_request(struct web_client *w, char *url, int datasource_type
918
919 while(args) {
920 tok = mystrsep(&args, "&");
899 - if(tok) {
921 + if(tok && *tok) {
922 char *name = mystrsep(&tok, "=");
901 - if(name && strcmp(name, "tqx") == 0) {
923 + if(name && *name && strcmp(name, "tqx") == 0) {
924 char *key = mystrsep(&tok, ":");
925 char *value = mystrsep(&tok, ";");
926 if(key && value && *key && *value) {
@@ -1090,118 +1112,142 @@ void web_client_process(struct web_client *w) {
1112 w->last_url[URL_MAX] = '\0';
1113
1114 tok = mystrsep(&url, "/?");
1115 + if(tok && *tok) {
1116 + debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, tok);
1117
1094 - debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, tok);
1095 -
1096 - if(strcmp(tok, "api") == 0) {
1097 - // the client is requesting api access
1098 - datasource_type = DATASOURCE_JSON;
1099 - code = web_client_api_request(w, url);
1100 - }
1101 -#ifdef NETDATA_INTERNAL_CHECKS
1102 - else if(strcmp(tok, "exit") == 0) {
1103 - netdata_exit = 1;
1104 - code = 200;
1105 - w->response.data->contenttype = CT_TEXT_PLAIN;
1106 - buffer_flush(w->response.data);
1107 - buffer_strcat(w->response.data, "will do");
1108 - }
1109 -#endif
1110 - else if(strcmp(tok, WEB_PATH_DATA) == 0) { // "data"
1111 - // the client is requesting rrd data
1112 - datasource_type = DATASOURCE_JSON;
1113 - code = web_client_data_request(w, url, datasource_type);
1114 - }
1115 - else if(strcmp(tok, WEB_PATH_DATASOURCE) == 0) { // "datasource"
1116 - // the client is requesting google datasource
1117 - code = web_client_data_request(w, url, datasource_type);
1118 - }
1119 - else if(strcmp(tok, WEB_PATH_GRAPH) == 0) { // "graph"
1120 - // the client is requesting an rrd graph
1121 -
1122 - // get the name of the data to show
1123 - tok = mystrsep(&url, "/?&");
1124 - debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1125 -
1126 - // do we have such a data set?
1127 - RRDSET *st = rrdset_find_byname(tok);
1128 - if(!st) st = rrdset_find(tok);
1129 - if(!st) {
1130 - // we don't have it
1131 - // try to send a file with that name
1132 - buffer_flush(w->response.data);
1133 - code = mysendfile(w, tok);
1118 + if(strcmp(tok, "api") == 0) {
1119 + // the client is requesting api access
1120 + datasource_type = DATASOURCE_JSON;
1121 + code = web_client_api_request(w, url);
1122 }
1135 - else {
1123 +#ifdef NETDATA_INTERNAL_CHECKS
1124 + else if(strcmp(tok, "exit") == 0) {
1125 + netdata_exit = 1;
1126 code = 200;
1137 - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
1138 - w->response.data->contenttype = CT_APPLICATION_JSON;
1127 + w->response.data->contenttype = CT_TEXT_PLAIN;
1128 buffer_flush(w->response.data);
1140 - rrd_stats_graph_json(st, url, w->response.data);
1129 + buffer_strcat(w->response.data, "will do");
1130 + }
1131 +#endif
1132 + else if(strcmp(tok, WEB_PATH_DATA) == 0) { // "data"
1133 + // the client is requesting rrd data
1134 + datasource_type = DATASOURCE_JSON;
1135 + code = web_client_data_request(w, url, datasource_type);
1136 + }
1137 + else if(strcmp(tok, WEB_PATH_DATASOURCE) == 0) { // "datasource"
1138 + // the client is requesting google datasource
1139 + code = web_client_data_request(w, url, datasource_type);
1140 + }
1141 + else if(strcmp(tok, WEB_PATH_GRAPH) == 0) { // "graph"
1142 + // the client is requesting an rrd graph
1143 +
1144 + // get the name of the data to show
1145 + tok = mystrsep(&url, "/?&");
1146 + if(tok && *tok) {
1147 + debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1148 +
1149 + // do we have such a data set?
1150 + RRDSET *st = rrdset_find_byname(tok);
1151 + if(!st) st = rrdset_find(tok);
1152 + if(!st) {
1153 + // we don't have it
1154 + // try to send a file with that name
1155 + buffer_flush(w->response.data);
1156 + code = mysendfile(w, tok);
1157 + }
1158 + else {
1159 + code = 200;
1160 + debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
1161 + w->response.data->contenttype = CT_APPLICATION_JSON;
1162 + buffer_flush(w->response.data);
1163 + rrd_stats_graph_json(st, url, w->response.data);
1164 + }
1165 + }
1166 + else {
1167 + code = 400;
1168 + buffer_flush(w->response.data);
1169 + buffer_strcat(w->response.data, "Graph name?\r\n");
1170 + }
1171 }
1142 - }
1172 #ifdef NETDATA_INTERNAL_CHECKS
1144 - else if(strcmp(tok, "debug") == 0) {
1145 - buffer_flush(w->response.data);
1173 + else if(strcmp(tok, "debug") == 0) {
1174 + buffer_flush(w->response.data);
1175
1147 - // get the name of the data to show
1148 - tok = mystrsep(&url, "/?&");
1149 - debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1150 -
1151 - // do we have such a data set?
1152 - RRDSET *st = rrdset_find_byname(tok);
1153 - if(!st) st = rrdset_find(tok);
1154 - if(!st) {
1155 - code = 404;
1156 - buffer_sprintf(w->response.data, "Chart %s is not found.\r\n", tok);
1157 - debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
1176 + // get the name of the data to show
1177 + tok = mystrsep(&url, "/?&");
1178 + if(tok && *tok) {
1179 + debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
1180 +
1181 + // do we have such a data set?
1182 + RRDSET *st = rrdset_find_byname(tok);
1183 + if(!st) st = rrdset_find(tok);
1184 + if(!st) {
1185 + code = 404;
1186 + buffer_sprintf(w->response.data, "Chart %s is not found.\r\n", tok);
1187 + debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
1188 + }
1189 + else {
1190 + code = 200;
1191 + debug_flags |= D_RRD_STATS;
1192 + st->debug = st->debug?0:1;
1193 + buffer_sprintf(w->response.data, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
1194 + debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, st->debug?"enabled":"disabled");
1195 + }
1196 + }
1197 + else {
1198 + code = 500;
1199 + buffer_flush(w->response.data);
1200 + buffer_strcat(w->response.data, "debug which chart?\r\n");
1201 + }
1202 }
1159 - else {
1203 + else if(strcmp(tok, "mirror") == 0) {
1204 code = 200;
1161 - debug_flags |= D_RRD_STATS;
1162 - st->debug = st->debug?0:1;
1163 - buffer_sprintf(w->response.data, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
1164 - debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, st->debug?"enabled":"disabled");
1165 - }
1166 - }
1167 - else if(strcmp(tok, "mirror") == 0) {
1168 - code = 200;
1205
1170 - debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id);
1206 + debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id);
1207
1172 - // replace the zero bytes with spaces
1173 - buffer_char_replace(w->response.data, '\0', ' ');
1208 + // replace the zero bytes with spaces
1209 + buffer_char_replace(w->response.data, '\0', ' ');
1210
1175 - // just leave the buffer as is
1176 - // it will be copied back to the client
1177 - }
1211 + // just leave the buffer as is
1212 + // it will be copied back to the client
1213 + }
1214 #endif
1179 - else if(strcmp(tok, "list") == 0) {
1180 - code = 200;
1215 + else if(strcmp(tok, "list") == 0) {
1216 + code = 200;
1217
1182 - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending list of RRD_STATS...", w->id);
1218 + debug(D_WEB_CLIENT_ACCESS, "%llu: Sending list of RRD_STATS...", w->id);
1219
1184 - buffer_flush(w->response.data);
1185 - RRDSET *st = rrdset_root;
1220 + buffer_flush(w->response.data);
1221 + RRDSET *st = rrdset_root;
1222
1187 - for ( ; st ; st = st->next )
1188 - buffer_sprintf(w->response.data, "%s\n", st->name);
1189 - }
1190 - else if(strcmp(tok, "all.json") == 0) {
1191 - code = 200;
1192 - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending JSON list of all monitors of RRD_STATS...", w->id);
1223 + for ( ; st ; st = st->next )
1224 + buffer_sprintf(w->response.data, "%s\n", st->name);
1225 + }
1226 + else if(strcmp(tok, "all.json") == 0) {
1227 + code = 200;
1228 + debug(D_WEB_CLIENT_ACCESS, "%llu: Sending JSON list of all monitors of RRD_STATS...", w->id);
1229
1194 - w->response.data->contenttype = CT_APPLICATION_JSON;
1195 - buffer_flush(w->response.data);
1196 - rrd_stats_all_json(w->response.data);
1197 - }
1198 - else if(strcmp(tok, "netdata.conf") == 0) {
1199 - code = 200;
1200 - debug(D_WEB_CLIENT_ACCESS, "%llu: Sending netdata.conf ...", w->id);
1230 + w->response.data->contenttype = CT_APPLICATION_JSON;
1231 + buffer_flush(w->response.data);
1232 + rrd_stats_all_json(w->response.data);
1233 + }
1234 + else if(strcmp(tok, "netdata.conf") == 0) {
1235 + code = 200;
1236 + debug(D_WEB_CLIENT_ACCESS, "%llu: Sending netdata.conf ...", w->id);
1237
1202 - w->response.data->contenttype = CT_TEXT_PLAIN;
1203 - buffer_flush(w->response.data);
1204 - generate_config(w->response.data, 0);
1238 + w->response.data->contenttype = CT_TEXT_PLAIN;
1239 + buffer_flush(w->response.data);
1240 + generate_config(w->response.data, 0);
1241 + }
1242 + else {
1243 + char filename[FILENAME_MAX+1];
1244 + url = filename;
1245 + strncpy(filename, w->last_url, FILENAME_MAX);
1246 + filename[FILENAME_MAX] = '\0';
1247 + tok = mystrsep(&url, "?");
1248 + buffer_flush(w->response.data);
1249 + code = mysendfile(w, (tok && *tok)?tok:"/");
1250 + }
1251 }
1252 else {
1253 char filename[FILENAME_MAX+1];
@@ -1224,7 +1270,10 @@ void web_client_process(struct web_client *w) {
1270 }
1271
1272 // free url_decode() buffer
1227 - if(pointer_to_free) free(pointer_to_free);
1273 + if(pointer_to_free) {
1274 + free(pointer_to_free);
1275 + pointer_to_free = NULL;
1276 + }
1277 }
1278 else if(w->response.data->len > TOO_BIG_REQUEST) {
1279 strcpy(w->last_url, "too big request");