Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/. */
5 /*
6 * Test program for SDR (Secret Decoder Ring) functions.
7 */
9 #include "nspr.h"
10 #include "string.h"
11 #include "nss.h"
12 #include "secutil.h"
13 #include "cert.h"
14 #include "pk11func.h"
15 #include "nssb64.h"
17 #include "plgetopt.h"
18 #include "pk11sdr.h"
20 #define DEFAULT_VALUE "Test"
22 static void
23 synopsis (char *program_name)
24 {
25 PRFileDesc *pr_stderr;
27 pr_stderr = PR_STDERR;
28 PR_fprintf (pr_stderr,
29 "Usage:\t%s [-i <input-file>] [-o <output-file>] [-d <dir>]\n"
30 " \t[-l logfile] [-p pwd] [-f pwfile]\n", program_name);
31 }
34 static void
35 short_usage (char *program_name)
36 {
37 PR_fprintf (PR_STDERR,
38 "Type %s -H for more detailed descriptions\n",
39 program_name);
40 synopsis (program_name);
41 }
44 static void
45 long_usage (char *program_name)
46 {
47 PRFileDesc *pr_stderr;
49 pr_stderr = PR_STDERR;
50 synopsis (program_name);
51 PR_fprintf (pr_stderr, "\nDecode encrypted passwords (and other data).\n");
52 PR_fprintf (pr_stderr,
53 "This program reads in standard configuration files looking\n"
54 "for base 64 encoded data. Data that looks like it's base 64 encode\n"
55 "is decoded an passed to the NSS SDR code. If the decode and decrypt\n"
56 "is successful, then decrypted data is outputted in place of the\n"
57 "original base 64 data. If the decode or decrypt fails, the original\n"
58 "data is written and the reason for failure is logged to the \n"
59 "optional logfile.\n");
60 PR_fprintf (pr_stderr,
61 " %-13s Read stream including encrypted data from "
62 "\"read_file\"\n",
63 "-i read_file");
64 PR_fprintf (pr_stderr,
65 " %-13s Write results to \"write_file\"\n",
66 "-o write_file");
67 PR_fprintf (pr_stderr,
68 " %-13s Find security databases in \"dbdir\"\n",
69 "-d dbdir");
70 PR_fprintf (pr_stderr,
71 " %-13s Log failed decrypt/decode attempts to \"log_file\"\n",
72 "-l log_file");
73 PR_fprintf (pr_stderr,
74 " %-13s Token password\n",
75 "-p pwd");
76 PR_fprintf (pr_stderr,
77 " %-13s Password file\n",
78 "-f pwfile");
79 }
81 /*
82 * base64 table only used to identify the end of a base64 string
83 */
84 static unsigned char b64[256] = {
85 /* 00: */ 0, 0, 0, 0, 0, 0, 0, 0,
86 /* 08: */ 0, 0, 0, 0, 0, 0, 0, 0,
87 /* 10: */ 0, 0, 0, 0, 0, 0, 0, 0,
88 /* 18: */ 0, 0, 0, 0, 0, 0, 0, 0,
89 /* 20: */ 0, 0, 0, 0, 0, 0, 0, 0,
90 /* 28: */ 0, 0, 0, 1, 0, 0, 0, 1,
91 /* 30: */ 1, 1, 1, 1, 1, 1, 1, 1,
92 /* 38: */ 1, 1, 0, 0, 0, 0, 0, 0,
93 /* 40: */ 0, 1, 1, 1, 1, 1, 1, 1,
94 /* 48: */ 1, 1, 1, 1, 1, 1, 1, 1,
95 /* 50: */ 1, 1, 1, 1, 1, 1, 1, 1,
96 /* 58: */ 1, 1, 1, 0, 0, 0, 0, 0,
97 /* 60: */ 0, 1, 1, 1, 1, 1, 1, 1,
98 /* 68: */ 1, 1, 1, 1, 1, 1, 1, 1,
99 /* 70: */ 1, 1, 1, 1, 1, 1, 1, 1,
100 /* 78: */ 1, 1, 1, 0, 0, 0, 0, 0,
101 };
103 enum {
104 false = 0,
105 true = 1
106 } bool;
108 #define isatobchar(c) (b64[c])
110 #define MAX_STRING 8192
112 int
113 isBase64(char *inString)
114 {
115 unsigned int i;
116 unsigned char c;
118 for (i = 0; (c = inString[i]) != 0 && isatobchar(c); ++i)
119 ;
120 if (c == '=') {
121 while ((c = inString[++i]) == '=')
122 ; /* skip trailing '=' characters */
123 }
124 if (c && c != '\n' && c != '\r')
125 return false;
126 if (i == 0 || i % 4)
127 return false;
128 return true;
129 }
131 void
132 doDecrypt(char * dataString, FILE *outFile, FILE *logFile, secuPWData *pwdata)
133 {
134 int strLen = strlen(dataString);
135 SECItem *decoded = NSSBase64_DecodeBuffer(NULL, NULL, dataString, strLen);
136 SECStatus rv;
137 int err;
138 SECItem result = { siBuffer, NULL, 0 };
140 if ((decoded == NULL) || (decoded->len == 0)) {
141 if (logFile) {
142 err = PORT_GetError();
143 fprintf(logFile,"Base 64 decode failed on <%s>\n", dataString);
144 fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err));
145 }
146 fputs(dataString, outFile);
147 if (decoded)
148 SECITEM_FreeItem(decoded, PR_TRUE);
149 return;
150 }
152 rv = PK11SDR_Decrypt(decoded, &result, pwdata);
153 SECITEM_ZfreeItem(decoded, PR_TRUE);
154 if (rv == SECSuccess) {
155 /* result buffer has no extra space for a NULL */
156 fprintf(outFile, "Decrypted: \"%.*s\"\n", result.len, result.data);
157 SECITEM_ZfreeItem(&result, PR_FALSE);
158 return;
159 }
160 /* Encryption failed. output raw input. */
161 if (logFile) {
162 err = PORT_GetError();
163 fprintf(logFile,"SDR decrypt failed on <%s>\n", dataString);
164 fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err));
165 }
166 fputs(dataString,outFile);
167 }
169 void
170 doDecode(char * dataString, FILE *outFile, FILE *logFile)
171 {
172 int strLen = strlen(dataString + 1);
173 SECItem *decoded;
175 decoded = NSSBase64_DecodeBuffer(NULL, NULL, dataString + 1, strLen);
176 if ((decoded == NULL) || (decoded->len == 0)) {
177 if (logFile) {
178 int err = PORT_GetError();
179 fprintf(logFile,"Base 64 decode failed on <%s>\n", dataString + 1);
180 fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err));
181 }
182 fputs(dataString, outFile);
183 if (decoded)
184 SECITEM_FreeItem(decoded, PR_TRUE);
185 return;
186 }
187 fprintf(outFile, "Decoded: \"%.*s\"\n", decoded->len, decoded->data);
188 SECITEM_ZfreeItem(decoded, PR_TRUE);
189 }
191 char dataString[MAX_STRING + 1];
193 int
194 main (int argc, char **argv)
195 {
196 int retval = 0; /* 0 - test succeeded. -1 - test failed */
197 SECStatus rv;
198 PLOptState *optstate;
199 char *program_name;
200 char *input_file = NULL; /* read encrypted data from here (or create) */
201 char *output_file = NULL; /* write new encrypted data here */
202 char *log_file = NULL; /* write new encrypted data here */
203 FILE *inFile = stdin;
204 FILE *outFile = stdout;
205 FILE *logFile = NULL;
206 PLOptStatus optstatus;
207 secuPWData pwdata = { PW_NONE, NULL };
210 program_name = PL_strrchr(argv[0], '/');
211 program_name = program_name ? (program_name + 1) : argv[0];
213 optstate = PL_CreateOptState (argc, argv, "Hd:f:i:o:l:p:?");
214 if (optstate == NULL) {
215 SECU_PrintError (program_name, "PL_CreateOptState failed");
216 return 1;
217 }
219 while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
220 switch (optstate->option) {
221 case '?':
222 short_usage (program_name);
223 return 1;
225 case 'H':
226 long_usage (program_name);
227 return 1;
229 case 'd':
230 SECU_ConfigDirectory(optstate->value);
231 break;
233 case 'i':
234 input_file = PL_strdup(optstate->value);
235 break;
237 case 'o':
238 output_file = PL_strdup(optstate->value);
239 break;
241 case 'l':
242 log_file = PL_strdup(optstate->value);
243 break;
245 case 'f':
246 pwdata.source = PW_FROMFILE;
247 pwdata.data = PL_strdup(optstate->value);
248 break;
250 case 'p':
251 pwdata.source = PW_PLAINTEXT;
252 pwdata.data = PL_strdup(optstate->value);
253 break;
255 }
256 }
257 PL_DestroyOptState(optstate);
258 if (optstatus == PL_OPT_BAD) {
259 short_usage (program_name);
260 return 1;
261 }
263 if (input_file) {
264 inFile = fopen(input_file,"r");
265 if (inFile == NULL) {
266 perror(input_file);
267 return 1;
268 }
269 PR_Free(input_file);
270 }
271 if (output_file) {
272 outFile = fopen(output_file,"w+");
273 if (outFile == NULL) {
274 perror(output_file);
275 return 1;
276 }
277 PR_Free(output_file);
278 }
279 if (log_file) {
280 if (log_file[0] == '-')
281 logFile = stderr;
282 else
283 logFile = fopen(log_file,"w+");
284 if (logFile == NULL) {
285 perror(log_file);
286 return 1;
287 }
288 PR_Free(log_file);
289 }
291 /*
292 * Initialize the Security libraries.
293 */
294 PK11_SetPasswordFunc(SECU_GetModulePassword);
295 rv = NSS_Init(SECU_ConfigDirectory(NULL));
296 if (rv != SECSuccess) {
297 SECU_PrintError (program_name, "NSS_Init failed");
298 retval = 1;
299 goto prdone;
300 }
302 /* Get the encrypted result, either from the input file
303 * or from encrypting the plaintext value
304 */
305 while (fgets(dataString, sizeof dataString, inFile)) {
306 unsigned char c = dataString[0];
308 if (c == 'M' && isBase64(dataString)) {
309 doDecrypt(dataString, outFile, logFile, &pwdata);
310 } else if (c == '~' && isBase64(dataString + 1)) {
311 doDecode(dataString, outFile, logFile);
312 } else {
313 fputs(dataString, outFile);
314 }
315 }
316 if (pwdata.data)
317 PR_Free(pwdata.data);
319 fclose(outFile);
320 fclose(inFile);
321 if (logFile && logFile != stderr) {
322 fclose(logFile);
323 }
325 if (NSS_Shutdown() != SECSuccess) {
326 SECU_PrintError (program_name, "NSS_Shutdown failed");
327 exit(1);
328 }
330 prdone:
331 PR_Cleanup ();
332 return retval;
333 }