From 11aee50eef2478aca06eef10045a01a53d6e9b94 Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 18 May 2017 12:32:05 +0300 Subject: [PATCH] sample: net: http: Add Basic auth support to server sample Basic auth support was missing from HTTP server sample. Signed-off-by: Jukka Rissanen --- samples/net/http_server/README.rst | 22 ++++++++- samples/net/http_server/src/config.h | 8 ++++ samples/net/http_server/src/main.c | 70 ++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/samples/net/http_server/README.rst b/samples/net/http_server/README.rst index 66ba16a1861..adb5416ee03 100644 --- a/samples/net/http_server/README.rst +++ b/samples/net/http_server/README.rst @@ -217,6 +217,27 @@ and this is the HTML message that wget will save:

404 Not Found

+To test the HTTP Basic Authentication functionality, use the +following command: + +.. code-block:: console + + wget 192.168.1.120/auth -O index.html --user=zephyr --password=0123456789 + +the :file:`index.html` file will contain the following information: + +.. code-block:: html + + + + Zephyr HTTP Server + + +

Zephyr HTTP server

+

user: zephyr, password: 0123456789

+ + + HTTPS Server ============ @@ -274,4 +295,3 @@ Known Issues and Limitations - Currently, this sample application only generates HTTP responses in chunk transfer mode. -- Basic authentication is not yet implemented. diff --git a/samples/net/http_server/src/config.h b/samples/net/http_server/src/config.h index 475ed0221bc..348fc87f7bd 100644 --- a/samples/net/http_server/src/config.h +++ b/samples/net/http_server/src/config.h @@ -30,4 +30,12 @@ #define ZEPHYR_PORT 8080 #endif +#define HTTP_AUTH_URL "/auth" +#define HTTP_AUTH_TYPE "Basic" + +/* HTTP Basic Auth, see https://tools.ietf.org/html/rfc7617 */ +#define HTTP_AUTH_REALM "Zephyr" +#define HTTP_AUTH_USERNAME "zephyr" +#define HTTP_AUTH_PASSWORD "0123456789" + #endif diff --git a/samples/net/http_server/src/main.c b/samples/net/http_server/src/main.c index 28e091cc233..8ca74ff5d51 100644 --- a/samples/net/http_server/src/main.c +++ b/samples/net/http_server/src/main.c @@ -17,6 +17,11 @@ #include #include +/* For Basic auth, we need base64 decoder which can be found + * in mbedtls library. + */ +#include + #include #include @@ -77,6 +82,10 @@ void panic(const char *msg) "Transfer-Encoding: chunked\r\n" \ "\r\n" +#define HTTP_401_STATUS_US "HTTP/1.1 401 Unauthorized status\r\n" \ + "WWW-Authenticate: Basic realm=" \ + "\""HTTP_AUTH_REALM"\"\r\n\r\n" + #define HTML_HEADER "" \ "Zephyr HTTP Server" \ "

" \ @@ -167,6 +176,65 @@ static int http_response_soft_404(struct http_server_ctx *ctx) HTML_FOOTER); } +static int http_response_auth(struct http_server_ctx *ctx) +{ + return http_response(ctx, HTTP_STATUS_200_OK, HTML_HEADER + "

user: "HTTP_AUTH_USERNAME + ", password: "HTTP_AUTH_PASSWORD + "

" HTML_FOOTER); +} + +int http_response_401(struct http_server_ctx *ctx, s32_t timeout) +{ + return http_response_wait(ctx, HTTP_401_STATUS_US, NULL, timeout); +} + +static int http_basic_auth(struct http_server_ctx *ctx) +{ + const char auth_str[] = HTTP_CRLF "Authorization: Basic "; + char *ptr; + + ptr = strstr(ctx->req.field_values[0].key, auth_str); + if (ptr) { + char output[sizeof(HTTP_AUTH_USERNAME) + + sizeof(":") + + sizeof(HTTP_AUTH_PASSWORD)]; + size_t olen, ilen, alen; + char *end, *colon; + int ret; + + memset(output, 0, sizeof(output)); + + end = strstr(ptr + 2, HTTP_CRLF); + if (!end) { + return http_response_401(ctx, K_NO_WAIT); + } + + alen = sizeof(auth_str) - 1; + ilen = end - (ptr + alen); + + ret = mbedtls_base64_decode(output, sizeof(output) - 1, + &olen, ptr + alen, ilen); + if (ret) { + return http_response_401(ctx, K_NO_WAIT); + } + + colon = memchr(output, ':', olen); + + if (colon && colon > output && colon < (output + olen) && + memcmp(output, HTTP_AUTH_USERNAME, colon - output) == 0 && + memcmp(colon + 1, HTTP_AUTH_PASSWORD, + output + olen - colon) == 0) { + return http_response_auth(ctx); + } + + return http_response_401(ctx, K_NO_WAIT); + } + + /* Wait 2 secs for the reply with proper credentials */ + return http_response_401(ctx, K_SECONDS(2)); +} + #if defined(CONFIG_HTTPS) /* Load the certificates and private RSA key. */ @@ -271,6 +339,8 @@ void main(void) #endif http_server_add_default(&http_urls, http_response_soft_404); + http_server_add_url(&http_urls, HTTP_AUTH_URL, HTTP_URL_STANDARD, + http_basic_auth); http_server_add_url(&http_urls, "/headers", HTTP_URL_STANDARD, http_response_header_fields); http_server_add_url(&http_urls, "/index.html", HTTP_URL_STANDARD,