mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-30 21:55:31 +00:00
372 lines
11 KiB
C
372 lines
11 KiB
C
/*
|
|
* 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 Netscape are
|
|
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the
|
|
* terms of the GNU General Public License Version 2 or later (the
|
|
* "GPL"), in which case the provisions of the GPL are applicable
|
|
* instead of those above. If you wish to allow use of your
|
|
* version of this file only under the terms of the GPL and not to
|
|
* allow others to use your version of this file under the MPL,
|
|
* indicate your decision by deleting the provisions above and
|
|
* replace them with the notice and other provisions required by
|
|
* the GPL. If you do not delete the provisions above, a recipient
|
|
* may use your version of this file under either the MPL or the
|
|
* GPL.
|
|
*/
|
|
|
|
#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:
|
|
NSS_Shutdown();
|
|
|
|
return rv;
|
|
}
|