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