1 /* remote.c
2 
3    The dhcpctl remote object. */
4 
5 /*
6  * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1999-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 #include <omapip/omapip_p.h>
31 #include "dhcpctl.h"
32 
33 /* dhcpctl_new_authenticator
34 
35    synchronous - creates an authenticator object.
36    returns nonzero status code if the object couldn't be created
37    stores handle to authenticator through h if successful, and returns zero.
38    name is the authenticator name (NUL-terminated string).
39    algorithm is the NUL-terminated string name of the algorithm to use
40    (currently, only "hmac-md5" is supported).
41    secret and secret_len is the key secret. */
42 
dhcpctl_new_authenticator(dhcpctl_handle * h,const char * name,const char * algorithm,const unsigned char * secret,unsigned secret_len)43 dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *h,
44 					  const char *name,
45 					  const char *algorithm,
46 					  const unsigned char *secret,
47 					  unsigned secret_len)
48 {
49 	struct auth_key *key = (struct auth_key *)0;
50 	isc_result_t status;
51 
52 	status = omapi_auth_key_new (&key, MDL);
53 	if (status != ISC_R_SUCCESS)
54 		return status;
55 
56 	key -> name = dmalloc (strlen (name) + 1, MDL);
57 	if (!key -> name) {
58 		omapi_auth_key_dereference (&key, MDL);
59 		return ISC_R_NOMEMORY;
60 	}
61 	strcpy (key -> name, name);
62 
63 	/* If the algorithm name isn't an FQDN, tack on the
64 	   .SIG-ALG.REG.NET. domain. */
65 	if (strchr (algorithm, '.') == 0) {
66 		static char add[] = ".SIG-ALG.REG.INT.";
67 		key -> algorithm = dmalloc (strlen (algorithm) +
68 		                            sizeof (add), MDL);
69 		if (!key -> algorithm) {
70 			omapi_auth_key_dereference (&key, MDL);
71 			return ISC_R_NOMEMORY;
72 		}
73 		strcpy (key -> algorithm, algorithm);
74 		strcat (key -> algorithm, add);
75 	} else {
76 		key -> algorithm = dmalloc (strlen (algorithm) + 1, MDL);
77 		if (!key -> algorithm) {
78 			omapi_auth_key_dereference (&key, MDL);
79 			return ISC_R_NOMEMORY;
80 		}
81 		strcpy (key -> algorithm, algorithm);
82 	}
83 
84 	status = omapi_data_string_new (&key -> key, secret_len, MDL);
85 	if (status != ISC_R_SUCCESS) {
86 		omapi_auth_key_dereference (&key, MDL);
87 		return status;
88 	}
89 	memcpy (key -> key -> value, secret, secret_len);
90 	key -> key -> len = secret_len;
91 
92 	*h = (dhcpctl_handle) key;
93 	return ISC_R_SUCCESS;
94 }
95 
96 
97 /* dhcpctl_new_object
98 
99    synchronous - creates a local handle for a host entry.
100    returns nonzero status code if the local host entry couldn't
101    be created
102    stores handle to host through h if successful, and returns zero.
103    object_type is a pointer to a NUL-terminated string containing
104    the ascii name of the type of object being accessed - e.g., "host" */
105 
dhcpctl_new_object(dhcpctl_handle * h,dhcpctl_handle connection,const char * object_type)106 dhcpctl_status dhcpctl_new_object (dhcpctl_handle *h,
107 				   dhcpctl_handle connection,
108 				   const char *object_type)
109 {
110 	dhcpctl_remote_object_t *m;
111 	omapi_object_t *g;
112 	isc_result_t status;
113 
114 	m = (dhcpctl_remote_object_t *)0;
115 	status = omapi_object_allocate((omapi_object_t **)&m,
116 				       dhcpctl_remote_type, 0, MDL);
117 	if (status != ISC_R_SUCCESS)
118 		return status;
119 
120 	g = (omapi_object_t *)0;
121 	status = omapi_generic_new (&g, MDL);
122 	if (status != ISC_R_SUCCESS) {
123 		dfree (m, MDL);
124 		return status;
125 	}
126 	status = omapi_object_reference (&m -> inner, g, MDL);
127 	if (status != ISC_R_SUCCESS) {
128 		omapi_object_dereference ((omapi_object_t **)&m, MDL);
129 		omapi_object_dereference (&g, MDL);
130 		return status;
131 	}
132 	status = omapi_object_reference (&g -> outer,
133 					 (omapi_object_t *)m, MDL);
134 
135 	if (status != ISC_R_SUCCESS) {
136 		omapi_object_dereference ((omapi_object_t **)&m, MDL);
137 		omapi_object_dereference (&g, MDL);
138 		return status;
139 	}
140 
141 	status = omapi_typed_data_new (MDL, &m -> rtype,
142 				       omapi_datatype_string,
143 				       object_type);
144 	if (status != ISC_R_SUCCESS) {
145 		omapi_object_dereference ((omapi_object_t **)&m, MDL);
146 		omapi_object_dereference (&g, MDL);
147 		return status;
148 	}
149 
150 	status = omapi_object_reference (h, (omapi_object_t *)m, MDL);
151 	omapi_object_dereference ((omapi_object_t **)&m, MDL);
152 	omapi_object_dereference (&g, MDL);
153 	if (status != ISC_R_SUCCESS)
154 		return status;
155 
156 	return status;
157 }
158 
159 /* asynchronous - just queues the request
160    returns nonzero status code if open couldn't be queued
161    returns zero if open was queued
162    h is a handle to an object created by dhcpctl_new_object
163    connection is a connection to a DHCP server
164    flags include:
165      DHCPCTL_CREATE - if the object doesn't exist, create it
166      DHCPCTL_UPDATE - update the object on the server using the
167      		      attached parameters
168      DHCPCTL_EXCL - error if the object exists and DHCPCTL_CREATE
169      		      was also specified */
170 
dhcpctl_open_object(dhcpctl_handle h,dhcpctl_handle connection,int flags)171 dhcpctl_status dhcpctl_open_object (dhcpctl_handle h,
172 				    dhcpctl_handle connection,
173 				    int flags)
174 {
175 	isc_result_t status;
176 	omapi_object_t *message = (omapi_object_t *)0;
177 	dhcpctl_remote_object_t *remote;
178 
179 	if (h -> type != dhcpctl_remote_type)
180 		return DHCP_R_INVALIDARG;
181 	remote = (dhcpctl_remote_object_t *)h;
182 
183 	status = omapi_message_new (&message, MDL);
184 	if (status != ISC_R_SUCCESS)
185 		return status;
186 	status = omapi_set_int_value (message, (omapi_object_t *)0,
187 				      "op", OMAPI_OP_OPEN);
188 	if (status != ISC_R_SUCCESS) {
189 		omapi_object_dereference (&message, MDL);
190 		return status;
191 	}
192 	status = omapi_set_object_value (message, (omapi_object_t *)0,
193 					 "object", h);
194 	if (status != ISC_R_SUCCESS) {
195 		omapi_object_dereference (&message, MDL);
196 		return status;
197 	}
198 	if (flags & DHCPCTL_CREATE) {
199 		status = omapi_set_boolean_value (message, (omapi_object_t *)0,
200 						  "create", 1);
201 		if (status != ISC_R_SUCCESS) {
202 			omapi_object_dereference (&message, MDL);
203 			return status;
204 		}
205 	}
206 	if (flags & DHCPCTL_UPDATE) {
207 		status = omapi_set_boolean_value (message, (omapi_object_t *)0,
208 						  "update", 1);
209 		if (status != ISC_R_SUCCESS) {
210 			omapi_object_dereference (&message, MDL);
211 			return status;
212 		}
213 	}
214 	if (flags & DHCPCTL_EXCL) {
215 		status = omapi_set_boolean_value (message, (omapi_object_t *)0,
216 						  "exclusive", 1);
217 		if (status != ISC_R_SUCCESS) {
218 			omapi_object_dereference (&message, MDL);
219 			return status;
220 		}
221 	}
222 
223 	if (remote -> rtype) {
224 		status = omapi_set_value_str (message, (omapi_object_t *)0,
225 					      "type", remote -> rtype);
226 		if (status != ISC_R_SUCCESS) {
227 			omapi_object_dereference (&message, MDL);
228 			return status;
229 		}
230 	}
231 
232 	status = omapi_message_register (message);
233 	if (status != ISC_R_SUCCESS) {
234 		omapi_object_dereference (&message, MDL);
235 		return status;
236 	}
237 
238 	status = omapi_protocol_send_message (connection -> outer,
239 					    (omapi_object_t *)0,
240 					    message, (omapi_object_t *)0);
241 
242 	if (status != ISC_R_SUCCESS)
243 		omapi_message_unregister (message);
244 
245 	omapi_object_dereference (&message, MDL);
246 	return status;
247 }
248 
249 /* Callback methods (not meant to be called directly) */
250 
dhcpctl_remote_set_value(omapi_object_t * h,omapi_object_t * id,omapi_data_string_t * name,omapi_typed_data_t * value)251 isc_result_t dhcpctl_remote_set_value (omapi_object_t *h,
252 				       omapi_object_t *id,
253 				       omapi_data_string_t *name,
254 				       omapi_typed_data_t *value)
255 {
256 	dhcpctl_remote_object_t *ro;
257 	unsigned long rh;
258 	isc_result_t status;
259 
260 	if (h -> type != dhcpctl_remote_type)
261 		return DHCP_R_INVALIDARG;
262 	ro = (dhcpctl_remote_object_t *)h;
263 
264 	if (!omapi_ds_strcmp (name, "remote-handle")) {
265 		status = omapi_get_int_value (&rh, value);
266 		if (status == ISC_R_SUCCESS)
267 			ro -> remote_handle = rh;
268 		return status;
269 	}
270 
271 	if (h -> inner && h -> inner -> type -> set_value)
272 		return (*(h -> inner -> type -> set_value))
273 			(h -> inner, id, name, value);
274 	return ISC_R_NOTFOUND;
275 }
276 
dhcpctl_remote_get_value(omapi_object_t * h,omapi_object_t * id,omapi_data_string_t * name,omapi_value_t ** value)277 isc_result_t dhcpctl_remote_get_value (omapi_object_t *h,
278 				       omapi_object_t *id,
279 				       omapi_data_string_t *name,
280 				       omapi_value_t **value)
281 {
282 	if (h -> type != dhcpctl_remote_type)
283 		return DHCP_R_INVALIDARG;
284 
285 	if (h -> inner && h -> inner -> type -> get_value)
286 		return (*(h -> inner -> type -> get_value))
287 			(h -> inner, id, name, value);
288 	return ISC_R_NOTFOUND;
289 }
290 
dhcpctl_remote_signal_handler(omapi_object_t * o,const char * name,va_list ap)291 isc_result_t dhcpctl_remote_signal_handler (omapi_object_t *o,
292 					    const char *name, va_list ap)
293 {
294 	dhcpctl_remote_object_t *p;
295 	omapi_typed_data_t *tv;
296 
297 	if (o -> type != dhcpctl_remote_type)
298 		return DHCP_R_INVALIDARG;
299 	p = (dhcpctl_remote_object_t *)o;
300 
301 	if (!strcmp (name, "updated")) {
302 		p -> waitstatus = ISC_R_SUCCESS;
303 		if (o -> inner -> type == omapi_type_generic)
304 			omapi_generic_clear_flags (o -> inner);
305 		return omapi_signal_in (o -> inner, "ready");
306 	}
307 	if (!strcmp (name, "status")) {
308 		p -> waitstatus = va_arg (ap, isc_result_t);
309 		if (p -> message)
310 			omapi_typed_data_dereference (&p -> message, MDL);
311 		tv = va_arg (ap, omapi_typed_data_t *);
312 		if (tv)
313 			omapi_typed_data_reference (&p -> message, tv, MDL);
314 		return omapi_signal_in (o -> inner, "ready");
315 	}
316 
317 	if (p -> inner && p -> inner -> type -> signal_handler)
318 		return (*(p -> inner -> type -> signal_handler))
319 			(p -> inner, name, ap);
320 
321 	return ISC_R_SUCCESS;
322 }
323 
dhcpctl_remote_destroy(omapi_object_t * h,const char * file,int line)324 isc_result_t dhcpctl_remote_destroy (omapi_object_t *h,
325 				     const char *file, int line)
326 {
327 	dhcpctl_remote_object_t *p;
328 	if (h -> type != dhcpctl_remote_type)
329 		return DHCP_R_INVALIDARG;
330 	p = (dhcpctl_remote_object_t *)h;
331 	if (p -> handle)
332 		omapi_object_dereference ((omapi_object_t **)&p -> handle,
333 					  file, line);
334 	if (p -> rtype)
335 		omapi_typed_data_dereference ((omapi_typed_data_t **)&p->rtype,
336 					      file, line);
337 	return ISC_R_SUCCESS;
338 }
339 
340 /* Write all the published values associated with the object through the
341    specified connection. */
342 
dhcpctl_remote_stuff_values(omapi_object_t * c,omapi_object_t * id,omapi_object_t * p)343 isc_result_t dhcpctl_remote_stuff_values (omapi_object_t *c,
344 					  omapi_object_t *id,
345 					  omapi_object_t *p)
346 {
347 	if (p -> type != dhcpctl_remote_type)
348 		return DHCP_R_INVALIDARG;
349 
350 	if (p -> inner && p -> inner -> type -> stuff_values)
351 		return (*(p -> inner -> type -> stuff_values)) (c, id,
352 								p -> inner);
353 	return ISC_R_SUCCESS;
354 }
355 
356