4 #include "http_header.h"
10 static http_auth_scheme_t http_auth_schemes
[8];
12 const http_auth_scheme_t
* http_auth_scheme_get (const buffer
*name
)
15 while (NULL
!= http_auth_schemes
[i
].name
16 && 0 != strcmp(http_auth_schemes
[i
].name
, name
->ptr
)) {
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
)
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
)
37 while (NULL
!= http_auth_backends
[i
].name
38 && 0 != strcmp(http_auth_backends
[i
].name
, name
->ptr
)) {
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
)
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;
62 for (size_t i
= 0, j
= 0; lim
; --lim
) {
63 diff
|= (a
[i
] ^ b
[j
]);
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();
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
);
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
)) {
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
)
117 && (require
->valid_user
118 || http_auth_array_contains(require
->user
, user
, strlen(user
)))) {
119 return 1; /* match */
123 && http_auth_array_contains(require
->group
, group
, strlen(group
))) {
124 return 1; /* match */
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
;
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) {
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;
164 if ('0' <= lo
&& lo
<= '9') lo
-= '0';
165 else if ((lo
|= 0x20), 'a' <= lo
&& lo
<= 'f') lo
+= -'a' + 10;
167 bin
[(i
>> 1)] = (unsigned char)((hi
<< 4) | lo
);
173 int http_auth_md5_hex2lc (char *md5hex
)
175 /* validate and transform 32-byte MD5 hex string to lowercase */
177 for (i
= 0; md5hex
[i
]; ++i
) {
179 if ('0' <= c
&& c
<= '9') continue;
180 else if ((c
|= 0x20), 'a' <= c
&& c
<= 'f') md5hex
[i
] = c
;
183 return (32 == i
) ? 0 : -1; /*(Note: char *md5hex must be a 32-char string)*/