]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTool/verify_cert.c
Security-58286.1.32.tar.gz
[apple/security.git] / SecurityTool / verify_cert.c
index 544e62cd761ba29ca11c9f91162986bd47a146b1..ae3c72e5b552a159c959e90bb55007c0a73c68f0 100644 (file)
@@ -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 <time.h>
 #include "trusted_cert_utils.h"
 #include "verify_cert.h"
+#include <utilities/SecCFRelease.h>
 
 /*
  * 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);