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"
35 #include <Security/cssmtype.h>
36 #include <Security/SecCertificate.h>
37 #include <Security/SecIdentity.h>
38 #include <Security/SecIdentitySearch.h>
40 // SecCertificateInferLabel, SecDigestGetData
41 #include <Security/SecCertificatePriv.h>
45 do_set_identity_preference(CFTypeRef keychainOrArray
,
52 CFStringRef serviceRef
= NULL
;
53 SecIdentityRef identityRef
= NULL
;
55 // must have a service name
60 // find identity (if specified by name or hash)
61 if (identity
|| hash
) {
62 identityRef
= find_identity(keychainOrArray
, identity
, hash
, keyUsage
);
64 sec_error("No matching identity found for \"%s\"", (hash
) ? hash
: identity
);
70 // set the identity preference
71 serviceRef
= CFStringCreateWithCString(NULL
, service
, kCFStringEncodingUTF8
);
72 result
= SecIdentitySetPreference(identityRef
, serviceRef
, keyUsage
);
76 CFRelease(identityRef
);
78 CFRelease(serviceRef
);
84 do_get_identity_preference(const char *service
,
94 CFStringRef serviceRef
= CFStringCreateWithCString(NULL
, service
, kCFStringEncodingUTF8
);
95 SecCertificateRef certRef
= NULL
;
96 SecIdentityRef identityRef
= NULL
;
97 CSSM_DATA certData
= { 0, NULL
};
99 result
= SecIdentityCopyPreference(serviceRef
, keyUsage
, NULL
, &identityRef
);
101 sec_perror("SecIdentityCopyPreference", result
);
104 result
= SecIdentityCopyCertificate(identityRef
, &certRef
);
106 sec_perror("SecIdentityCopyCertificate", result
);
109 result
= SecCertificateGetData(certRef
, &certData
);
111 sec_perror("SecCertificateGetData", result
);
116 char *nameBuf
= NULL
;
117 CFStringRef nameRef
= NULL
;
118 (void)SecCertificateCopyCommonName(certRef
, &nameRef
);
119 CFIndex nameLen
= (nameRef
) ? CFStringGetLength(nameRef
) : 0;
121 CFIndex bufLen
= 1 + CFStringGetMaximumSizeForEncoding(nameLen
, kCFStringEncodingUTF8
);
122 nameBuf
= (char *)malloc(bufLen
);
123 if (!CFStringGetCString(nameRef
, nameBuf
, bufLen
-1, kCFStringEncodingUTF8
))
126 fprintf(stdout
, "common name: \"%s\"\n", (nameBuf
&& nameBuf
[0] != 0) ? nameBuf
: "<NULL>");
129 safe_CFRelease(&nameRef
);
135 digest
.Length
= sizeof(sha1_hash
);
136 digest
.Data
= sha1_hash
;
137 if (SecDigestGetData(CSSM_ALGID_SHA1
, &digest
, &certData
) == CSSM_OK
) {
139 uint32 len
= digest
.Length
;
140 uint8
*cp
= digest
.Data
;
141 fprintf(stdout
, "SHA-1 hash: ");
142 for(i
=0; i
<len
; i
++) {
143 fprintf(stdout
, "%02X", ((unsigned char *)cp
)[i
]);
145 fprintf(stdout
, "\n");
151 CSSM_DATA certData
= { 0, NULL
};
152 result
= SecCertificateGetData(certRef
, &certData
);
154 sec_perror("SecCertificateGetData", result
);
158 print_buffer_pem(stdout
, "CERTIFICATE", certData
.Length
, certData
.Data
);
162 print_keychain_item_attributes(stdout
, (SecKeychainItemRef
)certRef
, FALSE
, FALSE
, FALSE
, FALSE
);
166 safe_CFRelease(&serviceRef
);
167 safe_CFRelease(&certRef
);
168 safe_CFRelease(&identityRef
);
174 set_identity_preference(int argc
, char * const *argv
)
177 char *identity
= NULL
, *service
= NULL
, *hash
= NULL
;
178 CSSM_KEYUSE keyUsage
= 0;
179 CFTypeRef keychainOrArray
= NULL
;
182 * " -n Specify no identity (clears existing preference for service)\n"
183 * " -c Specify identity by common name of the certificate\n"
184 * " -s Specify service (URI, email address, DNS host, or other name)\n"
185 * " for which this identity is to be preferred\n"
186 * " -u Specify key usage (optional)\n"
187 * " -Z Specify identity by SHA-1 hash of certificate (optional)\n"
190 while ((ch
= getopt(argc
, argv
, "hnc:s:u:Z:")) != -1)
204 keyUsage
= atoi(optarg
);
211 result
= 2; /* @@@ Return 2 triggers usage message. */
219 keychainOrArray
= keychain_create_array(argc
, argv
);
221 result
= do_set_identity_preference(keychainOrArray
, identity
, service
, keyUsage
, hash
);
224 safe_CFRelease(&keychainOrArray
);
230 get_identity_preference(int argc
, char * const *argv
)
233 char *service
= NULL
;
234 Boolean printName
= FALSE
, printHash
= FALSE
, pemFormat
= FALSE
;
235 CSSM_KEYUSE keyUsage
= 0;
238 * " -s Specify service (URI, email address, DNS host, or other name)\n"
239 * " -u Specify key usage (optional)\n"
240 * " -p Output identity certificate in pem format\n"
241 * " -c Print common name of the preferred identity certificate (optional)\n"
242 * " -Z Print SHA-1 hash of the preferred identity certificate (optional)\n"
245 while ((ch
= getopt(argc
, argv
, "hs:u:pcZ")) != -1)
259 keyUsage
= atoi(optarg
);
266 result
= 2; /* @@@ Return 2 triggers usage message. */
271 result
= do_get_identity_preference(service
, keyUsage
, printName
, printHash
, pemFormat
);