1/*
2 * Copyright (c) 2003-2009 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.h"
31#include <unistd.h>
32#include <Security/SecKeychain.h>
33#include <Security/SecKeychainItem.h>
34#include <Security/SecTrustSettings.h>
35
36static int
37do_delete(CFTypeRef keychainOrArray)
38{
39	/* @@@ SecKeychainDelete should really take a CFTypeRef argument. */
40	OSStatus result = SecKeychainDelete((SecKeychainRef)keychainOrArray);
41	if (result)
42	{
43		/* @@@ Add printing of keychainOrArray. */
44		sec_perror("SecKeychainDelete", result);
45	}
46
47	return result;
48}
49
50static int
51do_delete_certificate(CFTypeRef keychainOrArray, const char *name, const char *hash, Boolean deleteTrust)
52{
53	OSStatus result = noErr;
54	SecKeychainItemRef itemToDelete = NULL;
55	if (!name && !hash) {
56		return 2;
57	}
58
59	itemToDelete = find_unique_certificate(keychainOrArray, name, hash);
60	if (itemToDelete) {
61		if (deleteTrust) {
62			result = SecTrustSettingsRemoveTrustSettings((SecCertificateRef)itemToDelete,
63														 kSecTrustSettingsDomainUser);
64			if (result && result != errSecItemNotFound) {
65				sec_perror("SecTrustSettingsRemoveTrustSettings (user)", result);
66			}
67			if (geteuid() == 0) {
68				result = SecTrustSettingsRemoveTrustSettings((SecCertificateRef)itemToDelete,
69															 kSecTrustSettingsDomainAdmin);
70				if (result && result != errSecItemNotFound) {
71					sec_perror("SecTrustSettingsRemoveTrustSettings (admin)", result);
72				}
73			}
74		}
75		result = SecKeychainItemDelete(itemToDelete);
76		if (result) {
77			sec_perror("SecKeychainItemDelete", result);
78			goto cleanup;
79		}
80	} else {
81		result = 1;
82		fprintf(stderr, "Unable to delete certificate matching \"%s\"",
83				(name) ? name : (hash) ? hash : "");
84	}
85
86cleanup:
87	safe_CFRelease(&itemToDelete);
88
89	return result;
90}
91
92int
93keychain_delete_certificate(int argc, char * const *argv)
94{
95	CFTypeRef keychainOrArray = NULL;
96	char *name = NULL;
97	char *hash = NULL;
98	Boolean delete_trust = FALSE;
99	int ch, result = 0;
100
101    while ((ch = getopt(argc, argv, "hc:Z:t")) != -1)
102	{
103		switch  (ch)
104		{
105			case 'c':
106				name = optarg;
107				break;
108			case 'Z':
109				hash = optarg;
110				break;
111			case 't':
112				delete_trust = TRUE;
113				break;
114			case '?':
115			default:
116				result = 2; /* @@@ Return 2 triggers usage message. */
117				goto cleanup;
118		}
119	}
120
121	argc -= optind;
122	argv += optind;
123
124	keychainOrArray = keychain_create_array(argc, argv);
125
126	result = do_delete_certificate(keychainOrArray, name, hash, delete_trust);
127
128cleanup:
129	safe_CFRelease(&keychainOrArray);
130
131	return result;
132}
133
134int
135keychain_delete(int argc, char * const *argv)
136{
137	CFTypeRef keychainOrArray = NULL;
138	int ch, result = 0;
139
140    while ((ch = getopt(argc, argv, "h")) != -1)
141	{
142		switch  (ch)
143		{
144		case '?':
145		default:
146			return 2; /* @@@ Return 2 triggers usage message. */
147		}
148	}
149
150	argc -= optind;
151	argv += optind;
152
153	keychainOrArray = keychain_create_array(argc, argv);
154
155	result = do_delete(keychainOrArray);
156	if (keychainOrArray)
157		CFRelease(keychainOrArray);
158
159	return result;
160}
161