#include "keychain_create.h"
#include "readline.h"
#include "security_tool.h"
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <Security/SecKeychain.h>
static int
do_create(const char *keychain, const char *password, Boolean do_prompt)
{
SecKeychainRef keychainRef = NULL;
OSStatus result;
result = SecKeychainCreate(keychain, password ? (UInt32) strlen(password) : 0, password, do_prompt, NULL, &keychainRef);
if (keychainRef)
CFRelease(keychainRef);
if (result)
sec_error("SecKeychainCreate %s: %s", keychain, sec_errstr(result));
return result;
}
int
keychain_create(int argc, char * const *argv)
{
int free_keychain = 0, zero_password = 0;
char *password = NULL, *keychain = NULL;
int ch, result = 0;
Boolean do_prompt = FALSE;
while ((ch = getopt(argc, argv, "hp:P")) != -1)
{
switch (ch)
{
case 'p':
password = optarg;
break;
case 'P':
do_prompt = TRUE;
break;
case '?':
default:
return 2;
}
}
argc -= optind;
argv += optind;
if (argc > 0)
keychain = *argv;
else
{
fprintf(stderr, "keychain to create: ");
keychain = readline(NULL, 0);
if (!keychain)
{
result = -1;
goto loser;
}
free_keychain = 1;
if (*keychain == '\0')
goto loser;
}
if (!password && !do_prompt)
{
int compare = 1;
int tries;
for (tries = 3; tries-- > 0;)
{
char *firstpass;
password = getpass("password for new keychain: ");
if (!password)
{
result = -1;
goto loser;
}
firstpass = malloc(strlen(password) + 1);
strcpy(firstpass, password);
password = getpass("retype password for new keychain: ");
compare = password ? strcmp(password, firstpass) : 1;
memset(firstpass, 0, strlen(firstpass));
free(firstpass);
if (!password)
{
result = -1;
goto loser;
}
if (compare)
{
fprintf(stderr, "passwords don't match\n");
memset(password, 0, strlen(password));
}
else
{
zero_password = 1;
break;
}
}
if (compare)
{
result = 1;
goto loser;
}
}
do
{
result = do_create(keychain, password, do_prompt);
if (zero_password)
memset(password, 0, strlen(password));
if (result)
goto loser;
argc--;
argv++;
if (!free_keychain)
keychain = *argv;
} while (argc > 0);
loser:
if (free_keychain)
free(keychain);
return result;
}