diff options
Diffstat (limited to 'security/nss/cmd/p7content/p7content.c')
-rw-r--r-- | security/nss/cmd/p7content/p7content.c | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/security/nss/cmd/p7content/p7content.c b/security/nss/cmd/p7content/p7content.c new file mode 100644 index 000000000..d8c4d6524 --- /dev/null +++ b/security/nss/cmd/p7content/p7content.c @@ -0,0 +1,269 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * p7content -- A command to display pkcs7 content. + */ + +#include "nspr.h" +#include "secutil.h" +#include "plgetopt.h" +#include "secpkcs7.h" +#include "cert.h" +#include "certdb.h" +#include "nss.h" +#include "pk11pub.h" + +#if defined(XP_UNIX) +#include <unistd.h> +#endif + +#include <stdio.h> +#include <string.h> + +#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4)) +extern int fwrite(char *, size_t, size_t, FILE *); +extern int fprintf(FILE *, char *, ...); +#endif + +static void +Usage(char *progName) +{ + fprintf(stderr, + "Usage: %s [-d dbdir] [-i input] [-o output]\n", + progName); + fprintf(stderr, + "%-20s Key/Cert database directory (default is ~/.netscape)\n", + "-d dbdir"); + fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n", + "-i input"); + fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n", + "-o output"); + exit(-1); +} + +static PRBool saw_content; +static secuPWData pwdata = { PW_NONE, 0 }; + +static void +PrintBytes(void *arg, const char *buf, unsigned long len) +{ + FILE *out; + + out = arg; + fwrite(buf, len, 1, out); + + saw_content = PR_TRUE; +} + +/* + * XXX Someday we may want to do real policy stuff here. This allows + * anything to be decrypted, which is okay for a test program but does + * not set an example of how a real client with a real policy would + * need to do it. + */ +static PRBool +decryption_allowed(SECAlgorithmID *algid, PK11SymKey *key) +{ + return PR_TRUE; +} + +int +DecodeAndPrintFile(FILE *out, PRFileDesc *in, char *progName) +{ + SECItem derdata; + SEC_PKCS7ContentInfo *cinfo = NULL; + SEC_PKCS7DecoderContext *dcx; + + if (SECU_ReadDERFromFile(&derdata, in, PR_FALSE, PR_FALSE)) { + SECU_PrintError(progName, "error converting der"); + return -1; + } + + fprintf(out, + "Content printed between bars (newline added before second bar):"); + fprintf(out, "\n---------------------------------------------\n"); + + saw_content = PR_FALSE; + dcx = SEC_PKCS7DecoderStart(PrintBytes, out, NULL, &pwdata, + NULL, NULL, decryption_allowed); + if (dcx != NULL) { +#if 0 /* Test that decoder works when data is really streaming in. */ + { + unsigned long i; + for (i = 0; i < derdata.len; i++) + SEC_PKCS7DecoderUpdate(dcx, derdata.data + i, 1); + } +#else + SEC_PKCS7DecoderUpdate(dcx, (char *)derdata.data, derdata.len); +#endif + cinfo = SEC_PKCS7DecoderFinish(dcx); + } + + fprintf(out, "\n---------------------------------------------\n"); + + if (cinfo == NULL) + return -1; + + fprintf(out, "Content was%s encrypted.\n", + SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not"); + + if (SEC_PKCS7ContentIsSigned(cinfo)) { + char *signer_cname, *signer_ename; + SECItem *signing_time; + + if (saw_content) { + fprintf(out, "Signature is "); + PORT_SetError(0); + if (SEC_PKCS7VerifySignature(cinfo, certUsageEmailSigner, PR_FALSE)) + fprintf(out, "valid.\n"); + else + fprintf(out, "invalid (Reason: %s).\n", + SECU_Strerror(PORT_GetError())); + } else { + fprintf(out, + "Content is detached; signature cannot be verified.\n"); + } + + signer_cname = SEC_PKCS7GetSignerCommonName(cinfo); + if (signer_cname != NULL) { + fprintf(out, "The signer's common name is %s\n", signer_cname); + PORT_Free(signer_cname); + } else { + fprintf(out, "No signer common name.\n"); + } + + signer_ename = SEC_PKCS7GetSignerEmailAddress(cinfo); + if (signer_ename != NULL) { + fprintf(out, "The signer's email address is %s\n", signer_ename); + PORT_Free(signer_ename); + } else { + fprintf(out, "No signer email address.\n"); + } + + signing_time = SEC_PKCS7GetSigningTime(cinfo); + if (signing_time != NULL) { + SECU_PrintTimeChoice(out, signing_time, "Signing time", 0); + } else { + fprintf(out, "No signing time included.\n"); + } + } else { + fprintf(out, "Content was not signed.\n"); + } + + fprintf(out, "There were%s certs or crls included.\n", + SEC_PKCS7ContainsCertsOrCrls(cinfo) ? "" : " no"); + + SECITEM_FreeItem(&derdata, PR_FALSE); + SEC_PKCS7DestroyContentInfo(cinfo); + return 0; +} + +/* + * Print the contents of a PKCS7 message, indicating signatures, etc. + */ + +int +main(int argc, char **argv) +{ + char *progName; + FILE *outFile; + PRFileDesc *inFile; + PLOptState *optstate; + PLOptStatus status; + SECStatus rv; + int error = 0; + + progName = strrchr(argv[0], '/'); + progName = progName ? progName + 1 : argv[0]; + + inFile = NULL; + outFile = NULL; + + /* + * Parse command line arguments + */ + optstate = PL_CreateOptState(argc, argv, "d:i:o:p:f:"); + while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { + switch (optstate->option) { + case 'd': + SECU_ConfigDirectory(optstate->value); + break; + + case 'i': + inFile = PR_Open(optstate->value, PR_RDONLY, 0); + if (!inFile) { + fprintf(stderr, "%s: unable to open \"%s\" for reading\n", + progName, optstate->value); + error = -1; + goto done; + } + break; + + case 'o': + outFile = fopen(optstate->value, "w"); + if (!outFile) { + fprintf(stderr, "%s: unable to open \"%s\" for writing\n", + progName, optstate->value); + error = -1; + goto done; + } + break; + + case 'p': + pwdata.source = PW_PLAINTEXT; + pwdata.data = PORT_Strdup(optstate->value); + break; + + case 'f': + pwdata.source = PW_FROMFILE; + pwdata.data = PORT_Strdup(optstate->value); + break; + + default: + Usage(progName); + break; + } + } + PL_DestroyOptState(optstate); + + if (status == PL_OPT_BAD) + Usage(progName); + + if (!inFile) + inFile = PR_STDIN; + if (!outFile) + outFile = stdout; + + /* Call the initialization routines */ + PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); + rv = NSS_Init(SECU_ConfigDirectory(NULL)); + if (rv != SECSuccess) { + SECU_PrintPRandOSError(progName); + error = -1; + goto done; + } + + PK11_SetPasswordFunc(SECU_GetModulePassword); + + if (DecodeAndPrintFile(outFile, inFile, progName)) { + SECU_PrintError(progName, "problem decoding data"); + error = -1; + goto done; + } + +done: + if (inFile && inFile != PR_STDIN) { + PR_Close(inFile); + } + if (outFile && outFile != stdout) { + fclose(outFile); + } + + if (NSS_Shutdown() != SECSuccess) { + error = -1; + } + + return error; +} |