143
debug(D_WEB_CLIENT, "%llu: Closing filecopy input file descriptor %d.", w->id, w->ifd);
144
145
if(web_server_mode != WEB_SERVER_MODE_STATIC_THREADED) {
146
- if (w->ifd != -1) close(w->ifd);
146
+ if (w->ifd != -1){
147
+ close(w->ifd);
148
+ }
149
}
150
151
w->ifd = w->ofd;
690
case 200:
691
return "OK";
692
693
+ case 301:
694
+ return "Moved Permanently";
695
+
696
case 307:
697
return "Temporary Redirect";
698
729
}
730
731
static inline char *http_header_parse(struct web_client *w, char *s, int parse_useragent) {
727
- static uint32_t hash_origin = 0, hash_connection = 0, hash_accept_encoding = 0, hash_donottrack = 0, hash_useragent = 0, hash_authorization = 0;
732
+ static uint32_t hash_origin = 0, hash_connection = 0, hash_donottrack = 0, hash_useragent = 0, hash_authorization = 0, hash_host = 0;
733
+#ifdef NETDATA_WITH_ZLIB
734
+ static uint32_t hash_accept_encoding = 0;
735
+#endif
736
737
if(unlikely(!hash_origin)) {
738
hash_origin = simple_uhash("Origin");
739
hash_connection = simple_uhash("Connection");
740
+#ifdef NETDATA_WITH_ZLIB
741
hash_accept_encoding = simple_uhash("Accept-Encoding");
742
+#endif
743
hash_donottrack = simple_uhash("DNT");
744
hash_useragent = simple_uhash("User-Agent");
745
hash_authorization = simple_uhash("X-Auth-Token");
746
+ hash_host = simple_uhash("Host");
747
}
748
749
char *e = s;
791
} else if(hash == hash_authorization&& !strcasecmp(s, "X-Auth-Token")) {
792
w->auth_bearer_token = strdupz(v);
793
}
794
+ else if(hash == hash_host && !strcasecmp(s, "Host")){
795
+ strncpyz(w->host, v, (ve - v));
796
+ }
797
#ifdef NETDATA_WITH_ZLIB
798
else if(hash == hash_accept_encoding && !strcasecmp(s, "Accept-Encoding")) {
799
if(web_enable_gzip) {
821
typedef enum {
822
HTTP_VALIDATION_OK,
823
HTTP_VALIDATION_NOT_SUPPORTED,
810
- HTTP_VALIDATION_INCOMPLETE
824
+ HTTP_VALIDATION_INCOMPLETE,
825
+ HTTP_VALIDATION_REDIRECT
826
} HTTP_VALIDATION;
827
828
static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
862
w->mode = WEB_CLIENT_MODE_OPTIONS;
863
}
864
else if(!strncmp(s, "STREAM ", 7)) {
865
+#ifdef ENABLE_HTTPS
866
+ if ( (w->ssl.flags) && (netdata_use_ssl_on_stream & NETDATA_SSL_FORCE)){
867
+ w->header_parse_tries = 0;
868
+ w->header_parse_last_size = 0;
869
+ web_client_disable_wait_receive(w);
870
+ char hostname[256];
871
+ char *copyme = strstr(s,"hostname=");
872
+ if ( copyme ){
873
+ copyme += 9;
874
+ char *end = strchr(copyme,'&');
875
+ if(end){
876
+ size_t length = end - copyme;
877
+ memcpy(hostname,copyme,length);
878
+ hostname[length] = 0X00;
879
+ }
880
+ else{
881
+ memcpy(hostname,"not available",13);
882
+ hostname[13] = 0x00;
883
+ }
884
+ }
885
+ else{
886
+ memcpy(hostname,"not available",13);
887
+ hostname[13] = 0x00;
888
+ }
889
+ error("The server is configured to always use encrypt connection, please enable the SSL on slave with hostname '%s'.",hostname);
890
+ return HTTP_VALIDATION_NOT_SUPPORTED;
891
+ }
892
+#endif
893
+
894
encoded_url = s = &s[7];
895
w->mode = WEB_CLIENT_MODE_STREAM;
896
}
943
// copy the URL - we are going to overwrite parts of it
944
// TODO -- ideally we we should avoid copying buffers around
945
strncpyz(w->last_url, w->decoded_url, NETDATA_WEB_REQUEST_URL_SIZE);
946
+#ifdef ENABLE_HTTPS
947
+ if ( (!web_client_check_unix(w)) && (netdata_srv_ctx) ) {
948
+ if ((w->ssl.conn) && ((w->ssl.flags & NETDATA_SSL_NO_HANDSHAKE) && (netdata_use_ssl_on_http & NETDATA_SSL_FORCE) && (w->mode != WEB_CLIENT_MODE_STREAM)) ) {
949
+ w->header_parse_tries = 0;
950
+ w->header_parse_last_size = 0;
951
+ web_client_disable_wait_receive(w);
952
+ return HTTP_VALIDATION_REDIRECT;
953
+ }
954
+ }
955
+#endif
956
957
w->header_parse_tries = 0;
958
w->header_parse_last_size = 0;
972
return HTTP_VALIDATION_INCOMPLETE;
973
}
974
975
+static inline ssize_t web_client_send_data(struct web_client *w,const void *buf,size_t len, int flags)
976
+{
977
+ ssize_t bytes;
978
+#ifdef ENABLE_HTTPS
979
+ if ( (!web_client_check_unix(w)) && (netdata_srv_ctx) ) {
980
+ if ( ( w->ssl.conn ) && ( !w->ssl.flags ) ){
981
+ bytes = SSL_write(w->ssl.conn,buf, len) ;
982
+ } else {
983
+ bytes = send(w->ofd,buf, len , flags);
984
+ }
985
+ } else {
986
+ bytes = send(w->ofd,buf, len , flags);
987
+ }
988
+#else
989
+ bytes = send(w->ofd, buf, len, flags);
990
+#endif
991
+
992
+ return bytes;
993
+}
994
+
995
static inline void web_client_send_http_header(struct web_client *w) {
996
if(unlikely(w->response.code != 200))
997
buffer_no_cacheable(w->response.data);
1022
strftime(edate, sizeof(edate), "%a, %d %b %Y %H:%M:%S %Z", tm);
1023
}
1024
1025
+ char headerbegin[8328];
1026
+ if (w->response.code == 301) {
1027
+ memcpy(headerbegin,"\r\nLocation: https://",20);
1028
+ size_t headerlength = strlen(w->host);
1029
+ memcpy(&headerbegin[20],w->host,headerlength);
1030
+ headerlength += 20;
1031
+ size_t tmp = strlen(w->last_url);
1032
+ memcpy(&headerbegin[headerlength],w->last_url,tmp);
1033
+ headerlength += tmp;
1034
+ memcpy(&headerbegin[headerlength],"\r\n",2);
1035
+ headerlength += 2;
1036
+ headerbegin[headerlength] = 0x00;
1037
+ }else {
1038
+ memcpy(headerbegin,"\r\n",2);
1039
+ headerbegin[2]=0x00;
1040
+ }
1041
+
1042
buffer_sprintf(w->response.header_output,
1043
"HTTP/1.1 %d %s\r\n"
1044
"Connection: %s\r\n"
1046
"Access-Control-Allow-Origin: %s\r\n"
1047
"Access-Control-Allow-Credentials: true\r\n"
1048
"Content-Type: %s\r\n"
958
- "Date: %s\r\n"
1049
+ "Date: %s%s"
1050
, w->response.code, code_msg
1051
, web_client_has_keepalive(w)?"keep-alive":"close"
1052
, VERSION
1053
, w->origin
1054
, content_type_string
1055
, date
1056
+ , headerbegin
1057
);
1058
1059
if(unlikely(web_x_frame_options))
1138
1139
size_t count = 0;
1140
ssize_t bytes;
1141
+#ifdef ENABLE_HTTPS
1142
+ if ( (!web_client_check_unix(w)) && (netdata_srv_ctx) ) {
1143
+ if ( ( w->ssl.conn ) && ( !w->ssl.flags ) ){
1144
+ while((bytes = SSL_write(w->ssl.conn, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output))) < 0) {
1145
+ count++;
1146
+ if(count > 100 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
1147
+ error("Cannot send HTTP headers to web client.");
1148
+ break;
1149
+ }
1150
+ }
1151
+ } else {
1152
+ while((bytes = send(w->ofd, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output), 0)) == -1) {
1153
+ count++;
1154
+
1155
+ if(count > 100 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
1156
+ error("Cannot send HTTP headers to web client.");
1157
+ break;
1158
+ }
1159
+ }
1160
+ }
1161
+ } else {
1162
+ while((bytes = send(w->ofd, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output), 0)) == -1) {
1163
+ count++;
1164
+
1165
+ if(count > 100 || (errno != EAGAIN && errno != EWOULDBLOCK)) {
1166
+ error("Cannot send HTTP headers to web client.");
1167
+ break;
1168
+ }
1169
+ }
1170
+ }
1171
+#else
1172
while((bytes = send(w->ofd, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output), 0)) == -1) {
1173
count++;
1174
1177
break;
1178
}
1179
}
1180
+#endif
1181
1182
if(bytes != (ssize_t) buffer_strlen(w->response.header_output)) {
1183
if(bytes > 0)
1427
return;
1428
}
1429
break;
1306
-
1430
+#ifdef ENABLE_HTTPS
1431
+ case HTTP_VALIDATION_REDIRECT:
1432
+ {
1433
+ buffer_flush(w->response.data);
1434
+ w->response.data->contenttype = CT_TEXT_HTML;
1435
+ buffer_strcat(w->response.data, "<!DOCTYPE html><!-- SPDX-License-Identifier: GPL-3.0-or-later --><html><body onload=\"window.location.href ='https://'+ window.location.hostname + ':' + window.location.port + window.location.pathname\">Redirecting to safety connection, case your browser does not support redirection, please click <a onclick=\"window.location.href ='https://'+ window.location.hostname + ':' + window.location.port + window.location.pathname\">here</a>.</body></html>");
1436
+ w->response.code = 301;
1437
+ break;
1438
+ }
1439
+#endif
1440
case HTTP_VALIDATION_NOT_SUPPORTED:
1441
debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, w->response.data->buffer);
1442
1506
{
1507
debug(D_DEFLATE, "%llu: OPEN CHUNK of %zu bytes (hex: %zx).", w->id, len, len);
1508
char buf[24];
1376
- sprintf(buf, "%zX\r\n", len);
1377
-
1378
- ssize_t bytes = send(w->ofd, buf, strlen(buf), 0);
1509
+ ssize_t bytes;
1510
+ bytes = (ssize_t)sprintf(buf, "%zX\r\n", len);
1511
+ buf[bytes] = 0x00;
1512
+
1513
+ bytes = web_client_send_data(w,buf,strlen(buf),0);
1514
if(bytes > 0) {
1515
debug(D_DEFLATE, "%llu: Sent chunk header %zd bytes.", w->id, bytes);
1516
w->stats_sent_bytes += bytes;
1532
{
1533
//debug(D_DEFLATE, "%llu: CLOSE CHUNK.", w->id);
1534
1400
- ssize_t bytes = send(w->ofd, "\r\n", 2, 0);
1535
+ ssize_t bytes;
1536
+ bytes = web_client_send_data(w,"\r\n",2,0);
1537
if(bytes > 0) {
1538
debug(D_DEFLATE, "%llu: Sent chunk suffix %zd bytes.", w->id, bytes);
1539
w->stats_sent_bytes += bytes;
1555
{
1556
//debug(D_DEFLATE, "%llu: FINALIZE CHUNK.", w->id);
1557
1422
- ssize_t bytes = send(w->ofd, "\r\n0\r\n\r\n", 7, 0);
1558
+ ssize_t bytes;
1559
+ bytes = web_client_send_data(w,"\r\n0\r\n\r\n",7,0);
1560
if(bytes > 0) {
1561
debug(D_DEFLATE, "%llu: Sent chunk suffix %zd bytes.", w->id, bytes);
1562
w->stats_sent_bytes += bytes;
1670
1671
debug(D_WEB_CLIENT, "%llu: Sending %zu bytes of data (+%zd of chunk header).", w->id, w->response.zhave - w->response.zsent, t);
1672
1536
- len = send(w->ofd, &w->response.zbuffer[w->response.zsent], (size_t) (w->response.zhave - w->response.zsent), MSG_DONTWAIT);
1673
+ len = web_client_send_data(w,&w->response.zbuffer[w->response.zsent], (size_t) (w->response.zhave - w->response.zsent), MSG_DONTWAIT);
1674
if(len > 0) {
1675
w->stats_sent_bytes += len;
1676
w->response.zsent += len;
1726
return 0;
1727
}
1728
1592
- bytes = send(w->ofd, &w->response.data->buffer[w->response.sent], w->response.data->len - w->response.sent, MSG_DONTWAIT);
1729
+ bytes = web_client_send_data(w,&w->response.data->buffer[w->response.sent], w->response.data->len - w->response.sent, MSG_DONTWAIT);
1730
if(likely(bytes > 0)) {
1731
w->stats_sent_bytes += bytes;
1732
w->response.sent += bytes;
1801
if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY))
1802
return web_client_read_file(w);
1803
1804
+ ssize_t bytes;
1805
+ ssize_t left = w->response.data->size - w->response.data->len;
1806
+
1807
// do we have any space for more data?
1808
buffer_need_bytes(w->response.data, NETDATA_WEB_REQUEST_RECEIVE_SIZE);
1809
1670
- ssize_t left = w->response.data->size - w->response.data->len;
1671
- ssize_t bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT);
1810
+#ifdef ENABLE_HTTPS
1811
+ if ( (!web_client_check_unix(w)) && (netdata_srv_ctx) ) {
1812
+ if ( ( w->ssl.conn ) && (!w->ssl.flags)) {
1813
+ bytes = SSL_read(w->ssl.conn, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1));
1814
+ }else {
1815
+ bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT);
1816
+ }
1817
+ }
1818
+ else{
1819
+ bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT);
1820
+ }
1821
+#else
1822
+ bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT);
1823
+#endif
1824
1825
if(likely(bytes > 0)) {
1826
w->stats_received_bytes += bytes;