[tests] skip mod-secdownload HMAC-SHA1,HMAC-SHA256
[lighttpd.git] / src / http_auth.c
blobe9a64f6025e9cb4f654888dd8ffe1abc8ec27a9d
1 #include "first.h"
3 #include "http_auth.h"
4 #include "http_header.h"
6 #include <stdlib.h>
7 #include <string.h>
10 static http_auth_scheme_t http_auth_schemes[8];
12 const http_auth_scheme_t * http_auth_scheme_get (const buffer *name)
14 int i = 0;
15 while (NULL != http_auth_schemes[i].name
16 && 0 != strcmp(http_auth_schemes[i].name, name->ptr)) {
17 ++i;
19 return (NULL != http_auth_schemes[i].name) ? http_auth_schemes+i : NULL;
22 void http_auth_scheme_set (const http_auth_scheme_t *scheme)
24 unsigned int i = 0;
25 while (NULL != http_auth_schemes[i].name) ++i;
26 /*(must resize http_auth_schemes[] if too many different auth schemes)*/
27 force_assert(i<(sizeof(http_auth_schemes)/sizeof(http_auth_scheme_t))-1);
28 memcpy(http_auth_schemes+i, scheme, sizeof(http_auth_scheme_t));
32 static http_auth_backend_t http_auth_backends[12];
34 const http_auth_backend_t * http_auth_backend_get (const buffer *name)
36 int i = 0;
37 while (NULL != http_auth_backends[i].name
38 && 0 != strcmp(http_auth_backends[i].name, name->ptr)) {
39 ++i;
41 return (NULL != http_auth_backends[i].name) ? http_auth_backends+i : NULL;
44 void http_auth_backend_set (const http_auth_backend_t *backend)
46 unsigned int i = 0;
47 while (NULL != http_auth_backends[i].name) ++i;
48 /*(must resize http_auth_backends[] if too many different auth backends)*/
49 force_assert(i<(sizeof(http_auth_backends)/sizeof(http_auth_backend_t))-1);
50 memcpy(http_auth_backends+i, backend, sizeof(http_auth_backend_t));
54 int http_auth_const_time_memeq (const char *a, const size_t alen, const char *b, const size_t blen)
56 /* constant time memory compare, unless compiler figures it out
57 * (similar to mod_secdownload.c:const_time_memeq()) */
58 /* round to next multiple of 64 to avoid potentially leaking exact
59 * password length when subject to high precision timing attacks) */
60 size_t lim = ((alen >= blen ? alen : blen) + 0x3F) & ~0x3F;
61 int diff = 0;
62 for (size_t i = 0, j = 0; lim; --lim) {
63 diff |= (a[i] ^ b[j]);
64 i += (i < alen);
65 j += (j < blen);
67 return (0 == diff);
71 void http_auth_dumbdata_reset (void)
73 memset(http_auth_schemes, 0, sizeof(http_auth_schemes));
74 memset(http_auth_backends, 0, sizeof(http_auth_backends));
78 http_auth_require_t * http_auth_require_init (void)
80 http_auth_require_t *require = calloc(1, sizeof(http_auth_require_t));
81 force_assert(NULL != require);
83 require->realm = buffer_init();
84 require->valid_user = 0;
85 require->user = array_init();
86 require->group = array_init();
87 require->host = array_init();
89 return require;
92 void http_auth_require_free (http_auth_require_t * const require)
94 buffer_free(require->realm);
95 array_free(require->user);
96 array_free(require->group);
97 array_free(require->host);
98 free(require);
101 /* (case-sensitive version of array.c:array_get_index(),
102 * and common case expects small num of allowed tokens,
103 * so it is reasonably performant to simply walk the array) */
104 static int http_auth_array_contains (const array * const a, const char * const k, const size_t klen)
106 for (size_t i = 0, used = a->used; i < used; ++i) {
107 if (buffer_is_equal_string(a->data[i]->key, k, klen)) {
108 return 1;
111 return 0;
114 int http_auth_match_rules (const http_auth_require_t * const require, const char * const user, const char * const group, const char * const host)
116 if (NULL != user
117 && (require->valid_user
118 || http_auth_array_contains(require->user, user, strlen(user)))) {
119 return 1; /* match */
122 if (NULL != group
123 && http_auth_array_contains(require->group, group, strlen(group))) {
124 return 1; /* match */
127 if (NULL != host
128 && http_auth_array_contains(require->host, host, strlen(host))) {
129 return 1; /* match */
132 return 0; /* no match */
135 void http_auth_setenv(connection *con, const char *username, size_t ulen, const char *auth_type, size_t alen) {
136 http_header_env_set(con, CONST_STR_LEN("REMOTE_USER"), username, ulen);
137 http_header_env_set(con, CONST_STR_LEN("AUTH_TYPE"), auth_type, alen);
140 unsigned int http_auth_digest_len (int algo)
142 if (algo & (HTTP_AUTH_DIGEST_SHA256 | HTTP_AUTH_DIGEST_SHA512_256)) {
143 /* HTTP_AUTH_DIGEST_SHA512_256_BINLEN */
144 return HTTP_AUTH_DIGEST_SHA256_BINLEN;
146 if (algo & HTTP_AUTH_DIGEST_MD5) {
147 return HTTP_AUTH_DIGEST_MD5_BINLEN;
150 return 0;
153 int http_auth_digest_hex2bin (const char *hexstr, size_t len, unsigned char *bin, size_t binlen)
155 /* validate and transform 32-byte MD5 hex string to 16-byte binary MD5,
156 * or 64-byte SHA-256 or SHA-512-256 hex string to 32-byte binary digest */
157 if (len > (binlen << 1)) return -1;
158 for (int i = 0, ilen = (int)len; i < ilen; i+=2) {
159 int hi = hexstr[i];
160 int lo = hexstr[i+1];
161 if ('0' <= hi && hi <= '9') hi -= '0';
162 else if ((hi |= 0x20), 'a' <= hi && hi <= 'f') hi += -'a' + 10;
163 else return -1;
164 if ('0' <= lo && lo <= '9') lo -= '0';
165 else if ((lo |= 0x20), 'a' <= lo && lo <= 'f') lo += -'a' + 10;
166 else return -1;
167 bin[(i >> 1)] = (unsigned char)((hi << 4) | lo);
169 return 0;
172 #if 0
173 int http_auth_md5_hex2lc (char *md5hex)
175 /* validate and transform 32-byte MD5 hex string to lowercase */
176 int i;
177 for (i = 0; md5hex[i]; ++i) {
178 int c = md5hex[i];
179 if ('0' <= c && c <= '9') continue;
180 else if ((c |= 0x20), 'a' <= c && c <= 'f') md5hex[i] = c;
181 else return -1;
183 return (32 == i) ? 0 : -1; /*(Note: char *md5hex must be a 32-char string)*/
185 #endif