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