1/* 2 * Copyright (c) 2003-2007,2009-2010,2013-2014 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#include "keychain_util.h" 60 61typedef uint32_t SecProtocolType; 62typedef uint32_t SecAuthenticationType; 63 64 65static void show_cert_eval(CFArrayRef certs, bool verbose) { 66 SecPolicyRef policy = SecPolicyCreateSSL(true, NULL); 67 SecTrustRef trust = NULL; 68 SecTrustCreateWithCertificates(certs, policy, &trust); 69 SecTrustResultType trustResult; 70 const char *trustResults[] = { 71 "invalid", 72 "proceed", 73 "confirm", 74 "deny", 75 "unspecified", 76 "recoverable trust failure", 77 "fatal trust failure", 78 "other error", 79 }; 80 (void) SecTrustEvaluate(trust, &trustResult); 81 printf("* trust: %s *\n", trustResults[trustResult]); 82 CFArrayRef properties = SecTrustCopyProperties(trust); 83 print_plist(properties); 84 CFReleaseNull(properties); 85 CFIndex ix, count = SecTrustGetCertificateCount(trust); 86 for (ix = 0; ix < count; ++ix) { 87 printf("* cert %ld summary properties *\n", ix); 88 properties = SecTrustCopySummaryPropertiesAtIndex(trust, ix); 89 print_plist(properties); 90 CFReleaseNull(properties); 91 if (verbose) { 92 printf("* cert %ld detail properties *\n", ix); 93 properties = SecTrustCopyDetailedPropertiesAtIndex(trust, ix); 94 print_plist(properties); 95 CFReleaseNull(properties); 96 } 97 } 98 99 CFDictionaryRef info = SecTrustCopyInfo(trust); 100 if (info) { 101 printf("* info *\n"); 102 CFShow(info); 103 CFReleaseNull(info); 104 } 105} 106 107static size_t print_buffer_pem(FILE *stream, const char *pem_name, size_t length, 108 const uint8_t *bytes) { 109 size_t pem_name_len = strlen(pem_name); 110 size_t b64_len = SecBase64Encode2(NULL, length, NULL, 0, 111 kSecB64_F_LINE_LEN_USE_PARAM, 64, NULL); 112 char *buffer = malloc(33 + 2 * pem_name_len + b64_len); 113 char *p = buffer; 114 p += sprintf(buffer, "-----BEGIN %s-----\n", pem_name); 115 SecBase64Result result; 116 p += SecBase64Encode2(bytes, length, p, b64_len,\ 117 kSecB64_F_LINE_LEN_USE_PARAM, 64, &result); 118 if (result) { 119 free(buffer); 120 return result; 121 } 122 p += sprintf(p, "\n-----END %s-----\n", pem_name); 123 size_t res = fwrite(buffer, 1, p - buffer, stream); 124 fflush(stream); 125 bzero(buffer, p - buffer); 126 free(buffer); 127 return res; 128} 129 130int keychain_show_certificates(int argc, char * const *argv) 131{ 132 int ch, result = 0; 133 bool output_subject = false; 134 bool verbose = false; 135 bool trust_eval = false; 136 bool keychain_certs = false; 137 bool output_pem = false; 138 bool output_finger_print = false; 139 CFMutableArrayRef certs = NULL; 140 CFMutableDictionaryRef query = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 141 142 while ((ch = getopt(argc, argv, "kfq:pstv")) != -1) 143 { 144 switch (ch) 145 { 146 case 'k': 147 keychain_certs = true; 148 break; 149 case 'p': 150 output_pem = true; 151 break; 152 case 's': 153 output_subject = true; 154 break; 155 case 'v': 156 verbose = true; 157 break; 158 case 't': 159 trust_eval = true; 160 break; 161 case 'f': 162 output_finger_print = true; 163 break; 164 case 'q': 165 if (!keychain_query_parse_cstring(query, optarg)) { 166 CFReleaseNull(query); 167 return 1; 168 } 169 keychain_certs = true; 170 break; 171 case '?': 172 default: 173 return 2; /* @@@ Return 2 triggers usage message. */ 174 } 175 } 176 177 argc -= optind; 178 argv += optind; 179 180 if ((keychain_certs && argc > 0) || (!keychain_certs && argc < 1)) 181 result = 2; 182 183 if (trust_eval) 184 certs = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); 185 186 CFArrayRef kc_certs = NULL; 187 int arg; 188 if (keychain_certs) { 189 for (arg = 0; arg < argc; ++arg) { 190 if (!keychain_query_parse_cstring(query, argv[arg])) { 191 CFReleaseSafe(query); 192 CFReleaseSafe(certs); 193 return 1; 194 } 195 } 196 CFDictionarySetValue(query, kSecClass, kSecClassCertificate); 197 CFDictionarySetValue(query, kSecMatchLimit, kSecMatchLimitAll); 198 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); 199 CFTypeRef results; 200 if (!SecItemCopyMatching(query, &results)) { 201 kc_certs = results; 202 argc = (int) CFArrayGetCount(kc_certs); 203 } 204 } 205 206 for (arg = 0; arg < argc; ++arg) { 207 SecCertificateRef cert = NULL; 208 if (keychain_certs) { 209 cert = (SecCertificateRef)CFArrayGetValueAtIndex(kc_certs, arg); 210 } else { 211 CFDataRef data = copyFileContents(argv[arg]); 212 if (data) { 213 cert = SecCertificateCreateWithData( 214 kCFAllocatorDefault, data); 215 if (!cert) { 216 /* DER failed, try PEM. */ 217 cert = SecCertificateCreateWithPEM(kCFAllocatorDefault, data); 218 } 219 CFRelease(data); 220 } else { 221 result = 1; 222 } 223 } 224 225 if (cert) { 226 if (!keychain_certs) { 227 printf( 228 "*******************************************************\n" 229 "%s\n" 230 "*******************************************************\n" 231 , argv[arg]); 232 } 233 if (trust_eval) { 234 if (keychain_certs) { 235 CFArraySetValueAtIndex(certs, 0, cert); 236 show_cert_eval(certs, verbose); 237 } else { 238 CFArrayAppendValue(certs, cert); 239 } 240 } else { 241 if (verbose) { 242 print_cert(cert, verbose); 243 } else if (output_subject) { 244 CFStringRef subject = SecCertificateCopySubjectString(cert); 245 if (subject) { 246 CFStringWriteToFileWithNewline(subject, stdout); 247 CFRelease(subject); 248 } 249 } else if (!output_pem) { 250 print_cert(cert, verbose); 251 } 252 } 253 if (output_finger_print) { 254 CFDataRef key_fingerprint = SecCertificateCopyPublicKeySHA1Digest(cert); 255 if (key_fingerprint) { 256 int i; 257 CFIndex j = CFDataGetLength(key_fingerprint); 258 const uint8_t *byte = CFDataGetBytePtr(key_fingerprint); 259 260 fprintf(stdout, "Key fingerprint:"); 261 for (i = 0; i < j; i++) { 262 fprintf(stdout, " %02X", byte[i]); 263 } 264 fprintf(stdout, "\n"); 265 } 266 CFReleaseSafe(key_fingerprint); 267 } 268 if (output_pem) { 269 print_buffer_pem(stdout, "CERTIFICATE", 270 SecCertificateGetLength(cert), 271 SecCertificateGetBytePtr(cert)); 272 } 273 if (!keychain_certs) { 274 CFRelease(cert); 275 } 276 } else { 277 result = 1; 278 fprintf(stderr, "file %s: does not contain a valid certificate", 279 argv[arg]); 280 } 281 } 282 283 if (trust_eval && !keychain_certs) 284 show_cert_eval(certs, verbose); 285 286 CFReleaseSafe(kc_certs); 287 CFReleaseSafe(certs); 288 289 return result; 290} 291 292#endif // TARGET_OS_EMBEDDED 293