]> git.saurik.com Git - apple/security.git/blob - SecurityTool/macOS/keychain_create.c
Security-59306.11.20.tar.gz
[apple/security.git] / SecurityTool / macOS / keychain_create.c
1 /*
2 * Copyright (c) 2003-2004,2008,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_create.c
24 */
25
26 #include "keychain_create.h"
27
28 #include "readline_cssm.h"
29 #include "security_tool.h"
30
31 #include <pwd.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <Security/SecKeychain.h>
37
38 static int
39 do_create(const char *keychain, const char *password, Boolean do_prompt)
40 {
41 SecKeychainRef keychainRef = NULL;
42 OSStatus result;
43
44 result = SecKeychainCreate(keychain, password ? (UInt32) strlen(password) : 0, password, do_prompt, NULL, &keychainRef);
45 if (keychainRef)
46 CFRelease(keychainRef);
47
48 if (result)
49 sec_error("SecKeychainCreate %s: %s", keychain, sec_errstr(result));
50
51 return result;
52 }
53
54 int
55 keychain_create(int argc, char * const *argv)
56 {
57 int free_keychain = 0, zero_password = 0;
58 char *password = NULL, *keychain = NULL;
59 int ch, result = 0;
60 Boolean do_prompt = FALSE;
61
62 /* AG: getopts optstring name [args]
63 AG: while loop calling getopt is used to extract password from cl from user
64 password is the only option to keychain_create
65 optstring is a string containing the legitimate option
66 characters. If such a character is followed by a colon,
67 the option requires an argument, so getopt places a
68 pointer to the following text in the same argv-element, or
69 the text of the following argv-element, in optarg.
70 */
71 while ((ch = getopt(argc, argv, "hp:P")) != -1)
72 {
73 switch (ch)
74 {
75 case 'p':
76 password = optarg;
77 break;
78 case 'P':
79 do_prompt = TRUE;
80 break;
81 case '?':
82 default:
83 return SHOW_USAGE_MESSAGE;
84 }
85 }
86 /*
87 AG: The external variable optind is the index of the next
88 array element of argv[] to be processed; it communicates
89 from one call of getopt() to the next which element to
90 process.
91 The variable optind is the index of the next element of the argv[] vector to be processed. It shall be initialized to 1 by the system, and getopt() shall update it when it finishes with each element of argv[]. When an element of argv[] contains multiple option characters, it is unspecified how getopt() determines which options have already been processed.
92
93 */
94 argc -= optind;
95 argv += optind;
96
97 if (argc > 0)
98 keychain = *argv;
99 else
100 {
101 fprintf(stderr, "keychain to create: ");
102 keychain = readline(NULL, 0);
103 if (!keychain)
104 {
105 result = -1;
106 goto loser;
107 }
108
109 free_keychain = 1;
110 if (*keychain == '\0')
111 goto loser;
112 }
113
114 if (!password && !do_prompt)
115 {
116 int compare = 1;
117 int tries;
118
119 for (tries = 3; tries-- > 0;)
120 {
121 char *firstpass;
122
123 password = getpass("password for new keychain: ");
124 if (!password)
125 {
126 result = -1;
127 goto loser;
128 }
129
130 firstpass = malloc(strlen(password) + 1);
131 strcpy(firstpass, password);
132 password = getpass("retype password for new keychain: ");
133 compare = password ? strcmp(password, firstpass) : 1;
134 memset(firstpass, 0, strlen(firstpass));
135 free(firstpass);
136 if (!password)
137 {
138 result = -1;
139 goto loser;
140 }
141
142 if (compare)
143 {
144 fprintf(stderr, "passwords don't match\n");
145 memset(password, 0, strlen(password));
146 }
147 else
148 {
149 zero_password = 1;
150 break;
151 }
152 }
153
154 if (compare)
155 {
156 result = 1;
157 goto loser;
158 }
159 }
160
161 do
162 {
163 result = do_create(keychain, password, do_prompt);
164 if (zero_password)
165 memset(password, 0, strlen(password));
166 if (result)
167 goto loser;
168
169 argc--;
170 argv++;
171 if (!free_keychain)
172 keychain = *argv;
173 } while (argc > 0);
174
175 loser:
176 if (free_keychain)
177 free(keychain);
178
179 return result;
180 }