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