2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-03 15:56:00 +00:00

Added authentication support. The tsig_key structure has been renamed

to auth_key and moved into libomapi.  libomapi now depends on libres,
which contains the data signing routines.
This commit is contained in:
Damien Neil
2000-08-03 21:00:41 +00:00
parent c62871ba64
commit 49146f3c15
27 changed files with 1467 additions and 375 deletions

View File

@@ -17,7 +17,7 @@
# http://www.isc.org for more information. # http://www.isc.org for more information.
# #
SUBDIRS= common omapip $(MINIRES) server client relay dhcpctl SUBDIRS= common $(MINIRES) omapip server client relay dhcpctl
all: all:
@for dir in ${SUBDIRS}; do \ @for dir in ${SUBDIRS}; do \

View File

@@ -43,7 +43,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -948,7 +948,8 @@ void parse_client_lease_declaration (cfile, lease, ipp, clientp)
skip_to_semi (cfile); skip_to_semi (cfile);
break; 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_warn (cfile, "unknown key %s", val);
parse_semi (cfile); parse_semi (cfile);
break; break;

View File

@@ -43,7 +43,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -292,29 +292,6 @@ void free_client_lease (lease, file, line)
dfree (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 free_pairs;
pair new_pair (file, line) pair new_pair (file, line)
@@ -1002,114 +979,6 @@ int packet_dereference (ptr, file, line)
return 1; 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) int dns_zone_allocate (ptr, file, line)
struct dns_zone **ptr; struct dns_zone **ptr;
const char *file; const char *file;

View File

@@ -42,7 +42,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #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) || strlen (zone -> key -> name) > NS_MAXDNAME) ||
(!zone -> key -> algorithm || (!zone -> key -> algorithm ||
strlen (zone -> key -> algorithm) > NS_MAXDNAME) || strlen (zone -> key -> algorithm) > NS_MAXDNAME) ||
(!zone -> key -> key.len)) { (!zone -> key)) {
dns_zone_dereference (&zone, MDL); dns_zone_dereference (&zone, MDL);
return ISC_R_INVALIDKEY; 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; return ISC_R_NOMEMORY;
} }
memset (tkey, 0, sizeof *tkey); memset (tkey, 0, sizeof *tkey);
tkey -> data = dmalloc (zone -> key -> key.len, MDL); tkey -> data = dmalloc (zone -> key -> key -> len, MDL);
if (!tkey -> data) { if (!tkey -> data) {
dfree (tkey, MDL); dfree (tkey, MDL);
goto nomem; 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 -> name, zone -> key -> name);
strcpy (tkey -> alg, zone -> key -> algorithm); strcpy (tkey -> alg, zone -> key -> algorithm);
memcpy (tkey -> data, memcpy (tkey -> data,
zone -> key -> key.data, zone -> key -> key.len); zone -> key -> key -> value, zone -> key -> key -> len);
tkey -> len = zone -> key -> key.len; tkey -> len = zone -> key -> key -> len;
*key = tkey; *key = tkey;
return ISC_R_SUCCESS; return ISC_R_SUCCESS;
} }
@@ -249,44 +249,6 @@ isc_result_t dns_zone_lookup (struct dns_zone **zone, const char *name)
return status; 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) int dns_zone_dereference (ptr, file, line)
struct dns_zone **ptr; struct dns_zone **ptr;
const char *file; const char *file;
@@ -326,7 +288,7 @@ int dns_zone_dereference (ptr, file, line)
if (dns_zone -> name) if (dns_zone -> name)
dfree (dns_zone -> name, file, line); dfree (dns_zone -> name, file, line);
if (dns_zone -> key) 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) if (dns_zone -> primary)
option_cache_dereference (&dns_zone -> primary, file, line); option_cache_dereference (&dns_zone -> primary, file, line);
if (dns_zone -> secondary) if (dns_zone -> secondary)
@@ -447,4 +409,3 @@ void repudiate_zone (struct dns_zone **zone)
#endif /* NSUPDATE */ #endif /* NSUPDATE */
HASH_FUNCTIONS (dns_zone, const char *, struct dns_zone) HASH_FUNCTIONS (dns_zone, const char *, struct dns_zone)
HASH_FUNCTIONS (tsig_key, const char *, struct tsig_key)

View File

@@ -43,7 +43,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -1806,7 +1806,8 @@ int parse_zone (struct dns_zone *zone, struct parse *cfile)
skip_to_semi (cfile); skip_to_semi (cfile);
return 0; 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); parse_warn (cfile, "unknown key %s", val);
if (!parse_semi (cfile)) if (!parse_semi (cfile))
return 0; return 0;
@@ -1839,7 +1840,8 @@ int parse_key (struct parse *cfile)
int token; int token;
const char *val; const char *val;
int done = 0; int done = 0;
struct tsig_key *key; struct auth_key *key;
struct data_string ds;
isc_result_t status; isc_result_t status;
token = next_token (&val, cfile); token = next_token (&val, cfile);
@@ -1848,8 +1850,8 @@ int parse_key (struct parse *cfile)
skip_to_semi (cfile); skip_to_semi (cfile);
return 0; return 0;
} }
key = (struct tsig_key *)0; key = (struct auth_key *)0;
if (!tsig_key_allocate (&key, MDL)) if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS)
log_fatal ("no memory for tsig key"); log_fatal ("no memory for tsig key");
key -> name = dmalloc (strlen (val) + 1, MDL); key -> name = dmalloc (strlen (val) + 1, MDL);
if (!key -> name) if (!key -> name)
@@ -1883,13 +1885,23 @@ int parse_key (struct parse *cfile)
break; break;
case SECRET: case SECRET:
if (key -> key.buffer) { if (key -> key) {
parse_warn (cfile, "key %s: too many secrets", parse_warn (cfile, "key %s: too many secrets",
key -> name); key -> name);
goto rbad; goto rbad;
} }
if (!parse_base64 (&key -> key, cfile))
memset (&ds, 0, sizeof(ds));
if (!parse_base64 (&ds, cfile))
goto rbad; 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)) if (!parse_semi (cfile))
goto rbad; goto rbad;
break; break;
@@ -1910,7 +1922,7 @@ int parse_key (struct parse *cfile)
token = next_token (&val, cfile); token = next_token (&val, cfile);
/* Remember the key. */ /* Remember the key. */
status = enter_tsig_key (key); status = omapi_auth_key_enter (key);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
parse_warn (cfile, "tsig key %s: %s", parse_warn (cfile, "tsig key %s: %s",
key -> name, isc_result_totext (status)); key -> name, isc_result_totext (status));
@@ -1921,7 +1933,7 @@ int parse_key (struct parse *cfile)
rbad: rbad:
skip_to_rbrace (cfile, 1); skip_to_rbrace (cfile, 1);
bad: bad:
tsig_key_dereference (&key, MDL); omapi_auth_key_dereference (&key, MDL);
return 0; return 0;
} }
/* /*

View File

@@ -30,13 +30,13 @@ CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS)
all: libdhcpctl.a svtest cltest $(CATMANPAGES) 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 \ $(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 \ $(CC) $(DEBUG) $(LFLAGS) -o cltest cltest.o libdhcpctl.a \
../omapip/libomapi.a $(LIBS) ../omapip/libomapi.a $(BINDLIB) $(LIBS)
libdhcpctl.a: $(OBJ) libdhcpctl.a: $(OBJ)
rm -f libdhcpctl.a rm -f libdhcpctl.a

View File

@@ -46,30 +46,61 @@
int main (int, char **); 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 main (argc, argv)
int argc; int argc;
char **argv; char **argv;
{ {
isc_result_t status, waitstatus; isc_result_t status, waitstatus;
dhcpctl_handle authenticator;
dhcpctl_handle connection; dhcpctl_handle connection;
dhcpctl_handle host_handle, group_handle, interface_handle; dhcpctl_handle host_handle, group_handle, interface_handle;
dhcpctl_data_string cid; dhcpctl_data_string cid;
dhcpctl_data_string result, groupname, identifier; dhcpctl_data_string result, groupname, identifier;
int i; int i;
int mode; int mode = undefined;
char *name = 0, *pass = 0, *algorithm = "hmac-md5", *interface = 0;
const char *action; const char *action;
if (!strcmp (argv [1], "-u")) { for (i = 1; i < argc; i++) {
mode = up; if (!strcmp (argv[i], "-u")) {
} else if (!strcmp (argv [1], "-d")) { mode = up;
mode = down; } else if (!strcmp (argv [1], "-d")) {
} else { mode = down;
fprintf (stderr, "Unknown switch \"%s\"\n", argv [1]); } else if (!strcmp (argv[i], "-n")) {
exit (1); 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 (); status = dhcpctl_initialize ();
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
fprintf (stderr, "dhcpctl_initialize: %s\n", fprintf (stderr, "dhcpctl_initialize: %s\n",
@@ -77,16 +108,29 @@ int main (argc, argv)
exit (1); 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, status = dhcpctl_connect (&connection, "127.0.0.1", 7911,
(dhcpctl_handle)0); authenticator);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
fprintf (stderr, "dhcpctl_connect: %s\n", fprintf (stderr, "dhcpctl_connect: %s\n",
isc_result_totext (status)); isc_result_totext (status));
exit (1); exit (1);
} }
memset (&interface_handle, 0, sizeof interface_handle); interface_handle = dhcpctl_null_handle;
status = dhcpctl_new_object (&interface_handle, status = dhcpctl_new_object (&interface_handle,
connection, "interface"); connection, "interface");
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
@@ -95,7 +139,8 @@ int main (argc, argv)
exit (1); 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) { if (status != ISC_R_SUCCESS) {
fprintf (stderr, "dhcpctl_set_value: %s\n", fprintf (stderr, "dhcpctl_set_value: %s\n",
isc_result_totext (status)); isc_result_totext (status));
@@ -104,7 +149,7 @@ int main (argc, argv)
if (mode == up) { if (mode == up) {
/* "up" the interface */ /* "up" the interface */
printf ("upping interface %s\n", argv [2]); printf ("upping interface %s\n", interface);
action = "create"; action = "create";
status = dhcpctl_open_object (interface_handle, connection, status = dhcpctl_open_object (interface_handle, connection,
DHCPCTL_CREATE | DHCPCTL_EXCL); DHCPCTL_CREATE | DHCPCTL_EXCL);
@@ -115,7 +160,7 @@ int main (argc, argv)
} }
} else { } else {
/* down the interface */ /* down the interface */
printf ("downing interface %s\n", argv [2]); printf ("downing interface %s\n", interface);
action = "remove"; action = "remove";
status = dhcpctl_open_object (interface_handle, connection, 0); status = dhcpctl_open_object (interface_handle, connection, 0);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {

View File

@@ -91,6 +91,7 @@ dhcpctl_status dhcpctl_connect (dhcpctl_handle *connection,
dhcpctl_handle authinfo) dhcpctl_handle authinfo)
{ {
isc_result_t status; isc_result_t status;
dhcpctl_status waitstatus;
status = omapi_generic_new (connection, MDL); status = omapi_generic_new (connection, MDL);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {

View File

@@ -50,9 +50,11 @@ typedef isc_result_t dhcpctl_status;
typedef omapi_object_t *dhcpctl_handle; typedef omapi_object_t *dhcpctl_handle;
typedef omapi_data_string_t *dhcpctl_data_string; typedef omapi_data_string_t *dhcpctl_data_string;
#define DHCPCTL_CREATE 1 #define dhcpctl_null_handle ((dhcpctl_handle) 0)
#define DHCPCTL_UPDATE 2
#define DHCPCTL_EXCL 4 #define DHCPCTL_CREATE OMAPI_CREATE
#define DHCPCTL_UPDATE OMAPI_UPDATE
#define DHCPCTL_EXCL OMAPI_EXCL
typedef struct { typedef struct {
OMAPI_OBJECT_PREAMBLE; OMAPI_OBJECT_PREAMBLE;
@@ -105,6 +107,10 @@ isc_result_t dhcpctl_callback_stuff_values (omapi_object_t *,
omapi_object_t *, 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_open_object (dhcpctl_handle, dhcpctl_handle, int);
dhcpctl_status dhcpctl_new_object (dhcpctl_handle *, dhcpctl_status dhcpctl_new_object (dhcpctl_handle *,
dhcpctl_handle, const char *); dhcpctl_handle, const char *);

View File

@@ -44,6 +44,56 @@
#include <omapip/omapip_p.h> #include <omapip/omapip_p.h>
#include "dhcpctl.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 /* dhcpctl_new_object
synchronous - creates a local handle for a host entry. synchronous - creates a local handle for a host entry.

View File

@@ -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];
};

View File

@@ -74,7 +74,6 @@
#include "statement.h" #include "statement.h"
#include "tree.h" #include "tree.h"
#include "inet.h" #include "inet.h"
#include "auth.h"
#include "dhctoken.h" #include "dhctoken.h"
#include <isc/result.h> #include <isc/result.h>
@@ -373,6 +372,7 @@ struct lease_state {
#define SV_LIMITED_BROADCAST_ADDRESS 33 #define SV_LIMITED_BROADCAST_ADDRESS 33
#define SV_REMOTE_PORT 34 #define SV_REMOTE_PORT 34
#define SV_LOCAL_ADDRESS 35 #define SV_LOCAL_ADDRESS 35
#define SV_OMAPI_KEY 36
#if !defined (DEFAULT_DEFAULT_LEASE_TIME) #if !defined (DEFAULT_DEFAULT_LEASE_TIME)
# define DEFAULT_DEFAULT_LEASE_TIME 43200 # define DEFAULT_DEFAULT_LEASE_TIME 43200
@@ -589,13 +589,6 @@ struct class {
struct executable_statement *statements; struct executable_statement *statements;
}; };
struct tsig_key {
int refcnt;
char *name;
char *algorithm;
struct data_string key;
};
/* DHCP client lease structure... */ /* DHCP client lease structure... */
struct client_lease { struct client_lease {
struct client_lease *next; /* Next lease in list. */ struct client_lease *next; /* Next lease in list. */
@@ -604,7 +597,7 @@ struct client_lease {
char *server_name; /* Name of boot server. */ char *server_name; /* Name of boot server. */
char *filename; /* Name of file we're supposed to boot. */ char *filename; /* Name of file we're supposed to boot. */
struct string_list *medium; /* Network medium. */ 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_static : 1; /* If set, lease is from config file. */
unsigned int is_bootp: 1; /* If set, lease was aquired with BOOTP. */ unsigned int is_bootp: 1; /* If set, lease was aquired with BOOTP. */
@@ -819,7 +812,7 @@ struct dns_zone {
char *name; char *name;
struct option_cache *primary; struct option_cache *primary;
struct option_cache *secondary; struct option_cache *secondary;
struct tsig_key *key; struct auth_key *key;
}; };
/* Bitmask of dhcp option codes. */ /* 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)); void free_dhcp_packet PROTO ((struct dhcp_packet *, const char *, int));
struct client_lease *new_client_lease PROTO ((const char *, int)); struct client_lease *new_client_lease PROTO ((const char *, int));
void free_client_lease PROTO ((struct client_lease *, 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)); struct permit *new_permit PROTO ((const char *, int));
void free_permit PROTO ((struct permit *, const char *, int)); void free_permit PROTO ((struct permit *, const char *, int));
pair new_pair PROTO ((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_allocate PROTO ((struct dns_zone **, const char *, int));
int dns_zone_reference PROTO ((struct dns_zone **, int dns_zone_reference PROTO ((struct dns_zone **,
struct dns_zone *, const char *, int)); 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 */ /* print.c */
char *print_hw_addr PROTO ((int, int, unsigned char *)); char *print_hw_addr PROTO ((int, int, unsigned char *));
@@ -1760,8 +1747,6 @@ void tkey_free (ns_tsig_key **);
#endif #endif
isc_result_t enter_dns_zone (struct dns_zone *); isc_result_t enter_dns_zone (struct dns_zone *);
isc_result_t dns_zone_lookup (struct dns_zone **, const char *); 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)); int dns_zone_dereference PROTO ((struct dns_zone **, const char *, int));
#if defined (NSUPDATE) #if defined (NSUPDATE)
ns_rcode find_cached_zone (const char *, ns_class, char *, 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 **); void repudiate_zone (struct dns_zone **);
#endif /* NSUPDATE */ #endif /* NSUPDATE */
HASH_FUNCTIONS_DECL (dns_zone, const char *, struct dns_zone) HASH_FUNCTIONS_DECL (dns_zone, const char *, struct dns_zone)
HASH_FUNCTIONS_DECL (tsig_key, const char *, struct tsig_key)
/* resolv.c */ /* resolv.c */
extern char path_resolv_conf []; extern char path_resolv_conf [];
@@ -1825,10 +1809,6 @@ int find_matching_case (struct executable_statement **,
struct binding_scope **, struct binding_scope **,
struct expression *, struct executable_statement *); 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 */ /* comapi.c */
extern omapi_object_type_t *dhcp_type_interface; extern omapi_object_type_t *dhcp_type_interface;
extern omapi_object_type_t *dhcp_type_group; extern omapi_object_type_t *dhcp_type_group;

View File

@@ -154,6 +154,18 @@ typedef struct {
omapi_addr_t *addresses; omapi_addr_t *addresses;
} omapi_addr_list_t; } 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) \ #define OMAPI_OBJECT_ALLOC(name, stype, type) \
isc_result_t name##_allocate (stype **p, const char *file, int line) \ 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 *, isc_result_t omapi_connect_list (omapi_object_t *, omapi_addr_list_t *,
omapi_addr_t *); omapi_addr_t *);
isc_result_t omapi_protocol_listen (omapi_object_t *, unsigned, int); 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_accept (omapi_object_t *);
isc_result_t omapi_protocol_send_intro (omapi_object_t *, unsigned, unsigned); 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_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 *, isc_result_t omapi_protocol_set_value (omapi_object_t *, omapi_object_t *,
omapi_data_string_t *, omapi_data_string_t *,
omapi_typed_data_t *); omapi_typed_data_t *);
@@ -221,6 +245,9 @@ isc_result_t omapi_protocol_listener_stuff (omapi_object_t *,
omapi_object_t *); omapi_object_t *);
isc_result_t omapi_protocol_send_status (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, 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 *, isc_result_t omapi_protocol_send_update (omapi_object_t *, omapi_object_t *,
unsigned, 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_reader (omapi_object_t *);
isc_result_t omapi_connection_writer (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_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 *, isc_result_t omapi_connection_set_value (omapi_object_t *, omapi_object_t *,
omapi_data_string_t *, omapi_data_string_t *,
omapi_typed_data_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 *); isc_result_t omapi_listener_accept (omapi_object_t *);
int omapi_listener_readfd (omapi_object_t *); int omapi_listener_readfd (omapi_object_t *);
isc_result_t omapi_accept (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 *, isc_result_t omapi_listener_set_value (omapi_object_t *, omapi_object_t *,
omapi_data_string_t *, omapi_data_string_t *,
omapi_typed_data_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_unregister (omapi_object_t *);
isc_result_t omapi_message_process (omapi_object_t *, 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_connection;
extern omapi_object_type_t *omapi_type_listener; extern omapi_object_type_t *omapi_type_listener;
extern omapi_object_type_t *omapi_type_io_object; 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_waiter;
extern omapi_object_type_t *omapi_type_remote; extern omapi_object_type_t *omapi_type_remote;
extern omapi_object_type_t *omapi_type_message; 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; 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); int, const char *, int);
isc_result_t omapi_make_uint_value (omapi_value_t **, omapi_data_string_t *, isc_result_t omapi_make_uint_value (omapi_value_t **, omapi_data_string_t *,
unsigned int, const char *, int); 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 *, isc_result_t omapi_make_handle_value (omapi_value_t **, omapi_data_string_t *,
omapi_object_t *, const char *, int); omapi_object_t *, const char *, int);
isc_result_t omapi_make_string_value (omapi_value_t **, omapi_data_string_t *, isc_result_t omapi_make_string_value (omapi_value_t **, omapi_data_string_t *,

View File

@@ -68,6 +68,7 @@
#include "cdefs.h" #include "cdefs.h"
#include "osdep.h" #include "osdep.h"
#include <isc/dst.h>
#include <isc/result.h> #include <isc/result.h>
#include <omapip/convert.h> #include <omapip/convert.h>
@@ -127,12 +128,17 @@ typedef struct __omapi_message_object {
u_int32_t rid; u_int32_t rid;
} omapi_message_object_t; } 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 { typedef struct {
OMAPI_OBJECT_PREAMBLE; OMAPI_OBJECT_PREAMBLE;
u_int32_t header_size; u_int32_t header_size;
u_int32_t protocol_version; u_int32_t protocol_version;
u_int32_t next_xid; u_int32_t next_xid;
omapi_object_t *authinfo; /* Default authinfo to use. */
omapi_protocol_state_t state; /* Input state. */ omapi_protocol_state_t state; /* Input state. */
int reading_message_values; /* True if reading message-specific int reading_message_values; /* True if reading message-specific
@@ -140,10 +146,24 @@ typedef struct {
omapi_message_object_t *message; /* Incoming message. */ omapi_message_object_t *message; /* Incoming message. */
omapi_data_string_t *name; /* Incoming name. */ omapi_data_string_t *name; /* Incoming name. */
omapi_typed_data_t *value; /* Incoming value. */ 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; } omapi_protocol_object_t;
typedef struct { typedef struct {
OMAPI_OBJECT_PREAMBLE; 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; } omapi_protocol_listener_object_t;
#include <omapip/buffer.h> #include <omapip/buffer.h>
@@ -152,6 +172,7 @@ typedef struct __omapi_listener_object {
OMAPI_OBJECT_PREAMBLE; OMAPI_OBJECT_PREAMBLE;
int socket; /* Connection socket. */ int socket; /* Connection socket. */
struct sockaddr_in address; struct sockaddr_in address;
isc_result_t (*verify_addr) (omapi_object_t *, omapi_addr_t *);
} omapi_listener_object_t; } omapi_listener_object_t;
typedef struct __omapi_connection_object { typedef struct __omapi_connection_object {
@@ -170,6 +191,12 @@ typedef struct __omapi_connection_object {
omapi_buffer_t *outbufs; omapi_buffer_t *outbufs;
omapi_listener_object_t *listener; /* Listener that accepted this omapi_listener_object_t *listener; /* Listener that accepted this
connection, if any. */ 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; } omapi_connection_object_t;
typedef struct __omapi_io_object { typedef struct __omapi_io_object {
@@ -191,6 +218,7 @@ typedef struct __omapi_generic_object {
typedef struct __omapi_waiter_object { typedef struct __omapi_waiter_object {
OMAPI_OBJECT_PREAMBLE; OMAPI_OBJECT_PREAMBLE;
int ready; int ready;
isc_result_t waitstatus;
struct __omapi_waiter_object *next; struct __omapi_waiter_object *next;
} omapi_waiter_object_t; } omapi_waiter_object_t;
@@ -226,6 +254,13 @@ OMAPI_OBJECT_ALLOC_DECL (omapi_generic,
OMAPI_OBJECT_ALLOC_DECL (omapi_message, OMAPI_OBJECT_ALLOC_DECL (omapi_message,
omapi_message_object_t, omapi_type_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_priority;
extern int log_perror; extern int log_perror;
extern void (*log_cleanup) (void); extern void (*log_cleanup) (void);

View File

@@ -1,5 +1,5 @@
#ifndef LINT #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 #endif
/* /*
@@ -722,7 +722,8 @@ dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage,
} }
memset(out_storage, 0, out_len); memset(out_storage, 0, out_len);
val = (u_int16_t)(key->dk_flags & 0xffff); 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; loc += 2;
out_storage[loc++] = (u_char) key->dk_proto; 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 */ if (key->dk_flags > 0xffff) { /* Extended flags */
val = (u_int16_t)((key->dk_flags >> 16) & 0xffff); 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; loc += 2;
} }
if (key->dk_KEY_struct == NULL) if (key->dk_KEY_struct == NULL)

View File

@@ -21,10 +21,10 @@ CATMANPAGES = omapi.cat3
SEDMANPAGES = omapi.man3 SEDMANPAGES = omapi.man3
SRC = protocol.c buffer.c alloc.c result.c connection.c errwarn.c \ 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 \ 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 \ 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 \ 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 MAN = omapi.3
DEBUG = -g DEBUG = -g
@@ -33,8 +33,8 @@ CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS)
all: libomapi.a svtest $(CATMANPAGES) all: libomapi.a svtest $(CATMANPAGES)
svtest: test.o libomapi.a svtest: test.o libomapi.a $(BINDLIB)
$(CC) $(DEBUG) $(LFLAGS) -o svtest test.o libomapi.a $(LIBS) $(CC) $(DEBUG) $(LFLAGS) -o svtest test.o libomapi.a $(BINDLIB) $(LIBS)
libomapi.a: $(OBJ) libomapi.a: $(OBJ)
rm -f libomapi.a rm -f libomapi.a

271
omapip/auth.c Normal file
View File

@@ -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)

View File

@@ -139,6 +139,7 @@ isc_result_t omapi_connection_copyin (omapi_object_t *h,
isc_result_t status; isc_result_t status;
int bytes_copied = 0; int bytes_copied = 0;
unsigned copy_len; unsigned copy_len;
int sig_flags = SIG_MODE_UPDATE;
omapi_connection_object_t *c; omapi_connection_object_t *c;
/* Make sure len is valid. */ /* 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)) if (copy_len > (len - bytes_copied))
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], memcpy (&buffer -> buf [buffer -> tail],
&bufp [bytes_copied], copy_len); &bufp [bytes_copied], copy_len);
buffer -> tail += copy_len; buffer -> tail += copy_len;
@@ -200,7 +212,9 @@ isc_result_t omapi_connection_copyout (unsigned char *buf,
unsigned first_byte; unsigned first_byte;
omapi_buffer_t *buffer; omapi_buffer_t *buffer;
unsigned char *bufp; unsigned char *bufp;
int sig_flags = SIG_MODE_UPDATE;
omapi_connection_object_t *c; omapi_connection_object_t *c;
isc_result_t status;
if (!h || h -> type != omapi_type_connection) if (!h || h -> type != omapi_type_connection)
return ISC_R_INVALIDARG; return ISC_R_INVALIDARG;
@@ -231,6 +245,20 @@ isc_result_t omapi_connection_copyout (unsigned char *buf,
if (bytes_this_copy > bytes_remaining) if (bytes_this_copy > bytes_remaining)
bytes_this_copy = bytes_remaining; bytes_this_copy = bytes_remaining;
if (bufp) { 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], memcpy (bufp, &buffer -> buf [first_byte],
bytes_this_copy); bytes_this_copy);
bufp += bytes_this_copy; bufp += bytes_this_copy;

View File

@@ -406,13 +406,188 @@ isc_result_t omapi_connection_reaper (omapi_object_t *h)
return ISC_R_SUCCESS; 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, isc_result_t omapi_connection_set_value (omapi_object_t *h,
omapi_object_t *id, omapi_object_t *id,
omapi_data_string_t *name, omapi_data_string_t *name,
omapi_typed_data_t *value) omapi_typed_data_t *value)
{ {
omapi_connection_object_t *c;
isc_result_t status;
if (h -> type != omapi_type_connection) if (h -> type != omapi_type_connection)
return ISC_R_INVALIDARG; 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) if (h -> inner && h -> inner -> type -> set_value)
return (*(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_data_string_t *name,
omapi_value_t **value) 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) if (h -> type != omapi_type_connection)
return ISC_R_INVALIDARG; 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) if (h -> inner && h -> inner -> type -> get_value)
return (*(h -> inner -> type -> get_value)) return (*(h -> inner -> type -> get_value))

View File

@@ -206,8 +206,9 @@ isc_result_t omapi_wait_for_completion (omapi_object_t *object,
if (waiter -> inner) if (waiter -> inner)
omapi_object_dereference (&waiter -> inner, MDL); omapi_object_dereference (&waiter -> inner, MDL);
status = waiter -> waitstatus;
omapi_waiter_dereference (&waiter, MDL); omapi_waiter_dereference (&waiter, MDL);
return ISC_R_SUCCESS; return status;;
} }
isc_result_t omapi_one_dispatch (omapi_object_t *wo, 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")) { if (!strcmp (name, "ready")) {
waiter = (omapi_waiter_object_t *)h; waiter = (omapi_waiter_object_t *)h;
waiter -> ready = 1; 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; return ISC_R_SUCCESS;
} }

View File

@@ -122,6 +122,17 @@ isc_result_t omapi_listen_addr (omapi_object_t *h,
} }
#endif #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 /* Try to bind to the wildcard address using the port number
we were given. */ we were given. */
i = bind (obj -> socket, i = bind (obj -> socket,
@@ -173,6 +184,7 @@ isc_result_t omapi_accept (omapi_object_t *h)
SOCKLEN_T len; SOCKLEN_T len;
omapi_connection_object_t *obj; omapi_connection_object_t *obj;
omapi_listener_object_t *listener; omapi_listener_object_t *listener;
omapi_addr_t addr;
int i; int i;
if (h -> type != omapi_type_listener) if (h -> type != omapi_type_listener)
@@ -200,6 +212,21 @@ isc_result_t omapi_accept (omapi_object_t *h)
obj -> state = omapi_connection_connected; 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, status = omapi_register_io_object ((omapi_object_t *)obj,
omapi_connection_readfd, omapi_connection_readfd,
omapi_connection_writefd, omapi_connection_writefd,
@@ -221,6 +248,22 @@ isc_result_t omapi_accept (omapi_object_t *h)
return status; 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, isc_result_t omapi_listener_set_value (omapi_object_t *h,
omapi_object_t *id, omapi_object_t *id,
omapi_data_string_t *name, omapi_data_string_t *name,

View File

@@ -249,14 +249,14 @@ isc_result_t omapi_message_signal_handler (omapi_object_t *h,
return ISC_R_INVALIDARG; return ISC_R_INVALIDARG;
m = (omapi_message_object_t *)h; m = (omapi_message_object_t *)h;
if (!strcmp (name, "status") && if (!strcmp (name, "status")) {
(m -> object || m -> notify_object)) { if (m -> notify_object &&
if (m -> object) m -> notify_object -> type -> signal_handler)
return ((m -> object -> type -> signal_handler))
(m -> object, name, ap);
else
return ((m -> notify_object -> type -> signal_handler)) return ((m -> notify_object -> type -> signal_handler))
(m -> notify_object, name, ap); (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) if (h -> inner && h -> inner -> type -> signal_handler)
return (*(h -> inner -> type -> signal_handler)) (h -> inner, 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. */ response, something's fishy. */
if (!m) if (!m)
return ISC_R_NOTFOUND; 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; 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) { switch (message -> op) {
case OMAPI_OP_OPEN: case OMAPI_OP_OPEN:
if (m) { if (m) {
return omapi_protocol_send_status 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"); message -> id, "OPEN can't be a response");
} }
/* Get the type of the requested object, if one was /* Get the type of the requested object, if one was
specified. */ specified. */
status = omapi_get_value_str (mo, (omapi_object_t *)0, status = omapi_get_value_str (mo, message -> id_object,
"type", &tv); "type", &tv);
if (status == ISC_R_SUCCESS && if (status == ISC_R_SUCCESS &&
(tv -> value -> type == omapi_datatype_data || (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) if (tv)
omapi_value_dereference (&tv, MDL); 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. */ /* Get the create flag. */
status = omapi_get_value_str (mo, status = omapi_get_value_str (mo, message -> id_object,
(omapi_object_t *)0,
"create", &tv); "create", &tv);
if (status == ISC_R_SUCCESS) { if (status == ISC_R_SUCCESS) {
status = omapi_get_int_value (&create, tv -> value); status = omapi_get_int_value (&create, tv -> value);
omapi_value_dereference (&tv, MDL); omapi_value_dereference (&tv, MDL);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
status, message -> id, status, message -> id,
"invalid create flag value"); "invalid create flag value");
} }
@@ -423,15 +447,14 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po)
create = 0; create = 0;
/* Get the update flag. */ /* Get the update flag. */
status = omapi_get_value_str (mo, status = omapi_get_value_str (mo, message -> id_object,
(omapi_object_t *)0,
"update", &tv); "update", &tv);
if (status == ISC_R_SUCCESS) { if (status == ISC_R_SUCCESS) {
status = omapi_get_int_value (&update, tv -> value); status = omapi_get_int_value (&update, tv -> value);
omapi_value_dereference (&tv, MDL); omapi_value_dereference (&tv, MDL);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
status, message -> id, status, message -> id,
"invalid update flag value"); "invalid update flag value");
} }
@@ -439,15 +462,14 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po)
update = 0; update = 0;
/* Get the exclusive flag. */ /* Get the exclusive flag. */
status = omapi_get_value_str (mo, status = omapi_get_value_str (mo, message -> id_object,
(omapi_object_t *)0,
"exclusive", &tv); "exclusive", &tv);
if (status == ISC_R_SUCCESS) { if (status == ISC_R_SUCCESS) {
status = omapi_get_int_value (&exclusive, tv -> value); status = omapi_get_int_value (&exclusive, tv -> value);
omapi_value_dereference (&tv, MDL); omapi_value_dereference (&tv, MDL);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
status, message -> id, status, message -> id,
"invalid exclusive flag value"); "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 (!type) {
if (create) { if (create) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
ISC_R_INVALIDARG, message -> id, ISC_R_INVALIDARG,
message -> id,
"type required on create"); "type required on create");
} }
goto refresh; goto refresh;
@@ -470,25 +493,25 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po)
look up the object. */ look up the object. */
if (!type -> lookup) { if (!type -> lookup) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
ISC_R_NOTIMPLEMENTED, message -> id, ISC_R_NOTIMPLEMENTED, message -> id,
"unsearchable object type"); "unsearchable object type");
} }
if (!message -> object) { if (!message -> object) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
ISC_R_NOTFOUND, message -> id, ISC_R_NOTFOUND, message -> id,
"no lookup key specified"); "no lookup key specified");
} }
status = (*(type -> lookup)) (&object, (omapi_object_t *)0, status = (*(type -> lookup)) (&object, message -> id_object,
message -> object); message -> object);
if (status != ISC_R_SUCCESS && if (status != ISC_R_SUCCESS &&
status != ISC_R_NOTFOUND && status != ISC_R_NOTFOUND &&
status != ISC_R_NOKEYS) { status != ISC_R_NOKEYS) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
status, message -> id, status, message -> id,
"object lookup failed"); "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. */ create it, return an error. */
if (status == ISC_R_NOTFOUND && !create) { if (status == ISC_R_NOTFOUND && !create) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
ISC_R_NOTFOUND, message -> id, ISC_R_NOTFOUND, message -> id,
"no object matches specification"); "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) { if (status == ISC_R_SUCCESS && create && exclusive) {
omapi_object_dereference (&object, MDL); omapi_object_dereference (&object, MDL);
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
ISC_R_EXISTS, message -> id, ISC_R_EXISTS, message -> id,
"specified object already exists"); "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 we're creating the object, do it now. */
if (!object) { if (!object) {
status = omapi_object_create (&object, status = omapi_object_create (&object,
(omapi_object_t *)0, message -> id_object,
type); type);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
status, message -> id, status, message -> id,
"can't create new object"); "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 we're updating it, do so now. */
if (create || update) { 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, status = omapi_object_update (object,
(omapi_object_t *)0, message -> id_object,
message -> object, message -> object,
message -> h); message -> h);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
omapi_object_dereference (&object, MDL); omapi_object_dereference (&object, MDL);
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
status, message -> id, status, message -> id,
"can't update object"); "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 /* Now send the new contents of the object back in
response. */ 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); status = omapi_handle_lookup (&object, message -> h);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
status, message -> id, status, message -> id,
"no matching handle"); "no matching handle");
} }
send: send:
status = omapi_protocol_send_update (po, (omapi_object_t *)0, status = omapi_protocol_send_update (po, message -> id_object,
message -> id, object); message -> id, object);
omapi_object_dereference (&object, MDL); omapi_object_dereference (&object, MDL);
return status; return status;
case OMAPI_OP_UPDATE: case OMAPI_OP_UPDATE:
if (m -> object) { if (m && m -> object) {
omapi_object_reference (&object, m -> object, MDL); omapi_object_reference (&object, m -> object, MDL);
} else { } else {
status = omapi_handle_lookup (&object, message -> h); status = omapi_handle_lookup (&object, message -> h);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
status, message -> id, status, message -> id,
"no matching handle"); "no matching handle");
} }
} }
status = omapi_object_update (object, (omapi_object_t *)0, if (object -> type == omapi_type_auth_key ||
message -> object, (object -> inner &&
message -> h); 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) { if (status != ISC_R_SUCCESS) {
omapi_object_dereference (&object, MDL); omapi_object_dereference (&object, MDL);
if (!message -> rid) if (!message -> rid)
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
status, message -> id, status, message -> id,
"can't update object"); "can't update object");
if (m) if (m)
@@ -591,7 +662,7 @@ isc_result_t omapi_message_process (omapi_object_t *mo, omapi_object_t *po)
} }
if (!message -> rid) if (!message -> rid)
status = omapi_protocol_send_status status = omapi_protocol_send_status
(po, (omapi_object_t *)0, ISC_R_SUCCESS, (po, message -> id_object, ISC_R_SUCCESS,
message -> id, (char *)0); message -> id, (char *)0);
if (m) if (m)
omapi_signal ((omapi_object_t *)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: case OMAPI_OP_NOTIFY:
return omapi_protocol_send_status 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"); message -> id, "notify not implemented yet");
case OMAPI_OP_STATUS: 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; return ISC_R_UNEXPECTED;
/* Get the wait status. */ /* Get the wait status. */
status = omapi_get_value_str (mo, status = omapi_get_value_str (mo, message -> id_object,
(omapi_object_t *)0,
"result", &tv); "result", &tv);
if (status == ISC_R_SUCCESS) { if (status == ISC_R_SUCCESS) {
status = omapi_get_int_value (&wsi, tv -> value); 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 } else
waitstatus = ISC_R_UNEXPECTED; waitstatus = ISC_R_UNEXPECTED;
status = omapi_get_value_str (mo, status = omapi_get_value_str (mo, message -> id_object,
(omapi_object_t *)0,
"message", &tv); "message", &tv);
omapi_signal ((omapi_object_t *)m, "status", waitstatus, tv); omapi_signal ((omapi_object_t *)m, "status", waitstatus, tv);
if (status == ISC_R_SUCCESS) 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); status = omapi_handle_lookup (&object, message -> h);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
status, message -> id, status, message -> id,
"no matching handle"); "no matching handle");
} }
if (!object -> type -> remove) if (!object -> type -> remove)
return omapi_protocol_send_status return omapi_protocol_send_status
(po, (omapi_object_t *)0, (po, message -> id_object,
ISC_R_NOTIMPLEMENTED, message -> id, ISC_R_NOTIMPLEMENTED, message -> id,
"no remove method for object"); "no remove method for object");
status = (*(object -> type -> remove)) (object, status = (*(object -> type -> remove)) (object,
(omapi_object_t *)0); message -> id_object);
omapi_object_dereference (&object, MDL); 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, status, message -> id,
(char *)0); (char *)0);
} }

View File

@@ -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, isc_result_t omapi_protocol_connect (omapi_object_t *h,
const char *server_name, const char *server_name,
unsigned port, unsigned port,
omapi_object_t *authinfo) omapi_object_t *a)
{ {
isc_result_t status; isc_result_t status;
omapi_protocol_object_t *obj; omapi_protocol_object_t *obj;
@@ -78,8 +78,30 @@ isc_result_t omapi_protocol_connect (omapi_object_t *h,
return status; return status;
} }
if (authinfo) /* If we were passed a default authenticator, store it now. We'll
omapi_object_reference (&obj -> authinfo, authinfo, MDL); 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); omapi_protocol_dereference (&obj, MDL);
return ISC_R_SUCCESS; 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_protocol_object_t *p;
omapi_object_t *c; omapi_object_t *c;
omapi_message_object_t *m, *om; omapi_message_object_t *m, *om;
omapi_remote_auth_t *ra;
omapi_value_t *signature;
isc_result_t status; isc_result_t status;
u_int32_t foo; u_int32_t foo;
unsigned auth_len;
if (po -> type != omapi_type_protocol || if (po -> type != omapi_type_protocol ||
!po -> outer || po -> outer -> type != omapi_type_connection || !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; m = (omapi_message_object_t *)mo;
om = (omapi_message_object_t *)omo; om = (omapi_message_object_t *)omo;
/* XXX Write the authenticator length */ /* Find the authid to use for this message. */
status = omapi_connection_put_uint32 (c, 0); if (id) {
if (status != ISC_R_SUCCESS) 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; 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) { if (status != ISC_R_SUCCESS) {
omapi_disconnect (c, 1); omapi_disconnect (c, 1);
return status; return status;
@@ -223,7 +293,35 @@ isc_result_t omapi_protocol_send_message (omapi_object_t *po,
return status; 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; return ISC_R_SUCCESS;
} }
@@ -235,6 +333,7 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
isc_result_t status; isc_result_t status;
omapi_protocol_object_t *p; omapi_protocol_object_t *p;
omapi_object_t *c; omapi_object_t *c;
omapi_value_t *signature;
u_int16_t nlen; u_int16_t nlen;
u_int32_t vlen; u_int32_t vlen;
u_int32_t th; u_int32_t th;
@@ -257,6 +356,19 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
return ISC_R_SUCCESS; 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? */ /* Not a signal we recognize? */
if (strcmp (name, "ready")) { if (strcmp (name, "ready")) {
if (p -> inner && p -> inner -> type -> signal_handler) 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; 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: to_header_wait:
/* The next thing we're expecting is a message header. */ /* 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; return status;
} }
p -> verify_result = ISC_R_SUCCESS;
/* Swap in the header... */ /* Swap in the header... */
omapi_connection_get_uint32 (c, &p -> message -> authid); 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 -> authlen);
omapi_connection_get_uint32 (c, &p -> message -> op); omapi_connection_get_uint32 (c, &p -> message -> op);
omapi_connection_get_uint32 (c, &th); omapi_connection_get_uint32 (c, &th);
@@ -462,31 +604,71 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h,
signature_wait: signature_wait:
case omapi_protocol_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, status = omapi_typed_data_new (MDL,
&p -> message -> authenticator, &p -> message -> authenticator,
omapi_datatype_data, omapi_datatype_data,
p -> message -> authlen); p -> message -> authlen);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
omapi_value_dereference (&signature, MDL);
omapi_disconnect (c, 1); omapi_disconnect (c, 1);
return ISC_R_NOMEMORY; return ISC_R_NOMEMORY;
} }
omapi_connection_copyout omapi_connection_copyout
(p -> message -> authenticator -> u.buffer.value, c, (p -> message -> authenticator -> u.buffer.value, c,
p -> message -> authlen); 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. */ /* Process the message. */
message_done: message_done:
status = omapi_message_process ((omapi_object_t *)p -> message, if (p -> verify_result != ISC_R_SUCCESS) {
h); 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) { if (status != ISC_R_SUCCESS) {
omapi_disconnect (c, 1); omapi_disconnect (c, 1);
return ISC_R_NOMEMORY; return ISC_R_NOMEMORY;
} }
/* XXX unbind the authenticator. */
auth_unbind:
omapi_message_dereference (&p -> message, MDL); omapi_message_dereference (&p -> message, MDL);
/* Now wait for the next message. */ /* 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; 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, isc_result_t omapi_protocol_set_value (omapi_object_t *h,
omapi_object_t *id, omapi_object_t *id,
omapi_data_string_t *name, omapi_data_string_t *name,
omapi_typed_data_t *value) omapi_typed_data_t *value)
{ {
omapi_protocol_object_t *p;
omapi_remote_auth_t *r;
if (h -> type != omapi_type_protocol) if (h -> type != omapi_type_protocol)
return ISC_R_INVALIDARG; 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) if (h -> inner && h -> inner -> type -> set_value)
return (*(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_data_string_t *name,
omapi_value_t **value) omapi_value_t **value)
{ {
omapi_protocol_object_t *p;
if (h -> type != omapi_type_protocol) if (h -> type != omapi_type_protocol)
return ISC_R_INVALIDARG; 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) if (h -> inner && h -> inner -> type -> get_value)
return (*(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; p = (omapi_protocol_object_t *)h;
if (p -> message) if (p -> message)
omapi_message_dereference (&p -> message, file, line); 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; return ISC_R_SUCCESS;
} }
@@ -559,6 +860,46 @@ isc_result_t omapi_protocol_stuff_values (omapi_object_t *c,
return ISC_R_SUCCESS; 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 /* Set up a listener for the omapi protocol. The handle stored points to
a listener object, not a protocol object. */ a listener object, not a protocol object. */
@@ -586,6 +927,9 @@ isc_result_t omapi_protocol_listen (omapi_object_t *h,
return status; return status;
} }
/* What a terrible default. */
obj -> insecure = 1;
status = omapi_listen ((omapi_object_t *)obj, port, max); status = omapi_listen ((omapi_object_t *)obj, port, max);
omapi_protocol_listener_dereference (&obj, MDL); omapi_protocol_listener_dereference (&obj, MDL);
return status; return status;
@@ -623,6 +967,9 @@ isc_result_t omapi_protocol_listener_signal (omapi_object_t *o,
if (status != ISC_R_SUCCESS) if (status != ISC_R_SUCCESS)
return status; return status;
obj -> verify_auth = p -> verify_auth;
obj -> insecure = p -> insecure;
status = omapi_object_reference (&obj -> outer, c, MDL); status = omapi_object_reference (&obj -> outer, c, MDL);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
lose: lose:
@@ -754,6 +1101,70 @@ isc_result_t omapi_protocol_send_status (omapi_object_t *po,
return status; 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, isc_result_t omapi_protocol_send_update (omapi_object_t *po,
omapi_object_t *id, omapi_object_t *id,
unsigned rid, unsigned rid,

View File

@@ -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_waiter;
omapi_object_type_t *omapi_type_remote; omapi_object_type_t *omapi_type_remote;
omapi_object_type_t *omapi_type_message; omapi_object_type_t *omapi_type_message;
omapi_object_type_t *omapi_type_auth_key;
omapi_object_type_t *omapi_object_types; omapi_object_type_t *omapi_object_types;
int omapi_object_type_count; int omapi_object_type_count;
@@ -62,6 +63,8 @@ isc_result_t omapi_init (void)
{ {
isc_result_t status; isc_result_t status;
dst_init();
/* Register all the standard object types... */ /* Register all the standard object types... */
status = omapi_object_type_register (&omapi_type_connection, status = omapi_object_type_register (&omapi_type_connection,
"connection", "connection",
@@ -159,6 +162,19 @@ isc_result_t omapi_init (void)
if (status != ISC_R_SUCCESS) if (status != ISC_R_SUCCESS)
return status; 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. */ /* This seems silly, but leave it. */
return ISC_R_SUCCESS; return ISC_R_SUCCESS;
} }
@@ -630,12 +646,11 @@ isc_result_t omapi_make_int_value (omapi_value_t **vp,
return status; return status;
} }
status = omapi_typed_data_new (file, line, &(*vp) -> value, status = omapi_typed_data_new (file, line, &(*vp) -> value,
omapi_datatype_int); omapi_datatype_int, value);
if (status != ISC_R_SUCCESS) { if (status != ISC_R_SUCCESS) {
omapi_value_dereference (vp, file, line); omapi_value_dereference (vp, file, line);
return status; return status;
} }
(*vp) -> value -> u.integer = value;
return ISC_R_SUCCESS; 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); 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, isc_result_t omapi_make_handle_value (omapi_value_t **vp,
omapi_data_string_t *name, omapi_data_string_t *name,
omapi_object_t *value, omapi_object_t *value,

View File

@@ -26,7 +26,7 @@ MAN = dhcrelay.8
DEBUG = -g DEBUG = -g
INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes 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) CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS)
all: $(PROG) $(CATMANPAGES) all: $(PROG) $(CATMANPAGES)

View File

@@ -43,7 +43,7 @@
#ifndef lint #ifndef lint
static char ocopyright[] = 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 #endif
static char copyright[] = 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; 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 main (argc, argv, envp)
int argc; int argc;
char **argv, **envp; char **argv, **envp;
@@ -164,6 +176,9 @@ int main (argc, argv, envp)
struct parse *parse; struct parse *parse;
int lose; int lose;
int omapi_port; int omapi_port;
omapi_object_t *auth;
struct tsig_key *key;
omapi_typed_data_t *td;
int no_dhcpd_conf = 0; int no_dhcpd_conf = 0;
int no_dhcpd_db = 0; int no_dhcpd_db = 0;
int no_dhcpd_pid = 0; int no_dhcpd_pid = 0;
@@ -413,6 +428,24 @@ int main (argc, argv, envp)
data_string_forget (&db, MDL); 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); oc = lookup_option (&server_universe, options, SV_LOCAL_PORT);
if (oc && if (oc &&
evaluate_option_cache (&db, (struct packet *)0, evaluate_option_cache (&db, (struct packet *)0,
@@ -510,6 +543,9 @@ int main (argc, argv, envp)
isc_result_totext (result)); isc_result_totext (result));
result = omapi_protocol_listen (listener, result = omapi_protocol_listen (listener,
(unsigned)omapi_port, 1); (unsigned)omapi_port, 1);
if (result == ISC_R_SUCCESS)
result = omapi_protocol_configure_security
(listener, verify_addr, verify_auth);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
log_fatal ("Can't start OMAPI protocol: %s", log_fatal ("Can't start OMAPI protocol: %s",
isc_result_totext (result)); isc_result_totext (result));

View File

@@ -43,7 +43,7 @@
#ifndef lint #ifndef lint
static char copyright[] = 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 */ #endif /* not lint */
#include "dhcpd.h" #include "dhcpd.h"
@@ -481,7 +481,7 @@ struct option server_options [256] = {
{ "limited-broadcast-address", "I", &server_universe, 33 }, { "limited-broadcast-address", "I", &server_universe, 33 },
{ "remote-port", "S", &server_universe, 34 }, { "remote-port", "S", &server_universe, 34 },
{ "local-address", "I", &server_universe, 35 }, { "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-37", "X", &server_universe, 37 },
{ "option-38", "X", &server_universe, 38 }, { "option-38", "X", &server_universe, 38 },
{ "option-39", "X", &server_universe, 39 }, { "option-39", "X", &server_universe, 39 },