]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTool/security.c
Security-59306.11.20.tar.gz
[apple/security.git] / SecurityTool / security.c
diff --git a/SecurityTool/security.c b/SecurityTool/security.c
deleted file mode 100644 (file)
index 798d2e6..0000000
+++ /dev/null
@@ -1,1118 +0,0 @@
-/*
- * Copyright (c) 2003-2017 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@
- *
- * security.c
- */
-
-#include "security_tool.h"
-
-#include "leaks.h"
-#include "readline_cssm.h"
-
-#include "cmsutil.h"
-#include "db_commands.h"
-#include "keychain_add.h"
-#include "keychain_create.h"
-#include "keychain_delete.h"
-#include "keychain_list.h"
-#include "keychain_lock.h"
-#include "keychain_set_settings.h"
-#include "keychain_show_info.h"
-#include "keychain_unlock.h"
-#include "keychain_recode.h"
-#include "key_create.h"
-#include "keychain_find.h"
-#include "keychain_import.h"
-#include "keychain_export.h"
-#include "identity_find.h"
-#include "identity_prefs.h"
-#include "mds_install.h"
-#include "trusted_cert_add.h"
-#include "trusted_cert_dump.h"
-#include "user_trust_enable.h"
-#include "trust_settings_impexp.h"
-#include "verify_cert.h"
-#include "authz.h"
-#include "smartcards.h"
-#include "display_error_code.h"
-#include "createFVMaster.h"
-#include "smartcards.h"
-#include "translocate.h"
-#include "requirement.h"
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <dispatch/dispatch.h>
-
-#include <CoreFoundation/CFRunLoop.h>
-#include <Security/SecBasePriv.h>
-#include <Security/SecKeychainPriv.h>
-#include <security_asn1/secerr.h>
-
-/* Maximum length of an input line in interactive mode. */
-#define MAX_LINE_LEN 4096
-/* Maximum number of arguments on an input line in interactive mode. */
-#define MAX_ARGS 32
-
-/* Entry in commands array for a command. */
-typedef struct command
-{
-       const char *c_name;    /* name of the command. */
-       command_func c_func;   /* function to execute the command. */
-       const char *c_usage;   /* usage sting for command. */
-       const char *c_help;    /* help string for (or description of) command. */
-} command;
-
-/* The default prompt. */
-const char *prompt_string = "security> ";
-
-/* Forward declarations of static functions. */
-static int help(int argc, char * const *argv);
-
-/*
- * The command array itself.
- * Add commands here at will.
- * Matching is done on a prefix basis.  The first command in the array
- * gets matched first.
- */
-const command commands[] =
-{
-       { "help", help,
-         "[command ...]",
-         "Show all commands, or show usage for a command." },
-
-       { "list-keychains", keychain_list,
-         "[-d user|system|common|dynamic] [-s [keychain...]]\n"
-         "    -d  Use the specified preference domain\n"
-         "    -s  Set the search list to the specified keychains\n"
-         "With no parameters, display the search list.",
-         "Display or manipulate the keychain search list." },
-
-    { "list-smartcards", ctk_list,
-      "Display IDs of available smartcards.",
-      "Display available smartcards." },
-
-       { "default-keychain", keychain_default,
-         "[-d user|system|common|dynamic] [-s [keychain]]\n"
-         "    -d  Use the specified preference domain\n"
-         "    -s  Set the default keychain to the specified keychain\n"
-         "With no parameters, display the default keychain.",
-         "Display or set the default keychain." },
-
-       { "login-keychain", keychain_login,
-         "[-d user|system|common|dynamic] [-s [keychain]]\n"
-         "    -d  Use the specified preference domain\n"
-         "    -s  Set the login keychain to the specified keychain\n"
-         "With no parameters, display the login keychain.",
-         "Display or set the login keychain." },
-
-       { "create-keychain", keychain_create,
-         "[-P] [-p password] [keychains...]\n"
-         "    -p  Use \"password\" as the password for the keychains being created\n"
-         "    -P  Prompt the user for a password using the SecurityAgent\n"
-      "Use of the -p option is insecure",
-         "Create keychains and add them to the search list.",
-    },
-
-       { "delete-keychain", keychain_delete,
-         "[keychains...]",
-         "Delete keychains and remove them from the search list." },
-
-       { "lock-keychain", keychain_lock,
-         "[-a | keychain]\n"
-         "    -a  Lock all keychains",
-         "Lock the specified keychain."},
-
-       { "unlock-keychain", keychain_unlock,
-         "[-u] [-p password] [keychain]\n"
-         "    -p  Use \"password\" as the password to unlock the keychain\n"
-         "    -u  Do not use the password\n"
-      "Use of the -p option is insecure",
-         "Unlock the specified keychain."},
-
-       { "set-keychain-settings", keychain_set_settings,
-         "[-lu] [-t timeout] [keychain]\n"
-         "    -l  Lock keychain when the system sleeps\n"
-         "    -u  Lock keychain after timeout interval\n"
-         "    -t  Timeout in seconds (omitting this option specifies \"no timeout\")\n",
-         "Set settings for a keychain."},
-
-       { "set-keychain-password", keychain_set_password,
-         "[-o oldPassword] [-p newPassword] [keychain]\n"
-         "    -o  Old keychain password (if not provided, will prompt)\n"
-         "    -p  New keychain password (if not provided, will prompt)\n"
-      "Use of either the -o or -p options is insecure\n",
-         "Set password for a keychain."},
-
-       { "show-keychain-info", keychain_show_info,
-         "[keychain]",
-         "Show the settings for keychain." },
-
-       { "dump-keychain", keychain_dump,
-         "[-adir] [keychain...]\n"
-         "    -a  Dump access control list of items\n"
-         "    -d  Dump (decrypted) data of items\n"
-         "    -i  Interactive access control list editing mode\n"
-         "    -r  Dump the raw (encrypted) data of items",
-         "Dump the contents of one or more keychains." },
-
-#ifndef NDEBUG
-       { "recode-keychain", keychain_recode,
-         "keychain_to_recode keychain_to_get_secrets_from",
-         "Recode a keychain to use the secrets from another one."},
-#endif
-
-       { "create-keypair", key_create_pair,
-         "[-a alg] [-s size] [-f date] [-t date] [-d days] [-k keychain] [-A|-T appPath] description\n"
-         "    -a  Use alg as the algorithm, can be rsa, dh, dsa or fee (default rsa)\n"
-         "    -s  Specify the keysize in bits (default 512)\n"
-         "    -f  Make a key valid from the specified date\n"
-         "    -t  Make a key valid to the specified date\n"
-         "    -d  Make a key valid for the number of days specified from today\n"
-         "    -k  Use the specified keychain rather than the default\n"
-         "    -A  Allow any application to access this key without warning (insecure, not recommended!)\n"
-         "    -T  Specify an application which may access this key (multiple -T options are allowed)\n"
-         "If no options are provided, ask the user interactively.",
-         "Create an asymmetric key pair." },
-
-       #if 0
-       /* this was added in mb's integration of PR-3420772, but this is an unimplemented command */
-       { "create-csr", csr_create,
-         "[-a alg] [-s size] [-f date] [-t date] [-d days] [-k keychain] [-A|-T appPath] description\n"
-         "    -a  Use alg as the algorithm, can be rsa, dh, dsa or fee (default rsa)\n"
-         "    -s  Specify the keysize in bits (default 512)\n"
-         "    -f  Make a key valid from the specified date\n"
-         "    -t  Make a key valid to the specified date\n"
-         "    -d  Make a key valid for the number of days specified from today\n"
-         "    -k  Use the specified keychain rather than the default\n"
-         "    -A  Allow any application to access this key without warning (insecure, not recommended!)\n"
-         "    -T  Specify an application which may access this key (multiple -T options are allowed)\n"
-         "If no options are provided, ask the user interactively.",
-         "Create a certificate signing request." },
-       #endif
-
-       { "add-generic-password", keychain_add_generic_password,
-         "[-a account] [-s service] [-w password] [options...] [-A|-T appPath] [keychain]\n"
-         "    -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"
-         "\n"
-         "By default, the application which creates an item is trusted to access its data without warning.\n"
-         "You can remove this default access by explicitly specifying an empty app pathname: -T \"\"\n"
-         "If no keychain is specified, the password is added to the default keychain.\n"
-      "Use of the -p or -w options is insecure. Specify -w as the last option to be prompted.\n",
-         "Add a generic password item."},
-
-       { "add-internet-password", keychain_add_internet_password,
-         "[-a account] [-s server] [-w password] [options...] [-A|-T appPath] [keychain]\n"
-         "    -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"
-         "\n"
-         "By default, the application which creates an item is trusted to access its data without warning.\n"
-         "You can remove this default access by explicitly specifying an empty app pathname: -T \"\"\n"
-         "If no keychain is specified, the password is added to the default keychain.\n"
-      "Use of the -p or -w options is insecure. Specify -w as the last option to be prompted.\n",
-         "Add an internet password item."},
-
-       { "add-certificates", keychain_add_certificates,
-         "[-k keychain] file...\n"
-         "If no keychain is specified, the certificates are added to the default keychain.",
-         "Add certificates to a keychain."},
-
-       { "find-generic-password", keychain_find_generic_password,
-         "[-a account] [-s service] [options...] [-g] [keychain...]\n"
-         "    -a  Match \"account\" string\n"
-         "    -c  Match \"creator\" (four-character code)\n"
-         "    -C  Match \"type\" (four-character code)\n"
-         "    -D  Match \"kind\" string\n"
-         "    -G  Match \"value\" string (generic attribute)\n"
-         "    -j  Match \"comment\" string\n"
-         "    -l  Match \"label\" string\n"
-         "    -s  Match \"service\" string\n"
-         "    -g  Display the password for the item found\n"
-         "    -w  Display only the password on stdout\n"
-         "If no keychains are specified to search, the default search list is used.",
-         "Find a generic password item."},
-
-       { "delete-generic-password", keychain_delete_generic_password,
-               "[-a account] [-s service] [options...] [keychain...]\n"
-               "    -a  Match \"account\" string\n"
-               "    -c  Match \"creator\" (four-character code)\n"
-               "    -C  Match \"type\" (four-character code)\n"
-               "    -D  Match \"kind\" string\n"
-               "    -G  Match \"value\" string (generic attribute)\n"
-               "    -j  Match \"comment\" string\n"
-               "    -l  Match \"label\" string\n"
-               "    -s  Match \"service\" string\n"
-               "If no keychains are specified to search, the default search list is used.",
-               "Delete a generic password item."},
-
-    { "set-generic-password-partition-list", keychain_set_generic_password_partition_list,
-        "[-a account] [-s service] [-S partition-list] [-k keychain password] [options...] [keychain]\n"
-        "    -a  Match \"account\" string\n"
-        "    -c  Match \"creator\" (four-character code)\n"
-        "    -C  Match \"type\" (four-character code)\n"
-        "    -D  Match \"kind\" string\n"
-        "    -G  Match \"value\" string (generic attribute)\n"
-        "    -j  Match \"comment\" string\n"
-        "    -l  Match \"label\" string\n"
-        "    -s  Match \"service\" string\n"
-        "    -S  Comma-separated list of allowed partition IDs\n"
-        "    -k  The password for the keychain (required)\n"
-        "If no keychains are specified to search, the default search list is used.\n"
-        "Use of the -k option is insecure. Omit it to be prompted.\n",
-        "Set the partition list of a generic password item."},
-
-       { "find-internet-password", keychain_find_internet_password,
-         "[-a account] [-s server] [options...] [-g] [keychain...]\n"
-         "    -a  Match \"account\" string\n"
-         "    -c  Match \"creator\" (four-character code)\n"
-         "    -C  Match \"type\" (four-character code)\n"
-         "    -d  Match \"securityDomain\" string\n"
-         "    -D  Match \"kind\" string\n"
-         "    -j  Match \"comment\" string\n"
-         "    -l  Match \"label\" string\n"
-         "    -p  Match \"path\" string\n"
-         "    -P  Match port number\n"
-         "    -r  Match \"protocol\" (four-character code)\n"
-         "    -s  Match \"server\" string\n"
-         "    -t  Match \"authenticationType\" (four-character code)\n"
-         "    -g  Display the password for the item found\n"
-         "    -w  Display only the password on stdout\n"
-         "If no keychains are specified to search, the default search list is used.",
-         "Find an internet password item."},
-
-       { "delete-internet-password", keychain_delete_internet_password,
-               "[-a account] [-s server] [options...] [keychain...]\n"
-               "    -a  Match \"account\" string\n"
-               "    -c  Match \"creator\" (four-character code)\n"
-               "    -C  Match \"type\" (four-character code)\n"
-               "    -d  Match \"securityDomain\" string\n"
-               "    -D  Match \"kind\" string\n"
-               "    -j  Match \"comment\" string\n"
-               "    -l  Match \"label\" string\n"
-               "    -p  Match \"path\" string\n"
-               "    -P  Match port number\n"
-               "    -r  Match \"protocol\" (four-character code)\n"
-               "    -s  Match \"server\" string\n"
-               "    -t  Match \"authenticationType\" (four-character code)\n"
-               "If no keychains are specified to search, the default search list is used.",
-               "Delete an internet password item."},
-
-    { "set-internet-password-partition-list", keychain_set_internet_password_partition_list,
-        "[-a account] [-s service] [-S partition-list] [-k keychain password] [options...] [keychain]\n"
-        "    -a  Match \"account\" string\n"
-        "    -c  Match \"creator\" (four-character code)\n"
-        "    -C  Match \"type\" (four-character code)\n"
-        "    -d  Match \"securityDomain\" string\n"
-        "    -D  Match \"kind\" string\n"
-        "    -j  Match \"comment\" string\n"
-        "    -l  Match \"label\" string\n"
-        "    -p  Match \"path\" string\n"
-        "    -P  Match port number\n"
-        "    -r  Match \"protocol\" (four-character code)\n"
-        "    -s  Match \"server\" string\n"
-        "    -t  Match \"authenticationType\" (four-character code)\n"
-        "    -S  Comma-separated list of allowed partition IDs\n"
-        "    -k  password for keychain (required)\n"
-
-        "If no keychains are specified to search, the default search list is used.\n"
-        "Use of the -k option is insecure. Omit it to be prompted.\n",
-        "Set the partition list of a internet password item."},
-
-    { "find-key", keychain_find_key,
-        "[options...] [keychain...]\n"
-        "    -a  Match \"application label\" string\n"
-        "    -c  Match \"creator\" (four-character code)\n"
-        "    -d  Match keys that can decrypt\n"
-        "    -D  Match \"description\" string\n"
-        "    -e  Match keys that can encrypt\n"
-        "    -j  Match \"comment\" string\n"
-        "    -l  Match \"label\" string\n"
-        "    -r  Match keys that can derive\n"
-        "    -s  Match keys that can sign\n"
-        "    -t  Type of key to find: one of \"symmetric\", \"public\", or \"private\"\n"
-        "    -u  Match keys that can unwrap\n"
-        "    -v  Match keys that can verify\n"
-        "    -w  Match keys that can wrap\n"
-
-        "If no keychains are specified to search, the default search list is used.",
-        "Find keys in the keychain"},
-
-    { "set-key-partition-list", keychain_set_key_partition_list,
-        "[options...] [keychain]\n"
-        "    -a  Match \"application label\" string\n"
-        "    -c  Match \"creator\" (four-character code)\n"
-        "    -d  Match keys that can decrypt\n"
-        "    -D  Match \"description\" string\n"
-        "    -e  Match keys that can encrypt\n"
-        "    -j  Match \"comment\" string\n"
-        "    -l  Match \"label\" string\n"
-        "    -r  Match keys that can derive\n"
-        "    -s  Match keys that can sign\n"
-        "    -t  Type of key to find: one of \"symmetric\", \"public\", or \"private\"\n"
-        "    -u  Match keys that can unwrap\n"
-        "    -v  Match keys that can verify\n"
-        "    -w  Match keys that can wrap\n"
-        "    -S  Comma-separated list of allowed partition IDs\n"
-        "    -k  password for keychain (required)\n"
-
-        "If no keychains are specified to search, the default search list is used.",
-        "Set the partition list of a key."},
-
-       { "find-certificate", keychain_find_certificate,
-         "[-a] [-c name] [-e emailAddress] [-m] [-p] [-Z] [keychain...]\n"
-         "    -a  Find all matching certificates, not just the first one\n"
-         "    -c  Match on \"name\" when searching (optional)\n"
-         "    -e  Match on \"emailAddress\" when searching (optional)\n"
-         "    -m  Show the email addresses in the certificate\n"
-         "    -p  Output certificate in pem format\n"
-         "    -Z  Print SHA-1 hash of the certificate\n"
-         "If no keychains are specified to search, the default search list is used.",
-         "Find a certificate item."},
-
-       { "find-identity", keychain_find_identity,
-               "[-p policy] [-s string] [-v] [keychain...]\n"
-               "    -p  Specify policy to evaluate (multiple -p options are allowed)\n"
-               "        Supported policies: basic, ssl-client, ssl-server, smime, eap,\n"
-               "        ipsec, ichat, codesigning, sys-default, sys-kerberos-kdc, macappstore, appleID\n"
-               "    -s  Specify optional policy-specific string (e.g. DNS hostname for SSL,\n"
-               "        or RFC822 email address for S/MIME)\n"
-               "    -v  Show valid identities only (default is to show all identities)\n"
-               "If no keychains are specified to search, the default search list is used.",
-       "Find an identity (certificate + private key)."},
-
-       { "delete-certificate", keychain_delete_certificate,
-         "[-c name] [-Z hash] [-t] [keychain...]\n"
-         "    -c  Specify certificate to delete by its common name\n"
-         "    -Z  Specify certificate to delete by its SHA-1 hash value\n"
-         "    -t  Also delete user trust settings for this certificate\n"
-         "The certificate to be deleted must be uniquely specified either by a\n"
-         "string found in its common name, or by its SHA-1 hash.\n"
-         "If no keychains are specified to search, the default search list is used.",
-         "Delete a certificate from a keychain."},
-
-       { "delete-identity", keychain_delete_identity,
-         "[-c name] [-Z hash] [-t] [keychain...]\n"
-         "    -c  Specify certificate to delete by its common name\n"
-         "    -Z  Specify certificate to delete by its SHA-1 hash value\n"
-         "    -t  Also delete user trust settings for this identity certificate\n"
-         "The identity to be deleted must be uniquely specified either by a\n"
-         "string found in its common name, or by its SHA-1 hash.\n"
-         "If no keychains are specified to search, the default search list is used.",
-         "Delete an identity (certificate + private key) from a keychain."},
-
-       { "set-identity-preference", set_identity_preference,
-         "[-n] [-c identity] [-s service] [-u keyUsage] [-Z hash] [keychain...]\n"
-         "    -n  Specify no identity (clears existing preference for service)\n"
-         "    -c  Specify identity by common name of the certificate\n"
-         "    -s  Specify service (may be a URL, RFC822 email address, DNS host, or\n"
-         "        other name) for which this identity is to be preferred\n"
-         "    -u  Specify key usage (optional) - see man page for values\n"
-         "    -Z  Specify identity by SHA-1 hash of certificate (optional)\n",
-         "Set the preferred identity to use for a service."},
-
-       { "get-identity-preference", get_identity_preference,
-               "[-s service] [-u keyUsage] [-p] [-c] [-Z] [keychain...]\n"
-               "    -s  Specify service (may be a URL, RFC822 email address, DNS host, or\n"
-               "        other name)\n"
-               "    -u  Specify key usage (optional) - see man page for values\n"
-               "    -p  Output identity certificate in pem format\n"
-               "    -c  Print common name of the preferred identity certificate\n"
-               "    -Z  Print SHA-1 hash of the preferred identity certificate\n",
-       "Get the preferred identity to use for a service."},
-
-       { "create-db", db_create,
-         "[-ao0] [-g dl|cspdl] [-m mode] [name]\n"
-         "    -a  Turn off autocommit\n"
-         "    -g  Attach to \"guid\" rather than the AppleFileDL\n"
-         "    -m  Set the inital mode of the created db to \"mode\"\n"
-         "    -o  Force using openparams argument\n"
-         "    -0  Force using version 0 openparams\n"
-         "If no name is provided, ask the user interactively.",
-         "Create a db using the DL." },
-
-       { "export" , keychain_export,
-         "[-k keychain] [-t type] [-f format] [-w] [-p] [-P passphrase] [-o outfile]\n"
-         "    -k  keychain to export items from\n"
-         "    -t  Type = certs|allKeys|pubKeys|privKeys|identities|all  (Default: all)\n"
-         "    -f  Format = openssl|openssh1|openssh2|bsafe|pkcs7|pkcs8|pkcs12|pemseq|x509\n"
-         "        ...default format is pemseq for aggregate, openssl for single\n"
-         "    -w  Private keys are wrapped\n"
-         "    -p  PEM encode the output\n"
-         "    -P  Specify wrapping passphrase immediately (default is secure passphrase via GUI)\n"
-         "    -o  Specify output file (default is stdout)\n"
-         "Use of the -P option is insecure\n",
-         "Export items from a keychain." },
-
-       { "import", keychain_import,
-         "inputfile [-k keychain] [-t type] [-f format] [-w] [-P passphrase] [options...]\n"
-         "    -k  Target keychain to import into\n"
-         "    -t  Type = pub|priv|session|cert|agg\n"
-         "    -f  Format = openssl|openssh1|openssh2|bsafe|raw|pkcs7|pkcs8|pkcs12|netscape|pemseq\n"
-         "    -w  Specify that private keys are wrapped and must be unwrapped on import\n"
-         "    -x  Specify that private keys are non-extractable after being imported\n"
-         "    -P  Specify wrapping passphrase immediately (default is secure passphrase via GUI)\n"
-         "    -a  Specify name and value of extended attribute (can be used multiple times)\n"
-         "    -A  Allow any application to access the imported key without warning (insecure, not recommended!)\n"
-         "    -T  Specify an application which may access the imported key (multiple -T options are allowed)\n"
-         "Use of the -P option is insecure\n",
-         "Import items into a keychain." },
-
-    { "export-smartcard" , ctk_export,
-        "[-i id] [-t type] [-e exportPath] \n"
-        "    -i  id of the smartcard to export (available IDs can be listed by list-smartcards\n"
-        "        command, default: export/display all smartcards)\n"
-        "    -t  Type = certs|privKeys|identities|all  (Default: all)\n"
-        "    -e  Specify path to export certificates and public keys. This option cannot be combined with -t option.\n",
-        "Export items from a smartcard." },
-
-       { "cms", cms_util,
-         "[-C|-D|-E|-S] [<options>]\n"
-         "  -C           create a CMS encrypted message\n"
-         "  -D           decode a CMS message\n"
-         "  -E           create a CMS enveloped message\n"
-         "  -S           create a CMS signed message\n"
-         "\n"
-         "Decoding options:\n"
-         "  -c content   use this detached content file\n"
-         "  -h level     generate email headers with info about CMS message\n"
-         "                 (output level >= 0)\n"
-         "  -n           suppress output of content\n"
-         "\n"
-         "Encoding options:\n"
-         "  -r id,...    create envelope for these recipients,\n"
-         "               where id can be a certificate nickname or email address\n"
-         "  -G           include a signing time attribute\n"
-         "  -H hash      hash = MD2|MD4|MD5|SHA1|SHA256|SHA384|SHA512 (default: SHA1)\n"
-         "  -N nick      use certificate named \"nick\" for signing\n"
-         "  -P           include a SMIMECapabilities attribute\n"
-         "  -T           do not include content in CMS message\n"
-         "  -Y nick      include an EncryptionKeyPreference attribute with certificate\n"
-         "                 (use \"NONE\" to omit)\n"
-         "  -Z hash      find a certificate by subject key ID\n"
-         "\n"
-         "Common options:\n"
-         "  -e envelope  specify envelope file (valid with -D or -E)\n"
-         "  -k keychain  specify keychain to use\n"
-         "  -i infile    use infile as source of data (default: stdin)\n"
-         "  -o outfile   use outfile as destination of data (default: stdout)\n"
-         "  -p password  use password as key db password (default: prompt). Using -p is insecure\n"
-         "  -s           pass data a single byte at a time to CMS\n"
-         "  -u certusage set type of certificate usage (default: certUsageEmailSigner)\n"
-         "  -v           print debugging information\n"
-         "\n"
-         "Cert usage codes:\n"
-         "                  0 - certUsageSSLClient\n"
-         "                  1 - certUsageSSLServer\n"
-         "                  2 - certUsageSSLServerWithStepUp\n"
-         "                  3 - certUsageSSLCA\n"
-         "                  4 - certUsageEmailSigner\n"
-         "                  5 - certUsageEmailRecipient\n"
-         "                  6 - certUsageObjectSigner\n"
-         "                  7 - certUsageUserCertImport\n"
-         "                  8 - certUsageVerifyCA\n"
-         "                  9 - certUsageProtectedObjectSigner\n"
-         "                 10 - certUsageStatusResponder\n"
-         "                 11 - certUsageAnyCA",
-         "Encode or decode CMS messages." },
-
-       { "install-mds" , mds_install,
-         "",           /* no options */
-         "Install (or re-install) the MDS database." },
-
-       { "add-trusted-cert" , trusted_cert_add,
-         " [<options>] [certFile]\n"
-         "    -d                  Add to admin cert store; default is user\n"
-         "    -r resultType       resultType = trustRoot|trustAsRoot|deny|unspecified;\n"
-         "                              default is trustRoot\n"
-         "    -p policy           Specify policy constraint (ssl, smime, codeSign, IPSec, iChat,\n"
-         "                              basic, swUpdate, pkgSign, pkinitClient, pkinitServer, eap)\n"
-         "    -a appPath          Specify application constraint\n"
-         "    -s policyString     Specify policy-specific string\n"
-         "    -e allowedError     Specify allowed error (certExpired, hostnameMismatch) or integer\n"
-         "    -u keyUsage         Specify key usage, an integer\n"
-         "    -k keychain         Specify keychain to which cert is added\n"
-         "    -i settingsFileIn   Input trust settings file; default is user domain\n"
-         "    -o settingsFileOut  Output trust settings file; default is user domain\n"
-         "    certFile            Certificate(s)",
-         "Add trusted certificate(s)." },
-
-       { "remove-trusted-cert" , trusted_cert_remove,
-         " [-d] [-D] [certFile]\n"
-         "    -d                  Remove from admin cert store (default is user)\n"
-         "    -D                  Remove default setting instead of per-cert setting\n"
-         "    certFile            Certificate(s)",
-         "Remove trusted certificate(s)." },
-
-       { "dump-trust-settings" , trusted_cert_dump,
-         " [-s] [-d]\n"
-         "    -s                  Display trusted system certs (default is user)\n"
-         "    -d                  Display trusted admin certs (default is user)\n",
-         "Display contents of trust settings." },
-
-       { "user-trust-settings-enable", user_trust_enable,
-         "[-d] [-e]\n"
-         "    -d                  Disable user-level trust Settings\n"
-         "    -e                  Enable user-level trust Settings\n"
-         "With no parameters, show current enable state of user-level trust settings.",
-         "Display or manipulate user-level trust settings." },
-
-       { "trust-settings-export", trust_settings_export,
-         " [-s] [-d] settings_file\n"
-         "    -s                  Export system trust settings (default is user)\n"
-         "    -d                  Export admin trust settings (default is user)\n",
-         "Export trust settings." },
-
-       { "trust-settings-import", trust_settings_import,
-         " [-d] settings_file\n"
-         "    -d                  Import admin trust settings (default is user)\n",
-         "Import trust settings." },
-
-       { "verify-cert" , verify_cert,
-         " [<options>]\n"
-         "    -c certFile         Certificate to verify. Can be specified multiple times, leaf first.\n"
-         "    -r rootCertFile     Root Certificate. Can be specified multiple times.\n"
-         "    -p policy           Verify Policy (basic, ssl, smime, codeSign, IPSec, swUpdate, pkgSign,\n"
-         "                        eap, appleID, macappstore, timestamping); default is basic.\n"
-         "    -C                  Set client policy to true. Default is server policy. (ssl, IPSec, eap)\n"
-         "    -d date             Set date and time to use when verifying certificate,\n"
-         "                        provided in the form of YYYY-MM-DD-hh:mm:ss (time optional) in GMT.\n"
-         "                        e.g: 2016-04-25-15:59:59 for April 25, 2016 at 3:59:59 pm in GMT\n"
-         "    -k keychain         Keychain. Can be specified multiple times. Default is default search list.\n"
-         "    -n name             Name to be verified. (ssl, IPSec, smime)\n"
-         "    -N                  No keychain search list. (For backward compatibility, -n without a\n"
-         "                        subsequent name argument is interpreted as equivalent to -N.)\n"
-         "    -L                  Local certificates only (do not try to fetch missing CA certs from net).\n"
-         "    -l                  Leaf cert is a CA (normally an error, unless this option is given).\n"
-         "    -e emailAddress     Email address for smime policy. (Deprecated; use -n instead.)\n"
-         "    -s sslHost          SSL host name for ssl policy. (Deprecated; use -n instead.)\n"
-         "    -q                  Quiet.\n"
-         "    -R revCheckOption   Perform revocation checking with one of the following options:\n"
-         "                            ocsp     Check revocation status using OCSP method.\n"
-         "                            crl      Check revocation status using CRL method.\n"
-         "                            require  Require a positive response for successful verification.\n"
-         "                            offline  Consult cached responses only (no network requests).\n"
-         "                        Can be specified multiple times; e.g. to enable revocation checking\n"
-         "                        via either OCSP or CRL methods and require a positive response, use\n"
-         "                        \"-R ocsp -R crl -R require\".\n",
-         "Verify certificate(s)." },
-
-       { "authorize" , authorize,
-         "[<options>] <right(s)...>\n"
-         "  -u        Allow user interaction.\n"
-         "  -c        Use login name and prompt for password.\n"
-         "  -C login  Use given login name and prompt for password.\n"
-         "  -x        Do NOT share -c/-C explicit credentials\n"
-#ifndef NDEBUG
-         "  -E        Don't extend rights.\n"
-#endif
-         "  -p        Allow returning partial rights.\n"
-         "  -d        Destroy acquired rights.\n"
-         "  -P        Pre-authorize rights only.\n"
-         "  -l        Operate authorizations in least privileged mode.\n"
-         "  -i        Internalize authref passed on stdin.\n"
-         "  -e        Externalize authref to stdout.\n"
-         "  -w        Wait until stdout is closed (to allow reading authref from pipe).\n"
-         "Extend rights flag is passed per default.",
-         "Perform authorization operations." },
-
-       { "authorizationdb" , authorizationdb,
-         "read <right-name>\n"
-         "       authorizationdb remove <right-name>\n"
-         "       authorizationdb write <right-name> [allow|deny|<rulename>]\n"
-         "If no rulename is specified, write will read a plist from stdin.\n"
-         "       authorizationdb merge source [destination]\n"
-         "If no destination path is specified, merge will merge to /etc/authorization.\n"
-      "       authorizationdb smartcard <enable|disable|status>\n"
-      "Enables/disables smartcard login support or report current status.",
-      "Make changes to the authorization policy database." },
-
-       { "execute-with-privileges" , execute_with_privileges,
-         "<program> [args...]\n"
-         "On success, stdin will be read and forwarded to the tool.",
-         "Execute tool with privileges." },
-
-       { "leaks", leaks,
-         "[-cycles] [-nocontext] [-nostacks] [-exclude symbol]\n"
-         "    -cycles       Use a stricter algorithm (\"man leaks\" for details)\n"
-         "    -nocontext    Withhold hex dumps of the leaked memory\n"
-         "    -nostacks     Don't show stack traces of leaked memory\n"
-         "    -exclude      Ignore leaks called from \"symbol\"\n"
-         "(Set the environment variable MallocStackLogging to get symbolic traces.)",
-         "Run /usr/bin/leaks on this process." },
-
-       { "error", display_error_code,
-         "<error code(s)...>\n"
-         "Display an error string for the given security-related error code.\n"
-         "The error can be in decimal or hex, e.g. 1234 or 0x1234. Multiple "
-         "errors can be separated by spaces.",
-         "Display a descriptive message for the given error code(s)." },
-
-       { "create-filevaultmaster-keychain", keychain_createMFV,
-         "[-p password] [keychain name]\n"
-         "    -p       Use \"password\" as the password for the keychain being created\n"
-      "    -s  Specify the keysize in bits (default 2048; 1024 & 4096 are allowed)\n"
-         "By default the keychain will be created in ~/Library/Keychains/.\n"
-         "Use of the -p option is insecure. Omit it to be prompted.\n",
-      "Create a keychain containing a key pair for FileVault recovery use."
-      },
-
-    { "smartcards" , smartcards,
-        "token [-l] [-e token] [-d token]\n"
-        "  -l         List disabled smartcard tokens]\n"
-        "  -e token   Enable specified token\n"
-        "  -d token   Disable specified token\n",
-        "Enable, disable or list disabled smartcard tokens." },
-
-    { "translocate-create", translocate_create,
-      "<path to translocate>\n"
-      "Displays the created path or the error returned.",
-      "Create a translocation point for the provided path" },
-
-    { "translocate-policy-check", translocate_policy,
-        "<path to check>\n"
-        "Displays \"Would translocate\" or \"Would not translocate\"\n"
-        "based on the current state of the path and system policy.",
-        "Check whether a path would be translocated." },
-
-    { "translocate-status-check", translocate_check,
-        "<path to check>\n"
-        "Displays \"TRANSLOCATED\" or \"NOT TRANSLOCATED\"\n"
-        "for the given path.",
-        "Check whether a path is translocated." },
-
-    { "translocate-original-path", translocate_original_path,
-        "<path to check>\n"
-        "If the provided path is translocated, display the original path\n"
-        "If the provided path is not translocated, display the passed in path",
-        "Find the original path for a translocated path." },
-
-    { "requirement-evaluate", requirement_evaluate,
-        "<requirements> [<DER certificate file> ...]\n"
-        "Evaluates the given requirement string against the given cert chain.",
-        "Evaluate a requirement against a cert chain." },
-
-    {}
-};
-
-/* Global variables. */
-int do_quiet = 0;
-int do_verbose = 0;
-
-/* Return 1 if name matches command. */
-static int
-match_command(const char *command, const char *name)
-{
-       return !strncmp(command, name, strlen(name));
-}
-
-/* The help command. */
-static int
-help(int argc, char * const *argv)
-{
-       const command *c;
-
-       if (argc > 1)
-       {
-               char * const *arg;
-               for (arg = argv + 1; *arg; ++arg)
-               {
-                       int found = 0;
-
-                       for (c = commands; c->c_name; ++c)
-                       {
-                               if (match_command(c->c_name, *arg))
-                               {
-                                       found = 1;
-                                       break;
-                               }
-                       }
-
-                       if (found)
-                               printf("Usage: %s %s\n", c->c_name, c->c_usage);
-                       else
-                       {
-                               sec_error("%s: no such command: %s", argv[0], *arg);
-                               return 1;
-                       }
-               }
-       }
-       else
-       {
-               for (c = commands; c->c_name; ++c)
-                       printf("    %-36s %s\n", c->c_name, c->c_help);
-       }
-
-       return 0;
-}
-
-/* States for split_line parser. */
-typedef enum
-{
-       SKIP_WS,
-       READ_ARG,
-       READ_ARG_ESCAPED,
-       QUOTED_ARG,
-       QUOTED_ARG_ESCAPED
-} parse_state;
-
-/* Split a line into multiple arguments and return them in *pargc and *pargv. */
-static void
-split_line(char *line, int *pargc, char * const **pargv)
-{
-       static char *argvec[MAX_ARGS + 1];
-       int argc = 0;
-       char *ptr = line;
-       char *dst = line;
-       parse_state state = SKIP_WS;
-       int quote_ch = 0;
-
-       for (ptr = line; *ptr; ++ptr)
-       {
-               if (state == SKIP_WS)
-               {
-                       if (isspace(*ptr))
-                               continue;
-
-                       if (*ptr == '"' || *ptr == '\'')
-                       {
-                               quote_ch = *ptr;
-                               state = QUOTED_ARG;
-                               argvec[argc] = dst;
-                               continue; /* Skip the quote. */
-                       }
-                       else
-                       {
-                               state = READ_ARG;
-                               argvec[argc] = dst;
-                       }
-               }
-
-               if (state == READ_ARG)
-               {
-                       if (*ptr == '\\')
-                       {
-                               state = READ_ARG_ESCAPED;
-                               continue;
-                       }
-                       else if (isspace(*ptr))
-                       {
-                               /* 0 terminate each arg. */
-                               *dst++ = '\0';
-                               argc++;
-                               state = SKIP_WS;
-                               if (argc >= MAX_ARGS)
-                                       break;
-                       }
-                       else
-                               *dst++ = *ptr;
-               }
-
-               if (state == QUOTED_ARG)
-               {
-                       if (*ptr == '\\')
-                       {
-                               state = QUOTED_ARG_ESCAPED;
-                               continue;
-                       }
-                       if (*ptr == quote_ch)
-                       {
-                               /* 0 terminate each arg. */
-                               *dst++ = '\0';
-                               argc++;
-                               state = SKIP_WS;
-                               if (argc >= MAX_ARGS)
-                                       break;
-                       }
-                       else
-                               *dst++ = *ptr;
-               }
-
-               if (state == READ_ARG_ESCAPED)
-               {
-                       *dst++ = *ptr;
-                       state = READ_ARG;
-               }
-
-               if (state == QUOTED_ARG_ESCAPED)
-               {
-                       *dst++ = *ptr;
-                       state = QUOTED_ARG;
-               }
-       }
-
-       if (state != SKIP_WS)
-       {
-               /* Terminate last arg. */
-               *dst++ = '\0';
-               argc++;
-       }
-
-       /* Teminate arg vector. */
-       argvec[argc] = NULL;
-
-       *pargv = argvec;
-       *pargc = argc;
-}
-
-/* Print a (hopefully) useful usage message. */
-static int
-usage(void)
-{
-       printf(
-               "Usage: %s [-h] [-i] [-l] [-p prompt] [-q] [-v] [command] [opt ...]\n"
-               "    -i    Run in interactive mode.\n"
-               "    -l    Run /usr/bin/leaks -nocontext before exiting.\n"
-               "    -p    Set the prompt to \"prompt\" (implies -i).\n"
-               "    -q    Be less verbose.\n"
-               "    -v    Be more verbose about what's going on.\n"
-               "%s commands are:\n", getprogname(), getprogname());
-       help(0, NULL);
-       return SHOW_USAGE_MESSAGE;
-}
-
-/* Execute a single command. */
-static int
-execute_command(int argc, char * const *argv)
-{
-       const command *c;
-       int found = 0;
-
-       /* Nothing to do. */
-       if (argc == 0)
-               return 0;
-
-       for (c = commands; c->c_name; ++c)
-       {
-               if (match_command(c->c_name, argv[0]))
-               {
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (found)
-       {
-               int result;
-
-               /* Reset getopt for command proc. */
-               optind = 1;
-               optreset = 1;
-
-               if (do_verbose)
-               {
-                       int ix;
-
-                       fprintf(stderr, "%s", c->c_name);
-                       for (ix = 1; ix < argc; ++ix)
-                               fprintf(stderr, " \"%s\"", argv[ix]);
-                       fprintf(stderr, "\n");
-               }
-
-               result = c->c_func(argc, argv);
-               if (result == 2)
-                       fprintf(stderr, "Usage: %s %s\n        %s\n", c->c_name, c->c_usage, c->c_help);
-
-               return result;
-       }
-       else
-       {
-               sec_error("unknown command \"%s\"", argv[0]);
-               return 1;
-       }
-}
-
-static void
-receive_notifications(void)
-{
-       /* Run the CFRunloop to get any pending notifications. */
-       while (CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.0, TRUE) == kCFRunLoopRunHandledSource);
-}
-
-
-const char *
-sec_errstr(int err)
-{
-    const char *errString;
-    if (IS_SEC_ERROR(err))
-        errString = SECErrorString(err);
-    else
-        errString = cssmErrorString(err);
-    return errString;
-}
-
-void
-sec_error(const char *msg, ...)
-{
-    va_list args;
-
-    fprintf(stderr, "%s: ", getprogname());
-
-    va_start(args, msg);
-    vfprintf(stderr, msg, args);
-    va_end(args);
-
-    fprintf(stderr, "\n");
-}
-
-void
-sec_perror(const char *msg, int err)
-{
-    sec_error("%s: %s", msg, sec_errstr(err));
-}
-
-int
-main(int argc, char * const *argv)
-{
-       int result = 0;
-       int do_help = 0;
-       int do_interactive = 0;
-       int do_leaks = 0;
-       int ch;
-
-
-       /* Do getopt stuff for global options. */
-       optind = 1;
-       optreset = 1;
-       while ((ch = getopt(argc, argv, "hilp:qvR")) != -1)
-       {
-               switch  (ch)
-               {
-               case 'h':
-                       do_help = 1;
-                       break;
-               case 'i':
-                       do_interactive = 1;
-                       break;
-               case 'l':
-                       do_leaks = 1;
-                       break;
-               case 'p':
-                       do_interactive = 1;
-                       prompt_string = optarg;
-                       break;
-               case 'q':
-                       do_quiet = 1;
-                       break;
-               case 'v':
-                       do_verbose = 1;
-                       break;
-               case 'R':
-                       // "Recovery mode", do NOT ask security-checksystem to run when using keychain APIs
-                       // NOTE: this is a hidden option (not in the usage message)
-                SecKeychainSystemKeychainCheckWouldDeadlock();
-                       break;
-               case '?':
-               default:
-                       return usage();
-               }
-       }
-
-       argc -= optind;
-       argv += optind;
-
-       if (do_help)
-       {
-               /* Munge argc/argv so that argv[0] is something. */
-               return help(argc + 1, argv - 1);
-       }
-       else if (argc > 0)
-       {
-               receive_notifications();
-               result = execute_command(argc, argv);
-               receive_notifications();
-       }
-       else if (do_interactive)
-       {
-               /* In interactive mode we just read commands and run them until readline returns NULL. */
-
-        /* Only show prompt string if stdin is a tty. */
-        int show_prompt = isatty(0);
-
-               for (;;)
-               {
-                       static char buffer[MAX_LINE_LEN];
-                       char * const *av, *input;
-                       int ac;
-
-            if (show_prompt)
-                fprintf(stderr, "%s", prompt_string);
-
-                       input = readline(buffer, MAX_LINE_LEN);
-                       if (!input)
-                               break;
-
-                       split_line(input, &ac, &av);
-                       receive_notifications();
-                       result = execute_command(ac, av);
-                       receive_notifications();
-                       if (result == -1)
-                       {
-                               result = 0;
-                               break;
-                       }
-
-                       if (result && ! do_quiet)
-                       {
-                               fprintf(stderr, "%s: returned %d\n", av[0], result);
-                       }
-               }
-       }
-       else
-               result = usage();
-
-       if (do_leaks)
-       {
-               char *const argvec[3] = { "leaks", "-nocontext", NULL };
-               leaks(2, argvec);
-       }
-
-       return result;
-}