diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-04-19 21:08:45 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1999-04-19 21:08:45 +0000 |
commit | 215dc0a82a679c56cc9305a54a9650721fbfa7ef (patch) | |
tree | 24bcc3f2ecddbd5597f8068ca4bd93ccf69a0755 /sbin | |
parent | 6b4bf50053691d23856fa79cfb2c6d00b51396ac (diff) |
./ike_auth.c: Merge with EOM 1.29
Accept multiple CERT payloads. Some style nits.
Style. alloc error reporting. Math error propagation. Allocate right
sizes.
Memory alloc. error reporting
1999 copyrights
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/isakmpd/ike_auth.c | 235 |
1 files changed, 145 insertions, 90 deletions
diff --git a/sbin/isakmpd/ike_auth.c b/sbin/isakmpd/ike_auth.c index 83e65303270..cde0ef866ae 100644 --- a/sbin/isakmpd/ike_auth.c +++ b/sbin/isakmpd/ike_auth.c @@ -1,8 +1,8 @@ -/* $OpenBSD: ike_auth.c,v 1.11 1999/03/24 14:42:49 niklas Exp $ */ -/* $EOM: ike_auth.c,v 1.25 1999/03/24 10:59:29 niklas Exp $ */ +/* $OpenBSD: ike_auth.c,v 1.12 1999/04/19 21:08:44 niklas Exp $ */ +/* $EOM: ike_auth.c,v 1.29 1999/04/18 15:17:51 niklas Exp $ */ /* - * Copyright (c) 1998 Niklas Hallqvist. All rights reserved. + * Copyright (c) 1998, 1999 Niklas Hallqvist. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,6 +45,7 @@ #include "asn.h" #include "cert.h" #include "conf.h" +#include "constants.h" #include "exchange.h" #include "gmp.h" #include "gmp_util.h" @@ -71,16 +72,26 @@ static int rsa_sig_encode_hash (struct message *); static int ike_auth_hash (struct exchange *, u_int8_t *); static struct ike_auth ike_auth[] = { - { IKE_AUTH_PRE_SHARED, pre_shared_gen_skeyid, pre_shared_decode_hash, - pre_shared_encode_hash}, - { IKE_AUTH_DSS, sig_gen_skeyid, pre_shared_decode_hash, - pre_shared_encode_hash}, - { IKE_AUTH_RSA_SIG, sig_gen_skeyid, rsa_sig_decode_hash, - rsa_sig_encode_hash}, - { IKE_AUTH_RSA_ENC, enc_gen_skeyid, pre_shared_decode_hash, - pre_shared_encode_hash}, - { IKE_AUTH_RSA_ENC_REV, enc_gen_skeyid, pre_shared_decode_hash, - pre_shared_encode_hash}, + { + IKE_AUTH_PRE_SHARED, pre_shared_gen_skeyid, pre_shared_decode_hash, + pre_shared_encode_hash + }, + { + IKE_AUTH_DSS, sig_gen_skeyid, pre_shared_decode_hash, + pre_shared_encode_hash + }, + { + IKE_AUTH_RSA_SIG, sig_gen_skeyid, rsa_sig_decode_hash, + rsa_sig_encode_hash + }, + { + IKE_AUTH_RSA_ENC, enc_gen_skeyid, pre_shared_decode_hash, + pre_shared_encode_hash + }, + { + IKE_AUTH_RSA_ENC_REV, enc_gen_skeyid, pre_shared_decode_hash, + pre_shared_encode_hash + }, }; struct ike_auth * @@ -94,45 +105,61 @@ ike_auth_get (u_int16_t id) return 0; } -static u_int8_t * -pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz) +/* + * Find and decode the configured key (pre-shared or public) for the + * peer denoted by ID. Stash the len in KEYLEN. + */ +static char * +ike_auth_get_key (char *id, size_t *keylen) { - struct prf *prf; - struct ipsec_exch *ie = exchange->data; - u_int8_t *skeyid; - u_int8_t *key; - u_int8_t *buf = 0; - size_t keylen; + char *key, *buf; /* Get the pre-shared key for our peer. */ - key = conf_get_str (exchange->name, "Authentication"); + key = conf_get_str (id, "Authentication"); if (!key) { - log_print ("pre_shared_gen_skeyid: no key found for peer \"%s\"", - exchange->name); + log_print ("ike_auth_get_key: no key found for peer \"%s\"", id); return 0; } /* If the key starts with 0x it is in hex format. */ if (strncasecmp (key, "0x", 2) == 0) { - keylen = (strlen (key) - 1) / 2; - buf = malloc (keylen); + *keylen = (strlen (key) - 1) / 2; + buf = malloc (*keylen); if (!buf) { - log_print ("pre_shared_gen_skeyid: malloc (%d) failed", keylen); + log_print ("ike_auth_get_key: malloc (%d) failed", *keylen); return 0; } - if (hex2raw (key + 2, buf, keylen)) + if (hex2raw (key + 2, buf, *keylen)) { free (buf); - log_print ("pre_shared_gen_skeyid: invalid hex key"); + log_print ("ike_auth_get_key: invalid hex key %s", key); return 0; } key = buf; } else - keylen = strlen (key); + *keylen = strlen (key); + + return key; +} + +static u_int8_t * +pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz) +{ + struct prf *prf; + struct ipsec_exch *ie = exchange->data; + u_int8_t *skeyid; + u_int8_t *key; + u_int8_t *buf = 0; + size_t keylen; + + /* Get the pre-shared key for our peer. */ + key = ike_auth_get_key (exchange->name, &keylen); + if (!key) + return 0; prf = prf_alloc (ie->prf_type, ie->hash->type, key, keylen); if (buf) @@ -144,6 +171,7 @@ pre_shared_gen_skeyid (struct exchange *exchange, size_t *sz) skeyid = malloc (*sz); if (!skeyid) { + log_error ("pre_shared_gen_skeyid: malloc (%d) failed", *sz); prf_free (prf); return 0; } @@ -181,6 +209,7 @@ sig_gen_skeyid (struct exchange *exchange, size_t *sz) skeyid = malloc (*sz); if (!skeyid) { + log_error ("sig_gen_skeyid: malloc (%d) failed", *sz); prf_free (prf); return 0; } @@ -217,6 +246,7 @@ enc_gen_skeyid (struct exchange *exchange, size_t *sz) skeyid = malloc (*sz); if (!skeyid) { + log_error ("enc_gen_skeyid: malloc (%d) failed", *sz); prf_free (prf); return 0; } @@ -254,7 +284,10 @@ pre_shared_decode_hash (struct message *msg) /* XXX Need this hash be in the SA? */ *hash_p = malloc (hashsize); if (!*hash_p) - return -1; + { + log_error ("pre_shared_decode_hash: malloc (%d) failed", hashsize); + return -1; + } memcpy (*hash_p, payload->p + ISAKMP_HASH_DATA_OFF, hashsize); snprintf (header, 80, "pre_shared_decode_hash: HASH_%c", @@ -266,10 +299,7 @@ pre_shared_decode_hash (struct message *msg) return 0; } -/* - * Decrypt the HASH in SIG, we already need a parsed ID payload - */ - +/* Decrypt the HASH in SIG, we already need a parsed ID payload. */ static int rsa_sig_decode_hash (struct message *msg) { @@ -285,13 +315,14 @@ rsa_sig_decode_hash (struct message *msg) u_int16_t len; u_int32_t id_cert_len; size_t id_len; + int found = 0; /* Choose the right fields to fill-in. */ hash_p = initiator ? &ie->hash_r : &ie->hash_i; id = initiator ? exchange->id_r : exchange->id_i; id_len = initiator ? exchange->id_r_len : exchange->id_i_len; - if (id == NULL || id_len == 0) + if (!id || id_len == 0) { log_print ("rsa_sig_decode_hash: no ID in sa"); return -1; @@ -301,48 +332,74 @@ rsa_sig_decode_hash (struct message *msg) id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; - p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_CERT]); - if (!p) - return -1; - - if ((handler = cert_get (GET_ISAKMP_CERT_ENCODING(p->p))) == NULL) + for (p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_CERT]); p; + p = TAILQ_NEXT (p, link)) { - log_print ("rsa_sig_decode_hash: no handler for CERT encoding"); - return -1; - } + p->flags |= PL_MARK; + + /* When we have found a key, just walk over the rest, marking them. */ + if (found) + continue; + + handler = cert_get (GET_ISAKMP_CERT_ENCODING (p->p)); + if (!handler) + { + log_debug (LOG_MISC, 30, + "rsa_sig_decode_hash: no handler for %s CERT encoding", + constant_lookup (isakmp_certenc_cst, + GET_ISAKMP_CERT_ENCODING (p->p))); + continue; + } - /* XXX - this assumes IPv4 here */ - if (!handler->cert_get_subject (p->p + ISAKMP_CERT_DATA_OFF, - GET_ISAKMP_GEN_LENGTH(p->p) - - ISAKMP_CERT_DATA_OFF, - &id_cert, &id_cert_len)) - { - log_print ("rsa_sig_decode_hash: can not get subject from CERT"); - return -1; - } + if (!handler->cert_get_subject (p->p + ISAKMP_CERT_DATA_OFF, + GET_ISAKMP_GEN_LENGTH (p->p) - + ISAKMP_CERT_DATA_OFF, + &id_cert, &id_cert_len)) + { + log_print ("rsa_sig_decode_hash: can not get subject from CERT"); + continue; + } - if (id_cert_len != id_len || memcmp (id, id_cert, id_len)) - { - log_print ("rsa_sig_decode_hash: CERT subject does not match ID"); + if (id_cert_len != id_len || memcmp (id, id_cert, id_len) != 0) + { + log_print ("rsa_sig_decode_hash: CERT subject does not match ID"); + free (id_cert); + continue; + } free (id_cert); - return -1; + + if (!handler->cert_get_key (p->p + ISAKMP_CERT_DATA_OFF, + GET_ISAKMP_GEN_LENGTH (p->p) - + ISAKMP_CERT_DATA_OFF, + &key)) + { + log_print ("rsa_sig_decode_hash: decoding payload CERT failed"); + continue; + } + + found++; } - free (id_cert); - if (!handler->cert_get_key (p->p + ISAKMP_CERT_DATA_OFF, - GET_ISAKMP_GEN_LENGTH(p->p) - - ISAKMP_CERT_DATA_OFF, - &key)) + /* If no certificate provided a key, try the config file. */ + if (!found) { - log_print ("rsa_sig_decode_hash: decoding payload CERT failed"); +#ifdef notyet + rawkey = ike_auth_get_key (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->flags |= PL_MARK; - p = TAILQ_FIRST (&msg->payload[ISAKMP_PAYLOAD_SIG]); if (!p) { + log_print ("rsa_sig_decode_hash: missing signature payload"); pkcs_free_public_key (&key); return -1; } @@ -351,13 +408,13 @@ rsa_sig_decode_hash (struct message *msg) if (GET_ISAKMP_GEN_LENGTH (p->p) - ISAKMP_SIG_SZ != mpz_sizeinoctets (key.n)) { pkcs_free_public_key (&key); - log_print ("rsa_sig_decode_hash: SIG payload length does not match " - "public key"); + log_print ("rsa_sig_decode_hash: " + "SIG payload length does not match public key"); return -1; } - if (!pkcs_rsa_decrypt (PKCS_PRIVATE, &key, NULL, - p->p + ISAKMP_SIG_DATA_OFF, hash_p, &len)) + if (!pkcs_rsa_decrypt (PKCS_PRIVATE, &key, 0, p->p + ISAKMP_SIG_DATA_OFF, + hash_p, &len)) { pkcs_free_public_key (&key); return -1; @@ -368,7 +425,7 @@ rsa_sig_decode_hash (struct message *msg) if (len != hashsize) { free (*hash_p); - *hash_p = NULL; + *hash_p = 0; return -1; } @@ -390,11 +447,12 @@ pre_shared_encode_hash (struct message *msg) int initiator = exchange->initiator; u_int8_t *buf; - /* XXX - hashsize is not necessarily prf->blocksize */ + /* XXX - hashsize is not necessarily prf->blocksize. */ buf = malloc (ISAKMP_HASH_SZ + hashsize); if (!buf) { - /* XXX Log? */ + log_error ("pre_shared_encode_hash: malloc (%d) failed", + ISAKMP_HASH_SZ + hashsize); return -1; } @@ -411,7 +469,6 @@ pre_shared_encode_hash (struct message *msg) if (message_add_payload (msg, ISAKMP_PAYLOAD_HASH, buf, ISAKMP_HASH_SZ + hashsize, 1)) { - /* XXX Log? */ free (buf); return -1; } @@ -419,9 +476,7 @@ pre_shared_encode_hash (struct message *msg) return 0; } - -/* Encrypt the HASH into a SIG type */ - +/* Encrypt the HASH into a SIG type. */ static int rsa_sig_encode_hash (struct message *msg) { @@ -436,24 +491,25 @@ rsa_sig_encode_hash (struct message *msg) u_int32_t asnlen, datalen; char *keyfile; - /* XXX - this needs to be configureable */ + /* XXX This needs to be configureable. */ handler = cert_get (ISAKMP_CERTENC_X509_SIG); - if (handler == NULL) + if (!handler) { - /* XXX - Log? */ + /* XXX Log? */ return -1; } - /* XXX - implicitly uses exchange->id_{i,r} */ - if (!handler->cert_obtain (exchange, NULL, &data, &datalen)) + /* XXX Implicitly uses exchange->id_{i,r}. */ + if (!handler->cert_obtain (exchange, 0, &data, &datalen)) { - /* XXX - Log? */ + /* XXX Log? */ return -1; } buf = realloc (data, ISAKMP_CERT_SZ + datalen); - if (buf == NULL) + if (!buf) { - /* XXX Log? */ + log_error ("rsa_sig_encode_hash: realloc (%p, %d) failed", data, + ISAKMP_CERT_SZ + datalen); free (data); return -1; } @@ -462,13 +518,12 @@ rsa_sig_encode_hash (struct message *msg) if (message_add_payload (msg, ISAKMP_PAYLOAD_CERT, buf, ISAKMP_CERT_SZ + datalen, 1)) { - /* XXX Log? */ free (buf); return -1; } /* XXX - do we want to store our files in ASN.1 ? */ - keyfile = conf_get_str ("rsa_sig", "privkey"); + keyfile = conf_get_str ("RSA_sig", "privkey"); if (!asn_get_from_file (keyfile, &asn, &asnlen)) { /* XXX Log? */ @@ -503,8 +558,8 @@ rsa_sig_encode_hash (struct message *msg) snprintf (header, 80, "rsa_sig_encode_hash: HASH_%c", initiator ? 'I' : 'R'); log_debug_buf (LOG_MISC, 80, header, buf, hashsize); - if (!pkcs_rsa_encrypt (PKCS_PRIVATE, NULL, &key, buf, hashsize, - &data, &datalen)) + if (!pkcs_rsa_encrypt (PKCS_PRIVATE, 0, &key, buf, hashsize, &data, + &datalen)) { free (buf); pkcs_free_private_key (&key); @@ -516,7 +571,8 @@ rsa_sig_encode_hash (struct message *msg) buf = realloc (data, ISAKMP_SIG_SZ + datalen); if (!buf) { - /* XXX Log? */ + log_error ("rsa_sig_encode_hash: realloc (%p, %d) failed", data, + ISAKMP_SIG_SZ + datalen); free (data); return -1; } @@ -527,7 +583,6 @@ rsa_sig_encode_hash (struct message *msg) if (message_add_payload (msg, ISAKMP_PAYLOAD_SIG, buf, ISAKMP_SIG_SZ + datalen, 1)) { - /* XXX Log? */ free (buf); return -1; } |