| 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 | } |