diff options
-rw-r--r-- | Makefile.dist | 2 | ||||
-rw-r--r-- | client/clparse.c | 5 | ||||
-rw-r--r-- | common/alloc.c | 133 | ||||
-rw-r--r-- | common/dns.c | 51 | ||||
-rw-r--r-- | common/parse.c | 30 | ||||
-rw-r--r-- | dhcpctl/Makefile.dist | 8 | ||||
-rw-r--r-- | dhcpctl/cltest.c | 77 | ||||
-rw-r--r-- | dhcpctl/dhcpctl.c | 1 | ||||
-rw-r--r-- | dhcpctl/dhcpctl.h | 12 | ||||
-rw-r--r-- | dhcpctl/remote.c | 50 | ||||
-rw-r--r-- | includes/auth.h | 59 | ||||
-rw-r--r-- | includes/dhcpd.h | 26 | ||||
-rw-r--r-- | includes/omapip/omapip.h | 52 | ||||
-rw-r--r-- | includes/omapip/omapip_p.h | 37 | ||||
-rw-r--r-- | minires/dst_api.c | 8 | ||||
-rw-r--r-- | omapip/Makefile.dist | 8 | ||||
-rw-r--r-- | omapip/auth.c | 271 | ||||
-rw-r--r-- | omapip/buffer.c | 28 | ||||
-rw-r--r-- | omapip/connection.c | 225 | ||||
-rw-r--r-- | omapip/dispatch.c | 11 | ||||
-rw-r--r-- | omapip/listener.c | 43 | ||||
-rw-r--r-- | omapip/message.c | 165 | ||||
-rw-r--r-- | omapip/protocol.c | 447 | ||||
-rw-r--r-- | omapip/support.c | 49 | ||||
-rw-r--r-- | relay/Makefile.dist | 2 | ||||
-rw-r--r-- | server/dhcpd.c | 38 | ||||
-rw-r--r-- | server/stables.c | 4 |
27 files changed, 1467 insertions, 375 deletions
diff --git a/Makefile.dist b/Makefile.dist index e51feb24..57802349 100644 --- a/Makefile.dist +++ b/Makefile.dist @@ -17,7 +17,7 @@ # http://www.isc.org for more information. # -SUBDIRS= common omapip $(MINIRES) server client relay dhcpctl +SUBDIRS= common $(MINIRES) omapip server client relay dhcpctl all: @for dir in ${SUBDIRS}; do \ diff --git a/client/clparse.c b/client/clparse.c index 48ffa7d1..97915253 100644 --- a/client/clparse.c +++ b/client/clparse.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: clparse.c,v 1.48 2000/07/20 00:53:17 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: clparse.c,v 1.49 2000/08/03 20:59:31 neild Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -948,7 +948,8 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp) skip_to_semi (cfile); break; } - if (tsig_key_lookup (&lease -> key, val) != ISC_R_SUCCESS) + if (omapi_auth_key_lookup_name (&lease -> key, val) != + ISC_R_SUCCESS) parse_warn (cfile, "unknown key %s", val); parse_semi (cfile); break; diff --git a/common/alloc.c b/common/alloc.c index 7cb83e19..040d826a 100644 --- a/common/alloc.c +++ b/common/alloc.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: alloc.c,v 1.51 2000/08/01 22:54:47 neild Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: alloc.c,v 1.52 2000/08/03 20:59:33 neild Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -292,29 +292,6 @@ void free_client_lease (lease, file, line) dfree (lease, file, line); } -struct auth_key *new_auth_key (len, file, line) - unsigned len; - const char *file; - int line; -{ - struct auth_key *peer; - unsigned size = len - 1 + sizeof (struct auth_key); - - peer = (struct auth_key *)dmalloc (size, file, line); - if (!peer) - return peer; - memset (peer, 0, size); - return peer; -} - -void free_auth_key (peer, file, line) - struct auth_key *peer; - const char *file; - int line; -{ - dfree (peer, file, line); -} - pair free_pairs; pair new_pair (file, line) @@ -1002,114 +979,6 @@ int packet_dereference (ptr, file, line) return 1; } -int tsig_key_allocate (ptr, file, line) - struct tsig_key **ptr; - const char *file; - int line; -{ - int size; - - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct tsig_key *)0; -#endif - } - - *ptr = dmalloc (sizeof **ptr, file, line); - if (*ptr) { - memset (*ptr, 0, sizeof **ptr); - (*ptr) -> refcnt = 1; - return 1; - } - return 0; -} - -int tsig_key_reference (ptr, bp, file, line) - struct tsig_key **ptr; - struct tsig_key *bp; - const char *file; - int line; -{ - if (!ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - if (*ptr) { - log_error ("%s(%d): non-null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - *ptr = (struct tsig_key *)0; -#endif - } - *ptr = bp; - bp -> refcnt++; - rc_register (file, line, ptr, bp, bp -> refcnt); - dmalloc_reuse (bp, file, line, 1); - return 1; -} - -int tsig_key_dereference (ptr, file, line) - struct tsig_key **ptr; - const char *file; - int line; -{ - int i; - struct tsig_key *tsig_key; - - if (!ptr || !*ptr) { - log_error ("%s(%d): null pointer", file, line); -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - tsig_key = *ptr; - *ptr = (struct tsig_key *)0; - --tsig_key -> refcnt; - rc_register (file, line, ptr, tsig_key, tsig_key -> refcnt); - if (tsig_key -> refcnt > 0) - return 1; - - if (tsig_key -> refcnt < 0) { - log_error ("%s(%d): negative refcnt!", file, line); -#if defined (DEBUG_RC_HISTORY) - dump_rc_history (); -#endif -#if defined (POINTER_DEBUG) - abort (); -#else - return 0; -#endif - } - - if (tsig_key -> name) - dfree (tsig_key -> name, file, line); - if (tsig_key -> algorithm) - dfree (tsig_key -> algorithm, file, line); - if (tsig_key -> key.buffer) - data_string_forget (&tsig_key -> key, file, line); - dfree (tsig_key, file, line); - return 1; -} - int dns_zone_allocate (ptr, file, line) struct dns_zone **ptr; const char *file; diff --git a/common/dns.c b/common/dns.c index 0d029da9..31800bfc 100644 --- a/common/dns.c +++ b/common/dns.c @@ -42,7 +42,7 @@ #ifndef lint static char copyright[] = -"$Id: dns.c,v 1.26 2000/07/05 07:14:26 mellon Exp $ Copyright (c) 2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: dns.c,v 1.27 2000/08/03 20:59:34 neild Exp $ Copyright (c) 2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -158,7 +158,7 @@ isc_result_t find_tsig_key (ns_tsig_key **key, const char *zname, strlen (zone -> key -> name) > NS_MAXDNAME) || (!zone -> key -> algorithm || strlen (zone -> key -> algorithm) > NS_MAXDNAME) || - (!zone -> key -> key.len)) { + (!zone -> key)) { dns_zone_dereference (&zone, MDL); return ISC_R_INVALIDKEY; } @@ -169,7 +169,7 @@ isc_result_t find_tsig_key (ns_tsig_key **key, const char *zname, return ISC_R_NOMEMORY; } memset (tkey, 0, sizeof *tkey); - tkey -> data = dmalloc (zone -> key -> key.len, MDL); + tkey -> data = dmalloc (zone -> key -> key -> len, MDL); if (!tkey -> data) { dfree (tkey, MDL); goto nomem; @@ -177,8 +177,8 @@ isc_result_t find_tsig_key (ns_tsig_key **key, const char *zname, strcpy (tkey -> name, zone -> key -> name); strcpy (tkey -> alg, zone -> key -> algorithm); memcpy (tkey -> data, - zone -> key -> key.data, zone -> key -> key.len); - tkey -> len = zone -> key -> key.len; + zone -> key -> key -> value, zone -> key -> key -> len); + tkey -> len = zone -> key -> key -> len; *key = tkey; return ISC_R_SUCCESS; } @@ -249,44 +249,6 @@ isc_result_t dns_zone_lookup (struct dns_zone **zone, const char *name) return status; } -isc_result_t enter_tsig_key (struct tsig_key *tkey) -{ - struct tsig_key *tk = (struct tsig_key *)0; - - if (tsig_key_hash) { - tsig_key_hash_lookup (&tk, tsig_key_hash, - tkey -> name, 0, MDL); - if (tk == tkey) { - tsig_key_dereference (&tk, MDL); - return ISC_R_SUCCESS; - } - if (tk) { - tsig_key_hash_delete (tsig_key_hash, - tkey -> name, 0, MDL); - tsig_key_dereference (&tk, MDL); - } - } else { - tsig_key_hash = - new_hash ((hash_reference)tsig_key_reference, - (hash_dereference)tsig_key_dereference, 1); - if (!tsig_key_hash) - return ISC_R_NOMEMORY; - } - tsig_key_hash_add (tsig_key_hash, tkey -> name, 0, tkey, MDL); - return ISC_R_SUCCESS; - -} - -isc_result_t tsig_key_lookup (struct tsig_key **tkey, const char *name) { - struct tsig_key *tk; - - if (!tsig_key_hash) - return ISC_R_NOTFOUND; - if (!tsig_key_hash_lookup (tkey, tsig_key_hash, name, 0, MDL)) - return ISC_R_NOTFOUND; - return ISC_R_SUCCESS; -} - int dns_zone_dereference (ptr, file, line) struct dns_zone **ptr; const char *file; @@ -326,7 +288,7 @@ int dns_zone_dereference (ptr, file, line) if (dns_zone -> name) dfree (dns_zone -> name, file, line); if (dns_zone -> key) - tsig_key_dereference (&dns_zone -> key, file, line); + omapi_auth_key_dereference (&dns_zone -> key, file, line); if (dns_zone -> primary) option_cache_dereference (&dns_zone -> primary, file, line); if (dns_zone -> secondary) @@ -447,4 +409,3 @@ void repudiate_zone (struct dns_zone **zone) #endif /* NSUPDATE */ HASH_FUNCTIONS (dns_zone, const char *, struct dns_zone) -HASH_FUNCTIONS (tsig_key, const char *, struct tsig_key) diff --git a/common/parse.c b/common/parse.c index fdbf6598..30f7c641 100644 --- a/common/parse.c +++ b/common/parse.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: parse.c,v 1.77 2000/07/06 09:57:23 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: parse.c,v 1.78 2000/08/03 20:59:36 neild Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -1806,7 +1806,8 @@ int parse_zone (struct dns_zone *zone, struct parse *cfile) skip_to_semi (cfile); return 0; } - if (tsig_key_lookup (&zone -> key, val) != ISC_R_SUCCESS) + if (omapi_auth_key_lookup_name (&zone -> key, val) != + ISC_R_SUCCESS) parse_warn (cfile, "unknown key %s", val); if (!parse_semi (cfile)) return 0; @@ -1839,7 +1840,8 @@ int parse_key (struct parse *cfile) int token; const char *val; int done = 0; - struct tsig_key *key; + struct auth_key *key; + struct data_string ds; isc_result_t status; token = next_token (&val, cfile); @@ -1848,8 +1850,8 @@ int parse_key (struct parse *cfile) skip_to_semi (cfile); return 0; } - key = (struct tsig_key *)0; - if (!tsig_key_allocate (&key, MDL)) + key = (struct auth_key *)0; + if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS) log_fatal ("no memory for tsig key"); key -> name = dmalloc (strlen (val) + 1, MDL); if (!key -> name) @@ -1883,13 +1885,23 @@ int parse_key (struct parse *cfile) break; case SECRET: - if (key -> key.buffer) { + if (key -> key) { parse_warn (cfile, "key %s: too many secrets", key -> name); goto rbad; } - if (!parse_base64 (&key -> key, cfile)) + + memset (&ds, 0, sizeof(ds)); + if (!parse_base64 (&ds, cfile)) + goto rbad; + status = omapi_data_string_new (&key -> key, ds.len, + MDL); + if (status != ISC_R_SUCCESS) goto rbad; + memcpy (key -> key -> value, + ds.buffer -> data, ds.len); + data_string_forget (&ds, MDL); + if (!parse_semi (cfile)) goto rbad; break; @@ -1910,7 +1922,7 @@ int parse_key (struct parse *cfile) token = next_token (&val, cfile); /* Remember the key. */ - status = enter_tsig_key (key); + status = omapi_auth_key_enter (key); if (status != ISC_R_SUCCESS) { parse_warn (cfile, "tsig key %s: %s", key -> name, isc_result_totext (status)); @@ -1921,7 +1933,7 @@ int parse_key (struct parse *cfile) rbad: skip_to_rbrace (cfile, 1); bad: - tsig_key_dereference (&key, MDL); + omapi_auth_key_dereference (&key, MDL); return 0; } /* diff --git a/dhcpctl/Makefile.dist b/dhcpctl/Makefile.dist index 24c875c5..03206b5d 100644 --- a/dhcpctl/Makefile.dist +++ b/dhcpctl/Makefile.dist @@ -30,13 +30,13 @@ CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) all: libdhcpctl.a svtest cltest $(CATMANPAGES) -svtest: test.o libdhcpctl.a ../omapip/libomapi.a +svtest: test.o libdhcpctl.a ../omapip/libomapi.a $(BINDLIB) $(CC) $(DEBUG) $(LFLAGS) -o svtest test.o libdhcpctl.a \ - ../omapip/libomapi.a $(LIBS) + ../omapip/libomapi.a $(BINDLIB) $(LIBS) -cltest: cltest.o libdhcpctl.a ../omapip/libomapi.a +cltest: cltest.o libdhcpctl.a ../omapip/libomapi.a $(BINDLIB) $(CC) $(DEBUG) $(LFLAGS) -o cltest cltest.o libdhcpctl.a \ - ../omapip/libomapi.a $(LIBS) + ../omapip/libomapi.a $(BINDLIB) $(LIBS) libdhcpctl.a: $(OBJ) rm -f libdhcpctl.a diff --git a/dhcpctl/cltest.c b/dhcpctl/cltest.c index 904f037e..cc4bba83 100644 --- a/dhcpctl/cltest.c +++ b/dhcpctl/cltest.c @@ -46,30 +46,61 @@ int main (int, char **); -enum modes { up, down }; +enum modes { up, down, undefined }; + +static void usage (char *s) { + fprintf (stderr, + "Usage: %s [-n <username>] [-p <password>] [-a <algorithm>]" + "(-u | -d) <if>\n", s); + exit (1); +} int main (argc, argv) int argc; char **argv; { isc_result_t status, waitstatus; + dhcpctl_handle authenticator; dhcpctl_handle connection; dhcpctl_handle host_handle, group_handle, interface_handle; dhcpctl_data_string cid; dhcpctl_data_string result, groupname, identifier; int i; - int mode; + int mode = undefined; + char *name = 0, *pass = 0, *algorithm = "hmac-md5", *interface = 0; const char *action; - - if (!strcmp (argv [1], "-u")) { - mode = up; - } else if (!strcmp (argv [1], "-d")) { - mode = down; - } else { - fprintf (stderr, "Unknown switch \"%s\"\n", argv [1]); - exit (1); + + for (i = 1; i < argc; i++) { + if (!strcmp (argv[i], "-u")) { + mode = up; + } else if (!strcmp (argv [1], "-d")) { + mode = down; + } else if (!strcmp (argv[i], "-n")) { + if (++i == argc) + usage(argv[0]); + name = argv[i]; + } else if (!strcmp (argv[i], "-p")) { + if (++i == argc) + usage(argv[0]); + pass = argv[i]; + } else if (!strcmp (argv[i], "-a")) { + if (++i == argc) + usage(argv[0]); + algorithm = argv[i]; + } else if (argv[i][0] == '-') { + usage(argv[0]); + } else { + interface = argv[i]; + } } + if (!interface) + usage(argv[0]); + if (mode == undefined) + usage(argv[0]); + if ((name || pass) && !(name && pass)) + usage(argv[0]); + status = dhcpctl_initialize (); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_initialize: %s\n", @@ -77,16 +108,29 @@ int main (argc, argv) exit (1); } - memset (&connection, 0, sizeof connection); + authenticator = dhcpctl_null_handle; + + if (name) { + status = dhcpctl_new_authenticator (&authenticator, + name, algorithm, pass, + strlen (pass) + 1); + if (status != ISC_R_SUCCESS) { + fprintf (stderr, "Cannot create authenticator: %s\n", + isc_result_totext (status)); + exit (1); + } + } + + connection = dhcpctl_null_handle; status = dhcpctl_connect (&connection, "127.0.0.1", 7911, - (dhcpctl_handle)0); + authenticator); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_connect: %s\n", isc_result_totext (status)); exit (1); } - memset (&interface_handle, 0, sizeof interface_handle); + interface_handle = dhcpctl_null_handle; status = dhcpctl_new_object (&interface_handle, connection, "interface"); if (status != ISC_R_SUCCESS) { @@ -95,7 +139,8 @@ int main (argc, argv) exit (1); } - status = dhcpctl_set_string_value (interface_handle, argv [2], "name"); + status = dhcpctl_set_string_value (interface_handle, + interface, "name"); if (status != ISC_R_SUCCESS) { fprintf (stderr, "dhcpctl_set_value: %s\n", isc_result_totext (status)); @@ -104,7 +149,7 @@ int main (argc, argv) if (mode == up) { /* "up" the interface */ - printf ("upping interface %s\n", argv [2]); + printf ("upping interface %s\n", interface); action = "create"; status = dhcpctl_open_object (interface_handle, connection, DHCPCTL_CREATE | DHCPCTL_EXCL); @@ -115,7 +160,7 @@ int main (argc, argv) } } else { /* down the interface */ - printf ("downing interface %s\n", argv [2]); + printf ("downing interface %s\n", interface); action = "remove"; status = dhcpctl_open_object (interface_handle, connection, 0); if (status != ISC_R_SUCCESS) { diff --git a/dhcpctl/dhcpctl.c b/dhcpctl/dhcpctl.c index 2a8e7bfb..cf1a6014 100644 --- a/dhcpctl/dhcpctl.c +++ b/dhcpctl/dhcpctl.c @@ -91,6 +91,7 @@ dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection, dhcpctl_handle authinfo) { isc_result_t status; + dhcpctl_status waitstatus; status = omapi_generic_new (connection, MDL); if (status != ISC_R_SUCCESS) { diff --git a/dhcpctl/dhcpctl.h b/dhcpctl/dhcpctl.h index 8eb9c812..afe70a2c 100644 --- a/dhcpctl/dhcpctl.h +++ b/dhcpctl/dhcpctl.h @@ -50,9 +50,11 @@ typedef isc_result_t dhcpctl_status; typedef omapi_object_t *dhcpctl_handle; typedef omapi_data_string_t *dhcpctl_data_string; -#define DHCPCTL_CREATE 1 -#define DHCPCTL_UPDATE 2 -#define DHCPCTL_EXCL 4 +#define dhcpctl_null_handle ((dhcpctl_handle) 0) + +#define DHCPCTL_CREATE OMAPI_CREATE +#define DHCPCTL_UPDATE OMAPI_UPDATE +#define DHCPCTL_EXCL OMAPI_EXCL typedef struct { OMAPI_OBJECT_PREAMBLE; @@ -105,6 +107,10 @@ isc_result_t dhcpctl_callback_stuff_values (omapi_object_t *, omapi_object_t *, omapi_object_t *); +dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *, + const char *, const char *, + const char *, unsigned); + dhcpctl_status dhcpctl_open_object (dhcpctl_handle, dhcpctl_handle, int); dhcpctl_status dhcpctl_new_object (dhcpctl_handle *, dhcpctl_handle, const char *); diff --git a/dhcpctl/remote.c b/dhcpctl/remote.c index 07a6e1d1..54650874 100644 --- a/dhcpctl/remote.c +++ b/dhcpctl/remote.c @@ -44,6 +44,56 @@ #include <omapip/omapip_p.h> #include "dhcpctl.h" +/* dhcpctl_new_authenticator + + synchronous - creates an authenticator object. + returns nonzero status code if the object couldn't be created + stores handle to authenticator through h if successful, and returns zero. + name is the authenticator name (NUL-terminated string). + algorithm is the NUL-terminated string name of the algorithm to use + (currently, only "hmac-md5" is supported). + secret and secret_len is the key secret. */ + +dhcpctl_status dhcpctl_new_authenticator (dhcpctl_handle *h, + const char *name, + const char *algorithm, + const char *secret, + unsigned secret_len) +{ + struct auth_key *key = (struct auth_key *)0; + isc_result_t status; + + status = omapi_auth_key_new (&key, MDL); + if (status != ISC_R_SUCCESS) + return status; + + key -> name = dmalloc (strlen (name) + 1, MDL); + if (!key -> name) { + omapi_auth_key_dereference (&key, MDL); + return ISC_R_NOMEMORY; + } + strcpy (key -> name, name); + + key -> algorithm = dmalloc (strlen (algorithm) + 1, MDL); + if (!key -> algorithm) { + omapi_auth_key_dereference (&key, MDL); + return ISC_R_NOMEMORY; + } + strcpy (key -> algorithm, algorithm); + + status = omapi_data_string_new (&key -> key, secret_len, MDL); + if (status != ISC_R_SUCCESS) { + omapi_auth_key_dereference (&key, MDL); + return status; + } + memcpy (key -> key -> value, secret, secret_len); + key -> key -> len = secret_len; + + *h = (dhcpctl_handle) key; + return ISC_R_SUCCESS; +} + + /* dhcpctl_new_object synchronous - creates a local handle for a host entry. diff --git a/includes/auth.h b/includes/auth.h deleted file mode 100644 index cc7dc065..00000000 --- a/includes/auth.h +++ /dev/null @@ -1,59 +0,0 @@ -/* auth.h - - Definitions to do with the DHCP authentication protocol... */ - -/* - * Copyright (c) 1996-1999 Internet Software Consortium. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The Internet Software Consortium nor the names - * of its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND - * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This software has been written for the Internet Software Consortium - * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. - * To learn more about the Internet Software Consortium, see - * ``http://www.isc.org/''. To learn more about Vixie Enterprises, - * see ``http://www.vix.com''. To learn more about Nominum, Inc., see - * ``http://www.nominum.com''. - */ - - -/* State structure for ongoing computation of a packet signature. */ - -struct signature_state { - u_int8_t *algorithm_state; - u_int8_t *output; - int output_len; - void (*update) PROTO ((u_int8_t *, u_int8_t *, u_int8_t *)); - void (*final) PROTO ((u_int8_t *, u_int8_t *)); -}; - -struct auth_key { - unsigned length; - u_int8_t data [1]; -}; - diff --git a/includes/dhcpd.h b/includes/dhcpd.h index f42307ec..9a008aff 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -74,7 +74,6 @@ #include "statement.h" #include "tree.h" #include "inet.h" -#include "auth.h" #include "dhctoken.h" #include <isc/result.h> @@ -373,6 +372,7 @@ struct lease_state { #define SV_LIMITED_BROADCAST_ADDRESS 33 #define SV_REMOTE_PORT 34 #define SV_LOCAL_ADDRESS 35 +#define SV_OMAPI_KEY 36 #if !defined (DEFAULT_DEFAULT_LEASE_TIME) # define DEFAULT_DEFAULT_LEASE_TIME 43200 @@ -589,13 +589,6 @@ struct class { struct executable_statement *statements; }; -struct tsig_key { - int refcnt; - char *name; - char *algorithm; - struct data_string key; -}; - /* DHCP client lease structure... */ struct client_lease { struct client_lease *next; /* Next lease in list. */ @@ -604,7 +597,7 @@ struct client_lease { char *server_name; /* Name of boot server. */ char *filename; /* Name of file we're supposed to boot. */ struct string_list *medium; /* Network medium. */ - struct tsig_key *key; /* Key used in basic DHCP authentication. */ + struct auth_key *key; /* Key used in basic DHCP authentication. */ unsigned int is_static : 1; /* If set, lease is from config file. */ unsigned int is_bootp: 1; /* If set, lease was aquired with BOOTP. */ @@ -819,7 +812,7 @@ struct dns_zone { char *name; struct option_cache *primary; struct option_cache *secondary; - struct tsig_key *key; + struct auth_key *key; }; /* Bitmask of dhcp option codes. */ @@ -1229,8 +1222,6 @@ void free_protocol PROTO ((struct protocol *, const char *, int)); void free_dhcp_packet PROTO ((struct dhcp_packet *, const char *, int)); struct client_lease *new_client_lease PROTO ((const char *, int)); void free_client_lease PROTO ((struct client_lease *, const char *, int)); -struct auth_key *new_auth_key PROTO ((unsigned, const char *, int)); -void free_auth_key PROTO ((struct auth_key *, const char *, int)); struct permit *new_permit PROTO ((const char *, int)); void free_permit PROTO ((struct permit *, const char *, int)); pair new_pair PROTO ((const char *, int)); @@ -1288,10 +1279,6 @@ int binding_scope_reference PROTO ((struct binding_scope **, int dns_zone_allocate PROTO ((struct dns_zone **, const char *, int)); int dns_zone_reference PROTO ((struct dns_zone **, struct dns_zone *, const char *, int)); -int tsig_key_allocate PROTO ((struct tsig_key **, const char *, int)); -int tsig_key_reference PROTO ((struct tsig_key **, - struct tsig_key *, const char *, int)); -int tsig_key_dereference PROTO ((struct tsig_key **, const char *, int)); /* print.c */ char *print_hw_addr PROTO ((int, int, unsigned char *)); @@ -1760,8 +1747,6 @@ void tkey_free (ns_tsig_key **); #endif isc_result_t enter_dns_zone (struct dns_zone *); isc_result_t dns_zone_lookup (struct dns_zone **, const char *); -isc_result_t enter_tsig_key (struct tsig_key *); -isc_result_t tsig_key_lookup (struct tsig_key **, const char *); int dns_zone_dereference PROTO ((struct dns_zone **, const char *, int)); #if defined (NSUPDATE) ns_rcode find_cached_zone (const char *, ns_class, char *, @@ -1771,7 +1756,6 @@ void forget_zone (struct dns_zone **); void repudiate_zone (struct dns_zone **); #endif /* NSUPDATE */ HASH_FUNCTIONS_DECL (dns_zone, const char *, struct dns_zone) -HASH_FUNCTIONS_DECL (tsig_key, const char *, struct tsig_key) /* resolv.c */ extern char path_resolv_conf []; @@ -1825,10 +1809,6 @@ int find_matching_case (struct executable_statement **, struct binding_scope **, struct expression *, struct executable_statement *); -/* auth.c */ -void enter_auth_key PROTO ((struct data_string *, struct auth_key *)); -const struct auth_key *auth_key_lookup PROTO ((struct data_string *)); - /* comapi.c */ extern omapi_object_type_t *dhcp_type_interface; extern omapi_object_type_t *dhcp_type_group; diff --git a/includes/omapip/omapip.h b/includes/omapip/omapip.h index c9c6b974..ecd80061 100644 --- a/includes/omapip/omapip.h +++ b/includes/omapip/omapip.h @@ -154,6 +154,18 @@ typedef struct { omapi_addr_t *addresses; } omapi_addr_list_t; +typedef struct auth_key { + OMAPI_OBJECT_PREAMBLE; + char *name; + char *algorithm; + omapi_data_string_t *key; +} omapi_auth_key_t; + +#define OMAPI_CREATE 1 +#define OMAPI_UPDATE 2 +#define OMAPI_EXCL 4 +#define OMAPI_NOTIFY_PROTOCOL 8 + #define OMAPI_OBJECT_ALLOC(name, stype, type) \ isc_result_t name##_allocate (stype **p, const char *file, int line) \ { \ @@ -184,9 +196,21 @@ isc_result_t omapi_protocol_connect (omapi_object_t *, isc_result_t omapi_connect_list (omapi_object_t *, omapi_addr_list_t *, omapi_addr_t *); isc_result_t omapi_protocol_listen (omapi_object_t *, unsigned, int); +isc_boolean_t omapi_protocol_authenticated (omapi_object_t *); +isc_result_t omapi_protocol_configure_security (omapi_object_t *, + isc_result_t (*) + (omapi_object_t *, + omapi_addr_t *), + isc_result_t (*) + (omapi_object_t *, + omapi_auth_key_t *)); isc_result_t omapi_protocol_accept (omapi_object_t *); isc_result_t omapi_protocol_send_intro (omapi_object_t *, unsigned, unsigned); isc_result_t omapi_protocol_ready (omapi_object_t *); +isc_result_t omapi_protocol_add_auth (omapi_object_t *, omapi_object_t *, + omapi_handle_t); +isc_result_t omapi_protocol_lookup_auth (omapi_object_t **, omapi_object_t *, + omapi_handle_t); isc_result_t omapi_protocol_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); @@ -221,6 +245,9 @@ isc_result_t omapi_protocol_listener_stuff (omapi_object_t *, omapi_object_t *); isc_result_t omapi_protocol_send_status (omapi_object_t *, omapi_object_t *, isc_result_t, unsigned, const char *); +isc_result_t omapi_protocol_send_open (omapi_object_t *, omapi_object_t *, + const char *, omapi_object_t *, + unsigned); isc_result_t omapi_protocol_send_update (omapi_object_t *, omapi_object_t *, unsigned, omapi_object_t *); @@ -232,6 +259,8 @@ isc_result_t omapi_connection_connect (omapi_object_t *); isc_result_t omapi_connection_reader (omapi_object_t *); isc_result_t omapi_connection_writer (omapi_object_t *); isc_result_t omapi_connection_reaper (omapi_object_t *); +isc_result_t omapi_connection_output_auth_length (omapi_object_t *, + unsigned *); isc_result_t omapi_connection_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); @@ -257,6 +286,10 @@ isc_result_t omapi_listen_addr (omapi_object_t *, isc_result_t omapi_listener_accept (omapi_object_t *); int omapi_listener_readfd (omapi_object_t *); isc_result_t omapi_accept (omapi_object_t *); +isc_result_t omapi_listener_configure_security (omapi_object_t *, + isc_result_t (*) + (omapi_object_t *, + omapi_addr_t *)); isc_result_t omapi_listener_set_value (omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *); @@ -324,6 +357,22 @@ isc_result_t omapi_message_register (omapi_object_t *); isc_result_t omapi_message_unregister (omapi_object_t *); isc_result_t omapi_message_process (omapi_object_t *, omapi_object_t *); +OMAPI_OBJECT_ALLOC_DECL (omapi_auth_key, + omapi_auth_key_t, omapi_type_auth_key) +isc_result_t omapi_auth_key_new (omapi_auth_key_t **, const char *, int); +isc_result_t omapi_auth_key_destroy (omapi_object_t *, const char *, int); +isc_result_t omapi_auth_key_enter (omapi_auth_key_t *); +isc_result_t omapi_auth_key_lookup_name (omapi_auth_key_t **, const char *); +isc_result_t omapi_auth_key_lookup (omapi_object_t **, + omapi_object_t *, + omapi_object_t *); +isc_result_t omapi_auth_key_get_value (omapi_object_t *, omapi_object_t *, + omapi_data_string_t *, + omapi_value_t **); +isc_result_t omapi_auth_key_stuff_values (omapi_object_t *, + omapi_object_t *, + omapi_object_t *); + extern omapi_object_type_t *omapi_type_connection; extern omapi_object_type_t *omapi_type_listener; extern omapi_object_type_t *omapi_type_io_object; @@ -333,6 +382,7 @@ extern omapi_object_type_t *omapi_type_protocol_listener; extern omapi_object_type_t *omapi_type_waiter; extern omapi_object_type_t *omapi_type_remote; extern omapi_object_type_t *omapi_type_message; +extern omapi_object_type_t *omapi_type_auth_key; extern omapi_object_type_t *omapi_object_types; @@ -408,6 +458,8 @@ isc_result_t omapi_make_int_value (omapi_value_t **, omapi_data_string_t *, int, const char *, int); isc_result_t omapi_make_uint_value (omapi_value_t **, omapi_data_string_t *, unsigned int, const char *, int); +isc_result_t omapi_make_object_value (omapi_value_t **, omapi_data_string_t *, + omapi_object_t *, const char *, int); isc_result_t omapi_make_handle_value (omapi_value_t **, omapi_data_string_t *, omapi_object_t *, const char *, int); isc_result_t omapi_make_string_value (omapi_value_t **, omapi_data_string_t *, diff --git a/includes/omapip/omapip_p.h b/includes/omapip/omapip_p.h index 74ef2e23..0661d970 100644 --- a/includes/omapip/omapip_p.h +++ b/includes/omapip/omapip_p.h @@ -68,6 +68,7 @@ #include "cdefs.h" #include "osdep.h" +#include <isc/dst.h> #include <isc/result.h> #include <omapip/convert.h> @@ -127,12 +128,17 @@ typedef struct __omapi_message_object { u_int32_t rid; } omapi_message_object_t; +typedef struct __omapi_remote_auth { + struct __omapi_remote_auth *next; + omapi_handle_t remote_handle; + omapi_object_t *a; +} omapi_remote_auth_t; + typedef struct { OMAPI_OBJECT_PREAMBLE; u_int32_t header_size; u_int32_t protocol_version; u_int32_t next_xid; - omapi_object_t *authinfo; /* Default authinfo to use. */ omapi_protocol_state_t state; /* Input state. */ int reading_message_values; /* True if reading message-specific @@ -140,10 +146,24 @@ typedef struct { omapi_message_object_t *message; /* Incoming message. */ omapi_data_string_t *name; /* Incoming name. */ omapi_typed_data_t *value; /* Incoming value. */ + isc_result_t verify_result; + omapi_remote_auth_t *default_auth; /* Default authinfo to use. */ + omapi_remote_auth_t *remote_auth_list; /* Authenticators active on + this connection. */ + + isc_boolean_t insecure; /* Set to allow unauthenticated + messages. */ + + isc_result_t (*verify_auth) (omapi_object_t *, omapi_auth_key_t *); } omapi_protocol_object_t; typedef struct { OMAPI_OBJECT_PREAMBLE; + + isc_boolean_t insecure; /* Set to allow unauthenticated + messages. */ + + isc_result_t (*verify_auth) (omapi_object_t *, omapi_auth_key_t *); } omapi_protocol_listener_object_t; #include <omapip/buffer.h> @@ -152,6 +172,7 @@ typedef struct __omapi_listener_object { OMAPI_OBJECT_PREAMBLE; int socket; /* Connection socket. */ struct sockaddr_in address; + isc_result_t (*verify_addr) (omapi_object_t *, omapi_addr_t *); } omapi_listener_object_t; typedef struct __omapi_connection_object { @@ -170,6 +191,12 @@ typedef struct __omapi_connection_object { omapi_buffer_t *outbufs; omapi_listener_object_t *listener; /* Listener that accepted this connection, if any. */ + DST_KEY *in_key; /* Authenticator signing incoming + data. */ + void *in_context; /* Input hash context. */ + DST_KEY *out_key; /* Authenticator signing outgoing + data. */ + void *out_context; /* Output hash context. */ } omapi_connection_object_t; typedef struct __omapi_io_object { @@ -191,6 +218,7 @@ typedef struct __omapi_generic_object { typedef struct __omapi_waiter_object { OMAPI_OBJECT_PREAMBLE; int ready; + isc_result_t waitstatus; struct __omapi_waiter_object *next; } omapi_waiter_object_t; @@ -226,6 +254,13 @@ OMAPI_OBJECT_ALLOC_DECL (omapi_generic, OMAPI_OBJECT_ALLOC_DECL (omapi_message, omapi_message_object_t, omapi_type_message) +isc_result_t omapi_connection_sign_data (int mode, + DST_KEY *key, + void **context, + const u_char *data, + const unsigned len, + omapi_typed_data_t **result); + extern int log_priority; extern int log_perror; extern void (*log_cleanup) (void); diff --git a/minires/dst_api.c b/minires/dst_api.c index 15e3ab55..69e68815 100644 --- a/minires/dst_api.c +++ b/minires/dst_api.c @@ -1,5 +1,5 @@ #ifndef LINT -static const char rcsid[] = "$Header: /tmp/cvstest/DHCP/minires/Attic/dst_api.c,v 1.2 2000/02/02 19:59:15 mellon Exp $"; +static const char rcsid[] = "$Header: /tmp/cvstest/DHCP/minires/Attic/dst_api.c,v 1.3 2000/08/03 21:00:05 neild Exp $"; #endif /* @@ -722,7 +722,8 @@ dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage, } memset(out_storage, 0, out_len); val = (u_int16_t)(key->dk_flags & 0xffff); - putUShort(out_storage, val); + out_storage[0] = (val >> 8) & 0xff; + out_storage[1] = val & 0xff; loc += 2; out_storage[loc++] = (u_char) key->dk_proto; @@ -730,7 +731,8 @@ dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage, if (key->dk_flags > 0xffff) { /* Extended flags */ val = (u_int16_t)((key->dk_flags >> 16) & 0xffff); - putUShort(&out_storage[loc], val); + out_storage[loc] = (val >> 8) & 0xff; + out_storage[loc+1] = val & 0xff; loc += 2; } if (key->dk_KEY_struct == NULL) diff --git a/omapip/Makefile.dist b/omapip/Makefile.dist index 9dd2dfb1..e7bec530 100644 --- a/omapip/Makefile.dist +++ b/omapip/Makefile.dist @@ -21,10 +21,10 @@ CATMANPAGES = omapi.cat3 SEDMANPAGES = omapi.man3 SRC = protocol.c buffer.c alloc.c result.c connection.c errwarn.c \ listener.c dispatch.c generic.c support.c handle.c message.c \ - convert.c hash.c + convert.c hash.c auth.c OBJ = protocol.o buffer.o alloc.o result.o connection.o errwarn.o \ listener.o dispatch.o generic.o support.o handle.o message.o \ - convert.o hash.o + convert.o hash.o auth.o MAN = omapi.3 DEBUG = -g @@ -33,8 +33,8 @@ CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) all: libomapi.a svtest $(CATMANPAGES) -svtest: test.o libomapi.a - $(CC) $(DEBUG) $(LFLAGS) -o svtest test.o libomapi.a $(LIBS) +svtest: test.o libomapi.a $(BINDLIB) + $(CC) $(DEBUG) $(LFLAGS) -o svtest test.o libomapi.a $(BINDLIB) $(LIBS) libomapi.a: $(OBJ) rm -f libomapi.a diff --git a/omapip/auth.c b/omapip/auth.c new file mode 100644 index 00000000..f5ce57bc --- /dev/null +++ b/omapip/auth.c @@ -0,0 +1,271 @@ +/* auth.c + + Subroutines having to do with authentication. */ + +/* + * Copyright (c) 1998-2000 Internet Software Consortium. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of The Internet Software Consortium nor the names + * of its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND + * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This software has been written for the Internet Software Consortium + * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc. + * To learn more about the Internet Software Consortium, see + * ``http://www.isc.org/''. To learn more about Vixie Enterprises, + * see ``http://www.vix.com''. To learn more about Nominum, Inc., see + * ``http://www.nominum.com''. + */ + +#ifndef lint +static char ocopyright[] = +"$Id: auth.c,v 1.1 2000/08/03 21:00:11 neild Exp $ Copyright 1998-2000 The Internet Software Consortium."; +#endif + +#include <omapip/omapip_p.h> + +OMAPI_OBJECT_ALLOC (omapi_auth_key, omapi_auth_key_t, omapi_type_auth_key); + +static struct hash_table *auth_key_hash = (struct hash_table *)0; +HASH_FUNCTIONS_DECL (omapi_auth_key, const char *, omapi_auth_key_t) + +isc_result_t omapi_auth_key_new (omapi_auth_key_t **o, const char *file, + int line) +{ + return omapi_auth_key_allocate (o, MDL); +} + +isc_result_t omapi_auth_key_destroy (omapi_object_t *h, + const char *file, int line) +{ + omapi_auth_key_t *a; + + if (h -> type != omapi_type_auth_key) + return ISC_R_INVALIDARG; + a = (omapi_auth_key_t *)h; + + if (auth_key_hash) + omapi_auth_key_hash_delete (auth_key_hash, a -> name, 0, MDL); + + if (a -> name) + dfree (a -> name, MDL); + if (a -> algorithm) + dfree (a -> algorithm, MDL); + if (a -> key) + omapi_data_string_dereference (&a -> key, MDL); + + return ISC_R_SUCCESS; +} + +isc_result_t omapi_auth_key_enter (omapi_auth_key_t *a) +{ + omapi_auth_key_t *tk; + + if (a -> type != omapi_type_auth_key) + return ISC_R_INVALIDARG; + + tk = (omapi_auth_key_t *)0; + if (auth_key_hash) { + omapi_auth_key_hash_lookup (&tk, auth_key_hash, + a -> name, 0, MDL); + if (tk == a) { + omapi_auth_key_dereference (&tk, MDL); + return ISC_R_SUCCESS; + } + if (tk) { + omapi_auth_key_hash_delete (auth_key_hash, + tk -> name, 0, MDL); + omapi_auth_key_dereference (&tk, MDL); + } + } else { + auth_key_hash = + new_hash ((hash_reference)omapi_auth_key_reference, + (hash_dereference)omapi_auth_key_dereference, + 1); + if (!auth_key_hash) + return ISC_R_NOMEMORY; + } + omapi_auth_key_hash_add (auth_key_hash, a -> name, 0, a, MDL); + return ISC_R_SUCCESS; + +} + +isc_result_t omapi_auth_key_lookup_name (omapi_auth_key_t **a, + const char *name) +{ + if (!auth_key_hash) + return ISC_R_NOTFOUND; + if (!omapi_auth_key_hash_lookup (a, auth_key_hash, name, 0, MDL)) + return ISC_R_NOTFOUND; + return ISC_R_SUCCESS; +} + +isc_result_t omapi_auth_key_lookup (omapi_object_t **h, + omapi_object_t *id, + omapi_object_t *ref) +{ + isc_result_t status; + omapi_value_t *name = (omapi_value_t *)0; + omapi_value_t *algorithm = (omapi_value_t *)0; + + if (!auth_key_hash) + return ISC_R_NOTFOUND; + + status = omapi_get_value_str (ref, id, "name", &name); + if (status != ISC_R_SUCCESS) + return status; + + if ((name -> value -> type != omapi_datatype_string) && + (name -> value -> type != omapi_datatype_data)) { + omapi_value_dereference (&name, MDL); + return ISC_R_NOTFOUND; + } + + status = omapi_get_value_str (ref, id, "algorithm", &algorithm); + if (status != ISC_R_SUCCESS) { + omapi_value_dereference (&name, MDL); + return status; + } + + if ((algorithm -> value -> type != omapi_datatype_string) && + (algorithm -> value -> type != omapi_datatype_data)) { + omapi_value_dereference (&name, MDL); + omapi_value_dereference (&algorithm, MDL); + return ISC_R_NOTFOUND; + } + + + if (!omapi_auth_key_hash_lookup ((omapi_auth_key_t **)h, auth_key_hash, + name -> value -> u.buffer.value, + name -> value -> u.buffer.len, MDL)) { + omapi_value_dereference (&name, MDL); + omapi_value_dereference (&algorithm, MDL); + return ISC_R_NOTFOUND; + } + + if (omapi_td_strcmp (algorithm -> value, + ((omapi_auth_key_t *)*h) -> algorithm) != 0) { + omapi_value_dereference (&name, MDL); + omapi_value_dereference (&algorithm, MDL); + omapi_object_dereference (h, MDL); + return ISC_R_NOTFOUND; + } + + omapi_value_dereference (&name, MDL); + omapi_value_dereference (&algorithm, MDL); + + return ISC_R_SUCCESS; +} + +isc_result_t omapi_auth_key_stuff_values (omapi_object_t *c, + omapi_object_t *id, + omapi_object_t *h) +{ + omapi_auth_key_t *a; + isc_result_t status; + + if (h -> type != omapi_type_auth_key) + return ISC_R_INVALIDARG; + a = (omapi_auth_key_t *)h; + + /* Write only the name and algorithm -- not the secret! */ + if (a -> name) { + status = omapi_connection_put_name (c, "name"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_string (c, a -> name); + if (status != ISC_R_SUCCESS) + return status; + } + if (a -> algorithm) { + status = omapi_connection_put_name (c, "algorithm"); + if (status != ISC_R_SUCCESS) + return status; + status = omapi_connection_put_string (c, a -> algorithm); + if (status != ISC_R_SUCCESS) + return status; + } + + return ISC_R_SUCCESS; +} + +isc_result_t omapi_auth_key_get_value (omapi_object_t *h, + omapi_object_t *id, + omapi_data_string_t *name, + omapi_value_t **value) +{ + omapi_auth_key_t *a; + isc_result_t status; + + if (h -> type != omapi_type_auth_key) + return ISC_R_UNEXPECTED; + a = (omapi_auth_key_t *)h; + + if (omapi_ds_strcmp (name, "name") == 0) { + if (a -> name) + return omapi_make_string_value + (value, name, a -> name, MDL); + else + return ISC_R_NOTFOUND; + } else if (omapi_ds_strcmp (name, "key") == 0) { + if (a -> key) { + status = omapi_value_new (value, MDL); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_data_string_reference + (&(*value) -> name, name, MDL); + if (status != ISC_R_SUCCESS) { + omapi_value_dereference (value, MDL); + return status; + } + + status = omapi_typed_data_new (MDL, &(*value) -> value, + omapi_datatype_data, + a -> key -> len); + if (status != ISC_R_SUCCESS) { + omapi_value_dereference (value, MDL); + return status; + } + + memcpy ((*value) -> value -> u.buffer.value, + a -> key -> value, a -> key -> len); + return ISC_R_SUCCESS; + } else + return ISC_R_NOTFOUND; + } else if (omapi_ds_strcmp (name, "algorithm") == 0) { + if (a -> algorithm) + return omapi_make_string_value + (value, name, a -> algorithm, MDL); + else + return ISC_R_NOTFOUND; + } + + return ISC_R_SUCCESS; +} + +HASH_FUNCTIONS (omapi_auth_key, const char *, omapi_auth_key_t) diff --git a/omapip/buffer.c b/omapip/buffer.c index 81fa07ce..e4bdc19a 100644 --- a/omapip/buffer.c +++ b/omapip/buffer.c @@ -139,6 +139,7 @@ isc_result_t omapi_connection_copyin (omapi_object_t *h, isc_result_t status; int bytes_copied = 0; unsigned copy_len; + int sig_flags = SIG_MODE_UPDATE; omapi_connection_object_t *c; /* Make sure len is valid. */ @@ -177,6 +178,17 @@ isc_result_t omapi_connection_copyin (omapi_object_t *h, if (copy_len > (len - bytes_copied)) copy_len = len - bytes_copied; + if (c -> out_key) { + if (!c -> out_context) + sig_flags |= SIG_MODE_INIT; + status = omapi_connection_sign_data + (sig_flags, c -> out_key, &c -> out_context, + &bufp [bytes_copied], copy_len, + (omapi_typed_data_t **)0); + if (status != ISC_R_SUCCESS) + return status; + } + memcpy (&buffer -> buf [buffer -> tail], &bufp [bytes_copied], copy_len); buffer -> tail += copy_len; @@ -200,7 +212,9 @@ isc_result_t omapi_connection_copyout (unsigned char *buf, unsigned first_byte; omapi_buffer_t *buffer; unsigned char *bufp; + int sig_flags = SIG_MODE_UPDATE; omapi_connection_object_t *c; + isc_result_t status; if (!h || h -> type != omapi_type_connection) return ISC_R_INVALIDARG; @@ -231,6 +245,20 @@ isc_result_t omapi_connection_copyout (unsigned char *buf, if (bytes_this_copy > bytes_remaining) bytes_this_copy = bytes_remaining; if (bufp) { + if (c -> in_key) { + if (!c -> in_context) + sig_flags |= SIG_MODE_INIT; + status = omapi_connection_sign_data + (sig_flags, + c -> in_key, + &c -> in_context, + &buffer -> buf [first_byte], + bytes_this_copy, + (omapi_typed_data_t **)0); + if (status != ISC_R_SUCCESS) + return status; + } + memcpy (bufp, &buffer -> buf [first_byte], bytes_this_copy); bufp += bytes_this_copy; diff --git a/omapip/connection.c b/omapip/connection.c index 2d85c39b..a02fe29f 100644 --- a/omapip/connection.c +++ b/omapip/connection.c @@ -406,13 +406,188 @@ isc_result_t omapi_connection_reaper (omapi_object_t *h) return ISC_R_SUCCESS; } +static isc_result_t make_dst_key (DST_KEY **dst_key, omapi_object_t *a) { + omapi_value_t *name = (omapi_value_t *)0; + omapi_value_t *algorithm = (omapi_value_t *)0; + omapi_value_t *key = (omapi_value_t *)0; + int algorithm_id; + char *name_str; + isc_result_t status = ISC_R_SUCCESS; + + if (status == ISC_R_SUCCESS) + status = omapi_get_value_str + (a, (omapi_object_t *)0, "name", &name); + + if (status == ISC_R_SUCCESS) + status = omapi_get_value_str + (a, (omapi_object_t *)0, "algorithm", &algorithm); + + if (status == ISC_R_SUCCESS) + status = omapi_get_value_str + (a, (omapi_object_t *)0, "key", &key); + + if (status == ISC_R_SUCCESS) { + if (omapi_td_strcmp (algorithm -> value, "hmac-md5") == 0) { + algorithm_id = KEY_HMAC_MD5; + } else { + status = ISC_R_INVALIDARG; + } + } + + if (status == ISC_R_SUCCESS) { + name_str = dmalloc (name -> value -> u.buffer.len + 1, MDL); + if (!name_str) + status = ISC_R_NOMEMORY; + } + + if (status == ISC_R_SUCCESS) { + memcpy (name_str, + name -> value -> u.buffer.value, + name -> value -> u.buffer.len); + name_str [name -> value -> u.buffer.len] = 0; + + *dst_key = dst_buffer_to_key (name_str, algorithm_id, 0, 0, + key -> value -> u.buffer.value, + key -> value -> u.buffer.len); + if (!*dst_key) + status = ISC_R_NOMEMORY; + } + + if (name_str) + dfree (name_str, MDL); + if (key) + omapi_value_dereference (&key, MDL); + if (algorithm) + omapi_value_dereference (&algorithm, MDL); + if (name) + omapi_value_dereference (&name, MDL); + + return status; +} + +isc_result_t omapi_connection_sign_data (int mode, + DST_KEY *key, + void **context, + const u_char *data, + const unsigned len, + omapi_typed_data_t **result) +{ + omapi_typed_data_t *td = (omapi_typed_data_t *)0; + isc_result_t status; + int r; + + if (mode & SIG_MODE_FINAL) { + status = omapi_typed_data_new (MDL, &td, + omapi_datatype_data, + dst_sig_size (key)); + if (status != ISC_R_SUCCESS) + return status; + } + + r = dst_sign_data (mode, key, context, data, len, + td ? td -> u.buffer.value : (u_char *)0, + td ? td -> u.buffer.len : 0); + + /* dst_sign_data() really should do this for us, shouldn't it? */ + if (mode & SIG_MODE_FINAL) + *context = (void *)0; + + if (r < 0) { + if (td) + omapi_typed_data_dereference (&td, MDL); + return ISC_R_INVALIDKEY; + } + + if (result && td) { + omapi_typed_data_reference (result, td, MDL); + } + + if (td) + omapi_typed_data_dereference (&td, MDL); + + return ISC_R_SUCCESS; +} + +isc_result_t omapi_connection_output_auth_length (omapi_object_t *h, + unsigned *l) +{ + omapi_connection_object_t *c; + + if (h -> type != omapi_type_connection) + return ISC_R_INVALIDARG; + c = (omapi_connection_object_t *)h; + + if (!c -> out_key) + return ISC_R_NOTFOUND; + + *l = dst_sig_size (c -> out_key); + return ISC_R_SUCCESS; +} + isc_result_t omapi_connection_set_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value) { + omapi_connection_object_t *c; + isc_result_t status; + if (h -> type != omapi_type_connection) return ISC_R_INVALIDARG; + c = (omapi_connection_object_t *)h; + + if (omapi_ds_strcmp (name, "input-authenticator") == 0) { + if (value && value -> type != omapi_datatype_object) + return ISC_R_INVALIDARG; + + if (c -> in_context) { + omapi_connection_sign_data (SIG_MODE_FINAL, + c -> in_key, + &c -> in_context, + 0, 0, + (omapi_typed_data_t **) 0); + } + + if (c -> in_key) { + dst_free_key (c -> in_key); + c -> in_key = (DST_KEY *)0; + } + + if (value) { + status = make_dst_key (&c -> in_key, + value -> u.object); + if (status != ISC_R_SUCCESS) + return status; + } + + return ISC_R_SUCCESS; + } + else if (omapi_ds_strcmp (name, "output-authenticator") == 0) { + if (value && value -> type != omapi_datatype_object) + return ISC_R_INVALIDARG; + + if (c -> out_context) { + omapi_connection_sign_data (SIG_MODE_FINAL, + c -> out_key, + &c -> out_context, + 0, 0, + (omapi_typed_data_t **) 0); + } + + if (c -> out_key) { + dst_free_key (c -> out_key); + c -> out_key = (DST_KEY *)0; + } + + if (value) { + status = make_dst_key (&c -> out_key, + value -> u.object); + if (status != ISC_R_SUCCESS) + return status; + } + + return ISC_R_SUCCESS; + } if (h -> inner && h -> inner -> type -> set_value) return (*(h -> inner -> type -> set_value)) @@ -425,8 +600,58 @@ isc_result_t omapi_connection_get_value (omapi_object_t *h, omapi_data_string_t *name, omapi_value_t **value) { + omapi_connection_object_t *c; + omapi_typed_data_t *td = (omapi_typed_data_t *)0; + isc_result_t status; + if (h -> type != omapi_type_connection) return ISC_R_INVALIDARG; + c = (omapi_connection_object_t *)h; + + if (omapi_ds_strcmp (name, "input-signature") == 0) { + if (!c -> in_key || !c -> in_context) + return ISC_R_NOTFOUND; + + status = omapi_connection_sign_data (SIG_MODE_FINAL, + c -> in_key, + &c -> in_context, + 0, 0, &td); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_make_value (value, name, td, MDL); + omapi_typed_data_dereference (&td, MDL); + return status; + + } else if (omapi_ds_strcmp (name, "input-signature-size") == 0) { + if (!c -> in_key) + return ISC_R_NOTFOUND; + + return omapi_make_int_value (value, name, + dst_sig_size (c -> in_key), MDL); + + } else if (omapi_ds_strcmp (name, "output-signature") == 0) { + if (!c -> out_key || !c -> out_context) + return ISC_R_NOTFOUND; + + status = omapi_connection_sign_data (SIG_MODE_FINAL, + c -> out_key, + &c -> out_context, + 0, 0, &td); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_make_value (value, name, td, MDL); + omapi_typed_data_dereference (&td, MDL); + return status; + + } else if (omapi_ds_strcmp (name, "output-signature-size") == 0) { + if (!c -> out_key) + return ISC_R_NOTFOUND; + + return omapi_make_int_value (value, name, + dst_sig_size (c -> out_key), MDL); + } if (h -> inner && h -> inner -> type -> get_value) return (*(h -> inner -> type -> get_value)) diff --git a/omapip/dispatch.c b/omapip/dispatch.c index ee402aed..2701d7b9 100644 --- a/omapip/dispatch.c +++ b/omapip/dispatch.c @@ -206,8 +206,9 @@ isc_result_t omapi_wait_for_completion (omapi_object_t *object, if (waiter -> inner) omapi_object_dereference (&waiter -> inner, MDL); + status = waiter -> waitstatus; omapi_waiter_dereference (&waiter, MDL); - return ISC_R_SUCCESS; + return status;; } isc_result_t omapi_one_dispatch (omapi_object_t *wo, @@ -510,6 +511,14 @@ isc_result_t omapi_waiter_signal_handler (omapi_object_t *h, if (!strcmp (name, "ready")) { waiter = (omapi_waiter_object_t *)h; waiter -> ready = 1; + waiter -> waitstatus = ISC_R_SUCCESS; + return ISC_R_SUCCESS; + } + + if (!strcmp (name, "status")) { + waiter = (omapi_waiter_object_t *)h; + waiter -> ready = 1; + waiter -> waitstatus = va_arg (ap, isc_result_t); return ISC_R_SUCCESS; } diff --git a/omapip/listener.c b/omapip/listener.c index 23c6250f..03ee6e5d 100644 --- a/omapip/listener.c +++ b/omapip/listener.c @@ -122,6 +122,17 @@ isc_result_t omapi_listen_addr (omapi_object_t *h, } #endif + /* Set the REUSEADDR option so that we don't fail to start if + we're being restarted. */ + i = 1; + if (setsockopt (obj -> socket, SOL_SOCKET, SO_REUSEADDR, + (char *)&i, sizeof i) < 0) { + close (obj -> socket); + omapi_listener_dereference (&obj, MDL); + return ISC_R_UNEXPECTED; + } + + /* Try to bind to the wildcard address using the port number we were given. */ i = bind (obj -> socket, @@ -173,6 +184,7 @@ isc_result_t omapi_accept (omapi_object_t *h) SOCKLEN_T len; omapi_connection_object_t *obj; omapi_listener_object_t *listener; + omapi_addr_t addr; int i; if (h -> type != omapi_type_listener) @@ -200,6 +212,21 @@ isc_result_t omapi_accept (omapi_object_t *h) obj -> state = omapi_connection_connected; + /* Verify that this host is allowed to connect. */ + if (listener -> verify_addr) { + addr.addrtype = AF_INET; + addr.addrlen = sizeof (obj -> remote_addr.sin_addr); + memcpy (addr.address, &obj -> remote_addr.sin_addr, + sizeof (obj -> remote_addr.sin_addr)); + addr.port = ntohs(obj -> remote_addr.sin_port); + + status = (listener -> verify_addr) (h, &addr); + if (status != ISC_R_SUCCESS) { + omapi_disconnect ((omapi_object_t *)obj, 1); + return status; + } + } + status = omapi_register_io_object ((omapi_object_t *)obj, omapi_connection_readfd, omapi_connection_writefd, @@ -221,6 +248,22 @@ isc_result_t omapi_accept (omapi_object_t *h) return status; } +isc_result_t omapi_listener_configure_security (omapi_object_t *h, + isc_result_t (*verify_addr) + (omapi_object_t *, + omapi_addr_t *)) +{ + omapi_listener_object_t *l; + + if (h -> type != omapi_type_listener) + return ISC_R_INVALIDARG; + l = (omapi_listener_object_t *)h; + + l -> verify_addr = verify_addr; + + return ISC_R_SUCCESS; +} + isc_result_t omapi_listener_set_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, diff --git a/omapip/message.c b/omapip/message.c index 60cd6857..7837f487 100644 --- a/omapip/message.c +++ b/omapip/message.c @@ -249,14 +249,14 @@ isc_result_t omapi_message_signal_handler (omapi_object_t *h, return ISC_R_INVALIDARG; m = (omapi_message_object_t *)h; - if (!strcmp (name, "status") && - (m -> object || m -> notify_object)) { - if (m -> object) - return ((m -> object -> type -> signal_handler)) - (m -> object, name, ap); - else + if (!strcmp (name, "status")) { + if (m -> notify_object && + m -> notify_object -> type -> signal_handler) return ((m -> notify_object -> type -> signal_handler)) (m -> notify_object, name, ap); + else if (m -> object && m -> object -> type -> signal_handler) + return ((m -> object -> type -> signal_handler)) + (m -> object, name, ap); } if (h -> inner && h -> inner -> type -> signal_handler) return (*(h -> inner -> type -> signal_handler)) (h -> inner, @@ -378,20 +378,35 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) response, something's fishy. */ if (!m) return ISC_R_NOTFOUND; - } else + /* The authenticator on responses must match the initial + message. */ + if (message -> authid != m -> authid) + return ISC_R_NOTFOUND; + } else { m = (omapi_message_object_t *)0; + /* All messages must have an authenticator, with the exception + of messages that are opening a new authenticator. */ + if (omapi_protocol_authenticated (po) && + !message -> id_object && + message -> op != OMAPI_OP_OPEN) { + return omapi_protocol_send_status + (po, message -> id_object, ISC_R_NOKEYS, + message -> id, "No authenticator on message"); + } + } + switch (message -> op) { case OMAPI_OP_OPEN: if (m) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, ISC_R_INVALIDARG, + (po, message -> id_object, ISC_R_INVALIDARG, message -> id, "OPEN can't be a response"); } /* Get the type of the requested object, if one was specified. */ - status = omapi_get_value_str (mo, (omapi_object_t *)0, + status = omapi_get_value_str (mo, message -> id_object, "type", &tv); if (status == ISC_R_SUCCESS && (tv -> value -> type == omapi_datatype_data || @@ -406,16 +421,25 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) if (tv) omapi_value_dereference (&tv, MDL); + /* If this object had no authenticator, the requested object + must be an authenticator object. */ + if (omapi_protocol_authenticated (po) && + !message -> id_object && + type != omapi_type_auth_key) { + return omapi_protocol_send_status + (po, message -> id_object, ISC_R_NOKEYS, + message -> id, "No authenticator on message"); + } + /* Get the create flag. */ - status = omapi_get_value_str (mo, - (omapi_object_t *)0, + status = omapi_get_value_str (mo, message -> id_object, "create", &tv); if (status == ISC_R_SUCCESS) { status = omapi_get_int_value (&create, tv -> value); omapi_value_dereference (&tv, MDL); if (status != ISC_R_SUCCESS) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, status, message -> id, "invalid create flag value"); } @@ -423,15 +447,14 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) create = 0; /* Get the update flag. */ - status = omapi_get_value_str (mo, - (omapi_object_t *)0, + status = omapi_get_value_str (mo, message -> id_object, "update", &tv); if (status == ISC_R_SUCCESS) { status = omapi_get_int_value (&update, tv -> value); omapi_value_dereference (&tv, MDL); if (status != ISC_R_SUCCESS) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, status, message -> id, "invalid update flag value"); } @@ -439,15 +462,14 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) update = 0; /* Get the exclusive flag. */ - status = omapi_get_value_str (mo, - (omapi_object_t *)0, + status = omapi_get_value_str (mo, message -> id_object, "exclusive", &tv); if (status == ISC_R_SUCCESS) { status = omapi_get_int_value (&exclusive, tv -> value); omapi_value_dereference (&tv, MDL); if (status != ISC_R_SUCCESS) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, status, message -> id, "invalid exclusive flag value"); } @@ -459,8 +481,9 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) if (!type) { if (create) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, - ISC_R_INVALIDARG, message -> id, + (po, message -> id_object, + ISC_R_INVALIDARG, + message -> id, "type required on create"); } goto refresh; @@ -470,25 +493,25 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) look up the object. */ if (!type -> lookup) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, ISC_R_NOTIMPLEMENTED, message -> id, "unsearchable object type"); } if (!message -> object) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, ISC_R_NOTFOUND, message -> id, "no lookup key specified"); } - status = (*(type -> lookup)) (&object, (omapi_object_t *)0, + status = (*(type -> lookup)) (&object, message -> id_object, message -> object); if (status != ISC_R_SUCCESS && status != ISC_R_NOTFOUND && status != ISC_R_NOKEYS) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, status, message -> id, "object lookup failed"); } @@ -497,7 +520,7 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) create it, return an error. */ if (status == ISC_R_NOTFOUND && !create) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, ISC_R_NOTFOUND, message -> id, "no object matches specification"); } @@ -508,7 +531,7 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) if (status == ISC_R_SUCCESS && create && exclusive) { omapi_object_dereference (&object, MDL); return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, ISC_R_EXISTS, message -> id, "specified object already exists"); } @@ -516,11 +539,11 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) /* If we're creating the object, do it now. */ if (!object) { status = omapi_object_create (&object, - (omapi_object_t *)0, + message -> id_object, type); if (status != ISC_R_SUCCESS) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, status, message -> id, "can't create new object"); } @@ -528,18 +551,50 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) /* If we're updating it, do so now. */ if (create || update) { + /* This check does not belong here. */ + if (object -> type == omapi_type_auth_key) { + omapi_object_dereference (&object, MDL); + return omapi_protocol_send_status + (po, message -> id_object, + status, message -> id, + "can't update object"); + } + status = omapi_object_update (object, - (omapi_object_t *)0, + message -> id_object, message -> object, message -> h); if (status != ISC_R_SUCCESS) { omapi_object_dereference (&object, MDL); return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, status, message -> id, "can't update object"); } } + + /* If this is an authenticator object, add it to the active + set for the connection. */ + if (object -> type == omapi_type_auth_key) { + omapi_handle_t handle; + status = omapi_object_handle (&handle, object); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&object, MDL); + return omapi_protocol_send_status + (po, message -> id_object, + status, message -> id, + "can't select authenticator"); + } + + status = omapi_protocol_add_auth (po, object, handle); + if (status != ISC_R_SUCCESS) { + omapi_object_dereference (&object, MDL); + return omapi_protocol_send_status + (po, message -> id_object, + status, message -> id, + "can't select authenticator"); + } + } /* Now send the new contents of the object back in response. */ @@ -550,37 +605,53 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) status = omapi_handle_lookup (&object, message -> h); if (status != ISC_R_SUCCESS) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, status, message -> id, "no matching handle"); } send: - status = omapi_protocol_send_update (po, (omapi_object_t *)0, + status = omapi_protocol_send_update (po, message -> id_object, message -> id, object); omapi_object_dereference (&object, MDL); return status; case OMAPI_OP_UPDATE: - if (m -> object) { + if (m && m -> object) { omapi_object_reference (&object, m -> object, MDL); } else { status = omapi_handle_lookup (&object, message -> h); if (status != ISC_R_SUCCESS) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, status, message -> id, "no matching handle"); } } - status = omapi_object_update (object, (omapi_object_t *)0, - message -> object, - message -> h); + if (object -> type == omapi_type_auth_key || + (object -> inner && + object -> inner -> type == omapi_type_auth_key)) { + if (!m) { + omapi_object_dereference (&object, MDL); + return omapi_protocol_send_status + (po, message -> id_object, + status, message -> id, + "cannot update authenticator"); + } + + status = omapi_protocol_add_auth (po, object, + message -> h); + } else { + status = omapi_object_update (object, + message -> id_object, + message -> object, + message -> h); + } if (status != ISC_R_SUCCESS) { omapi_object_dereference (&object, MDL); if (!message -> rid) return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, status, message -> id, "can't update object"); if (m) @@ -591,7 +662,7 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) } if (!message -> rid) status = omapi_protocol_send_status - (po, (omapi_object_t *)0, ISC_R_SUCCESS, + (po, message -> id_object, ISC_R_SUCCESS, message -> id, (char *)0); if (m) omapi_signal ((omapi_object_t *)m, @@ -601,7 +672,7 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) case OMAPI_OP_NOTIFY: return omapi_protocol_send_status - (po, (omapi_object_t *)0, ISC_R_NOTIMPLEMENTED, + (po, message -> id_object, ISC_R_NOTIMPLEMENTED, message -> id, "notify not implemented yet"); case OMAPI_OP_STATUS: @@ -610,8 +681,7 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) return ISC_R_UNEXPECTED; /* Get the wait status. */ - status = omapi_get_value_str (mo, - (omapi_object_t *)0, + status = omapi_get_value_str (mo, message -> id_object, "result", &tv); if (status == ISC_R_SUCCESS) { status = omapi_get_int_value (&wsi, tv -> value); @@ -622,8 +692,7 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) } else waitstatus = ISC_R_UNEXPECTED; - status = omapi_get_value_str (mo, - (omapi_object_t *)0, + status = omapi_get_value_str (mo, message -> id_object, "message", &tv); omapi_signal ((omapi_object_t *)m, "status", waitstatus, tv); if (status == ISC_R_SUCCESS) @@ -634,22 +703,22 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po) status = omapi_handle_lookup (&object, message -> h); if (status != ISC_R_SUCCESS) { return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, status, message -> id, "no matching handle"); } if (!object -> type -> remove) return omapi_protocol_send_status - (po, (omapi_object_t *)0, + (po, message -> id_object, ISC_R_NOTIMPLEMENTED, message -> id, "no remove method for object"); status = (*(object -> type -> remove)) (object, - (omapi_object_t *)0); + message -> id_object); omapi_object_dereference (&object, MDL); - return omapi_protocol_send_status (po, (omapi_object_t *)0, + return omapi_protocol_send_status (po, message -> id_object, status, message -> id, (char *)0); } diff --git a/omapip/protocol.c b/omapip/protocol.c index b254e2a0..7eaeab89 100644 --- a/omapip/protocol.c +++ b/omapip/protocol.c @@ -51,7 +51,7 @@ OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t, isc_result_t omapi_protocol_connect (omapi_object_t *h, const char *server_name, unsigned port, - omapi_object_t *authinfo) + omapi_object_t *a) { isc_result_t status; omapi_protocol_object_t *obj; @@ -78,8 +78,30 @@ isc_result_t omapi_protocol_connect (omapi_object_t *h, return status; } - if (authinfo) - omapi_object_reference (&obj -> authinfo, authinfo, MDL); + /* If we were passed a default authenticator, store it now. We'll + open it once we're connected. */ + if (a) { + obj -> default_auth = + dmalloc (sizeof(omapi_remote_auth_t), MDL); + if (!obj -> default_auth) { + omapi_protocol_dereference (&obj, MDL); + return ISC_R_NOMEMORY; + } + + obj -> default_auth -> next = (omapi_remote_auth_t *)0; + status = omapi_object_reference (&obj -> default_auth -> a, + a, MDL); + if (status != ISC_R_SUCCESS) { + dfree (obj -> default_auth, MDL); + omapi_protocol_dereference (&obj, MDL); + return status; + } + + obj -> insecure = 0; + } else { + obj -> insecure = 1; + } + omapi_protocol_dereference (&obj, MDL); return ISC_R_SUCCESS; } @@ -128,8 +150,11 @@ isc_result_t omapi_protocol_send_message (omapi_object_t *po, omapi_protocol_object_t *p; omapi_object_t *c; omapi_message_object_t *m, *om; + omapi_remote_auth_t *ra; + omapi_value_t *signature; isc_result_t status; u_int32_t foo; + unsigned auth_len; if (po -> type != omapi_type_protocol || !po -> outer || po -> outer -> type != omapi_type_connection || @@ -142,12 +167,57 @@ isc_result_t omapi_protocol_send_message (omapi_object_t *po, m = (omapi_message_object_t *)mo; om = (omapi_message_object_t *)omo; - /* XXX Write the authenticator length */ - status = omapi_connection_put_uint32 (c, 0); - if (status != ISC_R_SUCCESS) + /* Find the authid to use for this message. */ + if (id) { + for (ra = p -> remote_auth_list; ra; ra = ra -> next) { + if (ra -> a == id) { + break; + } + } + + if (!ra) + return ISC_R_KEY_UNKNOWN; + } else if (p -> remote_auth_list) { + ra = p -> default_auth; + } else { + ra = (omapi_remote_auth_t *)0; + } + + if (ra) { + m -> authid = ra -> remote_handle; + status = omapi_object_reference (&m -> id_object, + ra -> a, MDL); + if (status != ISC_R_SUCCESS) + return status; + } + + /* Write the ID of the authentication key we're using. */ + status = omapi_connection_put_uint32 (c, ra ? ra -> remote_handle : 0); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); return status; - /* XXX Write the ID of the authentication key we're using. */ - status = omapi_connection_put_uint32 (c, 0); + } + + /* Activate the authentication key on the connection. */ + auth_len = 0; + if (ra) { + status = omapi_set_object_value (c, (omapi_object_t *)0, + "output-authenticator", + ra -> a); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + + status = omapi_connection_output_auth_length (c, &auth_len); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + } + + /* Write the authenticator length */ + status = omapi_connection_put_uint32 (c, auth_len); if (status != ISC_R_SUCCESS) { omapi_disconnect (c, 1); return status; @@ -223,7 +293,35 @@ isc_result_t omapi_protocol_send_message (omapi_object_t *po, return status; } - /* XXX Write the authenticator... */ + if (ra) { + /* Calculate the message signature. */ + signature = (omapi_value_t *)0; + status = omapi_get_value_str (c, (omapi_object_t *)0, + "output-signature", &signature); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + + /* Write the authenticator... */ + status = (omapi_connection_copyin + (c, signature -> value -> u.buffer.value, + signature -> value -> u.buffer.len)); + omapi_value_dereference (&signature, MDL); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + + /* Dectivate the authentication key on the connection. */ + status = omapi_set_value_str (c, (omapi_object_t *)0, + "output-authenticator", + (omapi_typed_data_t *)0); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + } return ISC_R_SUCCESS; } @@ -235,6 +333,7 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, isc_result_t status; omapi_protocol_object_t *p; omapi_object_t *c; + omapi_value_t *signature; u_int16_t nlen; u_int32_t vlen; u_int32_t th; @@ -257,6 +356,19 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, return ISC_R_SUCCESS; } + /* Should only receive these when opening the initial authenticator. */ + if (!strcmp (name, "status")) { + status = va_arg (ap, isc_result_t); + if (status != ISC_R_SUCCESS) { + omapi_signal_in (h -> inner, "status", status, + (omapi_object_t *)0); + omapi_disconnect (p -> outer, 1); + return status; + } else { + return omapi_signal_in (h -> inner, "ready"); + } + } + /* Not a signal we recognize? */ if (strcmp (name, "ready")) { if (p -> inner && p -> inner -> type -> signal_handler) @@ -291,7 +403,18 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, return ISC_R_PROTOCOLERROR; } - status = omapi_signal_in (h -> inner, "ready"); + if (p -> default_auth) { + status = omapi_protocol_send_open + (h, (omapi_object_t *)0, "authenticator", + p -> default_auth -> a, + OMAPI_NOTIFY_PROTOCOL); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + } else { + status = omapi_signal_in (h -> inner, "ready"); + } to_header_wait: /* The next thing we're expecting is a message header. */ @@ -313,10 +436,29 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, return status; } + p -> verify_result = ISC_R_SUCCESS; + /* Swap in the header... */ omapi_connection_get_uint32 (c, &p -> message -> authid); - /* XXX bind the authenticator here! */ + /* Bind the authenticator to the message object. */ + if (p -> message -> authid) { + status = (omapi_protocol_lookup_auth + (&p -> message -> id_object, h, + p -> message -> authid)); + if (status != ISC_R_SUCCESS) + p -> verify_result = status; + + /* Activate the authentication key. */ + status = omapi_set_object_value + (c, (omapi_object_t *)0, "input-authenticator", + p -> message -> id_object); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + } + omapi_connection_get_uint32 (c, &p -> message -> authlen); omapi_connection_get_uint32 (c, &p -> message -> op); omapi_connection_get_uint32 (c, &th); @@ -462,31 +604,71 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, signature_wait: case omapi_protocol_signature_wait: + if (p -> message -> id_object) { + /* Compute the signature of the message. */ + signature = (omapi_value_t *)0; + status = omapi_get_value_str (c, (omapi_object_t *)0, + "input-signature", + &signature); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + + /* Disable the authentication key on the connection. */ + status = omapi_set_value_str (c, (omapi_object_t *)0, + "input-authenticator", + (omapi_typed_data_t *)0); + if (status != ISC_R_SUCCESS) { + omapi_value_dereference (&signature, MDL); + omapi_disconnect (c, 1); + return status; + } + } + + /* Read the authenticator. */ status = omapi_typed_data_new (MDL, &p -> message -> authenticator, omapi_datatype_data, p -> message -> authlen); if (status != ISC_R_SUCCESS) { + omapi_value_dereference (&signature, MDL); omapi_disconnect (c, 1); return ISC_R_NOMEMORY; } omapi_connection_copyout (p -> message -> authenticator -> u.buffer.value, c, p -> message -> authlen); - /* XXX now do something to verify the signature. */ + + /* Verify the signature. */ + if (p -> message -> id_object && + ((signature -> value -> u.buffer.len != + p -> message -> authlen) || + (memcmp (signature -> value -> u.buffer.value, + p -> message -> authenticator -> u.buffer.value, + p -> message -> authlen) != 0))) { + /* Invalid signature. */ + p -> verify_result = ISC_R_INVALIDKEY; + } + + omapi_value_dereference (&signature, MDL); /* Process the message. */ message_done: - status = omapi_message_process ((omapi_object_t *)p -> message, - h); + if (p -> verify_result != ISC_R_SUCCESS) { + status = omapi_protocol_send_status + (h, (omapi_object_t *)0, p -> verify_result, + p -> message -> id, (char *)0); + } else { + status = omapi_message_process + ((omapi_object_t *)p -> message, h); + } if (status != ISC_R_SUCCESS) { omapi_disconnect (c, 1); return ISC_R_NOMEMORY; } - /* XXX unbind the authenticator. */ - auth_unbind: omapi_message_dereference (&p -> message, MDL); /* Now wait for the next message. */ @@ -499,13 +681,110 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, return ISC_R_SUCCESS; } +isc_result_t omapi_protocol_add_auth (omapi_object_t *po, + omapi_object_t *ao, + omapi_handle_t handle) +{ + omapi_protocol_object_t *p; + omapi_remote_auth_t *r; + isc_result_t status; + + if (ao -> type != omapi_type_auth_key && + (!ao -> inner || ao -> inner -> type != omapi_type_auth_key)) + return ISC_R_INVALIDARG; + + if (po -> type != omapi_type_protocol) + return ISC_R_INVALIDARG; + p = (omapi_protocol_object_t *)po; + + if (p -> verify_auth) { + status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao); + if (status != ISC_R_SUCCESS) + return status; + } + + /* If omapi_protocol_connect() was called with a default + authenticator, p -> default_auth will already be set, + but p -> remote_auth_list will not yet be initialized. */ + if (p -> default_auth && !p -> remote_auth_list) { + if (p -> default_auth -> a != ao) { + /* Something just went horribly wrong. */ + omapi_disconnect (p -> outer, 1); + return ISC_R_UNEXPECTED; + } + + p -> remote_auth_list = p -> default_auth; + p -> default_auth -> remote_handle = handle; + + return omapi_signal_in (p -> inner, "ready"); + } + + r = dmalloc (sizeof(*r), MDL); + if (!r) + return ISC_R_NOMEMORY; + + status = omapi_object_reference (&r -> a, ao, MDL); + if (status != ISC_R_SUCCESS) { + dfree (r, MDL); + return status; + } + + r -> remote_handle = handle; + r -> next = p -> remote_auth_list; + p -> remote_auth_list = r; + + return ISC_R_SUCCESS; +} + +isc_result_t omapi_protocol_lookup_auth (omapi_object_t **a, + omapi_object_t *po, + omapi_handle_t handle) +{ + omapi_protocol_object_t *p; + omapi_remote_auth_t *r; + + if (po -> type != omapi_type_protocol) + return ISC_R_INVALIDARG; + p = (omapi_protocol_object_t *)po; + + for (r = p -> remote_auth_list; r; r = r -> next) + if (r -> remote_handle == handle) + return omapi_object_reference (a, r -> a, MDL); + + return ISC_R_NOTFOUND; +} + isc_result_t omapi_protocol_set_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value) { + omapi_protocol_object_t *p; + omapi_remote_auth_t *r; + if (h -> type != omapi_type_protocol) return ISC_R_INVALIDARG; + p = (omapi_protocol_object_t *)h; + + if (omapi_ds_strcmp (name, "default-authenticator") == 0) { + if (value -> type != omapi_datatype_object) + return ISC_R_INVALIDARG; + + if (!value || !value -> u.object) { + p -> default_auth = (omapi_remote_auth_t *)0; + } else { + for (r = p -> remote_auth_list; r; r = r -> next) + if (r -> a == value -> u.object) + break; + + if (!r) + return ISC_R_KEY_UNKNOWN; + + p -> default_auth = r; + } + + return ISC_R_SUCCESS; + } if (h -> inner && h -> inner -> type -> set_value) return (*(h -> inner -> type -> set_value)) @@ -518,8 +797,19 @@ isc_result_t omapi_protocol_get_value (omapi_object_t *h, omapi_data_string_t *name, omapi_value_t **value) { + omapi_protocol_object_t *p; + if (h -> type != omapi_type_protocol) return ISC_R_INVALIDARG; + p = (omapi_protocol_object_t *)h; + + if (omapi_ds_strcmp (name, "default-authenticator") == 0) { + if (!p -> default_auth) + return ISC_R_NOTFOUND; + + return omapi_make_object_value (value, name, + p -> default_auth -> a, MDL); + } if (h -> inner && h -> inner -> type -> get_value) return (*(h -> inner -> type -> get_value)) @@ -536,8 +826,19 @@ isc_result_t omapi_protocol_destroy (omapi_object_t *h, p = (omapi_protocol_object_t *)h; if (p -> message) omapi_message_dereference (&p -> message, file, line); - if (p -> authinfo) - return omapi_object_dereference (&p -> authinfo, file, line); + + /* This will happen if: 1) A default authenticator is supplied to + omapi_protocol_connect(), and 2) something goes wrong before + the authenticator can be opened. */ + if (p -> default_auth && !p -> remote_auth_list) + dfree (p -> default_auth, file, line); + + while (p -> remote_auth_list) { + omapi_remote_auth_t *r = p -> remote_auth_list -> next; + omapi_object_dereference (&r -> a, file, line); + dfree (r, file, line); + p -> remote_auth_list = r; + } return ISC_R_SUCCESS; } @@ -559,6 +860,46 @@ isc_result_t omapi_protocol_stuff_values (omapi_object_t *c, return ISC_R_SUCCESS; } +/* Returns a boolean indicating whether this protocol requires that + messages be authenticated or not. */ + +isc_boolean_t omapi_protocol_authenticated (omapi_object_t *h) +{ + if (h -> type != omapi_type_protocol) + return isc_boolean_false; + if (((omapi_protocol_object_t *)h) -> insecure) + return isc_boolean_false; + else + return isc_boolean_true; +} + +/* Sets the address and authenticator verification callbacks. The handle + is to a listener object, not a protocol object. */ + +isc_result_t omapi_protocol_configure_security (omapi_object_t *h, + isc_result_t (*verify_addr) + (omapi_object_t *, + omapi_addr_t *), + isc_result_t (*verify_auth) + (omapi_object_t *, + omapi_auth_key_t *)) +{ + omapi_protocol_listener_object_t *l; + + if (h -> outer && h -> outer -> type == omapi_type_protocol_listener) + h = h -> outer; + + if (h -> type != omapi_type_protocol_listener) + return ISC_R_INVALIDARG; + l = (omapi_protocol_listener_object_t *)h; + + l -> verify_auth = verify_auth; + l -> insecure = 0; + + return omapi_listener_configure_security (h -> outer, verify_addr); +} + + /* Set up a listener for the omapi protocol. The handle stored points to a listener object, not a protocol object. */ @@ -586,6 +927,9 @@ isc_result_t omapi_protocol_listen (omapi_object_t *h, return status; } + /* What a terrible default. */ + obj -> insecure = 1; + status = omapi_listen ((omapi_object_t *)obj, port, max); omapi_protocol_listener_dereference (&obj, MDL); return status; @@ -623,6 +967,9 @@ isc_result_t omapi_protocol_listener_signal (omapi_object_t *o, if (status != ISC_R_SUCCESS) return status; + obj -> verify_auth = p -> verify_auth; + obj -> insecure = p -> insecure; + status = omapi_object_reference (&obj -> outer, c, MDL); if (status != ISC_R_SUCCESS) { lose: @@ -754,6 +1101,70 @@ isc_result_t omapi_protocol_send_status (omapi_object_t *po, return status; } +/* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the + message to be set to the protocol object. This is used when opening + the default authenticator. */ + +isc_result_t omapi_protocol_send_open (omapi_object_t *po, + omapi_object_t *id, + const char *type, + omapi_object_t *object, + unsigned flags) +{ + isc_result_t status; + omapi_message_object_t *message = (omapi_message_object_t *)0; + omapi_object_t *mo; + + if (po -> type != omapi_type_protocol) + return ISC_R_INVALIDARG; + + status = omapi_message_new ((omapi_object_t **)&message, MDL); + mo = (omapi_object_t *)message; + + if (status == ISC_R_SUCCESS) + status = omapi_set_int_value (mo, (omapi_object_t *)0, + "op", OMAPI_OP_OPEN); + + if (status == ISC_R_SUCCESS) + status = omapi_set_object_value (mo, (omapi_object_t *)0, + "object", object); + + if ((flags & OMAPI_CREATE) && (status == ISC_R_SUCCESS)) + status = omapi_set_boolean_value (mo, (omapi_object_t *)0, + "create", 1); + + if ((flags & OMAPI_UPDATE) && (status == ISC_R_SUCCESS)) + status = omapi_set_boolean_value (mo, (omapi_object_t *)0, + "update", 1); + + if ((flags & OMAPI_EXCL) && (status == ISC_R_SUCCESS)) + status = omapi_set_boolean_value (mo, (omapi_object_t *)0, + "exclusive", 1); + + if ((flags & OMAPI_NOTIFY_PROTOCOL) && (status == ISC_R_SUCCESS)) + status = omapi_set_object_value (mo, (omapi_object_t *)0, + "notify-object", po); + + if (type && (status == ISC_R_SUCCESS)) + status = omapi_set_string_value (mo, (omapi_object_t *)0, + "type", type); + + if (status == ISC_R_SUCCESS) + status = omapi_message_register (mo); + + if (status == ISC_R_SUCCESS) { + status = omapi_protocol_send_message (po, id, mo, + (omapi_object_t *)0); + if (status != ISC_R_SUCCESS) + omapi_message_unregister (mo); + } + + if (message) + omapi_message_dereference (&message, MDL); + + return status; +} + isc_result_t omapi_protocol_send_update (omapi_object_t *po, omapi_object_t *id, unsigned rid, diff --git a/omapip/support.c b/omapip/support.c index 021fd405..f9f14887 100644 --- a/omapip/support.c +++ b/omapip/support.c @@ -53,6 +53,7 @@ omapi_object_type_t *omapi_type_protocol_listener; omapi_object_type_t *omapi_type_waiter; omapi_object_type_t *omapi_type_remote; omapi_object_type_t *omapi_type_message; +omapi_object_type_t *omapi_type_auth_key; omapi_object_type_t *omapi_object_types; int omapi_object_type_count; @@ -62,6 +63,8 @@ isc_result_t omapi_init (void) { isc_result_t status; + dst_init(); + /* Register all the standard object types... */ status = omapi_object_type_register (&omapi_type_connection, "connection", @@ -159,6 +162,19 @@ isc_result_t omapi_init (void) if (status != ISC_R_SUCCESS) return status; + status = omapi_object_type_register (&omapi_type_auth_key, + "authenticator", + 0, + omapi_auth_key_get_value, + omapi_auth_key_destroy, + 0, + omapi_auth_key_stuff_values, + omapi_auth_key_lookup, + 0, 0, 0, 0, 0, + sizeof (omapi_auth_key_t)); + if (status != ISC_R_SUCCESS) + return status; + /* This seems silly, but leave it. */ return ISC_R_SUCCESS; } @@ -630,12 +646,11 @@ isc_result_t omapi_make_int_value (omapi_value_t **vp, return status; } status = omapi_typed_data_new (file, line, &(*vp) -> value, - omapi_datatype_int); + omapi_datatype_int, value); if (status != ISC_R_SUCCESS) { omapi_value_dereference (vp, file, line); return status; } - (*vp) -> value -> u.integer = value; return ISC_R_SUCCESS; } @@ -647,6 +662,36 @@ isc_result_t omapi_make_uint_value (omapi_value_t **vp, return omapi_make_int_value (vp, name, (int)value, file, line); } +isc_result_t omapi_make_object_value (omapi_value_t **vp, + omapi_data_string_t *name, + omapi_object_t *value, + const char *file, int line) +{ + isc_result_t status; + + status = omapi_value_new (vp, file, line); + if (status != ISC_R_SUCCESS) + return status; + + status = omapi_data_string_reference (&(*vp) -> name, + name, file, line); + if (status != ISC_R_SUCCESS) { + omapi_value_dereference (vp, file, line); + return status; + } + + if (value) { + status = omapi_typed_data_new (file, line, &(*vp) -> value, + omapi_datatype_object, value); + if (status != ISC_R_SUCCESS) { + omapi_value_dereference (vp, file, line); + return status; + } + } + + return ISC_R_SUCCESS; +} + isc_result_t omapi_make_handle_value (omapi_value_t **vp, omapi_data_string_t *name, omapi_object_t *value, diff --git a/relay/Makefile.dist b/relay/Makefile.dist index 39e64f25..d02f79fa 100644 --- a/relay/Makefile.dist +++ b/relay/Makefile.dist @@ -26,7 +26,7 @@ MAN = dhcrelay.8 DEBUG = -g INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes -DHCPLIB = ../common/libdhcp.a ../omapip/libomapi.a +DHCPLIB = ../common/libdhcp.a ../omapip/libomapi.a $(BINDLIB) CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS) all: $(PROG) $(CATMANPAGES) diff --git a/server/dhcpd.c b/server/dhcpd.c index 4e7e57e4..d2f207c7 100644 --- a/server/dhcpd.c +++ b/server/dhcpd.c @@ -43,7 +43,7 @@ #ifndef lint static char ocopyright[] = -"$Id: dhcpd.c,v 1.97 2000/07/27 09:03:05 mellon Exp $ Copyright 1995-2000 Internet Software Consortium."; +"$Id: dhcpd.c,v 1.98 2000/08/03 21:00:39 neild Exp $ Copyright 1995-2000 Internet Software Consortium."; #endif static char copyright[] = @@ -137,6 +137,18 @@ const char *path_dhcpd_pid = _PATH_DHCPD_PID; int dhcp_max_agent_option_packet_length = DHCP_MTU_MAX; +static omapi_auth_key_t *omapi_key = (omapi_auth_key_t *)0; + +static isc_result_t verify_addr (omapi_object_t *l, omapi_addr_t *addr) { + return ISC_R_SUCCESS; +} + +static isc_result_t verify_auth (omapi_object_t *p, omapi_auth_key_t *a) { + if (a != omapi_key) + return ISC_R_INVALIDKEY; + return ISC_R_SUCCESS; +} + int main (argc, argv, envp) int argc; char **argv, **envp; @@ -164,6 +176,9 @@ int main (argc, argv, envp) struct parse *parse; int lose; int omapi_port; + omapi_object_t *auth; + struct tsig_key *key; + omapi_typed_data_t *td; int no_dhcpd_conf = 0; int no_dhcpd_db = 0; int no_dhcpd_pid = 0; @@ -413,6 +428,24 @@ int main (argc, argv, envp) data_string_forget (&db, MDL); } + oc = lookup_option (&server_universe, options, SV_OMAPI_KEY); + if (oc && + evaluate_option_cache (&db, (struct packet *)0, + (struct lease *)0, options, + (struct option_state *)0, + &global_scope, oc, MDL)) { + s = dmalloc (db.len + 1, MDL); + if (!s) + log_fatal ("no memory for OMAPI key filename."); + memcpy (s, db.data, db.len); + s [db.len] = 0; + data_string_forget (&db, MDL); + result = omapi_auth_key_lookup_name (&omapi_key, s); + dfree (s, MDL); + if (result != ISC_R_SUCCESS) + log_fatal ("Invalid OMAPI key: %s", s); + } + oc = lookup_option (&server_universe, options, SV_LOCAL_PORT); if (oc && evaluate_option_cache (&db, (struct packet *)0, @@ -510,6 +543,9 @@ int main (argc, argv, envp) isc_result_totext (result)); result = omapi_protocol_listen (listener, (unsigned)omapi_port, 1); + if (result == ISC_R_SUCCESS) + result = omapi_protocol_configure_security + (listener, verify_addr, verify_auth); if (result != ISC_R_SUCCESS) log_fatal ("Can't start OMAPI protocol: %s", isc_result_totext (result)); diff --git a/server/stables.c b/server/stables.c index 57381261..ccf7037f 100644 --- a/server/stables.c +++ b/server/stables.c @@ -43,7 +43,7 @@ #ifndef lint static char copyright[] = -"$Id: stables.c,v 1.15 2000/06/28 23:35:45 mellon Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; +"$Id: stables.c,v 1.16 2000/08/03 21:00:41 neild Exp $ Copyright (c) 1995-2000 The Internet Software Consortium. All rights reserved.\n"; #endif /* not lint */ #include "dhcpd.h" @@ -481,7 +481,7 @@ struct option server_options [256] = { { "limited-broadcast-address", "I", &server_universe, 33 }, { "remote-port", "S", &server_universe, 34 }, { "local-address", "I", &server_universe, 35 }, - { "option-36", "X", &server_universe, 36 }, + { "omapi-key", "t", &server_universe, 36 }, { "option-37", "X", &server_universe, 37 }, { "option-38", "X", &server_universe, 38 }, { "option-39", "X", &server_universe, 39 }, |