2 * Copyright (c) 2006,2010,2012,2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 #include <Security/SecTrust.h>
27 #include <Security/SecKeychain.h>
28 #include <Security/SecPolicy.h>
29 #include <Security/SecPolicySearch.h>
30 #include <Security/cssmapple.h>
31 #include <Security/oidsalg.h>
34 #include "trusted_cert_utils.h"
37 * Read file as a cert, add to a CFArray, creating the array if necessary
39 static int addCertFile(
41 CFMutableArrayRef
*array
)
43 SecCertificateRef certRef
;
45 if(readCertFile(fileName
, &certRef
)) {
49 *array
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
51 CFArrayAppendValue(*array
, certRef
);
57 verify_cert(int argc
, char * const *argv
)
63 CFMutableArrayRef certs
= NULL
;
64 CFMutableArrayRef roots
= NULL
;
65 CFMutableArrayRef keychains
= NULL
;
66 const CSSM_OID
*policy
= &CSSMOID_APPLE_X509_BASIC
;
67 SecKeychainRef kcRef
= NULL
;
70 SecPolicyRef policyRef
= NULL
;
71 SecTrustRef trustRef
= NULL
;
72 SecPolicySearchRef searchRef
= NULL
;
73 const char *emailAddrs
= NULL
;
74 const char *sslHost
= NULL
;
75 CSSM_APPLE_TP_SSL_OPTIONS sslOpts
;
76 CSSM_APPLE_TP_SMIME_OPTIONS smimeOpts
;
77 CSSM_APPLE_TP_ACTION_FLAGS actionFlags
= 0;
78 bool forceActionFlags
= false;
79 CSSM_APPLE_TP_ACTION_DATA actionData
;
81 CFDataRef cfActionData
= NULL
;
82 SecTrustResultType resultType
;
86 return 2; /* @@@ Return 2 triggers usage message. */
88 /* permit network cert fetch unless explicitly turned off with '-L' */
89 actionFlags
|= CSSM_TP_ACTION_FETCH_CERT_FROM_NET
;
91 while ((arg
= getopt(argc
, argv
, "c:r:p:k:e:s:Llnq")) != -1) {
94 /* this can be specified multiple times */
95 if(addCertFile(optarg
, &certs
)) {
101 /* this can be specified multiple times */
102 if(addCertFile(optarg
, &roots
)) {
108 policy
= policyStringToOid(optarg
);
115 ortn
= SecKeychainOpen(optarg
, &kcRef
);
117 cssmPerror("SecKeychainOpen", ortn
);
121 /* this can be specified multiple times */
122 if(keychains
== NULL
) {
123 keychains
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
125 CFArrayAppendValue(keychains
, kcRef
);
129 actionFlags
&= ~CSSM_TP_ACTION_FETCH_CERT_FROM_NET
;
130 forceActionFlags
= true;
133 actionFlags
|= CSSM_TP_ACTION_LEAF_IS_CA
;
136 /* No keychains, signalled by empty keychain array */
137 if(keychains
!= NULL
) {
138 fprintf(stderr
, "-k and -n are mutually exclusive\n");
142 keychains
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
165 fprintf(stderr
, "***No certs specified.\n");
169 if(CFArrayGetCount(roots
) != 1) {
170 fprintf(stderr
, "***Multiple roots and no certs not allowed.\n");
175 /* no certs and one root: verify the root */
176 certs
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
177 CFArrayAppendValue(certs
, CFArrayGetValueAtIndex(roots
, 0));
178 actionFlags
|= CSSM_TP_ACTION_LEAF_IS_CA
;
181 /* cook up a SecPolicyRef */
182 ortn
= SecPolicySearchCreate(CSSM_CERT_X_509v3
,
187 cssmPerror("SecPolicySearchCreate", ortn
);
191 ortn
= SecPolicySearchCopyNext(searchRef
, &policyRef
);
193 cssmPerror("SecPolicySearchCopyNext", ortn
);
198 /* per-policy options */
199 if(compareOids(policy
, &CSSMOID_APPLE_TP_SSL
) || compareOids(policy
, &CSSMOID_APPLE_TP_APPLEID_SHARING
)) {
200 if(sslHost
!= NULL
) {
201 memset(&sslOpts
, 0, sizeof(sslOpts
));
202 sslOpts
.Version
= CSSM_APPLE_TP_SSL_OPTS_VERSION
;
203 sslOpts
.ServerName
= sslHost
;
204 sslOpts
.ServerNameLen
= strlen(sslHost
);
205 optionData
.Data
= (uint8
*)&sslOpts
;
206 optionData
.Length
= sizeof(sslOpts
);
207 ortn
= SecPolicySetValue(policyRef
, &optionData
);
209 cssmPerror("SecPolicySetValue", ortn
);
215 if(compareOids(policy
, &CSSMOID_APPLE_TP_SMIME
)) {
216 if(emailAddrs
!= NULL
) {
217 memset(&smimeOpts
, 0, sizeof(smimeOpts
));
218 smimeOpts
.Version
= CSSM_APPLE_TP_SMIME_OPTS_VERSION
;
219 smimeOpts
.SenderEmail
= emailAddrs
;
220 smimeOpts
.SenderEmailLen
= strlen(emailAddrs
);
221 optionData
.Data
= (uint8
*)&smimeOpts
;
222 optionData
.Length
= sizeof(smimeOpts
);
223 ortn
= SecPolicySetValue(policyRef
, &optionData
);
225 cssmPerror("SecPolicySetValue", ortn
);
232 /* Now create a SecTrustRef and set its options */
233 ortn
= SecTrustCreateWithCertificates(certs
, policyRef
, &trustRef
);
235 cssmPerror("SecTrustCreateWithCertificates", ortn
);
240 /* roots (anchors) are optional */
242 ortn
= SecTrustSetAnchorCertificates(trustRef
, roots
);
244 cssmPerror("SecTrustSetAnchorCertificates", ortn
);
249 if(actionFlags
|| forceActionFlags
) {
250 memset(&actionData
, 0, sizeof(actionData
));
251 actionData
.Version
= CSSM_APPLE_TP_ACTION_VERSION
;
252 actionData
.ActionFlags
= actionFlags
;
253 cfActionData
= CFDataCreate(NULL
, (UInt8
*)&actionData
, sizeof(actionData
));
254 ortn
= SecTrustSetParameters(trustRef
, CSSM_TP_ACTION_DEFAULT
, cfActionData
);
256 cssmPerror("SecTrustSetParameters", ortn
);
262 ortn
= SecTrustSetKeychains(trustRef
, keychains
);
264 cssmPerror("SecTrustSetKeychains", ortn
);
271 ortn
= SecTrustEvaluate(trustRef
, &resultType
);
273 /* should never fail - error on this doesn't mean the cert verified badly */
274 cssmPerror("SecTrustEvaluate", ortn
);
279 case kSecTrustResultUnspecified
:
280 /* cert chain valid, no special UserTrust assignments */
281 case kSecTrustResultProceed
:
282 /* cert chain valid AND user explicitly trusts this */
284 case kSecTrustResultDeny
:
286 fprintf(stderr
, "SecTrustEvaluate result: kSecTrustResultDeny\n");
290 case kSecTrustResultConfirm
:
292 * Cert chain may well have verified OK, but user has flagged
293 * one of these certs as untrustable.
296 fprintf(stderr
, "SecTrustEvaluate result: kSecTrustResultConfirm\n");
303 /* See what the TP had to say about this */
304 ortn
= SecTrustGetCssmResultCode(trustRef
, &ocrtn
);
306 cssmPerror("SecTrustGetCssmResultCode", ortn
);
309 cssmPerror("Cert Verify Result", ocrtn
);
315 if((ourRtn
== 0) & !quiet
) {
316 printf("...certificate verification successful.\n");
322 CFRELEASE(keychains
);
323 CFRELEASE(policyRef
);
325 CFRELEASE(searchRef
);
326 CFRELEASE(cfActionData
);