diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-08-26 22:30:09 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-08-26 22:30:09 +0000 |
commit | fd017c93a0b2179074671fb0494c38c9456fd904 (patch) | |
tree | 0d5591bf25ae2b55adfd67ef8439b2dae40ce052 /sbin/isakmpd/ike_auth.c | |
parent | bf8d1ed4926ea7bf4d3a5a78ea0f5b89d4e4ac8a (diff) |
Merge with EOM 1.38
author: angelos
When doing preshared key authentication, if the responder has the
initiator's ID (as is the case in aggressive mode) and a shared key
cannot be found for the initiator's address (as may be the case for a
roaming laptop user), try to find the password under using as a lookup
key the initiator's Phase 1 ID, if it's an IPv4 address, an FQDN
(host.domain), or a User-FQDN (user@host.domain). This allows us to
support roaming laptop users with preshared key authentication, using
aggressive mode (sick).
There is also a lot of experimental, insecure, and ifdef'd out code
for fetching credentials and secret passphrases from a remote server
if all else fails. Extremely experimental code. Don't use. You'll be
blinded and your hair will fall if you even think about using it. You
have been warned.
author: angelos
Complete policy work; tested for the shared-key case. Documentation needed.
author: ho
Compile without USE_LIBCRYPTO and HAVE_DLOPEN.
author: niklas
Missing dynamic link fixes
author: niklas
Add support for dynamic loading of optional facilities, libcrypto first.
Diffstat (limited to 'sbin/isakmpd/ike_auth.c')
-rw-r--r-- | sbin/isakmpd/ike_auth.c | 224 |
1 files changed, 188 insertions, 36 deletions
diff --git a/sbin/isakmpd/ike_auth.c b/sbin/isakmpd/ike_auth.c index 8d260b5c621..97c1a26f28f 100644 --- a/sbin/isakmpd/ike_auth.c +++ b/sbin/isakmpd/ike_auth.c @@ -1,5 +1,5 @@ -/* $OpenBSD: ike_auth.c,v 1.16 1999/07/18 09:33:33 niklas Exp $ */ -/* $EOM: ike_auth.c,v 1.33 1999/07/18 09:25:33 niklas Exp $ */ +/* $OpenBSD: ike_auth.c,v 1.17 1999/08/26 22:30:08 niklas Exp $ */ +/* $EOM: ike_auth.c,v 1.38 1999/08/21 22:20:41 angelos Exp $ */ /* * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. @@ -35,15 +35,17 @@ * This code was written under funding by Ericsson Radio Systems. */ +/* #define OBTAIN_KEY 1 */ + #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> #include <string.h> -#include <ssl/evp.h> -#include <ssl/pem.h> -#include <ssl/x509.h> +#if defined(OBTAIN_KEY) +#include <unistd.h> +#endif /* OBTAIN_KEY */ #include "sysdep.h" @@ -57,6 +59,7 @@ #include "ike_auth.h" #include "ipsec.h" #include "ipsec_doi.h" +#include "libcrypto.h" #include "log.h" #include "message.h" #include "prf.h" @@ -72,7 +75,9 @@ static int rsa_sig_decode_hash (struct message *); static int pre_shared_encode_hash (struct message *); static int rsa_sig_encode_hash (struct message *); +#if defined (USE_LIBCRYPTO) || defined (HAVE_DLOPEN) static int ike_auth_hash (struct exchange *, u_int8_t *); +#endif static struct ike_auth ike_auth[] = { { @@ -116,9 +121,11 @@ static void * ike_auth_get_key (int type, char *id, size_t *keylen) { char *key, *buf; +#if defined (USE_LIBCRYPTO) || defined (HAVE_DLOPEN) char *keyfile; BIO *keyh; RSA *rsakey; +#endif switch (type) { @@ -154,32 +161,40 @@ ike_auth_get_key (int type, char *id, size_t *keylen) break; case IKE_AUTH_RSA_SIG: +#if defined (USE_LIBCRYPTO) || defined (HAVE_DLOPEN) +#ifdef HAVE_DLOPEN + if (!libcrypto) + return 0; +#endif + keyfile = conf_get_str ("X509-certificates", "Private-key"); - if ((keyh = BIO_new (BIO_s_file ())) == NULL) + if ((keyh = LC (BIO_new, (LC (BIO_s_file, ())))) == NULL) { - log_print ("ike_auth_get_key: BIO_new() failed"); + log_print ("ike_auth_get_key: " + "BIO_new (BIO_s_file ()) failed"); return 0; } - if (BIO_read_filename (keyh, keyfile) == -1) + if (LC (BIO_read_filename, (keyh, keyfile)) == -1) { - log_print ("ike_auth_get_key: BIO_read_filename(%s) failed", + log_print ("ike_auth_get_key: " + "BIO_read_filename (keyh, \"%s\") failed", keyfile); - BIO_free (keyh); + LC (BIO_free, (keyh)); return 0; } - rsakey = PEM_read_bio_RSAPrivateKey (keyh, NULL, NULL); + rsakey = LC (PEM_read_bio_RSAPrivateKey, (keyh, NULL, NULL)); if (!rsakey) { - log_print ("ike_auth_get_key: PEM_read_bio_RSAPrivateKey failed", - keyfile); - BIO_free (keyh); + log_print ("ike_auth_get_key: PEM_read_bio_RSAPrivateKey failed"); + LC (BIO_free, (keyh)); return 0; } - BIO_free (keyh); + LC (BIO_free, (keyh)); return rsakey; +#endif default: log_print ("ike_auth_get_key: unknown key type %d", type); @@ -199,10 +214,132 @@ pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz) u_int8_t *buf = 0; size_t keylen; +#if defined (OBTAIN_KEY) + struct sockaddr_in sin; + u_int32_t idlen; + int sock; +#else /* OBTAIN_KEY */ + in_addr_t addr; +#endif /* OBTAIN_KEY */ + /* Get the pre-shared key for our peer. */ key = ike_auth_get_key (IKE_AUTH_PRE_SHARED, exchange->name, &keylen); + +#if !defined (OBTAIN_KEY) if (!key) - return 0; + { + /* If we're the responder and have the initiator's ID (which is the + case in Aggressive mode), try to find the preshared key in the + section of the initiator's Phase I ID. This allows us to do mobile + user support with preshared keys. */ + if ((exchange->initiator == 0) && exchange->id_i) + { + switch (exchange->id_i[0]) + { + case IPSEC_ID_IPV4_ADDR: + buf = calloc (16, sizeof (char)); + if (!buf) + log_fatal ("pre_shared_gen_skeyid: failed to allocate 16 bytes for ID"); + addr = ntohl (decode_32 (exchange->id_i + + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ)); + inet_ntop (AF_INET, &addr, buf, 16); + break; + + case IPSEC_ID_FQDN: + case IPSEC_ID_USER_FQDN: + buf = calloc (exchange->id_i_len - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ + 1, sizeof (char)); + if (!buf) + log_fatal ("pre_shared_gen_skeyid: failed to allocate %d bytes for ID", exchange->id_i_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ + 1); + memcpy (buf, exchange->id_i + ISAKMP_ID_DATA_OFF - + ISAKMP_GEN_SZ, exchange->id_i_len - + ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ); + break; + + /* XXX Support more ID types ? */ + default: + return 0; + } + + key = ike_auth_get_key (IKE_AUTH_PRE_SHARED, buf, &keylen); + free (buf); + if (!key) + return 0; + } + else + return 0; + } +#else /* OBTAIN_KEY */ + /* If we didn't find the key in the config file, we can try to + * find it based on ID, or (if that fails) we can try to fetch it + * from a remote server. + */ + /* XXX Experimental */ + + if (!key) + { + sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == -1) + return 0; + + sin.sin_addr.s_addr = inet_addr ("158.130.6.141"); /* XXX */ + sin.sin_port = ntohs (3456); /* XXX */ + sin.sin_family = AF_INET; + sin.sin_len = sizeof (sin); + + if (connect (sock, (struct sockaddr *) &sin, sizeof (sin)) == -1) + { + close (sock); + return 0; + } + + idlen = htonl (exchange->id_i_len - ISAKMP_ID_DATA_OFF + + ISAKMP_GEN_SZ); + + printf ("%d [%s]\n", exchange->id_i[0], + exchange->id_i + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ); + + /* Simple protocol; write type (1 byte), size (4 bytes, big endian), + id data */ + if ((write (sock, exchange->id_i, 1) == -1) || + (write (sock, &idlen, sizeof (idlen)) == -1) || + (write (sock, exchange->id_i + ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ, + exchange->id_i_len - ISAKMP_ID_DATA_OFF + ISAKMP_GEN_SZ) == + -1)) + { + close (sock); + return 0; + } + + /* Read response; size (4 bytes, big endian), passphrase */ + /* XXX This should really be some sort of asynchronous operation... */ + /* XXXXXX This should be protected XXXXXXX */ + if (read (sock, &keylen, sizeof (idlen)) == -1) + { + close (sock); + return 0; + } + + keylen = ntohl (keylen); + key = malloc (keylen); + if (!key) + { + log_error ("pre_shared_gen_skeyid: malloc (%d) failed", keylen); + close (sock); + return 0; + } + + if (read (sock, key, keylen) == -1) + { + free (key); + close (sock); + return 0; + } + + close (sock); + } +#endif /* OBTAIN_KEY */ /* Store the secret key for later policy processing */ exchange->recv_cert = malloc (keylen); @@ -211,9 +348,10 @@ pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz) log_error ("pre_shared_gen_skeyid: malloc (%d) failed", keylen); return 0; } + memcpy (exchange->recv_cert, key, keylen); exchange->recv_certlen = keylen; exchange->recv_certtype = ISAKMP_CERTENC_NONE; - + prf = prf_alloc (ie->prf_type, ie->hash->type, key, keylen); if (buf) free (buf); @@ -359,6 +497,7 @@ pre_shared_decode_hash (struct message *msg) static int rsa_sig_decode_hash (struct message *msg) { +#if defined (USE_LIBCRYPTO) || defined (HAVE_DLOPEN) struct cert_handler *handler; struct exchange *exchange = msg->exchange; struct ipsec_exch *ie = exchange->data; @@ -369,9 +508,9 @@ rsa_sig_decode_hash (struct message *msg) RSA *key; size_t hashsize = ie->hash->hashsize; char header[80]; + int len; int initiator = exchange->initiator; u_int8_t **hash_p, *id_cert, *id; - int len; u_int32_t id_cert_len; size_t id_len; int found = 0; @@ -514,15 +653,15 @@ rsa_sig_decode_hash (struct message *msg) if (!p) { log_print ("rsa_sig_decode_hash: missing signature payload"); - RSA_free (key); + LC (RSA_free, (key)); return -1; } /* Check that the sig is of the correct size. */ len = GET_ISAKMP_GEN_LENGTH (p->p) - ISAKMP_SIG_SZ; - if (len != RSA_size (key)) + if (len != LC (RSA_size, (key))) { - RSA_free (key); + LC (RSA_free, (key)); log_print ("rsa_sig_decode_hash: " "SIG payload length does not match public key"); return -1; @@ -531,21 +670,21 @@ rsa_sig_decode_hash (struct message *msg) *hash_p = malloc (len); if (!*hash_p) { - RSA_free (key); + LC (RSA_free, (key)); log_error ("rsa_sig_decode_hash: malloc (%d) failed", len); return -1; } - len = RSA_public_decrypt (len, p->p + ISAKMP_SIG_DATA_OFF, *hash_p, key, - RSA_PKCS1_PADDING); + len = LC (RSA_public_decrypt, (len, p->p + ISAKMP_SIG_DATA_OFF, *hash_p, key, + RSA_PKCS1_PADDING)); if (len == -1) { - RSA_free (key); + LC (RSA_free, (key)); log_print ("rsa_sig_decode_hash: RSA_public_decrypt () failed"); return -1; } - RSA_free (key); + LC (RSA_free, (key)); if (len != hashsize) { @@ -561,11 +700,15 @@ rsa_sig_decode_hash (struct message *msg) p->flags |= PL_MARK; return 0; +#else + return -1; +#endif /* USE_LIBCRYPTO || HAVE_DLOPEN */ } static int pre_shared_encode_hash (struct message *msg) { +#if defined (USE_LIBCRYPTO) || defined (HAVE_DLOPEN) struct exchange *exchange = msg->exchange; struct ipsec_exch *ie = exchange->data; size_t hashsize = ie->hash->hashsize; @@ -583,14 +726,17 @@ pre_shared_encode_hash (struct message *msg) snprintf (header, 80, "pre_shared_encode_hash: HASH_%c", initiator ? 'I' : 'R'); log_debug_buf (LOG_MISC, 80, header, buf + ISAKMP_HASH_DATA_OFF, hashsize); - return 0; +#else + return -1; +#endif } /* Encrypt the HASH into a SIG type. */ static int rsa_sig_encode_hash (struct message *msg) { +#if defined (USE_LIBCRYPTO) || defined (HAVE_DLOPEN) struct exchange *exchange = msg->exchange; struct ipsec_exch *ie = exchange->data; size_t hashsize = ie->hash->hashsize; @@ -650,38 +796,40 @@ rsa_sig_encode_hash (struct message *msg) if (!buf) { log_error ("rsa_sig_encode_hash: malloc (%d) failed", hashsize); - RSA_free (key); + LC (RSA_free, (key)); return -1; } if (ike_auth_hash (exchange, buf) == -1) { free (buf); - RSA_free (key); + LC (RSA_free, (key)); return -1; } snprintf (header, 80, "rsa_sig_encode_hash: HASH_%c", initiator ? 'I' : 'R'); log_debug_buf (LOG_MISC, 80, header, buf, hashsize); - data = malloc (RSA_size (key)); + data = malloc (LC (RSA_size, (key))); if (!data) { - log_error ("rsa_sig_encode_hash: malloc (%d) failed", RSA_size (key)); - RSA_free (key); + log_error ("rsa_sig_encode_hash: malloc (%d) failed", + LC (RSA_size, (key))); + LC (RSA_free, (key)); return -1; } - datalen = RSA_private_encrypt (hashsize, buf, data, key, RSA_PKCS1_PADDING); + datalen + = LC (RSA_private_encrypt, (hashsize, buf, data, key, RSA_PKCS1_PADDING)); if (datalen == -1) { log_error ("rsa_sig_encode_hash: RSA_private_encrypt () failed"); free (buf); - RSA_free (key); + LC (RSA_free, (key)); return -1; } - RSA_free (key); + LC (RSA_free, (key)); free (buf); buf = realloc (data, ISAKMP_SIG_SZ + datalen); @@ -702,10 +850,13 @@ rsa_sig_encode_hash (struct message *msg) free (buf); return -1; } - return 0; +#else + return -1; +#endif /* USE_LIBCRYPTO || HAVE_DLOPEN */ } +#if defined (USE_LIBCRYPTO) || defined (HAVE_DLOPEN) int ike_auth_hash (struct exchange *exchange, u_int8_t *buf) { @@ -743,3 +894,4 @@ ike_auth_hash (struct exchange *exchange, u_int8_t *buf) return 0; } +#endif |