2 * Copyright (c) 2003-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 "identity_prefs.h"
27 #include "identity_find.h"
28 #include "keychain_utilities.h"
29 #include "security_tool.h"
35 #include <Security/cssmtype.h>
36 #include <Security/SecCertificate.h>
37 #include <Security/SecIdentity.h>
38 #include <Security/SecIdentitySearch.h>
39 #include <Security/SecItem.h>
41 // SecCertificateInferLabel, SecDigestGetData
42 #include <Security/SecCertificatePriv.h>
46 do_set_identity_preference(CFTypeRef keychainOrArray
,
53 CFStringRef serviceRef
= NULL
;
54 SecIdentityRef identityRef
= NULL
;
56 // must have a service name
58 return SHOW_USAGE_MESSAGE
;
61 // find identity (if specified by name or hash)
62 if (identity
|| hash
) {
63 identityRef
= CopyMatchingIdentity(keychainOrArray
, identity
, hash
, keyUsage
);
65 sec_error("No matching identity found for \"%s\"", (hash
) ? hash
: identity
);
71 // set the identity preference
72 serviceRef
= CFStringCreateWithCString(NULL
, service
, kCFStringEncodingUTF8
);
73 result
= SecIdentitySetPreference(identityRef
, serviceRef
, keyUsage
);
77 CFRelease(identityRef
);
79 CFRelease(serviceRef
);
89 OSStatus
ctk_dump_item(CFTypeRef item
, ctk_print_context
*ctx
);
92 do_get_identity_preference(const char *service
,
100 return SHOW_USAGE_MESSAGE
;
102 CFStringRef serviceRef
= CFStringCreateWithCString(NULL
, service
, kCFStringEncodingUTF8
);
103 SecCertificateRef certRef
= NULL
;
104 SecIdentityRef identityRef
= NULL
;
105 CSSM_DATA certData
= { 0, NULL
};
107 result
= SecIdentityCopyPreference(serviceRef
, keyUsage
, NULL
, &identityRef
);
109 sec_perror("SecIdentityCopyPreference", result
);
112 result
= SecIdentityCopyCertificate(identityRef
, &certRef
);
114 sec_perror("SecIdentityCopyCertificate", result
);
117 result
= SecCertificateGetData(certRef
, &certData
);
119 sec_perror("SecCertificateGetData", result
);
124 char *nameBuf
= NULL
;
125 CFStringRef nameRef
= NULL
;
126 (void)SecCertificateCopyCommonName(certRef
, &nameRef
);
127 CFIndex nameLen
= (nameRef
) ? CFStringGetLength(nameRef
) : 0;
129 CFIndex bufLen
= 1 + CFStringGetMaximumSizeForEncoding(nameLen
, kCFStringEncodingUTF8
);
130 nameBuf
= (char *)malloc(bufLen
);
131 if (!CFStringGetCString(nameRef
, nameBuf
, bufLen
-1, kCFStringEncodingUTF8
))
134 fprintf(stdout
, "common name: \"%s\"\n", (nameBuf
&& nameBuf
[0] != 0) ? nameBuf
: "<NULL>");
137 safe_CFRelease(&nameRef
);
143 digest
.Length
= sizeof(sha1_hash
);
144 digest
.Data
= sha1_hash
;
145 if (SecDigestGetData(CSSM_ALGID_SHA1
, &digest
, &certData
) == CSSM_OK
) {
147 size_t len
= digest
.Length
;
148 uint8
*cp
= digest
.Data
;
149 fprintf(stdout
, "SHA-1 hash: ");
150 for(i
=0; i
<len
; i
++) {
151 fprintf(stdout
, "%02X", ((unsigned char *)cp
)[i
]);
153 fprintf(stdout
, "\n");
159 CSSM_DATA certData
= { 0, NULL
};
160 result
= SecCertificateGetData(certRef
, &certData
);
162 sec_perror("SecCertificateGetData", result
);
166 print_buffer_pem(stdout
, "CERTIFICATE", certData
.Length
, certData
.Data
);
170 CFTypeRef keys
[] = { kSecValueRef
, kSecReturnAttributes
};
171 CFTypeRef values
[] = { certRef
, kCFBooleanTrue
};
172 CFDictionaryRef query
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, sizeof(keys
) / sizeof(CFTypeRef
), &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
173 CFDictionaryRef attributes
= NULL
;
174 if (SecItemCopyMatching(query
, (void *)&attributes
) == errSecSuccess
&& CFDictionaryContainsKey(attributes
, kSecAttrTokenID
)) {
175 ctk_print_context ctx
= { 1, "certificate" };
176 ctk_dump_item(attributes
, &ctx
);
178 print_keychain_item_attributes(stdout
, (SecKeychainItemRef
)certRef
, FALSE
, FALSE
, FALSE
, FALSE
);
182 CFRelease(attributes
);
186 safe_CFRelease(&serviceRef
);
187 safe_CFRelease(&certRef
);
188 safe_CFRelease(&identityRef
);
194 set_identity_preference(int argc
, char * const *argv
)
197 char *identity
= NULL
, *service
= NULL
, *hash
= NULL
;
198 CSSM_KEYUSE keyUsage
= 0;
199 CFTypeRef keychainOrArray
= NULL
;
202 * " -n Specify no identity (clears existing preference for service)\n"
203 * " -c Specify identity by common name of the certificate\n"
204 * " -s Specify service (URI, email address, DNS host, or other name)\n"
205 * " for which this identity is to be preferred\n"
206 * " -u Specify key usage (optional)\n"
207 * " -Z Specify identity by SHA-1 hash of certificate (optional)\n"
210 while ((ch
= getopt(argc
, argv
, "hnc:s:u:Z:")) != -1)
224 keyUsage
= atoi(optarg
);
231 result
= SHOW_USAGE_MESSAGE
;
239 keychainOrArray
= keychain_create_array(argc
, argv
);
241 result
= do_set_identity_preference(keychainOrArray
, identity
, service
, keyUsage
, hash
);
244 safe_CFRelease(&keychainOrArray
);
250 get_identity_preference(int argc
, char * const *argv
)
253 char *service
= NULL
;
254 Boolean printName
= FALSE
, printHash
= FALSE
, pemFormat
= FALSE
;
255 CSSM_KEYUSE keyUsage
= 0;
258 * " -s Specify service (URI, email address, DNS host, or other name)\n"
259 * " -u Specify key usage (optional)\n"
260 * " -p Output identity certificate in pem format\n"
261 * " -c Print common name of the preferred identity certificate (optional)\n"
262 * " -Z Print SHA-1 hash of the preferred identity certificate (optional)\n"
265 while ((ch
= getopt(argc
, argv
, "hs:u:pcZ")) != -1)
279 keyUsage
= atoi(optarg
);
286 result
= 2; /* @@@ Return 2 triggers usage message. */
291 result
= do_get_identity_preference(service
, keyUsage
, printName
, printHash
, pemFormat
);