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