1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/p7content/p7content.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,253 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * p7content -- A command to display pkcs7 content. 1.10 + */ 1.11 + 1.12 +#include "nspr.h" 1.13 +#include "secutil.h" 1.14 +#include "plgetopt.h" 1.15 +#include "secpkcs7.h" 1.16 +#include "cert.h" 1.17 +#include "certdb.h" 1.18 +#include "nss.h" 1.19 +#include "pk11pub.h" 1.20 + 1.21 +#if defined(XP_UNIX) 1.22 +#include <unistd.h> 1.23 +#endif 1.24 + 1.25 +#include <stdio.h> 1.26 +#include <string.h> 1.27 + 1.28 +#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4)) 1.29 +extern int fwrite(char *, size_t, size_t, FILE*); 1.30 +extern int fprintf(FILE *, char *, ...); 1.31 +#endif 1.32 + 1.33 + 1.34 + 1.35 +static void 1.36 +Usage(char *progName) 1.37 +{ 1.38 + fprintf(stderr, 1.39 + "Usage: %s [-d dbdir] [-i input] [-o output]\n", 1.40 + progName); 1.41 + fprintf(stderr, 1.42 + "%-20s Key/Cert database directory (default is ~/.netscape)\n", 1.43 + "-d dbdir"); 1.44 + fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n", 1.45 + "-i input"); 1.46 + fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n", 1.47 + "-o output"); 1.48 + exit(-1); 1.49 +} 1.50 + 1.51 +static PRBool saw_content; 1.52 +static secuPWData pwdata = { PW_NONE, 0 }; 1.53 + 1.54 +static void 1.55 +PrintBytes(void *arg, const char *buf, unsigned long len) 1.56 +{ 1.57 + FILE *out; 1.58 + 1.59 + out = arg; 1.60 + fwrite (buf, len, 1, out); 1.61 + 1.62 + saw_content = PR_TRUE; 1.63 +} 1.64 + 1.65 +/* 1.66 + * XXX Someday we may want to do real policy stuff here. This allows 1.67 + * anything to be decrypted, which is okay for a test program but does 1.68 + * not set an example of how a real client with a real policy would 1.69 + * need to do it. 1.70 + */ 1.71 +static PRBool 1.72 +decryption_allowed(SECAlgorithmID *algid, PK11SymKey *key) 1.73 +{ 1.74 + return PR_TRUE; 1.75 +} 1.76 + 1.77 +int 1.78 +DecodeAndPrintFile(FILE *out, PRFileDesc *in, char *progName) 1.79 +{ 1.80 + SECItem derdata; 1.81 + SEC_PKCS7ContentInfo *cinfo = NULL; 1.82 + SEC_PKCS7DecoderContext *dcx; 1.83 + 1.84 + if (SECU_ReadDERFromFile(&derdata, in, PR_FALSE, PR_FALSE)) { 1.85 + SECU_PrintError(progName, "error converting der"); 1.86 + return -1; 1.87 + } 1.88 + 1.89 + fprintf(out, 1.90 + "Content printed between bars (newline added before second bar):"); 1.91 + fprintf(out, "\n---------------------------------------------\n"); 1.92 + 1.93 + saw_content = PR_FALSE; 1.94 + dcx = SEC_PKCS7DecoderStart(PrintBytes, out, NULL, &pwdata, 1.95 + NULL, NULL, decryption_allowed); 1.96 + if (dcx != NULL) { 1.97 +#if 0 /* Test that decoder works when data is really streaming in. */ 1.98 + { 1.99 + unsigned long i; 1.100 + for (i = 0; i < derdata.len; i++) 1.101 + SEC_PKCS7DecoderUpdate(dcx, derdata.data + i, 1); 1.102 + } 1.103 +#else 1.104 + SEC_PKCS7DecoderUpdate(dcx, (char *)derdata.data, derdata.len); 1.105 +#endif 1.106 + cinfo = SEC_PKCS7DecoderFinish(dcx); 1.107 + } 1.108 + 1.109 + fprintf(out, "\n---------------------------------------------\n"); 1.110 + 1.111 + if (cinfo == NULL) 1.112 + return -1; 1.113 + 1.114 + fprintf(out, "Content was%s encrypted.\n", 1.115 + SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not"); 1.116 + 1.117 + if (SEC_PKCS7ContentIsSigned(cinfo)) { 1.118 + char *signer_cname, *signer_ename; 1.119 + SECItem *signing_time; 1.120 + 1.121 + if (saw_content) { 1.122 + fprintf(out, "Signature is "); 1.123 + PORT_SetError(0); 1.124 + if (SEC_PKCS7VerifySignature(cinfo, certUsageEmailSigner, PR_FALSE)) 1.125 + fprintf(out, "valid.\n"); 1.126 + else 1.127 + fprintf(out, "invalid (Reason: %s).\n", 1.128 + SECU_Strerror(PORT_GetError())); 1.129 + } else { 1.130 + fprintf(out, 1.131 + "Content is detached; signature cannot be verified.\n"); 1.132 + } 1.133 + 1.134 + signer_cname = SEC_PKCS7GetSignerCommonName(cinfo); 1.135 + if (signer_cname != NULL) { 1.136 + fprintf(out, "The signer's common name is %s\n", signer_cname); 1.137 + PORT_Free(signer_cname); 1.138 + } else { 1.139 + fprintf(out, "No signer common name.\n"); 1.140 + } 1.141 + 1.142 + signer_ename = SEC_PKCS7GetSignerEmailAddress(cinfo); 1.143 + if (signer_ename != NULL) { 1.144 + fprintf(out, "The signer's email address is %s\n", signer_ename); 1.145 + PORT_Free(signer_ename); 1.146 + } else { 1.147 + fprintf(out, "No signer email address.\n"); 1.148 + } 1.149 + 1.150 + signing_time = SEC_PKCS7GetSigningTime(cinfo); 1.151 + if (signing_time != NULL) { 1.152 + SECU_PrintTimeChoice(out, signing_time, "Signing time", 0); 1.153 + } else { 1.154 + fprintf(out, "No signing time included.\n"); 1.155 + } 1.156 + } else { 1.157 + fprintf(out, "Content was not signed.\n"); 1.158 + } 1.159 + 1.160 + fprintf(out, "There were%s certs or crls included.\n", 1.161 + SEC_PKCS7ContainsCertsOrCrls(cinfo) ? "" : " no"); 1.162 + 1.163 + SEC_PKCS7DestroyContentInfo(cinfo); 1.164 + return 0; 1.165 +} 1.166 + 1.167 +/* 1.168 + * Print the contents of a PKCS7 message, indicating signatures, etc. 1.169 + */ 1.170 + 1.171 +int 1.172 +main(int argc, char **argv) 1.173 +{ 1.174 + char *progName; 1.175 + FILE *outFile; 1.176 + PRFileDesc *inFile; 1.177 + PLOptState *optstate; 1.178 + PLOptStatus status; 1.179 + SECStatus rv; 1.180 + 1.181 + progName = strrchr(argv[0], '/'); 1.182 + progName = progName ? progName+1 : argv[0]; 1.183 + 1.184 + inFile = NULL; 1.185 + outFile = NULL; 1.186 + 1.187 + /* 1.188 + * Parse command line arguments 1.189 + */ 1.190 + optstate = PL_CreateOptState(argc, argv, "d:i:o:p:f:"); 1.191 + while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 1.192 + switch (optstate->option) { 1.193 + case 'd': 1.194 + SECU_ConfigDirectory(optstate->value); 1.195 + break; 1.196 + 1.197 + case 'i': 1.198 + inFile = PR_Open(optstate->value, PR_RDONLY, 0); 1.199 + if (!inFile) { 1.200 + fprintf(stderr, "%s: unable to open \"%s\" for reading\n", 1.201 + progName, optstate->value); 1.202 + return -1; 1.203 + } 1.204 + break; 1.205 + 1.206 + case 'o': 1.207 + outFile = fopen(optstate->value, "w"); 1.208 + if (!outFile) { 1.209 + fprintf(stderr, "%s: unable to open \"%s\" for writing\n", 1.210 + progName, optstate->value); 1.211 + return -1; 1.212 + } 1.213 + break; 1.214 + 1.215 + case 'p': 1.216 + pwdata.source = PW_PLAINTEXT; 1.217 + pwdata.data = PORT_Strdup (optstate->value); 1.218 + break; 1.219 + 1.220 + case 'f': 1.221 + pwdata.source = PW_FROMFILE; 1.222 + pwdata.data = PORT_Strdup (optstate->value); 1.223 + break; 1.224 + 1.225 + default: 1.226 + Usage(progName); 1.227 + break; 1.228 + } 1.229 + } 1.230 + if (status == PL_OPT_BAD) 1.231 + Usage(progName); 1.232 + 1.233 + if (!inFile) inFile = PR_STDIN; 1.234 + if (!outFile) outFile = stdout; 1.235 + 1.236 + /* Call the initialization routines */ 1.237 + PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 1.238 + rv = NSS_Init(SECU_ConfigDirectory(NULL)); 1.239 + if (rv != SECSuccess) { 1.240 + SECU_PrintPRandOSError(progName); 1.241 + return -1; 1.242 + } 1.243 + 1.244 + PK11_SetPasswordFunc(SECU_GetModulePassword); 1.245 + 1.246 + if (DecodeAndPrintFile(outFile, inFile, progName)) { 1.247 + SECU_PrintError(progName, "problem decoding data"); 1.248 + return -1; 1.249 + } 1.250 + 1.251 + if (NSS_Shutdown() != SECSuccess) { 1.252 + exit(1); 1.253 + } 1.254 + 1.255 + return 0; 1.256 +}