2014-01-22 22:55:10 +01:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2014 Joris Vink <joris@coders.se>
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
#include "kore.h"
|
|
|
|
#include "http.h"
|
|
|
|
|
|
|
|
TAILQ_HEAD(, kore_auth) auth_list;
|
|
|
|
|
2014-01-22 23:11:52 +01:00
|
|
|
static int kore_auth_cookie(struct http_request *, struct kore_auth *);
|
|
|
|
static int kore_auth_header(struct http_request *, struct kore_auth *);
|
2014-03-01 19:18:30 +01:00
|
|
|
static int kore_auth_request(struct http_request *, struct kore_auth *);
|
2014-01-22 23:11:52 +01:00
|
|
|
|
2014-01-22 22:55:10 +01:00
|
|
|
void
|
|
|
|
kore_auth_init(void)
|
|
|
|
{
|
|
|
|
TAILQ_INIT(&auth_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-08-04 12:40:21 +02:00
|
|
|
kore_auth_new(const char *name)
|
2014-01-22 22:55:10 +01:00
|
|
|
{
|
|
|
|
struct kore_auth *auth;
|
|
|
|
|
|
|
|
if ((auth = kore_auth_lookup(name)) != NULL)
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
|
|
|
auth = kore_malloc(sizeof(*auth));
|
|
|
|
auth->type = 0;
|
|
|
|
auth->value = NULL;
|
|
|
|
auth->redirect = NULL;
|
|
|
|
auth->validator = NULL;
|
|
|
|
auth->name = kore_strdup(name);
|
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&auth_list, auth, list);
|
|
|
|
|
|
|
|
return (KORE_RESULT_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2015-04-02 13:45:42 +02:00
|
|
|
kore_auth_run(struct http_request *req, struct kore_auth *auth)
|
2014-01-22 22:55:10 +01:00
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
kore_debug("kore_auth(%p, %p)", req, auth);
|
|
|
|
|
|
|
|
switch (auth->type) {
|
|
|
|
case KORE_AUTH_TYPE_COOKIE:
|
|
|
|
r = kore_auth_cookie(req, auth);
|
|
|
|
break;
|
2014-01-22 23:11:52 +01:00
|
|
|
case KORE_AUTH_TYPE_HEADER:
|
|
|
|
r = kore_auth_header(req, auth);
|
|
|
|
break;
|
2014-03-01 19:18:30 +01:00
|
|
|
case KORE_AUTH_TYPE_REQUEST:
|
|
|
|
r = kore_auth_request(req, auth);
|
|
|
|
break;
|
2014-01-22 22:55:10 +01:00
|
|
|
default:
|
|
|
|
kore_log(LOG_NOTICE, "unknown auth type %d", auth->type);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2014-04-22 23:07:24 +02:00
|
|
|
switch (r) {
|
|
|
|
case KORE_RESULT_OK:
|
2016-01-18 11:30:22 +01:00
|
|
|
req->flags |= HTTP_REQUEST_AUTHED;
|
2015-04-02 13:45:42 +02:00
|
|
|
kore_debug("kore_auth_run() for %s successful", req->path);
|
2014-04-22 23:07:24 +02:00
|
|
|
/* FALLTHROUGH */
|
|
|
|
case KORE_RESULT_RETRY:
|
|
|
|
return (r);
|
|
|
|
default:
|
|
|
|
break;
|
2014-01-22 22:55:10 +01:00
|
|
|
}
|
|
|
|
|
2015-02-04 12:04:07 +01:00
|
|
|
/* Authentication types of "request" send their own HTTP responses. */
|
|
|
|
if (auth->type == KORE_AUTH_TYPE_REQUEST)
|
|
|
|
return (r);
|
|
|
|
|
2015-04-02 13:45:42 +02:00
|
|
|
kore_debug("kore_auth_run() for %s failed", req->path);
|
2014-01-22 22:55:10 +01:00
|
|
|
|
|
|
|
if (auth->redirect == NULL) {
|
|
|
|
http_response(req, 403, NULL, 0);
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2014-08-05 14:26:31 +02:00
|
|
|
http_response_header(req, "location", auth->redirect);
|
2014-01-22 22:55:10 +01:00
|
|
|
http_response(req, 302, NULL, 0);
|
|
|
|
|
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
}
|
|
|
|
|
2014-01-22 23:11:52 +01:00
|
|
|
static int
|
2014-01-22 22:55:10 +01:00
|
|
|
kore_auth_cookie(struct http_request *req, struct kore_auth *auth)
|
|
|
|
{
|
|
|
|
int i, v;
|
|
|
|
size_t len, slen;
|
|
|
|
char *value, *c, *cookie, *cookies[HTTP_MAX_COOKIES];
|
|
|
|
|
2015-12-14 18:48:48 +01:00
|
|
|
if (!http_request_header(req, "cookie", &c))
|
2014-01-22 22:55:10 +01:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2015-12-14 18:48:48 +01:00
|
|
|
cookie = kore_strdup(c);
|
|
|
|
|
2014-01-22 22:55:10 +01:00
|
|
|
slen = strlen(auth->value);
|
|
|
|
v = kore_split_string(cookie, ";", cookies, HTTP_MAX_COOKIES);
|
|
|
|
for (i = 0; i < v; i++) {
|
|
|
|
for (c = cookies[i]; isspace(*c); c++)
|
|
|
|
;
|
|
|
|
|
|
|
|
len = MIN(slen, strlen(cookies[i]));
|
|
|
|
if (!strncmp(c, auth->value, len))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-12-14 18:48:48 +01:00
|
|
|
if (i == v) {
|
2016-07-12 13:54:14 +02:00
|
|
|
kore_free(cookie);
|
2014-01-22 22:55:10 +01:00
|
|
|
return (KORE_RESULT_ERROR);
|
2015-12-14 18:48:48 +01:00
|
|
|
}
|
2014-01-22 22:55:10 +01:00
|
|
|
|
|
|
|
c = cookies[i];
|
2015-12-14 18:48:48 +01:00
|
|
|
if ((value = strchr(c, '=')) == NULL) {
|
2016-07-12 13:54:14 +02:00
|
|
|
kore_free(cookie);
|
2014-01-22 22:55:10 +01:00
|
|
|
return (KORE_RESULT_ERROR);
|
2015-12-14 18:48:48 +01:00
|
|
|
}
|
2014-01-22 22:55:10 +01:00
|
|
|
|
2014-02-01 17:47:58 +01:00
|
|
|
i = kore_validator_check(req, auth->validator, ++value);
|
2016-07-12 13:54:14 +02:00
|
|
|
kore_free(cookie);
|
2015-12-14 18:48:48 +01:00
|
|
|
|
2014-01-22 22:55:10 +01:00
|
|
|
return (i);
|
|
|
|
}
|
|
|
|
|
2014-01-22 23:11:52 +01:00
|
|
|
static int
|
|
|
|
kore_auth_header(struct http_request *req, struct kore_auth *auth)
|
|
|
|
{
|
|
|
|
char *header;
|
|
|
|
|
2014-08-05 14:26:31 +02:00
|
|
|
if (!http_request_header(req, auth->value, &header))
|
2014-01-22 23:11:52 +01:00
|
|
|
return (KORE_RESULT_ERROR);
|
|
|
|
|
2016-02-21 18:29:06 +01:00
|
|
|
return (kore_validator_check(req, auth->validator, header));
|
2014-01-22 23:11:52 +01:00
|
|
|
}
|
|
|
|
|
2014-03-01 19:18:30 +01:00
|
|
|
static int
|
|
|
|
kore_auth_request(struct http_request *req, struct kore_auth *auth)
|
|
|
|
{
|
2017-01-25 21:17:12 +01:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
req->flags |= HTTP_VALIDATOR_IS_REQUEST;
|
|
|
|
ret = kore_validator_check(req, auth->validator, req);
|
|
|
|
req->flags &= ~HTTP_VALIDATOR_IS_REQUEST;
|
|
|
|
|
|
|
|
return (ret);
|
2014-03-01 19:18:30 +01:00
|
|
|
}
|
|
|
|
|
2014-01-22 22:55:10 +01:00
|
|
|
struct kore_auth *
|
2014-08-04 12:40:21 +02:00
|
|
|
kore_auth_lookup(const char *name)
|
2014-01-22 22:55:10 +01:00
|
|
|
{
|
|
|
|
struct kore_auth *auth;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(auth, &auth_list, list) {
|
|
|
|
if (!strcmp(auth->name, name))
|
|
|
|
return (auth);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (NULL);
|
|
|
|
}
|