diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2000-06-08 20:51:43 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2000-06-08 20:51:43 +0000 |
commit | d333d8779299c8e3437e10e3443af65bd0dfb12e (patch) | |
tree | b7c390f818095c2b7c3d43166ad0ff563011373c | |
parent | 2799b030503b124f2f1e1f19a122350ff407cbc8 (diff) |
Merge with EOM 1.38
author: angelos
No need for NODEBUG actually...
author: angelos
Use LOG_DBG() instead of log_debug()
author: angelos
NODEBUG compile option, so regress doesn't barf.
author: angelos
No point adding a handling attribute for the generic session.
author: angelos
log_debug() for the action attributes.
author: angelos
Different policy/Keynote sessions per Phase 1 SA.
author: angelos
Allow exchange of KeyNote credentials over IKE. Multiple credentials
may be passed in a single CERT payload. KeyNote is used if a
directory named as the local ID we use in an exchange exists in the
KeyNote directory (default: /etc/isakmpd/keynote/). Note that
asymmetric credentials are possible (use KeyNote in one direction and
X509 in the other); such authentication is envisioned to be the most
common: the clients will use KeyNote credentials to authenticate and
authorize with a server, whilst the server will just provide an X509
certificate proving its binding to the IP address or ID.
Totally asymmetric authentication (e.g., shared key in one direction,
RSA in the other) is not supported by the IKE protocol.
author: angelos
Correct pointer handling.
author: angelos
A few more certificate handling routines for KeyNote.
author: angelos
Some more support for KeyNote credential exchange (not yet done).
author: angelos
Add a couple more KeyNote functions in the sym entries.
author: ho
Some systems do not define IPPROTO_ETHERIP (yet).
-rw-r--r-- | sbin/isakmpd/policy.c | 425 |
1 files changed, 361 insertions, 64 deletions
diff --git a/sbin/isakmpd/policy.c b/sbin/isakmpd/policy.c index 47fc5b15036..a9f6def7c5c 100644 --- a/sbin/isakmpd/policy.c +++ b/sbin/isakmpd/policy.c @@ -1,5 +1,5 @@ -/* $OpenBSD: policy.c,v 1.12 2000/05/02 14:35:27 niklas Exp $ */ -/* $EOM: policy.c,v 1.26 2000/05/01 19:52:50 niklas Exp $ */ +/* $OpenBSD: policy.c,v 1.13 2000/06/08 20:51:42 niklas Exp $ */ +/* $EOM: policy.c,v 1.38 2000/06/08 04:36:26 angelos Exp $ */ /* * Copyright (c) 1999, 2000 Angelos D. Keromytis. All rights reserved. @@ -53,6 +53,12 @@ #include <arpa/inet.h> #include <errno.h> +#ifdef KAME +# include <openssl/ssl.h> +#else +# include <ssl/ssl.h> +#endif + #include "sysdep.h" #include "app.h" @@ -75,6 +81,7 @@ #include "ui.h" #include "util.h" #include "policy.h" +#include "x509.h" #if defined (HAVE_DLOPEN) && !defined (USE_KEYNOTE) && 0 @@ -94,6 +101,9 @@ char *(*lk_kn_encode_key) (struct keynote_deckey *, int, int, int); int (*lk_kn_init) (void); char **(*lk_kn_read_asserts) (char *, int, int *); int (*lk_kn_remove_authorizer) (int, char *); +int (*lk_kn_get_authorizer) (int, int, int *); +void (*lk_kn_free_key) (struct keynote_deckey *); +struct keynote_keylist *(*lk_kn_get_licensees) (int, int); #define SYMENTRY(x) { SYM, SYM (x), (void **)&lk_ ## x } static struct dynload_script libkeynote_script[] = { @@ -111,12 +121,18 @@ static struct dynload_script libkeynote_script[] = { SYMENTRY (kn_init), SYMENTRY (kn_read_asserts), SYMENTRY (kn_remove_authorizer), + SYMENTRY (kn_get_licensees), + SYMENTRY (kn_get_authorizer), { EOS } }; #endif int keynote_sessid = -1; - +char **keynote_policy_asserts = NULL; +int keynote_policy_asserts_num = 0; +char **x509_policy_asserts = NULL; +int x509_policy_asserts_num = 0; +int x509_policy_asserts_num_alloc = 0; struct exchange *policy_exchange = 0; struct sa *policy_sa = 0; struct sa *policy_isakmp_sa = 0; @@ -146,7 +162,7 @@ my_inet_ntop4 (const in_addr_t *src, char *dst, size_t size, int normalize) return dst; } -static char * +char * policy_callback (char *name) { struct proto *proto; @@ -769,9 +785,11 @@ policy_callback (char *name) remote_id_proto = "udp"; break; +#ifdef IPPROTO_ETHERIP case IPPROTO_ETHERIP: remote_id_proto = "etherip"; break; +#endif default: sprintf (remote_id_proto_num, "%2d", id[1]); @@ -945,9 +963,11 @@ policy_callback (char *name) remote_filter_proto = "udp"; break; +#ifdef IPPROTO_ETHERIP case IPPROTO_ETHERIP: remote_filter_proto = "etherip"; break; +#endif default: sprintf (remote_filter_proto_num, "%2d", id[1]); @@ -1123,9 +1143,11 @@ policy_callback (char *name) local_filter_proto = "udp"; break; +#ifdef IPPROTO_ETHERIP case IPPROTO_ETHERIP: local_filter_proto = "etherip"; break; +#endif default: sprintf (local_filter_proto_num, "%2d", id[1]); @@ -1157,56 +1179,55 @@ policy_callback (char *name) } } -#if 0 - printf ("esp_present == %s\n", esp_present); - printf ("ah_present == %s\n", ah_present); - printf ("comp_present == %s\n", comp_present); - printf ("ah_hash_alg == %s\n", ah_hash_alg); - printf ("esp_enc_alg == %s\n", esp_enc_alg); - printf ("comp_alg == %s\n", comp_alg); - printf ("ah_auth_alg == %s\n", ah_auth_alg); - printf ("esp_auth_alg == %s\n", esp_auth_alg); - printf ("ah_life_seconds == %s\n", ah_life_seconds); - printf ("ah_life_kbytes == %s\n", ah_life_kbytes); - printf ("esp_life_seconds == %s\n", esp_life_seconds); - printf ("esp_life_kbytes == %s\n", esp_life_kbytes); - printf ("comp_life_seconds == %s\n", comp_life_seconds); - printf ("comp_life_kbytes == %s\n", comp_life_kbytes); - printf ("ah_encapsulation == %s\n", ah_encapsulation); - printf ("esp_encapsulation == %s\n", esp_encapsulation); - printf ("comp_encapsulation == %s\n", comp_encapsulation); - printf ("comp_dict_size == %s\n", comp_dict_size); - printf ("comp_private_alg == %s\n", comp_private_alg); - printf ("ah_key_length == %s\n", ah_key_length); - printf ("ah_key_rounds == %s\n", ah_key_rounds); - printf ("esp_key_length == %s\n", esp_key_length); - printf ("esp_key_rounds == %s\n", esp_key_rounds); - printf ("ah_group_desc == %s\n", ah_group_desc); - printf ("esp_group_desc == %s\n", esp_group_desc); - printf ("comp_group_desc == %s\n", comp_group_desc); - printf ("remote_filter_type == %s\n", remote_filter_type); - printf ("remote_filter_addr_upper == %s\n", remote_filter_addr_upper); - printf ("remote_filter_addr_lower == %s\n", remote_filter_addr_lower); - printf ("remote_filter == %s\n", remote_filter); - printf ("remote_filter_port == %s\n", remote_filter_port); - printf ("remote_filter_proto == %s\n", remote_filter_proto); - printf ("local_filter_type == %s\n", local_filter_type); - printf ("local_filter_addr_upper == %s\n", local_filter_addr_upper); - printf ("local_filter_addr_lower == %s\n", local_filter_addr_lower); - printf ("local_filter == %s\n", local_filter); - printf ("local_filter_port == %s\n", local_filter_port); - printf ("local_filter_proto == %s\n", local_filter_proto); - printf ("remote_id_type == %s\n", remote_id_type); - printf ("remote_id_addr_upper == %s\n", remote_id_addr_upper); - printf ("remote_id_addr_lower == %s\n", remote_id_addr_lower); - printf ("remote_id == %s\n", remote_id); - printf ("remote_id_port == %s\n", remote_id_port); - printf ("remote_id_proto == %s\n", remote_id_proto); - printf ("remote_negotiation_address == %s\n", remote_ike_address); - printf ("local_negotiation_address == %s\n", local_ike_address); - printf ("pfs == %s\n", pfs); - printf ("initiator == %s\n", initiator); -#endif /* 0 */ + LOG_DBG ((LOG_SA, 80, "Policy context (action attributes):")); + LOG_DBG ((LOG_SA, 80, "esp_present == %s", esp_present)); + LOG_DBG ((LOG_SA, 80, "ah_present == %s", ah_present)); + LOG_DBG ((LOG_SA, 80, "comp_present == %s", comp_present)); + LOG_DBG ((LOG_SA, 80, "ah_hash_alg == %s", ah_hash_alg)); + LOG_DBG ((LOG_SA, 80, "esp_enc_alg == %s", esp_enc_alg)); + LOG_DBG ((LOG_SA, 80, "comp_alg == %s", comp_alg)); + LOG_DBG ((LOG_SA, 80, "ah_auth_alg == %s", ah_auth_alg)); + LOG_DBG ((LOG_SA, 80, "esp_auth_alg == %s", esp_auth_alg)); + LOG_DBG ((LOG_SA, 80, "ah_life_seconds == %s", ah_life_seconds)); + LOG_DBG ((LOG_SA, 80, "ah_life_kbytes == %s", ah_life_kbytes)); + LOG_DBG ((LOG_SA, 80, "esp_life_seconds == %s", esp_life_seconds)); + LOG_DBG ((LOG_SA, 80, "esp_life_kbytes == %s", esp_life_kbytes)); + LOG_DBG ((LOG_SA, 80, "comp_life_seconds == %s", comp_life_seconds)); + LOG_DBG ((LOG_SA, 80, "comp_life_kbytes == %s", comp_life_kbytes)); + LOG_DBG ((LOG_SA, 80, "ah_encapsulation == %s", ah_encapsulation)); + LOG_DBG ((LOG_SA, 80, "esp_encapsulation == %s", esp_encapsulation)); + LOG_DBG ((LOG_SA, 80, "comp_encapsulation == %s", comp_encapsulation)); + LOG_DBG ((LOG_SA, 80, "comp_dict_size == %s", comp_dict_size)); + LOG_DBG ((LOG_SA, 80, "comp_private_alg == %s", comp_private_alg)); + LOG_DBG ((LOG_SA, 80, "ah_key_length == %s", ah_key_length)); + LOG_DBG ((LOG_SA, 80, "ah_key_rounds == %s", ah_key_rounds)); + LOG_DBG ((LOG_SA, 80, "esp_key_length == %s", esp_key_length)); + LOG_DBG ((LOG_SA, 80, "esp_key_rounds == %s", esp_key_rounds)); + LOG_DBG ((LOG_SA, 80, "ah_group_desc == %s", ah_group_desc)); + LOG_DBG ((LOG_SA, 80, "esp_group_desc == %s", esp_group_desc)); + LOG_DBG ((LOG_SA, 80, "comp_group_desc == %s", comp_group_desc)); + LOG_DBG ((LOG_SA, 80, "remote_filter_type == %s", remote_filter_type)); + LOG_DBG ((LOG_SA, 80, "remote_filter_addr_upper == %s", remote_filter_addr_upper)); + LOG_DBG ((LOG_SA, 80, "remote_filter_addr_lower == %s", remote_filter_addr_lower)); + LOG_DBG ((LOG_SA, 80, "remote_filter == %s", remote_filter)); + LOG_DBG ((LOG_SA, 80, "remote_filter_port == %s", remote_filter_port)); + LOG_DBG ((LOG_SA, 80, "remote_filter_proto == %s", remote_filter_proto)); + LOG_DBG ((LOG_SA, 80, "local_filter_type == %s", local_filter_type)); + LOG_DBG ((LOG_SA, 80, "local_filter_addr_upper == %s", local_filter_addr_upper)); + LOG_DBG ((LOG_SA, 80, "local_filter_addr_lower == %s", local_filter_addr_lower)); + LOG_DBG ((LOG_SA, 80, "local_filter == %s", local_filter)); + LOG_DBG ((LOG_SA, 80, "local_filter_port == %s", local_filter_port)); + LOG_DBG ((LOG_SA, 80, "local_filter_proto == %s", local_filter_proto)); + LOG_DBG ((LOG_SA, 80, "remote_id_type == %s", remote_id_type)); + LOG_DBG ((LOG_SA, 80, "remote_id_addr_upper == %s", remote_id_addr_upper)); + LOG_DBG ((LOG_SA, 80, "remote_id_addr_lower == %s", remote_id_addr_lower)); + LOG_DBG ((LOG_SA, 80, "remote_id == %s", remote_id)); + LOG_DBG ((LOG_SA, 80, "remote_id_port == %s", remote_id_port)); + LOG_DBG ((LOG_SA, 80, "remote_id_proto == %s", remote_id_proto)); + LOG_DBG ((LOG_SA, 80, "remote_negotiation_address == %s", remote_ike_address)); + LOG_DBG ((LOG_SA, 80, "local_negotiation_address == %s", local_ike_address)); + LOG_DBG ((LOG_SA, 80, "pfs == %s", pfs)); + LOG_DBG ((LOG_SA, 80, "initiator == %s", initiator)); /* Unset dirty now. */ dirty = 0; @@ -1454,18 +1475,294 @@ policy_init (void) log_print ("policy_init: " "kn_add_assertion (%d, %p, %d, ASSERT_FLAG_LOCAL) failed", keynote_sessid, asserts[fd], strlen (asserts[fd])); + } + + /* Cleanup */ + if (keynote_policy_asserts) + { + for (fd = 0; fd < keynote_policy_asserts_num; fd++) + if (keynote_policy_asserts && keynote_policy_asserts[fd]) + free (keynote_policy_asserts[fd]); + + free (keynote_policy_asserts); + } + + keynote_policy_asserts = asserts; + keynote_policy_asserts_num = i; +} + +/* Nothing needed for initialization */ +int +keynote_cert_init (void) +{ + return 1; +} + +/* Just copy and return */ +void * +keynote_cert_get (u_int8_t *data, u_int32_t len) +{ + char *foo = calloc (len + 1, sizeof(char)); + + if (foo == NULL) + return NULL; + + memcpy (foo, data, len); + return foo; +} + +/* + * We just verify the signature on the certificates. + * XXX Is this the right thing to do -- verify the signature on all + * XXX credentials ? + */ +int +keynote_cert_validate (void *scert) +{ + char **foo; + int num, i; + + if (scert == NULL) + return 0; + + foo = LK (kn_read_asserts, ((char *) scert, strlen ((char *) scert), + &num)); + if (foo == NULL) + return 0; + + for (i = 0; i < num; i++) + { + if (LK (kn_verify_assertion, (scert, strlen ((char *) scert))) != + SIGRESULT_TRUE) + { + for (; i < num; i++) + free (foo[i]); + free (foo); + return 0; + } + + free (foo[i]); + } + + free (foo); + return 1; +} + +/* Add received credentials */ +int +keynote_cert_insert (int sid, void *scert) +{ + char **foo; + int num; + + if (scert == NULL) + return 0; + + foo = LK (kn_read_asserts, ((char *) scert, strlen ((char *) scert), + &num)); + if (foo == NULL) + return 0; + + while (num--) + LK (kn_add_assertion, (sid, foo[num], strlen (foo[num]), 0)); + + return 1; +} + +/* Just regular memory free */ +void +keynote_cert_free (void *cert) +{ + free (cert); +} + +/* Verify that the key given to us is valid */ +int +keynote_certreq_validate (u_int8_t *data, u_int32_t len) +{ + struct keynote_deckey dc; + int err = 1; + char *dat; + + dat = calloc (len + 1, sizeof(char)); + if (dat == NULL) + return 0; + + memcpy (dat, data, len); + + if (LK (kn_decode_key, (&dc, dat, KEYNOTE_PUBLIC_KEY)) != 0) + err = 0; + else + LK (kn_free_key, (&dc)); + + free (dat); + + return err; +} + +/* Beats me what we should be doing with this */ +void * +keynote_certreq_decode (u_int8_t *data, u_int32_t len) +{ + /* XXX */ + return NULL; +} - free (asserts[fd]); +void +keynote_free_aca (void *blob) +{ + /* XXX */ +} + +int +keynote_cert_obtain (u_int8_t *id, size_t id_len, void *data, u_int8_t **cert, + u_int32_t *certlen) +{ + char *dirname, *file; + struct stat sb; + int idtype, fd, len; + + if (!id) + { + log_print ("keynote_cert_obtain: ID is missing"); + return 0; + } + + /* Get type of ID */ + idtype = id[0]; + id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; + + dirname = conf_get_str ("KeyNote", "Credential-directory"); + if (!dirname) + { + log_print ("keynote_cert_obtain: no Credential-directory"); + return 0; + } + + len = strlen (dirname) + strlen (CREDENTIAL_FILE) + 3; + + switch (idtype) + { + case IPSEC_ID_IPV4_ADDR: + { + struct in_addr in; + + file = calloc (len + 15, sizeof(char)); + if (file == NULL) + { + log_print ("keynote_cert_obtain: failed to allocate %d bytes", + len + 15); + return 0; + } + + memcpy (&in, id, sizeof(in)); + sprintf (file, "%s/%s/%s", dirname, inet_ntoa (in), CREDENTIAL_FILE); + break; + } + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + { + file = calloc (len + id_len, sizeof(char)); + if (file == NULL) + { + log_print ("keynote_cert_obtain: failed to allocate %d bytes", + len + id_len); + return 0; + } + + sprintf (file, "%s/", dirname); + memcpy (file + strlen (file), id, id_len); + sprintf (file + strlen (dirname) + 1 + id_len, "/%s", CREDENTIAL_FILE); + break; + } + + default: + return 0; + } + + if (stat (file, &sb) < 0) + { + log_print ("keynote_cert_obtain: failed to stat \"%s\"", file); + free (file); + return 0; + } + + *cert = calloc (sb.st_size, sizeof(char)); + if (*cert == NULL) + { + log_print ("keynote_cert_obtain: failed to allocate %d bytes", + sb.st_size); + free (file); + return 0; + } + + fd = open (file, O_RDONLY, 0); + if (fd < 0) + { + log_print ("keynote_cert_obtain: failed to open \"%s\"", file); + free (file); + return 0; } - if (asserts) - free (asserts); + if (read (fd, *cert, sb.st_size) != sb.st_size) + { + log_print ("keynote_cert_obtain: failed to read %d bytes from \"%s\"", + sb.st_size, file); + free (file); + close (fd); + return 0; + } + + close (fd); + free (file); + *certlen = sb.st_size; + return 1; +} + +/* This should never be called */ +int +keynote_cert_get_subject (void *scert, u_int8_t **id, u_int32_t *id_len) +{ + return 0; +} + +/* Get the Authorizer key */ +int +keynote_cert_get_key (void *scert, void *keyp) +{ + struct keynote_keylist *kl; + int sid, num; + char **foo; + + foo = LK (kn_read_asserts, ((char *) scert, strlen ((char *) scert), &num)); + if ((foo == NULL) || (num == 0)) + return 0; + + sid = LK (kn_add_assertion, (keynote_sessid, foo[num - 1], + strlen (scert), 0)); + while (num--) + free (foo[num]); + free (foo); + + if (sid == -1) + return 0; + + *(RSA **)keyp = NULL; + + kl = LK (kn_get_licensees, (keynote_sessid, sid)); + while (kl) + { + if (kl->key_alg == KEYNOTE_ALGORITHM_RSA) + { + *(RSA **)keyp = LC (RSAPublicKey_dup, (kl->key_key)); + break; + } + + kl = kl->key_next; + } - /* Add the callback that will handle attributes. */ - if (LK (kn_add_action, (keynote_sessid, ".*", (char *) policy_callback, - ENVIRONMENT_FLAG_FUNC | ENVIRONMENT_FLAG_REGEX)) - == -1) - log_fatal ("policy_init: " - "kn_add_action (%d, \".*\", %p, FUNC | REGEX) failed", - keynote_sessid, policy_callback); + LK (kn_remove_assertion, (keynote_sessid, sid)); + return *(RSA **)keyp == NULL ? 0 : 1; } |