summaryrefslogtreecommitdiff
path: root/sbin/isakmpd/ike_auth.c
diff options
context:
space:
mode:
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