From fce29cd989a6ce7aa0e28bd9ade0752be16cb893 Mon Sep 17 00:00:00 2001 From: Apple Date: Mon, 29 Mar 2010 18:40:32 +0000 Subject: [PATCH] ipsec-93.6.tar.gz --- ipsec-tools/Common/ipsecMessageTracer.h | 15 ++ ipsec-tools/racoon/crypto_cssm.c | 205 ++++++++++++++++++++++-- ipsec-tools/racoon/crypto_cssm.h | 4 +- ipsec-tools/racoon/ike_session.c | 58 ++++++- ipsec-tools/racoon/ike_session.h | 3 + ipsec-tools/racoon/isakmp.c | 11 +- ipsec-tools/racoon/isakmp_inf.c | 8 +- ipsec-tools/racoon/isakmp_var.h | 2 +- ipsec-tools/racoon/oakley.c | 28 +++- ipsec-tools/racoon/oakley.h | 10 ++ ipsec-tools/racoon/pfkey_racoon.c | 6 +- ipsec-tools/racoon/vpn_control.h | 3 + 12 files changed, 323 insertions(+), 30 deletions(-) diff --git a/ipsec-tools/Common/ipsecMessageTracer.h b/ipsec-tools/Common/ipsecMessageTracer.h index 14bafba..9a3f50a 100644 --- a/ipsec-tools/Common/ipsecMessageTracer.h +++ b/ipsec-tools/Common/ipsecMessageTracer.h @@ -39,6 +39,19 @@ #define PLAINIPSEC_PHASE_DOMAIN CONSTSTR("com.apple.Networking.ipsec.phasestats.plain") #define PLAINIPSECDOMAIN CONSTSTR("com.apple.Networking.ipsec.main") +#if TARGET_OS_EMBEDDED + +#define IPSECCONFIGTRACEREVENT(config, eventCode, message, failure_reason) + +#define IPSECPOLICYTRACEREVENT(policy, eventCode, message, failure_reason) + +#define IPSECSESSIONTRACERSTART(session) +#define IPSECSESSIONTRACEREVENT(session, eventCode, message, failure_reason) +#define IPSECSESSIONTRACERSTOP(session, is_failure, reason) +#define IPSECSESSIONTRACERESTABLISHED(session) + +#else + #define IPSECCONFIGTRACEREVENT(config, eventCode, message, failure_reason) ipsecConfigTracerEvent(config, eventCode, message, failure_reason) #define IPSECPOLICYTRACEREVENT(policy, eventCode, message, failure_reason) ipsecPolicyTracerEvent(policy, eventCode, message, failure_reason) @@ -48,6 +61,8 @@ #define IPSECSESSIONTRACERSTOP(session, is_failure, reason) ipsecSessionTracerStop(session, is_failure, reason) #define IPSECSESSIONTRACERESTABLISHED(session) ipsecSessionTracerLogEstablished(session) +#endif + static inline double get_percentage (double numerator, double denominator) { if (numerator >= denominator || denominator == 0) { diff --git a/ipsec-tools/racoon/crypto_cssm.c b/ipsec-tools/racoon/crypto_cssm.c index e5b35d6..e47aa6d 100644 --- a/ipsec-tools/racoon/crypto_cssm.c +++ b/ipsec-tools/racoon/crypto_cssm.c @@ -36,6 +36,9 @@ #include #if TARGET_OS_EMBEDDED #include +#include +#include +#include #else #include #include @@ -55,6 +58,7 @@ #include "plog.h" #include "debug.h" #include "misc.h" +#include "oakley.h" #include "crypto_cssm.h" @@ -70,7 +74,7 @@ static OSStatus CopySystemKeychain(SecKeychainRef *keychainRef); /* * Verify cert using security framework */ -int crypto_cssm_check_x509cert(vchar_t *cert, CFStringRef hostname) +int crypto_cssm_check_x509cert(vchar_t *cert, CFStringRef hostname, cert_status_t certStatus) { OSStatus status; SecCertificateRef certRef = NULL; @@ -110,22 +114,13 @@ int crypto_cssm_check_x509cert(vchar_t *cert, CFStringRef hostname) } if (hostname) { - policyRef = SecPolicyCreateSSL(FALSE, hostname); + policyRef = SecPolicyCreateIPSec(FALSE, hostname); if (policyRef == NULL) { plog(LLV_ERROR, LOCATION, NULL, "unable to create a SSL policyRef.\n"); status = -1; goto end; } - } else - { - policyRef = SecPolicyCreateBasicX509(); - if (policyRef == NULL) { - plog(LLV_ERROR, LOCATION, NULL, - "unable to create a Basic X509 policyRef.\n"); - status = -1; - goto end; - } } #endif @@ -144,7 +139,11 @@ end: plog(LLV_ERROR, LOCATION, NULL, "error %d %s.\n", status, GetSecurityErrorString(status)); status = -1; - } + } else if (certStatus) { + plog(LLV_ERROR, LOCATION, NULL, + "certificate failed date verification: %d.\n", certStatus); + status = -1; + } return status; } @@ -350,7 +349,8 @@ end: /* * Retrieve a cert from the keychain */ -vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef) +vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef, + cert_status_t *certStatus) { OSStatus status; @@ -408,6 +408,10 @@ vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef) // data must be copied to be returned memcpy(cert->v, cssmData.Data, cssmData.Length); + // verify expiry or missing fields + if (certStatus) { + *certStatus = CERT_STATUS_OK; + } #else CFDictionaryRef persistFind = NULL; @@ -415,6 +419,21 @@ vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef) const void *values_persist[] = { kCFBooleanTrue, persistentCertRef }; size_t dataLen; CFDataRef certData = NULL; + CFAbsoluteTime timeNow = 0; + CFAbsoluteTime notvalidbeforedate = 0; + CFAbsoluteTime notvalidafterdate = 0; + CFDateRef nowcfdatedata = NULL; + CFDateRef notvalidbeforedatedata = NULL; + CFDateRef notvalidafterdatedata = NULL; + CFArrayRef certProparray = NULL; + CFRange range; + CFDictionaryRef *values = NULL; + CFDictionaryRef propDict = NULL; + const void *datevalue = NULL; + const void *labelvalue = NULL; + CFGregorianDate gregoriandate; + int count; + int i; /* find identity by persistent ref */ persistFind = CFDictionaryCreate(NULL, keys_persist, values_persist, @@ -444,6 +463,68 @@ vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef) CFDataGetBytes(certData, CFRangeMake(0, dataLen), cert->v); + // verify expiry or missing fields + if (certStatus) { + + *certStatus = CERT_STATUS_OK; + + if ((certProparray = SecCertificateCopyProperties(certificateRef))){ + if ((count = CFArrayGetCount( certProparray ))){ + range.location = 0; + range.length = count; + if ( (values = CFAllocatorAllocate(NULL, count * sizeof(CFDictionaryRef), 0))){ + CFArrayGetValues(certProparray, range, (const void **)values); + for( i = 0; i < count; i++) + { + if ((propDict = values[i])){ + if ( CFDictionaryContainsValue(propDict, kSecPropertyTypeDate) ){ + if ( CFDictionaryGetValueIfPresent(propDict, kSecPropertyKeyValue, (const void**)&datevalue)){ + /* get kSecPropertyKeyLabel */ + if ( (datevalue) && (CFDictionaryGetValueIfPresent(propDict, kSecPropertyKeyLabel, (const void**)&labelvalue))){ + if ( (labelvalue) && (CFStringCompare( (CFStringRef)labelvalue, CFSTR("Not Valid Before"), 0) == kCFCompareEqualTo)){ + if ( notvalidbeforedate = CFDateGetAbsoluteTime(datevalue)) + notvalidbeforedatedata = CFDateCreate(NULL, notvalidbeforedate); + }else if ((labelvalue) && (CFStringCompare( (CFStringRef)labelvalue, CFSTR("Not Valid After"), 0 ) == kCFCompareEqualTo)){ + if ( notvalidafterdate = CFDateGetAbsoluteTime(datevalue)) + notvalidafterdatedata = CFDateCreate(NULL, notvalidafterdate); + } + } + } + } + } + + } + } + } + } + + if ( (timeNow = CFAbsoluteTimeGetCurrent()) && (nowcfdatedata = CFDateCreate( NULL, timeNow))){ + if ( notvalidbeforedatedata ){ + gregoriandate = CFAbsoluteTimeGetGregorianDate(notvalidbeforedate, NULL); + plog(LLV_DEBUG, LOCATION, NULL, + "cert not valid before yr %d, mon %d, days %d, hours %d, min %d\n", gregoriandate.year, gregoriandate.month, gregoriandate.day, gregoriandate.hour, gregoriandate.minute); + gregoriandate = CFAbsoluteTimeGetGregorianDate(notvalidafterdate, NULL); + plog(LLV_DEBUG, LOCATION, NULL, + "cert not valid after yr %d, mon %d, days %d, hours %d, min %d\n", gregoriandate.year, gregoriandate.month, gregoriandate.day, gregoriandate.hour, gregoriandate.minute); + if ( CFDateCompare( nowcfdatedata, notvalidbeforedatedata, NULL ) == kCFCompareLessThan){ + plog(LLV_ERROR, LOCATION, NULL, + "current time before valid time\n"); + *certStatus = CERT_STATUS_PREMATURE; + } + else if (notvalidafterdatedata && (CFDateCompare( nowcfdatedata, notvalidafterdatedata, NULL ) == kCFCompareGreaterThan)){ + plog(LLV_ERROR, LOCATION, NULL, + "current time after valid time\n"); + *certStatus = CERT_STATUS_EXPIRED; + }else { + plog(LLV_INFO, LOCATION, NULL, "certificate expiration date OK\n"); + *certStatus = CERT_STATUS_OK; + } + + } + + } + } + #endif end: @@ -457,6 +538,16 @@ end: if (keychainRef) CFRelease(keychainRef); #else + if (notvalidbeforedatedata) + CFRelease(notvalidbeforedatedata); + if (notvalidafterdatedata) + CFRelease(notvalidafterdatedata); + if (certProparray) + CFRelease(certProparray); + if (values) + CFAllocatorDeallocate(NULL, values); + if (nowcfdatedata) + CFRelease(nowcfdatedata); if (persistFind) CFRelease(persistFind); if (certData) @@ -509,6 +600,13 @@ static OSStatus EvaluateCert(SecCertificateRef cert, CFTypeRef policyRef) OSStatus status; SecTrustRef trustRef = 0; SecTrustResultType evalResult; + +#if TARGET_OS_EMBEDDED + CFArrayRef errorStrings; +#else + CSSM_TP_APPLE_EVIDENCE_INFO *statusChain; + CFArrayRef certChain; +#endif SecCertificateRef evalCertArray[1] = { cert }; @@ -524,14 +622,89 @@ static OSStatus EvaluateCert(SecCertificateRef cert, CFTypeRef policyRef) status = SecTrustCreateWithCertificates(cfCertRef, policyRef, &trustRef); if (status != noErr) goto end; - + status = SecTrustEvaluate(trustRef, &evalResult); if (status != noErr) goto end; if (evalResult != kSecTrustResultProceed && evalResult != kSecTrustResultUnspecified) { - plog(LLV_ERROR, LOCATION, NULL, - "error evaluating certificate.\n"); + plog(LLV_ERROR, LOCATION, NULL, "Error evaluating certificate.\n"); + + switch (evalResult) { + case kSecTrustResultInvalid: + plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultInvalid.\n"); + break; + case kSecTrustResultProceed: + plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultProceed.\n"); + break; + case kSecTrustResultConfirm: + plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultConfirm.\n"); + break; + case kSecTrustResultDeny: + plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultDeny.\n"); + break; + case kSecTrustResultUnspecified: + plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultUnspecified.\n"); + break; + case kSecTrustResultRecoverableTrustFailure: + plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultRecoverableTrustFailure.\n"); + break; + case kSecTrustResultFatalTrustFailure: + plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultFatalTrustFailure.\n"); + break; + case kSecTrustResultOtherError: + plog(LLV_DEBUG, LOCATION, NULL, "eval result = kSecTrustResultOtherError.\n"); + break; + default: + plog(LLV_DEBUG, LOCATION, NULL, "eval result unknown: value = %d.\n", (int)evalResult); + break; + } + + +#if TARGET_OS_EMBEDDED + errorStrings = SecTrustCopyProperties(trustRef); + if (errorStrings) { + + CFDictionaryRef dict; + CFStringRef val; + const char *str; + CFIndex count, maxcount = CFArrayGetCount(errorStrings); + + plog(LLV_ERROR, LOCATION, NULL, "---------------Returned error strings: ---------------.\n"); + for (count = 0; count < maxcount; count++) { + dict = CFArrayGetValueAtIndex(errorStrings, count); + if (dict && (CFGetTypeID(dict) == CFDictionaryGetTypeID())) { + val = CFDictionaryGetValue(dict, kSecPropertyKeyType); + if (val && (CFGetTypeID(val) == CFStringGetTypeID())) { + str = CFStringGetCStringPtr(val, kCFStringEncodingMacRoman); + if (str) + plog(LLV_ERROR, LOCATION, NULL, "type = %s.\n", str); + } + val = CFDictionaryGetValue(dict, kSecPropertyKeyValue); + if (val && (CFGetTypeID(val) == CFStringGetTypeID())) { + str = CFStringGetCStringPtr(val, kCFStringEncodingMacRoman); + if (str) + plog(LLV_ERROR, LOCATION, NULL, "value = %s.\n", str); + } + } + } + plog(LLV_ERROR, LOCATION, NULL, "-----------------------------------------------------.\n"); + CFRelease(errorStrings); + } + +#else + SecTrustGetResult(trustRef, &evalResult, &certChain, &statusChain); + plog(LLV_ERROR, LOCATION, NULL, "Cert status bits = 0x%x.\n", statusChain->StatusBits); + plog(LLV_ERROR, LOCATION, NULL, "Cert status NumStatusCodes = 0x%x.\n", statusChain->NumStatusCodes); + { + int i; + for (i = 0; i < statusChain->NumStatusCodes; i++) + plog(LLV_ERROR, LOCATION, NULL, "Cert status code i = 0x%x %d.\n", *(statusChain->StatusCodes + i), *(statusChain->StatusCodes + i)); + } + plog(LLV_ERROR, LOCATION, NULL, "Cert status Index = %d.\n", statusChain->Index); + CFRelease(certChain); +#endif + status = -1; } diff --git a/ipsec-tools/racoon/crypto_cssm.h b/ipsec-tools/racoon/crypto_cssm.h index e7c94c3..d0562bf 100644 --- a/ipsec-tools/racoon/crypto_cssm.h +++ b/ipsec-tools/racoon/crypto_cssm.h @@ -33,9 +33,9 @@ #include -extern int crypto_cssm_check_x509cert(vchar_t *cert, CFStringRef hostname); +extern int crypto_cssm_check_x509cert(vchar_t *cert, CFStringRef hostname, cert_status_t certStatus); extern vchar_t* crypto_cssm_getsign(CFDataRef persistentCertRef, vchar_t* hash); -extern vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef); +extern vchar_t* crypto_cssm_get_x509cert(CFDataRef persistentCertRef, cert_status_t *certStatus); #endif /* __CRYPTO_CSSM_H__ */ diff --git a/ipsec-tools/racoon/ike_session.c b/ipsec-tools/racoon/ike_session.c index 3bb62d7..ffc1516 100644 --- a/ipsec-tools/racoon/ike_session.c +++ b/ipsec-tools/racoon/ike_session.c @@ -1207,6 +1207,8 @@ ike_session_update_traffic_idle_status (ike_session_t *session, session->i_sent_data_sc_idle = 1; } } + if (!idle) + session->last_time_data_sc_detected = time(NULL); ike_session_monitor_idle(session); } @@ -1465,4 +1467,58 @@ ike_session_get_sainfo_r (struct ph2handle *iph2) } } return -1; -} \ No newline at end of file +} + +int +ike_session_drop_rekey (ike_session_t *session) +{ + if (session) { + // drop if btmm session is idle) { + if (session->is_btmm_ipsec && + session->last_time_data_sc_detected && + session->traffic_monitor.interv_mon && + session->traffic_monitor.interv_idle) { + time_t now = time(NULL); + + if ((now - session->last_time_data_sc_detected) > (session->traffic_monitor.interv_mon << 1)) { + plog(LLV_DEBUG2, LOCATION, NULL, "session is idle: drop rekey.\n"); + return 1; + } + } + } + return 0; +} + +void +ike_session_ph2_retransmits (struct ph2handle *iph2) +{ + int num_retransmits; + + if (!iph2->is_dying && + iph2->is_rekey && + iph2->ph1 && + iph2->ph1->sce_rekey && !iph2->ph1->sce_rekey->dead && + iph2->parent_session && + !iph2->parent_session->is_cisco_ipsec && /* not for Cisco */ + iph2->parent_session->is_client) { + num_retransmits = iph2->ph1->rmconf->retry_counter - iph2->retry_counter; + if (num_retransmits == 3) { + /* + * phase2 negotiation is stalling on retransmits, inspite of a valid ph1. + * one of the following is possible: + * - (0) severe packet loss. + * - (1) the peer is dead. + * - (2) the peer is out of sync hence dropping this phase2 rekey (and perhaps responding with insecure + * invalid-cookie notifications... but those are untrusted and so we can't rekey phase1 off that) + * (2.1) the peer rebooted (or process restarted) and is now alive. + * (2.2) the peer has deleted phase1 without notifying us (or the notification got dropped somehow). + * (2.3) the peer has a policy/bug stopping this phase2 rekey + * + * in all these cases, one sure way to know is to trigger a phase1 rekey early. + */ + plog(LLV_DEBUG2, LOCATION, NULL, "many phase2 retransmits: try phase1 rekey and this phase2 to quit earlier.\n"); + isakmp_ph1rekeyexpire(iph2->ph1, TRUE); + iph2->retry_counter = 0; + } + } +} diff --git a/ipsec-tools/racoon/ike_session.h b/ipsec-tools/racoon/ike_session.h index e840c37..4d4854c 100644 --- a/ipsec-tools/racoon/ike_session.h +++ b/ipsec-tools/racoon/ike_session.h @@ -96,6 +96,7 @@ struct ike_session { int i_sent_data_sc_dpd:1; int i_sent_data_sc_idle:1; int is_client:1; + time_t last_time_data_sc_detected; u_int32_t natt_flags; char *term_reason; @@ -152,5 +153,7 @@ extern int ike_session_is_client_ph1_rekey __P((struct ph1handle extern void ike_session_start_xauth_timer __P((struct ph1handle *)); extern void ike_session_stop_xauth_timer __P((struct ph1handle *)); extern int ike_session_get_sainfo_r __P((struct ph2handle *)); +extern int ike_session_drop_rekey __P((ike_session_t *)); +extern void ike_session_ph2_retransmits __P((struct ph2handle *)); #endif /* _IKE_SESSION_H */ diff --git a/ipsec-tools/racoon/isakmp.c b/ipsec-tools/racoon/isakmp.c index 7bcf121..f499850 100644 --- a/ipsec-tools/racoon/isakmp.c +++ b/ipsec-tools/racoon/isakmp.c @@ -2317,6 +2317,8 @@ isakmp_ph2resend(iph2) isakmp_pindex(&iph2->ph1->index, iph2->msgid)); EVT_PUSH(iph2->src, iph2->dst, EVTT_PEER_NO_RESPONSE, NULL); return -1; + } else { + ike_session_ph2_retransmits(iph2); } if (isakmp_send(iph2->ph1, iph2->sendbuf) < 0){ @@ -2412,12 +2414,13 @@ isakmp_ph1rekeyexpire_stub(p) void *p; { - isakmp_ph1rekeyexpire((struct ph1handle *)p); + isakmp_ph1rekeyexpire((struct ph1handle *)p, FALSE); } void -isakmp_ph1rekeyexpire(iph1) +isakmp_ph1rekeyexpire(iph1, ignore_sess_drop_policy) struct ph1handle *iph1; +int ignore_sess_drop_policy; { char *src, *dst; struct remoteconf *rmconf; @@ -2443,6 +2446,10 @@ struct ph1handle *iph1; racoon_free(src); racoon_free(dst); + if (!ignore_sess_drop_policy && ike_session_drop_rekey(iph1->parent_session)) { + return; + } + // exit if there is another ph1 that is established (with a pending rekey timer) if (ike_session_has_other_established_ph1(iph1->parent_session, iph1)) { plog(LLV_INFO, LOCATION, iph1->remote, diff --git a/ipsec-tools/racoon/isakmp_inf.c b/ipsec-tools/racoon/isakmp_inf.c index 9ed13ef..44fa30f 100644 --- a/ipsec-tools/racoon/isakmp_inf.c +++ b/ipsec-tools/racoon/isakmp_inf.c @@ -635,7 +635,7 @@ isakmp_info_recv_d(iph1, delete, msgid, encrypted) del_ph1->parent_session && del_ph1->parent_session->is_client && del_ph1->parent_session->established) { - isakmp_ph1rekeyexpire(del_ph1); + isakmp_ph1rekeyexpire(del_ph1, FALSE); } EVT_PUSH(del_ph1->local, del_ph1->remote, @@ -658,7 +658,11 @@ isakmp_info_recv_d(iph1, delete, msgid, encrypted) address = ((struct sockaddr_in *)(iph1->remote))->sin_addr.s_addr; else address = 0; - vpncontrol_notify_ike_failed(VPNCTL_NTYPE_PH1_DELETE, FROM_REMOTE, address, 0, NULL); + if (iph1->cert && IS_CERT_STATUS_ERROR(iph1->cert->status)) { + vpncontrol_notify_ike_failed(VPNCTL_NTYPE_PH1_DELETE_CERT_ERROR + iph1->cert->status, FROM_REMOTE, address, 0, NULL); + } else { + vpncontrol_notify_ike_failed(VPNCTL_NTYPE_PH1_DELETE, FROM_REMOTE, address, 0, NULL); + } } #endif isakmp_ph1expire(del_ph1); diff --git a/ipsec-tools/racoon/isakmp_var.h b/ipsec-tools/racoon/isakmp_var.h index d6dc017..a3edc8b 100644 --- a/ipsec-tools/racoon/isakmp_var.h +++ b/ipsec-tools/racoon/isakmp_var.h @@ -89,7 +89,7 @@ extern int isakmp_ph2resend __P((struct ph2handle *)); extern void isakmp_ph1expire_stub __P((void *)); extern void isakmp_ph1expire __P((struct ph1handle *)); extern void isakmp_ph1rekeyexpire_stub __P((void *)); -extern void isakmp_ph1rekeyexpire __P((struct ph1handle *)); +extern void isakmp_ph1rekeyexpire __P((struct ph1handle *, int)); extern int isakmp_ph1rekeyretry __P((struct ph1handle *)); extern void isakmp_ph1delete_stub __P((void *)); extern void isakmp_ph1delete __P((struct ph1handle *)); diff --git a/ipsec-tools/racoon/oakley.c b/ipsec-tools/racoon/oakley.c index 139c3db..0fad2e6 100644 --- a/ipsec-tools/racoon/oakley.c +++ b/ipsec-tools/racoon/oakley.c @@ -102,6 +102,7 @@ #include #endif #include "remoteconf.h" +#include "vpn_control.h" #ifdef HAVE_GSSAPI #include "gssapi.h" @@ -1520,7 +1521,7 @@ oakley_validate_auth(iph1) } else hostname = CFStringCreateWithBytes(NULL, (u_int8_t *)id_spec->id->v, id_spec->id->l, kCFStringEncodingUTF8, FALSE); } - error = crypto_cssm_check_x509cert(&iph1->cert_p->cert, hostname); + error = crypto_cssm_check_x509cert(&iph1->cert_p->cert, hostname, iph1->cert_p->status); if (hostname) CFRelease(hostname); } @@ -1528,7 +1529,7 @@ oakley_validate_auth(iph1) #else /* TARGET_OS_EMBEDDED */ #ifdef __APPLE__ if (iph1->rmconf->cert_verification == VERIFICATION_MODULE_SEC_FRAMEWORK) - error = crypto_cssm_check_x509cert(&iph1->cert_p->cert, NULL); + error = crypto_cssm_check_x509cert(&iph1->cert_p->cert, NULL, iph1->cert_p->status); else #endif /* __APPLE__ */ { @@ -1728,11 +1729,27 @@ int oakley_getmycert(iph1) struct ph1handle *iph1; { + int err; + u_int32_t address; + switch (iph1->rmconf->certtype) { case ISAKMP_CERT_X509SIGN: if (iph1->cert) return 0; - return get_cert_fromlocal(iph1, 1); +/* only do the local cert test on the phone */ + { + if ( !(err = get_cert_fromlocal(iph1, 1))){ + if ( iph1->cert->status == CERT_STATUS_EXPIRED || iph1->cert->status == CERT_STATUS_PREMATURE){ + if (iph1->remote->sa_family == AF_INET) + address = ((struct sockaddr_in *)(iph1->remote))->sin_addr.s_addr; + else + address = 0; + vpncontrol_notify_ike_failed(VPNCTL_NTYPE_PH1_DELETE_CERT_ERROR + iph1->cert->status, FROM_LOCAL, address, 0, NULL); + return -1; + } + } + } + return err; case ISAKMP_CERT_PLAINRSA: if (iph1->rsa) @@ -1764,6 +1781,7 @@ get_cert_fromlocal(iph1, my) cert_t **certpl; char *certfile; int error = -1; + cert_status_t status = CERT_STATUS_OK; if (my) { certfile = iph1->rmconf->mycertfile; @@ -1790,7 +1808,8 @@ get_cert_fromlocal(iph1, my) if (iph1->rmconf->keychainCertRef == NULL || base64toCFData(iph1->rmconf->keychainCertRef, &dataRef)) goto end; - cert = crypto_cssm_get_x509cert(dataRef); + cert = crypto_cssm_get_x509cert(dataRef, &status); + plog(LLV_DEBUG, LOCATION, NULL, "done with chking cert status %d\n",status); CFRelease(dataRef); break; } // else fall thru @@ -1838,6 +1857,7 @@ get_cert_fromlocal(iph1, my) memcpy((*certpl)->pl->v + 1, cert->v, cert->l); (*certpl)->pl->v[0] = iph1->rmconf->certtype; (*certpl)->type = iph1->rmconf->certtype; + (*certpl)->status = status; (*certpl)->cert.v = (*certpl)->pl->v + 1; (*certpl)->cert.l = (*certpl)->pl->l - 1; diff --git a/ipsec-tools/racoon/oakley.h b/ipsec-tools/racoon/oakley.h index 5916b16..7b0a601 100644 --- a/ipsec-tools/racoon/oakley.h +++ b/ipsec-tools/racoon/oakley.h @@ -162,11 +162,21 @@ struct dhgroup { vchar_t *order; }; +typedef enum cert_status { + CERT_STATUS_OK = 0, + CERT_STATUS_PREMATURE, + CERT_STATUS_EXPIRED, + CERT_STATUS_INVALID, +} cert_status_t; + +#define IS_CERT_STATUS_ERROR(status) (status > CERT_STATUS_OK && status < CERT_STATUS_INVALID) + /* certificate holder */ typedef struct cert_t_tag { u_int8_t type; /* type of CERT, must be same to pl->v[0]*/ vchar_t cert; /* pointer to the CERT */ vchar_t *pl; /* CERT payload minus isakmp general header */ + cert_status_t status; } cert_t; struct ph1handle; diff --git a/ipsec-tools/racoon/pfkey_racoon.c b/ipsec-tools/racoon/pfkey_racoon.c index 390cb19..4ff5db3 100644 --- a/ipsec-tools/racoon/pfkey_racoon.c +++ b/ipsec-tools/racoon/pfkey_racoon.c @@ -1413,7 +1413,8 @@ pk_recvupdate(mhp) #endif /* count up */ - iph2->ph1->ph2cnt++; + if (iph2->ph1) + iph2->ph1->ph2cnt++; /* turn off schedule */ if (iph2->scr) @@ -1831,7 +1832,8 @@ pk_recvexpire(mhp) /* INITIATOR, begin phase 2 exchange only if there's no other established ph2. */ /* allocate buffer for status management of pfkey message */ if (iph2->side == INITIATOR && - !ike_session_has_other_established_ph2(iph2->parent_session, iph2)) { + !ike_session_has_other_established_ph2(iph2->parent_session, iph2) && + !ike_session_drop_rekey(iph2->parent_session)) { initph2(iph2); diff --git a/ipsec-tools/racoon/vpn_control.h b/ipsec-tools/racoon/vpn_control.h index fd545d8..7f52515 100644 --- a/ipsec-tools/racoon/vpn_control.h +++ b/ipsec-tools/racoon/vpn_control.h @@ -290,6 +290,9 @@ struct vpnctl_cmd_start_dpd { #define VPNCTL_NTYPE_PEER_DEAD 50001 /* detected by DPD */ #define VPNCTL_NTYPE_PH1_DELETE 50002 /* received a delete payload leaving no PH1 SA for the remote address */ #define VPNCTL_NTYPE_IDLE_TIMEOUT 50003 +#define VPNCTL_NTYPE_PH1_DELETE_CERT_ERROR VPNCTL_NTYPE_IDLE_TIMEOUT /* used for offsetting cert errors */ +#define VPNCTL_NTYPE_PH1_DELETE_CERT_PREMATURE 50004 /* received a delete payload & there was a cert verification error leaving no PH1 SA for the remote address */ +#define VPNCTL_NTYPE_PH1_DELETE_CERT_EXPIRED 50005 /* received a delete payload & there was a cert verification error leaving no PH1 SA for the remote address */ #define VPNCTL_NTYPE_INTERNAL_ERROR -1 -- 2.45.2