# include <time.h>
# endif
#endif
-#ifdef ENABLE_HYBRID
-#include <resolv.h>
-#endif
#include "var.h"
#include "misc.h"
#if HAVE_OPENDIR
#include "open_dir.h"
#endif
-#include "dnssec.h"
#include "sockmisc.h"
#include "strnames.h"
#include "gcmalloc.h"
#include <CoreFoundation/CoreFoundation.h>
#include "remoteconf.h"
#include "vpn_control.h"
-#if TARGET_OS_EMBEDDED
+#ifndef HAVE_OPENSSL
#include <Security/SecCertificate.h>
#include <Security/SecCertificatePriv.h>
#endif
#include "vpn_control_var.h"
-#include "ikev2_rfc.h"
#include "extern.h"
#define OUTBOUND_SA 0
static int oakley_check_dh_pub (vchar_t *, vchar_t **);
static int oakley_compute_keymat_x (phase2_handle_t *, int, int);
-static int oakley_compute_ikev2_keymat_x (phase2_handle_t *);
static int get_cert_fromlocal (phase1_handle_t *, int);
static int oakley_check_certid (phase1_handle_t *iph1);
static int oakley_check_certid_1 (vchar_t *, int, int, void*, cert_status_t *certStatus);
-static vchar_t * oakley_prf_plus (vchar_t *, vchar_t *, int, phase1_handle_t *iph1);
#ifdef HAVE_OPENSSL
static int check_typeofcertname (int, int);
#endif
oakley_prf(vchar_t *key, vchar_t *buf, phase1_handle_t *iph1)
{
vchar_t *res = NULL;
- int type;
+ int type = OAKLEY_ATTR_HASH_ALG_MD5;
if (iph1->approval == NULL) {
if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
* We use md5 as default.
*/
type = OAKLEY_ATTR_HASH_ALG_MD5;
- } else {
- type = OAKLEY_ATTR_HASH_ALG_SHA;
}
} else
{
oakley_hash(vchar_t *buf, phase1_handle_t *iph1)
{
vchar_t *res = NULL;
- int type;
+ int type = OAKLEY_ATTR_HASH_ALG_MD5;
if (iph1->approval == NULL) {
if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
* We use md5 as default.
*/
type = OAKLEY_ATTR_HASH_ALG_MD5;
- } else {
- type = OAKLEY_ATTR_HASH_ALG_SHA;
}
} else {
if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
type = iph1->approval->hashtype;
- } else {
- type = OAKLEY_ATTR_HASH_ALG_SHA;
}
}
return error;
}
-
/*
* compute KEYMAT.
* KEYMAT = prf(SKEYID_d, protocol | SPI | Ni_b | Nr_b).
len = 1 + sizeof(u_int32_t) + body->l;
buf = vmalloc(len);
if (buf == NULL) {
- plog(ASL_LEVEL_DEBUG,
+ plog(ASL_LEVEL_NOTICE,
"failed to get hash buffer\n");
goto end;
}
len = sizeof(u_int32_t) + body->l;
buf = vmalloc(len);
if (buf == NULL) {
- plog(ASL_LEVEL_DEBUG,
+ plog(ASL_LEVEL_NOTICE,
"failed to get hash buffer\n");
goto end;
}
cert_t *p;
vchar_t *user_id;
int user_id_found = 0;
+#ifndef HAVE_OPENSSL
+ SecCertificateRef certificate;
+ CFArrayRef commonNames;
+ CFIndex i, l;
+ CFStringRef name;
+#endif /* HAVE_OPENSSL */
for (p = iph1->cert_p; p; p = p->chain) {
+#ifdef HAVE_OPENSSL
user_id = eay_get_x509_common_name(&p->cert); //%%%%%%%% fix this
if (user_id) {
user_id_found = 1;
}
vfree(user_id);
}
+#else /* HAVE_OPENSSL */
+ certificate = crypto_cssm_x509cert_CreateSecCertificateRef(&p->cert);
+ if (certificate == NULL) {
+ plog(ASL_LEVEL_ERR,
+ "ovuid failed to get SecCertificateRef\n");
+ continue;
+ }
+
+ commonNames = SecCertificateCopyCommonNames(certificate);
+ if (commonNames == NULL) {
+ plog(ASL_LEVEL_ERR,
+ "ovuid failed to get commonNames\n");
+ CFRelease(certificate);
+ continue;
+ }
+
+ l = CFArrayGetCount(commonNames);
+ for (i = 0; i < l; i++) {
+ name = CFArrayGetValueAtIndex(commonNames, i);
+ user_id = vmalloc(CFStringGetMaximumSizeForEncoding(CFStringGetLength(name),
+ kCFStringEncodingUTF8) + 1);
+ if (user_id) {
+ if (CFStringGetCString(name, user_id->v, user_id->l,
+ kCFStringEncodingUTF8)) {
+ user_id_found = 1;
+ // the following functions will check if user_id == 0
+ if (open_dir_authorize_id(user_id, iph1->rmconf->open_dir_auth_group)) {
+ vfree(user_id);
+ CFRelease(certificate);
+ CFRelease(commonNames);
+ return 0;
+ }
+ }
+ vfree(user_id);
+ }
+ }
+ CFRelease(certificate);
+ CFRelease(commonNames);
+#endif /* HAVE_OPENSSL */
}
if (user_id_found) {
plog(ASL_LEVEL_ERR,
"invalid etype %d\n", iph1->etype);
return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
}
- } else {
- my_hash = oakley_ph1hash_common(iph1, VALIDATE);
}
if (my_hash == NULL)
return ISAKMP_INTERNAL_ERROR;
return ISAKMP_NTYPE_PAYLOAD_MALFORMED;
}
- plog(ASL_LEVEL_DEBUG, "*** SIGN passed\n");
+ plog(ASL_LEVEL_DEBUG, "SIGN passed\n");
/* get peer's cert */
switch (iph1->rmconf->getcert_method) {
"invalid etype %d\n", iph1->etype);
return ISAKMP_NTYPE_INVALID_EXCHANGE_TYPE;
}
- } else {
- vchar_t *octets = NULL;
- octets = ikev2_ike_sa_auth_get_octets(iph1, (iph1->side == INITIATOR)? FALSE : TRUE);
- my_hash = alg_oakley_hashdef_one(OAKLEY_ATTR_HASH_ALG_SHA, octets);
}
if (my_hash == NULL)
return ISAKMP_INTERNAL_ERROR;
}
if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
error = crypto_cssm_verify_x509sign(publicKeyRef, my_hash, iph1->sig_p, FALSE);
- } else {
- error = crypto_cssm_verify_x509sign(publicKeyRef, my_hash, iph1->sig_p, TRUE);
}
if (error) {
plog(ASL_LEVEL_ERR, "error verifying signature %s\n", GetSecurityErrorString(error));
return ISAKMP_NTYPE_SITUATION_NOT_SUPPORTED;
break;
}
- plog(ASL_LEVEL_INFO, "No SIG was passed, "
+ plog(ASL_LEVEL_NOTICE, "No SIG was passed, "
"but hybrid auth is enabled\n");
return 0;
int
oakley_vpncontrol_notify_ike_failed_if_mycert_invalid (phase1_handle_t *iph1, int notify_initiator)
{
-#if TARGET_OS_EMBEDDED
+#ifndef HAVE_OPENSSL
int premature = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_PREMATURE);
int expired = oakley_find_status_in_certchain(iph1->cert, CERT_STATUS_EXPIRED);
if (premature || expired) {
- u_int32_t address;
u_int32_t fail_reason;
- if (iph1->remote->ss_family == AF_INET)
- address = ((struct sockaddr_in *)(iph1->remote))->sin_addr.s_addr;
- else
- address = 0;
if (premature) {
fail_reason = VPNCTL_NTYPE_LOCAL_CERT_PREMATURE;
} else {
fail_reason = VPNCTL_NTYPE_LOCAL_CERT_EXPIRED;
}
- vpncontrol_notify_ike_failed(fail_reason, notify_initiator, address, 0, NULL);
+ vpncontrol_notify_ike_failed(fail_reason, notify_initiator, iph1_get_remote_v4_address(iph1), 0, NULL);
return -1;
}
-#endif /* TARGET_OS_EMBEDDED */
+#endif /* HAVE_OPENSSL */
return 0;
}
oakley_check_certid_1(vchar_t *cert, int idtype, int idlen, void *id, cert_status_t *certStatus)
{
- int len;
+ int len = 0;
int error = 0;
-#if !TARGET_OS_EMBEDDED
+#ifdef HAVE_OPENSSL
int type;
char *altname = NULL;
#endif
{
CFDataRef subject;
SecCertificateRef certificate;
- UInt8* namePtr;
+ UInt8* namePtr = NULL;
certificate = crypto_cssm_x509cert_CreateSecCertificateRef(cert);
if (certificate == NULL) {
if (error) {
plog(ASL_LEVEL_ERR,
"ID mismatched with certificate subjectName\n");
- plogdump(ASL_LEVEL_ERR, namePtr, len, "subjectName (type %s):\n",
- s_ipsecdoi_ident(idtype));
+ if (namePtr != NULL) {
+ plogdump(ASL_LEVEL_ERR, namePtr, len, "subjectName (type %s):\n",
+ s_ipsecdoi_ident(idtype));
+ } else {
+ plog(ASL_LEVEL_ERR, "subjectName (type %s):\n", s_ipsecdoi_ident(idtype));
+ }
plogdump(ASL_LEVEL_ERR, id, idlen, "ID:\n");
if (certStatus && !*certStatus) {
*certStatus = CERT_STATUS_INVALID_SUBJNAME;
}
}
CFRelease(certificate);
- CFRelease(subject);
+ if (subject != NULL) {
+ CFRelease(subject);
+ }
return 0;
}
break;
case IPSECDOI_ID_IPV4_ADDR:
case IPSECDOI_ID_IPV6_ADDR:
{
-#if TARGET_OS_EMBEDDED
+#ifndef HAVE_OPENSSL
CFIndex pos, count;
SecCertificateRef certificate;
CFArrayRef addresses;
*certStatus = CERT_STATUS_INVALID_SUBJALTNAME;
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
-#endif /* TARGET_OS_EMBEDDED */
+#endif /* HAVE_OPENSSL */
}
-#if TARGET_OS_EMBEDDED
+#ifndef HAVE_OPENSSL
case IPSECDOI_ID_FQDN:
{
CFIndex pos, count;
}
memcpy(secret->v, iph1->rmconf->shared_secret->v, secret->l);
}
- } else if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV2 ||
- iph1->etype != ISAKMP_ETYPE_IDENT) {
+ } else if (iph1->etype != ISAKMP_ETYPE_IDENT) {
secret = getpskbyname(iph1->id_p);
if (!secret) {
if (iph1->rmconf->verify_identifier) {
char *p;
int len;
int error = -1;
-
-
+
/* SKEYID */
switch (AUTHMETHOD(iph1)) {
case OAKLEY_ATTR_AUTH_METHOD_PSKEY:
return error;
}
-static vchar_t *
-oakley_prf_plus (vchar_t *key, vchar_t *buf, int result_len, phase1_handle_t *iph1)
-{
- vchar_t *t = 0;
- uint8_t byte_value;
- vchar_t *result = 0;
- uint8_t *p;
- vchar_t *bp;
- int bp_len;
- uint8_t *tmp;
- vchar_t *prf;
-
- /*
- * (draft-17)
- prf+ (K,S) = T1 | T2 | T3 | T4 | ...
-
- where:
- T1 = prf (K, S | 0x01)
- T2 = prf (K, T1 | S | 0x02)
- T3 = prf (K, T2 | S | 0x03)
- T4 = prf (K, T3 | S | 0x04)
- */
-
- if (!(result = vmalloc(result_len))) {
- return NULL;
- }
-
- /*
- * initial T0 = empty
- */
- t = 0;
- p = (uint8_t *)result->v;
- for (byte_value = 1; result_len > 0; ++byte_value) {
- /*
- * prf_output = prf(K, Ti-1 | S | byte)
- */
- bp_len = buf->l + sizeof(byte_value);
- if (t) {
- bp_len += t->l;
- }
- bp = vmalloc(bp_len);
- if (!bp) {
- return NULL;
- }
- tmp = (__typeof__(tmp))bp->v;
-
- if (t) {
- memcpy(tmp, t->v, t->l);
- tmp += t->l;
- }
- memcpy(tmp, buf->v, buf->l);
- tmp += buf->l;
- memcpy(tmp, &byte_value, sizeof(byte_value));
- tmp += sizeof(byte_value);
-
- if (!(prf = oakley_prf(key, bp, iph1))) {
- VPTRINIT(bp);
- return (vchar_t *)-1;
- }
- VPTRINIT(bp);
-
- /*
- * concat prf_output
- */
- memcpy(p, prf->v, prf->l > (size_t)result_len ? (size_t)result_len : prf->l);
- p += prf->l;
- result_len -= prf->l;
-
- /*
- * Ti = prf_output
- */
- if (t) {
- bzero(t->v, t->l);
- vfree(t);
- }
- t = prf;
- }
- if (t) {
- bzero(t->v, t->l);
- vfree(t);
- }
- return result;
-}
-
/*
* compute SKEYID_[dae]
*/
int
oakley_skeyid_dae(phase1_handle_t *iph1)
{
- vchar_t *buf = NULL, *bp = NULL;
+ vchar_t *buf = NULL;
char *p;
int len;
int error = -1;
plog(ASL_LEVEL_ERR, "no SKEYID found.\n");
goto end;
}
+
/*
* see seciton 5. Exchanges in RFC 2409
* SKEYID_d = prf(SKEYID, g^ir | CKY-I | CKY-R | 0)
"failed to get key buffer\n");
goto end;
}
- if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV2) {
- iph1->key_p = vmalloc(keylen >> 3);
- if (iph1->key_p == NULL) {
- plog(ASL_LEVEL_ERR,
- "failed to get key buffer\n");
- goto end;
- }
-
- if (iph1->key->l <= iph1->skeyid_e->l) {
- plog(ASL_LEVEL_DEBUG,
- "%s setting key len %zd, val %d (len %zd)", __FUNCTION__, iph1->key->l, (int)iph1->skeyid_e->v[0], iph1->skeyid_e->l);
- /*
- * if length(Ka) <= length(SKEYID_e)
- * Ka = first length(K) bit of SKEYID_e
- */
- memcpy(iph1->key->v, iph1->skeyid_e->v, iph1->key->l);
- } else {
- plog(ASL_LEVEL_ERR,
- "unexpected key length error (exp %zd, got %zd)",
- iph1->key->l, iph1->skeyid_e->l);
- goto end;
- }
- if (iph1->key_p->l <= iph1->skeyid_e_p->l) {
- plog(ASL_LEVEL_DEBUG,
- "%s setting peer key len %zd, val %d (len %zd)", __FUNCTION__, iph1->key_p->l, (int)iph1->skeyid_e_p->v[0], iph1->skeyid_e_p->l);
- /*
- * if length(Ka) <= length(SKEYID_e)
- * Ka = first length(K) bit of SKEYID_e
- */
- memcpy(iph1->key_p->v, iph1->skeyid_e_p->v, iph1->key_p->l);
- } else {
- plog(ASL_LEVEL_ERR,
- "unexpected peer key length error (exp %zd, got %zd)",
- iph1->key_p->l, iph1->skeyid_e_p->l);
- goto end;
- }
- }
/* set prf length */
prflen = alg_oakley_hashdef_hashlen(iph1->approval->hashtype);
int cplen;
int subkey;
- if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV2) {
- plog(ASL_LEVEL_ERR,
- "invalid key len (got %zu, expected %zu.\n", iph1->key->l, iph1->skeyid_e->l);
- goto end;
- }
-
/*
* otherwise,
* Ka = K1 | K2 | K3
return newivm;
}
-/*
- * Compute unpredictable IV for IKEv2.
- */
-int
-oakley_newiv_ikev2(phase1_handle_t * iph1)
-{
- struct isakmp_ivm *newivm = NULL;
- int iv_length;
-
- /* Get IV length */
- iv_length = alg_oakley_encdef_blocklen(iph1->approval->enctype);
- if (iv_length == -1) {
- plog(ASL_LEVEL_ERR, "Invalid encryption algorithm %d.\n", iph1->approval->enctype);
- }
-
- /* Allocate IV Manager */
- newivm = racoon_calloc(1, sizeof(struct isakmp_ivm));
- if (newivm == NULL) {
- plog(ASL_LEVEL_ERR, "Failed to allocate IV buffer.\n");
- return -1;
- }
-
- /* Compute IV */
- /* There are two recommended methods for generating unpredictable IVs. The first method is to apply the forward cipher function, under the same key that is used for the encryption of the plaintext, to a nonce. The nonce must be a data block that is unique to each execution of the encryption operation. For example, the nonce may be a counter, as described in Appendix B, or a message number. The second method is to generate a random data block using a FIPS- approved random number generator.
- [National Institute of Standards and Technology, U.S.
- Department of Commerce, "Recommendation for Block Cipher
- Modes of Operation", SP 800-38A, 2001.]
- */
- /* Currently, we implement the second scheme, which uses a random block */
- newivm->iv = eay_set_random(iv_length);
- if (newivm->iv == NULL) {
- oakley_delivm(newivm);
- return -1;
- }
-
- /* Adjust length of IV */
- if (newivm->iv->l != iv_length) {
- plog(ASL_LEVEL_WARNING, "IV length was adjusted.\n");
- newivm->iv->l = iv_length;
- }
-
- /* Make copy of IV in IVe */
- if ((newivm->ive = vdup(newivm->iv)) == NULL) {
- plog(ASL_LEVEL_ERR, "vdup (%s)\n", strerror(errno));
- oakley_delivm(newivm);
- return -1;
- }
-
- /* Delete old IV if there is one */
- if (iph1->ivm != NULL)
- oakley_delivm(iph1->ivm);
-
- iph1->ivm = newivm;
-
- return 0;
-}
-
-
void
oakley_delivm(struct isakmp_ivm *ivm)
{
if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
return(oakley_do_ikev1_decrypt(iph1, msg, ivdp, ivep));
}
+
plog(ASL_LEVEL_ERR, "Failed to decrypt invalid IKE version");
return NULL;
}
return buf;
}
-
/*
* encrypt packet.
*/
if (iph1->version == ISAKMP_VERSION_NUMBER_IKEV1) {
return(oakley_do_ikev1_encrypt(iph1, msg, ivep, ivp));
}
+
plog(ASL_LEVEL_ERR, "Failed to encrypt invalid IKE version");
return NULL;
}