]> git.saurik.com Git - apple/security.git/blob - SecurityTool/macOS/keychain_set_settings.c
Security-59306.11.20.tar.gz
[apple/security.git] / SecurityTool / macOS / 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 /* change the password, if daemon agrees everything looks good */
132 result = SecKeychainChangePassword(keychain, oldLen, oldPass, newLen, newPass);
133 if (result)
134 {
135 sec_error("error changing password for \"%s\": %s",
136 keychainName ? keychainName : "<NULL>", sec_errstr(result));
137 }
138
139 cleanup:
140 /* if we allocated password buffers, zero and free them */
141 if (oldBuf) {
142 bzero(oldBuf, PW_BUF_SIZE);
143 free(oldBuf);
144 }
145 if (newBuf) {
146 bzero(newBuf, PW_BUF_SIZE);
147 free(newBuf);
148 }
149 if (keychain) {
150 CFRelease(keychain);
151 }
152 return result;
153 }
154
155
156 int
157 keychain_set_settings(int argc, char * const *argv)
158 {
159 char *keychainName = NULL;
160 int ch, result = 0;
161 SecKeychainSettings newKeychainSettings =
162 { SEC_KEYCHAIN_SETTINGS_VERS1, FALSE, FALSE, INT_MAX };
163
164 while ((ch = getopt(argc, argv, "hlt:u")) != -1)
165 {
166 switch (ch)
167 {
168 case 'l':
169 newKeychainSettings.lockOnSleep = TRUE;
170 break;
171 case 't':
172 newKeychainSettings.lockInterval = atoi(optarg);
173 break;
174 case 'u':
175 newKeychainSettings.useLockInterval = TRUE;
176 break;
177 case '?':
178 default:
179 result = 2; /* @@@ Return 2 triggers usage message. */
180 goto cleanup;
181 }
182 }
183
184 if (newKeychainSettings.lockInterval != INT_MAX) {
185 // -t was specified, which implies -u
186 newKeychainSettings.useLockInterval = TRUE;
187 } else {
188 // -t was unspecified, so revert to no timeout
189 newKeychainSettings.useLockInterval = FALSE;
190 }
191
192 argc -= optind;
193 argv += optind;
194
195 if (argc == 1)
196 {
197 keychainName = argv[0];
198 if (*keychainName == '\0')
199 {
200 result = 2;
201 goto cleanup;
202 }
203 }
204 else if (argc != 0)
205 {
206 result = 2;
207 goto cleanup;
208 }
209
210 result = do_keychain_set_settings(keychainName, newKeychainSettings);
211
212 cleanup:
213
214 return result;
215 }
216
217 int
218 keychain_set_password(int argc, char * const *argv)
219 {
220 char *keychainName = NULL;
221 char *oldPassword = NULL;
222 char *newPassword = NULL;
223 int ch, result = 0;
224
225 while ((ch = getopt(argc, argv, "ho:p:")) != -1)
226 {
227 switch (ch)
228 {
229 case 'o':
230 oldPassword = optarg;
231 break;
232 case 'p':
233 newPassword = optarg;
234 break;
235 case '?':
236 default:
237 result = 2; /* @@@ Return 2 triggers usage message. */
238 goto cleanup;
239 }
240 }
241
242 argc -= optind;
243 argv += optind;
244
245 if (argc == 1)
246 {
247 keychainName = argv[0];
248 if (*keychainName == '\0')
249 {
250 result = 2;
251 goto cleanup;
252 }
253 }
254 else if (argc != 0)
255 {
256 result = 2;
257 goto cleanup;
258 }
259
260 result = do_keychain_set_password(keychainName, oldPassword, newPassword);
261
262 cleanup:
263
264 return result;
265 }
266