diff -u a/httpd.c b/httpd.c --- a/httpd.c 2020-04-23 12:22:52.163327518 +0200 +++ b/httpd.c 2020-04-23 16:15:53.854185917 +0200 @@ -311,6 +311,12 @@ static err_t http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri, u8_t tag_check, char *params); static err_t http_poll(void *arg, struct altcp_pcb *pcb); static u8_t http_check_eof(struct altcp_pcb *pcb, struct http_state *hs); + +#if LWIP_HTTPD_BASIC_AUTH == 1 +/* must be provided externally */ +char http_basic_credentials_ok(char* credentials, int len); +#endif /* LWIP_HTTPD_BASIC_AUTH */ + #if LWIP_HTTPD_FS_ASYNC_READ static void http_continue(void *connection); #endif /* LWIP_HTTPD_FS_ASYNC_READ */ @@ -874,12 +880,18 @@ special case. We assume that any filename with "404" in it must be indicative of a 404 server error whereas all other files require the 200 OK header. */ - if (strstr(uri, "404.") == uri) { + if (strstr(uri, "/404.") == uri) { /* see https://savannah.nongnu.org/bugs/?58223 */ hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_FOUND]; - } else if (strstr(uri, "400.") == uri) { + } else if (strstr(uri, "/400.") == uri) { hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_BAD_REQUEST]; - } else if (strstr(uri, "501.") == uri) { + } else if (strstr(uri, "/501.") == uri) { hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_NOT_IMPL]; +#if LWIP_HTTPD_BASIC_AUTH == 1 + } else if (strstr(uri, "/401.") == uri) { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = "HTTP/1.0 401 Unauthorized\r\nWWW-Authenticate: Basic realm=\"Access to site\"\r\n"; /* 1.0 or 1.1? */ + } else if (strstr(uri, "/403.") == uri) { + hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = "HTTP/1.0 403 Forbidden\r\n"; /* 1.0 or 1.1? */ +#endif /* LWIP_HTTPD_BASIC_AUTH */ } else { hs->hdrs[HDR_STRINGS_IDX_HTTP_STATUS] = g_psHTTPHeaderStrings[HTTP_HDR_OK]; } @@ -1655,12 +1667,27 @@ uri1 = "/501.html"; uri2 = "/501.htm"; uri3 = "/501.shtml"; +#if LWIP_HTTPD_BASIC_AUTH == 1 + } else if (error_nr == 401) { + uri1 = "/401.html"; + uri2 = "/401.htm"; + uri3 = "/401.shtml"; + } else if (error_nr == 403) { + uri1 = "/403.html"; + uri2 = "/403.htm"; + uri3 = "/403.shtml"; + } else if (error_nr == 404) { + uri1 = "/404.html"; + uri2 = "/404.htm"; + uri3 = "/404.shtml"; +#endif /* LWIP_HTTPD_BASIC_AUTH */ } else { /* 400 (bad request is the default) */ uri1 = "/400.html"; uri2 = "/400.htm"; uri3 = "/400.shtml"; } + if (fs_open(&hs->file_handle, uri1) == ERR_OK) { uri = uri1; } else if (fs_open(&hs->file_handle, uri2) == ERR_OK) { @@ -2084,7 +2111,25 @@ } else { hs->keepalive = 0; } -#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ +#endif /* LWIP_HTTPD_SUPPORT_11_KEEPALIVE */ +#if LWIP_HTTPD_BASIC_AUTH == 1 + char* authorization_header = lwip_strnstr(data, CRLF "Authorization: Basic ", data_len); + if(authorization_header == NULL) + { + /* Header is missing -> HTTP status code 401 */ + return http_find_error_file(hs, 401); + } + /* skips CRLF */ + authorization_header+=2; + char* credentials = &authorization_header[strlen("Authorization: Basic ")]; + int credentials_left_len = (u16_t)(data_len - ((credentials + 1) - data)); + char* credentials_end = lwip_strnstr(credentials + 1, CRLF, credentials_left_len); + if(!http_basic_credentials_ok(credentials,credentials_end-credentials)) + { + /* wrong credentials, returns 401 in order to give another chance */ + return http_find_error_file(hs, 401); + } +#endif /* LWIP_HTTPD_BASIC_AUTH */ /* null-terminate the METHOD (pbuf is freed anyway wen returning) */ *sp1 = 0; uri[uri_len] = 0;