]> git.saurik.com Git - apple/security.git/blame - sec/Security/Tool/show_certificates.c
Security-55471.14.18.tar.gz
[apple/security.git] / sec / Security / Tool / show_certificates.c
CommitLineData
427c49bc
A
1/*
2 * Copyright (c) 2003-2007,2009-2010 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 * keychain_find.c
24 */
25
26#include <TargetConditionals.h>
27#if TARGET_OS_EMBEDDED
28
29#include "SecurityCommands.h"
30
31#include "security.h"
32#include "SecurityTool/print_cert.h"
33#include "SecBase64.h"
34#include <errno.h>
35#include <fcntl.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <sys/types.h>
40#include <unistd.h>
41
42#include <SecurityTool/tool_errors.h>
43
44#include <Security/SecItem.h>
45
46#include <CoreFoundation/CFArray.h>
47#include <CoreFoundation/CFDate.h>
48#include <CoreFoundation/CFNumber.h>
49#include <CoreFoundation/CFString.h>
50
51#include <Security/SecCertificatePriv.h>
52#include <Security/SecPolicyPriv.h>
53#include <Security/SecTrustPriv.h>
54#include <Security/SecInternal.h>
55
56#include <SecurityTool/readline.h>
57
58#include <utilities/SecCFWrappers.h>
59
60typedef uint32_t SecProtocolType;
61typedef uint32_t SecAuthenticationType;
62
63static void
64keychain_query_parse_string(CFMutableDictionaryRef q, CFStringRef s) {
65 bool inkey = true;
66 bool escaped = false;
67 CFStringRef key = NULL;
68 CFMutableStringRef str = CFStringCreateMutable(0, 0);
69 CFRange rng = { .location = 0, .length = CFStringGetLength(s) };
70 CFCharacterSetRef cs_key = CFCharacterSetCreateWithCharactersInString(0, CFSTR("=\\"));
71 CFCharacterSetRef cs_value = CFCharacterSetCreateWithCharactersInString(0, CFSTR(",\\"));
72 while (rng.length) {
73 CFRange r;
74 CFStringRef sub;
75 bool complete = false;
76 if (escaped) {
77 r.location = rng.location;
78 r.length = 1;
79 sub = CFStringCreateWithSubstring(0, s, r);
80 escaped = false;
81 } else if (CFStringFindCharacterFromSet(s, inkey ? cs_key : cs_value, rng, 0, &r)) {
82 if (CFStringGetCharacterAtIndex(s, r.location) == '\\') {
83 escaped = true;
84 } else {
85 complete = true;
86 }
87 CFIndex next = r.location + 1;
88 r.length = r.location - rng.location;
89 r.location = rng.location;
90 sub = CFStringCreateWithSubstring(0, s, r);
91 rng.length -= next - rng.location;
92 rng.location = next;
93 } else {
94 sub = CFStringCreateWithSubstring(0, s, rng);
95 rng.location += rng.length;
96 rng.length = 0;
97 complete = true;
98 }
99 CFStringAppend(str, sub);
100 CFRelease(sub);
101 if (complete) {
102 CFStringRef value = CFStringCreateCopy(0, str);
103 CFStringReplaceAll(str, CFSTR(""));
104 if (inkey) {
105 key = value;
106 } else {
107 CFDictionarySetValue(q, key, value);
108 CFReleaseNull(value);
109 CFReleaseNull(key);
110 }
111 inkey = !inkey;
112 }
113 }
114 if (key) {
115 /* Dangeling key value is true?. */
116 CFDictionarySetValue(q, key, kCFBooleanTrue);
117 CFRelease(key);
118 }
119 CFRelease(str);
120}
121
122static void
123keychain_query_parse_cstring(CFMutableDictionaryRef q, const char *query) {
124 CFStringRef s;
125 s = CFStringCreateWithCStringNoCopy(0, query, kCFStringEncodingUTF8, kCFAllocatorNull);
126 keychain_query_parse_string(q, s);
127 CFRelease(s);
128}
129
130static void show_cert_eval(CFArrayRef certs, bool verbose) {
131 SecPolicyRef policy = SecPolicyCreateSSL(true, NULL);
132 SecTrustRef trust = NULL;
133 OSStatus status = SecTrustCreateWithCertificates(certs, policy, &trust);
134 SecTrustResultType trustResult;
135 const char *trustResults[] = {
136 "invalid",
137 "proceed",
138 "confirm",
139 "deny",
140 "unspecified",
141 "recoverable trust failure",
142 "fatal trust failure",
143 "other error",
144 };
145 status = SecTrustEvaluate(trust, &trustResult);
146 printf("* trust: %s *\n", trustResults[trustResult]);
147 CFArrayRef properties = SecTrustCopyProperties(trust);
148 print_plist(properties);
149 CFReleaseNull(properties);
150 CFIndex ix, count = SecTrustGetCertificateCount(trust);
151 for (ix = 0; ix < count; ++ix) {
152 printf("* cert %ld summary properties *\n", ix);
153 properties = SecTrustCopySummaryPropertiesAtIndex(trust, ix);
154 print_plist(properties);
155 CFReleaseNull(properties);
156 if (verbose) {
157 printf("* cert %ld detail properties *\n", ix);
158 properties = SecTrustCopyDetailedPropertiesAtIndex(trust, ix);
159 print_plist(properties);
160 CFReleaseNull(properties);
161 }
162 }
163
164 CFDictionaryRef info = SecTrustCopyInfo(trust);
165 if (info) {
166 printf("* info *\n");
167 CFShow(info);
168 CFReleaseNull(info);
169 }
170}
171
172static size_t print_buffer_pem(FILE *stream, const char *pem_name, size_t length,
173 const uint8_t *bytes) {
174 size_t pem_name_len = strlen(pem_name);
175 size_t b64_len = SecBase64Encode2(NULL, length, NULL, 0,
176 kSecB64_F_LINE_LEN_USE_PARAM, 64, NULL);
177 char *buffer = malloc(33 + 2 * pem_name_len + b64_len);
178 char *p = buffer;
179 p += sprintf(buffer, "-----BEGIN %s-----\n", pem_name);
180 SecBase64Result result;
181 p += SecBase64Encode2(bytes, length, p, b64_len,\
182 kSecB64_F_LINE_LEN_USE_PARAM, 64, &result);
183 if (result) {
184 free(buffer);
185 return result;
186 }
187 p += sprintf(p, "\n-----END %s-----\n", pem_name);
188 size_t res = fwrite(buffer, 1, p - buffer, stream);
189 fflush(stream);
190 bzero(buffer, p - buffer);
191 free(buffer);
192 return res;
193}
194
195int keychain_show_certificates(int argc, char * const *argv)
196{
197 int ch, result = 0;
198 bool output_subject = false;
199 bool verbose = false;
200 bool trust_eval = false;
201 bool keychain_certs = false;
202 bool output_pem = false;
203 bool output_finger_print = false;
204 CFMutableArrayRef certs = NULL;
205 CFMutableDictionaryRef query = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
206
207 while ((ch = getopt(argc, argv, "kfq:pstv")) != -1)
208 {
209 switch (ch)
210 {
211 case 'k':
212 keychain_certs = true;
213 break;
214 case 'p':
215 output_pem = true;
216 break;
217 case 's':
218 output_subject = true;
219 break;
220 case 'v':
221 verbose = true;
222 break;
223 case 't':
224 trust_eval = true;
225 break;
226 case 'f':
227 output_finger_print = true;
228 break;
229 case 'q':
230 keychain_query_parse_cstring(query, optarg);
231 keychain_certs = true;
232 break;
233 case '?':
234 default:
235 return 2; /* @@@ Return 2 triggers usage message. */
236 }
237 }
238
239 argc -= optind;
240 argv += optind;
241
242 if ((keychain_certs && argc > 0) || (!keychain_certs && argc < 1))
243 result = 2;
244
245 if (trust_eval)
246 certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
247
248 CFArrayRef kc_certs = NULL;
249 int arg;
250 if (keychain_certs) {
251 for (arg = 0; arg < argc; ++arg) {
252 keychain_query_parse_cstring(query, argv[arg]);
253 }
254 CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
255 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll);
256 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
257 CFTypeRef results;
258 if (!SecItemCopyMatching(query, &results)) {
259 kc_certs = results;
260 argc = (int) CFArrayGetCount(kc_certs);
261 }
262 }
263
264 for (arg = 0; arg < argc; ++arg) {
265 SecCertificateRef cert = NULL;
266 if (keychain_certs) {
267 cert = (SecCertificateRef)CFArrayGetValueAtIndex(kc_certs, arg);
268 } else {
269 CFDataRef data = copyFileContents(argv[arg]);
270 if (data) {
271 cert = SecCertificateCreateWithData(
272 kCFAllocatorDefault, data);
273 if (!cert) {
274 /* DER failed, try PEM. */
275 cert = SecCertificateCreateWithPEM(kCFAllocatorDefault, data);
276 }
277 CFRelease(data);
278 } else {
279 result = 1;
280 }
281 }
282
283 if (cert) {
284 if (!keychain_certs) {
285 printf(
286 "*******************************************************\n"
287 "%s\n"
288 "*******************************************************\n"
289 , argv[arg]);
290 }
291 if (trust_eval) {
292 if (keychain_certs) {
293 CFArraySetValueAtIndex(certs, 0, cert);
294 show_cert_eval(certs, verbose);
295 } else {
296 CFArrayAppendValue(certs, cert);
297 }
298 } else {
299 if (verbose) {
300 print_cert(cert, verbose);
301 } else if (output_subject) {
302 CFStringRef subject = SecCertificateCopySubjectString(cert);
303 if (subject) {
304 CFStringWriteToFileWithNewline(subject, stdout);
305 CFRelease(subject);
306 }
307 } else if (!output_pem) {
308 print_cert(cert, verbose);
309 }
310 }
311 if (output_finger_print) {
312 CFDataRef key_fingerprint = SecCertificateCopyPublicKeySHA1Digest(cert);
313 if (key_fingerprint) {
314 int i;
315 CFIndex j = CFDataGetLength(key_fingerprint);
316 const uint8_t *byte = CFDataGetBytePtr(key_fingerprint);
317
318 fprintf(stdout, "Key fingerprint:");
319 for (i = 0; i < j; i++) {
320 fprintf(stdout, " %02X", byte[i]);
321 }
322 fprintf(stdout, "\n");
323 }
324 }
325 if (output_pem) {
326 print_buffer_pem(stdout, "CERTIFICATE",
327 SecCertificateGetLength(cert),
328 SecCertificateGetBytePtr(cert));
329 }
330 if (!keychain_certs) {
331 CFRelease(cert);
332 }
333 } else {
334 result = 1;
335 fprintf(stderr, "file %s: does not contain a valid certificate",
336 argv[arg]);
337 }
338 }
339
340 if (trust_eval && !keychain_certs)
341 show_cert_eval(certs, verbose);
342
343 CFReleaseSafe(kc_certs);
344 CFReleaseSafe(certs);
345
346 return result;
347}
348
349#endif // TARGET_OS_EMBEDDED