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 #include "plgetopt.h"
6 #include "secutil.h"
7 #include "nssb64.h"
8 #include <errno.h>
9
10 #if defined(XP_WIN) || (defined(__sun) && !defined(SVR4))
11 #if !defined(WIN32)
12 extern int fread(char *, size_t, size_t, FILE *);
13 extern int fwrite(char *, size_t, size_t, FILE *);
14 extern int fprintf(FILE *, char *, ...);
15 #endif
16 #endif
17
18 #if defined(WIN32)
19 #include "fcntl.h"
20 #include "io.h"
21 #endif
22
23 static PRInt32
output_ascii(void * arg,const char * obuf,PRInt32 size)24 output_ascii(void *arg, const char *obuf, PRInt32 size)
25 {
26 FILE *outFile = arg;
27 int nb;
28
29 nb = fwrite(obuf, 1, size, outFile);
30 if (nb != size) {
31 PORT_SetError(SEC_ERROR_IO);
32 return -1;
33 }
34
35 return nb;
36 }
37
38 static SECStatus
encode_file(FILE * outFile,FILE * inFile)39 encode_file(FILE *outFile, FILE *inFile)
40 {
41 NSSBase64Encoder *cx;
42 int nb;
43 SECStatus status = SECFailure;
44 unsigned char ibuf[4096];
45
46 cx = NSSBase64Encoder_Create(output_ascii, outFile);
47 if (!cx) {
48 return -1;
49 }
50
51 for (;;) {
52 if (feof(inFile))
53 break;
54 nb = fread(ibuf, 1, sizeof(ibuf), inFile);
55 if (nb != sizeof(ibuf)) {
56 if (nb == 0) {
57 if (ferror(inFile)) {
58 PORT_SetError(SEC_ERROR_IO);
59 goto loser;
60 }
61 /* eof */
62 break;
63 }
64 }
65
66 status = NSSBase64Encoder_Update(cx, ibuf, nb);
67 if (status != SECSuccess)
68 goto loser;
69 }
70
71 status = NSSBase64Encoder_Destroy(cx, PR_FALSE);
72 if (status != SECSuccess)
73 return status;
74
75 /*
76 * Add a trailing CRLF. Note this must be done *after* the call
77 * to Destroy above (because only then are we sure all data has
78 * been written out).
79 */
80 fwrite("\r\n", 1, 2, outFile);
81 return SECSuccess;
82
83 loser:
84 (void)NSSBase64Encoder_Destroy(cx, PR_TRUE);
85 return status;
86 }
87
88 static void
Usage(char * progName)89 Usage(char *progName)
90 {
91 fprintf(stderr,
92 "Usage: %s [-i input] [-o output]\n",
93 progName);
94 fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
95 "-i input");
96 fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
97 "-o output");
98 fprintf(stderr, "%-20s Wrap output in BEGIN/END lines and the given suffix\n",
99 "-w suffix");
100 fprintf(stderr, "%-20s (use \"c\" as a shortcut for suffix CERTIFICATE)\n",
101 "");
102 exit(-1);
103 }
104
105 int
main(int argc,char ** argv)106 main(int argc, char **argv)
107 {
108 char *progName;
109 SECStatus rv;
110 FILE *inFile, *outFile;
111 PLOptState *optstate;
112 PLOptStatus status;
113 char *suffix = NULL;
114
115 inFile = 0;
116 outFile = 0;
117 progName = strrchr(argv[0], '/');
118 if (!progName)
119 progName = strrchr(argv[0], '\\');
120 progName = progName ? progName + 1 : argv[0];
121
122 /* Parse command line arguments */
123 optstate = PL_CreateOptState(argc, argv, "i:o:w:");
124 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
125 switch (optstate->option) {
126 default:
127 Usage(progName);
128 break;
129
130 case 'i':
131 inFile = fopen(optstate->value, "rb");
132 if (!inFile) {
133 fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
134 progName, optstate->value);
135 return -1;
136 }
137 break;
138
139 case 'o':
140 outFile = fopen(optstate->value, "wb");
141 if (!outFile) {
142 fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
143 progName, optstate->value);
144 return -1;
145 }
146 break;
147
148 case 'w':
149 if (!strcmp(optstate->value, "c"))
150 suffix = strdup("CERTIFICATE");
151 else
152 suffix = strdup(optstate->value);
153 break;
154 }
155 }
156 if (status == PL_OPT_BAD)
157 Usage(progName);
158 if (!inFile) {
159 #if defined(WIN32)
160 /* If we're going to read binary data from stdin, we must put stdin
161 ** into O_BINARY mode or else incoming \r\n's will become \n's.
162 */
163
164 int smrv = _setmode(_fileno(stdin), _O_BINARY);
165 if (smrv == -1) {
166 fprintf(stderr,
167 "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
168 progName);
169 return smrv;
170 }
171 #endif
172 inFile = stdin;
173 }
174 if (!outFile) {
175 #if defined(WIN32)
176 /* We're going to write binary data to stdout. We must put stdout
177 ** into O_BINARY mode or else outgoing \r\n's will become \r\r\n's.
178 */
179
180 int smrv = _setmode(_fileno(stdout), _O_BINARY);
181 if (smrv == -1) {
182 fprintf(stderr,
183 "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
184 progName);
185 return smrv;
186 }
187 #endif
188 outFile = stdout;
189 }
190 if (suffix) {
191 fprintf(outFile, "-----BEGIN %s-----\n", suffix);
192 }
193 rv = encode_file(outFile, inFile);
194 if (rv != SECSuccess) {
195 fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
196 progName, PORT_GetError(), errno);
197 return -1;
198 }
199 if (suffix) {
200 fprintf(outFile, "-----END %s-----\n", suffix);
201 }
202 return 0;
203 }
204