1 /* $NetBSD: auth.c,v 1.2 2018/04/07 22:37:30 christos Exp $ */ 2 3 /* auth.c 4 5 Subroutines having to do with authentication. */ 6 7 /* 8 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC") 9 * Copyright (c) 1998-2003 by Internet Software Consortium 10 * 11 * This Source Code Form is subject to the terms of the Mozilla Public 12 * License, v. 2.0. If a copy of the MPL was not distributed with this 13 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 * 23 * Internet Systems Consortium, Inc. 24 * 950 Charter Street 25 * Redwood City, CA 94063 26 * <info@isc.org> 27 * https://www.isc.org/ 28 * 29 */ 30 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: auth.c,v 1.2 2018/04/07 22:37:30 christos Exp $"); 33 34 #include "dhcpd.h" 35 36 #include <omapip/omapip_p.h> 37 38 OMAPI_OBJECT_ALLOC (omapi_auth_key, omapi_auth_key_t, omapi_type_auth_key) 39 typedef struct hash omapi_auth_hash_t; 40 HASH_FUNCTIONS_DECL (omapi_auth_key, const char *, 41 omapi_auth_key_t, omapi_auth_hash_t) 42 omapi_auth_hash_t *auth_key_hash; 43 HASH_FUNCTIONS (omapi_auth_key, const char *, omapi_auth_key_t, 44 omapi_auth_hash_t, 45 omapi_auth_key_reference, omapi_auth_key_dereference, 46 do_case_hash) 47 48 isc_result_t omapi_auth_key_new (omapi_auth_key_t **o, const char *file, 49 int line) 50 { 51 return omapi_auth_key_allocate (o, file, line); 52 } 53 54 isc_result_t omapi_auth_key_destroy (omapi_object_t *h, 55 const char *file, int line) 56 { 57 omapi_auth_key_t *a; 58 59 if (h->type != omapi_type_auth_key) 60 return DHCP_R_INVALIDARG; 61 a = (omapi_auth_key_t *)h; 62 63 if (auth_key_hash != NULL) 64 omapi_auth_key_hash_delete(auth_key_hash, a->name, 0, MDL); 65 66 if (a->name != NULL) 67 dfree(a->name, MDL); 68 if (a->algorithm != NULL) 69 dfree(a->algorithm, MDL); 70 if (a->key != NULL) 71 omapi_data_string_dereference(&a->key, MDL); 72 if (a->tsec_key != NULL) 73 dns_tsec_destroy(&a->tsec_key); 74 75 return ISC_R_SUCCESS; 76 } 77 78 isc_result_t omapi_auth_key_enter (omapi_auth_key_t *a) 79 { 80 omapi_auth_key_t *tk; 81 isc_result_t status; 82 dst_key_t *dstkey; 83 84 if (a -> type != omapi_type_auth_key) 85 return DHCP_R_INVALIDARG; 86 87 tk = (omapi_auth_key_t *)0; 88 if (auth_key_hash) { 89 omapi_auth_key_hash_lookup (&tk, auth_key_hash, 90 a -> name, 0, MDL); 91 if (tk == a) { 92 omapi_auth_key_dereference (&tk, MDL); 93 return ISC_R_SUCCESS; 94 } 95 if (tk) { 96 omapi_auth_key_hash_delete (auth_key_hash, 97 tk -> name, 0, MDL); 98 omapi_auth_key_dereference (&tk, MDL); 99 } 100 } else { 101 if (!omapi_auth_key_new_hash(&auth_key_hash, 102 KEY_HASH_SIZE, MDL)) 103 return ISC_R_NOMEMORY; 104 } 105 106 /* 107 * If possible create a tsec structure for this key, 108 * if we can't create the structure we put out a warning 109 * and continue. 110 */ 111 status = isclib_make_dst_key(a->name, a->algorithm, 112 a->key->value, a->key->len, 113 &dstkey); 114 if (status == ISC_R_SUCCESS) { 115 status = dns_tsec_create(dhcp_gbl_ctx.mctx, dns_tsectype_tsig, 116 dstkey, &a->tsec_key); 117 dst_key_free(&dstkey); 118 } 119 if (status != ISC_R_SUCCESS) 120 log_error("Unable to create tsec structure for %s", a->name); 121 122 omapi_auth_key_hash_add (auth_key_hash, a -> name, 0, a, MDL); 123 return ISC_R_SUCCESS; 124 } 125 126 isc_result_t omapi_auth_key_lookup_name (omapi_auth_key_t **a, 127 const char *name) 128 { 129 if (!auth_key_hash) 130 return ISC_R_NOTFOUND; 131 if (!omapi_auth_key_hash_lookup (a, auth_key_hash, name, 0, MDL)) 132 return ISC_R_NOTFOUND; 133 return ISC_R_SUCCESS; 134 } 135 136 isc_result_t omapi_auth_key_lookup (omapi_object_t **h, 137 omapi_object_t *id, 138 omapi_object_t *ref) 139 { 140 isc_result_t status; 141 omapi_value_t *name = (omapi_value_t *)0; 142 omapi_value_t *algorithm = (omapi_value_t *)0; 143 144 if (!auth_key_hash) 145 return ISC_R_NOTFOUND; 146 147 if (!ref) 148 return DHCP_R_NOKEYS; 149 150 status = omapi_get_value_str (ref, id, "name", &name); 151 if (status != ISC_R_SUCCESS) 152 return status; 153 154 if ((name -> value -> type != omapi_datatype_string) && 155 (name -> value -> type != omapi_datatype_data)) { 156 omapi_value_dereference (&name, MDL); 157 return ISC_R_NOTFOUND; 158 } 159 160 status = omapi_get_value_str (ref, id, "algorithm", &algorithm); 161 if (status != ISC_R_SUCCESS) { 162 omapi_value_dereference (&name, MDL); 163 return status; 164 } 165 166 if ((algorithm -> value -> type != omapi_datatype_string) && 167 (algorithm -> value -> type != omapi_datatype_data)) { 168 omapi_value_dereference (&name, MDL); 169 omapi_value_dereference (&algorithm, MDL); 170 return ISC_R_NOTFOUND; 171 } 172 173 174 if (!omapi_auth_key_hash_lookup ((omapi_auth_key_t **)h, auth_key_hash, 175 (const char *) 176 name -> value -> u.buffer.value, 177 name -> value -> u.buffer.len, MDL)) { 178 omapi_value_dereference (&name, MDL); 179 omapi_value_dereference (&algorithm, MDL); 180 return ISC_R_NOTFOUND; 181 } 182 183 if (omapi_td_strcasecmp (algorithm -> value, 184 ((omapi_auth_key_t *)*h) -> algorithm) != 0) { 185 omapi_value_dereference (&name, MDL); 186 omapi_value_dereference (&algorithm, MDL); 187 omapi_object_dereference (h, MDL); 188 return ISC_R_NOTFOUND; 189 } 190 191 omapi_value_dereference (&name, MDL); 192 omapi_value_dereference (&algorithm, MDL); 193 194 return ISC_R_SUCCESS; 195 } 196 197 isc_result_t omapi_auth_key_stuff_values (omapi_object_t *c, 198 omapi_object_t *id, 199 omapi_object_t *h) 200 { 201 omapi_auth_key_t *a; 202 isc_result_t status; 203 204 if (h -> type != omapi_type_auth_key) 205 return DHCP_R_INVALIDARG; 206 a = (omapi_auth_key_t *)h; 207 208 /* Write only the name and algorithm -- not the secret! */ 209 if (a -> name) { 210 status = omapi_connection_put_name (c, "name"); 211 if (status != ISC_R_SUCCESS) 212 return status; 213 status = omapi_connection_put_string (c, a -> name); 214 if (status != ISC_R_SUCCESS) 215 return status; 216 } 217 if (a -> algorithm) { 218 status = omapi_connection_put_name (c, "algorithm"); 219 if (status != ISC_R_SUCCESS) 220 return status; 221 status = omapi_connection_put_string (c, a -> algorithm); 222 if (status != ISC_R_SUCCESS) 223 return status; 224 } 225 226 return ISC_R_SUCCESS; 227 } 228 229 isc_result_t omapi_auth_key_get_value (omapi_object_t *h, 230 omapi_object_t *id, 231 omapi_data_string_t *name, 232 omapi_value_t **value) 233 { 234 omapi_auth_key_t *a; 235 isc_result_t status; 236 237 if (h -> type != omapi_type_auth_key) 238 return ISC_R_UNEXPECTED; 239 a = (omapi_auth_key_t *)h; 240 241 if (omapi_ds_strcmp (name, "name") == 0) { 242 if (a -> name) 243 return omapi_make_string_value 244 (value, name, a -> name, MDL); 245 else 246 return ISC_R_NOTFOUND; 247 } else if (omapi_ds_strcmp (name, "key") == 0) { 248 if (a -> key) { 249 status = omapi_value_new (value, MDL); 250 if (status != ISC_R_SUCCESS) 251 return status; 252 253 status = omapi_data_string_reference 254 (&(*value) -> name, name, MDL); 255 if (status != ISC_R_SUCCESS) { 256 omapi_value_dereference (value, MDL); 257 return status; 258 } 259 260 status = omapi_typed_data_new (MDL, &(*value) -> value, 261 omapi_datatype_data, 262 a -> key -> len); 263 if (status != ISC_R_SUCCESS) { 264 omapi_value_dereference (value, MDL); 265 return status; 266 } 267 268 memcpy ((*value) -> value -> u.buffer.value, 269 a -> key -> value, a -> key -> len); 270 return ISC_R_SUCCESS; 271 } else 272 return ISC_R_NOTFOUND; 273 } else if (omapi_ds_strcmp (name, "algorithm") == 0) { 274 if (a -> algorithm) 275 return omapi_make_string_value 276 (value, name, a -> algorithm, MDL); 277 else 278 return ISC_R_NOTFOUND; 279 } 280 281 return ISC_R_SUCCESS; 282 } 283