File: | libs/sofia-sip/libsofia-sip-ua/iptsec/auth_module.c |
Location: | line 693, column 3 |
Description: | Value stored to 'phrase' is never read |
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 |
57 | static 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 | |
78 | char const auth_internal_server_error[] = "Internal server error"; |
79 | |
80 | static void auth_call_scheme_destructor(void *); |
81 | static 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 | |
88 | HTABLE_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); |
89 | HTABLE_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 | */ |
101 | auth_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 | */ |
134 | int 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. */ |
261 | void auth_mod_destroy(auth_mod_t *am) |
262 | { |
263 | su_home_unref(am->am_home); |
264 | } |
265 | |
266 | /** Call scheme-specific destructor function. */ |
267 | static 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 | */ |
278 | void auth_destroy_default(auth_mod_t *am) |
279 | { |
280 | } |
281 | |
282 | /** Create a new reference to authentication module. */ |
283 | auth_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. */ |
289 | void 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. */ |
295 | char 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 | */ |
305 | auth_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 | */ |
315 | auth_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 | |
339 | auth_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 | */ |
352 | auth_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 | */ |
359 | void 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 | */ |
406 | void 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 | */ |
458 | void 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 | */ |
473 | void 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 | */ |
484 | void auth_cancel_default(auth_mod_t *am, auth_status_t *as) |
485 | { |
486 | } |
487 | |
488 | /* ====================================================================== */ |
489 | /* Basic authentication scheme */ |
490 | |
491 | static 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 | |
496 | auth_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 | */ |
511 | static |
512 | void 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 | */ |
526 | void 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. */ |
585 | void 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 | |
598 | static 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 | |
603 | auth_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 | |
614 | struct 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 | */ |
627 | static |
628 | void 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 | */ |
641 | void 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 */ |
674 | void 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. */ |
780 | void 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. */ |
823 | void 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 | |
844 | su_inlinestatic inline void |
845 | auth_htable_append_local(auth_htable_t *pr, auth_passwd_t *apw); |
846 | |
847 | /** Get an passwd entry for user. */ |
848 | auth_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. */ |
876 | auth_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 | |
929 | static ssize_t readfile(su_home_t *, FILE *, |
930 | void **contents, int add_trailing_lf); |
931 | static int auth_readdb_internal(auth_mod_t *am, int always); |
932 | |
933 | /** Read authentication database */ |
934 | int auth_readdb(auth_mod_t *am) |
935 | { |
936 | return auth_readdb_internal(am, 1); |
937 | } |
938 | |
939 | /** Read authentication database only when needed */ |
940 | int 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 */ |
967 | static |
968 | int 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 */ |
1150 | su_inlinestatic inline void |
1151 | auth_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 | |
1183 | static |
1184 | ssize_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 | */ |
1233 | int 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. */ |
1255 | msg_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. */ |
1296 | msg_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 | */ |
1381 | isize_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 | */ |
1412 | int 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 */ |
1473 | static |
1474 | void 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 | |
1497 | void auth_md5_hmac_init(auth_mod_t *am, struct su_md5_t *imd5) |
1498 | { |
1499 | *imd5 = am->am_hmac_ipad; |
1500 | } |
1501 | |
1502 | void 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 | |
1533 | void 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 | |
1541 | void 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 | |
1550 | void 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 | } |