X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/fa7225c82381bac4432a6edf16f53b5370238d85..866f8763175ff60e4fa455b92b5eb660a12fe6c7:/SecurityTool/verify_cert.c?ds=sidebyside diff --git a/SecurityTool/verify_cert.c b/SecurityTool/verify_cert.c index 544e62cd..ae3c72e5 100644 --- a/SecurityTool/verify_cert.c +++ b/SecurityTool/verify_cert.c @@ -1,15 +1,15 @@ /* - * Copyright (c) 2006,2010,2012,2014 Apple Inc. All Rights Reserved. + * Copyright (c) 2006,2010,2012,2014-2017 Apple Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -17,7 +17,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_LICENSE_HEADER_END@ * * verify_cert.c @@ -35,6 +35,7 @@ #include #include "trusted_cert_utils.h" #include "verify_cert.h" +#include /* * Read file as a cert, add to a CFArray, creating the array if necessary @@ -66,15 +67,19 @@ verify_cert(int argc, char * const *argv) CFMutableArrayRef certs = NULL; CFMutableArrayRef roots = NULL; CFMutableArrayRef keychains = NULL; + CFMutableArrayRef policies = NULL; const CSSM_OID *policy = &CSSMOID_APPLE_X509_BASIC; SecKeychainRef kcRef = NULL; int ourRtn = 0; bool quiet = false; + bool client = false; SecPolicyRef policyRef = NULL; + SecPolicyRef revPolicyRef = NULL; SecTrustRef trustRef = NULL; SecPolicySearchRef searchRef = NULL; const char *emailAddrs = NULL; const char *sslHost = NULL; + const char *name = NULL; CSSM_APPLE_TP_SSL_OPTIONS sslOpts; CSSM_APPLE_TP_SMIME_OPTIONS smimeOpts; CSSM_APPLE_TP_ACTION_FLAGS actionFlags = 0; @@ -84,9 +89,10 @@ verify_cert(int argc, char * const *argv) CFDataRef cfActionData = NULL; SecTrustResultType resultType; OSStatus ocrtn; - struct tm time; - CFGregorianDate gregorianDate; - CFDateRef dateRef = NULL; + struct tm time; + CFGregorianDate gregorianDate; + CFDateRef dateRef = NULL; + CFOptionFlags revOptions = 0; if(argc < 2) { return 2; /* @@@ Return 2 triggers usage message. */ @@ -94,8 +100,11 @@ verify_cert(int argc, char * const *argv) /* permit network cert fetch unless explicitly turned off with '-L' */ actionFlags |= CSSM_TP_ACTION_FETCH_CERT_FROM_NET; optind = 1; - while ((arg = getopt(argc, argv, "c:r:p:k:e:s:d:Llnq")) != -1) { + while ((arg = getopt(argc, argv, "Cc:r:p:k:e:s:d:LlNnqR:")) != -1) { switch (arg) { + case 'C': + client = true; + break; case 'c': /* this can be specified multiple times */ if(addCertFile(optarg, &certs)) { @@ -138,10 +147,21 @@ verify_cert(int argc, char * const *argv) case 'l': actionFlags |= CSSM_TP_ACTION_LEAF_IS_CA; break; - case 'n': + case 'n': { + /* Legacy macOS used 'n' as the "no keychain search list" flag. + iOS interprets it as the name option, with one argument. + */ + char *o = argv[optind]; + if (o && o[0] != '-') { + name = optarg; + ++optind; + break; + } + } /* intentional fall-through to "no keychains" case, if no arg */ + case 'N': /* No keychains, signalled by empty keychain array */ if(keychains != NULL) { - fprintf(stderr, "-k and -n are mutually exclusive\n"); + fprintf(stderr, "-k and -%c are mutually exclusive\n", arg); ourRtn = 2; goto errOut; } @@ -156,27 +176,29 @@ verify_cert(int argc, char * const *argv) case 'q': quiet = true; break; - case 'd': - memset(&time, 0, sizeof(struct tm)); - if (strptime(optarg, "%Y-%m-%d-%H:%M:%S", &time) == NULL) { - if (strptime(optarg, "%Y-%m-%d", &time) == NULL) { - fprintf(stderr, "Date processing error\n"); - ourRtn = 2; - goto errOut; - } - } - - gregorianDate.second = time.tm_sec; - gregorianDate.minute = time.tm_min; - gregorianDate.hour = time.tm_hour; - gregorianDate.day = time.tm_mday; - gregorianDate.month = time.tm_mon + 1; - gregorianDate.year = time.tm_year + 1900; - - if (dateRef == NULL) { - dateRef = CFDateCreate(NULL, CFGregorianDateGetAbsoluteTime(gregorianDate, NULL)); - } - break; + case 'd': + memset(&time, 0, sizeof(struct tm)); + if (strptime(optarg, "%Y-%m-%d-%H:%M:%S", &time) == NULL) { + if (strptime(optarg, "%Y-%m-%d", &time) == NULL) { + fprintf(stderr, "Date processing error\n"); + ourRtn = 2; + goto errOut; + } + } + gregorianDate.second = time.tm_sec; + gregorianDate.minute = time.tm_min; + gregorianDate.hour = time.tm_hour; + gregorianDate.day = time.tm_mday; + gregorianDate.month = time.tm_mon + 1; + gregorianDate.year = time.tm_year + 1900; + + if (dateRef == NULL) { + dateRef = CFDateCreate(NULL, CFGregorianDateGetAbsoluteTime(gregorianDate, NULL)); + } + break; + case 'R': + revOptions |= revCheckOptionStringToFlags(optarg); + break; default: ourRtn = 2; goto errOut; @@ -224,11 +246,13 @@ verify_cert(int argc, char * const *argv) /* per-policy options */ if(compareOids(policy, &CSSMOID_APPLE_TP_SSL) || compareOids(policy, &CSSMOID_APPLE_TP_APPLEID_SHARING)) { - if(sslHost != NULL) { + const char *nameStr = (name) ? name : ((sslHost) ? sslHost : NULL); + if(nameStr) { memset(&sslOpts, 0, sizeof(sslOpts)); sslOpts.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION; - sslOpts.ServerName = sslHost; - sslOpts.ServerNameLen = (uint32) strlen(sslHost); + sslOpts.ServerName = nameStr; + sslOpts.ServerNameLen = (uint32) strlen(nameStr); + sslOpts.Flags = (client) ? CSSM_APPLE_TP_SSL_CLIENT : 0; optionData.Data = (uint8 *)&sslOpts; optionData.Length = sizeof(sslOpts); ortn = SecPolicySetValue(policyRef, &optionData); @@ -240,11 +264,12 @@ verify_cert(int argc, char * const *argv) } } if(compareOids(policy, &CSSMOID_APPLE_TP_SMIME)) { - if(emailAddrs != NULL) { + const char *nameStr = (name) ? name : ((emailAddrs) ? emailAddrs : NULL); + if(nameStr) { memset(&smimeOpts, 0, sizeof(smimeOpts)); smimeOpts.Version = CSSM_APPLE_TP_SMIME_OPTS_VERSION; - smimeOpts.SenderEmail = emailAddrs; - smimeOpts.SenderEmailLen = (uint32) strlen(emailAddrs); + smimeOpts.SenderEmail = nameStr; + smimeOpts.SenderEmailLen = (uint32) strlen(nameStr); optionData.Data = (uint8 *)&smimeOpts; optionData.Length = sizeof(smimeOpts); ortn = SecPolicySetValue(policyRef, &optionData); @@ -256,8 +281,17 @@ verify_cert(int argc, char * const *argv) } } - /* Now create a SecTrustRef and set its options */ - ortn = SecTrustCreateWithCertificates(certs, policyRef, &trustRef); + /* create policies array */ + policies = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(policies, policyRef); + /* add optional SecPolicyRef for revocation, if specified */ + if(revOptions != 0) { + revPolicyRef = SecPolicyCreateRevocation(revOptions); + CFArrayAppendValue(policies, revPolicyRef); + } + + /* create trust reference from certs and policies */ + ortn = SecTrustCreateWithCertificates(certs, policies, &trustRef); if(ortn) { cssmPerror("SecTrustCreateWithCertificates", ortn); ourRtn = 1; @@ -293,14 +327,14 @@ verify_cert(int argc, char * const *argv) goto errOut; } } - if(dateRef != NULL) { - ortn = SecTrustSetVerifyDate(trustRef, dateRef); - if(ortn) { - cssmPerror("SecTrustSetVerifyDate", ortn); - ourRtn = 1; - goto errOut; - } - } + if(dateRef != NULL) { + ortn = SecTrustSetVerifyDate(trustRef, dateRef); + if(ortn) { + cssmPerror("SecTrustSetVerifyDate", ortn); + ourRtn = 1; + goto errOut; + } + } /* GO */ ortn = SecTrustEvaluate(trustRef, &resultType); @@ -322,16 +356,6 @@ verify_cert(int argc, char * const *argv) } ourRtn = 1; break; - case kSecTrustResultConfirm: - /* - * Cert chain may well have verified OK, but user has flagged - * one of these certs as untrustable. - */ - if(!quiet) { - fprintf(stderr, "SecTrustEvaluate result: kSecTrustResultConfirm\n"); - } - ourRtn = 1; - break; default: ourRtn = 1; if(!quiet) { @@ -351,10 +375,13 @@ verify_cert(int argc, char * const *argv) printf("...certificate verification successful.\n"); } errOut: + CFReleaseNull(dateRef); /* cleanup */ CFRELEASE(certs); CFRELEASE(roots); CFRELEASE(keychains); + CFRELEASE(policies); + CFRELEASE(revPolicyRef); CFRELEASE(policyRef); CFRELEASE(trustRef); CFRELEASE(searchRef);