Bug Summary

File:libs/sofia-sip/libsofia-sip-ua/iptsec/auth_module.c
Location:line 693, column 3
Description:Value stored to 'phrase' is never read

Annotated Source Code

1/*
2 * This file is part of the Sofia-SIP package
3 *
4 * Copyright (C) 2005 Nokia Corporation.
5 *
6 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25/**@CFILE auth_module.c
26 * @brief Authentication verification module
27 *
28 * The authentication module provides server or proxy-side authentication
29 * verification for network elements like registrars, presence servers, and
30 * proxies.
31 *
32 * @author Pekka Pessi <Pekka.Pessi@nokia.com>.
33 *
34 * @date Created: Wed Apr 11 15:14:03 2001 ppessi
35 */
36
37#include "config.h"
38
39#include <stddef.h>
40#include <stdlib.h>
41#include <string.h>
42#include <stdio.h>
43#include <assert.h>
44
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <unistd.h>
48
49#include <sofia-sip/auth_digest.h>
50
51#include "iptsec_debug.h"
52
53#if HAVE_FUNC1
54#elif HAVE_FUNCTION1
55#define __func__ __FUNCTION__
56#else
57static char const __func__[] = "auth_mod";
58#endif
59
60#include <sofia-sip/su_debug.h>
61
62#include <sofia-sip/su_wait.h>
63#include <sofia-sip/su_alloc.h>
64#include <sofia-sip/su_string.h>
65#include <sofia-sip/su_tagarg.h>
66
67#include <sofia-sip/base64.h>
68#include <sofia-sip/su_md5.h>
69
70#include <sofia-sip/msg_parser.h>
71#include <sofia-sip/msg_date.h>
72
73#include "sofia-sip/auth_module.h"
74#include "sofia-sip/auth_plugin.h"
75
76#define APW_HASH(apw)((apw)->apw_index) ((apw)->apw_index)
77
78char const auth_internal_server_error[] = "Internal server error";
79
80static void auth_call_scheme_destructor(void *);
81static void auth_md5_hmac_key(auth_mod_t *am);
82
83#ifdef __clang__1
84#pragma clang diagnostic push
85#pragma clang diagnostic ignored "-Wunused-function"
86#endif
87
88HTABLE_PROTOS_WITH(auth_htable, aht, auth_passwd_t, usize_t, unsigned)static inline int auth_htable_resize(su_home_t *, auth_htable_t
aht[1], usize_t); static inline int auth_htable_is_full(auth_htable_t
const *); static inline auth_passwd_t **auth_htable_hash(auth_htable_t
const *, unsigned hv); static inline auth_passwd_t **auth_htable_next
(auth_htable_t const *, auth_passwd_t * const *ee); static inline
void auth_htable_append(auth_htable_t *aht, auth_passwd_t const
*e); static inline void auth_htable_insert(auth_htable_t *aht
, auth_passwd_t const *e); static inline int auth_htable_remove
(auth_htable_t *, auth_passwd_t const *e)
;
89HTABLE_BODIES_WITH(auth_htable, aht, auth_passwd_t, APW_HASH,static inline int auth_htable_resize(su_home_t *home, auth_htable_t
aht[], usize_t new_size) { auth_passwd_t **new_hash; auth_passwd_t
**old_hash = aht-> aht_table; usize_t old_size; usize_t i
, j, i0; unsigned again = 0; usize_t used = 0, collisions = 0
; if (new_size == 0) new_size = 2 * aht-> aht_size + 1; if
(new_size < 31) new_size = 31; if (new_size < 5 * aht->
aht_used / 4) new_size = 5 * aht-> aht_used / 4; if (!(new_hash
= su_zalloc(home, sizeof(*new_hash) * new_size))) return -1;
old_size = aht-> aht_size; do for (j = 0; j < old_size
; j++) { if (!old_hash[j]) continue; if (again < 2 &&
((old_hash[j])->apw_index) % old_size > j) { again = 1
; continue; } i0 = ((old_hash[j])->apw_index) % new_size; for
(i = i0; new_hash[i]; i = (i + 1) % new_size, ((i != i0) ? (
void) (0) : __assert_fail ("i != i0", "auth_module.c", 90, __PRETTY_FUNCTION__
))) collisions++; new_hash[i] = old_hash[j], old_hash[j] = ((
void*)0); used++; } while (again++ == 1); aht-> aht_table =
new_hash, aht-> aht_size = new_size; ((aht-> aht_used ==
used) ? (void) (0) : __assert_fail ("aht-> aht_used == used"
, "auth_module.c", 90, __PRETTY_FUNCTION__)); su_free(home, old_hash
); return 0; } static inline int auth_htable_is_full(auth_htable_t
const *aht) { return aht-> aht_table == ((void*)0) || 3 *
aht-> aht_used > 2 * aht-> aht_size; } static inline
auth_passwd_t **auth_htable_hash(auth_htable_t const *aht, unsigned
hv) { return aht-> aht_table + hv % aht-> aht_size; } static
inline auth_passwd_t **auth_htable_next(auth_htable_t const *
aht, auth_passwd_t * const *ee) { if (++ee < aht-> aht_table
+ aht-> aht_size && ee >= aht-> aht_table) return
(auth_passwd_t **)ee; else return aht-> aht_table; } static
inline void auth_htable_append(auth_htable_t *aht, auth_passwd_t
const *e) { auth_passwd_t **ee; aht-> aht_used++; for (ee
= auth_htable_hash(aht, ((e)->apw_index)); *ee; ee = auth_htable_next
(aht, ee)) ; *ee = (auth_passwd_t *)e; } static inline void auth_htable_insert
(auth_htable_t *aht, auth_passwd_t const *e) { auth_passwd_t *
e0, **ee; aht-> aht_used++; for (ee = auth_htable_hash(aht
, ((e)->apw_index)); (e0 = *ee); ee = auth_htable_next(aht
, ee)) *ee = (auth_passwd_t *)e, e = e0; *ee = (auth_passwd_t
*)e; } static inline int auth_htable_remove(auth_htable_t *aht
, auth_passwd_t const *e) { usize_t i, j, k; usize_t size = aht
-> aht_size; auth_passwd_t **htable = aht-> aht_table; if
(!e) return -1; for (i = ((e)->apw_index) % size; htable[
i]; i = (i + 1) % size) if (e == htable[i]) break; if (!htable
[i]) return -1; for (j = (i + 1) % size; htable[j]; j = (j + 1
) % size) { k = ((htable[j])->apw_index) % size; if (k == j
) continue; if (j > i ? (i < k && k < j) : (
i < k || k < j)) continue; htable[i] = htable[j], i = j
; } aht-> aht_used--; htable[i] = ((void*)0); return 0; } extern
int auth_htable_dummy
90 usize_t, unsigned)static inline int auth_htable_resize(su_home_t *home, auth_htable_t
aht[], usize_t new_size) { auth_passwd_t **new_hash; auth_passwd_t
**old_hash = aht-> aht_table; usize_t old_size; usize_t i
, j, i0; unsigned again = 0; usize_t used = 0, collisions = 0
; if (new_size == 0) new_size = 2 * aht-> aht_size + 1; if
(new_size < 31) new_size = 31; if (new_size < 5 * aht->
aht_used / 4) new_size = 5 * aht-> aht_used / 4; if (!(new_hash
= su_zalloc(home, sizeof(*new_hash) * new_size))) return -1;
old_size = aht-> aht_size; do for (j = 0; j < old_size
; j++) { if (!old_hash[j]) continue; if (again < 2 &&
((old_hash[j])->apw_index) % old_size > j) { again = 1
; continue; } i0 = ((old_hash[j])->apw_index) % new_size; for
(i = i0; new_hash[i]; i = (i + 1) % new_size, ((i != i0) ? (
void) (0) : __assert_fail ("i != i0", "auth_module.c", 90, __PRETTY_FUNCTION__
))) collisions++; new_hash[i] = old_hash[j], old_hash[j] = ((
void*)0); used++; } while (again++ == 1); aht-> aht_table =
new_hash, aht-> aht_size = new_size; ((aht-> aht_used ==
used) ? (void) (0) : __assert_fail ("aht-> aht_used == used"
, "auth_module.c", 90, __PRETTY_FUNCTION__)); su_free(home, old_hash
); return 0; } static inline int auth_htable_is_full(auth_htable_t
const *aht) { return aht-> aht_table == ((void*)0) || 3 *
aht-> aht_used > 2 * aht-> aht_size; } static inline
auth_passwd_t **auth_htable_hash(auth_htable_t const *aht, unsigned
hv) { return aht-> aht_table + hv % aht-> aht_size; } static
inline auth_passwd_t **auth_htable_next(auth_htable_t const *
aht, auth_passwd_t * const *ee) { if (++ee < aht-> aht_table
+ aht-> aht_size && ee >= aht-> aht_table) return
(auth_passwd_t **)ee; else return aht-> aht_table; } static
inline void auth_htable_append(auth_htable_t *aht, auth_passwd_t
const *e) { auth_passwd_t **ee; aht-> aht_used++; for (ee
= auth_htable_hash(aht, ((e)->apw_index)); *ee; ee = auth_htable_next
(aht, ee)) ; *ee = (auth_passwd_t *)e; } static inline void auth_htable_insert
(auth_htable_t *aht, auth_passwd_t const *e) { auth_passwd_t *
e0, **ee; aht-> aht_used++; for (ee = auth_htable_hash(aht
, ((e)->apw_index)); (e0 = *ee); ee = auth_htable_next(aht
, ee)) *ee = (auth_passwd_t *)e, e = e0; *ee = (auth_passwd_t
*)e; } static inline int auth_htable_remove(auth_htable_t *aht
, auth_passwd_t const *e) { usize_t i, j, k; usize_t size = aht
-> aht_size; auth_passwd_t **htable = aht-> aht_table; if
(!e) return -1; for (i = ((e)->apw_index) % size; htable[
i]; i = (i + 1) % size) if (e == htable[i]) break; if (!htable
[i]) return -1; for (j = (i + 1) % size; htable[j]; j = (j + 1
) % size) { k = ((htable[j])->apw_index) % size; if (k == j
) continue; if (j > i ? (i < k && k < j) : (
i < k || k < j)) continue; htable[i] = htable[j], i = j
; } aht-> aht_used--; htable[i] = ((void*)0); return 0; } extern
int auth_htable_dummy
;
91
92#ifdef __clang__1
93#pragma clang diagnostic pop
94#endif
95
96/**Allocate an authentication module instance.
97 *
98 * The function auth_mod_alloc() allocates an authentication module object.
99 *
100 */
101auth_mod_t *auth_mod_alloc(auth_scheme_t *scheme,
102 tag_type_t tag, tag_value_t value, ...)
103{
104 auth_mod_t *am = NULL((void*)0);
105
106 if ((am = su_home_new(scheme->asch_size))) {
107 am->am_scheme = scheme;
108 su_home_destructor(am->am_home, auth_call_scheme_destructor);
109 }
110
111 return am;
112}
113
114/**Initialize an authentication module instance.
115 *
116 * The function auth_mod_init_default() initializes an authentication module
117 * object used to authenticate the requests.
118 *
119 * @param am
120 * @param base
121 * @param root
122 * @param tag,value,... tagged argument list
123 *
124 * @TAGS
125 * AUTHTAG_REALM(), AUTHTAG_OPAQUE(), AUTHTAG_DB(), AUTHTAG_QOP(),
126 * AUTHTAG_ALGORITHM(), AUTHTAG_EXPIRES(), AUTHTAG_NEXT_EXPIRES(),
127 * AUTHTAG_BLACKLIST(), AUTHTAG_FORBIDDEN(), AUTHTAG_ANONYMOUS(),
128 * AUTHTAG_FAKE(), AUTHTAG_ALLOW(), AUTHTAG_REMOTE(), and
129 * AUTHTAG_MASTER_KEY().
130 *
131 * @return 0 if successful
132 * @return -1 upon an error
133 */
134int auth_init_default(auth_mod_t *am,
135 auth_scheme_t *base,
136 su_root_t *root,
137 tag_type_t tag, tag_value_t value, ...)
138{
139 int retval = 0;
140
141 ta_list ta;
142
143 char const *realm = NULL((void*)0), *opaque = NULL((void*)0), *db = NULL((void*)0), *allows = NULL((void*)0);
144 char const *qop = NULL((void*)0), *algorithm = NULL((void*)0);
145 unsigned expires = 60 * 60, next_expires = 5 * 60;
146 unsigned max_ncount = 0;
147 unsigned blacklist = 5;
148 int forbidden = 0;
149 int anonymous = 0;
150 int fake = 0;
151 url_string_t const *remote = NULL((void*)0);
152 char const *master_key = "fish";
153 char *s;
154
155 ta_start(ta, tag, value)do { tag_type_t ta_start__tag = (tag); tag_value_t ta_start__value
= (value); __builtin_va_start((ta).ap, (value)); while ((ta_start__tag
) == tag_next && (ta_start__value) != 0) { ta_start__tag
= ((tagi_t *)ta_start__value)->t_tag; if (ta_start__tag ==
tag_null || ta_start__tag == ((void*)0)) break; if (ta_start__tag
== tag_next) { ta_start__value = ((tagi_t *)ta_start__value)
->t_value; } else { ta_start__tag = tag_next; break; } } (
ta).tl->t_tag = ta_start__tag; (ta).tl->t_value = ta_start__value
; if (ta_start__tag != ((void*)0) && ta_start__tag !=
tag_null && ta_start__tag != tag_next) { va_list ta_start__ap
; __builtin_va_copy((ta_start__ap), ((ta).ap)); (ta).tl[1].t_tag
= tag_next; (ta).tl[1].t_value = (tag_value_t)tl_vlist(ta_start__ap
); __builtin_va_end(ta_start__ap); } else { (ta).tl[1].t_value
= 0; (ta).tl[1].t_value = (tag_value_t)0; } } while(0)
;
156
157 /* Authentication stuff */
158 tl_gets(ta_args(ta)(ta).tl,
159 AUTHTAG_REALM_REF(realm)authtag_realm_ref, tag_str_vr((&realm)),
160 AUTHTAG_OPAQUE_REF(opaque)authtag_opaque_ref, tag_str_vr((&opaque)),
161 AUTHTAG_DB_REF(db)authtag_db_ref, tag_str_vr((&db)),
162 AUTHTAG_QOP_REF(qop)authtag_qop_ref, tag_str_vr((&qop)),
163 AUTHTAG_ALGORITHM_REF(algorithm)authtag_algorithm_ref, tag_str_vr((&algorithm)),
164 AUTHTAG_EXPIRES_REF(expires)authtag_expires_ref, tag_uint_vr((&expires)),
165 AUTHTAG_NEXT_EXPIRES_REF(next_expires)authtag_next_expires_ref, tag_uint_vr((&next_expires)),
166 AUTHTAG_MAX_NCOUNT_REF(max_ncount)authtag_max_ncount_ref, tag_uint_vr((&max_ncount)),
167 AUTHTAG_BLACKLIST_REF(blacklist)authtag_blacklist_ref, tag_uint_vr((&blacklist)),
168 AUTHTAG_FORBIDDEN_REF(forbidden)authtag_forbidden_ref, tag_bool_vr((&forbidden)),
169 AUTHTAG_ANONYMOUS_REF(anonymous)authtag_anonymous_ref, tag_bool_vr((&anonymous)),
170 AUTHTAG_FAKE_REF(fake)authtag_fake_ref, tag_bool_vr((&fake)),
171 AUTHTAG_ALLOW_REF(allows)authtag_allow_ref, tag_str_vr((&allows)),
172 AUTHTAG_REMOTE_REF(remote)authtag_remote_ref, urltag_url_vr((&remote)),
173 AUTHTAG_MASTER_KEY_REF(master_key)authtag_master_key_ref, tag_str_vr((&master_key)),
174 TAG_NULL()(tag_type_t)0, (tag_value_t)0);
175
176 if (!realm) realm = "*";
177 if (!allows) allows = "ACK, BYE, CANCEL";
178
179 am->am_realm = su_strdup(am->am_home, realm);
180 am->am_opaque = su_strdup(am->am_home, opaque);
181 am->am_db = su_strdup(am->am_home, db);
182 s = su_strdup(am->am_home, allows);
183 if (s)
184 msg_commalist_d(am->am_home, &s, &am->am_allow, NULL((void*)0));
185 am->am_expires = expires;
186 am->am_next_exp = next_expires;
187 am->am_max_ncount = max_ncount;
188 am->am_blacklist = blacklist;
189 am->am_forbidden = forbidden;
190 am->am_anonymous = anonymous;
191 am->am_fake = fake;
192 am->am_remote = url_hdup(am->am_home, (url_t *)remote);
193 am->am_algorithm = algorithm ? su_strdup(am->am_home, algorithm) : "MD5";
194 am->am_nextnonce = !algorithm || su_casematch(algorithm, "MD5");
195 if (next_expires == 0)
196 am->am_nextnonce = 0;
197 am->am_qop = su_strdup(am->am_home, qop);
198
199 if (master_key) {
200 su_md5_t md5[1];
201
202 su_md5_init(md5);
203 su_md5_strupdate(md5, master_key);
204 su_md5_strupdate(md5, "70P 53KR37");
205 su_md5_digest(md5, am->am_master_key);
206 }
207
208 auth_md5_hmac_key(am);
209
210 /* Make sure that we have something
211 that can be used to identify credentials */
212 if (am->am_opaque && strcmp(am->am_opaque, "*")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(am->am_opaque) && __builtin_constant_p ("*") &&
(__s1_len = __builtin_strlen (am->am_opaque), __s2_len = __builtin_strlen
("*"), (!((size_t)(const void *)((am->am_opaque) + 1) - (
size_t)(const void *)(am->am_opaque) == 1) || __s1_len >=
4) && (!((size_t)(const void *)(("*") + 1) - (size_t
)(const void *)("*") == 1) || __s2_len >= 4)) ? __builtin_strcmp
(am->am_opaque, "*") : (__builtin_constant_p (am->am_opaque
) && ((size_t)(const void *)((am->am_opaque) + 1) -
(size_t)(const void *)(am->am_opaque) == 1) && (__s1_len
= __builtin_strlen (am->am_opaque), __s1_len < 4) ? (__builtin_constant_p
("*") && ((size_t)(const void *)(("*") + 1) - (size_t
)(const void *)("*") == 1) ? __builtin_strcmp (am->am_opaque
, "*") : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) ("*"); int __result = (((const
unsigned char *) (const char *) (am->am_opaque))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (am->am_opaque
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (am->
am_opaque))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (am
->am_opaque))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("*") && ((size_t)(const void *)(("*") + 1) - (size_t
)(const void *)("*") == 1) && (__s2_len = __builtin_strlen
("*"), __s2_len < 4) ? (__builtin_constant_p (am->am_opaque
) && ((size_t)(const void *)((am->am_opaque) + 1) -
(size_t)(const void *)(am->am_opaque) == 1) ? __builtin_strcmp
(am->am_opaque, "*") : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (am->
am_opaque); int __result = (((const unsigned char *) (const char
*) ("*"))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
"*"))[1] - __s2[1]); if (__s2_len > 1 && __result ==
0) { __result = (((const unsigned char *) (const char *) ("*"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("*"))[
3] - __s2[3]); } } __result; })))) : __builtin_strcmp (am->
am_opaque, "*")))); })
== 0) {
213#ifndef HOST_NAME_MAX64
214#define HOST_NAME_MAX64 255
215#endif
216 char hostname[HOST_NAME_MAX64 + 1];
217 su_md5_t md5[1];
218 uint8_t hmac[6];
219
220 gethostname(hostname, sizeof hostname);
221
222 auth_md5_hmac_init(am, md5);
223
224 su_md5_strupdate(md5, hostname);
225 su_md5_update(md5, ":", 1);
226 if (am->am_remote)
227 url_update(md5, am->am_remote);
228
229 auth_md5_hmac_digest(am, md5, hmac, sizeof hmac);
230
231 base64_e(hostname, sizeof hostname, hmac, sizeof hmac);
232
233 am->am_opaque = su_strdup(am->am_home, hostname);
234
235 if (!am->am_opaque) {
236 retval = -1;
237 SU_DEBUG_1(("%s: cannot create unique identifier\n", __func__))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 1 ? (_su_llog((iptsec_log), 1, "auth_module.c"
, (const char *)__func__, 237, "%s: cannot create unique identifier\n"
, __func__)) : (void)0)
;
238 }
239 }
240
241 if (retval < 0)
242 ;
243 else if (db) {
244 retval = auth_readdb(am);
245 if (retval == -1) {
246 int err = errno(*__errno_location ());
247 SU_DEBUG_1(("auth-module: %s: %s\n", am->am_db, strerror(err)))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 1 ? (_su_llog((iptsec_log), 1, "auth_module.c"
, (const char *)__func__, 247, "auth-module: %s: %s\n", am->
am_db, strerror(err))) : (void)0)
;
248 errno(*__errno_location ()) = err;
249 }
250 }
251 else {
252 retval = auth_htable_resize(am->am_home, am->am_users, 0);
253 }
254
255 ta_end(ta)((((ta).tl[1].t_value) ? (tl_vfree((tagi_t *)((ta).tl[1].t_value
))) : (void)0), (ta).tl[1].t_value = 0, __builtin_va_end((ta)
.ap))
;
256
257 return retval;
258}
259
260/** Destroy (a reference to) an authentication module. */
261void auth_mod_destroy(auth_mod_t *am)
262{
263 su_home_unref(am->am_home);
264}
265
266/** Call scheme-specific destructor function. */
267static void auth_call_scheme_destructor(void *arg)
268{
269 auth_mod_t *am = arg;
270 am->am_scheme->asch_destroy(am);
271}
272
273/** Do-nothing destroy function.
274 *
275 * The auth_destroy_default() is the default member function called by
276 * auth_mod_destroy().
277 */
278void auth_destroy_default(auth_mod_t *am)
279{
280}
281
282/** Create a new reference to authentication module. */
283auth_mod_t *auth_mod_ref(auth_mod_t *am)
284{
285 return (auth_mod_t *)su_home_ref(am->am_home);
286}
287
288/** Destroy a reference to an authentication module. */
289void auth_mod_unref(auth_mod_t *am)
290{
291 su_home_unref(am->am_home);
292}
293
294/** Get authenticatin module name. @NEW_1_12_4. */
295char const *auth_mod_name(auth_mod_t *am)
296{
297 return am ? am->am_scheme->asch_method : "<nil>";
298}
299
300/** Initialize a auth_status_t stucture.
301 *
302 * @retval NULL upon an error
303 * @relates auth_status_t
304 */
305auth_status_t *auth_status_init(void *p, isize_t size)
306{
307 return auth_status_init_with(p, size, 500, auth_internal_server_error);
308}
309
310/** Initialize a auth_status_t stucture.
311 *
312 * @retval NULL upon an error
313 * @relates auth_status_t
314 */
315auth_status_t *auth_status_init_with(void *p,
316 isize_t size,
317 int status,
318 char const *phrase)
319{
320 auth_status_t *as;
321
322 if (!p || size < (sizeof *as))
323 return NULL((void*)0);
324
325 if (size > INT_MAX2147483647) size = INT_MAX2147483647;
326
327 as = memset(p, 0, size);
328 as->as_home->suh_size = (int)size;
329
330 /* su_home_init(as->as_home); */
331
332 as->as_status = status, as->as_phrase = phrase;
333
334 return as;
335}
336
337/** Allocate a new auth_status_t structure. @relates auth_status_t */
338
339auth_status_t *auth_status_new(su_home_t *home)
340{
341 auth_status_t *as = su_home_clone(home, (sizeof *as));
342 if (as) {
343 as->as_status = 500;
344 as->as_phrase = auth_internal_server_error;
345 }
346 return as;
347}
348
349/** Create a new reference to an auth_status_t structure.
350 * @relates auth_status_t
351 */
352auth_status_t *auth_status_ref(auth_status_t *as)
353{
354 return (auth_status_t *)su_home_ref(as->as_home);
355}
356
357/** Destroy (a reference to) an auth_status_t structure. @relates auth_status_t
358 */
359void auth_status_unref(auth_status_t *as)
360{
361 su_home_unref(as->as_home);
362}
363
364/** Authenticate user.
365 *
366 * The function auth_mod_method() invokes scheme-specific authentication
367 * operation where the user's credentials are checked using scheme-specific
368 * method. The authentication result along with an optional challenge header
369 * is stored in the @a as structure.
370 *
371 * @param am pointer to authentication module object [in]
372 * @param as pointer to authentication status structure [in/out]
373 * @param credentials pointer to a header with user's credentials [in]
374 * @param ach pointer to a structure describing challenge [in]
375 *
376 * The @a ach structure defines what kind of response and challenge header
377 * is returned to the user. For example, a server authentication is
378 * implemented with 401 response code and phrase along with WWW-Authenticate
379 * header template in the @a ach structure.
380 *
381 * The auth_mod_method() returns the authentication result in the
382 * #auth_mod_t @a as structure. The @a as->as_status describes the result
383 * as follows:
384 * - <i>as->as_status == 0</i> authentication is successful
385 * - <i>as->as_status == 100</i> authentication is pending
386 * - <i>as->as_status >= 400</i> authentication fails,
387 * return as_status as an error code to client
388 *
389 * When the authentication is left pending, the client must set the
390 * as_callback pointer in @a as structure to an appropriate callback
391 * function. The callback is invoked when the authentication is completed,
392 * either successfully or with an error.
393 *
394 * Note that the authentication module may generate a new challenge each
395 * time authentication is used (e.g., Digest using MD5 algorithm). Such a
396 * challenge header is stored in the @a as->as_response return-value field.
397 *
398 * @note The authentication plugin may use the given reference to @a as, @a
399 * credentials and @a ach structures until the asynchronous authentication
400 * completes. Therefore, they should not be allocated from stack unless
401 * application uses strictly synchronous authentication schemes only (Basic
402 * and Digest).
403 *
404 * @note This function should be called auth_mod_check().
405 */
406void auth_mod_verify(auth_mod_t *am,
407 auth_status_t *as,
408 msg_auth_t *credentials,
409 auth_challenger_t const *ach)
410{
411 char const *wildcard, *host;
412
413 if (!am || !as || !ach)
414 return;
415
416 wildcard = strchr(am->am_realm, '*')(__extension__ (__builtin_constant_p ('*') && !__builtin_constant_p
(am->am_realm) && ('*') == '\0' ? (char *) __rawmemchr
(am->am_realm, '*') : __builtin_strchr (am->am_realm, '*'
)))
;
417
418 host = as->as_domain;
419
420 /* Initialize per-request realm */
421 if (as->as_realm)
422 ;
423 else if (!wildcard) {
424 as->as_realm = am->am_realm;
425 }
426 else if (!host) {
427 return; /* Internal error */
428 }
429 else if (strcmp(am->am_realm, "*")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(am->am_realm) && __builtin_constant_p ("*") &&
(__s1_len = __builtin_strlen (am->am_realm), __s2_len = __builtin_strlen
("*"), (!((size_t)(const void *)((am->am_realm) + 1) - (size_t
)(const void *)(am->am_realm) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)(("*") + 1) - (size_t)(const void *
)("*") == 1) || __s2_len >= 4)) ? __builtin_strcmp (am->
am_realm, "*") : (__builtin_constant_p (am->am_realm) &&
((size_t)(const void *)((am->am_realm) + 1) - (size_t)(const
void *)(am->am_realm) == 1) && (__s1_len = __builtin_strlen
(am->am_realm), __s1_len < 4) ? (__builtin_constant_p (
"*") && ((size_t)(const void *)(("*") + 1) - (size_t)
(const void *)("*") == 1) ? __builtin_strcmp (am->am_realm
, "*") : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) ("*"); int __result = (((const
unsigned char *) (const char *) (am->am_realm))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (am->am_realm)
)[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (am->
am_realm))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (am
->am_realm))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
("*") && ((size_t)(const void *)(("*") + 1) - (size_t
)(const void *)("*") == 1) && (__s2_len = __builtin_strlen
("*"), __s2_len < 4) ? (__builtin_constant_p (am->am_realm
) && ((size_t)(const void *)((am->am_realm) + 1) -
(size_t)(const void *)(am->am_realm) == 1) ? __builtin_strcmp
(am->am_realm, "*") : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (am->
am_realm); int __result = (((const unsigned char *) (const char
*) ("*"))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
"*"))[1] - __s2[1]); if (__s2_len > 1 && __result ==
0) { __result = (((const unsigned char *) (const char *) ("*"
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) ("*"))[
3] - __s2[3]); } } __result; })))) : __builtin_strcmp (am->
am_realm, "*")))); })
== 0) {
430 as->as_realm = host;
431 }
432 else {
433 /* Replace * with hostpart */
434 as->as_realm = su_sprintf(as->as_home, "%.*s%s%s",
435 (int)(wildcard - am->am_realm), am->am_realm,
436 host,
437 wildcard + 1);
438 }
439
440 am->am_scheme->asch_check(am, as, credentials, ach);
441}
442
443/** Make a challenge header.
444 *
445 * This function invokes plugin-specific member function generating a
446 * challenge header. Client uses the challenge header contents when
447 * prompting the user for a username and password then generates its
448 * credential header using the parameters given in the challenge header.
449 *
450 * @param am pointer to authentication module object
451 * @param as pointer to authentication status structure (return-value)
452 * @param ach pointer to a structure describing challenge
453 *
454 * The auth_mod_challenge() returns the challenge header, appropriate
455 * response code and reason phrase in the #auth_status_t structure. The
456 * auth_mod_challenge() is currently always synchronous function.
457 */
458void auth_mod_challenge(auth_mod_t *am,
459 auth_status_t *as,
460 auth_challenger_t const *ach)
461{
462 if (am && as && ach)
463 am->am_scheme->asch_challenge(am, as, ach);
464}
465
466
467/** Cancel asynchronous authentication.
468 *
469 * The auth_mod_cancel() function cancels a pending authentication.
470 * Application can reclaim the authentication status, credential and
471 * challenger objects by using auth_mod_cancel().
472 */
473void auth_mod_cancel(auth_mod_t *am, auth_status_t *as)
474{
475 if (am && as)
476 am->am_scheme->asch_cancel(am, as);
477}
478
479/** Do-nothing cancel function.
480 *
481 * The auth_cancel_default() is the default member function called by
482 * auth_mod_cancel().
483 */
484void auth_cancel_default(auth_mod_t *am, auth_status_t *as)
485{
486}
487
488/* ====================================================================== */
489/* Basic authentication scheme */
490
491static void auth_method_basic_x(auth_mod_t *am,
492 auth_status_t *as,
493 msg_auth_t *au,
494 auth_challenger_t const *ach);
495
496auth_scheme_t auth_scheme_basic[1] =
497 {{
498 "Basic", /* asch_method */
499 sizeof (auth_mod_t), /* asch_size */
500 auth_init_default, /* asch_init */
501 auth_method_basic_x, /* asch_check */
502 auth_challenge_basic, /* asch_challenge */
503 auth_cancel_default, /* asch_cancel */
504 auth_destroy_default /* asch_destroy */
505 }};
506
507/**Authenticate a request with @b Basic authentication.
508 *
509 * This function reads user database before authentication, if needed.
510 */
511static
512void auth_method_basic_x(auth_mod_t *am,
513 auth_status_t *as,
514 msg_auth_t *au,
515 auth_challenger_t const *ach)
516{
517 if (am) {
518 auth_readdb_if_needed(am);
519 auth_method_basic(am, as, au, ach);
520 }
521}
522
523/** Authenticate a request with @b Basic authentication scheme.
524 *
525 */
526void auth_method_basic(auth_mod_t *am,
527 auth_status_t *as,
528 msg_auth_t *au,
529 auth_challenger_t const *ach)
530{
531 char *userpass, buffer[128];
532 size_t n, upsize;
533 char *pass;
534 auth_passwd_t *apw;
535
536 if (!as->as_realm)
537 return;
538
539 userpass = buffer, upsize = sizeof buffer;
540
541 for (au = auth_mod_credentials(au, "Basic", NULL((void*)0));
542 au;
543 au = auth_mod_credentials(au->au_next, "Basic", NULL((void*)0))) {
544 if (!au->au_params)
545 continue;
546 n = base64_d(userpass, upsize - 1, au->au_params[0]);
547 if (n >= upsize) {
548 void *b = realloc(userpass == buffer ? NULL((void*)0) : userpass, upsize = n + 1);
549 if (b == NULL((void*)0))
550 break;
551 base64_d(userpass = b, upsize - 1, au->au_params[0]);
552 }
553 userpass[n] = 0;
554 if (!(pass = strchr(userpass, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(userpass) && (':') == '\0' ? (char *) __rawmemchr (
userpass, ':') : __builtin_strchr (userpass, ':')))
))
555 continue;
556 *pass++ = '\0';
557 SU_DEBUG_5(("auth_method_basic: %s => %s:%s\n",((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 558, "auth_method_basic: %s => %s:%s\n"
, au->au_params[0], userpass, pass)) : (void)0)
558 au->au_params[0], userpass, pass))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 558, "auth_method_basic: %s => %s:%s\n"
, au->au_params[0], userpass, pass)) : (void)0)
;
559
560 if (!(apw = auth_mod_getpass(am, userpass, as->as_realm)))
561 continue;
562 if (strcmp(apw->apw_pass, pass)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(apw->apw_pass) && __builtin_constant_p (pass) &&
(__s1_len = __builtin_strlen (apw->apw_pass), __s2_len = __builtin_strlen
(pass), (!((size_t)(const void *)((apw->apw_pass) + 1) - (
size_t)(const void *)(apw->apw_pass) == 1) || __s1_len >=
4) && (!((size_t)(const void *)((pass) + 1) - (size_t
)(const void *)(pass) == 1) || __s2_len >= 4)) ? __builtin_strcmp
(apw->apw_pass, pass) : (__builtin_constant_p (apw->apw_pass
) && ((size_t)(const void *)((apw->apw_pass) + 1) -
(size_t)(const void *)(apw->apw_pass) == 1) && (__s1_len
= __builtin_strlen (apw->apw_pass), __s1_len < 4) ? (__builtin_constant_p
(pass) && ((size_t)(const void *)((pass) + 1) - (size_t
)(const void *)(pass) == 1) ? __builtin_strcmp (apw->apw_pass
, pass) : (__extension__ ({ const unsigned char *__s2 = (const
unsigned char *) (const char *) (pass); int __result = (((const
unsigned char *) (const char *) (apw->apw_pass))[0] - __s2
[0]); if (__s1_len > 0 && __result == 0) { __result
= (((const unsigned char *) (const char *) (apw->apw_pass
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (apw->
apw_pass))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (apw
->apw_pass))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(pass) && ((size_t)(const void *)((pass) + 1) - (size_t
)(const void *)(pass) == 1) && (__s2_len = __builtin_strlen
(pass), __s2_len < 4) ? (__builtin_constant_p (apw->apw_pass
) && ((size_t)(const void *)((apw->apw_pass) + 1) -
(size_t)(const void *)(apw->apw_pass) == 1) ? __builtin_strcmp
(apw->apw_pass, pass) : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (apw->
apw_pass); int __result = (((const unsigned char *) (const char
*) (pass))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
pass))[1] - __s2[1]); if (__s2_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
pass))[2] - __s2[2]); if (__s2_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (pass
))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp (apw
->apw_pass, pass)))); })
)
563 continue;
564
565 as->as_user = apw->apw_user;
566 as->as_anonymous = apw == am->am_anon_user;
567 as->as_ident = apw->apw_ident;
568 as->as_match = (msg_header_t *)au;
569 as->as_status = 0; /* Successful authentication! */
570
571 break;
572 }
573
574 if (userpass != buffer)
575 free(userpass);
576
577 if (au)
578 return;
579
580 if (auth_allow_check(am, as))
581 auth_challenge_basic(am, as, ach);
582}
583
584/** Construct a challenge header for @b Basic authentication scheme. */
585void auth_challenge_basic(auth_mod_t *am,
586 auth_status_t *as,
587 auth_challenger_t const *ach)
588{
589 as->as_status = ach->ach_status;
590 as->as_phrase = ach->ach_phrase;
591 as->as_response = msg_header_format(as->as_home, ach->ach_header,
592 "Basic realm=\"%s\"", as->as_realm);
593}
594
595/* ====================================================================== */
596/* Digest authentication scheme */
597
598static void auth_method_digest_x(auth_mod_t *am,
599 auth_status_t *as,
600 msg_auth_t *au,
601 auth_challenger_t const *ach);
602
603auth_scheme_t auth_scheme_digest[1] =
604 {{
605 "Digest", /* asch_method */
606 sizeof (auth_mod_t), /* asch_size */
607 auth_init_default, /* asch_init */
608 auth_method_digest_x, /* asch_check */
609 auth_challenge_digest, /* asch_challenge */
610 auth_cancel_default, /* asch_cancel */
611 auth_destroy_default /* asch_destroy */
612 }};
613
614struct nonce {
615 msg_time_t issued;
616 uint32_t count;
617 uint16_t nextnonce;
618 uint8_t digest[6];
619};
620
621#define AUTH_DIGEST_NONCE_LEN(((sizeof (struct nonce) * 4 + 2) / 3) + 1) (BASE64_MINSIZE(sizeof (struct nonce))((sizeof (struct nonce) * 4 + 2) / 3) + 1)
622
623/** Authenticate a request with @b Digest authentication scheme.
624 *
625 * This function reads user database before authentication, if needed.
626 */
627static
628void auth_method_digest_x(auth_mod_t *am,
629 auth_status_t *as,
630 msg_auth_t *au,
631 auth_challenger_t const *ach)
632{
633 if (am) {
634 auth_readdb_if_needed(am);
635 auth_method_digest(am, as, au, ach);
636 }
637}
638
639/** Authenticate a request with @b Digest authentication scheme.
640 */
641void auth_method_digest(auth_mod_t *am,
642 auth_status_t *as,
643 msg_auth_t *au,
644 auth_challenger_t const *ach)
645{
646 as->as_allow = as->as_allow || auth_allow_check(am, as) == 0;
647
648 if (as->as_realm)
649 au = auth_digest_credentials(au, as->as_realm, am->am_opaque);
650 else
651 au = NULL((void*)0);
652
653 if (as->as_allow) {
654 SU_DEBUG_5(("%s: allow unauthenticated %s\n", __func__, as->as_method))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 654, "%s: allow unauthenticated %s\n"
, __func__, as->as_method)) : (void)0)
;
655 as->as_status = 0, as->as_phrase = NULL((void*)0);
656 as->as_match = (msg_header_t *)au;
657 return;
658 }
659
660 if (au) {
661 auth_response_t ar[1] = {{ sizeof(ar) }};
662 auth_digest_response_get(as->as_home, ar, au->au_params);
663 as->as_match = (msg_header_t *)au;
664 auth_check_digest(am, as, ar, ach);
665 }
666 else {
667 /* There was no matching credentials, send challenge */
668 SU_DEBUG_5(("%s: no credentials matched\n", __func__))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 668, "%s: no credentials matched\n"
, __func__)) : (void)0)
;
669 auth_challenge_digest(am, as, ach);
670 }
671}
672
673/** Verify digest authentication */
674void auth_check_digest(auth_mod_t *am,
675 auth_status_t *as,
676 auth_response_t *ar,
677 auth_challenger_t const *ach)
678{
679 char const *a1;
680 auth_hexmd5_t a1buf, response;
681 auth_passwd_t *apw;
682 char const *phrase;
683 msg_time_t now = msg_now();
684
685 if (am == NULL((void*)0) || as == NULL((void*)0) || ar == NULL((void*)0) || ach == NULL((void*)0)) {
686 if (as) {
687 as->as_status = 500, as->as_phrase = "Internal Server Error";
688 as->as_response = NULL((void*)0);
689 }
690 return;
691 }
692
693 phrase = "Bad authorization";
Value stored to 'phrase' is never read
694
695#define PA"Authorization missing " "Authorization missing "
696
697 if ((!ar->ar_username && (phrase = PA"Authorization missing " "username")) ||
698 (!ar->ar_nonce && (phrase = PA"Authorization missing " "nonce")) ||
699 (!ar->ar_uri && (phrase = PA"Authorization missing " "URI")) ||
700 (!ar->ar_response && (phrase = PA"Authorization missing " "response")) ||
701 /* (!ar->ar_opaque && (phrase = PA "opaque")) || */
702 /* Check for qop */
703 (ar->ar_qop &&
704 ((ar->ar_auth &&
705 !su_casematch(ar->ar_qop, "auth") &&
706 !su_casematch(ar->ar_qop, "\"auth\"")) ||
707 (ar->ar_auth_int &&
708 !su_casematch(ar->ar_qop, "auth-int") &&
709 !su_casematch(ar->ar_qop, "\"auth-int\"")))
710 && (phrase = PA"Authorization missing " "has invalid qop"))) {
711 assert(phrase)((phrase) ? (void) (0) : __assert_fail ("phrase", "auth_module.c"
, 711, __PRETTY_FUNCTION__))
;
712 SU_DEBUG_5(("auth_method_digest: 400 %s\n", phrase))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 712, "auth_method_digest: 400 %s\n"
, phrase)) : (void)0)
;
713 as->as_status = 400, as->as_phrase = phrase;
714 as->as_response = NULL((void*)0);
715 return;
716 }
717
718 if (as->as_nonce_issued == 0 /* Already validated nonce */ &&
719 auth_validate_digest_nonce(am, as, ar, now) < 0) {
720 as->as_blacklist = am->am_blacklist;
721 auth_challenge_digest(am, as, ach);
722 return;
723 }
724
725 if (as->as_stale) {
726 auth_challenge_digest(am, as, ach);
727 return;
728 }
729
730 apw = auth_mod_getpass(am, ar->ar_username, ar->ar_realm);
731
732 if (apw && apw->apw_hash)
733 a1 = apw->apw_hash;
734 else if (apw && apw->apw_pass)
735 auth_digest_a1(ar, a1buf, apw->apw_pass), a1 = a1buf;
736 else
737 auth_digest_a1(ar, a1buf, "xyzzy"), a1 = a1buf, apw = NULL((void*)0);
738
739 if (ar->ar_md5sess)
740 auth_digest_a1sess(ar, a1buf, a1), a1 = a1buf;
741
742 auth_digest_response(ar, response, a1,
743 as->as_method, as->as_body, as->as_bodylen);
744
745 if (!apw || strcmp(response, ar->ar_response)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(response) && __builtin_constant_p (ar->ar_response
) && (__s1_len = __builtin_strlen (response), __s2_len
= __builtin_strlen (ar->ar_response), (!((size_t)(const void
*)((response) + 1) - (size_t)(const void *)(response) == 1) ||
__s1_len >= 4) && (!((size_t)(const void *)((ar->
ar_response) + 1) - (size_t)(const void *)(ar->ar_response
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (response, ar
->ar_response) : (__builtin_constant_p (response) &&
((size_t)(const void *)((response) + 1) - (size_t)(const void
*)(response) == 1) && (__s1_len = __builtin_strlen (
response), __s1_len < 4) ? (__builtin_constant_p (ar->ar_response
) && ((size_t)(const void *)((ar->ar_response) + 1
) - (size_t)(const void *)(ar->ar_response) == 1) ? __builtin_strcmp
(response, ar->ar_response) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (ar->
ar_response); int __result = (((const unsigned char *) (const
char *) (response))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (response))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (response))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (response))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(ar->ar_response) && ((size_t)(const void *)((ar->
ar_response) + 1) - (size_t)(const void *)(ar->ar_response
) == 1) && (__s2_len = __builtin_strlen (ar->ar_response
), __s2_len < 4) ? (__builtin_constant_p (response) &&
((size_t)(const void *)((response) + 1) - (size_t)(const void
*)(response) == 1) ? __builtin_strcmp (response, ar->ar_response
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (response); int __result = (((const unsigned
char *) (const char *) (ar->ar_response))[0] - __s2[0]); if
(__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) (ar->ar_response))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (ar->ar_response
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (ar->
ar_response))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(response, ar->ar_response)))); })
) {
746
747 if (am->am_forbidden) {
748 as->as_status = 403, as->as_phrase = "Forbidden";
749 as->as_response = NULL((void*)0);
750 as->as_blacklist = am->am_blacklist;
751 }
752 else {
753 auth_challenge_digest(am, as, ach);
754 as->as_blacklist = am->am_blacklist;
755 }
756 SU_DEBUG_5(("auth_method_digest: response did not match\n" VA_NONE))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 756, "auth_method_digest: response did not match\n"
"%s", "")) : (void)0)
;
757
758 return;
759 }
760
761 assert(apw)((apw) ? (void) (0) : __assert_fail ("apw", "auth_module.c", 761
, __PRETTY_FUNCTION__))
;
762
763 as->as_user = apw->apw_user;
764 as->as_anonymous = apw == am->am_anon_user;
765 as->as_ident = apw->apw_ident;
766
767 if (am->am_nextnonce || am->am_mutual)
768 auth_info_digest(am, as, ach);
769
770 if (am->am_challenge)
771 auth_challenge_digest(am, as, ach);
772
773 SU_DEBUG_7(("auth_method_digest: successful authentication\n" VA_NONE))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 7 ? (_su_llog((iptsec_log), 7, "auth_module.c"
, (const char *)__func__, 773, "auth_method_digest: successful authentication\n"
"%s", "")) : (void)0)
;
774
775 as->as_status = 0; /* Successful authentication! */
776 as->as_phrase = "";
777}
778
779/** Construct a challenge header for @b Digest authentication scheme. */
780void auth_challenge_digest(auth_mod_t *am,
781 auth_status_t *as,
782 auth_challenger_t const *ach)
783{
784 char const *u, *d;
785 char nonce[AUTH_DIGEST_NONCE_LEN(((sizeof (struct nonce) * 4 + 2) / 3) + 1)];
786
787 auth_generate_digest_nonce(am, nonce, sizeof nonce, 0, msg_now());
788
789 u = as->as_uri;
790 d = as->as_pdomain;
791
792 as->as_response =
793 msg_header_format(as->as_home, ach->ach_header,
794 "Digest"
795 " realm=\"%s\","
796 "%s%s%s"
797 "%s%s%s"
798 " nonce=\"%s\","
799 "%s%s%s"
800 "%s" /* stale */
801 " algorithm=%s"
802 "%s%s%s",
803 as->as_realm,
804 u ? " uri=\"" : "", u ? u : "", u ? "\"," : "",
805 d ? " domain=\"" : "", d ? d : "", d ? "\"," : "",
806 nonce,
807 am->am_opaque ? " opaque=\"" : "",
808 am->am_opaque ? am->am_opaque : "",
809 am->am_opaque ? "\"," : "",
810 as->as_stale ? " stale=true," : "",
811 am->am_algorithm,
812 am->am_qop ? ", qop=\"" : "",
813 am->am_qop ? am->am_qop : "",
814 am->am_qop ? "\"" : "");
815
816 if (!as->as_response)
817 as->as_status = 500, as->as_phrase = auth_internal_server_error;
818 else
819 as->as_status = ach->ach_status, as->as_phrase = ach->ach_phrase;
820}
821
822/** Construct a info header for @b Digest authentication scheme. */
823void auth_info_digest(auth_mod_t *am,
824 auth_status_t *as,
825 auth_challenger_t const *ach)
826{
827 if (!ach->ach_info)
828 return;
829
830 if (am->am_nextnonce) {
831 char nonce[AUTH_DIGEST_NONCE_LEN(((sizeof (struct nonce) * 4 + 2) / 3) + 1)];
832
833 auth_generate_digest_nonce(am, nonce, sizeof nonce, 1, msg_now());
834
835 as->as_info =
836 msg_header_format(as->as_home, ach->ach_info, "nextnonce=\"%s\"", nonce);
837 }
838}
839
840
841/* ====================================================================== */
842/* Password database */
843
844su_inlinestatic inline void
845auth_htable_append_local(auth_htable_t *pr, auth_passwd_t *apw);
846
847/** Get an passwd entry for user. */
848auth_passwd_t *auth_mod_getpass(auth_mod_t *am,
849 char const *user,
850 char const *realm)
851{
852 auth_passwd_t *apw, **slot;
853 unsigned hash;
854
855 if (am == NULL((void*)0) || user == NULL((void*)0))
856 return NULL((void*)0);
857
858 hash = msg_hash_string(user);
859
860 for (slot = auth_htable_hash(am->am_users, hash);
861 (apw = *slot);
862 slot = auth_htable_next(am->am_users, slot)) {
863 if (hash != apw->apw_index)
864 continue;
865 if (strcmp(user, apw->apw_user)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(user) && __builtin_constant_p (apw->apw_user) &&
(__s1_len = __builtin_strlen (user), __s2_len = __builtin_strlen
(apw->apw_user), (!((size_t)(const void *)((user) + 1) - (
size_t)(const void *)(user) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((apw->apw_user) + 1) - (size_t)
(const void *)(apw->apw_user) == 1) || __s2_len >= 4)) ?
__builtin_strcmp (user, apw->apw_user) : (__builtin_constant_p
(user) && ((size_t)(const void *)((user) + 1) - (size_t
)(const void *)(user) == 1) && (__s1_len = __builtin_strlen
(user), __s1_len < 4) ? (__builtin_constant_p (apw->apw_user
) && ((size_t)(const void *)((apw->apw_user) + 1) -
(size_t)(const void *)(apw->apw_user) == 1) ? __builtin_strcmp
(user, apw->apw_user) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (apw->apw_user
); int __result = (((const unsigned char *) (const char *) (user
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (user
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (user
))[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (user))
[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (apw
->apw_user) && ((size_t)(const void *)((apw->apw_user
) + 1) - (size_t)(const void *)(apw->apw_user) == 1) &&
(__s2_len = __builtin_strlen (apw->apw_user), __s2_len <
4) ? (__builtin_constant_p (user) && ((size_t)(const
void *)((user) + 1) - (size_t)(const void *)(user) == 1) ? __builtin_strcmp
(user, apw->apw_user) : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (user); int
__result = (((const unsigned char *) (const char *) (apw->
apw_user))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
apw->apw_user))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (apw->apw_user))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (apw->apw_user))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (user, apw->apw_user)))); })
)
866 continue;
867 if (realm && apw->apw_realm[0] && strcmp(realm, apw->apw_realm)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(realm) && __builtin_constant_p (apw->apw_realm) &&
(__s1_len = __builtin_strlen (realm), __s2_len = __builtin_strlen
(apw->apw_realm), (!((size_t)(const void *)((realm) + 1) -
(size_t)(const void *)(realm) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((apw->apw_realm) + 1) - (size_t
)(const void *)(apw->apw_realm) == 1) || __s2_len >= 4)
) ? __builtin_strcmp (realm, apw->apw_realm) : (__builtin_constant_p
(realm) && ((size_t)(const void *)((realm) + 1) - (size_t
)(const void *)(realm) == 1) && (__s1_len = __builtin_strlen
(realm), __s1_len < 4) ? (__builtin_constant_p (apw->apw_realm
) && ((size_t)(const void *)((apw->apw_realm) + 1)
- (size_t)(const void *)(apw->apw_realm) == 1) ? __builtin_strcmp
(realm, apw->apw_realm) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (apw->
apw_realm); int __result = (((const unsigned char *) (const char
*) (realm))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
realm))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
realm))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (realm
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
apw->apw_realm) && ((size_t)(const void *)((apw->
apw_realm) + 1) - (size_t)(const void *)(apw->apw_realm) ==
1) && (__s2_len = __builtin_strlen (apw->apw_realm
), __s2_len < 4) ? (__builtin_constant_p (realm) &&
((size_t)(const void *)((realm) + 1) - (size_t)(const void *
)(realm) == 1) ? __builtin_strcmp (realm, apw->apw_realm) :
(- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (realm); int __result = (((const unsigned
char *) (const char *) (apw->apw_realm))[0] - __s2[0]); if
(__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) (apw->apw_realm))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (apw->apw_realm
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (apw->
apw_realm))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(realm, apw->apw_realm)))); })
)
868 continue;
869 break; /* Found it */
870 }
871
872 return apw;
873}
874
875/** Add a password entry. */
876auth_passwd_t *auth_mod_addpass(auth_mod_t *am,
877 char const *user,
878 char const *realm)
879{
880 auth_passwd_t *apw, **slot;
881 unsigned index;
882
883 if (am == NULL((void*)0) || user == NULL((void*)0))
884 return NULL((void*)0);
885
886 index = msg_hash_string(user);
887
888 for (slot = auth_htable_hash(am->am_users, index);
889 (apw = *slot);
890 slot = auth_htable_next(am->am_users, slot)) {
891 if (index != apw->apw_index)
892 continue;
893 if (strcmp(user, apw->apw_user)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(user) && __builtin_constant_p (apw->apw_user) &&
(__s1_len = __builtin_strlen (user), __s2_len = __builtin_strlen
(apw->apw_user), (!((size_t)(const void *)((user) + 1) - (
size_t)(const void *)(user) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((apw->apw_user) + 1) - (size_t)
(const void *)(apw->apw_user) == 1) || __s2_len >= 4)) ?
__builtin_strcmp (user, apw->apw_user) : (__builtin_constant_p
(user) && ((size_t)(const void *)((user) + 1) - (size_t
)(const void *)(user) == 1) && (__s1_len = __builtin_strlen
(user), __s1_len < 4) ? (__builtin_constant_p (apw->apw_user
) && ((size_t)(const void *)((apw->apw_user) + 1) -
(size_t)(const void *)(apw->apw_user) == 1) ? __builtin_strcmp
(user, apw->apw_user) : (__extension__ ({ const unsigned char
*__s2 = (const unsigned char *) (const char *) (apw->apw_user
); int __result = (((const unsigned char *) (const char *) (user
))[0] - __s2[0]); if (__s1_len > 0 && __result == 0
) { __result = (((const unsigned char *) (const char *) (user
))[1] - __s2[1]); if (__s1_len > 1 && __result == 0
) { __result = (((const unsigned char *) (const char *) (user
))[2] - __s2[2]); if (__s1_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (user))
[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (apw
->apw_user) && ((size_t)(const void *)((apw->apw_user
) + 1) - (size_t)(const void *)(apw->apw_user) == 1) &&
(__s2_len = __builtin_strlen (apw->apw_user), __s2_len <
4) ? (__builtin_constant_p (user) && ((size_t)(const
void *)((user) + 1) - (size_t)(const void *)(user) == 1) ? __builtin_strcmp
(user, apw->apw_user) : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (user); int
__result = (((const unsigned char *) (const char *) (apw->
apw_user))[0] - __s2[0]); if (__s2_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
apw->apw_user))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (apw->apw_user))[2] - __s2[2]); if (__s2_len >
2 && __result == 0) __result = (((const unsigned char
*) (const char *) (apw->apw_user))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (user, apw->apw_user)))); })
)
894 continue;
895 if (realm && strcmp(realm, apw->apw_realm)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(realm) && __builtin_constant_p (apw->apw_realm) &&
(__s1_len = __builtin_strlen (realm), __s2_len = __builtin_strlen
(apw->apw_realm), (!((size_t)(const void *)((realm) + 1) -
(size_t)(const void *)(realm) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((apw->apw_realm) + 1) - (size_t
)(const void *)(apw->apw_realm) == 1) || __s2_len >= 4)
) ? __builtin_strcmp (realm, apw->apw_realm) : (__builtin_constant_p
(realm) && ((size_t)(const void *)((realm) + 1) - (size_t
)(const void *)(realm) == 1) && (__s1_len = __builtin_strlen
(realm), __s1_len < 4) ? (__builtin_constant_p (apw->apw_realm
) && ((size_t)(const void *)((apw->apw_realm) + 1)
- (size_t)(const void *)(apw->apw_realm) == 1) ? __builtin_strcmp
(realm, apw->apw_realm) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (apw->
apw_realm); int __result = (((const unsigned char *) (const char
*) (realm))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
realm))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
realm))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (realm
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
apw->apw_realm) && ((size_t)(const void *)((apw->
apw_realm) + 1) - (size_t)(const void *)(apw->apw_realm) ==
1) && (__s2_len = __builtin_strlen (apw->apw_realm
), __s2_len < 4) ? (__builtin_constant_p (realm) &&
((size_t)(const void *)((realm) + 1) - (size_t)(const void *
)(realm) == 1) ? __builtin_strcmp (realm, apw->apw_realm) :
(- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (realm); int __result = (((const unsigned
char *) (const char *) (apw->apw_realm))[0] - __s2[0]); if
(__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) (apw->apw_realm))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (apw->apw_realm
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (apw->
apw_realm))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(realm, apw->apw_realm)))); })
)
896 continue;
897 break; /* Found it */
898 }
899
900 if (realm == NULL((void*)0))
901 realm = "";
902
903 if (!apw) {
904 size_t ulen = strlen(user) + 1, rlen = strlen(realm) + 1;
905 size_t size = sizeof *apw + ulen + rlen;
906
907 apw = su_alloc(am->am_home, size);
908
909 if (apw) {
910 memset(apw, 0, sizeof *apw);
911 apw->apw_index = index;
912 apw->apw_user = memcpy((char *)(apw + 1), user, ulen);
913 apw->apw_realm = memcpy((char *)apw->apw_user + ulen, realm, rlen);
914
915 if (!auth_htable_is_full(am->am_users)) {
916 *slot = apw, am->am_users->aht_used++;
917 } else {
918 if (auth_htable_resize(am->am_home, am->am_users, 0) < 0)
919 su_free(am->am_home, apw), apw = NULL((void*)0);
920 else
921 auth_htable_append(am->am_users, apw);
922 }
923 }
924 }
925
926 return apw;
927}
928
929static ssize_t readfile(su_home_t *, FILE *,
930 void **contents, int add_trailing_lf);
931static int auth_readdb_internal(auth_mod_t *am, int always);
932
933/** Read authentication database */
934int auth_readdb(auth_mod_t *am)
935{
936 return auth_readdb_internal(am, 1);
937}
938
939/** Read authentication database only when needed */
940int auth_readdb_if_needed(auth_mod_t *am)
941{
942 struct stat st[1];
943
944 if (!am->am_stat || !am->am_db)
945 return 0;
946
947 if (stat(am->am_db, st) != -1 &&
948 st->st_dev == am->am_stat->st_dev &&
949 st->st_ino == am->am_stat->st_ino &&
950 st->st_size == am->am_stat->st_size &&
951 memcmp(&st->st_mtimest_mtim.tv_sec, &am->am_stat->st_mtimest_mtim.tv_sec,
952 (sizeof st->st_mtimest_mtim.tv_sec)) == 0)
953 /* Nothing has changed or passwd file is removed */
954 return 0;
955
956 return auth_readdb_internal(am, 0);
957}
958
959#if HAVE_FLOCK1
960#include <sys/file.h>
961#endif
962
963/* This is just a magic value */
964#define auth_apw_local((void *)(intptr_t)auth_readdb_internal) ((void *)(intptr_t)auth_readdb_internal)
965
966/** Read authentication database */
967static
968int auth_readdb_internal(auth_mod_t *am, int always)
969{
970 FILE *f;
971 char *data, *s;
972 size_t len, i, n, N;
973 ssize_t slen;
974 auth_passwd_t *apw;
975
976 if (!am->am_stat)
977 am->am_stat = su_zalloc(am->am_home, sizeof (*am->am_stat));
978
979 f = fopen(am->am_db, "rb");
980
981 if (f) {
982 void *buffer = NULL((void*)0);
983 auth_passwd_t *fresh = NULL((void*)0);
984
985#if HAVE_FLOCK1
986 int locked;
987
988 /* Obtain shared lock on the database file */
989 if (flock(fileno(f), LOCK_SH1 | (always ? 0 : LOCK_NB4)) == 0) {
990 locked = 1;
991 } else {
992 locked = 0;
993
994 if (errno(*__errno_location ()) == ENOLCK37) {
995 ;
996 }
997 else if (errno(*__errno_location ()) == EWOULDBLOCK11) {
998 SU_DEBUG_3(("auth(%s): user file \"%s\" is busy, trying again later\n",((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 3 ? (_su_llog((iptsec_log), 3, "auth_module.c"
, (const char *)__func__, 999, "auth(%s): user file \"%s\" is busy, trying again later\n"
, am->am_scheme->asch_method, am->am_db)) : (void)0)
999 am->am_scheme->asch_method, am->am_db))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 3 ? (_su_llog((iptsec_log), 3, "auth_module.c"
, (const char *)__func__, 999, "auth(%s): user file \"%s\" is busy, trying again later\n"
, am->am_scheme->asch_method, am->am_db)) : (void)0)
;
1000 fclose(f);
1001 return always ? -1 : 0;
1002 }
1003 else {
1004 SU_DEBUG_3(("auth(%s): flock(\"%s\"): %s (%u)\n",((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 3 ? (_su_llog((iptsec_log), 3, "auth_module.c"
, (const char *)__func__, 1006, "auth(%s): flock(\"%s\"): %s (%u)\n"
, am->am_scheme->asch_method, am->am_db, strerror((*
__errno_location ())), (*__errno_location ()))) : (void)0)
1005 am->am_scheme->asch_method, am->am_db,((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 3 ? (_su_llog((iptsec_log), 3, "auth_module.c"
, (const char *)__func__, 1006, "auth(%s): flock(\"%s\"): %s (%u)\n"
, am->am_scheme->asch_method, am->am_db, strerror((*
__errno_location ())), (*__errno_location ()))) : (void)0)
1006 strerror(errno), errno))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 3 ? (_su_llog((iptsec_log), 3, "auth_module.c"
, (const char *)__func__, 1006, "auth(%s): flock(\"%s\"): %s (%u)\n"
, am->am_scheme->asch_method, am->am_db, strerror((*
__errno_location ())), (*__errno_location ()))) : (void)0)
;
1007 fclose(f);
1008 return always ? -1 : 0;
1009 }
1010 }
1011#endif
1012 if (am->am_stat)
1013 stat(am->am_db, am->am_stat); /* too bad if this fails */
1014
1015 slen = readfile(am->am_home, f, &buffer, 1);
1016
1017#if HAVE_FLOCK1
1018 /* Release shared lock on the database file */
1019 if (locked && flock(fileno(f), LOCK_UN8) == -1) {
1020 SU_DEBUG_0(("auth(%s): un-flock(\"%s\"): %s (%u)\n",((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 0 ? (_su_llog((iptsec_log), 0, "auth_module.c"
, (const char *)__func__, 1021, "auth(%s): un-flock(\"%s\"): %s (%u)\n"
, am->am_scheme->asch_method, am->am_db, strerror((*
__errno_location ())), (*__errno_location ()))) : (void)0)
1021 am->am_scheme->asch_method, am->am_db, strerror(errno), errno))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 0 ? (_su_llog((iptsec_log), 0, "auth_module.c"
, (const char *)__func__, 1021, "auth(%s): un-flock(\"%s\"): %s (%u)\n"
, am->am_scheme->asch_method, am->am_db, strerror((*
__errno_location ())), (*__errno_location ()))) : (void)0)
;
1022 fclose(f);
1023 return -1;
1024 }
1025#endif
1026
1027 fclose(f);
1028
1029 if (slen < 0)
1030 return -1;
1031 len = (size_t)slen;
1032
1033 /* Count number of entries in new buffer */
1034 for (i = am->am_anonymous, s = data = buffer;
1035 s < data + len;
1036 s += n + strspn(s + n, "\r\n")__extension__ ({ char __a0, __a1, __a2; (__builtin_constant_p
("\r\n") && ((size_t)(const void *)(("\r\n") + 1) - (
size_t)(const void *)("\r\n") == 1) ? ((__builtin_constant_p (
s + n) && ((size_t)(const void *)((s + n) + 1) - (size_t
)(const void *)(s + n) == 1)) ? __builtin_strspn (s + n, "\r\n"
) : ((__a0 = ((const char *) ("\r\n"))[0], __a0 == '\0') ? ((
void) (s + n), (size_t) 0) : ((__a1 = ((const char *) ("\r\n"
))[1], __a1 == '\0') ? __strspn_c1 (s + n, __a0) : ((__a2 = (
(const char *) ("\r\n"))[2], __a2 == '\0') ? __strspn_c2 (s +
n, __a0, __a1) : (((const char *) ("\r\n"))[3] == '\0' ? __strspn_c3
(s + n, __a0, __a1, __a2) : __builtin_strspn (s + n, "\r\n")
))))) : __builtin_strspn (s + n, "\r\n")); })
) {
1037 n = strcspn(s, "\r\n")__extension__ ({ char __r0, __r1, __r2; (__builtin_constant_p
("\r\n") && ((size_t)(const void *)(("\r\n") + 1) - (
size_t)(const void *)("\r\n") == 1) ? ((__builtin_constant_p (
s) && ((size_t)(const void *)((s) + 1) - (size_t)(const
void *)(s) == 1)) ? __builtin_strcspn (s, "\r\n") : ((__r0 =
((const char *) ("\r\n"))[0], __r0 == '\0') ? strlen (s) : (
(__r1 = ((const char *) ("\r\n"))[1], __r1 == '\0') ? __strcspn_c1
(s, __r0) : ((__r2 = ((const char *) ("\r\n"))[2], __r2 == '\0'
) ? __strcspn_c2 (s, __r0, __r1) : (((const char *) ("\r\n"))
[3] == '\0' ? __strcspn_c3 (s, __r0, __r1, __r2) : __builtin_strcspn
(s, "\r\n")))))) : __builtin_strcspn (s, "\r\n")); })
;
1038 if (*s != '#' && *s != '\n' && *s != '\r')
1039 i++;
1040 }
1041
1042 N = i, i = 0;
1043
1044 if (N > 0) {
1045 size_t size = (N * 5 + 3) / 4;
1046 if (auth_htable_resize(am->am_home, am->am_users, size) < 0 ||
1047 !(fresh = su_zalloc(am->am_home, sizeof(*fresh) * N))) {
1048 su_free(am->am_home, buffer);
1049 return -1;
1050 }
1051 }
1052
1053 if (am->am_anonymous) {
1054 assert(i < N)((i < N) ? (void) (0) : __assert_fail ("i < N", "auth_module.c"
, 1054, __PRETTY_FUNCTION__))
;
1055
1056 apw = fresh + i++;
1057
1058 apw->apw_index = msg_hash_string("anonymous");
1059 apw->apw_user = "anonymous";
1060 apw->apw_pass = "";
1061 apw->apw_realm = "";
1062
1063 am->am_anon_user = apw;
1064
1065 if (auth_htable_is_full(am->am_users))
1066 auth_htable_resize(am->am_home, am->am_users, 0);
1067
1068 auth_htable_append_local(am->am_users, apw);
1069 }
1070
1071 apw = NULL((void*)0);
1072
1073 for (data = buffer, s = data;
1074 s < data + len && i < N;
1075 s += n + strspn(s + n, "\r\n")__extension__ ({ char __a0, __a1, __a2; (__builtin_constant_p
("\r\n") && ((size_t)(const void *)(("\r\n") + 1) - (
size_t)(const void *)("\r\n") == 1) ? ((__builtin_constant_p (
s + n) && ((size_t)(const void *)((s + n) + 1) - (size_t
)(const void *)(s + n) == 1)) ? __builtin_strspn (s + n, "\r\n"
) : ((__a0 = ((const char *) ("\r\n"))[0], __a0 == '\0') ? ((
void) (s + n), (size_t) 0) : ((__a1 = ((const char *) ("\r\n"
))[1], __a1 == '\0') ? __strspn_c1 (s + n, __a0) : ((__a2 = (
(const char *) ("\r\n"))[2], __a2 == '\0') ? __strspn_c2 (s +
n, __a0, __a1) : (((const char *) ("\r\n"))[3] == '\0' ? __strspn_c3
(s + n, __a0, __a1, __a2) : __builtin_strspn (s + n, "\r\n")
))))) : __builtin_strspn (s + n, "\r\n")); })
) {
1076 char *user, *pass, *realm, *ident;
1077
1078 n = strcspn(s, "\r\n")__extension__ ({ char __r0, __r1, __r2; (__builtin_constant_p
("\r\n") && ((size_t)(const void *)(("\r\n") + 1) - (
size_t)(const void *)("\r\n") == 1) ? ((__builtin_constant_p (
s) && ((size_t)(const void *)((s) + 1) - (size_t)(const
void *)(s) == 1)) ? __builtin_strcspn (s, "\r\n") : ((__r0 =
((const char *) ("\r\n"))[0], __r0 == '\0') ? strlen (s) : (
(__r1 = ((const char *) ("\r\n"))[1], __r1 == '\0') ? __strcspn_c1
(s, __r0) : ((__r2 = ((const char *) ("\r\n"))[2], __r2 == '\0'
) ? __strcspn_c2 (s, __r0, __r1) : (((const char *) ("\r\n"))
[3] == '\0' ? __strcspn_c3 (s, __r0, __r1, __r2) : __builtin_strcspn
(s, "\r\n")))))) : __builtin_strcspn (s, "\r\n")); })
;
1079 if (*s == '#')
1080 continue;
1081
1082 user = s;
1083 s[n++] = '\0';
1084 if (!(pass = strchr(user, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(user) && (':') == '\0' ? (char *) __rawmemchr (user
, ':') : __builtin_strchr (user, ':')))
))
1085 continue;
1086
1087 *pass++ = '\0';
1088 if (!*pass || !*user)
1089 continue;
1090
1091 if ((realm = strchr(pass, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(pass) && (':') == '\0' ? (char *) __rawmemchr (pass
, ':') : __builtin_strchr (pass, ':')))
))
1092 *realm++ = '\0';
1093 else
1094 realm = "";
1095
1096 if ((ident = strchr(realm, ':')(__extension__ (__builtin_constant_p (':') && !__builtin_constant_p
(realm) && (':') == '\0' ? (char *) __rawmemchr (realm
, ':') : __builtin_strchr (realm, ':')))
))
1097 *ident++ = '\0';
1098 else
1099 ident = "";
1100
1101 apw = fresh + i++;
1102
1103 apw->apw_index = msg_hash_string(user);
1104 apw->apw_user = user;
1105 apw->apw_ident = ident;
1106
1107 /* Check for htdigest format */
1108 if (span_hexdigit(realm) == 32 && realm[32] == '\0') {
1109 apw->apw_realm = pass;
1110 apw->apw_hash = realm;
1111 } else {
1112 apw->apw_pass = pass;
1113 apw->apw_realm = realm;
1114 }
1115
1116 if (auth_htable_is_full(am->am_users))
1117 auth_htable_resize(am->am_home, am->am_users, 0);
1118
1119 auth_htable_append_local(am->am_users, apw);
1120 }
1121
1122 assert(i <= N)((i <= N) ? (void) (0) : __assert_fail ("i <= N", "auth_module.c"
, 1122, __PRETTY_FUNCTION__))
;
1123 N = i;
1124
1125 /* Remove from hash those entries that were read from old passwd file */
1126 for (i = 0; i < am->am_local_count; i++) {
1127 if (am->am_locals[i].apw_type == auth_apw_local((void *)(intptr_t)auth_readdb_internal))
1128 auth_htable_remove(am->am_users, &am->am_locals[i]);
1129 }
1130
1131 if (am->am_locals)
1132 su_free(am->am_home, am->am_locals); /* Free old entries */
1133 if (am->am_buffer)
1134 su_free(am->am_home, am->am_buffer); /* Free old passwd file contents */
1135
1136 SU_DEBUG_5(("auth(%s): read %u entries from \"%s\"\n",((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 1137, "auth(%s): read %u entries from \"%s\"\n"
, am->am_scheme->asch_method, (unsigned)N, am->am_db
)) : (void)0)
1137 am->am_scheme->asch_method, (unsigned)N, am->am_db))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 1137, "auth(%s): read %u entries from \"%s\"\n"
, am->am_scheme->asch_method, (unsigned)N, am->am_db
)) : (void)0)
;
1138
1139 am->am_locals = fresh;
1140 am->am_local_count = N;
1141 am->am_buffer = buffer;
1142
1143 return 0;
1144 }
1145
1146 return -1;
1147}
1148
1149/** Append to hash, remove existing local user */
1150su_inlinestatic inline void
1151auth_htable_append_local(auth_htable_t *aht, auth_passwd_t *apw)
1152{
1153 auth_passwd_t **slot;
1154
1155 apw->apw_type = auth_apw_local((void *)(intptr_t)auth_readdb_internal);
1156
1157 /* Append to hash */
1158 for (slot = auth_htable_hash(aht, apw->apw_index);
1159 *slot;
1160 slot = auth_htable_next(aht, slot)) {
1161 if (strcmp((*slot)->apw_user, apw->apw_user)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
((*slot)->apw_user) && __builtin_constant_p (apw->
apw_user) && (__s1_len = __builtin_strlen ((*slot)->
apw_user), __s2_len = __builtin_strlen (apw->apw_user), (!
((size_t)(const void *)(((*slot)->apw_user) + 1) - (size_t
)(const void *)((*slot)->apw_user) == 1) || __s1_len >=
4) && (!((size_t)(const void *)((apw->apw_user) +
1) - (size_t)(const void *)(apw->apw_user) == 1) || __s2_len
>= 4)) ? __builtin_strcmp ((*slot)->apw_user, apw->
apw_user) : (__builtin_constant_p ((*slot)->apw_user) &&
((size_t)(const void *)(((*slot)->apw_user) + 1) - (size_t
)(const void *)((*slot)->apw_user) == 1) && (__s1_len
= __builtin_strlen ((*slot)->apw_user), __s1_len < 4) ?
(__builtin_constant_p (apw->apw_user) && ((size_t
)(const void *)((apw->apw_user) + 1) - (size_t)(const void
*)(apw->apw_user) == 1) ? __builtin_strcmp ((*slot)->apw_user
, apw->apw_user) : (__extension__ ({ const unsigned char *
__s2 = (const unsigned char *) (const char *) (apw->apw_user
); int __result = (((const unsigned char *) (const char *) ((
*slot)->apw_user))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ((*slot)->apw_user))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) ((*slot)->apw_user))[2] - __s2[2]); if (
__s1_len > 2 && __result == 0) __result = (((const
unsigned char *) (const char *) ((*slot)->apw_user))[3] -
__s2[3]); } } __result; }))) : (__builtin_constant_p (apw->
apw_user) && ((size_t)(const void *)((apw->apw_user
) + 1) - (size_t)(const void *)(apw->apw_user) == 1) &&
(__s2_len = __builtin_strlen (apw->apw_user), __s2_len <
4) ? (__builtin_constant_p ((*slot)->apw_user) &&
((size_t)(const void *)(((*slot)->apw_user) + 1) - (size_t
)(const void *)((*slot)->apw_user) == 1) ? __builtin_strcmp
((*slot)->apw_user, apw->apw_user) : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ((*slot)->apw_user); int __result = (((const unsigned
char *) (const char *) (apw->apw_user))[0] - __s2[0]); if
(__s2_len > 0 && __result == 0) { __result = (((const
unsigned char *) (const char *) (apw->apw_user))[1] - __s2
[1]); if (__s2_len > 1 && __result == 0) { __result
= (((const unsigned char *) (const char *) (apw->apw_user
))[2] - __s2[2]); if (__s2_len > 2 && __result == 0
) __result = (((const unsigned char *) (const char *) (apw->
apw_user))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
((*slot)->apw_user, apw->apw_user)))); })
== 0) {
1162 if ((*slot)->apw_type == auth_apw_local((void *)(intptr_t)auth_readdb_internal)) {
1163 (*slot)->apw_type = NULL((void*)0);
1164 assert(aht->aht_used > 0)((aht->aht_used > 0) ? (void) (0) : __assert_fail ("aht->aht_used > 0"
, "auth_module.c", 1164, __PRETTY_FUNCTION__))
; aht->aht_used--;
1165 apw->apw_extended = (*slot)->apw_extended;
1166 *slot = NULL((void*)0);
1167 break;
1168 }
1169 else {
1170 /* We insert local before external entry */
1171 auth_passwd_t *swap = apw;
1172 apw = *slot;
1173 *slot = swap;
1174 }
1175 }
1176 }
1177
1178 aht->aht_used++; assert(aht->aht_used <= aht->aht_size)((aht->aht_used <= aht->aht_size) ? (void) (0) : __assert_fail
("aht->aht_used <= aht->aht_size", "auth_module.c",
1178, __PRETTY_FUNCTION__))
;
1179
1180 *slot = apw;
1181}
1182
1183static
1184ssize_t readfile(su_home_t *home,
1185 FILE *f,
1186 void **contents,
1187 int add_trailing_lf)
1188{
1189 /* Read in whole (binary!) file */
1190 char *buffer = NULL((void*)0);
1191 long size;
1192 size_t len;
1193
1194 /* Read whole file in */
1195 if (fseek(f, 0, SEEK_END2) < 0 ||
1196 (size = ftell(f)) < 0 ||
1197 fseek(f, 0, SEEK_SET0) < 0 ||
1198 (long)(len = (size_t)size) != size ||
1199 size + 2 > SSIZE_MAX9223372036854775807L) {
1200 SU_DEBUG_1(("%s: unable to determine file size (%s)\n",((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 1 ? (_su_llog((iptsec_log), 1, "auth_module.c"
, (const char *)__func__, 1201, "%s: unable to determine file size (%s)\n"
, __func__, strerror((*__errno_location ())))) : (void)0)
1201 __func__, strerror(errno)))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 1 ? (_su_llog((iptsec_log), 1, "auth_module.c"
, (const char *)__func__, 1201, "%s: unable to determine file size (%s)\n"
, __func__, strerror((*__errno_location ())))) : (void)0)
;
1202 return -1;
1203 }
1204
1205 if (!(buffer = su_alloc(home, len + 2)) ||
1206 fread(buffer, 1, len, f) != len) {
1207 SU_DEBUG_1(("%s: unable to read file (%s)\n", __func__, strerror(errno)))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 1 ? (_su_llog((iptsec_log), 1, "auth_module.c"
, (const char *)__func__, 1207, "%s: unable to read file (%s)\n"
, __func__, strerror((*__errno_location ())))) : (void)0)
;
1208 if (buffer)
1209 su_free(home, buffer);
1210 return -1;
1211 }
1212
1213 if (add_trailing_lf) {
1214 /* Make sure that the buffer has trailing newline */
1215 if (len == 0 || buffer[len - 1] != '\n')
1216 buffer[len++] = '\n';
1217 }
1218
1219 buffer[len] = '\0';
1220 *contents = buffer;
1221
1222 return (ssize_t)len;
1223}
1224
1225/* ====================================================================== */
1226/* Helper functions */
1227
1228/** Check if request method is on always-allowed list.
1229 *
1230 * @return 0 if allowed
1231 * @return 1 otherwise
1232 */
1233int auth_allow_check(auth_mod_t *am, auth_status_t *as)
1234{
1235 char const *method = as->as_method;
1236 int i;
1237
1238 if (method && strcmp(method, "ACK")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(method) && __builtin_constant_p ("ACK") && (
__s1_len = __builtin_strlen (method), __s2_len = __builtin_strlen
("ACK"), (!((size_t)(const void *)((method) + 1) - (size_t)(
const void *)(method) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)(("ACK") + 1) - (size_t)(const void *
)("ACK") == 1) || __s2_len >= 4)) ? __builtin_strcmp (method
, "ACK") : (__builtin_constant_p (method) && ((size_t
)(const void *)((method) + 1) - (size_t)(const void *)(method
) == 1) && (__s1_len = __builtin_strlen (method), __s1_len
< 4) ? (__builtin_constant_p ("ACK") && ((size_t)
(const void *)(("ACK") + 1) - (size_t)(const void *)("ACK") ==
1) ? __builtin_strcmp (method, "ACK") : (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
("ACK"); int __result = (((const unsigned char *) (const char
*) (method))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
method))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
method))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (method
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
"ACK") && ((size_t)(const void *)(("ACK") + 1) - (size_t
)(const void *)("ACK") == 1) && (__s2_len = __builtin_strlen
("ACK"), __s2_len < 4) ? (__builtin_constant_p (method) &&
((size_t)(const void *)((method) + 1) - (size_t)(const void *
)(method) == 1) ? __builtin_strcmp (method, "ACK") : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (method); int __result = (((const unsigned char *) (
const char *) ("ACK"))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("ACK"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("ACK"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ("ACK"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(method, "ACK")))); })
== 0) /* Hack */
1239 return as->as_status = 0;
1240
1241 if (!method || !am->am_allow)
1242 return 1;
1243
1244 if (am->am_allow[0] && strcmp(am->am_allow[0], "*")__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(am->am_allow[0]) && __builtin_constant_p ("*") &&
(__s1_len = __builtin_strlen (am->am_allow[0]), __s2_len =
__builtin_strlen ("*"), (!((size_t)(const void *)((am->am_allow
[0]) + 1) - (size_t)(const void *)(am->am_allow[0]) == 1) ||
__s1_len >= 4) && (!((size_t)(const void *)(("*")
+ 1) - (size_t)(const void *)("*") == 1) || __s2_len >= 4
)) ? __builtin_strcmp (am->am_allow[0], "*") : (__builtin_constant_p
(am->am_allow[0]) && ((size_t)(const void *)((am->
am_allow[0]) + 1) - (size_t)(const void *)(am->am_allow[0]
) == 1) && (__s1_len = __builtin_strlen (am->am_allow
[0]), __s1_len < 4) ? (__builtin_constant_p ("*") &&
((size_t)(const void *)(("*") + 1) - (size_t)(const void *)(
"*") == 1) ? __builtin_strcmp (am->am_allow[0], "*") : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) ("*"); int __result = (((const unsigned char *) (const
char *) (am->am_allow[0]))[0] - __s2[0]); if (__s1_len >
0 && __result == 0) { __result = (((const unsigned char
*) (const char *) (am->am_allow[0]))[1] - __s2[1]); if (__s1_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (am->am_allow[0]))[2] - __s2[2]); if
(__s1_len > 2 && __result == 0) __result = (((const
unsigned char *) (const char *) (am->am_allow[0]))[3] - __s2
[3]); } } __result; }))) : (__builtin_constant_p ("*") &&
((size_t)(const void *)(("*") + 1) - (size_t)(const void *)(
"*") == 1) && (__s2_len = __builtin_strlen ("*"), __s2_len
< 4) ? (__builtin_constant_p (am->am_allow[0]) &&
((size_t)(const void *)((am->am_allow[0]) + 1) - (size_t)
(const void *)(am->am_allow[0]) == 1) ? __builtin_strcmp (
am->am_allow[0], "*") : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (am->
am_allow[0]); int __result = (((const unsigned char *) (const
char *) ("*"))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("*"))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) ("*"))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) ("*"))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(am->am_allow[0], "*")))); })
== 0)
1245 return as->as_status = 0;
1246
1247 for (i = 0; am->am_allow[i]; i++)
1248 if (strcmp(am->am_allow[i], method)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(am->am_allow[i]) && __builtin_constant_p (method
) && (__s1_len = __builtin_strlen (am->am_allow[i]
), __s2_len = __builtin_strlen (method), (!((size_t)(const void
*)((am->am_allow[i]) + 1) - (size_t)(const void *)(am->
am_allow[i]) == 1) || __s1_len >= 4) && (!((size_t
)(const void *)((method) + 1) - (size_t)(const void *)(method
) == 1) || __s2_len >= 4)) ? __builtin_strcmp (am->am_allow
[i], method) : (__builtin_constant_p (am->am_allow[i]) &&
((size_t)(const void *)((am->am_allow[i]) + 1) - (size_t)
(const void *)(am->am_allow[i]) == 1) && (__s1_len
= __builtin_strlen (am->am_allow[i]), __s1_len < 4) ? (
__builtin_constant_p (method) && ((size_t)(const void
*)((method) + 1) - (size_t)(const void *)(method) == 1) ? __builtin_strcmp
(am->am_allow[i], method) : (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (method)
; int __result = (((const unsigned char *) (const char *) (am
->am_allow[i]))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (am->am_allow[i]))[1] - __s2[1]); if (__s1_len >
1 && __result == 0) { __result = (((const unsigned char
*) (const char *) (am->am_allow[i]))[2] - __s2[2]); if (__s1_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (am->am_allow[i]))[3] - __s2[3]); }
} __result; }))) : (__builtin_constant_p (method) &&
((size_t)(const void *)((method) + 1) - (size_t)(const void *
)(method) == 1) && (__s2_len = __builtin_strlen (method
), __s2_len < 4) ? (__builtin_constant_p (am->am_allow[
i]) && ((size_t)(const void *)((am->am_allow[i]) +
1) - (size_t)(const void *)(am->am_allow[i]) == 1) ? __builtin_strcmp
(am->am_allow[i], method) : (- (__extension__ ({ const unsigned
char *__s2 = (const unsigned char *) (const char *) (am->
am_allow[i]); int __result = (((const unsigned char *) (const
char *) (method))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (method))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (method))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (method))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(am->am_allow[i], method)))); })
== 0)
1249 return as->as_status = 0;
1250
1251 return 1;
1252}
1253
1254/** Find a credential header with matching scheme and realm. */
1255msg_auth_t *auth_mod_credentials(msg_auth_t *auth,
1256 char const *scheme,
1257 char const *realm)
1258{
1259 char const *arealm;
1260
1261 for (;auth; auth = auth->au_next) {
1262 if (!su_casematch(auth->au_scheme, scheme))
1263 continue;
1264
1265 if (!realm)
1266 return auth;
1267
1268 arealm = msg_header_find_param(auth->au_common, "realm=");
1269
1270 if (!arealm)
1271 continue;
1272
1273 if (arealm[0] == '"') {
1274 /* Compare quoted arealm with unquoted realm */
1275 int i, j;
1276 for (i = 1, j = 0; arealm[i] != 0; i++, j++) {
1277 if (arealm[i] == '"' && realm[j] == 0)
1278 return auth;
1279
1280 if (arealm[i] == '\\' && arealm[i + 1] != '\0')
1281 i++;
1282
1283 if (arealm[i] != realm[j])
1284 break;
1285 }
1286 } else {
1287 if (strcmp(arealm, realm)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(arealm) && __builtin_constant_p (realm) && (
__s1_len = __builtin_strlen (arealm), __s2_len = __builtin_strlen
(realm), (!((size_t)(const void *)((arealm) + 1) - (size_t)(
const void *)(arealm) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((realm) + 1) - (size_t)(const void *
)(realm) == 1) || __s2_len >= 4)) ? __builtin_strcmp (arealm
, realm) : (__builtin_constant_p (arealm) && ((size_t
)(const void *)((arealm) + 1) - (size_t)(const void *)(arealm
) == 1) && (__s1_len = __builtin_strlen (arealm), __s1_len
< 4) ? (__builtin_constant_p (realm) && ((size_t)
(const void *)((realm) + 1) - (size_t)(const void *)(realm) ==
1) ? __builtin_strcmp (arealm, realm) : (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(realm); int __result = (((const unsigned char *) (const char
*) (arealm))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
arealm))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
arealm))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (arealm
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
realm) && ((size_t)(const void *)((realm) + 1) - (size_t
)(const void *)(realm) == 1) && (__s2_len = __builtin_strlen
(realm), __s2_len < 4) ? (__builtin_constant_p (arealm) &&
((size_t)(const void *)((arealm) + 1) - (size_t)(const void *
)(arealm) == 1) ? __builtin_strcmp (arealm, realm) : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (arealm); int __result = (((const unsigned char *) (
const char *) (realm))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (realm))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (realm))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (realm))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(arealm, realm)))); })
== 0)
1288 return auth;
1289 }
1290 }
1291
1292 return NULL((void*)0);
1293}
1294
1295/** Find a Digest credential header with matching realm and opaque. */
1296msg_auth_t *auth_digest_credentials(msg_auth_t *auth,
1297 char const *realm,
1298 char const *opaque)
1299{
1300 char const *arealm, *aopaque;
1301
1302 for (;auth; auth = auth->au_next) {
1303 if (!su_casematch(auth->au_scheme, "Digest"))
1304 continue;
1305
1306 if (realm) {
1307 int cmp = 1;
1308
1309 arealm = msg_header_find_param(auth->au_common, "realm=");
1310 if (!arealm)
1311 continue;
1312
1313 if (arealm[0] == '"') {
1314 /* Compare quoted arealm with unquoted realm */
1315 int i, j;
1316 for (i = 1, j = 0, cmp = 1; arealm[i] != 0; i++, j++) {
1317 if (arealm[i] == '"' && realm[j] == 0) {
1318 cmp = 0;
1319 break;
1320 }
1321
1322 if (arealm[i] == '\\' && arealm[i + 1] != '\0')
1323 i++;
1324
1325 if (arealm[i] != realm[j])
1326 break;
1327 }
1328 }
1329 else {
1330 cmp = strcmp(arealm, realm)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(arealm) && __builtin_constant_p (realm) && (
__s1_len = __builtin_strlen (arealm), __s2_len = __builtin_strlen
(realm), (!((size_t)(const void *)((arealm) + 1) - (size_t)(
const void *)(arealm) == 1) || __s1_len >= 4) && (
!((size_t)(const void *)((realm) + 1) - (size_t)(const void *
)(realm) == 1) || __s2_len >= 4)) ? __builtin_strcmp (arealm
, realm) : (__builtin_constant_p (arealm) && ((size_t
)(const void *)((arealm) + 1) - (size_t)(const void *)(arealm
) == 1) && (__s1_len = __builtin_strlen (arealm), __s1_len
< 4) ? (__builtin_constant_p (realm) && ((size_t)
(const void *)((realm) + 1) - (size_t)(const void *)(realm) ==
1) ? __builtin_strcmp (arealm, realm) : (__extension__ ({ const
unsigned char *__s2 = (const unsigned char *) (const char *)
(realm); int __result = (((const unsigned char *) (const char
*) (arealm))[0] - __s2[0]); if (__s1_len > 0 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
arealm))[1] - __s2[1]); if (__s1_len > 1 && __result
== 0) { __result = (((const unsigned char *) (const char *) (
arealm))[2] - __s2[2]); if (__s1_len > 2 && __result
== 0) __result = (((const unsigned char *) (const char *) (arealm
))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (
realm) && ((size_t)(const void *)((realm) + 1) - (size_t
)(const void *)(realm) == 1) && (__s2_len = __builtin_strlen
(realm), __s2_len < 4) ? (__builtin_constant_p (arealm) &&
((size_t)(const void *)((arealm) + 1) - (size_t)(const void *
)(arealm) == 1) ? __builtin_strcmp (arealm, realm) : (- (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (arealm); int __result = (((const unsigned char *) (
const char *) (realm))[0] - __s2[0]); if (__s2_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (realm))[1] - __s2[1]); if (__s2_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (realm))[2] - __s2[2]); if (__s2_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (realm))[3] - __s2[3]); } } __result; })))) : __builtin_strcmp
(arealm, realm)))); })
;
1331 }
1332
1333 if (cmp)
1334 continue;
1335 }
1336
1337 if (opaque) {
1338 int cmp = 1;
1339
1340 aopaque = msg_header_find_param(auth->au_common, "opaque=");
1341 if (!aopaque)
1342 continue;
1343
1344 if (aopaque[0] == '"') {
1345 /* Compare quoted aopaque with unquoted opaque */
1346 int i, j;
1347 for (i = 1, j = 0, cmp = 1; aopaque[i] != 0; i++, j++) {
1348 if (aopaque[i] == '"' && opaque[j] == 0) {
1349 cmp = 0;
1350 break;
1351 }
1352
1353 if (aopaque[i] == '\\' && aopaque[i + 1] != '\0')
1354 i++;
1355
1356 if (aopaque[i] != opaque[j])
1357 break;
1358 }
1359 } else {
1360 cmp = strcmp(aopaque, opaque)__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p
(aopaque) && __builtin_constant_p (opaque) &&
(__s1_len = __builtin_strlen (aopaque), __s2_len = __builtin_strlen
(opaque), (!((size_t)(const void *)((aopaque) + 1) - (size_t
)(const void *)(aopaque) == 1) || __s1_len >= 4) &&
(!((size_t)(const void *)((opaque) + 1) - (size_t)(const void
*)(opaque) == 1) || __s2_len >= 4)) ? __builtin_strcmp (aopaque
, opaque) : (__builtin_constant_p (aopaque) && ((size_t
)(const void *)((aopaque) + 1) - (size_t)(const void *)(aopaque
) == 1) && (__s1_len = __builtin_strlen (aopaque), __s1_len
< 4) ? (__builtin_constant_p (opaque) && ((size_t
)(const void *)((opaque) + 1) - (size_t)(const void *)(opaque
) == 1) ? __builtin_strcmp (aopaque, opaque) : (__extension__
({ const unsigned char *__s2 = (const unsigned char *) (const
char *) (opaque); int __result = (((const unsigned char *) (
const char *) (aopaque))[0] - __s2[0]); if (__s1_len > 0 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (aopaque))[1] - __s2[1]); if (__s1_len > 1 &&
__result == 0) { __result = (((const unsigned char *) (const
char *) (aopaque))[2] - __s2[2]); if (__s1_len > 2 &&
__result == 0) __result = (((const unsigned char *) (const char
*) (aopaque))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p
(opaque) && ((size_t)(const void *)((opaque) + 1) - (
size_t)(const void *)(opaque) == 1) && (__s2_len = __builtin_strlen
(opaque), __s2_len < 4) ? (__builtin_constant_p (aopaque)
&& ((size_t)(const void *)((aopaque) + 1) - (size_t)
(const void *)(aopaque) == 1) ? __builtin_strcmp (aopaque, opaque
) : (- (__extension__ ({ const unsigned char *__s2 = (const unsigned
char *) (const char *) (aopaque); int __result = (((const unsigned
char *) (const char *) (opaque))[0] - __s2[0]); if (__s2_len
> 0 && __result == 0) { __result = (((const unsigned
char *) (const char *) (opaque))[1] - __s2[1]); if (__s2_len
> 1 && __result == 0) { __result = (((const unsigned
char *) (const char *) (opaque))[2] - __s2[2]); if (__s2_len
> 2 && __result == 0) __result = (((const unsigned
char *) (const char *) (opaque))[3] - __s2[3]); } } __result
; })))) : __builtin_strcmp (aopaque, opaque)))); })
;
1361 }
1362
1363 if (cmp)
1364 continue;
1365 }
1366
1367 return auth;
1368 }
1369
1370 return NULL((void*)0);
1371}
1372
1373/** Generate nonce parameter.
1374 *
1375 * @param am pointer to authentication module object
1376 * @param buffer string buffer for nonce [OUT]
1377 * @param bsize size of buffer [IN]
1378 * @param nextnonce true if this is a "nextnonce" [IN]
1379 * @param now current time [IN]
1380 */
1381isize_t auth_generate_digest_nonce(auth_mod_t *am,
1382 char buffer[],
1383 size_t bsize,
1384 int nextnonce,
1385 msg_time_t now)
1386{
1387 struct nonce nonce[1] = {{ 0 }};
1388 su_md5_t md5[1];
1389
1390 am->am_count += 3730029547U; /* 3730029547 is a prime */
1391
1392 nonce->issued = now;
1393 nonce->count = am->am_count;
1394 nonce->nextnonce = nextnonce != 0;
1395
1396 /* Calculate HMAC of nonce data */
1397 auth_md5_hmac_init(am, md5);
1398 su_md5_update(md5, nonce, offsetof(struct nonce, digest)__builtin_offsetof(struct nonce, digest));
1399 auth_md5_hmac_digest(am, md5, nonce->digest, sizeof nonce->digest);
1400
1401 return base64_e(buffer, bsize, nonce, sizeof(nonce));
1402}
1403
1404
1405/** Validate nonce parameter.
1406 *
1407 * @param am pointer to authentication module object
1408 * @param as authentication status structure [OUT]
1409 * @param ar decoded authentication response from client [IN]
1410 * @param now current time [IN]
1411 */
1412int auth_validate_digest_nonce(auth_mod_t *am,
1413 auth_status_t *as,
1414 auth_response_t *ar,
1415 msg_time_t now)
1416{
1417 struct nonce nonce[1] = {{ 0 }};
1418 su_md5_t md5[1];
1419 uint8_t hmac[sizeof nonce->digest];
1420 unsigned expires;
1421
1422 /* Check nonce */
1423 if (!ar->ar_nonce) {
1424 SU_DEBUG_5(("auth_method_digest: no nonce\n" VA_NONE))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 1424, "auth_method_digest: no nonce\n"
"%s", "")) : (void)0)
;
1425 return -1;
1426 }
1427 if (base64_d((void*)nonce, (sizeof nonce), ar->ar_nonce) != (sizeof nonce)) {
1428 SU_DEBUG_5(("auth_method_digest: too short nonce\n" VA_NONE))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 1428, "auth_method_digest: too short nonce\n"
"%s", "")) : (void)0)
;
1429 return -1;
1430 }
1431
1432 /* Calculate HMAC over decoded nonce data */
1433 auth_md5_hmac_init(am, md5);
1434 su_md5_update(md5, nonce, offsetof(struct nonce, digest)__builtin_offsetof(struct nonce, digest));
1435 auth_md5_hmac_digest(am, md5, hmac, sizeof hmac);
1436
1437 if (memcmp(nonce->digest, hmac, sizeof nonce->digest)) {
1438 SU_DEBUG_5(("auth_method_digest: bad nonce\n" VA_NONE))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 1438, "auth_method_digest: bad nonce\n"
"%s", "")) : (void)0)
;
1439 return -1;
1440 }
1441
1442 as->as_nonce_issued = nonce->issued;
1443 as->as_nextnonce = nonce->nextnonce != 0;
1444
1445 expires = nonce->nextnonce ? am->am_next_exp : am->am_expires;
1446
1447 if (nonce->issued > now ||
1448 (expires && nonce->issued + expires < now)) {
1449 SU_DEBUG_5(("auth_method_digest: nonce expired %lu seconds ago "((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 1451, "auth_method_digest: nonce expired %lu seconds ago "
"(lifetime %u)\n", now - (nonce->issued + expires), expires
)) : (void)0)
1450 "(lifetime %u)\n",((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 1451, "auth_method_digest: nonce expired %lu seconds ago "
"(lifetime %u)\n", now - (nonce->issued + expires), expires
)) : (void)0)
1451 now - (nonce->issued + expires), expires))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 1451, "auth_method_digest: nonce expired %lu seconds ago "
"(lifetime %u)\n", now - (nonce->issued + expires), expires
)) : (void)0)
;
1452 as->as_stale = 1;
1453 }
1454
1455 if (am->am_max_ncount && ar->ar_nc) {
1456 unsigned long nc = strtoul(ar->ar_nc, NULL((void*)0), 10);
1457
1458 if (nc == 0 || nc > am->am_max_ncount) {
1459 SU_DEBUG_5(("auth_method_digest: nonce used %s times, max %u\n",((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 1460, "auth_method_digest: nonce used %s times, max %u\n"
, ar->ar_nc, am->am_max_ncount)) : (void)0)
1460 ar->ar_nc, am->am_max_ncount))((((iptsec_log) != ((void*)0) && (iptsec_log)->log_init
) == 0 ? 9 : (((iptsec_log) != ((void*)0) && (iptsec_log
)->log_init > 1) ? (iptsec_log)->log_level : su_log_default
->log_level)) >= 5 ? (_su_llog((iptsec_log), 5, "auth_module.c"
, (const char *)__func__, 1460, "auth_method_digest: nonce used %s times, max %u\n"
, ar->ar_nc, am->am_max_ncount)) : (void)0)
;
1461 as->as_stale = 1;
1462 }
1463 }
1464
1465 /* We should also check cnonce, nc... */
1466
1467 return 0;
1468}
1469
1470
1471/* ====================================================================== */
1472/* HMAC routines */
1473static
1474void auth_md5_hmac_key(auth_mod_t *am)
1475{
1476 size_t i;
1477 uint8_t ipad[SU_MD5_DIGEST_SIZE16];
1478 uint8_t opad[SU_MD5_DIGEST_SIZE16];
1479
1480 assert(SU_MD5_DIGEST_SIZE == sizeof am->am_master_key)((16 == sizeof am->am_master_key) ? (void) (0) : __assert_fail
("16 == sizeof am->am_master_key", "auth_module.c", 1480,
__PRETTY_FUNCTION__))
;
1481
1482 /* Derive HMAC ipad and opad from master key */
1483 for (i = 0; i < sizeof am->am_master_key; i++) {
1484 ipad[i] = am->am_master_key[i] ^ 0x36;
1485 opad[i] = am->am_master_key[i] ^ 0x5C;
1486 }
1487
1488 /* Pre-calculate sum of ipad */
1489 su_md5_init(&am->am_hmac_ipad);
1490 su_md5_update(&am->am_hmac_ipad, ipad, sizeof ipad);
1491
1492 /* Pre-calculate sum of opad */
1493 su_md5_init(&am->am_hmac_opad);
1494 su_md5_update(&am->am_hmac_opad, opad, sizeof opad);
1495}
1496
1497void auth_md5_hmac_init(auth_mod_t *am, struct su_md5_t *imd5)
1498{
1499 *imd5 = am->am_hmac_ipad;
1500}
1501
1502void auth_md5_hmac_digest(auth_mod_t *am, struct su_md5_t *imd5,
1503 void *hmac, size_t size)
1504{
1505 uint8_t digest[SU_MD5_DIGEST_SIZE16];
1506 su_md5_t omd5[1];
1507
1508 /* inner sum */
1509 su_md5_digest(imd5, digest);
1510
1511 *omd5 = am->am_hmac_opad;
1512 su_md5_update(omd5, digest, sizeof *digest);
1513
1514 /* outer sum */
1515 if (size == sizeof digest) {
1516 su_md5_digest(omd5, hmac);
1517 }
1518 else {
1519 su_md5_digest(omd5, digest);
1520
1521 if (size > sizeof digest) {
1522 memset((char *)hmac + (sizeof digest), 0, size - sizeof digest);
1523 size = sizeof digest;
1524 }
1525
1526 memcpy(hmac, digest, size);
1527 }
1528}
1529
1530/* ====================================================================== */
1531/* Compatibility interface */
1532
1533void auth_mod_method(auth_mod_t *am,
1534 auth_status_t *as,
1535 msg_auth_t *credentials,
1536 auth_challenger_t const *ach)
1537{
1538 auth_mod_verify(am, as, credentials, ach);
1539}
1540
1541void auth_mod_check_client(auth_mod_t *am,
1542 auth_status_t *as,
1543 msg_auth_t *credentials,
1544 auth_challenger_t const *ach)
1545{
1546 auth_mod_verify(am, as, credentials, ach);
1547}
1548
1549
1550void auth_mod_challenge_client(auth_mod_t *am,
1551 auth_status_t *as,
1552 auth_challenger_t const *ach)
1553{
1554 auth_mod_challenge(am, as, ach);
1555}