diff options
author | Damien Neil <source@isc.org> | 2000-08-03 21:00:41 +0000 |
---|---|---|
committer | Damien Neil <source@isc.org> | 2000-08-03 21:00:41 +0000 |
commit | 49146f3c1512a5a18445237ad3edfb91b6434545 (patch) | |
tree | 54c43f2be43c9bfafd0be51c1a4e246e40bd148e /omapip/protocol.c | |
parent | c62871ba64e76992da8518f4d1ff717d9cdf67e4 (diff) | |
download | isc-dhcp-49146f3c1512a5a18445237ad3edfb91b6434545.tar.gz |
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.
Diffstat (limited to 'omapip/protocol.c')
-rw-r--r-- | omapip/protocol.c | 447 |
1 files changed, 429 insertions, 18 deletions
diff --git a/omapip/protocol.c b/omapip/protocol.c index b254e2a0..7eaeab89 100644 --- a/omapip/protocol.c +++ b/omapip/protocol.c @@ -51,7 +51,7 @@ OMAPI_OBJECT_ALLOC (omapi_protocol_listener, omapi_protocol_listener_object_t, isc_result_t omapi_protocol_connect (omapi_object_t *h, const char *server_name, unsigned port, - omapi_object_t *authinfo) + omapi_object_t *a) { isc_result_t status; omapi_protocol_object_t *obj; @@ -78,8 +78,30 @@ isc_result_t omapi_protocol_connect (omapi_object_t *h, return status; } - if (authinfo) - omapi_object_reference (&obj -> authinfo, authinfo, MDL); + /* If we were passed a default authenticator, store it now. We'll + open it once we're connected. */ + if (a) { + obj -> default_auth = + dmalloc (sizeof(omapi_remote_auth_t), MDL); + if (!obj -> default_auth) { + omapi_protocol_dereference (&obj, MDL); + return ISC_R_NOMEMORY; + } + + obj -> default_auth -> next = (omapi_remote_auth_t *)0; + status = omapi_object_reference (&obj -> default_auth -> a, + a, MDL); + if (status != ISC_R_SUCCESS) { + dfree (obj -> default_auth, MDL); + omapi_protocol_dereference (&obj, MDL); + return status; + } + + obj -> insecure = 0; + } else { + obj -> insecure = 1; + } + omapi_protocol_dereference (&obj, MDL); return ISC_R_SUCCESS; } @@ -128,8 +150,11 @@ isc_result_t omapi_protocol_send_message (omapi_object_t *po, omapi_protocol_object_t *p; omapi_object_t *c; omapi_message_object_t *m, *om; + omapi_remote_auth_t *ra; + omapi_value_t *signature; isc_result_t status; u_int32_t foo; + unsigned auth_len; if (po -> type != omapi_type_protocol || !po -> outer || po -> outer -> type != omapi_type_connection || @@ -142,12 +167,57 @@ isc_result_t omapi_protocol_send_message (omapi_object_t *po, m = (omapi_message_object_t *)mo; om = (omapi_message_object_t *)omo; - /* XXX Write the authenticator length */ - status = omapi_connection_put_uint32 (c, 0); - if (status != ISC_R_SUCCESS) + /* Find the authid to use for this message. */ + if (id) { + for (ra = p -> remote_auth_list; ra; ra = ra -> next) { + if (ra -> a == id) { + break; + } + } + + if (!ra) + return ISC_R_KEY_UNKNOWN; + } else if (p -> remote_auth_list) { + ra = p -> default_auth; + } else { + ra = (omapi_remote_auth_t *)0; + } + + if (ra) { + m -> authid = ra -> remote_handle; + status = omapi_object_reference (&m -> id_object, + ra -> a, MDL); + if (status != ISC_R_SUCCESS) + return status; + } + + /* Write the ID of the authentication key we're using. */ + status = omapi_connection_put_uint32 (c, ra ? ra -> remote_handle : 0); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); return status; - /* XXX Write the ID of the authentication key we're using. */ - status = omapi_connection_put_uint32 (c, 0); + } + + /* Activate the authentication key on the connection. */ + auth_len = 0; + if (ra) { + status = omapi_set_object_value (c, (omapi_object_t *)0, + "output-authenticator", + ra -> a); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + + status = omapi_connection_output_auth_length (c, &auth_len); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + } + + /* Write the authenticator length */ + status = omapi_connection_put_uint32 (c, auth_len); if (status != ISC_R_SUCCESS) { omapi_disconnect (c, 1); return status; @@ -223,7 +293,35 @@ isc_result_t omapi_protocol_send_message (omapi_object_t *po, return status; } - /* XXX Write the authenticator... */ + if (ra) { + /* Calculate the message signature. */ + signature = (omapi_value_t *)0; + status = omapi_get_value_str (c, (omapi_object_t *)0, + "output-signature", &signature); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + + /* Write the authenticator... */ + status = (omapi_connection_copyin + (c, signature -> value -> u.buffer.value, + signature -> value -> u.buffer.len)); + omapi_value_dereference (&signature, MDL); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + + /* Dectivate the authentication key on the connection. */ + status = omapi_set_value_str (c, (omapi_object_t *)0, + "output-authenticator", + (omapi_typed_data_t *)0); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + } return ISC_R_SUCCESS; } @@ -235,6 +333,7 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, isc_result_t status; omapi_protocol_object_t *p; omapi_object_t *c; + omapi_value_t *signature; u_int16_t nlen; u_int32_t vlen; u_int32_t th; @@ -257,6 +356,19 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, return ISC_R_SUCCESS; } + /* Should only receive these when opening the initial authenticator. */ + if (!strcmp (name, "status")) { + status = va_arg (ap, isc_result_t); + if (status != ISC_R_SUCCESS) { + omapi_signal_in (h -> inner, "status", status, + (omapi_object_t *)0); + omapi_disconnect (p -> outer, 1); + return status; + } else { + return omapi_signal_in (h -> inner, "ready"); + } + } + /* Not a signal we recognize? */ if (strcmp (name, "ready")) { if (p -> inner && p -> inner -> type -> signal_handler) @@ -291,7 +403,18 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, return ISC_R_PROTOCOLERROR; } - status = omapi_signal_in (h -> inner, "ready"); + if (p -> default_auth) { + status = omapi_protocol_send_open + (h, (omapi_object_t *)0, "authenticator", + p -> default_auth -> a, + OMAPI_NOTIFY_PROTOCOL); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + } else { + status = omapi_signal_in (h -> inner, "ready"); + } to_header_wait: /* The next thing we're expecting is a message header. */ @@ -313,10 +436,29 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, return status; } + p -> verify_result = ISC_R_SUCCESS; + /* Swap in the header... */ omapi_connection_get_uint32 (c, &p -> message -> authid); - /* XXX bind the authenticator here! */ + /* Bind the authenticator to the message object. */ + if (p -> message -> authid) { + status = (omapi_protocol_lookup_auth + (&p -> message -> id_object, h, + p -> message -> authid)); + if (status != ISC_R_SUCCESS) + p -> verify_result = status; + + /* Activate the authentication key. */ + status = omapi_set_object_value + (c, (omapi_object_t *)0, "input-authenticator", + p -> message -> id_object); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + } + omapi_connection_get_uint32 (c, &p -> message -> authlen); omapi_connection_get_uint32 (c, &p -> message -> op); omapi_connection_get_uint32 (c, &th); @@ -462,31 +604,71 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, signature_wait: case omapi_protocol_signature_wait: + if (p -> message -> id_object) { + /* Compute the signature of the message. */ + signature = (omapi_value_t *)0; + status = omapi_get_value_str (c, (omapi_object_t *)0, + "input-signature", + &signature); + if (status != ISC_R_SUCCESS) { + omapi_disconnect (c, 1); + return status; + } + + /* Disable the authentication key on the connection. */ + status = omapi_set_value_str (c, (omapi_object_t *)0, + "input-authenticator", + (omapi_typed_data_t *)0); + if (status != ISC_R_SUCCESS) { + omapi_value_dereference (&signature, MDL); + omapi_disconnect (c, 1); + return status; + } + } + + /* Read the authenticator. */ status = omapi_typed_data_new (MDL, &p -> message -> authenticator, omapi_datatype_data, p -> message -> authlen); if (status != ISC_R_SUCCESS) { + omapi_value_dereference (&signature, MDL); omapi_disconnect (c, 1); return ISC_R_NOMEMORY; } omapi_connection_copyout (p -> message -> authenticator -> u.buffer.value, c, p -> message -> authlen); - /* XXX now do something to verify the signature. */ + + /* Verify the signature. */ + if (p -> message -> id_object && + ((signature -> value -> u.buffer.len != + p -> message -> authlen) || + (memcmp (signature -> value -> u.buffer.value, + p -> message -> authenticator -> u.buffer.value, + p -> message -> authlen) != 0))) { + /* Invalid signature. */ + p -> verify_result = ISC_R_INVALIDKEY; + } + + omapi_value_dereference (&signature, MDL); /* Process the message. */ message_done: - status = omapi_message_process ((omapi_object_t *)p -> message, - h); + if (p -> verify_result != ISC_R_SUCCESS) { + status = omapi_protocol_send_status + (h, (omapi_object_t *)0, p -> verify_result, + p -> message -> id, (char *)0); + } else { + status = omapi_message_process + ((omapi_object_t *)p -> message, h); + } if (status != ISC_R_SUCCESS) { omapi_disconnect (c, 1); return ISC_R_NOMEMORY; } - /* XXX unbind the authenticator. */ - auth_unbind: omapi_message_dereference (&p -> message, MDL); /* Now wait for the next message. */ @@ -499,13 +681,110 @@ isc_result_t omapi_protocol_signal_handler (omapi_object_t *h, return ISC_R_SUCCESS; } +isc_result_t omapi_protocol_add_auth (omapi_object_t *po, + omapi_object_t *ao, + omapi_handle_t handle) +{ + omapi_protocol_object_t *p; + omapi_remote_auth_t *r; + isc_result_t status; + + if (ao -> type != omapi_type_auth_key && + (!ao -> inner || ao -> inner -> type != omapi_type_auth_key)) + return ISC_R_INVALIDARG; + + if (po -> type != omapi_type_protocol) + return ISC_R_INVALIDARG; + p = (omapi_protocol_object_t *)po; + + if (p -> verify_auth) { + status = (p -> verify_auth) (po, (omapi_auth_key_t *)ao); + if (status != ISC_R_SUCCESS) + return status; + } + + /* If omapi_protocol_connect() was called with a default + authenticator, p -> default_auth will already be set, + but p -> remote_auth_list will not yet be initialized. */ + if (p -> default_auth && !p -> remote_auth_list) { + if (p -> default_auth -> a != ao) { + /* Something just went horribly wrong. */ + omapi_disconnect (p -> outer, 1); + return ISC_R_UNEXPECTED; + } + + p -> remote_auth_list = p -> default_auth; + p -> default_auth -> remote_handle = handle; + + return omapi_signal_in (p -> inner, "ready"); + } + + r = dmalloc (sizeof(*r), MDL); + if (!r) + return ISC_R_NOMEMORY; + + status = omapi_object_reference (&r -> a, ao, MDL); + if (status != ISC_R_SUCCESS) { + dfree (r, MDL); + return status; + } + + r -> remote_handle = handle; + r -> next = p -> remote_auth_list; + p -> remote_auth_list = r; + + return ISC_R_SUCCESS; +} + +isc_result_t omapi_protocol_lookup_auth (omapi_object_t **a, + omapi_object_t *po, + omapi_handle_t handle) +{ + omapi_protocol_object_t *p; + omapi_remote_auth_t *r; + + if (po -> type != omapi_type_protocol) + return ISC_R_INVALIDARG; + p = (omapi_protocol_object_t *)po; + + for (r = p -> remote_auth_list; r; r = r -> next) + if (r -> remote_handle == handle) + return omapi_object_reference (a, r -> a, MDL); + + return ISC_R_NOTFOUND; +} + isc_result_t omapi_protocol_set_value (omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value) { + omapi_protocol_object_t *p; + omapi_remote_auth_t *r; + if (h -> type != omapi_type_protocol) return ISC_R_INVALIDARG; + p = (omapi_protocol_object_t *)h; + + if (omapi_ds_strcmp (name, "default-authenticator") == 0) { + if (value -> type != omapi_datatype_object) + return ISC_R_INVALIDARG; + + if (!value || !value -> u.object) { + p -> default_auth = (omapi_remote_auth_t *)0; + } else { + for (r = p -> remote_auth_list; r; r = r -> next) + if (r -> a == value -> u.object) + break; + + if (!r) + return ISC_R_KEY_UNKNOWN; + + p -> default_auth = r; + } + + return ISC_R_SUCCESS; + } if (h -> inner && h -> inner -> type -> set_value) return (*(h -> inner -> type -> set_value)) @@ -518,8 +797,19 @@ isc_result_t omapi_protocol_get_value (omapi_object_t *h, omapi_data_string_t *name, omapi_value_t **value) { + omapi_protocol_object_t *p; + if (h -> type != omapi_type_protocol) return ISC_R_INVALIDARG; + p = (omapi_protocol_object_t *)h; + + if (omapi_ds_strcmp (name, "default-authenticator") == 0) { + if (!p -> default_auth) + return ISC_R_NOTFOUND; + + return omapi_make_object_value (value, name, + p -> default_auth -> a, MDL); + } if (h -> inner && h -> inner -> type -> get_value) return (*(h -> inner -> type -> get_value)) @@ -536,8 +826,19 @@ isc_result_t omapi_protocol_destroy (omapi_object_t *h, p = (omapi_protocol_object_t *)h; if (p -> message) omapi_message_dereference (&p -> message, file, line); - if (p -> authinfo) - return omapi_object_dereference (&p -> authinfo, file, line); + + /* This will happen if: 1) A default authenticator is supplied to + omapi_protocol_connect(), and 2) something goes wrong before + the authenticator can be opened. */ + if (p -> default_auth && !p -> remote_auth_list) + dfree (p -> default_auth, file, line); + + while (p -> remote_auth_list) { + omapi_remote_auth_t *r = p -> remote_auth_list -> next; + omapi_object_dereference (&r -> a, file, line); + dfree (r, file, line); + p -> remote_auth_list = r; + } return ISC_R_SUCCESS; } @@ -559,6 +860,46 @@ isc_result_t omapi_protocol_stuff_values (omapi_object_t *c, return ISC_R_SUCCESS; } +/* Returns a boolean indicating whether this protocol requires that + messages be authenticated or not. */ + +isc_boolean_t omapi_protocol_authenticated (omapi_object_t *h) +{ + if (h -> type != omapi_type_protocol) + return isc_boolean_false; + if (((omapi_protocol_object_t *)h) -> insecure) + return isc_boolean_false; + else + return isc_boolean_true; +} + +/* Sets the address and authenticator verification callbacks. The handle + is to a listener object, not a protocol object. */ + +isc_result_t omapi_protocol_configure_security (omapi_object_t *h, + isc_result_t (*verify_addr) + (omapi_object_t *, + omapi_addr_t *), + isc_result_t (*verify_auth) + (omapi_object_t *, + omapi_auth_key_t *)) +{ + omapi_protocol_listener_object_t *l; + + if (h -> outer && h -> outer -> type == omapi_type_protocol_listener) + h = h -> outer; + + if (h -> type != omapi_type_protocol_listener) + return ISC_R_INVALIDARG; + l = (omapi_protocol_listener_object_t *)h; + + l -> verify_auth = verify_auth; + l -> insecure = 0; + + return omapi_listener_configure_security (h -> outer, verify_addr); +} + + /* Set up a listener for the omapi protocol. The handle stored points to a listener object, not a protocol object. */ @@ -586,6 +927,9 @@ isc_result_t omapi_protocol_listen (omapi_object_t *h, return status; } + /* What a terrible default. */ + obj -> insecure = 1; + status = omapi_listen ((omapi_object_t *)obj, port, max); omapi_protocol_listener_dereference (&obj, MDL); return status; @@ -623,6 +967,9 @@ isc_result_t omapi_protocol_listener_signal (omapi_object_t *o, if (status != ISC_R_SUCCESS) return status; + obj -> verify_auth = p -> verify_auth; + obj -> insecure = p -> insecure; + status = omapi_object_reference (&obj -> outer, c, MDL); if (status != ISC_R_SUCCESS) { lose: @@ -754,6 +1101,70 @@ isc_result_t omapi_protocol_send_status (omapi_object_t *po, return status; } +/* The OMAPI_NOTIFY_PROTOCOL flag will cause the notify-object for the + message to be set to the protocol object. This is used when opening + the default authenticator. */ + +isc_result_t omapi_protocol_send_open (omapi_object_t *po, + omapi_object_t *id, + const char *type, + omapi_object_t *object, + unsigned flags) +{ + isc_result_t status; + omapi_message_object_t *message = (omapi_message_object_t *)0; + omapi_object_t *mo; + + if (po -> type != omapi_type_protocol) + return ISC_R_INVALIDARG; + + status = omapi_message_new ((omapi_object_t **)&message, MDL); + mo = (omapi_object_t *)message; + + if (status == ISC_R_SUCCESS) + status = omapi_set_int_value (mo, (omapi_object_t *)0, + "op", OMAPI_OP_OPEN); + + if (status == ISC_R_SUCCESS) + status = omapi_set_object_value (mo, (omapi_object_t *)0, + "object", object); + + if ((flags & OMAPI_CREATE) && (status == ISC_R_SUCCESS)) + status = omapi_set_boolean_value (mo, (omapi_object_t *)0, + "create", 1); + + if ((flags & OMAPI_UPDATE) && (status == ISC_R_SUCCESS)) + status = omapi_set_boolean_value (mo, (omapi_object_t *)0, + "update", 1); + + if ((flags & OMAPI_EXCL) && (status == ISC_R_SUCCESS)) + status = omapi_set_boolean_value (mo, (omapi_object_t *)0, + "exclusive", 1); + + if ((flags & OMAPI_NOTIFY_PROTOCOL) && (status == ISC_R_SUCCESS)) + status = omapi_set_object_value (mo, (omapi_object_t *)0, + "notify-object", po); + + if (type && (status == ISC_R_SUCCESS)) + status = omapi_set_string_value (mo, (omapi_object_t *)0, + "type", type); + + if (status == ISC_R_SUCCESS) + status = omapi_message_register (mo); + + if (status == ISC_R_SUCCESS) { + status = omapi_protocol_send_message (po, id, mo, + (omapi_object_t *)0); + if (status != ISC_R_SUCCESS) + omapi_message_unregister (mo); + } + + if (message) + omapi_message_dereference (&message, MDL); + + return status; +} + isc_result_t omapi_protocol_send_update (omapi_object_t *po, omapi_object_t *id, unsigned rid, |