]> git.saurik.com Git - apple/security.git/blob - SecurityTool/keychain_list.c
Security-57337.20.44.tar.gz
[apple/security.git] / SecurityTool / keychain_list.c
1 /*
2 * Copyright (c) 2003-2010,2012,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_list.c
24 */
25
26 #include "keychain_list.h"
27
28 #include "keychain_utilities.h"
29 #include "security.h"
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <sys/param.h>
34 #include <unistd.h>
35 #include <CoreFoundation/CFArray.h>
36 #include <Security/SecKeychain.h>
37
38 // SecKeychainCopyLogin
39 #include <Security/SecKeychainPriv.h>
40
41
42 typedef enum
43 {
44 kList,
45 kAdd,
46 kRemove,
47 kSet,
48 } list_operation;
49
50 static void
51 display_name(const void *value, void *context)
52 {
53 SecKeychainRef keychain = (SecKeychainRef)value;
54 UInt32 pathLength = MAXPATHLEN;
55 char pathName[MAXPATHLEN + 1];
56 OSStatus result = SecKeychainGetPath(keychain, &pathLength, pathName);
57 if (result)
58 sec_error("SecKeychainGetPath %p: %s", keychain, sec_errstr(result));
59 else
60 fprintf(stdout, " \"%*s\"\n", (int)pathLength, pathName);
61 }
62
63
64 static void
65 display_list(const char *desc, CFTypeRef keychainOrArray)
66 {
67 if (desc && strlen(desc))
68 fprintf(stdout, "%s\n", desc);
69
70 if (!keychainOrArray)
71 {
72 fprintf(stdout, " <NULL>\n");
73 }
74 else if (CFGetTypeID(keychainOrArray) == SecKeychainGetTypeID())
75 {
76 display_name(keychainOrArray, NULL);
77 }
78 else
79 {
80 CFArrayRef array = (CFArrayRef)keychainOrArray;
81 CFRange range = { 0, CFArrayGetCount(array) };
82 CFArrayApplyFunction(array, range, display_name, NULL);
83 }
84 }
85
86 static int
87 parse_domain(const char *name, SecPreferencesDomain *domain)
88 {
89 size_t len = strlen(name);
90
91 if (!strncmp("user", name, len))
92 *domain = kSecPreferencesDomainUser;
93 else if (!strncmp("system", name, len))
94 *domain = kSecPreferencesDomainSystem;
95 else if (!strncmp("common", name, len))
96 *domain = kSecPreferencesDomainCommon;
97 else if (!strncmp("dynamic", name, len))
98 *domain = kSecPreferencesDomainDynamic;
99 else
100 {
101 sec_error("Invalid domain: %s", name);
102 return 2;
103 }
104
105 return 0;
106 }
107
108 const char *
109 domain2str(SecPreferencesDomain domain)
110 {
111 switch (domain)
112 {
113 case kSecPreferencesDomainUser:
114 return "user";
115 case kSecPreferencesDomainSystem:
116 return "system";
117 case kSecPreferencesDomainCommon:
118 return "common";
119 case kSecPreferencesDomainDynamic:
120 return "dynamic";
121 default:
122 return "unknown";
123 }
124 }
125
126 int
127 keychain_list(int argc, char * const *argv)
128 {
129 CFTypeRef keychainOrArray = NULL;
130 CFArrayRef searchList = NULL;
131 list_operation operation = kList;
132 SecPreferencesDomain domain = kSecPreferencesDomainUser;
133 Boolean use_domain = false;
134 int ch, result = 0;
135 OSStatus status;
136
137 while ((ch = getopt(argc, argv, "d:hs")) != -1)
138 {
139 switch (ch)
140 {
141 case 'd':
142 result = parse_domain(optarg, &domain);
143 if (result)
144 return result;
145 use_domain = true;
146 break;
147 case 's':
148 operation = kSet;
149 break;
150 case '?':
151 default:
152 return 2; /* @@@ Return 2 triggers usage message. */
153 }
154 }
155
156 argc -= optind;
157 argv += optind;
158
159 switch (operation)
160 {
161 case kAdd:
162 result = 1;
163 break;
164 case kRemove:
165 result = 1;
166 break;
167 case kList:
168 if (argc > 0)
169 result = 2; // Show usage
170 else
171 {
172 if (use_domain)
173 {
174 status = SecKeychainCopyDomainSearchList(domain, &searchList);
175 if (status)
176 {
177 sec_error("SecKeychainCopyDomainSearchList %s: %s", domain2str(domain), sec_errstr(status));
178 result = 1;
179 }
180 else
181 {
182 #if 0
183 fprintf(stdout, "%s search list: ", domain2str(domain));
184 #endif
185 display_list("", searchList);
186 }
187 }
188 else
189 {
190 status = SecKeychainCopySearchList(&searchList);
191 if (status)
192 {
193 sec_perror("SecKeychainCopySearchList", status);
194 result = 1;
195 }
196 else
197 {
198 #if 0
199 display_list("search list:", searchList);
200 #else
201 display_list("", searchList);
202 #endif
203 }
204 }
205 }
206 break;
207 case kSet:
208 keychainOrArray = keychain_create_array(argc, argv);
209 if (argc == 0)
210 searchList = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
211 else if (argc == 1)
212 searchList = CFArrayCreate(NULL, &keychainOrArray, 1, &kCFTypeArrayCallBacks);
213 else
214 searchList = (CFArrayRef)CFRetain(keychainOrArray);
215
216 if (use_domain)
217 {
218 status = SecKeychainSetDomainSearchList(domain, searchList);
219 if (status)
220 {
221 sec_error("SecKeychainSetDomainSearchList %s: %s", domain2str(domain), sec_errstr(status));
222 result = 1;
223 }
224 }
225 else
226 {
227 status = SecKeychainSetSearchList(searchList);
228 if (status)
229 {
230 sec_perror("SecKeychainSetSearchList", status);
231 result = 1;
232 }
233 }
234 break;
235 }
236
237 if (keychainOrArray)
238 CFRelease(keychainOrArray);
239 if (searchList)
240 CFRelease(searchList);
241
242 return result;
243 }
244
245 int
246 keychain_default(int argc, char * const *argv)
247 {
248 SecPreferencesDomain domain = kSecPreferencesDomainUser;
249 SecKeychainRef keychain = NULL;
250 Boolean use_domain = false;
251 Boolean do_set = false;
252 int ch, result = 0;
253 OSStatus status;
254
255 while ((ch = getopt(argc, argv, "d:hs")) != -1)
256 {
257 switch (ch)
258 {
259 case 'd':
260 result = parse_domain(optarg, &domain);
261 if (result)
262 return result;
263 use_domain = true;
264 break;
265 case 's':
266 do_set = true;
267 break;
268 case '?':
269 default:
270 return 2; /* @@@ Return 2 triggers usage message. */
271 }
272 }
273
274 argc -= optind;
275 argv += optind;
276
277 if (do_set)
278 {
279 if (argc == 1)
280 keychain = (SecKeychainRef)keychain_create_array(argc, argv);
281 else if (argc > 0)
282 return 2;
283
284 if (use_domain)
285 {
286 status = SecKeychainSetDomainDefault(domain, keychain);
287 if (status)
288 {
289 sec_error("SecKeychainSetDomainDefault %s: %s", domain2str(domain), sec_errstr(status));
290 result = 1;
291 }
292 }
293 else
294 {
295 status = SecKeychainSetDefault(keychain);
296 if (status)
297 {
298 sec_perror("SecKeychainSetDefault", status);
299 result = 1;
300 }
301 }
302 }
303 else
304 {
305 if (argc > 0)
306 return 2;
307
308 if (use_domain)
309 {
310 status = SecKeychainCopyDomainDefault(domain, &keychain);
311 if (status)
312 {
313 sec_error("SecKeychainCopyDomainDefault %s: %s", domain2str(domain), sec_errstr(status));
314 result = 1;
315 }
316 else
317 {
318 #if 0
319 fprintf(stdout, "default %s keychain: ", domain2str(domain));
320 #endif
321 display_list("", keychain);
322 }
323 }
324 else
325 {
326 status = SecKeychainCopyDefault(&keychain);
327 if (status)
328 {
329 sec_perror("SecKeychainCopyDefault", status);
330 result = 1;
331 }
332 else
333 {
334 #if 0
335 display_list("default keychain: ", keychain);
336 #else
337 display_list("", keychain);
338 #endif
339 }
340 }
341 }
342
343 if (keychain)
344 CFRelease(keychain);
345
346 return result;
347 }
348
349 int
350 keychain_login(int argc, char * const *argv)
351 {
352 SecPreferencesDomain domain = kSecPreferencesDomainUser;
353 SecKeychainRef keychain = NULL;
354 Boolean use_domain = false;
355 Boolean do_set = false;
356 int ch, result = 0;
357 OSStatus status;
358
359 while ((ch = getopt(argc, argv, "d:hs")) != -1)
360 {
361 switch (ch)
362 {
363 case 'd':
364 result = parse_domain(optarg, &domain);
365 if (result)
366 return result;
367 use_domain = true;
368 break;
369 case 's':
370 do_set = true;
371 break;
372 case '?':
373 default:
374 return 2; /* @@@ Return 2 triggers usage message. */
375 }
376 }
377
378 argc -= optind;
379 argv += optind;
380
381 if (do_set)
382 {
383 if (argc == 1)
384 keychain = (SecKeychainRef)keychain_create_array(argc, argv);
385 else if (argc > 0)
386 return 2;
387
388 #if 0
389 if (use_domain)
390 {
391 status = SecKeychainSetDomainLogin(domain, keychain);
392 if (status)
393 {
394 sec_error("SecKeychainSetDomainLogin %s: %s", domain2str(domain), sec_errstr(status));
395 result = 1;
396 }
397 }
398 else
399 {
400 status = SecKeychainSetLogin(keychain);
401 if (status)
402 {
403 sec_perror("SecKeychainSetLogin", status);
404 result = 1;
405 }
406 }
407 #else
408 result = 1;
409 #endif
410 }
411 else
412 {
413 if (argc > 0)
414 return 2;
415
416 if (use_domain)
417 {
418 #if 0
419 status = SecKeychainCopyDomainLogin(domain, &keychain);
420 if (status)
421 {
422 sec_error("SecKeychainCopyDomainLogin %s: %s", domain2str(domain), sec_errstr(status));
423 result = 1;
424 }
425 else
426 {
427 #if 0
428 fprintf(stdout, "login %s keychain: ", domain2str(domain));
429 #endif
430 display_list("", keychain);
431 }
432 #else
433 result = 1;
434 #endif
435 }
436 else
437 {
438 status = SecKeychainCopyLogin(&keychain);
439 if (status)
440 {
441 sec_perror("SecKeychainCopyLogin", status);
442 result = 1;
443 }
444 else
445 {
446 #if 0
447 display_list("login keychain: ", keychain);
448 #else
449 display_list("", keychain);
450 #endif
451 }
452 }
453 }
454
455 if (keychain)
456 CFRelease(keychain);
457
458 return result;
459 }