]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTool/keychain_add.c
Security-59306.11.20.tar.gz
[apple/security.git] / SecurityTool / keychain_add.c
diff --git a/SecurityTool/keychain_add.c b/SecurityTool/keychain_add.c
deleted file mode 100644 (file)
index 71d5949..0000000
+++ /dev/null
@@ -1,978 +0,0 @@
-/*
- * Copyright (c) 2003-2009,2011-2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- *
- * keychain_add.c
- */
-
-#include "keychain_add.h"
-#include "keychain_find.h"
-#include "readline_cssm.h"
-#include "security_tool.h"
-#include "access_utils.h"
-#include "keychain_utilities.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <AssertMacros.h>
-#include <libkern/OSByteOrder.h>
-#include <Security/SecAccess.h>
-#include <Security/SecCertificate.h>
-#include <Security/SecKeychain.h>
-#include <Security/SecKeychainItem.h>
-#include <Security/SecTrustedApplication.h>
-
-// SecTrustedApplicationCreateApplicationGroup
-#include <Security/SecTrustedApplicationPriv.h>
-
-
-static int
-do_update_generic_password(const char *keychainName,
-        FourCharCode itemCreator,
-        FourCharCode itemType,
-        const char *kind,
-        const char *value,
-        const char *comment,
-        const char *label,
-        const char *serviceName,
-        const char *accountName,
-        const void *passwordData,
-        SecAccessRef access)
-{
-       OSStatus status;
-       SecKeychainRef keychainRef = NULL;
-       SecKeychainItemRef itemRef = NULL;
-
-       if (keychainName) {
-               keychainRef = keychain_open(keychainName);
-       }
-       itemRef = find_first_generic_password(keychainRef,itemCreator,itemType,kind,value,comment,label,serviceName,accountName);
-       if (keychainRef) {
-               CFRelease(keychainRef);
-       }
-       if (!itemRef) {
-               return errSecItemNotFound;
-       }
-
-       // build list of attributes
-       SecKeychainAttribute attrs[8]; // maximum number of attributes
-       SecKeychainAttributeList attrList = { 0, attrs };
-
-       if ((UInt32)itemCreator != 0) {
-               attrs[attrList.count].tag = kSecCreatorItemAttr;
-               attrs[attrList.count].length = sizeof(FourCharCode);
-               attrs[attrList.count].data = (FourCharCode *)&itemCreator;
-               attrList.count++;
-       }
-       if ((UInt32)itemType != 0) {
-               attrs[attrList.count].tag = kSecTypeItemAttr;
-               attrs[attrList.count].length = sizeof(FourCharCode);
-               attrs[attrList.count].data = (FourCharCode *)&itemType;
-               attrList.count++;
-       }
-       if (kind != NULL) {
-               attrs[attrList.count].tag = kSecDescriptionItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(kind);
-               attrs[attrList.count].data = (void *)kind;
-               attrList.count++;
-       }
-       if (value != NULL) {
-               attrs[attrList.count].tag = kSecGenericItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(value);
-               attrs[attrList.count].data = (void *)value;
-               attrList.count++;
-       }
-       if (comment != NULL) {
-               attrs[attrList.count].tag = kSecCommentItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(comment);
-               attrs[attrList.count].data = (void *)comment;
-               attrList.count++;
-       }
-       if (label != NULL) {
-               attrs[attrList.count].tag = kSecLabelItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(label);
-               attrs[attrList.count].data = (void *)label;
-               attrList.count++;
-       }
-       if (serviceName != NULL) {
-               attrs[attrList.count].tag = kSecServiceItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(serviceName);
-               attrs[attrList.count].data = (void *)serviceName;
-               attrList.count++;
-       }
-       if (accountName != NULL) {
-               attrs[attrList.count].tag = kSecAccountItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(accountName);
-               attrs[attrList.count].data = (void *)accountName;
-               attrList.count++;
-       }
-
-       // modify attributes and password data, if provided
-       status = SecKeychainItemModifyContent(itemRef, &attrList, (passwordData) ? ((UInt32) strlen(passwordData)) : 0, passwordData);
-       if (status) {
-               sec_error("SecKeychainItemModifyContent: %s", sec_errstr(status));
-       }
-
-       // modify access, if provided
-       if (!status && access) {
-               SecAccessRef curAccess = NULL;
-               // for historical reasons, we have to modify the item's existing access reference
-               // (setting the item's access to a freshly created SecAccessRef instance doesn't behave as expected)
-               status = SecKeychainItemCopyAccess(itemRef, &curAccess);
-               if (status) {
-                       sec_error("SecKeychainItemCopyAccess: %s", sec_errstr(status));
-               } else {
-                       int result = merge_access(curAccess, access); // make changes to the existing access reference
-                       if (result == noErr) {
-                               status = SecKeychainItemSetAccess(itemRef, curAccess); // will prompt
-                               if (status) {
-                                       sec_error("SecKeychainItemSetAccess: %s", sec_errstr(status));
-                               }
-                       }
-               }
-               if (curAccess) {
-                       CFRelease(curAccess);
-               }
-       }
-
-       CFRelease(itemRef);
-
-       return status;
-}
-
-static int
-do_add_generic_password(const char *keychainName,
-       FourCharCode itemCreator,
-       FourCharCode itemType,
-       const char *kind,
-       const char *value,
-       const char *comment,
-       const char *label,
-       const char *serviceName,
-       const char *accountName,
-       const void *passwordData,
-       SecAccessRef access,
-       Boolean update)
-{
-       SecKeychainRef keychain = NULL;
-       OSStatus result = 0;
-    SecKeychainItemRef itemRef = NULL;
-
-       // if update flag is specified, try to find and update an existing item
-       if (update) {
-               result = do_update_generic_password(keychainName,itemCreator,itemType,kind,value,comment,label,serviceName,accountName,passwordData,access);
-               if (result == noErr)
-                       return result;
-       }
-
-       if (keychainName)
-       {
-               keychain = keychain_open(keychainName);
-               if (!keychain)
-               {
-                       result = 1;
-                       goto cleanup;
-               }
-       }
-
-       // set up attribute vector for new item (each attribute consists of {tag, length, pointer})
-       SecKeychainAttribute attrs[] = {
-               { kSecLabelItemAttr, label ? (UInt32) strlen(label) : 0, (char *)label },
-               { kSecDescriptionItemAttr, kind ? (UInt32) strlen(kind) : 0, (char *)kind },
-               { kSecGenericItemAttr, value ? (UInt32) strlen(value) : 0, (char *)value },
-               { kSecCommentItemAttr, comment ? (UInt32) strlen(comment) : 0, (char *)comment },
-               { kSecServiceItemAttr, serviceName ? (UInt32) strlen(serviceName) : 0, (char *)serviceName },
-               { kSecAccountItemAttr, accountName ? (UInt32) strlen(accountName) : 0, (char *)accountName },
-               { (SecKeychainAttrType)0, sizeof(FourCharCode), NULL }, /* placeholder */
-               { (SecKeychainAttrType)0, sizeof(FourCharCode), NULL }  /* placeholder */
-       };
-       SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
-       attributes.count -= 2;
-
-       if (itemCreator != 0)
-       {
-               attrs[attributes.count].tag = kSecCreatorItemAttr;
-               attrs[attributes.count].data = (FourCharCode *)&itemCreator;
-               attributes.count++;
-       }
-       if (itemType != 0)
-       {
-               attrs[attributes.count].tag = kSecTypeItemAttr;
-               attrs[attributes.count].data = (FourCharCode *)&itemType;
-               attributes.count++;
-       }
-
-       result = SecKeychainItemCreateFromContent(kSecGenericPasswordItemClass,
-               &attributes,
-               passwordData ? (UInt32) strlen(passwordData) : 0,
-               passwordData,
-               keychain,
-               access,
-               &itemRef);
-
-       if (result)
-       {
-               sec_error("SecKeychainItemCreateFromContent (%s): %s", keychainName ? keychainName : "<default>", sec_errstr(result));
-       }
-
-cleanup:
-       if (itemRef)
-               CFRelease(itemRef);
-       if (keychain)
-               CFRelease(keychain);
-
-       return result;
-}
-
-static int
-do_update_internet_password(const char *keychainName,
-        FourCharCode itemCreator,
-        FourCharCode itemType,
-        const char *kind,
-        const char *comment,
-        const char *label,
-        const char *serverName,
-        const char *securityDomain,
-        const char *accountName,
-        const char *path,
-        UInt16 port,
-        SecProtocolType protocol,
-        SecAuthenticationType authenticationType,
-        const void *passwordData,
-        SecAccessRef access)
-{
-       OSStatus status;
-       SecKeychainRef keychainRef = NULL;
-       SecKeychainItemRef itemRef = NULL;
-
-       if (keychainName) {
-               keychainRef = keychain_open(keychainName);
-       }
-       itemRef = find_first_internet_password(keychainRef,itemCreator,itemType,kind,comment,label,serverName,
-                                                                                  securityDomain,accountName,path,port,protocol,authenticationType);
-       if (keychainRef) {
-               CFRelease(keychainRef);
-       }
-       if (!itemRef) {
-               return errSecItemNotFound;
-       }
-
-       // build list of attributes
-       SecKeychainAttribute attrs[12]; // maximum number of attributes
-       SecKeychainAttributeList attrList = { 0, attrs };
-
-       if ((UInt32)itemCreator != 0) {
-               attrs[attrList.count].tag = kSecCreatorItemAttr;
-               attrs[attrList.count].length = sizeof(FourCharCode);
-               attrs[attrList.count].data = (FourCharCode *)&itemCreator;
-               attrList.count++;
-       }
-       if ((UInt32)itemType != 0) {
-               attrs[attrList.count].tag = kSecTypeItemAttr;
-               attrs[attrList.count].length = sizeof(FourCharCode);
-               attrs[attrList.count].data = (FourCharCode *)&itemType;
-               attrList.count++;
-       }
-       if (kind != NULL) {
-               attrs[attrList.count].tag = kSecDescriptionItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(kind);
-               attrs[attrList.count].data = (void *)kind;
-               attrList.count++;
-       }
-       if (comment != NULL) {
-               attrs[attrList.count].tag = kSecCommentItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(comment);
-               attrs[attrList.count].data = (void *)comment;
-               attrList.count++;
-       }
-       if (label != NULL) {
-               attrs[attrList.count].tag = kSecLabelItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(label);
-               attrs[attrList.count].data = (void *)label;
-               attrList.count++;
-       }
-       if (serverName != NULL) {
-               attrs[attrList.count].tag = kSecServerItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(serverName);
-               attrs[attrList.count].data = (void *)serverName;
-               attrList.count++;
-       }
-       if (securityDomain != NULL) {
-               attrs[attrList.count].tag = kSecSecurityDomainItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(securityDomain);
-               attrs[attrList.count].data = (void *)securityDomain;
-               attrList.count++;
-       }
-       if (accountName != NULL) {
-               attrs[attrList.count].tag = kSecAccountItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(accountName);
-               attrs[attrList.count].data = (void *)accountName;
-               attrList.count++;
-       }
-       if (path != NULL) {
-               attrs[attrList.count].tag = kSecPathItemAttr;
-               attrs[attrList.count].length = (UInt32) strlen(path);
-               attrs[attrList.count].data = (void *)path;
-               attrList.count++;
-       }
-       if (port != 0) {
-               attrs[attrList.count].tag = kSecPortItemAttr;
-               attrs[attrList.count].length = sizeof(UInt16);
-               attrs[attrList.count].data = (UInt16 *)&port;
-               attrList.count++;
-       }
-       if ((UInt32)protocol != 0) {
-               attrs[attrList.count].tag = kSecProtocolItemAttr;
-               attrs[attrList.count].length = sizeof(SecProtocolType);
-               attrs[attrList.count].data = (SecProtocolType *)&protocol;
-               attrList.count++;
-       }
-       if ((UInt32)authenticationType != 0) {
-               attrs[attrList.count].tag = kSecAuthenticationTypeItemAttr;
-               attrs[attrList.count].length = sizeof(SecAuthenticationType);
-               attrs[attrList.count].data = (SecAuthenticationType *)&authenticationType;
-               attrList.count++;
-       }
-
-       // modify attributes and password data, if provided
-       status = SecKeychainItemModifyContent(itemRef, &attrList, (passwordData) ? (UInt32) strlen(passwordData) : 0, passwordData);
-       if (status) {
-               sec_error("SecKeychainItemModifyContent: %s", sec_errstr(status));
-       }
-
-       // modify access, if provided
-       if (!status && access) {
-               status = modify_access(itemRef, access);
-       }
-
-       CFRelease(itemRef);
-
-       return status;
-}
-
-static int
-do_add_internet_password(const char *keychainName,
-       FourCharCode itemCreator,
-       FourCharCode itemType,
-       const char *kind,
-       const char *comment,
-       const char *label,
-       const char *serverName,
-       const char *securityDomain,
-       const char *accountName,
-       const char *path,
-       UInt16 port,
-       SecProtocolType protocol,
-       SecAuthenticationType authenticationType,
-       const void *passwordData,
-       SecAccessRef access,
-       Boolean update)
-{
-       SecKeychainRef keychain = NULL;
-    SecKeychainItemRef itemRef = NULL;
-       OSStatus result = 0;
-
-       // if update flag is specified, try to find and update an existing item
-       if (update) {
-               result = do_update_internet_password(keychainName,itemCreator,itemType,kind,comment,label,serverName,
-                                                                                        securityDomain,accountName,path,port,protocol,authenticationType,
-                                                                                        passwordData,access);
-               if (result == noErr)
-                       return result;
-       }
-
-       if (keychainName)
-       {
-               keychain = keychain_open(keychainName);
-               if (!keychain)
-               {
-                       result = 1;
-                       goto cleanup;
-               }
-       }
-
-       // set up attribute vector for new item (each attribute consists of {tag, length, pointer})
-       SecKeychainAttribute attrs[] = {
-               { kSecLabelItemAttr, label ? (UInt32) strlen(label) : 0, (char *)label },
-               { kSecDescriptionItemAttr, kind ? (UInt32) strlen(kind) : 0, (char *)kind },
-               { kSecCommentItemAttr, comment ? (UInt32) strlen(comment) : 0, (char *)comment },
-               { kSecServerItemAttr, serverName ? (UInt32) strlen(serverName) : 0, (char *)serverName },
-               { kSecSecurityDomainItemAttr, securityDomain ? (UInt32) strlen(securityDomain) : 0, (char *)securityDomain },
-               { kSecAccountItemAttr, accountName ? (UInt32) strlen(accountName) : 0, (char *)accountName },
-               { kSecPathItemAttr, path ? (UInt32) strlen(path) : 0, (char *)path },
-               { kSecPortItemAttr, sizeof(UInt16), (UInt16 *)&port },
-               { kSecProtocolItemAttr, sizeof(SecProtocolType), (SecProtocolType *)&protocol },
-               { kSecAuthenticationTypeItemAttr, sizeof(SecAuthenticationType), (SecAuthenticationType *)&authenticationType },
-               { (SecKeychainAttrType)0, sizeof(FourCharCode), NULL }, /* placeholder */
-               { (SecKeychainAttrType)0, sizeof(FourCharCode), NULL }  /* placeholder */
-       };
-       SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
-       attributes.count -= 2;
-
-       if (itemCreator != 0)
-       {
-               attrs[attributes.count].tag = kSecCreatorItemAttr;
-               attrs[attributes.count].data = (FourCharCode *)&itemCreator;
-               attributes.count++;
-       }
-       if (itemType != 0)
-       {
-               attrs[attributes.count].tag = kSecTypeItemAttr;
-               attrs[attributes.count].data = (FourCharCode *)&itemType;
-               attributes.count++;
-       }
-
-       result = SecKeychainItemCreateFromContent(kSecInternetPasswordItemClass,
-               &attributes,
-               passwordData ? (UInt32) strlen(passwordData) : 0,
-               passwordData,
-               keychain,
-               access,
-               &itemRef);
-
-       if (result)
-       {
-               sec_error("SecKeychainAddInternetPassword %s: %s", keychainName ? keychainName : "<NULL>", sec_errstr(result));
-       }
-
-cleanup:
-       if (itemRef)
-               CFRelease(itemRef);
-       if (keychain)
-               CFRelease(keychain);
-
-       return result;
-}
-
-static int
-do_add_certificates(const char *keychainName, int argc, char * const *argv)
-{
-       SecKeychainRef keychain = NULL;
-       int ix, result = 0;
-
-       if (keychainName)
-       {
-               keychain = keychain_open(keychainName);
-               if (!keychain)
-               {
-                       result = 1;
-                       goto cleanup;
-               }
-       }
-
-       for (ix = 0; ix < argc; ++ix)
-       {
-               CSSM_DATA certData = {};
-               OSStatus status;
-               SecCertificateRef certificate = NULL;
-
-               if (read_file(argv[ix], &certData))
-               {
-                       result = 1;
-                       continue;
-               }
-
-               status = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_UNKNOWN, &certificate);
-               if (status)
-               {
-                       sec_perror("SecCertificateCreateFromData", status);
-                       result = 1;
-               }
-               else
-               {
-                       status = SecCertificateAddToKeychain(certificate, keychain);
-                       if (status)
-                       {
-                if (status == errSecDuplicateItem)
-                {
-                    if (keychainName)
-                        sec_error("%s: already in %s", argv[ix], keychainName);
-                    else
-                        sec_error("%s: already in default keychain", argv[ix]);
-                }
-                else
-                {
-                    sec_perror("SecCertificateAddToKeychain", status);
-                }
-                               result = 1;
-                       }
-               }
-
-               if (certData.Data)
-                       free(certData.Data);
-               if (certificate)
-                       CFRelease(certificate);
-       }
-
-cleanup:
-       if (keychain)
-               CFRelease(keychain);
-
-       return result;
-}
-
-static bool promptForPasswordData(char **returnedPasswordData) {
-    // Caller must zero memory and free returned value.
-    // Returns true if we have data; false means the user canceled
-    if (!returnedPasswordData)
-        return false;
-
-    bool result = false;
-    char *password = NULL;
-    int tries;
-
-    for (tries = 3; tries-- > 0;) {
-        bool passwordsMatch = false;
-        char *firstpass = NULL;
-
-        password = getpass("password data for new item: ");
-        if (!password)
-            break;
-
-        firstpass = malloc(strlen(password) + 1);
-        strcpy(firstpass, password);
-        password = getpass("retype password for new item: ");
-        passwordsMatch = password && (strcmp(password, firstpass) == 0);
-        memset(firstpass, 0, strlen(firstpass));
-        free(firstpass);
-        if (!password)
-            break;
-
-        if (passwordsMatch) {
-            result = true;
-            break;
-        }
-
-        fprintf(stderr, "passwords don't match\n");
-        memset(password, 0, strlen(password));
-    }
-
-    if (result) {
-        *returnedPasswordData = password;
-    } else {
-        free(password);
-    }
-    return result;
-}
-
-int
-keychain_add_generic_password(int argc, char * const *argv)
-{
-       char *serviceName = NULL, *passwordData  = NULL, *accountName = NULL;
-       char *kind = NULL, *label = NULL, *value = NULL, *comment = NULL;
-       FourCharCode itemCreator = 0, itemType = 0;
-       int ch, result = 0;
-       const char *keychainName = NULL;
-       Boolean access_specified = FALSE;
-       Boolean always_allow = FALSE;
-       Boolean update_item = FALSE;
-       SecAccessRef access = NULL;
-       CFMutableArrayRef trusted_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-       OSStatus status;
-    bool mustFreePasswordData = false; // if we got it via user prompting
-
-  /*
-   *  "    -a  Specify account name (required)\n"
-   *  "    -c  Specify item creator (optional four-character code)\n"
-   *  "    -C  Specify item type (optional four-character code)\n"
-   *  "    -D  Specify kind (default is \"application password\")\n"
-   *  "    -G  Specify generic attribute (optional)\n"
-   *  "    -j  Specify comment string (optional)\n"
-   *  "    -l  Specify label (if omitted, service name is used as default label)\n"
-   *  "    -s  Specify service name (required)\n"
-   *  "    -p  Specify password to be added (legacy option, equivalent to -w)\n"
-   *  "    -w  Specify password to be added\n"
-   *  "    -A  Allow any application to access this item without warning (insecure, not recommended!)\n"
-   *  "    -T  Specify an application which may access this item (multiple -T options are allowed)\n"
-   *  "    -U  Update item if it already exists (if omitted, the item cannot already exist)\n"
-   */
-
-       while ((ch = getopt(argc, argv, ":a:c:C:D:G:j:l:s:p:w:UAT:")) != -1)
-       {
-               switch  (ch)
-               {
-        case 'a':
-            accountName = optarg;
-                       break;
-               case 'c':
-                       result = parse_fourcharcode(optarg, &itemCreator);
-                       if (result) goto cleanup;
-                       break;
-               case 'C':
-                       result = parse_fourcharcode(optarg, &itemType);
-                       if (result) goto cleanup;
-                       break;
-        case 'D':
-            kind = optarg;
-                       break;
-               case 'G':
-                       value = optarg;
-                       break;
-               case 'j':
-                       comment = optarg;
-                       break;
-               case 'l':
-                       label = optarg;
-                       break;
-               case 's':
-                       serviceName = optarg;
-                       break;
-        case 'p':
-        case 'w':
-            passwordData = optarg;
-            break;
-               case 'U':
-                       update_item = TRUE;
-                       break;
-               case 'A':
-                       always_allow = TRUE;
-                       access_specified = TRUE;
-                       break;
-               case 'T':
-               {
-                       if (optarg[0])
-                       {
-                               SecTrustedApplicationRef app = NULL;
-                               /* check whether the argument specifies an application group */
-                               const char *groupPrefix = "group://";
-                               size_t prefixLen = strlen(groupPrefix);
-                               if (strlen(optarg) > prefixLen && !memcmp(optarg, groupPrefix, prefixLen)) {
-                                       const char *groupName = &optarg[prefixLen];
-                                       if ((status = SecTrustedApplicationCreateApplicationGroup(groupName, NULL, &app)) != noErr) {
-                                               sec_error("SecTrustedApplicationCreateApplicationGroup %s: %s", optarg, sec_errstr(status));
-                                       }
-                               } else {
-                                       if ((status = SecTrustedApplicationCreateFromPath(optarg, &app)) != noErr) {
-                                               sec_error("SecTrustedApplicationCreateFromPath %s: %s", optarg, sec_errstr(status));
-                                       }
-                               }
-
-                               if (status) {
-                                       result = 1;
-                                       goto cleanup;
-                               }
-
-                               CFArrayAppendValue(trusted_list, app);
-                               CFRelease(app);
-                       }
-                       access_specified = TRUE;
-                       break;
-               }
-        case '?':
-        case ':':
-            // They supplied the -p or -w but with no data, so prompt
-            // This differs from the case where no -p or -w was given, where we set the data to empty
-            if (optopt == 'p' || optopt == 'w') {
-                if (promptForPasswordData(&passwordData)) {
-                    mustFreePasswordData = true;
-                    break;
-                } else {
-                    result = 1;
-                    goto cleanup; /* @@@ Do not trigger usage message, but indicate failure. */
-                }
-            }
-            result = 2;
-            goto cleanup; /* @@@ Return 2 triggers usage message. */
-               default:
-                       result = 2;
-                       goto cleanup; /* @@@ Return 2 triggers usage message. */
-               }
-       }
-
-       argc -= optind;
-       argv += optind;
-
-       if (!accountName || !serviceName)
-       {
-               result = 2;
-               goto cleanup;
-       }
-       else if (argc > 0)
-       {
-               keychainName = argv[0];
-               if (argc > 1 || *keychainName == '\0')
-               {
-                       result = 2;
-                       goto cleanup;
-               }
-       }
-
-       if (access_specified)
-       {
-               const char *accessName = (label) ? label : (serviceName) ? serviceName : (accountName) ? accountName : "";
-               if ((result = create_access(accessName, always_allow, trusted_list, &access)) != 0)
-                       goto cleanup;
-       }
-
-       result = do_add_generic_password(keychainName,
-                                                                        itemCreator,
-                                                                        itemType,
-                                                                        kind,
-                                                                        value,
-                                                                        comment,
-                                                                        (label) ? label : serviceName,
-                                                                        serviceName,
-                                                                        accountName,
-                                                                        passwordData,
-                                                                        access,
-                                                                        update_item);
-
-cleanup:
-    if (mustFreePasswordData)
-        free(passwordData);
-       if (trusted_list)
-               CFRelease(trusted_list);
-       if (access)
-               CFRelease(access);
-
-       return result;
-}
-
-int
-keychain_add_internet_password(int argc, char * const *argv)
-{
-       char *serverName = NULL, *securityDomain = NULL, *accountName = NULL, *path = NULL, *passwordData = NULL;
-       char *kind = NULL, *comment = NULL, *label = NULL;
-       FourCharCode itemCreator = 0, itemType = 0;
-       UInt16 port = 0;
-       SecProtocolType protocol = 0;
-       SecAuthenticationType authenticationType = OSSwapHostToBigInt32('dflt');
-       int ch, result = 0;
-       const char *keychainName = NULL;
-       Boolean access_specified = FALSE;
-       Boolean always_allow = FALSE;
-       Boolean update_item = FALSE;
-       SecAccessRef access = NULL;
-       CFMutableArrayRef trusted_list = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-       OSStatus status;
-    bool mustFreePasswordData = false; // if we got it via user prompting
-
-  /*
-   *  "    -a  Specify account name (required)\n"
-   *  "    -c  Specify item creator (optional four-character code)\n"
-   *  "    -C  Specify item type (optional four-character code)\n"
-   *  "    -d  Specify security domain string (optional)\n"
-   *  "    -D  Specify kind (default is \"Internet password\")\n"
-   *  "    -j  Specify comment string (optional)\n"
-   *  "    -l  Specify label (if omitted, server name is used as default label)\n"
-   *  "    -p  Specify path string (optional)\n"
-   *  "    -P  Specify port number (optional)\n"
-   *  "    -r  Specify protocol (optional four-character SecProtocolType, e.g. \"http\", \"ftp \")\n"
-   *  "    -s  Specify server name (required)\n"
-   *  "    -t  Specify authentication type (as a four-character SecAuthenticationType, default is \"dflt\")\n"
-   *  "    -w  Specify password to be added\n"
-   *  "    -A  Allow any application to access this item without warning (insecure, not recommended!)\n"
-   *  "    -T  Specify an application which may access this item (multiple -T options are allowed)\n"
-   *  "    -U  Update item if it already exists (if omitted, the item cannot already exist)\n"
-   */
-
-       while ((ch = getopt(argc, argv, ":a:c:C:d:D:j:l:p:P:r:s:t:w:UAT:h")) != -1)
-       {
-               switch  (ch)
-               {
-               case 'a':
-                       accountName = optarg;
-                       break;
-               case 'c':
-                       result = parse_fourcharcode(optarg, &itemCreator);
-                       if (result) goto cleanup;
-                       break;
-               case 'C':
-                       result = parse_fourcharcode(optarg, &itemType);
-                       if (result) goto cleanup;
-                       break;
-               case 'd':
-                       securityDomain = optarg;
-                       break;
-        case 'D':
-            kind = optarg;
-                       break;
-               case 'j':
-                       comment = optarg;
-                       break;
-               case 'l':
-                       label = optarg;
-                       break;
-               case 'p':
-                       path = optarg;
-                       break;
-               case 'P':
-                       port = atoi(optarg);
-                       break;
-               case 'r':
-                       result = parse_fourcharcode(optarg, &protocol);
-                       if (result) goto cleanup;
-                       break;
-               case 's':
-                       serverName = optarg;
-                       break;
-               case 't':
-                       result = parse_fourcharcode(optarg, &authenticationType);
-                       if (result) goto cleanup;
-                       /* auth type attribute is special */
-                       authenticationType = OSSwapHostToBigInt32(authenticationType);
-                       break;
-               case 'w':
-                       passwordData = optarg;
-                       break;
-               case 'U':
-                       update_item = TRUE;
-                       break;
-               case 'A':
-                       always_allow = TRUE;
-                       access_specified = TRUE;
-                       break;
-               case 'T':
-               {
-                       if (optarg[0])
-                       {
-                               SecTrustedApplicationRef app = NULL;
-                               /* check whether the argument specifies an application group */
-                               const char *groupPrefix = "group://";
-                               size_t prefixLen = strlen(groupPrefix);
-                               if (strlen(optarg) > prefixLen && !memcmp(optarg, groupPrefix, prefixLen)) {
-                                       const char *groupName = &optarg[prefixLen];
-                                       if ((status = SecTrustedApplicationCreateApplicationGroup(groupName, NULL, &app)) != noErr) {
-                                               sec_error("SecTrustedApplicationCreateApplicationGroup %s: %s", optarg, sec_errstr(status));
-                                       }
-                               } else {
-                                       if ((status = SecTrustedApplicationCreateFromPath(optarg, &app)) != noErr) {
-                                               sec_error("SecTrustedApplicationCreateFromPath %s: %s", optarg, sec_errstr(status));
-                                       }
-                               }
-
-                               if (status) {
-                                       result = 1;
-                                       goto cleanup;
-                               }
-
-                               CFArrayAppendValue(trusted_list, app);
-                               CFRelease(app);
-                       }
-                       access_specified = TRUE;
-                       break;
-               }
-               case '?':
-        case ':':
-            // They supplied the -p or -w but with no data, so prompt
-            // This differs from the case where no -p or -w was given, where we set the data to empty
-            if (optopt == 'p' || optopt == 'w') {
-                if (promptForPasswordData(&passwordData)) {
-                    mustFreePasswordData = true;
-                    break;
-                } else {
-                    result = 1;
-                    goto cleanup; /* @@@ Do not trigger usage message, but indicate failure. */
-                }
-            }
-            result = 2;
-            goto cleanup; /* @@@ Return 2 triggers usage message. */
-
-               default:
-                       result = 2;
-                       goto cleanup; /* @@@ Return 2 triggers usage message. */
-               }
-       }
-
-       argc -= optind;
-       argv += optind;
-
-       if (!accountName || !serverName)
-       {
-               result = 2;
-               goto cleanup;
-       }
-       else if (argc > 0)
-       {
-               keychainName = argv[0];
-               if (argc > 1 || *keychainName == '\0')
-               {
-                       result = 2;
-                       goto cleanup;
-               }
-       }
-
-       if (access_specified)
-       {
-               const char *accessName = (label) ? label : (serverName) ? serverName : (accountName) ? accountName : "";
-               if ((result = create_access(accessName, always_allow, trusted_list, &access)) != 0)
-                       goto cleanup;
-       }
-
-       result = do_add_internet_password(keychainName,
-                                                                         itemCreator,
-                                                                         itemType,
-                                                                         kind,
-                                                                         comment,
-                                                                         (label) ? label : serverName,
-                                                                         serverName,
-                                                                         securityDomain,
-                                                                         accountName,
-                                                                         path,
-                                                                         port,
-                                                                         protocol,
-                                                                         authenticationType,
-                                                                         passwordData,
-                                                                         access,
-                                                                         update_item);
-
-cleanup:
-    if (mustFreePasswordData)
-        free(passwordData);
-       if (trusted_list)
-               CFRelease(trusted_list);
-       if (access)
-               CFRelease(access);
-
-       return result;
-}
-
-int
-keychain_add_certificates(int argc, char * const *argv)
-{
-       int ch, result = 0;
-       const char *keychainName = NULL;
-       while ((ch = getopt(argc, argv, "hk:")) != -1)
-       {
-               switch  (ch)
-               {
-        case 'k':
-            keychainName = optarg;
-                       if (*keychainName == '\0')
-                               return SHOW_USAGE_MESSAGE;
-            break;
-               case '?':
-               default:
-                       return SHOW_USAGE_MESSAGE;
-               }
-       }
-
-       argc -= optind;
-       argv += optind;
-
-       if (argc == 0)
-               return SHOW_USAGE_MESSAGE;
-
-       result = do_add_certificates(keychainName, argc, argv);
-
-       return result;
-}