summaryrefslogtreecommitdiff
path: root/sbin/isakmpd/ike_auth.c
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1999-08-26 22:30:09 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1999-08-26 22:30:09 +0000
commitfd017c93a0b2179074671fb0494c38c9456fd904 (patch)
tree0d5591bf25ae2b55adfd67ef8439b2dae40ce052 /sbin/isakmpd/ike_auth.c
parentbf8d1ed4926ea7bf4d3a5a78ea0f5b89d4e4ac8a (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.c224
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