]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: server: Added support for authentication.
authorStephan Bosch <stephan@rename-it.nl>
Wed, 10 Sep 2014 10:39:37 +0000 (13:39 +0300)
committerStephan Bosch <stephan@rename-it.nl>
Wed, 10 Sep 2014 10:39:37 +0000 (13:39 +0300)
src/lib-http/http-server-private.h
src/lib-http/http-server-request.c
src/lib-http/http-server-response.c
src/lib-http/http-server.h

index 88d6f896de33034a890b010d19344143b46b3c34..13ad3ae0b3695f977526eb06e527e972d07570d5 100644 (file)
@@ -47,6 +47,7 @@ struct http_server_response {
 
        string_t *headers;
        time_t date;
+       ARRAY_TYPE(http_auth_challenge) auth_challenges;
 
        struct istream *payload_input;
        uoff_t payload_size, payload_offset;
index 8862f579ae71a1ec34dd1b64a86318207c57d405..c01cb9ea527aff6d6d41f81376cc77bcf06ea6d2 100644 (file)
@@ -111,6 +111,22 @@ http_server_request_get_response(struct http_server_request *req)
        return req->response;
 }
 
+int http_server_request_get_auth(struct http_server_request *req,
+       struct http_auth_credentials *credentials)
+{
+       const char *auth;
+
+       auth = http_request_header_get(&req->req, "Authorization");
+       if (auth == NULL)
+               return 0;
+
+       if (http_auth_parse_credentials
+               ((const unsigned char *)auth, strlen(auth), credentials) < 0)
+               return -1;
+       
+       return 1;
+}
+
 bool http_server_request_is_finished(struct http_server_request *req)
 {
        return req->response != NULL ||
@@ -197,9 +213,9 @@ void http_server_request_finished(struct http_server_request *req)
        http_server_connection_send_responses(conn);
 }
 
-static void
-http_server_request_fail_full(struct http_server_request *req,
-       unsigned int status, const char *reason, bool close)
+static         struct http_server_response *
+http_server_request_create_fail_response(struct http_server_request *req,
+       unsigned int status, const char *reason)
 {
        struct http_server_response *resp;
 
@@ -211,6 +227,18 @@ http_server_request_fail_full(struct http_server_request *req,
        reason = t_strconcat(reason, "\r\n", NULL);
        http_server_response_set_payload_data
                (resp, (const unsigned char *)reason, strlen(reason));
+
+       return resp;
+}
+
+static void
+http_server_request_fail_full(struct http_server_request *req,
+       unsigned int status, const char *reason, bool close)
+{
+       struct http_server_response *resp;
+
+       req->failed = TRUE;
+       resp = http_server_request_create_fail_response(req, status, reason);
        if (close)
                http_server_response_submit_close(resp);
        else
@@ -229,3 +257,28 @@ void http_server_request_fail_close(struct http_server_request *req,
 {
        http_server_request_fail_full(req, status, reason, TRUE);
 }
+
+void http_server_request_fail_auth(struct http_server_request *req,
+       const char *reason, const struct http_auth_challenge *chlng)
+{
+       struct http_server_response *resp;
+
+       req->failed = TRUE;
+
+       if (reason == NULL)
+               reason = "Unauthenticated";
+
+       resp = http_server_request_create_fail_response(req, 401, reason);
+       http_server_response_add_auth(resp, chlng);
+       http_server_response_submit(resp);
+}
+
+void http_server_request_fail_auth_basic(struct http_server_request *req,
+       const char *reason, const char *realm)
+{
+       struct http_auth_challenge chlng;
+
+       http_auth_basic_challenge_init(&chlng, realm);
+       http_server_request_fail_auth(req, reason, &chlng);
+}
+
index 40079dfeaa09ed82780326b5c6651bf5144ee85e..33989472c32fd9d82fba0baf382159ba30117981 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "str.h"
+#include "array.h"
 #include "istream.h"
 #include "ostream.h"
 #include "http-date.h"
@@ -137,6 +138,29 @@ void http_server_response_set_payload_data(struct http_server_response *resp,
        i_stream_unref(&input);
 }
 
+void http_server_response_add_auth(
+       struct http_server_response *resp,
+       const struct http_auth_challenge *chlng)
+{
+       struct http_auth_challenge *new;
+       pool_t pool = resp->request->pool;
+
+       if (!array_is_created(&resp->auth_challenges))
+               p_array_init(&resp->auth_challenges, pool, 4);
+
+       new = array_append_space(&resp->auth_challenges);
+       http_auth_challenge_copy(pool, new, chlng);
+}
+
+void http_server_response_add_auth_basic(
+       struct http_server_response *resp, const char *realm)
+{
+       struct http_auth_challenge chlng;
+
+       http_auth_basic_challenge_init(&chlng, realm);
+       http_server_response_add_auth(resp, &chlng);
+}
+
 static void http_server_response_do_submit(struct http_server_response *resp,
        bool close)
 {
@@ -284,6 +308,11 @@ static int http_server_response_send_real(struct http_server_response *resp,
                str_append(rtext, http_date_create(resp->date));
                str_append(rtext, "\r\n");
        }
+       if (array_is_created(&resp->auth_challenges)) {
+               str_append(rtext, "WWW-Authenticate: ");
+               http_auth_create_challenges(rtext, &resp->auth_challenges);
+               str_append(rtext, "\r\n");
+       }
        if (resp->payload_chunked) {
                if (http_server_request_version_equals(req, 1, 0)) {
                        /* cannot use Transfer-Encoding */
@@ -382,4 +411,3 @@ int http_server_response_send(struct http_server_response *resp,
        } T_END;
        return ret;
 }
-
index 2bc1bfcad21cffe72a1bd8ce29bc4948391eba58..260bd26afe588f3d1146a3ec77cc66e804414a34 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef HTTP_SERVER_H
 #define HTTP_SERVER_H
 
+#include "http-auth.h"
 #include "http-request.h"
 
 struct istream;
@@ -90,6 +91,12 @@ http_server_request_get_response(struct http_server_request *req);
    or because the request was aborted. */
 bool http_server_request_is_finished(struct http_server_request *req);
 
+/* Get the authentication credentials provided in this request. Returns 0 if
+   the Authorization header is absent, returns -1 when that header cannot be
+   parsed, and returns 1 otherwise */
+int http_server_request_get_auth(struct http_server_request *req,
+       struct http_auth_credentials *credentials);
+
 /* Send a failure response to the request with given status/reason. */
 void http_server_request_fail(struct http_server_request *req,
        unsigned int status, const char *reason);
@@ -97,6 +104,18 @@ void http_server_request_fail(struct http_server_request *req,
    and close the connection. */
 void http_server_request_fail_close(struct http_server_request *req,
        unsigned int status, const char *reason);
+/* Send an authentication failure response to the request with given reason.
+   The provided challenge is set in the WWW-Authenticate header of the
+   response. */
+void http_server_request_fail_auth(struct http_server_request *req,
+       const char *reason, const struct http_auth_challenge *chlng)
+       ATTR_NULL(2);
+/* Send a authentication failure response to the request with given reason.
+   The provided realm is used to construct an Basic challenge in the
+   WWW-Authenticate header of the response. */
+void http_server_request_fail_auth_basic(struct http_server_request *req,
+       const char *reason, const char *realm)
+       ATTR_NULL(2);
 
 /* Call the specified callback when HTTP request is destroyed. This happens
    after one of the following:
@@ -131,6 +150,13 @@ void http_server_response_set_payload(struct http_server_response *resp,
                                     struct istream *input);
 void http_server_response_set_payload_data(struct http_server_response *resp,
                                     const unsigned char *data, size_t size);
+
+void http_server_response_add_auth(
+       struct http_server_response *resp,
+       const struct http_auth_challenge *chlng);
+void http_server_response_add_auth_basic(
+       struct http_server_response *resp, const char *realm);
+
 void http_server_response_submit(struct http_server_response *resp);
 /* Submit response and close the connection. */
 void http_server_response_submit_close(struct http_server_response *resp);