Back to index

lightning-sunbird  0.9+nobinonly
p7content.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  * p7content -- A command to display pkcs7 content.
00039  *
00040  * $Id: p7content.c,v 1.10 2004/04/25 15:02:48 gerv%gerv.net Exp $
00041  */
00042 
00043 #include "nspr.h"
00044 #include "secutil.h"
00045 #include "plgetopt.h"
00046 #include "secpkcs7.h"
00047 #include "cert.h"
00048 #include "certdb.h"
00049 #include "nss.h"
00050 
00051 #if defined(XP_UNIX)
00052 #include <unistd.h>
00053 #endif
00054 
00055 #include <stdio.h>
00056 #include <string.h>
00057 
00058 #if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
00059 extern int fwrite(char *, size_t, size_t, FILE*);
00060 extern int fprintf(FILE *, char *, ...);
00061 #endif
00062 
00063 
00064 
00065 static void
00066 Usage(char *progName)
00067 {
00068     fprintf(stderr,
00069            "Usage:  %s [-d dbdir] [-i input] [-o output]\n",
00070            progName);
00071     fprintf(stderr,
00072            "%-20s Key/Cert database directory (default is ~/.netscape)\n",
00073            "-d dbdir");
00074     fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
00075            "-i input");
00076     fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
00077            "-o output");
00078     exit(-1);
00079 }
00080 
00081 static PRBool saw_content;
00082 
00083 static void
00084 PrintBytes(void *arg, const char *buf, unsigned long len)
00085 {
00086     FILE *out;
00087 
00088     out = arg; 
00089     fwrite (buf, len, 1, out);
00090 
00091     saw_content = PR_TRUE;
00092 }
00093 
00094 /*
00095  * XXX Someday we may want to do real policy stuff here.  This allows
00096  * anything to be decrypted, which is okay for a test program but does
00097  * not set an example of how a real client with a real policy would
00098  * need to do it.
00099  */
00100 static PRBool
00101 decryption_allowed(SECAlgorithmID *algid, PK11SymKey *key)
00102 {
00103     return PR_TRUE;
00104 }
00105 
00106 int
00107 DecodeAndPrintFile(FILE *out, PRFileDesc *in, char *progName)
00108 {
00109     SECItem derdata;
00110     SEC_PKCS7ContentInfo *cinfo = NULL;
00111     SEC_PKCS7DecoderContext *dcx;
00112 
00113     if (SECU_ReadDERFromFile(&derdata, in, PR_FALSE)) {
00114         SECU_PrintError(progName, "error converting der");
00115        return -1;
00116     }
00117 
00118     fprintf(out,
00119            "Content printed between bars (newline added before second bar):");
00120     fprintf(out, "\n---------------------------------------------\n");
00121 
00122     saw_content = PR_FALSE;
00123     dcx = SEC_PKCS7DecoderStart(PrintBytes, out, NULL, NULL,
00124                             NULL, NULL, decryption_allowed);
00125     if (dcx != NULL) {
00126 #if 0  /* Test that decoder works when data is really streaming in. */
00127        {
00128            unsigned long i;
00129            for (i = 0; i < derdata.len; i++)
00130               SEC_PKCS7DecoderUpdate(dcx, derdata.data + i, 1);
00131        }
00132 #else
00133        SEC_PKCS7DecoderUpdate(dcx, (char *)derdata.data, derdata.len);
00134 #endif
00135        cinfo = SEC_PKCS7DecoderFinish(dcx);
00136     }
00137 
00138     fprintf(out, "\n---------------------------------------------\n");
00139 
00140     if (cinfo == NULL)
00141        return -1;
00142 
00143     fprintf(out, "Content was%s encrypted.\n",
00144            SEC_PKCS7ContentIsEncrypted(cinfo) ? "" : " not");
00145 
00146     if (SEC_PKCS7ContentIsSigned(cinfo)) {
00147        char *signer_cname, *signer_ename;
00148        SECItem *signing_time;
00149 
00150        if (saw_content) {
00151            fprintf(out, "Signature is ");
00152            PORT_SetError(0);
00153            if (SEC_PKCS7VerifySignature(cinfo, certUsageEmailSigner, PR_FALSE))
00154               fprintf(out, "valid.\n");
00155            else
00156               fprintf(out, "invalid (Reason: %s).\n",
00157                      SECU_Strerror(PORT_GetError()));
00158        } else {
00159            fprintf(out,
00160                   "Content is detached; signature cannot be verified.\n");
00161        }
00162 
00163        signer_cname = SEC_PKCS7GetSignerCommonName(cinfo);
00164        if (signer_cname != NULL) {
00165            fprintf(out, "The signer's common name is %s\n", signer_cname);
00166            PORT_Free(signer_cname);
00167        } else {
00168            fprintf(out, "No signer common name.\n");
00169        }
00170 
00171        signer_ename = SEC_PKCS7GetSignerEmailAddress(cinfo);
00172        if (signer_ename != NULL) {
00173            fprintf(out, "The signer's email address is %s\n", signer_ename);
00174            PORT_Free(signer_ename);
00175        } else {
00176            fprintf(out, "No signer email address.\n");
00177        }
00178 
00179        signing_time = SEC_PKCS7GetSigningTime(cinfo);
00180        if (signing_time != NULL) {
00181            SECU_PrintTimeChoice(out, signing_time, "Signing time", 0);
00182        } else {
00183            fprintf(out, "No signing time included.\n");
00184        }
00185     } else {
00186        fprintf(out, "Content was not signed.\n");
00187     }
00188 
00189     fprintf(out, "There were%s certs or crls included.\n",
00190            SEC_PKCS7ContainsCertsOrCrls(cinfo) ? "" : " no");
00191 
00192     SEC_PKCS7DestroyContentInfo(cinfo);
00193     return 0;
00194 }
00195 
00196 
00197 /*
00198  * Print the contents of a PKCS7 message, indicating signatures, etc.
00199  */
00200 
00201 int
00202 main(int argc, char **argv)
00203 {
00204     char *progName;
00205     FILE *outFile;
00206     PRFileDesc *inFile;
00207     PLOptState *optstate;
00208     PLOptStatus status;
00209     SECStatus rv;
00210 
00211     progName = strrchr(argv[0], '/');
00212     progName = progName ? progName+1 : argv[0];
00213 
00214     inFile = NULL;
00215     outFile = NULL;
00216 
00217     /*
00218      * Parse command line arguments
00219      */
00220     optstate = PL_CreateOptState(argc, argv, "d:i:o:");
00221     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
00222        switch (optstate->option) {
00223          case 'd':
00224            SECU_ConfigDirectory(optstate->value);
00225            break;
00226 
00227          case 'i':
00228            inFile = PR_Open(optstate->value, PR_RDONLY, 0);
00229            if (!inFile) {
00230               fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
00231                      progName, optstate->value);
00232               return -1;
00233            }
00234            break;
00235 
00236          case 'o':
00237            outFile = fopen(optstate->value, "w");
00238            if (!outFile) {
00239               fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
00240                      progName, optstate->value);
00241               return -1;
00242            }
00243            break;
00244 
00245          default:
00246            Usage(progName);
00247            break;
00248        }
00249     }
00250     if (status == PL_OPT_BAD)
00251        Usage(progName);
00252 
00253     if (!inFile) inFile = PR_STDIN;
00254     if (!outFile) outFile = stdout;
00255 
00256     /* Call the initialization routines */
00257     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
00258     rv = NSS_Init(SECU_ConfigDirectory(NULL));
00259     if (rv != SECSuccess) {
00260        SECU_PrintPRandOSError(progName);
00261        return -1;
00262     }
00263 
00264     if (DecodeAndPrintFile(outFile, inFile, progName)) {
00265        SECU_PrintError(progName, "problem decoding data");
00266        return -1;
00267     }
00268     
00269     if (NSS_Shutdown() != SECSuccess) {
00270         exit(1);
00271     }
00272 
00273     return 0;
00274 }