diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2001-05-31 20:29:50 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 2001-05-31 20:29:50 +0000 |
commit | 9ded00ef20a5ea6949311d164ddf98821ac9eacc (patch) | |
tree | 4655801cf787096ee114a0b42cd41ee4aab647bb /sbin/isakmpd | |
parent | c30a916d131d4548d484f0f2238af0dde3b769bf (diff) |
When trying to find the right certificate/key to use, first check in
the conf space, as we may have been passed that information from the
kernel.
Likewise, store the peer's key and cert so we can send it back to the
kernel when we establish the SA.
Diffstat (limited to 'sbin/isakmpd')
-rw-r--r-- | sbin/isakmpd/ike_auth.c | 227 |
1 files changed, 147 insertions, 80 deletions
diff --git a/sbin/isakmpd/ike_auth.c b/sbin/isakmpd/ike_auth.c index 03db1a74d43..4ec821e0a07 100644 --- a/sbin/isakmpd/ike_auth.c +++ b/sbin/isakmpd/ike_auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ike_auth.c,v 1.40 2001/05/24 03:15:37 angelos Exp $ */ +/* $OpenBSD: ike_auth.c,v 1.41 2001/05/31 20:29:49 angelos Exp $ */ /* $EOM: ike_auth.c,v 1.59 2000/11/21 00:21:31 angelos Exp $ */ /* @@ -71,6 +71,7 @@ #include "prf.h" #include "transport.h" #include "util.h" +#include "key.h" #ifdef notyet static u_int8_t *enc_gen_skeyid (struct exchange *, size_t *); @@ -304,14 +305,13 @@ ike_auth_get_key (int type, char *id, char *local_id, size_t *keylen) #else rsakey = LC (PEM_read_bio_RSAPrivateKey, (keyh, NULL, NULL)); #endif + LC (BIO_free, (keyh)); if (!rsakey) { log_print ("ike_auth_get_key: PEM_read_bio_RSAPrivateKey failed"); - LC (BIO_free, (keyh)); return 0; } - LC (BIO_free, (keyh)); return rsakey; #endif #endif @@ -378,7 +378,10 @@ pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz) } } - /* Get the pre-shared key for our peer. */ + /* + * Get the pre-shared key for our peer. This will work even if the key + * has been passed to us through a mechanism like PFKEYv2. + */ key = ike_auth_get_key (IKE_AUTH_PRE_SHARED, exchange->name, buf, &keylen); if (buf) free (buf); @@ -388,16 +391,16 @@ pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz) return 0; /* Store the secret key for later policy processing. */ - exchange->recv_cert = malloc (keylen); - if (!exchange->recv_cert) + exchange->recv_key = malloc (keylen); + exchange->recv_keytype = ISAKMP_KEY_PASSPHRASE; + if (!exchange->recv_key) { log_error ("pre_shared_gen_skeyid: malloc (%d) failed", keylen); return 0; } - memcpy (exchange->recv_cert, key, keylen); - exchange->recv_certlen = keylen; + memcpy (exchange->recv_key, key, keylen); exchange->recv_certtype = ISAKMP_CERTENC_NONE; - + prf = prf_alloc (ie->prf_type, ie->hash->type, key, keylen); if (!prf) return 0; @@ -741,9 +744,10 @@ rsa_sig_decode_hash (struct message *msg) return -1; } - exchange->recv_key = calloc (strlen (pp) + strlen ("rsa-hex:") + 1, - sizeof (char)); - if (exchange->recv_key == NULL) + exchange->keynote_key = calloc (strlen (pp) + + strlen ("rsa-hex:") + 1, + sizeof (char)); + if (exchange->keynote_key == NULL) { free (pp); LK (kn_free_key, (&dc)); @@ -752,7 +756,7 @@ rsa_sig_decode_hash (struct message *msg) return -1; } - sprintf (exchange->recv_key, "rsa-hex:%s", pp); + sprintf (exchange->keynote_key, "rsa-hex:%s", pp); free (pp); } #endif @@ -779,22 +783,6 @@ rsa_sig_decode_hash (struct message *msg) } #endif /* USE_DNSSEC */ - /* If we still have not found a key, try the config file. */ - if (!found) - { -#ifdef notyet - rawkey = ike_auth_get_key (IKE_AUTH_RSA_SIG, exchange->name, &keylen); - if (!rawkey) - { - log_print ("rsa_sig_decode_hash: no public key found"); - return -1; - } -#else - log_print ("rsa_sig_decode_hash: no public key found"); - return -1; -#endif - } - p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SIG]); if (!p) { @@ -830,8 +818,10 @@ rsa_sig_decode_hash (struct message *msg) return -1; } - LC (RSA_free, (key)); - + /* Store key for later use */ + exchange->recv_key = key; + exchange->recv_keytype = ISAKMP_KEY_RSA; + if (len != hashsize) { free (*hash_p); @@ -881,7 +871,6 @@ rsa_sig_encode_hash (struct message *msg) struct ipsec_exch *ie = exchange->data; size_t hashsize = ie->hash->hashsize; struct cert_handler *handler; - RSA *key; char header[80]; int initiator = exchange->initiator; u_int8_t *buf, *data, *buf2; @@ -894,56 +883,109 @@ rsa_sig_encode_hash (struct message *msg) id = initiator ? exchange->id_i : exchange->id_r; id_len = initiator ? exchange->id_i_len : exchange->id_r_len; - /* XXX This needs to be configureable. */ - idtype = ISAKMP_CERTENC_KEYNOTE; - - doitagain: - handler = cert_get (idtype); - if (!handler) + /* We may have been provided these by the kernel */ + if ((buf = conf_get_str (exchange->name, "Credentials")) != NULL && + (idtype = conf_get_num (exchange->name, "Credential_Type", -1) != -1)) { - if (idtype == ISAKMP_CERTENC_KEYNOTE) - { - idtype = ISAKMP_CERTENC_X509_SIG; - goto doitagain; - } + exchange->sent_certtype = idtype; + handler = cert_get (idtype); + if (!handler) + { + log_error ("rsa_sig_encode_hash: cert_get (%d) failed", idtype); + return -1; + } - log_print ("rsa_sig_encode_hash: " - "cert_get(%d) failed", idtype); - return -1; - } + exchange->sent_cert = handler->cert_from_printable (buf); + if (exchange->sent_cert == NULL) + { + log_error ("rsa_sig_encode_hash: failed to retrieve certificate"); + return -1; + } - /* Find a certificate with subjectAltName = id. */ - if (handler->cert_obtain (id, id_len, 0, &data, &datalen)) - { - buf = realloc (data, ISAKMP_CERT_SZ + datalen); - if (!buf) + handler->cert_serialize (exchange->sent_cert, &data, &datalen); + if (data == NULL) { - log_error ("rsa_sig_encode_hash: realloc (%p, %d) failed", data, - ISAKMP_CERT_SZ + datalen); - free (data); + log_error ("rsa_sig_encode_hash: cert serialization failed"); return -1; } - memmove (buf + ISAKMP_CERT_SZ, buf, datalen); - SET_ISAKMP_CERT_ENCODING (buf, idtype); - if (message_add_payload (msg, ISAKMP_PAYLOAD_CERT, buf, - ISAKMP_CERT_SZ + datalen, 1)) + + goto aftercert; /* Skip all the certificate discovery */ + } + + /* XXX This needs to be configurable. */ + idtype = ISAKMP_CERTENC_KEYNOTE; + + /* Find a certificate with subjectAltName = id. */ + handler = cert_get (idtype); + if (!handler) + { + idtype = ISAKMP_CERTENC_X509_SIG; + handler = cert_get (idtype); + if (!handler) { - free (buf); + log_print ("rsa_sig_encode_hash: cert_get(%d) failed", idtype); return -1; } } - else + + if (handler->cert_obtain (id, id_len, 0, &data, &datalen) == 0) { - if (handler->id == ISAKMP_CERTENC_KEYNOTE) - { + if (idtype == ISAKMP_CERTENC_KEYNOTE) + { idtype = ISAKMP_CERTENC_X509_SIG; - goto doitagain; + handler = cert_get (idtype); + if (!handler) + { + log_print ("rsa_sig_encode_hash: cert_get(%d) failed", idtype); + return -1; + } + + if (handler->cert_obtain (id, id_len, 0, &data, &datalen) == 0) + { + LOG_DBG ((LOG_MISC, 10, + "rsa_sig_encode_hash: no certificate to send")); + goto skipcert; + } } else - LOG_DBG ((LOG_MISC, 10, - "rsa_sig_encode_hash: no certificate to send")); + { + LOG_DBG ((LOG_MISC, 10, + "rsa_sig_encode_hash: no certificate to send")); + goto skipcert; + } } + /* Let's store the certificate we are going to use */ + exchange->sent_certtype = idtype; + exchange->sent_cert = handler->cert_get (data, datalen); + if (!exchange->sent_cert) + { + free (data); + log_error ("rsa_sig_encode_hash: failed to get certificate from wire encoding"); + return -1; + } + + aftercert: + + buf = realloc (data, ISAKMP_CERT_SZ + datalen); + if (!buf) + { + log_error ("rsa_sig_encode_hash: realloc (%p, %d) failed", data, + ISAKMP_CERT_SZ + datalen); + free (data); + return -1; + } + memmove (buf + ISAKMP_CERT_SZ, buf, datalen); + SET_ISAKMP_CERT_ENCODING (buf, idtype); + if (message_add_payload (msg, ISAKMP_PAYLOAD_CERT, buf, + ISAKMP_CERT_SZ + datalen, 1)) + { + free (buf); + return -1; + } + + skipcert: + switch (id[ISAKMP_ID_TYPE_OFF - ISAKMP_GEN_SZ]) { case IPSEC_ID_IPV4_ADDR: @@ -977,12 +1019,42 @@ rsa_sig_encode_hash (struct message *msg) break; } - key = ike_auth_get_key (IKE_AUTH_RSA_SIG, exchange->name, buf2, NULL); - free (buf2); - if (key == NULL) + /* Again, we may have these from the kernel */ + if ((buf = conf_get_str (exchange->name, "OKAuthentication")) != NULL) { - log_print ("rsa_sig_encode_hash: could not get private key"); - return -1; + key_from_printable (ISAKMP_KEY_RSA, ISAKMP_KEYTYPE_PRIVATE, buf, &data, + &datalen); + if ((data == NULL) || (datalen == -1)) + { + log_error ("rsa_sig_encode_hash: badly formatted RSA private key"); + return 0; + } + + exchange->sent_keytype = ISAKMP_KEY_RSA; + exchange->sent_key = key_internalize (ISAKMP_KEY_RSA, + ISAKMP_KEYTYPE_PRIVATE, data, + datalen); + if (exchange->sent_key == NULL) + { + log_error ("rsa_sig_encode_hash: bad RSA private key from dynamic " + "SA acquisition subsystem"); + return 0; + } + } + else /* Try through the regular means */ + { + exchange->sent_key = ike_auth_get_key (IKE_AUTH_RSA_SIG, exchange->name, + buf2, NULL); + free (buf2); + + /* Did we find a key ? */ + if (exchange->sent_key == NULL) + { + log_print ("rsa_sig_encode_hash: could not get private key"); + return -1; + } + + exchange->sent_keytype = ISAKMP_KEY_RSA; } /* XXX hashsize is not necessarily prf->blocksize. */ @@ -990,40 +1062,35 @@ rsa_sig_encode_hash (struct message *msg) if (!buf) { log_error ("rsa_sig_encode_hash: malloc (%d) failed", hashsize); - LC (RSA_free, (key)); return -1; } if (ike_auth_hash (exchange, buf) == -1) { free (buf); - LC (RSA_free, (key)); return -1; } snprintf (header, 80, "rsa_sig_encode_hash: HASH_%c", initiator ? 'I' : 'R'); LOG_DBG_BUF ((LOG_MISC, 80, header, buf, hashsize)); - data = malloc (LC (RSA_size, (key))); + data = malloc (LC (RSA_size, (exchange->sent_key))); if (!data) { log_error ("rsa_sig_encode_hash: malloc (%d) failed", - LC (RSA_size, (key))); - LC (RSA_free, (key)); + LC (RSA_size, (exchange->sent_key))); return -1; } - datalen - = LC (RSA_private_encrypt, (hashsize, buf, data, key, RSA_PKCS1_PADDING)); + datalen = LC (RSA_private_encrypt, (hashsize, buf, data, + exchange->sent_key, RSA_PKCS1_PADDING)); if (datalen == -1) { log_error ("rsa_sig_encode_hash: RSA_private_encrypt () failed"); free (buf); - LC (RSA_free, (key)); return -1; } - LC (RSA_free, (key)); free (buf); buf = realloc (data, ISAKMP_SIG_SZ + datalen); |