diff options
author | Sergey Ponomarev <stokito@gmail.com> | 2020-08-16 14:58:31 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2020-08-16 14:58:31 +0200 |
commit | a949399d178f7b052ada2099c62621736eafce44 (patch) | |
tree | bc0fb58ad8a919de24b6633993b441cc2a14aa6b /networking/httpd.c | |
parent | 4864a685967bd098307a0d64293b5de1fc5f8210 (diff) | |
download | busybox-w32-a949399d178f7b052ada2099c62621736eafce44.tar.gz busybox-w32-a949399d178f7b052ada2099c62621736eafce44.tar.bz2 busybox-w32-a949399d178f7b052ada2099c62621736eafce44.zip |
httpd: Make Deny/Allow by IP config support optional
When disabled:
function old new delta
if_ip_denied_send_HTTP_FORBIDDEN_and_exit 52 - -52
handle_incoming_and_exit 2201 2097 -104
scan_ip 170 - -170
parse_conf 1365 1065 -300
------------------------------------------------------------------------------
(add/remove: 0/2 grow/shrink: 0/2 up/down: 0/-626) Total: -626 bytes
Signed-off-by: Sergey Ponomarev <stokito@gmail.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/httpd.c')
-rw-r--r-- | networking/httpd.c | 62 |
1 files changed, 44 insertions, 18 deletions
diff --git a/networking/httpd.c b/networking/httpd.c index 0297cf9ec..2946b2a54 100644 --- a/networking/httpd.c +++ b/networking/httpd.c | |||
@@ -245,6 +245,13 @@ | |||
245 | //config: help | 245 | //config: help |
246 | //config: RFC2616 says that server MUST add Date header to response. | 246 | //config: RFC2616 says that server MUST add Date header to response. |
247 | //config: But it is almost useless and can be omitted. | 247 | //config: But it is almost useless and can be omitted. |
248 | //config: | ||
249 | //config:config FEATURE_HTTPD_ACL_IP | ||
250 | //config: bool "ACL IP" | ||
251 | //config: default y | ||
252 | //config: depends on HTTPD | ||
253 | //config: help | ||
254 | //config: Support IP deny/allow rules | ||
248 | 255 | ||
249 | //applet:IF_HTTPD(APPLET(httpd, BB_DIR_USR_SBIN, BB_SUID_DROP)) | 256 | //applet:IF_HTTPD(APPLET(httpd, BB_DIR_USR_SBIN, BB_SUID_DROP)) |
250 | 257 | ||
@@ -314,6 +321,7 @@ typedef struct Htaccess { | |||
314 | char before_colon[1]; /* really bigger, must be last */ | 321 | char before_colon[1]; /* really bigger, must be last */ |
315 | } Htaccess; | 322 | } Htaccess; |
316 | 323 | ||
324 | #if ENABLE_FEATURE_HTTPD_ACL_IP | ||
317 | /* Must have "next" as a first member */ | 325 | /* Must have "next" as a first member */ |
318 | typedef struct Htaccess_IP { | 326 | typedef struct Htaccess_IP { |
319 | struct Htaccess_IP *next; | 327 | struct Htaccess_IP *next; |
@@ -321,6 +329,7 @@ typedef struct Htaccess_IP { | |||
321 | unsigned mask; | 329 | unsigned mask; |
322 | int allow_deny; | 330 | int allow_deny; |
323 | } Htaccess_IP; | 331 | } Htaccess_IP; |
332 | #endif | ||
324 | 333 | ||
325 | /* Must have "next" as a first member */ | 334 | /* Must have "next" as a first member */ |
326 | typedef struct Htaccess_Proxy { | 335 | typedef struct Htaccess_Proxy { |
@@ -449,7 +458,9 @@ struct globals { | |||
449 | 458 | ||
450 | const char *found_mime_type; | 459 | const char *found_mime_type; |
451 | const char *found_moved_temporarily; | 460 | const char *found_moved_temporarily; |
461 | #if ENABLE_FEATURE_HTTPD_ACL_IP | ||
452 | Htaccess_IP *ip_a_d; /* config allow/deny lines */ | 462 | Htaccess_IP *ip_a_d; /* config allow/deny lines */ |
463 | #endif | ||
453 | 464 | ||
454 | IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) | 465 | IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) |
455 | IF_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) | 466 | IF_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) |
@@ -499,7 +510,6 @@ struct globals { | |||
499 | #define found_mime_type (G.found_mime_type ) | 510 | #define found_mime_type (G.found_mime_type ) |
500 | #define found_moved_temporarily (G.found_moved_temporarily) | 511 | #define found_moved_temporarily (G.found_moved_temporarily) |
501 | #define last_mod (G.last_mod ) | 512 | #define last_mod (G.last_mod ) |
502 | #define ip_a_d (G.ip_a_d ) | ||
503 | #define g_realm (G.g_realm ) | 513 | #define g_realm (G.g_realm ) |
504 | #define remoteuser (G.remoteuser ) | 514 | #define remoteuser (G.remoteuser ) |
505 | #define file_size (G.file_size ) | 515 | #define file_size (G.file_size ) |
@@ -560,11 +570,14 @@ static ALWAYS_INLINE void free_Htaccess_list(Htaccess **pptr) | |||
560 | free_llist((has_next_ptr**)pptr); | 570 | free_llist((has_next_ptr**)pptr); |
561 | } | 571 | } |
562 | 572 | ||
573 | #if ENABLE_FEATURE_HTTPD_ACL_IP | ||
563 | static ALWAYS_INLINE void free_Htaccess_IP_list(Htaccess_IP **pptr) | 574 | static ALWAYS_INLINE void free_Htaccess_IP_list(Htaccess_IP **pptr) |
564 | { | 575 | { |
565 | free_llist((has_next_ptr**)pptr); | 576 | free_llist((has_next_ptr**)pptr); |
566 | } | 577 | } |
578 | #endif | ||
567 | 579 | ||
580 | #if ENABLE_FEATURE_HTTPD_ACL_IP | ||
568 | /* Returns presumed mask width in bits or < 0 on error. | 581 | /* Returns presumed mask width in bits or < 0 on error. |
569 | * Updates strp, stores IP at provided pointer */ | 582 | * Updates strp, stores IP at provided pointer */ |
570 | static int scan_ip(const char **strp, unsigned *ipp, unsigned char endc) | 583 | static int scan_ip(const char **strp, unsigned *ipp, unsigned char endc) |
@@ -649,6 +662,7 @@ static int scan_ip_mask(const char *str, unsigned *ipp, unsigned *maskp) | |||
649 | *maskp = (uint32_t)(~mask); | 662 | *maskp = (uint32_t)(~mask); |
650 | return 0; | 663 | return 0; |
651 | } | 664 | } |
665 | #endif | ||
652 | 666 | ||
653 | /* | 667 | /* |
654 | * Parse configuration file into in-memory linked list. | 668 | * Parse configuration file into in-memory linked list. |
@@ -678,7 +692,9 @@ static void parse_conf(const char *path, int flag) | |||
678 | char buf[160]; | 692 | char buf[160]; |
679 | 693 | ||
680 | /* discard old rules */ | 694 | /* discard old rules */ |
681 | free_Htaccess_IP_list(&ip_a_d); | 695 | #if ENABLE_FEATURE_HTTPD_ACL_IP |
696 | free_Htaccess_IP_list(&G.ip_a_d); | ||
697 | #endif | ||
682 | flg_deny_all = 0; | 698 | flg_deny_all = 0; |
683 | /* retain previous auth and mime config only for subdir parse */ | 699 | /* retain previous auth and mime config only for subdir parse */ |
684 | if (flag != SUBDIR_PARSE) { | 700 | if (flag != SUBDIR_PARSE) { |
@@ -783,6 +799,7 @@ static void parse_conf(const char *path, int flag) | |||
783 | continue; | 799 | continue; |
784 | } | 800 | } |
785 | 801 | ||
802 | #if ENABLE_FEATURE_HTTPD_ACL_IP | ||
786 | if (ch == 'A' || ch == 'D') { | 803 | if (ch == 'A' || ch == 'D') { |
787 | Htaccess_IP *pip; | 804 | Htaccess_IP *pip; |
788 | 805 | ||
@@ -804,13 +821,13 @@ static void parse_conf(const char *path, int flag) | |||
804 | pip->allow_deny = ch; | 821 | pip->allow_deny = ch; |
805 | if (ch == 'D') { | 822 | if (ch == 'D') { |
806 | /* Deny:from_IP - prepend */ | 823 | /* Deny:from_IP - prepend */ |
807 | pip->next = ip_a_d; | 824 | pip->next = G.ip_a_d; |
808 | ip_a_d = pip; | 825 | G.ip_a_d = pip; |
809 | } else { | 826 | } else { |
810 | /* A:from_IP - append (thus all D's precedes A's) */ | 827 | /* A:from_IP - append (thus all D's precedes A's) */ |
811 | Htaccess_IP *prev_IP = ip_a_d; | 828 | Htaccess_IP *prev_IP = G.ip_a_d; |
812 | if (prev_IP == NULL) { | 829 | if (prev_IP == NULL) { |
813 | ip_a_d = pip; | 830 | G.ip_a_d = pip; |
814 | } else { | 831 | } else { |
815 | while (prev_IP->next) | 832 | while (prev_IP->next) |
816 | prev_IP = prev_IP->next; | 833 | prev_IP = prev_IP->next; |
@@ -819,6 +836,7 @@ static void parse_conf(const char *path, int flag) | |||
819 | } | 836 | } |
820 | continue; | 837 | continue; |
821 | } | 838 | } |
839 | #endif | ||
822 | 840 | ||
823 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES | 841 | #if ENABLE_FEATURE_HTTPD_ERROR_PAGES |
824 | if (flag == FIRST_PARSE && ch == 'E') { | 842 | if (flag == FIRST_PARSE && ch == 'E') { |
@@ -1920,11 +1938,12 @@ static NOINLINE void send_file_and_exit(const char *url, int what) | |||
1920 | log_and_exit(); | 1938 | log_and_exit(); |
1921 | } | 1939 | } |
1922 | 1940 | ||
1941 | #if ENABLE_FEATURE_HTTPD_ACL_IP | ||
1923 | static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(unsigned remote_ip) | 1942 | static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(unsigned remote_ip) |
1924 | { | 1943 | { |
1925 | Htaccess_IP *cur; | 1944 | Htaccess_IP *cur; |
1926 | 1945 | ||
1927 | for (cur = ip_a_d; cur; cur = cur->next) { | 1946 | for (cur = G.ip_a_d; cur; cur = cur->next) { |
1928 | #if DEBUG | 1947 | #if DEBUG |
1929 | fprintf(stderr, | 1948 | fprintf(stderr, |
1930 | "checkPermIP: '%s' ? '%u.%u.%u.%u/%u.%u.%u.%u'\n", | 1949 | "checkPermIP: '%s' ? '%u.%u.%u.%u/%u.%u.%u.%u'\n", |
@@ -1949,6 +1968,9 @@ static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(unsigned remote_ip) | |||
1949 | if (flg_deny_all) /* depends on whether we saw "D:*" */ | 1968 | if (flg_deny_all) /* depends on whether we saw "D:*" */ |
1950 | send_headers_and_exit(HTTP_FORBIDDEN); | 1969 | send_headers_and_exit(HTTP_FORBIDDEN); |
1951 | } | 1970 | } |
1971 | #else | ||
1972 | # define if_ip_denied_send_HTTP_FORBIDDEN_and_exit(arg) ((void)0) | ||
1973 | #endif | ||
1952 | 1974 | ||
1953 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH | 1975 | #if ENABLE_FEATURE_HTTPD_BASIC_AUTH |
1954 | 1976 | ||
@@ -2184,7 +2206,9 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2184 | char *urlcopy; | 2206 | char *urlcopy; |
2185 | char *urlp; | 2207 | char *urlp; |
2186 | char *tptr; | 2208 | char *tptr; |
2209 | #if ENABLE_FEATURE_HTTPD_ACL_IP | ||
2187 | unsigned remote_ip; | 2210 | unsigned remote_ip; |
2211 | #endif | ||
2188 | #if ENABLE_FEATURE_HTTPD_CGI | 2212 | #if ENABLE_FEATURE_HTTPD_CGI |
2189 | unsigned total_headers_len; | 2213 | unsigned total_headers_len; |
2190 | #endif | 2214 | #endif |
@@ -2206,17 +2230,6 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2206 | * (IOW, server process doesn't need to waste 8k) */ | 2230 | * (IOW, server process doesn't need to waste 8k) */ |
2207 | iobuf = xmalloc(IOBUF_SIZE); | 2231 | iobuf = xmalloc(IOBUF_SIZE); |
2208 | 2232 | ||
2209 | remote_ip = 0; | ||
2210 | if (fromAddr->u.sa.sa_family == AF_INET) { | ||
2211 | remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr); | ||
2212 | } | ||
2213 | #if ENABLE_FEATURE_IPV6 | ||
2214 | if (fromAddr->u.sa.sa_family == AF_INET6 | ||
2215 | && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0 | ||
2216 | && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0 | ||
2217 | && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff) | ||
2218 | remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]); | ||
2219 | #endif | ||
2220 | if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) { | 2233 | if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) { |
2221 | /* NB: can be NULL (user runs httpd -i by hand?) */ | 2234 | /* NB: can be NULL (user runs httpd -i by hand?) */ |
2222 | rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr->u.sa); | 2235 | rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr->u.sa); |
@@ -2228,7 +2241,20 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) | |||
2228 | if (verbose > 2) | 2241 | if (verbose > 2) |
2229 | bb_simple_error_msg("connected"); | 2242 | bb_simple_error_msg("connected"); |
2230 | } | 2243 | } |
2244 | #if ENABLE_FEATURE_HTTPD_ACL_IP | ||
2245 | remote_ip = 0; | ||
2246 | if (fromAddr->u.sa.sa_family == AF_INET) { | ||
2247 | remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr); | ||
2248 | } | ||
2249 | # if ENABLE_FEATURE_IPV6 | ||
2250 | if (fromAddr->u.sa.sa_family == AF_INET6 | ||
2251 | && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0 | ||
2252 | && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0 | ||
2253 | && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff) | ||
2254 | remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]); | ||
2255 | # endif | ||
2231 | if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip); | 2256 | if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip); |
2257 | #endif | ||
2232 | 2258 | ||
2233 | /* Install timeout handler. get_line() needs it. */ | 2259 | /* Install timeout handler. get_line() needs it. */ |
2234 | signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit); | 2260 | signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit); |