diff options
Diffstat (limited to 'security/nss/cmd/pkiutil/pkiutil.c')
-rw-r--r-- | security/nss/cmd/pkiutil/pkiutil.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/security/nss/cmd/pkiutil/pkiutil.c b/security/nss/cmd/pkiutil/pkiutil.c new file mode 100644 index 000000000..b059baa87 --- /dev/null +++ b/security/nss/cmd/pkiutil/pkiutil.c @@ -0,0 +1,376 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nspr.h" +#include "prtypes.h" +#include "prtime.h" +#include "prlong.h" +#include "nss.h" +#include "cmdutil.h" +#include "nsspki.h" +/* hmmm...*/ +#include "pki.h" + +#define PKIUTIL_VERSION_STRING "pkiutil version 0.1" + +char *progName = NULL; + +typedef struct { + PRBool raw; + PRBool ascii; + char *name; + PRFileDesc *file; +} objOutputMode; + +typedef enum { + PKIUnknown = -1, + PKICertificate, + PKIPublicKey, + PKIPrivateKey, + PKIAny +} PKIObjectType; + +static PKIObjectType +get_object_class(char *type) +{ + if (strcmp(type, "certificate") == 0 || strcmp(type, "cert") == 0 || + strcmp(type, "Certificate") == 0 || strcmp(type, "Cert") == 0) { + return PKICertificate; + } else if (strcmp(type, "public_key") == 0 || + strcmp(type, "PublicKey") == 0) { + return PKIPublicKey; + } else if (strcmp(type, "private_key") == 0 || + strcmp(type, "PrivateKey") == 0) { + return PKIPrivateKey; + } else if (strcmp(type, "all") == 0 || strcmp(type, "any") == 0) { + return PKIAny; + } + fprintf(stderr, "%s: \"%s\" is not a valid PKCS#11 object type.\n", + progName, type); + return PKIUnknown; +} + +static PRStatus +print_cert_callback(NSSCertificate *c, void *arg) +{ + int i; + NSSUTF8 *label; + NSSItem *id; + label = NSSCertificate_GetLabel(c); + printf("%s\n", label); + nss_ZFreeIf((void*)label); +#if 0 + id = NSSCertificate_GetID(c); + for (i=0; i<id->size; i++) { + printf("%c", ((char *)id->data)[i]); + } + printf("\n"); +#endif + return PR_SUCCESS; +} + +/* pkiutil commands */ +enum { + cmd_Add = 0, + cmd_Dump, + cmd_List, + cmd_Version, + pkiutil_num_commands +}; + +/* pkiutil options */ +enum { + opt_Help = 0, + opt_Ascii, + opt_ProfileDir, + opt_TokenName, + opt_InputFile, + opt_Nickname, + opt_OutputFile, + opt_Binary, + opt_Trust, + opt_Type, + pkiutil_num_options +}; + +static cmdCommandLineArg pkiutil_commands[] = +{ + { /* cmd_Add */ 'A', "add", CMDNoArg, 0, PR_FALSE, + CMDBIT(opt_Nickname) | CMDBIT(opt_Trust), + CMDBIT(opt_Ascii) | CMDBIT(opt_ProfileDir) + | CMDBIT(opt_TokenName) | CMDBIT(opt_InputFile) + | CMDBIT(opt_Binary) | CMDBIT(opt_Type) }, + { /* cmd_Dump */ 0 , "dump", CMDNoArg, 0, PR_FALSE, + CMDBIT(opt_Nickname), + CMDBIT(opt_Ascii) | CMDBIT(opt_ProfileDir) + | CMDBIT(opt_TokenName) | CMDBIT(opt_Binary) + | CMDBIT(opt_Type) }, + { /* cmd_List */ 'L', "list", CMDNoArg, 0, PR_FALSE, 0, + CMDBIT(opt_Ascii) | CMDBIT(opt_ProfileDir) + | CMDBIT(opt_TokenName) | CMDBIT(opt_Binary) + | CMDBIT(opt_Nickname) | CMDBIT(opt_Type) }, + { /* cmd_Version */ 'Y', "version", CMDNoArg, 0, PR_FALSE, 0, 0 } +}; + +static cmdCommandLineOpt pkiutil_options[] = +{ + { /* opt_Help */ '?', "help", CMDNoArg, 0, PR_FALSE }, + { /* opt_Ascii */ 'a', "ascii", CMDNoArg, 0, PR_FALSE }, + { /* opt_ProfileDir */ 'd', "dbdir", CMDArgReq, 0, PR_FALSE }, + { /* opt_TokenName */ 'h', "token", CMDArgReq, 0, PR_FALSE }, + { /* opt_InputFile */ 'i', "infile", CMDArgReq, 0, PR_FALSE }, + { /* opt_Nickname */ 'n', "nickname", CMDArgReq, 0, PR_FALSE }, + { /* opt_OutputFile */ 'o', "outfile", CMDArgReq, 0, PR_FALSE }, + { /* opt_Binary */ 'r', "raw", CMDNoArg, 0, PR_FALSE }, + { /* opt_Trust */ 't', "trust", CMDArgReq, 0, PR_FALSE }, + { /* opt_Type */ 0 , "type", CMDArgReq, 0, PR_FALSE } +}; + +void pkiutil_usage(cmdPrintState *ps, + int num, PRBool cmd, PRBool header, PRBool footer) +{ +#define pusg CMD_PrintUsageString + if (header) { + pusg(ps, "utility for managing PKCS#11 objects (certs and keys)\n"); + } else if (footer) { + /* + printf("certificate trust can be:\n"); + printf(" p - valid peer, P - trusted peer (implies p)\n"); + printf(" c - valid CA\n"); + printf(" T - trusted CA to issue client certs (implies c)\n"); + printf(" C - trusted CA to issue server certs (implies c)\n"); + printf(" u - user cert\n"); + printf(" w - send warning\n"); + */ + } else if (cmd) { + switch(num) { + case cmd_Add: + pusg(ps, "Add an object to the token"); break; + case cmd_Dump: + pusg(ps, "Dump a single object"); break; + case cmd_List: + pusg(ps, "List objects on the token (-n for single object)"); break; + case cmd_Version: + pusg(ps, "Report version"); break; + default: + pusg(ps, "Unrecognized command"); break; + } + } else { + switch(num) { + case opt_Ascii: + pusg(ps, "Use ascii (base-64 encoded) mode for I/O"); break; + case opt_ProfileDir: + pusg(ps, "Directory containing security databases (def: \".\")"); + break; + case opt_TokenName: + pusg(ps, "Name of PKCS#11 token to use (def: internal)"); break; + case opt_InputFile: + pusg(ps, "File for input (def: stdin)"); break; + case opt_Nickname: + pusg(ps, "Nickname of object"); break; + case opt_OutputFile: + pusg(ps, "File for output (def: stdout)"); break; + case opt_Binary: + pusg(ps, "Use raw (binary der-encoded) mode for I/O"); break; + case opt_Trust: + pusg(ps, "Trust level for certificate"); break; + case opt_Help: break; + default: + pusg(ps, "Unrecognized option"); + } + } +} + +int +main(int argc, char **argv) +{ + PRFileDesc *infile = NULL; + PRFileDesc *outfile = NULL; + char *profiledir = "./"; +#if 0 + secuPWData pwdata = { PW_NONE, 0 }; +#endif + int objclass = 3; /* ANY */ + NSSTrustDomain *root_cert_td = NULL; + char *rootpath = NULL; + char builtin_name[]= "libnssckbi.so"; /* temporary hardcode */ + PRStatus rv = PR_SUCCESS; + + int cmdToRun; + cmdCommand pkiutil; + pkiutil.ncmd = pkiutil_num_commands; + pkiutil.nopt = pkiutil_num_options; + pkiutil.cmd = pkiutil_commands; + pkiutil.opt = pkiutil_options; + + progName = strrchr(argv[0], '/'); + progName = progName ? progName+1 : argv[0]; + + cmdToRun = CMD_ParseCommandLine(argc, argv, progName, &pkiutil); + +#if 0 + { int i, nc; + for (i=0; i<pkiutil.ncmd; i++) + printf("%s: %s <%s>\n", pkiutil.cmd[i].s, + (pkiutil.cmd[i].on) ? "on" : "off", + pkiutil.cmd[i].arg); + for (i=0; i<pkiutil.nopt; i++) + printf("%s: %s <%s>\n", pkiutil.opt[i].s, + (pkiutil.opt[i].on) ? "on" : "off", + pkiutil.opt[i].arg); + } +#endif + + if (pkiutil.opt[opt_Help].on) + CMD_LongUsage(progName, &pkiutil, pkiutil_usage); + + if (cmdToRun < 0) + CMD_Usage(progName, &pkiutil); + + /* -d */ + if (pkiutil.opt[opt_ProfileDir].on) { + profiledir = strdup(pkiutil.opt[opt_ProfileDir].arg); + } + + /* -i */ + if (pkiutil.opt[opt_InputFile].on) { + char *fn = pkiutil.opt[opt_InputFile].arg; + infile = PR_Open(fn, PR_RDONLY, 0660); + } else { + infile = PR_STDIN; + } + + /* -o */ + if (pkiutil.opt[opt_OutputFile].on) { + char *fn = pkiutil.opt[opt_OutputFile].arg; + outfile = PR_Open(fn, PR_WRONLY | PR_CREATE_FILE, 0660); + } else { + outfile = PR_STDOUT; + } + + /* --type can be found on many options */ + if (pkiutil.opt[opt_Type].on) + objclass = get_object_class(pkiutil.opt[opt_Type].arg); + else if (cmdToRun == cmd_Dump && pkiutil.cmd[cmd_Dump].arg) + objclass = get_object_class(pkiutil.cmd[cmd_Dump].arg); + else if (cmdToRun == cmd_List && pkiutil.cmd[cmd_List].arg) + objclass = get_object_class(pkiutil.cmd[cmd_List].arg); + else if (cmdToRun == cmd_Add && pkiutil.cmd[cmd_Add].arg) + objclass = get_object_class(pkiutil.cmd[cmd_Add].arg); + if (objclass < 0) + goto done; + + /* --print is an alias for --list --nickname */ + if (cmdToRun == cmd_Dump) cmdToRun = cmd_List; + + /* if list has raw | ascii must have -n. can't have both raw and ascii */ + if (pkiutil.opt[opt_Binary].on || pkiutil.opt[opt_Ascii].on) { + if (cmdToRun == cmd_List && !pkiutil.opt[opt_Nickname].on) { + fprintf(stderr, "%s: specify a object to output with -n\n", + progName); + CMD_LongUsage(progName, &pkiutil, pkiutil_usage); + } + } + + /* initialize */ + PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); + /* NSS_InitReadWrite(profiledir); */ + NSS_NoDB_Init(NULL); + + /* Display version info and exit */ + if (cmdToRun == cmd_Version) { + printf("%s\nNSS Version %s\n", PKIUTIL_VERSION_STRING, NSS_VERSION); + goto done; + } + + /* XXX okay - bootstrap stan by loading the root cert module for testing */ + root_cert_td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL); + { + int rootpathlen = strlen(profiledir) + strlen(builtin_name) + 1; + rootpath = (char *)malloc(rootpathlen); + memcpy(rootpath, profiledir, strlen(profiledir)); + memcpy(rootpath + strlen(profiledir), + builtin_name, strlen(builtin_name)); + rootpath[rootpathlen - 1] = '\0'; + } + NSSTrustDomain_LoadModule(root_cert_td, "Builtin Root Module", rootpath, + NULL, NULL); + + printf("\n"); + if (pkiutil.opt[opt_Nickname].on) { + int i; + NSSCertificate **certs; + NSSCertificate *cert; + certs = NSSTrustDomain_FindCertificatesByNickname(root_cert_td, + pkiutil.opt[opt_Nickname].arg, NULL, 0, NULL); + i = 0; + while ((cert = certs[i++]) != NULL) { + printf("Found cert:\n"); + print_cert_callback(cert, NULL); + } + } else { + NSSTrustDomain_TraverseCertificates(root_cert_td, print_cert_callback, 0); + } + + NSSTrustDomain_Destroy(root_cert_td); + + /* List token objects */ + if (cmdToRun == cmd_List) { +#if 0 + rv = list_token_objects(slot, objclass, + pkiutil.opt[opt_Nickname].arg, + pkiutil.opt[opt_Binary].on, + pkiutil.opt[opt_Ascii].on, + outfile, &pwdata); +#endif + goto done; + } + +#if 0 + /* Import an object into the token. */ + if (cmdToRun == cmd_Add) { + rv = add_object_to_token(slot, object); + goto done; + } +#endif + +done: + if (NSS_Shutdown() != SECSuccess) { + exit(1); + } + + return rv; +} |