1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 /*
6  * Pretty-print some well-known BER or DER encoded data (e.g. certificates,
7  * keys, pkcs7)
8  */
9 
10 #include "secutil.h"
11 
12 #if defined(__sun) && !defined(SVR4)
13 extern int fprintf(FILE *, char *, ...);
14 #endif
15 
16 #include "plgetopt.h"
17 
18 #include "pk11func.h"
19 #include "nspr.h"
20 #include "nss.h"
21 
22 static void
Usage(char * progName)23 Usage(char *progName)
24 {
25     fprintf(stderr,
26             "Usage:  %s [-t type] [-a] [-i input] [-o output] [-w] [-u]\n",
27             progName);
28     fprintf(stderr, "Pretty prints a file containing ASN.1 data in DER or ascii format.\n");
29     fprintf(stderr, "%-14s Specify input and display type:", "-t type");
30     fprintf(stderr, " %s (sk),", SEC_CT_PRIVATE_KEY);
31     fprintf(stderr, "\n");
32     fprintf(stderr, "%-14s %s (pk), %s (c), %s (cr),\n", "", SEC_CT_PUBLIC_KEY,
33             SEC_CT_CERTIFICATE, SEC_CT_CERTIFICATE_REQUEST);
34     fprintf(stderr, "%-14s %s (ci), %s (p7), %s (p12), %s or %s (n).\n", "",
35             SEC_CT_CERTIFICATE_ID, SEC_CT_PKCS7, SEC_CT_PKCS12,
36             SEC_CT_CRL, SEC_CT_NAME);
37     fprintf(stderr, "%-14s (Use either the long type name or the shortcut.)\n", "");
38     fprintf(stderr, "%-14s Input is in ascii encoded form (RFC1113)\n",
39             "-a");
40     fprintf(stderr, "%-14s Define an input file to use (default is stdin)\n",
41             "-i input");
42     fprintf(stderr, "%-14s Define an output file to use (default is stdout)\n",
43             "-o output");
44     fprintf(stderr, "%-14s Don't wrap long output lines\n",
45             "-w");
46     fprintf(stderr, "%-14s Use UTF-8 (default is to show non-ascii as .)\n",
47             "-u");
48     exit(-1);
49 }
50 
51 int
main(int argc,char ** argv)52 main(int argc, char **argv)
53 {
54     int rv, ascii;
55     char *progName;
56     FILE *outFile;
57     PRFileDesc *inFile;
58     SECItem der, data;
59     char *typeTag;
60     PLOptState *optstate;
61     PRBool wrap = PR_TRUE;
62 
63     progName = strrchr(argv[0], '/');
64     progName = progName ? progName + 1 : argv[0];
65 
66     ascii = 0;
67     inFile = 0;
68     outFile = 0;
69     typeTag = 0;
70     optstate = PL_CreateOptState(argc, argv, "at:i:o:uw");
71     while (PL_GetNextOpt(optstate) == PL_OPT_OK) {
72         switch (optstate->option) {
73             case '?':
74                 Usage(progName);
75                 break;
76 
77             case 'a':
78                 ascii = 1;
79                 break;
80 
81             case 'i':
82                 inFile = PR_Open(optstate->value, PR_RDONLY, 0);
83                 if (!inFile) {
84                     fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
85                             progName, optstate->value);
86                     PORT_Free(typeTag);
87                     PL_DestroyOptState(optstate);
88                     return -1;
89                 }
90                 break;
91 
92             case 'o':
93                 outFile = fopen(optstate->value, "w");
94                 if (!outFile) {
95                     fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
96                             progName, optstate->value);
97                     PORT_Free(typeTag);
98                     PL_DestroyOptState(optstate);
99                     return -1;
100                 }
101                 break;
102 
103             case 't':
104                 typeTag = strdup(optstate->value);
105                 break;
106 
107             case 'u':
108                 SECU_EnableUtf8Display(PR_TRUE);
109                 break;
110 
111             case 'w':
112                 wrap = PR_FALSE;
113                 break;
114         }
115     }
116     PL_DestroyOptState(optstate);
117     if (!typeTag)
118         Usage(progName);
119 
120     if (!inFile)
121         inFile = PR_STDIN;
122     if (!outFile)
123         outFile = stdout;
124 
125     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
126     rv = NSS_NoDB_Init(NULL);
127     if (rv != SECSuccess) {
128         fprintf(stderr, "%s: NSS_NoDB_Init failed (%s)\n",
129                 progName, SECU_Strerror(PORT_GetError()));
130         exit(1);
131     }
132     SECU_RegisterDynamicOids();
133 
134     rv = SECU_ReadDERFromFile(&der, inFile, ascii, PR_FALSE);
135     if (rv != SECSuccess) {
136         fprintf(stderr, "%s: SECU_ReadDERFromFile failed\n", progName);
137         exit(1);
138     }
139 
140     /* Data is untyped, using the specified type */
141     data.data = der.data;
142     data.len = der.len;
143 
144     SECU_EnableWrap(wrap);
145 
146     /* Pretty print it */
147     if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE) == 0 ||
148         PORT_Strcmp(typeTag, "c") == 0) {
149         rv = SECU_PrintSignedData(outFile, &data, "Certificate", 0,
150                                   (SECU_PPFunc)SECU_PrintCertificate);
151     } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_ID) == 0 ||
152                PORT_Strcmp(typeTag, "ci") == 0) {
153         rv = SECU_PrintSignedContent(outFile, &data, 0, 0,
154                                      SECU_PrintDumpDerIssuerAndSerial);
155     } else if (PORT_Strcmp(typeTag, SEC_CT_CERTIFICATE_REQUEST) == 0 ||
156                PORT_Strcmp(typeTag, "cr") == 0) {
157         rv = SECU_PrintSignedData(outFile, &data, "Certificate Request", 0,
158                                   SECU_PrintCertificateRequest);
159     } else if (PORT_Strcmp(typeTag, SEC_CT_CRL) == 0) {
160         rv = SECU_PrintSignedData(outFile, &data, "CRL", 0, SECU_PrintCrl);
161     } else if (PORT_Strcmp(typeTag, SEC_CT_PRIVATE_KEY) == 0 ||
162                PORT_Strcmp(typeTag, "sk") == 0) {
163         rv = SECU_PrintPrivateKey(outFile, &data, "Private Key", 0);
164     } else if (PORT_Strcmp(typeTag, SEC_CT_PUBLIC_KEY) == 0 ||
165                PORT_Strcmp(typeTag, "pk") == 0) {
166         rv = SECU_PrintSubjectPublicKeyInfo(outFile, &data, "Public Key", 0);
167     } else if (PORT_Strcmp(typeTag, SEC_CT_PKCS7) == 0 ||
168                PORT_Strcmp(typeTag, "p7") == 0) {
169         rv = SECU_PrintPKCS7ContentInfo(outFile, &data,
170                                         "PKCS #7 Content Info", 0);
171     } else if (PORT_Strcmp(typeTag, SEC_CT_NAME) == 0 ||
172                PORT_Strcmp(typeTag, "n") == 0) {
173         rv = SECU_PrintDERName(outFile, &data, "Name", 0);
174     } else if (PORT_Strcmp(typeTag, SEC_CT_PKCS12) == 0 ||
175                PORT_Strcmp(typeTag, "p12") == 0) {
176         rv = SECU_PrintPKCS12(outFile, &data, "PKCS #12 File", 0);
177     } else {
178         fprintf(stderr, "%s: don't know how to print out '%s' files\n",
179                 progName, typeTag);
180         SECU_PrintAny(outFile, &data, "File contains", 0);
181         return -1;
182     }
183 
184     PORT_Free(typeTag);
185 
186     if (inFile != PR_STDIN)
187         PR_Close(inFile);
188     PORT_Free(der.data);
189     if (rv) {
190         fprintf(stderr, "%s: problem converting data (%s)\n",
191                 progName, SECU_Strerror(PORT_GetError()));
192     }
193     if (NSS_Shutdown() != SECSuccess) {
194         fprintf(stderr, "%s: NSS_Shutdown failed (%s)\n",
195                 progName, SECU_Strerror(PORT_GetError()));
196         rv = SECFailure;
197     }
198     PR_Cleanup();
199     return rv;
200 }
201