From a949399d178f7b052ada2099c62621736eafce44 Mon Sep 17 00:00:00 2001 From: Sergey Ponomarev Date: Sun, 16 Aug 2020 14:58:31 +0200 Subject: [PATCH] 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 Signed-off-by: Denys Vlasenko --- networking/httpd.c | 62 ++++++++++++++++++++++++++++++++-------------- 1 file 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 @@ //config: help //config: RFC2616 says that server MUST add Date header to response. //config: But it is almost useless and can be omitted. +//config: +//config:config FEATURE_HTTPD_ACL_IP +//config: bool "ACL IP" +//config: default y +//config: depends on HTTPD +//config: help +//config: Support IP deny/allow rules //applet:IF_HTTPD(APPLET(httpd, BB_DIR_USR_SBIN, BB_SUID_DROP)) @@ -314,6 +321,7 @@ typedef struct Htaccess { char before_colon[1]; /* really bigger, must be last */ } Htaccess; +#if ENABLE_FEATURE_HTTPD_ACL_IP /* Must have "next" as a first member */ typedef struct Htaccess_IP { struct Htaccess_IP *next; @@ -321,6 +329,7 @@ typedef struct Htaccess_IP { unsigned mask; int allow_deny; } Htaccess_IP; +#endif /* Must have "next" as a first member */ typedef struct Htaccess_Proxy { @@ -449,7 +458,9 @@ struct globals { const char *found_mime_type; const char *found_moved_temporarily; +#if ENABLE_FEATURE_HTTPD_ACL_IP Htaccess_IP *ip_a_d; /* config allow/deny lines */ +#endif IF_FEATURE_HTTPD_BASIC_AUTH(const char *g_realm;) IF_FEATURE_HTTPD_BASIC_AUTH(char *remoteuser;) @@ -499,7 +510,6 @@ struct globals { #define found_mime_type (G.found_mime_type ) #define found_moved_temporarily (G.found_moved_temporarily) #define last_mod (G.last_mod ) -#define ip_a_d (G.ip_a_d ) #define g_realm (G.g_realm ) #define remoteuser (G.remoteuser ) #define file_size (G.file_size ) @@ -560,11 +570,14 @@ static ALWAYS_INLINE void free_Htaccess_list(Htaccess **pptr) free_llist((has_next_ptr**)pptr); } +#if ENABLE_FEATURE_HTTPD_ACL_IP static ALWAYS_INLINE void free_Htaccess_IP_list(Htaccess_IP **pptr) { free_llist((has_next_ptr**)pptr); } +#endif +#if ENABLE_FEATURE_HTTPD_ACL_IP /* Returns presumed mask width in bits or < 0 on error. * Updates strp, stores IP at provided pointer */ 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) *maskp = (uint32_t)(~mask); return 0; } +#endif /* * Parse configuration file into in-memory linked list. @@ -678,7 +692,9 @@ static void parse_conf(const char *path, int flag) char buf[160]; /* discard old rules */ - free_Htaccess_IP_list(&ip_a_d); +#if ENABLE_FEATURE_HTTPD_ACL_IP + free_Htaccess_IP_list(&G.ip_a_d); +#endif flg_deny_all = 0; /* retain previous auth and mime config only for subdir parse */ if (flag != SUBDIR_PARSE) { @@ -783,6 +799,7 @@ static void parse_conf(const char *path, int flag) continue; } +#if ENABLE_FEATURE_HTTPD_ACL_IP if (ch == 'A' || ch == 'D') { Htaccess_IP *pip; @@ -804,13 +821,13 @@ static void parse_conf(const char *path, int flag) pip->allow_deny = ch; if (ch == 'D') { /* Deny:from_IP - prepend */ - pip->next = ip_a_d; - ip_a_d = pip; + pip->next = G.ip_a_d; + G.ip_a_d = pip; } else { /* A:from_IP - append (thus all D's precedes A's) */ - Htaccess_IP *prev_IP = ip_a_d; + Htaccess_IP *prev_IP = G.ip_a_d; if (prev_IP == NULL) { - ip_a_d = pip; + G.ip_a_d = pip; } else { while (prev_IP->next) prev_IP = prev_IP->next; @@ -819,6 +836,7 @@ static void parse_conf(const char *path, int flag) } continue; } +#endif #if ENABLE_FEATURE_HTTPD_ERROR_PAGES if (flag == FIRST_PARSE && ch == 'E') { @@ -1920,11 +1938,12 @@ static NOINLINE void send_file_and_exit(const char *url, int what) log_and_exit(); } +#if ENABLE_FEATURE_HTTPD_ACL_IP static void if_ip_denied_send_HTTP_FORBIDDEN_and_exit(unsigned remote_ip) { Htaccess_IP *cur; - for (cur = ip_a_d; cur; cur = cur->next) { + for (cur = G.ip_a_d; cur; cur = cur->next) { #if DEBUG fprintf(stderr, "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) if (flg_deny_all) /* depends on whether we saw "D:*" */ send_headers_and_exit(HTTP_FORBIDDEN); } +#else +# define if_ip_denied_send_HTTP_FORBIDDEN_and_exit(arg) ((void)0) +#endif #if ENABLE_FEATURE_HTTPD_BASIC_AUTH @@ -2184,7 +2206,9 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) char *urlcopy; char *urlp; char *tptr; +#if ENABLE_FEATURE_HTTPD_ACL_IP unsigned remote_ip; +#endif #if ENABLE_FEATURE_HTTPD_CGI unsigned total_headers_len; #endif @@ -2206,17 +2230,6 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) * (IOW, server process doesn't need to waste 8k) */ iobuf = xmalloc(IOBUF_SIZE); - remote_ip = 0; - if (fromAddr->u.sa.sa_family == AF_INET) { - remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr); - } -#if ENABLE_FEATURE_IPV6 - if (fromAddr->u.sa.sa_family == AF_INET6 - && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0 - && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0 - && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff) - remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]); -#endif if (ENABLE_FEATURE_HTTPD_CGI || DEBUG || verbose) { /* NB: can be NULL (user runs httpd -i by hand?) */ rmt_ip_str = xmalloc_sockaddr2dotted(&fromAddr->u.sa); @@ -2228,7 +2241,20 @@ static void handle_incoming_and_exit(const len_and_sockaddr *fromAddr) if (verbose > 2) bb_simple_error_msg("connected"); } +#if ENABLE_FEATURE_HTTPD_ACL_IP + remote_ip = 0; + if (fromAddr->u.sa.sa_family == AF_INET) { + remote_ip = ntohl(fromAddr->u.sin.sin_addr.s_addr); + } +# if ENABLE_FEATURE_IPV6 + if (fromAddr->u.sa.sa_family == AF_INET6 + && fromAddr->u.sin6.sin6_addr.s6_addr32[0] == 0 + && fromAddr->u.sin6.sin6_addr.s6_addr32[1] == 0 + && ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[2]) == 0xffff) + remote_ip = ntohl(fromAddr->u.sin6.sin6_addr.s6_addr32[3]); +# endif if_ip_denied_send_HTTP_FORBIDDEN_and_exit(remote_ip); +#endif /* Install timeout handler. get_line() needs it. */ signal(SIGALRM, send_REQUEST_TIMEOUT_and_exit);