Browse Source

[mod_auth] structured data, register auth schemes

- parse auth.* directives into structured data during config processing
- register auth schemes (basic, digest, extern, ...) for extensibility
- remove auth.debug directive
personal/stbuehler/mod-csrf-old
Glenn Strauss 5 years ago
parent
commit
7ba06c71a6
  1. 107
      src/http_auth.c
  2. 28
      src/http_auth.h
  3. 968
      src/mod_auth.c
  4. 12
      tests/mod-auth.t

107
src/http_auth.c

@ -5,6 +5,28 @@
#include <string.h>
static http_auth_scheme_t http_auth_schemes[8];
const http_auth_scheme_t * http_auth_scheme_get (const buffer *name)
{
int i = 0;
while (NULL != http_auth_schemes[i].name
&& 0 != strcmp(http_auth_schemes[i].name, name->ptr)) {
++i;
}
return (NULL != http_auth_schemes[i].name) ? http_auth_schemes+i : NULL;
}
void http_auth_scheme_set (const http_auth_scheme_t *scheme)
{
unsigned int i = 0;
while (NULL != http_auth_schemes[i].name) ++i;
/*(must resize http_auth_schemes[] if too many different auth schemes)*/
force_assert(i<(sizeof(http_auth_schemes)/sizeof(http_auth_scheme_t))-1);
memcpy(http_auth_schemes+i, scheme, sizeof(http_auth_scheme_t));
}
static http_auth_backend_t http_auth_backends[8];
const http_auth_backend_t * http_auth_backend_get (const buffer *name)
@ -14,7 +36,7 @@ const http_auth_backend_t * http_auth_backend_get (const buffer *name)
&& 0 != strcmp(http_auth_backends[i].name, name->ptr)) {
++i;
}
return http_auth_backends+i;
return (NULL != http_auth_backends[i].name) ? http_auth_backends+i : NULL;
}
void http_auth_backend_set (const http_auth_backend_t *backend)
@ -26,6 +48,89 @@ void http_auth_backend_set (const http_auth_backend_t *backend)
memcpy(http_auth_backends+i, backend, sizeof(http_auth_backend_t));
}
http_auth_require_t * http_auth_require_init (void)
{
http_auth_require_t *require = calloc(1, sizeof(http_auth_require_t));
force_assert(NULL != require);
require->realm = buffer_init();
require->valid_user = 0;
require->user = array_init();
require->group = array_init();
require->host = array_init();
return require;
}
void http_auth_require_free (http_auth_require_t * const require)
{
buffer_free(require->realm);
array_free(require->user);
array_free(require->group);
array_free(require->host);
free(require);
}
/* (case-sensitive version of array.c:array_get_index(),
* and common case expects small num of allowed tokens,
* so it is reasonably performant to simply walk the array) */
static int http_auth_array_contains (const array * const a, const char * const k, const size_t klen)
{
for (size_t i = 0, used = a->used; i < used; ++i) {
if (buffer_is_equal_string(a->data[i]->key, k, klen)) {
return 1;
}
}
return 0;
}
int http_auth_match_rules (const http_auth_require_t * const require, const char * const user, const char * const group, const char * const host)
{
if (NULL != user
&& (require->valid_user
|| http_auth_array_contains(require->user, user, strlen(user)))) {
return 1; /* match */
}
if (NULL != group
&& http_auth_array_contains(require->group, group, strlen(group))) {
return 1; /* match */
}
if (NULL != host
&& http_auth_array_contains(require->host, host, strlen(host))) {
return 1; /* match */
}
return 0; /* no match */
}
void http_auth_setenv(array *env, const char *username, size_t ulen, const char *auth_type, size_t alen) {
data_string *ds;
/* REMOTE_USER */
if (NULL == (ds = (data_string *)array_get_element(env, "REMOTE_USER"))) {
if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
ds = data_string_init();
}
buffer_copy_string_len(ds->key, CONST_STR_LEN("REMOTE_USER"));
array_insert_unique(env, (data_unset *)ds);
}
buffer_copy_string_len(ds->value, username, ulen);
/* AUTH_TYPE */
if (NULL == (ds = (data_string *)array_get_element(env, "AUTH_TYPE"))) {
if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
ds = data_string_init();
}
buffer_copy_string_len(ds->key, CONST_STR_LEN("AUTH_TYPE"));
array_insert_unique(env, (data_unset *)ds);
}
buffer_copy_string_len(ds->value, auth_type, alen);
}
int http_auth_md5_hex2bin (const char *md5hex, size_t len, unsigned char md5bin[16])
{
/* validate and transform 32-byte MD5 hex string to 16-byte binary MD5 */

28
src/http_auth.h

@ -4,6 +4,23 @@
#include "base.h"
struct http_auth_scheme_t;
struct http_auth_require_t;
struct http_auth_backend_t;
typedef struct http_auth_require_t {
const struct http_auth_scheme_t *scheme;
buffer *realm;
int valid_user;
array *user;
array *group;
array *host;
} http_auth_require_t;
http_auth_require_t * http_auth_require_init (void);
void http_auth_require_free (http_auth_require_t *require);
int http_auth_match_rules (const http_auth_require_t *require, const char *user, const char *group, const char *host);
typedef struct http_auth_backend_t {
const char *name;
handler_t(*basic)(server *srv, connection *con, void *p_d, const buffer *username, const buffer *realm, const char *pw);
@ -11,9 +28,20 @@ typedef struct http_auth_backend_t {
void *p_d;
} http_auth_backend_t;
typedef struct http_auth_scheme_t {
const char *name;
handler_t(*checkfn)(server *srv, connection *con, void *p_d, const struct http_auth_require_t *require, const struct http_auth_backend_t *backend);
/*(backend is arg only because auth.backend is separate config directive)*/
void *p_d;
} http_auth_scheme_t;
const http_auth_scheme_t * http_auth_scheme_get (const buffer *name);
void http_auth_scheme_set (const http_auth_scheme_t *scheme);
const http_auth_backend_t * http_auth_backend_get (const buffer *name);
void http_auth_backend_set (const http_auth_backend_t *backend);
void http_auth_setenv(array *env, const char *username, size_t ulen, const char *auth_type, size_t alen);
int http_auth_md5_hex2bin (const char *md5hex, size_t len, unsigned char md5bin[16]);
#endif

968
src/mod_auth.c
File diff suppressed because it is too large
View File

12
tests/mod-auth.t

@ -24,16 +24,16 @@ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
ok($tf->handle_http($t) == 0, 'Missing Auth-token');
$t->{REQUEST} = ( <<EOF
GET /server-status HTTP/1.0
GET /server-config HTTP/1.0
Authorization: Basic \x80mFuOmphb
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
ok($tf->handle_http($t) == 0, 'Basic-Auth: Invalid base64 Auth-token');
$t->{REQUEST} = ( <<EOF
GET /server-status HTTP/1.0
Authorization: Basic amFuOmphb
GET /server-config HTTP/1.0
Authorization: Basic bm90Oml0Cg==
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
@ -151,11 +151,11 @@ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
ok($tf->handle_http($t) == 0, 'Digest-Auth: missing nc (noncecount instead), no crash');
$t->{REQUEST} = ( <<EOF
GET /server-status HTTP/1.0
GET /server-config HTTP/1.0
Authorization: Basic =
EOF
);
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 400 } ];
ok($tf->handle_http($t) == 0, 'Basic-Auth: Invalid Base64');
$t->{REQUEST} = ( <<EOF

Loading…
Cancel
Save