]> git.saurik.com Git - apple/security.git/blob - SecurityTool/macOS/keychain_delete.c
Security-59306.11.20.tar.gz
[apple/security.git] / SecurityTool / macOS / keychain_delete.c
1 /*
2 * Copyright (c) 2003-2019 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_delete.c
24 */
25
26 #include "keychain_delete.h"
27 #include "keychain_find.h"
28
29 #include "keychain_utilities.h"
30 #include "security_tool.h"
31 #include <unistd.h>
32 #include <Security/SecIdentity.h>
33 #include <Security/SecKeychain.h>
34 #include <Security/SecKeychainItem.h>
35 #include <Security/SecTrustSettings.h>
36
37 static int
38 do_delete(CFTypeRef keychainOrArray)
39 {
40 /* @@@ SecKeychainDelete should really take a CFTypeRef argument. */
41 OSStatus result = SecKeychainDelete((SecKeychainRef)keychainOrArray);
42 if (result)
43 {
44 /* @@@ Add printing of keychainOrArray. */
45 sec_perror("SecKeychainDelete", result);
46 }
47
48 return result;
49 }
50
51 static int
52 do_delete_certificate(CFTypeRef keychainOrArray, const char *name, const char *hash,
53 Boolean deleteTrust, Boolean deleteIdentity)
54 {
55 OSStatus result = noErr;
56 SecKeychainItemRef itemToDelete = NULL;
57 if (!name && !hash) {
58 return SHOW_USAGE_MESSAGE;
59 }
60
61 itemToDelete = find_unique_certificate(keychainOrArray, name, hash);
62 if (itemToDelete) {
63 OSStatus status = noErr;
64 if (deleteTrust) {
65 status = SecTrustSettingsRemoveTrustSettings((SecCertificateRef)itemToDelete,
66 kSecTrustSettingsDomainUser);
67 if (status) {
68 // if trust settings do not exist, it's not an error.
69 if (status != errSecItemNotFound) {
70 result = status;
71 sec_perror("SecTrustSettingsRemoveTrustSettings (user)", result);
72 }
73 }
74 if (geteuid() == 0) {
75 status = SecTrustSettingsRemoveTrustSettings((SecCertificateRef)itemToDelete,
76 kSecTrustSettingsDomainAdmin);
77 if (status) {
78 if (status != errSecItemNotFound) {
79 result = status;
80 sec_perror("SecTrustSettingsRemoveTrustSettings (admin)", result);
81 }
82 }
83 }
84 }
85 if (!result && deleteIdentity) {
86 SecIdentityRef identity = NULL;
87 status = SecIdentityCreateWithCertificate(keychainOrArray,
88 (SecCertificateRef)itemToDelete,
89 &identity);
90 if (status) {
91 // if the private key doesn't exist, and we succeed in deleting
92 // the certificate, overall result will still be good.
93 if (status == errSecItemNotFound) {
94 status = noErr;
95 } else {
96 result = status;
97 }
98 } else {
99 SecKeyRef keyToDelete = NULL;
100 status = SecIdentityCopyPrivateKey(identity, &keyToDelete);
101 if (status) {
102 result = status;
103 } else {
104 result = SecKeychainItemDelete((SecKeychainItemRef)keyToDelete);
105 if (result) {
106 sec_perror("SecKeychainItemDelete", result);
107 }
108 }
109 safe_CFRelease(&keyToDelete);
110 }
111 safe_CFRelease(&identity);
112
113 if (status) {
114 fprintf(stderr, "Unable to obtain private key reference for \"%s\" (error %d)",
115 (name) ? name : (hash) ? hash : "", (int) status);
116 }
117 }
118 if (!result) {
119 result = SecKeychainItemDelete(itemToDelete);
120 if (result) {
121 sec_perror("SecKeychainItemDelete", result);
122 goto cleanup;
123 }
124 }
125 } else {
126 result = 1;
127 fprintf(stderr, "Unable to delete certificate matching \"%s\"",
128 (name) ? name : (hash) ? hash : "");
129 }
130
131 cleanup:
132 safe_CFRelease(&itemToDelete);
133
134 return result;
135 }
136
137 static int
138 keychain_delete_cert_common(int argc, char * const *argv, Boolean delete_identity)
139 {
140 CFTypeRef keychainOrArray = NULL;
141 char *name = NULL;
142 char *hash = NULL;
143 Boolean delete_trust = FALSE;
144 int ch, result = 0;
145
146 while ((ch = getopt(argc, argv, "hc:Z:t")) != -1)
147 {
148 switch (ch)
149 {
150 case 'c':
151 name = optarg;
152 break;
153 case 'Z':
154 hash = optarg;
155 break;
156 case 't':
157 delete_trust = TRUE;
158 break;
159 case '?':
160 default:
161 result = 2; /* @@@ Return 2 triggers usage message. */
162 goto cleanup;
163 }
164 }
165
166 argc -= optind;
167 argv += optind;
168
169 keychainOrArray = keychain_create_array(argc, argv);
170
171 result = do_delete_certificate(keychainOrArray, name, hash, delete_trust, delete_identity);
172
173 cleanup:
174 safe_CFRelease(&keychainOrArray);
175
176 return result;
177 }
178
179 int
180 keychain_delete_certificate(int argc, char * const *argv)
181 {
182 return keychain_delete_cert_common(argc, argv, FALSE);
183 }
184
185 int
186 keychain_delete_identity(int argc, char * const *argv)
187 {
188 return keychain_delete_cert_common(argc, argv, TRUE);
189 }
190
191 int
192 keychain_delete(int argc, char * const *argv)
193 {
194 CFTypeRef keychainOrArray = NULL;
195 int ch, result = 0;
196
197 while ((ch = getopt(argc, argv, "h")) != -1)
198 {
199 switch (ch)
200 {
201 case '?':
202 default:
203 return SHOW_USAGE_MESSAGE;
204 }
205 }
206
207 argc -= optind;
208 argv += optind;
209
210 keychainOrArray = keychain_create_array(argc, argv);
211
212 result = do_delete(keychainOrArray);
213 if (keychainOrArray)
214 CFRelease(keychainOrArray);
215
216 return result;
217 }