1/*
2 * Copyright (c) 2003-2009 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 *
23 * trusted_cert_dump.c
24 */
25
26#include "trusted_cert_dump.h"
27#include "trusted_cert_utils.h"
28
29#include <errno.h>
30#include <unistd.h>
31#include <Security/Security.h>
32#include <Security/cssmapple.h>
33#include <Security/SecTrustSettings.h>
34#include <Security/oidsalg.h>
35#include <security_cdsa_utils/cuFileIo.h>
36#include <CoreFoundation/CoreFoundation.h>
37
38// SecCertificateInferLabel
39#include <Security/SecCertificatePriv.h>
40
41
42/* print cert's label (the one SecCertificate infers) */
43static OSStatus printCertLabel(
44	SecCertificateRef certRef)
45{
46	OSStatus ortn;
47	CFStringRef label;
48
49	ortn = SecCertificateInferLabel(certRef, &label);
50	if(ortn) {
51		cssmPerror("SecCertificateInferLabel", ortn);
52		return ortn;
53	}
54	printCfStr(label);
55	CFRelease(label);
56	return noErr;
57}
58
59/*
60 * Display a Trust Settings array as obtained from
61 * SecTrustSettingsCopyTrustSettings().
62 */
63static int displayTrustSettings(
64	CFArrayRef	trustSettings)
65{
66	/* must always be there though it may be empty */
67	if(trustSettings == NULL) {
68		fprintf(stderr, "***displayTrustSettings: missing trust settings array");
69		return -1;
70	}
71	if(CFGetTypeID(trustSettings) != CFArrayGetTypeID()) {
72		fprintf(stderr, "***displayTrustSettings: malformed trust settings array");
73		return -1;
74	}
75
76	int ourRtn = 0;
77	CFIndex numUseConstraints = CFArrayGetCount(trustSettings);
78	indentIncr();
79	indent(); printf("Number of trust settings : %ld\n", (long)numUseConstraints);
80	OSStatus ortn;
81	SecPolicyRef certPolicy;
82	SecTrustedApplicationRef certApp;
83	CFDictionaryRef ucDict;
84	CFStringRef policyStr;
85	CFNumberRef cfNum;
86	CFIndex ucDex;
87
88	/* grind thru the trust settings dictionaries */
89	for(ucDex=0; ucDex<numUseConstraints; ucDex++) {
90		indent(); printf("Trust Setting %ld:\n", (long)ucDex);
91		indentIncr();
92
93		ucDict = (CFDictionaryRef)CFArrayGetValueAtIndex(trustSettings, ucDex);
94		if(CFGetTypeID(ucDict) != CFDictionaryGetTypeID()) {
95			fprintf(stderr, "***displayTrustSettings: malformed usage constraints dictionary");
96			ourRtn = -1;
97			goto nextAp;
98		}
99
100		/* policy - optional */
101		certPolicy = (SecPolicyRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsPolicy);
102		if(certPolicy != NULL) {
103			if(CFGetTypeID(certPolicy) != SecPolicyGetTypeID()) {
104				fprintf(stderr, "***displayTrustSettings: malformed certPolicy");
105				ourRtn = -1;
106				goto nextAp;
107			}
108			CSSM_OID policyOid;
109			ortn = SecPolicyGetOID(certPolicy, &policyOid);
110			if(ortn) {
111				cssmPerror("SecPolicyGetOID", ortn);
112				ourRtn = -1;
113				goto nextAp;
114			}
115			indent(); printf("Policy OID            : %s\n",
116					oidToOidString(&policyOid));
117		}
118
119		/* app - optional  */
120		certApp = (SecTrustedApplicationRef)CFDictionaryGetValue(ucDict,
121			kSecTrustSettingsApplication);
122		if(certApp != NULL) {
123			if(CFGetTypeID(certApp) != SecTrustedApplicationGetTypeID()) {
124				fprintf(stderr, "***displayTrustSettings: malformed certApp");
125				ourRtn = -1;
126				goto nextAp;
127			}
128			CFDataRef appPath = NULL;
129			ortn = SecTrustedApplicationCopyData(certApp, &appPath);
130			if(ortn) {
131				cssmPerror("SecTrustedApplicationCopyData", ortn);
132				ourRtn = -1;
133				goto nextAp;
134			}
135			indent(); printf("Application           : %s", CFDataGetBytePtr(appPath));
136			printf("\n");
137			CFRelease(appPath);
138		}
139
140		/* policy string */
141		policyStr = (CFStringRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsPolicyString);
142		if(policyStr != NULL) {
143			if(CFGetTypeID(policyStr) != CFStringGetTypeID()) {
144				fprintf(stderr, "***displayTrustSettings: malformed policyStr");
145				ourRtn = -1;
146				goto nextAp;
147			}
148			indent(); printf("Policy String         : ");
149			printCfStr(policyStr); printf("\n");
150		}
151
152		/* Allowed error */
153		cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsAllowedError);
154		if(cfNum != NULL) {
155			if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) {
156				fprintf(stderr, "***displayTrustSettings: malformed allowedError");
157				ourRtn = -1;
158				goto nextAp;
159			}
160			indent(); printf("Allowed Error         : ");
161			printCssmErr(cfNum); printf("\n");
162		}
163
164		/* ResultType */
165		cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsResult);
166		if(cfNum != NULL) {
167			if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) {
168				fprintf(stderr, "***displayTrustSettings: malformed ResultType");
169				ourRtn = -1;
170				goto nextAp;
171			}
172			indent(); printf("Result Type           : ");
173			printResultType(cfNum); printf("\n");
174		}
175
176		/* key usage */
177		cfNum = (CFNumberRef)CFDictionaryGetValue(ucDict, kSecTrustSettingsKeyUsage);
178		if(cfNum != NULL) {
179			if(CFGetTypeID(cfNum) != CFNumberGetTypeID()) {
180				fprintf(stderr, "***displayTrustSettings: malformed keyUsage");
181				ourRtn = -1;
182				goto nextAp;
183			}
184			indent(); printf("Key Usage             : ");
185			printKeyUsage(cfNum); printf("\n");
186		}
187
188	nextAp:
189		indentDecr();
190	}
191	indentDecr();
192	return ourRtn;
193}
194
195int
196trusted_cert_dump(int argc, char * const *argv)
197{
198	CFArrayRef certArray = NULL;
199	OSStatus ortn = noErr;
200	CFIndex numCerts;
201	CFIndex dex;
202	CFArrayRef trustSettings;
203	int ourRtn = 0;
204	SecTrustSettingsDomain domain = kSecTrustSettingsDomainUser;
205
206	extern char *optarg;
207	extern int optind;
208	int arg;
209
210	optind = 1;
211	while ((arg = getopt(argc, argv, "sdh")) != -1) {
212		switch (arg) {
213			case 's':
214				domain = kSecTrustSettingsDomainSystem;
215				break;
216			case 'd':
217				domain = kSecTrustSettingsDomainAdmin;
218				break;
219			default:
220			case 'h':
221				return 2; /* @@@ Return 2 triggers usage message. */
222		}
223	}
224
225	if(optind != argc) {
226		return 2; /* @@@ Return 2 triggers usage message. */
227	}
228
229	ortn = SecTrustSettingsCopyCertificates(domain, &certArray);
230	if(ortn) {
231		cssmPerror("SecTrustSettingsCopyCertificates", ortn);
232		return 1;
233	}
234	numCerts = CFArrayGetCount(certArray);
235	printf("Number of trusted certs = %ld\n", (long)numCerts);
236
237	for(dex=0; dex<numCerts; dex++) {
238		SecCertificateRef certRef =
239				(SecCertificateRef)CFArrayGetValueAtIndex(certArray, dex);
240		if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) {
241			fprintf(stderr, "***Bad CFGetTypeID for cert %ld\n", (long)dex);
242			ourRtn = -1;
243			break;
244		}
245
246		/* always print the cert's label */
247		printf("Cert %ld: ", dex);
248		printCertLabel(certRef);
249		printf("\n");
250
251		/* see if the cert has any usage constraints (it should!) */
252		ortn = SecTrustSettingsCopyTrustSettings(certRef, domain, &trustSettings);
253		if(ortn) {
254			cssmPerror("SecTrustSettingsCopyTrustSettings", ortn);
255			ourRtn = -1;
256			continue;
257		}
258		if(displayTrustSettings(trustSettings)) {
259			ourRtn = -1;
260		}
261	}
262	CFRelease(certArray);
263
264	return ourRtn;
265}
266