Annotation of src/external/mpl/dhcp/dist/omapip/protocol.c, Revision 1.1.1.1
1.1 christos 1: /* $NetBSD$ */
2:
3: /* protocol.c
4:
5: Functions supporting the object management protocol... */
6:
7: /*
8: * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
9: * Copyright (c) 1999-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$");
33:
34: #include "dhcpd.h"
35:
36: #include <omapip/omapip_p.h>
37:
38: OMAPI_OBJECT_ALLOC (omapi_protocol, omapi_protocol_object_t,
39: omapi_type_protocol)
40: OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t,
41: omapi_type_protocol_listener)
42:
43: isc_result_t omapi_protocol_connect (omapi_object_t *h,
44: const char *server_name,
45: unsigned port,
46: omapi_object_t *a)
47: {
48: isc_result_t rstatus, status;
49: omapi_protocol_object_t *obj;
50:
51: #ifdef DEBUG_PROTOCOL
52: log_debug ("omapi_protocol_connect(%s port=%d)", server_name, port);
53: #endif
54:
55: obj = (omapi_protocol_object_t *)0;
56: status = omapi_protocol_allocate (&obj, MDL);
57: if (status != ISC_R_SUCCESS)
58: return status;
59:
60: rstatus = omapi_connect ((omapi_object_t *)obj, server_name, port);
61: if (rstatus != ISC_R_SUCCESS && rstatus != DHCP_R_INCOMPLETE) {
62: omapi_protocol_dereference (&obj, MDL);
63: return rstatus;
64: }
65: status = omapi_object_reference (&h -> outer,
66: (omapi_object_t *)obj, MDL);
67: if (status != ISC_R_SUCCESS) {
68: omapi_protocol_dereference (&obj, MDL);
69: return status;
70: }
71: status = omapi_object_reference (&obj -> inner, h, MDL);
72: if (status != ISC_R_SUCCESS) {
73: omapi_protocol_dereference (&obj, MDL);
74: return status;
75: }
76:
77: /* If we were passed a default authenticator, store it now. We'll
78: open it once we're connected. */
79: if (a) {
80: obj -> default_auth =
81: dmalloc (sizeof(omapi_remote_auth_t), MDL);
82: if (!obj -> default_auth) {
83: omapi_protocol_dereference (&obj, MDL);
84: return ISC_R_NOMEMORY;
85: }
86:
87: obj -> default_auth -> next = (omapi_remote_auth_t *)0;
88: status = omapi_object_reference (&obj -> default_auth -> a,
89: a, MDL);
90: if (status != ISC_R_SUCCESS) {
91: dfree (obj -> default_auth, MDL);
92: omapi_protocol_dereference (&obj, MDL);
93: return status;
94: }
95:
96: obj -> insecure = 0;
97: rstatus = DHCP_R_INCOMPLETE;
98: } else {
99: obj -> insecure = 1;
100: #if 0
101: status = ISC_R_SUCCESS;
102: #endif
103: }
104:
105: omapi_protocol_dereference (&obj, MDL);
106: return rstatus;
107: }
108:
109: /* Send the protocol introduction message. */
110: isc_result_t omapi_protocol_send_intro (omapi_object_t *h,
111: unsigned ver,
112: unsigned hsize)
113: {
114: isc_result_t status;
115: omapi_protocol_object_t *p;
116:
117: #ifdef DEBUG_PROTOCOL
118: log_debug ("omapi_protocol_send_intro()");
119: #endif
120:
121: if (h -> type != omapi_type_protocol)
122: return DHCP_R_INVALIDARG;
123: p = (omapi_protocol_object_t *)h;
124:
125: if (!h -> outer || h -> outer -> type != omapi_type_connection)
126: return ISC_R_NOTCONNECTED;
127:
128: status = omapi_connection_put_uint32 (h -> outer, ver);
129: if (status != ISC_R_SUCCESS)
130: return status;
131:
132: status = omapi_connection_put_uint32 (h -> outer, hsize);
133:
134: if (status != ISC_R_SUCCESS)
135: return status;
136:
137: /* Require the other end to send an intro - this kicks off the
138: protocol input state machine. */
139: p -> state = omapi_protocol_intro_wait;
140: status = omapi_connection_require (h -> outer, 8);
141: if (status != ISC_R_SUCCESS && status != DHCP_R_NOTYET)
142: return status;
143:
144: /* Make up an initial transaction ID for this connection. */
145: p -> next_xid = random ();
146: return ISC_R_SUCCESS;
147: }
148:
149: #ifdef DEBUG_PROTOCOL
150: extern const char *omapi_message_op_name(int);
151: #endif /* DEBUG_PROTOCOL */
152:
153: isc_result_t omapi_protocol_send_message (omapi_object_t *po,
154: omapi_object_t *id,
155: omapi_object_t *mo,
156: omapi_object_t *omo)
157: {
158: omapi_protocol_object_t *p;
159: omapi_object_t *c;
160: omapi_message_object_t *m, *om;
161: omapi_remote_auth_t *ra;
162: omapi_value_t *signature;
163: isc_result_t status;
164: unsigned auth_len;
165:
166: if (po -> type != omapi_type_protocol ||
167: !po -> outer || po -> outer -> type != omapi_type_connection ||
168: mo -> type != omapi_type_message)
169: return DHCP_R_INVALIDARG;
170: if (omo && omo -> type != omapi_type_message)
171: return DHCP_R_INVALIDARG;
172: p = (omapi_protocol_object_t *)po;
173: c = (omapi_object_t *)(po -> outer);
174: m = (omapi_message_object_t *)mo;
175: om = (omapi_message_object_t *)omo;
176:
177: #ifdef DEBUG_PROTOCOL
178: log_debug ("omapi_protocol_send_message(): "
179: "op=%s handle=%#lx id=%#lx rid=%#lx",
180: omapi_message_op_name (m->op),
181: (long)(m -> object ? m -> object -> handle : m -> handle),
182: (long)p -> next_xid, (long)m -> rid);
183: #endif
184:
185: /* Find the authid to use for this message. */
186: if (id) {
187: for (ra = p -> remote_auth_list; ra; ra = ra -> next) {
188: if (ra -> a == id) {
189: break;
190: }
191: }
192:
193: if (!ra)
194: return DHCP_R_KEY_UNKNOWN;
195: } else if (p -> remote_auth_list) {
196: ra = p -> default_auth;
197: } else {
198: ra = (omapi_remote_auth_t *)0;
199: }
200:
201: if (ra) {
202: m -> authid = ra -> remote_handle;
203: status = omapi_object_reference (&m -> id_object,
204: ra -> a, MDL);
205: if (status != ISC_R_SUCCESS)
206: return status;
207: }
208:
209: /* Write the ID of the authentication key we're using. */
210: status = omapi_connection_put_uint32 (c, ra ? ra -> remote_handle : 0);
211: if (status != ISC_R_SUCCESS) {
212: omapi_disconnect (c, 1);
213: return status;
214: }
215:
216: /* Activate the authentication key on the connection. */
217: auth_len = 0;
218: if (ra) {
219: status = omapi_set_object_value (c, (omapi_object_t *)0,
220: "output-authenticator",
221: ra -> a);
222: if (status != ISC_R_SUCCESS) {
223: omapi_disconnect (c, 1);
224: return status;
225: }
226:
227: status = omapi_connection_output_auth_length (c, &auth_len);
228: if (status != ISC_R_SUCCESS) {
229: omapi_disconnect (c, 1);
230: return status;
231: }
232: }
233:
234: /* Write the authenticator length */
235: status = omapi_connection_put_uint32 (c, auth_len);
236: if (status != ISC_R_SUCCESS) {
237: omapi_disconnect (c, 1);
238: return status;
239: }
240:
241: /* Write the opcode. */
242: status = omapi_connection_put_uint32 (c, m -> op);
243: if (status != ISC_R_SUCCESS) {
244: omapi_disconnect (c, 1);
245: return status;
246: }
247:
248: /* Write the handle. If we've been given an explicit handle, use
249: that. Otherwise, use the handle of the object we're sending.
250: The caller is responsible for arranging for one of these handles
251: to be set (or not). */
252: status = omapi_connection_put_uint32 (c, (m -> h
253: ? m -> h
254: : (m -> object
255: ? m -> object -> handle
256: : 0)));
257: if (status != ISC_R_SUCCESS) {
258: omapi_disconnect (c, 1);
259: return status;
260: }
261:
262: /* Set and write the transaction ID. */
263: m -> id = p -> next_xid++;
264: status = omapi_connection_put_uint32 (c, m -> id);
265: if (status != ISC_R_SUCCESS) {
266: omapi_disconnect (c, 1);
267: return status;
268: }
269:
270: /* Write the transaction ID of the message to which this is a
271: response, if there is such a message. */
272: status = omapi_connection_put_uint32 (c, om ? om -> id : m -> rid);
273: if (status != ISC_R_SUCCESS) {
274: omapi_disconnect (c, 1);
275: return status;
276: }
277:
278: /* Stuff out the name/value pairs specific to this message. */
279: status = omapi_stuff_values (c, id, (omapi_object_t *)m);
280: if (status != ISC_R_SUCCESS) {
281: omapi_disconnect (c, 1);
282: return status;
283: }
284:
285: /* Write the zero-length name that terminates the list of name/value
286: pairs specific to the message. */
287: status = omapi_connection_put_uint16 (c, 0);
288: if (status != ISC_R_SUCCESS) {
289: omapi_disconnect (c, 1);
290: return status;
291: }
292:
293: /* Stuff out all the published name/value pairs in the object that's
294: being sent in the message, if there is one. */
295: if (m -> object) {
296: status = omapi_stuff_values (c, id, m -> object);
297: if (status != ISC_R_SUCCESS) {
298: omapi_disconnect (c, 1);
299: return status;
300: }
301: }
302:
303: /* Write the zero-length name that terminates the list of name/value
304: pairs for the associated object. */
305: status = omapi_connection_put_uint16 (c, 0);
306: if (status != ISC_R_SUCCESS) {
307: omapi_disconnect (c, 1);
308: return status;
309: }
310:
311: if (ra) {
312: /* Calculate the message signature. */
313: signature = (omapi_value_t *)0;
314: status = omapi_get_value_str (c, (omapi_object_t *)0,
315: "output-signature", &signature);
316: if (status != ISC_R_SUCCESS) {
317: omapi_disconnect (c, 1);
318: return status;
319: }
320:
321: /* Write the authenticator... */
322: status = (omapi_connection_copyin
323: (c, signature -> value -> u.buffer.value,
324: signature -> value -> u.buffer.len));
325: omapi_value_dereference (&signature, MDL);
326: if (status != ISC_R_SUCCESS) {
327: omapi_disconnect (c, 1);
328: return status;
329: }
330:
331: /* Dectivate the authentication key on the connection. */
332: status = omapi_set_value_str (c, (omapi_object_t *)0,
333: "output-authenticator",
334: (omapi_typed_data_t *)0);
335: if (status != ISC_R_SUCCESS) {
336: omapi_disconnect (c, 1);
337: return status;
338: }
339: }
340:
341: if (!omo) {
342: omapi_protocol_reference (&m -> protocol_object, p, MDL);
343: }
344: return ISC_R_SUCCESS;
345: }
346:
347:
348: isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
349: const char *name, va_list ap)
350: {
351: isc_result_t status;
352: omapi_protocol_object_t *p;
353: omapi_object_t *c;
354: omapi_message_object_t *m;
355: omapi_value_t *signature = NULL;
356: u_int16_t nlen;
357: u_int32_t vlen;
358: u_int32_t th;
359: #if defined (DEBUG_MEMORY_LEAKAGE)
360: unsigned long previous_outstanding = 0xDEADBEEF;
361: unsigned long connect_outstanding = 0xDEADBEEF;
362: #endif
363:
364: if (h -> type != omapi_type_protocol) {
365: /* XXX shouldn't happen. Put an assert here? */
366: return ISC_R_UNEXPECTED;
367: }
368: p = (omapi_protocol_object_t *)h;
369:
370: if (!strcmp (name, "connect")) {
371: #if defined (DEBUG_MEMORY_LEAKAGE)
372: connect_outstanding = dmalloc_outstanding;
373: #endif
374: /* Send the introductory message. */
375: status = omapi_protocol_send_intro
376: (h, OMAPI_PROTOCOL_VERSION,
377: sizeof (omapi_protocol_header_t));
378: if (status != ISC_R_SUCCESS) {
379: omapi_disconnect (p -> outer, 1);
380: return status;
381: }
382: return ISC_R_SUCCESS;
383: }
384:
385: /* Should only receive these when opening the initial authenticator. */
386: if (!strcmp (name, "status")) {
387: status = va_arg (ap, isc_result_t);
388: if (status != ISC_R_SUCCESS) {
389: omapi_signal_in (h -> inner, "status", status,
390: (omapi_object_t *)0);
391: omapi_disconnect (p -> outer, 1);
392: return status;
393: } else {
394: return omapi_signal_in (h -> inner, "ready");
395: }
396: }
397:
398: /* If we get a disconnect, dump memory usage. */
399: if (!strcmp (name, "disconnect")) {
400: #if defined (DEBUG_MEMORY_LEAKAGE)
401: if (connect_outstanding != 0xDEADBEEF) {
402: log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
403: dmalloc_generation,
404: dmalloc_outstanding - previous_outstanding,
405: dmalloc_outstanding, dmalloc_longterm, " long-term");
406: }
407: #endif
408: #if defined (DEBUG_MEMORY_LEAKAGE)
409: dmalloc_dump_outstanding ();
410: #endif
411: #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
412: dump_rc_history (h);
413: #endif
414: for (m = omapi_registered_messages; m; m = m -> next) {
415: if (m -> protocol_object == p) {
416: if (m -> object)
417: omapi_signal (m -> object, "disconnect");
418: }
419: }
420:
421: /* XXX */
422: return ISC_R_SUCCESS;
423: }
424:
425: /* Not a signal we recognize? */
426: if (strcmp (name, "ready")) {
427: if (p -> inner && p -> inner -> type -> signal_handler)
428: return (*(p -> inner -> type -> signal_handler)) (h,
429: name,
430: ap);
431: return ISC_R_NOTFOUND;
432: }
433:
434: if (!p -> outer || p -> outer -> type != omapi_type_connection)
435: return DHCP_R_INVALIDARG;
436: c = p -> outer;
437:
438: /* We get here because we requested that we be woken up after
439: some number of bytes were read, and that number of bytes
440: has in fact been read. */
441: switch (p -> state) {
442: case omapi_protocol_intro_wait:
443: /* Get protocol version and header size in network
444: byte order. */
445: omapi_connection_get_uint32 (c, &p -> protocol_version);
446: omapi_connection_get_uint32 (c, &p -> header_size);
447:
448: /* We currently only support the current protocol version. */
449: if (p -> protocol_version != OMAPI_PROTOCOL_VERSION) {
450: omapi_disconnect (c, 1);
451: return DHCP_R_VERSIONMISMATCH;
452: }
453:
454: if (p -> header_size < sizeof (omapi_protocol_header_t)) {
455: omapi_disconnect (c, 1);
456: return DHCP_R_PROTOCOLERROR;
457: }
458:
459: if (p -> default_auth) {
460: status = omapi_protocol_send_open
461: (h, (omapi_object_t *)0, "authenticator",
462: p -> default_auth -> a,
463: OMAPI_NOTIFY_PROTOCOL);
464: if (status != ISC_R_SUCCESS) {
465: omapi_disconnect (c, 1);
466: return status;
467: }
468: } else {
469: status = omapi_signal_in (h -> inner, "ready");
470: }
471:
472: to_header_wait:
473: /* The next thing we're expecting is a message header. */
474: p -> state = omapi_protocol_header_wait;
475:
476: /* Register a need for the number of bytes in a
477: header, and if we already have that many, process
478: them immediately. */
479: if ((omapi_connection_require (c, p -> header_size)) !=
480: ISC_R_SUCCESS)
481: break;
482: /* If we already have the data, fall through. */
483:
484: case omapi_protocol_header_wait:
485: #if defined (DEBUG_MEMORY_LEAKAGE)
486: if (previous_outstanding != 0xDEADBEEF) {
487: log_info ("%s %ld: %ld new, %ld outstanding, %ld%s",
488: "generation", dmalloc_generation,
489: dmalloc_outstanding - previous_outstanding,
490: dmalloc_outstanding, dmalloc_longterm,
491: " long-term");
492: #endif
493: #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
494: dmalloc_dump_outstanding ();
495: #endif
496: #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
497: dump_rc_history (h);
498: #endif
499: #if defined (DEBUG_MEMORY_LEAKAGE)
500: }
501: previous_outstanding = dmalloc_outstanding;
502: #endif
503: status = omapi_message_new ((omapi_object_t **)&p -> message,
504: MDL);
505: if (status != ISC_R_SUCCESS) {
506: omapi_disconnect (c, 1);
507: return status;
508: }
509:
510: p -> verify_result = ISC_R_SUCCESS;
511:
512: /* Swap in the header... */
513: omapi_connection_get_uint32 (c, &p -> message -> authid);
514:
515: /* Bind the authenticator to the message object. */
516: if (p -> message -> authid) {
517: status = (omapi_protocol_lookup_auth
518: (&p -> message -> id_object, h,
519: p -> message -> authid));
520: if (status != ISC_R_SUCCESS)
521: p -> verify_result = status;
522:
523: /* Activate the authentication key. */
524: status = omapi_set_object_value
525: (c, (omapi_object_t *)0, "input-authenticator",
526: p -> message -> id_object);
527: if (status != ISC_R_SUCCESS) {
528: omapi_disconnect (c, 1);
529: return status;
530: }
531: }
532:
533: omapi_connection_get_uint32 (c, &p -> message -> authlen);
534: omapi_connection_get_uint32 (c, &p -> message -> op);
535: omapi_connection_get_uint32 (c, &th);
536: p -> message -> h = th;
537: omapi_connection_get_uint32 (c, &p -> message -> id);
538: omapi_connection_get_uint32 (c, &p -> message -> rid);
539:
540: /* If there was any extra header data, skip over it. */
541: if (p -> header_size > sizeof (omapi_protocol_header_t)) {
542: omapi_connection_copyout
543: (0, c, (p -> header_size -
544: sizeof (omapi_protocol_header_t)));
545: }
546:
547: /* XXX must compute partial signature across the
548: XXX preceding bytes. Also, if authenticator
549: specifies encryption as well as signing, we may
550: have to decrypt the data on the way in. */
551:
552: /* First we read in message-specific values, then object
553: values. */
554: p -> reading_message_values = 1;
555:
556: need_name_length:
557: /* The next thing we're expecting is length of the
558: first name. */
559: p -> state = omapi_protocol_name_length_wait;
560:
561: /* Wait for a 16-bit length. */
562: if ((omapi_connection_require (c, 2)) != ISC_R_SUCCESS)
563: break;
564: /* If it's already here, fall through. */
565:
566: case omapi_protocol_name_length_wait:
567: omapi_connection_get_uint16 (c, &nlen);
568: /* A zero-length name means that we're done reading name+value
569: pairs. */
570: if (nlen == 0) {
571: /* If we've already read in the object, we are
572: done reading the message, but if we've just
573: finished reading in the values associated
574: with the message, we need to read the
575: object. */
576: if (p -> reading_message_values) {
577: p -> reading_message_values = 0;
578: goto need_name_length;
579: }
580:
581: /* If the authenticator length is zero, there's no
582: signature to read in, so go straight to processing
583: the message. */
584: if (p -> message -> authlen == 0)
585: goto message_done;
586:
587: /* The next thing we're expecting is the
588: message signature. */
589: p -> state = omapi_protocol_signature_wait;
590:
591: /* Wait for the number of bytes specified for
592: the authenticator. If we already have it,
593: go read it in. */
594: if (omapi_connection_require
595: (c, p -> message -> authlen) == ISC_R_SUCCESS)
596: goto signature_wait;
597: break;
598: }
599:
600: /* Allocate a buffer for the name. */
601: status = (omapi_data_string_new (&p -> name, nlen, MDL));
602: if (status != ISC_R_SUCCESS) {
603: omapi_disconnect (c, 1);
604: return ISC_R_NOMEMORY;
605: }
606: p -> state = omapi_protocol_name_wait;
607: if (omapi_connection_require (c, nlen) != ISC_R_SUCCESS)
608: break;
609: /* If it's already here, fall through. */
610:
611: case omapi_protocol_name_wait:
612: omapi_connection_copyout (p -> name -> value, c,
613: p -> name -> len);
614: /* Wait for a 32-bit length. */
615: p -> state = omapi_protocol_value_length_wait;
616: if ((omapi_connection_require (c, 4)) != ISC_R_SUCCESS)
617: break;
618: /* If it's already here, fall through. */
619:
620: case omapi_protocol_value_length_wait:
621: omapi_connection_get_uint32 (c, &vlen);
622:
623: /* Zero-length values are allowed - if we get one, we
624: don't have to read any data for the value - just
625: get the next one, if there is a next one. */
626: if (!vlen)
627: goto insert_new_value;
628:
629: status = omapi_typed_data_new (MDL, &p -> value,
630: omapi_datatype_data,
631: vlen);
632: if (status != ISC_R_SUCCESS) {
633: omapi_disconnect (c, 1);
634: return ISC_R_NOMEMORY;
635: }
636:
637: p -> state = omapi_protocol_value_wait;
638: if (omapi_connection_require (c, vlen) != ISC_R_SUCCESS)
639: break;
640: /* If it's already here, fall through. */
641:
642: case omapi_protocol_value_wait:
643: omapi_connection_copyout (p -> value -> u.buffer.value, c,
644: p -> value -> u.buffer.len);
645:
646: insert_new_value:
647: if (p -> reading_message_values) {
648: status = (omapi_set_value
649: ((omapi_object_t *)p -> message,
650: p -> message -> id_object,
651: p -> name, p -> value));
652: } else {
653: if (!p -> message -> object) {
654: /* We need a generic object to hang off of the
655: incoming message. */
656: status = (omapi_generic_new
657: (&p -> message -> object, MDL));
658: if (status != ISC_R_SUCCESS) {
659: omapi_disconnect (c, 1);
660: return status;
661: }
662: }
663: status = (omapi_set_value
664: ((omapi_object_t *)p -> message -> object,
665: p -> message -> id_object,
666: p -> name, p -> value));
667: }
668: if (status != ISC_R_SUCCESS) {
669: omapi_disconnect (c, 1);
670: return status;
671: }
672: omapi_data_string_dereference (&p -> name, MDL);
673: if (p -> value)
674: omapi_typed_data_dereference (&p -> value, MDL);
675: goto need_name_length;
676:
677: signature_wait:
678: case omapi_protocol_signature_wait:
679: if (p -> message -> id_object) {
680: /* Compute the signature of the message. */
681: status = omapi_get_value_str (c, (omapi_object_t *)0,
682: "input-signature",
683: &signature);
684: if (status != ISC_R_SUCCESS) {
685: omapi_disconnect (c, 1);
686: return status;
687: }
688:
689: /* Disable the authentication key on the connection. */
690: status = omapi_set_value_str (c, (omapi_object_t *)0,
691: "input-authenticator",
692: (omapi_typed_data_t *)0);
693: if (status != ISC_R_SUCCESS) {
694: omapi_value_dereference (&signature, MDL);
695: omapi_disconnect (c, 1);
696: return status;
697: }
698: }
699:
700: /* Read the authenticator. */
701: status = omapi_typed_data_new (MDL,
702: &p -> message -> authenticator,
703: omapi_datatype_data,
704: p -> message -> authlen);
705:
706: if (status != ISC_R_SUCCESS) {
707: if (signature != NULL) {
708: omapi_value_dereference (&signature, MDL);
709: }
710: omapi_disconnect (c, 1);
711: return ISC_R_NOMEMORY;
712: }
713: omapi_connection_copyout
714: (p -> message -> authenticator -> u.buffer.value, c,
715: p -> message -> authlen);
716:
717: /* Verify the signature. */
718: if (p -> message -> id_object &&
719: ((signature -> value -> u.buffer.len !=
720: p -> message -> authlen) ||
721: (memcmp (signature -> value -> u.buffer.value,
722: p -> message -> authenticator -> u.buffer.value,
723: p -> message -> authlen) != 0))) {
724: /* Invalid signature. */
725: p->verify_result = DHCP_R_INVALIDKEY;
726: }
727:
728: if (signature != NULL) {
729: omapi_value_dereference (&signature, MDL);
730: }
731:
732: /* Process the message. */
733: message_done:
734: if (p -> verify_result != ISC_R_SUCCESS) {
735: status = omapi_protocol_send_status
736: (h, (omapi_object_t *)0, p -> verify_result,
737: p -> message -> id, (char *)0);
738: } else {
739: status = omapi_message_process
740: ((omapi_object_t *)p -> message, h);
741: }
742: if (status != ISC_R_SUCCESS) {
743: omapi_disconnect (c, 1);
744: return ISC_R_NOMEMORY;
745: }
746:
747: omapi_message_dereference (&p -> message, MDL);
748: #if defined (DEBUG_MEMORY_LEAKAGE)
749: log_info ("generation %ld: %ld new, %ld outstanding, %ld%s",
750: dmalloc_generation,
751: dmalloc_outstanding - previous_outstanding,
752: dmalloc_outstanding, dmalloc_longterm, " long-term");
753: #endif
754: #if (defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MALLOC_POOL))
755: dmalloc_dump_outstanding ();
756: #endif
757: #if defined (DEBUG_RC_HISTORY_EXHAUSTIVELY)
758: dump_rc_history (h);
759: #endif
760: #if defined (DEBUG_MEMORY_LEAKAGE)
761: previous_outstanding = 0xDEADBEEF;
762: #endif
763: /* Now wait for the next message. */
764: goto to_header_wait;
765:
766: default:
767: /* XXX should never get here. Assertion? */
768: break;
769: }
770: return ISC_R_SUCCESS;
771: }
772:
773: isc_result_t omapi_protocol_add_auth (omapi_object_t *po,
774: omapi_object_t *ao,
775: omapi_handle_t handle)
776: {
777: omapi_protocol_object_t *p;
778: omapi_remote_auth_t *r;
779: isc_result_t status;
780:
781: if (ao -> type != omapi_type_auth_key &&
782: (!ao -> inner || ao -> inner -> type != omapi_type_auth_key))
783: return DHCP_R_INVALIDARG;
784:
785: if (po -> type != omapi_type_protocol)
786: return DHCP_R_INVALIDARG;
787: p = (omapi_protocol_object_t *)po;
788:
789: #ifdef DEBUG_PROTOCOL
790: log_debug ("omapi_protocol_add_auth(name=%s)",
791: ((omapi_auth_key_t *)ao) -> name);
792: #endif
793:
794: if (p -> verify_auth) {
795: status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao);
796: if (status != ISC_R_SUCCESS)
797: return status;
798: }
799:
800: /* If omapi_protocol_connect() was called with a default
801: authenticator, p -> default_auth will already be set,
802: but p -> remote_auth_list will not yet be initialized. */
803: if (p -> default_auth && !p -> remote_auth_list) {
804: if (p -> default_auth -> a != ao) {
805: /* Something just went horribly wrong. */
806: omapi_disconnect (p -> outer, 1);
807: return ISC_R_UNEXPECTED;
808: }
809:
810: p -> remote_auth_list = p -> default_auth;
811: p -> default_auth -> remote_handle = handle;
812:
813: return omapi_signal_in (p -> inner, "ready");
814: }
815:
816: r = dmalloc (sizeof(*r), MDL);
817: if (!r)
818: return ISC_R_NOMEMORY;
819:
820: status = omapi_object_reference (&r -> a, ao, MDL);
821: if (status != ISC_R_SUCCESS) {
822: dfree (r, MDL);
823: return status;
824: }
825:
826: r -> remote_handle = handle;
827: r -> next = p -> remote_auth_list;
828: p -> remote_auth_list = r;
829:
830: return ISC_R_SUCCESS;
831: }
832:
833: isc_result_t omapi_protocol_lookup_auth (omapi_object_t **a,
834: omapi_object_t *po,
835: omapi_handle_t handle)
836: {
837: omapi_protocol_object_t *p;
838: omapi_remote_auth_t *r;
839:
840: if (po -> type != omapi_type_protocol)
841: return DHCP_R_INVALIDARG;
842: p = (omapi_protocol_object_t *)po;
843:
844: for (r = p -> remote_auth_list; r; r = r -> next)
845: if (r -> remote_handle == handle)
846: return omapi_object_reference (a, r -> a, MDL);
847:
848: return DHCP_R_KEY_UNKNOWN;
849: }
850:
851: isc_result_t omapi_protocol_set_value (omapi_object_t *h,
852: omapi_object_t *id,
853: omapi_data_string_t *name,
854: omapi_typed_data_t *value)
855: {
856: omapi_protocol_object_t *p;
857: omapi_remote_auth_t *r;
858:
859: if (h -> type != omapi_type_protocol)
860: return DHCP_R_INVALIDARG;
861: p = (omapi_protocol_object_t *)h;
862:
863: if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
864: if (!value || value -> type != omapi_datatype_object)
865: return DHCP_R_INVALIDARG;
866:
867: if (!value -> u.object) {
868: p -> default_auth = (omapi_remote_auth_t *)0;
869: } else {
870: for (r = p -> remote_auth_list; r; r = r -> next)
871: if (r -> a == value -> u.object)
872: break;
873:
874: if (!r)
875: return DHCP_R_KEY_UNKNOWN;
876:
877: p -> default_auth = r;
878: }
879:
880: return ISC_R_SUCCESS;
881: }
882:
883: if (h -> inner && h -> inner -> type -> set_value)
884: return (*(h -> inner -> type -> set_value))
885: (h -> inner, id, name, value);
886: return ISC_R_NOTFOUND;
887: }
888:
889: isc_result_t omapi_protocol_get_value (omapi_object_t *h,
890: omapi_object_t *id,
891: omapi_data_string_t *name,
892: omapi_value_t **value)
893: {
894: omapi_protocol_object_t *p;
895:
896: if (h -> type != omapi_type_protocol)
897: return DHCP_R_INVALIDARG;
898: p = (omapi_protocol_object_t *)h;
899:
900: if (omapi_ds_strcmp (name, "default-authenticator") == 0) {
901: if (!p -> default_auth)
902: return ISC_R_NOTFOUND;
903:
904: return omapi_make_object_value (value, name,
905: p -> default_auth -> a, MDL);
906: }
907:
908: if (h -> inner && h -> inner -> type -> get_value)
909: return (*(h -> inner -> type -> get_value))
910: (h -> inner, id, name, value);
911: return ISC_R_NOTFOUND;
912: }
913:
914: isc_result_t omapi_protocol_destroy (omapi_object_t *h,
915: const char *file, int line)
916: {
917: omapi_protocol_object_t *p;
918: if (h -> type != omapi_type_protocol)
919: return DHCP_R_INVALIDARG;
920: p = (omapi_protocol_object_t *)h;
921: if (p -> message)
922: omapi_message_dereference (&p -> message, file, line);
923:
924: /* This will happen if: 1) A default authenticator is supplied to
925: omapi_protocol_connect(), and 2) something goes wrong before
926: the authenticator can be opened. */
927: if (p -> default_auth && !p -> remote_auth_list)
928: dfree (p -> default_auth, file, line);
929:
930: while (p -> remote_auth_list) {
931: omapi_remote_auth_t *r = p -> remote_auth_list;
932: p -> remote_auth_list = p -> remote_auth_list -> next;
933: omapi_object_dereference (&r -> a, file, line);
934: dfree (r, file, line);
935: }
936: return ISC_R_SUCCESS;
937: }
938:
939: /* Write all the published values associated with the object through the
940: specified connection. */
941:
942: isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
943: omapi_object_t *id,
944: omapi_object_t *p)
945: {
946: if (p -> type != omapi_type_protocol)
947: return DHCP_R_INVALIDARG;
948:
949: if (p -> inner && p -> inner -> type -> stuff_values)
950: return (*(p -> inner -> type -> stuff_values)) (c, id,
951: p -> inner);
952: return ISC_R_SUCCESS;
953: }
954:
955: /* Returns a boolean indicating whether this protocol requires that
956: messages be authenticated or not. */
957:
958: isc_boolean_t omapi_protocol_authenticated (omapi_object_t *h)
959: {
960: if (h -> type != omapi_type_protocol)
961: return isc_boolean_false;
962: if (((omapi_protocol_object_t *)h) -> insecure)
963: return isc_boolean_false;
964: else
965: return isc_boolean_true;
966: }
967:
968: /* Sets the address and authenticator verification callbacks. The handle
969: is to a listener object, not a protocol object. */
970:
971: isc_result_t omapi_protocol_configure_security (omapi_object_t *h,
972: isc_result_t (*verify_addr)
973: (omapi_object_t *,
974: omapi_addr_t *),
975: isc_result_t (*verify_auth)
976: (omapi_object_t *,
977: omapi_auth_key_t *))
978: {
979: omapi_protocol_listener_object_t *l;
980:
981: if (h -> outer && h -> outer -> type == omapi_type_protocol_listener)
982: h = h -> outer;
983:
984: if (h -> type != omapi_type_protocol_listener)
985: return DHCP_R_INVALIDARG;
986: l = (omapi_protocol_listener_object_t *)h;
987:
988: l -> verify_auth = verify_auth;
989: l -> insecure = 0;
990:
991: if (h -> outer != NULL) {
992: return omapi_listener_configure_security (h -> outer, verify_addr);
993: } else {
994: return DHCP_R_INVALIDARG;
995: }
996: }
997:
998:
999: /* Set up a listener for the omapi protocol. The handle stored points to
1000: a listener object, not a protocol object. */
1001:
1002: isc_result_t omapi_protocol_listen (omapi_object_t *h,
1003: unsigned port,
1004: int max)
1005: {
1006: isc_result_t status;
1007: omapi_protocol_listener_object_t *obj;
1008:
1009: obj = (omapi_protocol_listener_object_t *)0;
1010: status = omapi_protocol_listener_allocate (&obj, MDL);
1011: if (status != ISC_R_SUCCESS)
1012: return status;
1013:
1014: status = omapi_object_reference (&h -> outer,
1015: (omapi_object_t *)obj, MDL);
1016: if (status != ISC_R_SUCCESS) {
1017: omapi_protocol_listener_dereference (&obj, MDL);
1018: return status;
1019: }
1020: status = omapi_object_reference (&obj -> inner, h, MDL);
1021: if (status != ISC_R_SUCCESS) {
1022: omapi_protocol_listener_dereference (&obj, MDL);
1023: return status;
1024: }
1025:
1026: /* What a terrible default. */
1027: obj -> insecure = 1;
1028:
1029: status = omapi_listen ((omapi_object_t *)obj, port, max);
1030: omapi_protocol_listener_dereference (&obj, MDL);
1031: return status;
1032: }
1033:
1034: /* Signal handler for protocol listener - if we get a connect signal,
1035: create a new protocol connection, otherwise pass the signal down. */
1036:
1037: isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
1038: const char *name, va_list ap)
1039: {
1040: isc_result_t status;
1041: omapi_object_t *c;
1042: omapi_protocol_object_t *obj;
1043: omapi_protocol_listener_object_t *p;
1044:
1045: if (!o || o -> type != omapi_type_protocol_listener)
1046: return DHCP_R_INVALIDARG;
1047: p = (omapi_protocol_listener_object_t *)o;
1048:
1049: /* Not a signal we recognize? */
1050: if (strcmp (name, "connect")) {
1051: if (p -> inner && p -> inner -> type -> signal_handler)
1052: return (*(p -> inner -> type -> signal_handler))
1053: (p -> inner, name, ap);
1054: return ISC_R_NOTFOUND;
1055: }
1056:
1057: c = va_arg (ap, omapi_object_t *);
1058: if (!c || c -> type != omapi_type_connection)
1059: return DHCP_R_INVALIDARG;
1060:
1061: obj = (omapi_protocol_object_t *)0;
1062: status = omapi_protocol_allocate (&obj, MDL);
1063: if (status != ISC_R_SUCCESS)
1064: return status;
1065:
1066: obj -> verify_auth = p -> verify_auth;
1067: obj -> insecure = p -> insecure;
1068:
1069: status = omapi_object_reference (&obj -> outer, c, MDL);
1070: if (status != ISC_R_SUCCESS) {
1071: lose:
1072: omapi_protocol_dereference (&obj, MDL);
1073: omapi_disconnect (c, 1);
1074: return status;
1075: }
1076:
1077: status = omapi_object_reference (&c -> inner,
1078: (omapi_object_t *)obj, MDL);
1079: if (status != ISC_R_SUCCESS)
1080: goto lose;
1081:
1082: /* Send the introductory message. */
1083: status = omapi_protocol_send_intro ((omapi_object_t *)obj,
1084: OMAPI_PROTOCOL_VERSION,
1085: sizeof (omapi_protocol_header_t));
1086: if (status != ISC_R_SUCCESS)
1087: goto lose;
1088:
1089: omapi_protocol_dereference (&obj, MDL);
1090: return status;
1091: }
1092:
1093: isc_result_t omapi_protocol_listener_set_value (omapi_object_t *h,
1094: omapi_object_t *id,
1095: omapi_data_string_t *name,
1096: omapi_typed_data_t *value)
1097: {
1098: if (h -> type != omapi_type_protocol_listener)
1099: return DHCP_R_INVALIDARG;
1100:
1101: if (h -> inner && h -> inner -> type -> set_value)
1102: return (*(h -> inner -> type -> set_value))
1103: (h -> inner, id, name, value);
1104: return ISC_R_NOTFOUND;
1105: }
1106:
1107: isc_result_t omapi_protocol_listener_get_value (omapi_object_t *h,
1108: omapi_object_t *id,
1109: omapi_data_string_t *name,
1110: omapi_value_t **value)
1111: {
1112: if (h -> type != omapi_type_protocol_listener)
1113: return DHCP_R_INVALIDARG;
1114:
1115: if (h -> inner && h -> inner -> type -> get_value)
1116: return (*(h -> inner -> type -> get_value))
1117: (h -> inner, id, name, value);
1118: return ISC_R_NOTFOUND;
1119: }
1120:
1121: isc_result_t omapi_protocol_listener_destroy (omapi_object_t *h,
1122: const char *file, int line)
1123: {
1124: if (h -> type != omapi_type_protocol_listener)
1125: return DHCP_R_INVALIDARG;
1126: return ISC_R_SUCCESS;
1127: }
1128:
1129: /* Write all the published values associated with the object through the
1130: specified connection. */
1131:
1132: isc_result_t omapi_protocol_listener_stuff (omapi_object_t *c,
1133: omapi_object_t *id,
1134: omapi_object_t *p)
1135: {
1136: if (p -> type != omapi_type_protocol_listener)
1137: return DHCP_R_INVALIDARG;
1138:
1139: if (p -> inner && p -> inner -> type -> stuff_values)
1140: return (*(p -> inner -> type -> stuff_values)) (c, id,
1141: p -> inner);
1142: return ISC_R_SUCCESS;
1143: }
1144:
1145: isc_result_t omapi_protocol_send_status (omapi_object_t *po,
1146: omapi_object_t *id,
1147: isc_result_t waitstatus,
1148: unsigned rid, const char *msg)
1149: {
1150: isc_result_t status;
1151: omapi_message_object_t *message = (omapi_message_object_t *)0;
1152: omapi_object_t *mo;
1153:
1154: if (po -> type != omapi_type_protocol)
1155: return DHCP_R_INVALIDARG;
1156:
1157: status = omapi_message_new ((omapi_object_t **)&message, MDL);
1158: if (status != ISC_R_SUCCESS)
1159: return status;
1160: mo = (omapi_object_t *)message;
1161:
1162: status = omapi_set_int_value (mo, (omapi_object_t *)0,
1163: "op", OMAPI_OP_STATUS);
1164: if (status != ISC_R_SUCCESS) {
1165: omapi_message_dereference (&message, MDL);
1166: return status;
1167: }
1168:
1169: status = omapi_set_int_value (mo, (omapi_object_t *)0,
1170: "rid", (int)rid);
1171: if (status != ISC_R_SUCCESS) {
1172: omapi_message_dereference (&message, MDL);
1173: return status;
1174: }
1175:
1176: status = omapi_set_int_value (mo, (omapi_object_t *)0,
1177: "result", (int)waitstatus);
1178: if (status != ISC_R_SUCCESS) {
1179: omapi_message_dereference (&message, MDL);
1180: return status;
1181: }
1182:
1183: /* If a message has been provided, send it. */
1184: if (msg) {
1185: status = omapi_set_string_value (mo, (omapi_object_t *)0,
1186: "message", msg);
1187: if (status != ISC_R_SUCCESS) {
1188: omapi_message_dereference (&message, MDL);
1189: return status;
1190: }
1191: }
1192:
1193: status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
1194: omapi_message_dereference (&message, MDL);
1195: return status;
1196: }
1197:
1198: /* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the
1199: message to be set to the protocol object. This is used when opening
1200: the default authenticator. */
1201:
1202: isc_result_t omapi_protocol_send_open (omapi_object_t *po,
1203: omapi_object_t *id,
1204: const char *type,
1205: omapi_object_t *object,
1206: unsigned flags)
1207: {
1208: isc_result_t status;
1209: omapi_message_object_t *message = (omapi_message_object_t *)0;
1210: omapi_object_t *mo;
1211:
1212: if (po -> type != omapi_type_protocol)
1213: return DHCP_R_INVALIDARG;
1214:
1215: status = omapi_message_new ((omapi_object_t **)&message, MDL);
1216: mo = (omapi_object_t *)message;
1217:
1218: if (status == ISC_R_SUCCESS)
1219: status = omapi_set_int_value (mo, (omapi_object_t *)0,
1220: "op", OMAPI_OP_OPEN);
1221:
1222: if (status == ISC_R_SUCCESS)
1223: status = omapi_set_object_value (mo, (omapi_object_t *)0,
1224: "object", object);
1225:
1226: if ((flags & OMAPI_CREATE) && (status == ISC_R_SUCCESS))
1227: status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1228: "create", 1);
1229:
1230: if ((flags & OMAPI_UPDATE) && (status == ISC_R_SUCCESS))
1231: status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1232: "update", 1);
1233:
1234: if ((flags & OMAPI_EXCL) && (status == ISC_R_SUCCESS))
1235: status = omapi_set_boolean_value (mo, (omapi_object_t *)0,
1236: "exclusive", 1);
1237:
1238: if ((flags & OMAPI_NOTIFY_PROTOCOL) && (status == ISC_R_SUCCESS))
1239: status = omapi_set_object_value (mo, (omapi_object_t *)0,
1240: "notify-object", po);
1241:
1242: if (type && (status == ISC_R_SUCCESS))
1243: status = omapi_set_string_value (mo, (omapi_object_t *)0,
1244: "type", type);
1245:
1246: if (status == ISC_R_SUCCESS)
1247: status = omapi_message_register (mo);
1248:
1249: if (status == ISC_R_SUCCESS) {
1250: status = omapi_protocol_send_message (po, id, mo,
1251: (omapi_object_t *)0);
1252: if (status != ISC_R_SUCCESS)
1253: omapi_message_unregister (mo);
1254: }
1255:
1256: if (message)
1257: omapi_message_dereference (&message, MDL);
1258:
1259: return status;
1260: }
1261:
1262: isc_result_t omapi_protocol_send_update (omapi_object_t *po,
1263: omapi_object_t *id,
1264: unsigned rid,
1265: omapi_object_t *object)
1266: {
1267: isc_result_t status;
1268: omapi_message_object_t *message = (omapi_message_object_t *)0;
1269: omapi_object_t *mo;
1270:
1271: if (po -> type != omapi_type_protocol)
1272: return DHCP_R_INVALIDARG;
1273:
1274: status = omapi_message_new ((omapi_object_t **)&message, MDL);
1275: if (status != ISC_R_SUCCESS)
1276: return status;
1277: mo = (omapi_object_t *)message;
1278:
1279: status = omapi_set_int_value (mo, (omapi_object_t *)0,
1280: "op", OMAPI_OP_UPDATE);
1281: if (status != ISC_R_SUCCESS) {
1282: omapi_message_dereference (&message, MDL);
1283: return status;
1284: }
1285:
1286: if (rid) {
1287: omapi_handle_t handle;
1288: status = omapi_set_int_value (mo, (omapi_object_t *)0,
1289: "rid", (int)rid);
1290: if (status != ISC_R_SUCCESS) {
1291: omapi_message_dereference (&message, MDL);
1292: return status;
1293: }
1294:
1295: status = omapi_object_handle (&handle, object);
1296: if (status != ISC_R_SUCCESS) {
1297: omapi_message_dereference (&message, MDL);
1298: return status;
1299: }
1300: status = omapi_set_int_value (mo, (omapi_object_t *)0,
1301: "handle", (int)handle);
1302: if (status != ISC_R_SUCCESS) {
1303: omapi_message_dereference (&message, MDL);
1304: return status;
1305: }
1306: }
1307:
1308: status = omapi_set_object_value (mo, (omapi_object_t *)0,
1309: "object", object);
1310: if (status != ISC_R_SUCCESS) {
1311: omapi_message_dereference (&message, MDL);
1312: return status;
1313: }
1314:
1315: status = omapi_protocol_send_message (po, id, mo, (omapi_object_t *)0);
1316: omapi_message_dereference (&message, MDL);
1317: return status;
1318: }
CVSweb <webmaster@jp.NetBSD.org>