web_server.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #define WEB_SERVER_INTERNALS 1
  3. #include "web_server.h"
  4. WEB_SERVER_MODE web_server_mode = WEB_SERVER_MODE_STATIC_THREADED;
  5. // --------------------------------------------------------------------------------------
  6. WEB_SERVER_MODE web_server_mode_id(const char *mode) {
  7. if(!strcmp(mode, "none"))
  8. return WEB_SERVER_MODE_NONE;
  9. else
  10. return WEB_SERVER_MODE_STATIC_THREADED;
  11. }
  12. const char *web_server_mode_name(WEB_SERVER_MODE id) {
  13. switch(id) {
  14. case WEB_SERVER_MODE_NONE:
  15. return "none";
  16. default:
  17. case WEB_SERVER_MODE_STATIC_THREADED:
  18. return "static-threaded";
  19. }
  20. }
  21. // --------------------------------------------------------------------------------------
  22. // API sockets
  23. LISTEN_SOCKETS api_sockets = {
  24. .config = &netdata_config,
  25. .config_section = CONFIG_SECTION_WEB,
  26. .default_bind_to = "*",
  27. .default_port = API_LISTEN_PORT,
  28. .backlog = API_LISTEN_BACKLOG
  29. };
  30. void debug_sockets() {
  31. BUFFER *wb = buffer_create(256 * sizeof(char), NULL);
  32. int i;
  33. for(i = 0 ; i < (int)api_sockets.opened ; i++) {
  34. buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_NOCHECK)?"NONE ":"");
  35. buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_DASHBOARD)?"dashboard ":"");
  36. buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_REGISTRY)?"registry ":"");
  37. buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_BADGE)?"badges ":"");
  38. buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_MGMT)?"management ":"");
  39. buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_STREAMING)?"streaming ":"");
  40. buffer_strcat(wb, (api_sockets.fds_acl_flags[i] & WEB_CLIENT_ACL_NETDATACONF)?"netdata.conf ":"");
  41. debug(D_WEB_CLIENT, "Socket fd %d name '%s' acl_flags: %s",
  42. i,
  43. api_sockets.fds_names[i],
  44. buffer_tostring(wb));
  45. buffer_reset(wb);
  46. }
  47. buffer_free(wb);
  48. }
  49. void api_listen_sockets_setup(void) {
  50. int socks = listen_sockets_setup(&api_sockets);
  51. if(!socks)
  52. fatal("LISTENER: Cannot listen on any API socket. Exiting...");
  53. if(unlikely(debug_flags & D_WEB_CLIENT))
  54. debug_sockets();
  55. return;
  56. }
  57. // --------------------------------------------------------------------------------------
  58. // access lists
  59. SIMPLE_PATTERN *web_allow_connections_from = NULL;
  60. int web_allow_connections_dns;
  61. // WEB_CLIENT_ACL
  62. SIMPLE_PATTERN *web_allow_dashboard_from = NULL;
  63. int web_allow_dashboard_dns;
  64. SIMPLE_PATTERN *web_allow_registry_from = NULL;
  65. int web_allow_registry_dns;
  66. SIMPLE_PATTERN *web_allow_badges_from = NULL;
  67. int web_allow_badges_dns;
  68. SIMPLE_PATTERN *web_allow_mgmt_from = NULL;
  69. int web_allow_mgmt_dns;
  70. SIMPLE_PATTERN *web_allow_streaming_from = NULL;
  71. int web_allow_streaming_dns;
  72. SIMPLE_PATTERN *web_allow_netdataconf_from = NULL;
  73. int web_allow_netdataconf_dns;
  74. void web_client_update_acl_matches(struct web_client *w) {
  75. w->acl = WEB_CLIENT_ACL_NONE;
  76. if (!web_allow_dashboard_from ||
  77. connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
  78. web_allow_dashboard_from, "dashboard", web_allow_dashboard_dns))
  79. w->acl |= WEB_CLIENT_ACL_DASHBOARD;
  80. if (!web_allow_registry_from ||
  81. connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
  82. web_allow_registry_from, "registry", web_allow_registry_dns))
  83. w->acl |= WEB_CLIENT_ACL_REGISTRY;
  84. if (!web_allow_badges_from ||
  85. connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
  86. web_allow_badges_from, "badges", web_allow_badges_dns))
  87. w->acl |= WEB_CLIENT_ACL_BADGE;
  88. if (!web_allow_mgmt_from ||
  89. connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
  90. web_allow_mgmt_from, "management", web_allow_mgmt_dns))
  91. w->acl |= WEB_CLIENT_ACL_MGMT;
  92. if (!web_allow_streaming_from ||
  93. connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
  94. web_allow_streaming_from, "streaming", web_allow_streaming_dns))
  95. w->acl |= WEB_CLIENT_ACL_STREAMING;
  96. if (!web_allow_netdataconf_from ||
  97. connection_allowed(w->ifd, w->client_ip, w->client_host, sizeof(w->client_host),
  98. web_allow_netdataconf_from, "netdata.conf", web_allow_netdataconf_dns))
  99. w->acl |= WEB_CLIENT_ACL_NETDATACONF;
  100. w->acl &= w->port_acl;
  101. }
  102. // --------------------------------------------------------------------------------------
  103. void web_server_log_connection(struct web_client *w, const char *msg) {
  104. log_access("%llu: %d '[%s]:%s' '%s'", w->id, gettid(), w->client_ip, w->client_port, msg);
  105. }
  106. // --------------------------------------------------------------------------------------
  107. void web_client_initialize_connection(struct web_client *w) {
  108. int flag = 1;
  109. if(unlikely(web_client_check_tcp(w) && setsockopt(w->ifd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0))
  110. debug(D_WEB_CLIENT, "%llu: failed to enable TCP_NODELAY on socket fd %d.", w->id, w->ifd);
  111. flag = 1;
  112. if(unlikely(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0))
  113. debug(D_WEB_CLIENT, "%llu: failed to enable SO_KEEPALIVE on socket fd %d.", w->id, w->ifd);
  114. web_client_update_acl_matches(w);
  115. w->origin[0] = '*'; w->origin[1] = '\0';
  116. w->cookie1[0] = '\0'; w->cookie2[0] = '\0';
  117. freez(w->user_agent); w->user_agent = NULL;
  118. web_client_enable_wait_receive(w);
  119. web_server_log_connection(w, "CONNECTED");
  120. web_client_cache_verify(0);
  121. }