string_t *headers;
time_t date;
+ ARRAY_TYPE(http_auth_challenge) auth_challenges;
struct istream *payload_input;
uoff_t payload_size, payload_offset;
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 ||
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;
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
{
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);
+}
+
#include "lib.h"
#include "str.h"
+#include "array.h"
#include "istream.h"
#include "ostream.h"
#include "http-date.h"
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)
{
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 */
} T_END;
return ret;
}
-
#ifndef HTTP_SERVER_H
#define HTTP_SERVER_H
+#include "http-auth.h"
#include "http-request.h"
struct istream;
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);
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:
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);