1/* 2 * Copyright (c) 2003-2004 Apple Computer, 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.h" 29#include "security.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 38static int 39do_create(const char *keychain, const char *password, Boolean do_prompt) 40{ 41 SecKeychainRef keychainRef = NULL; 42 OSStatus result; 43 44 result = SecKeychainCreate(keychain, password ? 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 54int 55keychain_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 2; /* @@@ Return 2 triggers 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 175loser: 176 if (free_keychain) 177 free(keychain); 178 179 return result; 180} 181