]> git.saurik.com Git - apple/security.git/blob - SecurityTool/keychain_set_settings.c
Security-58286.240.4.tar.gz
[apple/security.git] / SecurityTool / keychain_set_settings.c
1 /*
2 * Copyright (c) 2003-2009,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_set_settings.c
24 */
25
26 #include "keychain_set_settings.h"
27 #include "keychain_utilities.h"
28 #include "readline_cssm.h"
29 #include "security_tool.h"
30
31 #include <limits.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <Security/SecKeychain.h>
37 #include <Security/SecKeychainPriv.h>
38
39 #define PW_BUF_SIZE 512 /* size of buffer to alloc for password */
40
41
42 static int
43 do_keychain_set_settings(const char *keychainName, SecKeychainSettings newKeychainSettings)
44 {
45 SecKeychainRef keychain = NULL;
46 OSStatus result;
47
48 if (keychainName)
49 {
50 keychain = keychain_open(keychainName);
51 if (!keychain)
52 {
53 result = 1;
54 goto cleanup;
55 }
56 }
57 result = SecKeychainSetSettings(keychain, &newKeychainSettings);
58 if (result)
59 {
60 sec_error("SecKeychainSetSettings %s: %s", keychainName ? keychainName : "<NULL>", sec_errstr(result));
61 }
62
63 cleanup:
64 if (keychain)
65 CFRelease(keychain);
66
67 return result;
68 }
69
70
71 static int
72 do_keychain_set_password(const char *keychainName, const char* oldPassword, const char* newPassword)
73 {
74 SecKeychainRef keychain = NULL;
75 OSStatus result = 1;
76 UInt32 oldLen = (oldPassword) ? (UInt32) strlen(oldPassword) : 0;
77 UInt32 newLen = (newPassword) ? (UInt32) strlen(newPassword) : 0;
78 char *oldPass = (oldPassword) ? (char*)oldPassword : NULL;
79 char *newPass = (newPassword) ? (char*)newPassword : NULL;
80 char *oldBuf = NULL;
81 char *newBuf = NULL;
82
83 if (keychainName)
84 {
85 keychain = keychain_open(keychainName);
86 if (!keychain)
87 {
88 result = 1;
89 goto cleanup;
90 }
91 }
92
93 if (!oldPass) {
94 /* prompt for old password */
95 char *pBuf = getpass("Old Password: ");
96 if (pBuf) {
97 oldBuf = (char*) calloc(PW_BUF_SIZE, 1);
98 oldLen = (UInt32) strlen(pBuf);
99 memcpy(oldBuf, pBuf, oldLen);
100 bzero(pBuf, oldLen);
101 oldPass = oldBuf;
102 }
103 }
104
105 if (!newPass) {
106 /* prompt for new password */
107 char *pBuf = getpass("New Password: ");
108 if (pBuf) {
109 newBuf = (char*) calloc(PW_BUF_SIZE, 1);
110 newLen = (UInt32) strlen(pBuf);
111 memcpy(newBuf, pBuf, newLen);
112 bzero(pBuf, newLen);
113 }
114 /* confirm new password */
115 pBuf = getpass("Retype New Password: ");
116 if (pBuf) {
117 UInt32 confirmLen = (UInt32) strlen(pBuf);
118 if (confirmLen == newLen && newBuf &&
119 !memcmp(pBuf, newBuf, newLen)) {
120 newPass = newBuf;
121 }
122 bzero(pBuf, confirmLen);
123 }
124 }
125
126 if (!oldPass || !newPass) {
127 sec_error("try again");
128 goto cleanup;
129 }
130
131 /* lock keychain first to remove existing credentials */
132 (void)SecKeychainLock(keychain);
133
134 /* change the password */
135 result = SecKeychainChangePassword(keychain, oldLen, oldPass, newLen, newPass);
136 if (result)
137 {
138 sec_error("error changing password for \"%s\": %s",
139 keychainName ? keychainName : "<NULL>", sec_errstr(result));
140 }
141
142 cleanup:
143 /* if we allocated password buffers, zero and free them */
144 if (oldBuf) {
145 bzero(oldBuf, PW_BUF_SIZE);
146 free(oldBuf);
147 }
148 if (newBuf) {
149 bzero(newBuf, PW_BUF_SIZE);
150 free(newBuf);
151 }
152 if (keychain) {
153 CFRelease(keychain);
154 }
155 return result;
156 }
157
158
159 int
160 keychain_set_settings(int argc, char * const *argv)
161 {
162 char *keychainName = NULL;
163 int ch, result = 0;
164 SecKeychainSettings newKeychainSettings =
165 { SEC_KEYCHAIN_SETTINGS_VERS1, FALSE, FALSE, INT_MAX };
166
167 while ((ch = getopt(argc, argv, "hlt:u")) != -1)
168 {
169 switch (ch)
170 {
171 case 'l':
172 newKeychainSettings.lockOnSleep = TRUE;
173 break;
174 case 't':
175 newKeychainSettings.lockInterval = atoi(optarg);
176 break;
177 case 'u':
178 newKeychainSettings.useLockInterval = TRUE;
179 break;
180 case '?':
181 default:
182 result = 2; /* @@@ Return 2 triggers usage message. */
183 goto cleanup;
184 }
185 }
186
187 if (newKeychainSettings.lockInterval != INT_MAX) {
188 // -t was specified, which implies -u
189 newKeychainSettings.useLockInterval = TRUE;
190 } else {
191 // -t was unspecified, so revert to no timeout
192 newKeychainSettings.useLockInterval = FALSE;
193 }
194
195 argc -= optind;
196 argv += optind;
197
198 if (argc == 1)
199 {
200 keychainName = argv[0];
201 if (*keychainName == '\0')
202 {
203 result = 2;
204 goto cleanup;
205 }
206 }
207 else if (argc != 0)
208 {
209 result = 2;
210 goto cleanup;
211 }
212
213 result = do_keychain_set_settings(keychainName, newKeychainSettings);
214
215 cleanup:
216
217 return result;
218 }
219
220 int
221 keychain_set_password(int argc, char * const *argv)
222 {
223 char *keychainName = NULL;
224 char *oldPassword = NULL;
225 char *newPassword = NULL;
226 int ch, result = 0;
227
228 while ((ch = getopt(argc, argv, "ho:p:")) != -1)
229 {
230 switch (ch)
231 {
232 case 'o':
233 oldPassword = optarg;
234 break;
235 case 'p':
236 newPassword = optarg;
237 break;
238 case '?':
239 default:
240 result = 2; /* @@@ Return 2 triggers usage message. */
241 goto cleanup;
242 }
243 }
244
245 argc -= optind;
246 argv += optind;
247
248 if (argc == 1)
249 {
250 keychainName = argv[0];
251 if (*keychainName == '\0')
252 {
253 result = 2;
254 goto cleanup;
255 }
256 }
257 else if (argc != 0)
258 {
259 result = 2;
260 goto cleanup;
261 }
262
263 result = do_keychain_set_password(keychainName, oldPassword, newPassword);
264
265 cleanup:
266
267 return result;
268 }
269