1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/pwdecrypt/pwdecrypt.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,333 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * Test program for SDR (Secret Decoder Ring) functions. 1.10 + */ 1.11 + 1.12 +#include "nspr.h" 1.13 +#include "string.h" 1.14 +#include "nss.h" 1.15 +#include "secutil.h" 1.16 +#include "cert.h" 1.17 +#include "pk11func.h" 1.18 +#include "nssb64.h" 1.19 + 1.20 +#include "plgetopt.h" 1.21 +#include "pk11sdr.h" 1.22 + 1.23 +#define DEFAULT_VALUE "Test" 1.24 + 1.25 +static void 1.26 +synopsis (char *program_name) 1.27 +{ 1.28 + PRFileDesc *pr_stderr; 1.29 + 1.30 + pr_stderr = PR_STDERR; 1.31 + PR_fprintf (pr_stderr, 1.32 + "Usage:\t%s [-i <input-file>] [-o <output-file>] [-d <dir>]\n" 1.33 + " \t[-l logfile] [-p pwd] [-f pwfile]\n", program_name); 1.34 +} 1.35 + 1.36 + 1.37 +static void 1.38 +short_usage (char *program_name) 1.39 +{ 1.40 + PR_fprintf (PR_STDERR, 1.41 + "Type %s -H for more detailed descriptions\n", 1.42 + program_name); 1.43 + synopsis (program_name); 1.44 +} 1.45 + 1.46 + 1.47 +static void 1.48 +long_usage (char *program_name) 1.49 +{ 1.50 + PRFileDesc *pr_stderr; 1.51 + 1.52 + pr_stderr = PR_STDERR; 1.53 + synopsis (program_name); 1.54 + PR_fprintf (pr_stderr, "\nDecode encrypted passwords (and other data).\n"); 1.55 + PR_fprintf (pr_stderr, 1.56 + "This program reads in standard configuration files looking\n" 1.57 + "for base 64 encoded data. Data that looks like it's base 64 encode\n" 1.58 + "is decoded an passed to the NSS SDR code. If the decode and decrypt\n" 1.59 + "is successful, then decrypted data is outputted in place of the\n" 1.60 + "original base 64 data. If the decode or decrypt fails, the original\n" 1.61 + "data is written and the reason for failure is logged to the \n" 1.62 + "optional logfile.\n"); 1.63 + PR_fprintf (pr_stderr, 1.64 + " %-13s Read stream including encrypted data from " 1.65 + "\"read_file\"\n", 1.66 + "-i read_file"); 1.67 + PR_fprintf (pr_stderr, 1.68 + " %-13s Write results to \"write_file\"\n", 1.69 + "-o write_file"); 1.70 + PR_fprintf (pr_stderr, 1.71 + " %-13s Find security databases in \"dbdir\"\n", 1.72 + "-d dbdir"); 1.73 + PR_fprintf (pr_stderr, 1.74 + " %-13s Log failed decrypt/decode attempts to \"log_file\"\n", 1.75 + "-l log_file"); 1.76 + PR_fprintf (pr_stderr, 1.77 + " %-13s Token password\n", 1.78 + "-p pwd"); 1.79 + PR_fprintf (pr_stderr, 1.80 + " %-13s Password file\n", 1.81 + "-f pwfile"); 1.82 +} 1.83 + 1.84 +/* 1.85 + * base64 table only used to identify the end of a base64 string 1.86 + */ 1.87 +static unsigned char b64[256] = { 1.88 +/* 00: */ 0, 0, 0, 0, 0, 0, 0, 0, 1.89 +/* 08: */ 0, 0, 0, 0, 0, 0, 0, 0, 1.90 +/* 10: */ 0, 0, 0, 0, 0, 0, 0, 0, 1.91 +/* 18: */ 0, 0, 0, 0, 0, 0, 0, 0, 1.92 +/* 20: */ 0, 0, 0, 0, 0, 0, 0, 0, 1.93 +/* 28: */ 0, 0, 0, 1, 0, 0, 0, 1, 1.94 +/* 30: */ 1, 1, 1, 1, 1, 1, 1, 1, 1.95 +/* 38: */ 1, 1, 0, 0, 0, 0, 0, 0, 1.96 +/* 40: */ 0, 1, 1, 1, 1, 1, 1, 1, 1.97 +/* 48: */ 1, 1, 1, 1, 1, 1, 1, 1, 1.98 +/* 50: */ 1, 1, 1, 1, 1, 1, 1, 1, 1.99 +/* 58: */ 1, 1, 1, 0, 0, 0, 0, 0, 1.100 +/* 60: */ 0, 1, 1, 1, 1, 1, 1, 1, 1.101 +/* 68: */ 1, 1, 1, 1, 1, 1, 1, 1, 1.102 +/* 70: */ 1, 1, 1, 1, 1, 1, 1, 1, 1.103 +/* 78: */ 1, 1, 1, 0, 0, 0, 0, 0, 1.104 +}; 1.105 + 1.106 +enum { 1.107 + false = 0, 1.108 + true = 1 1.109 +} bool; 1.110 + 1.111 +#define isatobchar(c) (b64[c]) 1.112 + 1.113 +#define MAX_STRING 8192 1.114 + 1.115 +int 1.116 +isBase64(char *inString) 1.117 +{ 1.118 + unsigned int i; 1.119 + unsigned char c; 1.120 + 1.121 + for (i = 0; (c = inString[i]) != 0 && isatobchar(c); ++i) 1.122 + ; 1.123 + if (c == '=') { 1.124 + while ((c = inString[++i]) == '=') 1.125 + ; /* skip trailing '=' characters */ 1.126 + } 1.127 + if (c && c != '\n' && c != '\r') 1.128 + return false; 1.129 + if (i == 0 || i % 4) 1.130 + return false; 1.131 + return true; 1.132 +} 1.133 + 1.134 +void 1.135 +doDecrypt(char * dataString, FILE *outFile, FILE *logFile, secuPWData *pwdata) 1.136 +{ 1.137 + int strLen = strlen(dataString); 1.138 + SECItem *decoded = NSSBase64_DecodeBuffer(NULL, NULL, dataString, strLen); 1.139 + SECStatus rv; 1.140 + int err; 1.141 + SECItem result = { siBuffer, NULL, 0 }; 1.142 + 1.143 + if ((decoded == NULL) || (decoded->len == 0)) { 1.144 + if (logFile) { 1.145 + err = PORT_GetError(); 1.146 + fprintf(logFile,"Base 64 decode failed on <%s>\n", dataString); 1.147 + fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err)); 1.148 + } 1.149 + fputs(dataString, outFile); 1.150 + if (decoded) 1.151 + SECITEM_FreeItem(decoded, PR_TRUE); 1.152 + return; 1.153 + } 1.154 + 1.155 + rv = PK11SDR_Decrypt(decoded, &result, pwdata); 1.156 + SECITEM_ZfreeItem(decoded, PR_TRUE); 1.157 + if (rv == SECSuccess) { 1.158 + /* result buffer has no extra space for a NULL */ 1.159 + fprintf(outFile, "Decrypted: \"%.*s\"\n", result.len, result.data); 1.160 + SECITEM_ZfreeItem(&result, PR_FALSE); 1.161 + return; 1.162 + } 1.163 + /* Encryption failed. output raw input. */ 1.164 + if (logFile) { 1.165 + err = PORT_GetError(); 1.166 + fprintf(logFile,"SDR decrypt failed on <%s>\n", dataString); 1.167 + fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err)); 1.168 + } 1.169 + fputs(dataString,outFile); 1.170 +} 1.171 + 1.172 +void 1.173 +doDecode(char * dataString, FILE *outFile, FILE *logFile) 1.174 +{ 1.175 + int strLen = strlen(dataString + 1); 1.176 + SECItem *decoded; 1.177 + 1.178 + decoded = NSSBase64_DecodeBuffer(NULL, NULL, dataString + 1, strLen); 1.179 + if ((decoded == NULL) || (decoded->len == 0)) { 1.180 + if (logFile) { 1.181 + int err = PORT_GetError(); 1.182 + fprintf(logFile,"Base 64 decode failed on <%s>\n", dataString + 1); 1.183 + fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err)); 1.184 + } 1.185 + fputs(dataString, outFile); 1.186 + if (decoded) 1.187 + SECITEM_FreeItem(decoded, PR_TRUE); 1.188 + return; 1.189 + } 1.190 + fprintf(outFile, "Decoded: \"%.*s\"\n", decoded->len, decoded->data); 1.191 + SECITEM_ZfreeItem(decoded, PR_TRUE); 1.192 +} 1.193 + 1.194 +char dataString[MAX_STRING + 1]; 1.195 + 1.196 +int 1.197 +main (int argc, char **argv) 1.198 +{ 1.199 + int retval = 0; /* 0 - test succeeded. -1 - test failed */ 1.200 + SECStatus rv; 1.201 + PLOptState *optstate; 1.202 + char *program_name; 1.203 + char *input_file = NULL; /* read encrypted data from here (or create) */ 1.204 + char *output_file = NULL; /* write new encrypted data here */ 1.205 + char *log_file = NULL; /* write new encrypted data here */ 1.206 + FILE *inFile = stdin; 1.207 + FILE *outFile = stdout; 1.208 + FILE *logFile = NULL; 1.209 + PLOptStatus optstatus; 1.210 + secuPWData pwdata = { PW_NONE, NULL }; 1.211 + 1.212 + 1.213 + program_name = PL_strrchr(argv[0], '/'); 1.214 + program_name = program_name ? (program_name + 1) : argv[0]; 1.215 + 1.216 + optstate = PL_CreateOptState (argc, argv, "Hd:f:i:o:l:p:?"); 1.217 + if (optstate == NULL) { 1.218 + SECU_PrintError (program_name, "PL_CreateOptState failed"); 1.219 + return 1; 1.220 + } 1.221 + 1.222 + while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 1.223 + switch (optstate->option) { 1.224 + case '?': 1.225 + short_usage (program_name); 1.226 + return 1; 1.227 + 1.228 + case 'H': 1.229 + long_usage (program_name); 1.230 + return 1; 1.231 + 1.232 + case 'd': 1.233 + SECU_ConfigDirectory(optstate->value); 1.234 + break; 1.235 + 1.236 + case 'i': 1.237 + input_file = PL_strdup(optstate->value); 1.238 + break; 1.239 + 1.240 + case 'o': 1.241 + output_file = PL_strdup(optstate->value); 1.242 + break; 1.243 + 1.244 + case 'l': 1.245 + log_file = PL_strdup(optstate->value); 1.246 + break; 1.247 + 1.248 + case 'f': 1.249 + pwdata.source = PW_FROMFILE; 1.250 + pwdata.data = PL_strdup(optstate->value); 1.251 + break; 1.252 + 1.253 + case 'p': 1.254 + pwdata.source = PW_PLAINTEXT; 1.255 + pwdata.data = PL_strdup(optstate->value); 1.256 + break; 1.257 + 1.258 + } 1.259 + } 1.260 + PL_DestroyOptState(optstate); 1.261 + if (optstatus == PL_OPT_BAD) { 1.262 + short_usage (program_name); 1.263 + return 1; 1.264 + } 1.265 + 1.266 + if (input_file) { 1.267 + inFile = fopen(input_file,"r"); 1.268 + if (inFile == NULL) { 1.269 + perror(input_file); 1.270 + return 1; 1.271 + } 1.272 + PR_Free(input_file); 1.273 + } 1.274 + if (output_file) { 1.275 + outFile = fopen(output_file,"w+"); 1.276 + if (outFile == NULL) { 1.277 + perror(output_file); 1.278 + return 1; 1.279 + } 1.280 + PR_Free(output_file); 1.281 + } 1.282 + if (log_file) { 1.283 + if (log_file[0] == '-') 1.284 + logFile = stderr; 1.285 + else 1.286 + logFile = fopen(log_file,"w+"); 1.287 + if (logFile == NULL) { 1.288 + perror(log_file); 1.289 + return 1; 1.290 + } 1.291 + PR_Free(log_file); 1.292 + } 1.293 + 1.294 + /* 1.295 + * Initialize the Security libraries. 1.296 + */ 1.297 + PK11_SetPasswordFunc(SECU_GetModulePassword); 1.298 + rv = NSS_Init(SECU_ConfigDirectory(NULL)); 1.299 + if (rv != SECSuccess) { 1.300 + SECU_PrintError (program_name, "NSS_Init failed"); 1.301 + retval = 1; 1.302 + goto prdone; 1.303 + } 1.304 + 1.305 + /* Get the encrypted result, either from the input file 1.306 + * or from encrypting the plaintext value 1.307 + */ 1.308 + while (fgets(dataString, sizeof dataString, inFile)) { 1.309 + unsigned char c = dataString[0]; 1.310 + 1.311 + if (c == 'M' && isBase64(dataString)) { 1.312 + doDecrypt(dataString, outFile, logFile, &pwdata); 1.313 + } else if (c == '~' && isBase64(dataString + 1)) { 1.314 + doDecode(dataString, outFile, logFile); 1.315 + } else { 1.316 + fputs(dataString, outFile); 1.317 + } 1.318 + } 1.319 + if (pwdata.data) 1.320 + PR_Free(pwdata.data); 1.321 + 1.322 + fclose(outFile); 1.323 + fclose(inFile); 1.324 + if (logFile && logFile != stderr) { 1.325 + fclose(logFile); 1.326 + } 1.327 + 1.328 + if (NSS_Shutdown() != SECSuccess) { 1.329 + SECU_PrintError (program_name, "NSS_Shutdown failed"); 1.330 + exit(1); 1.331 + } 1.332 + 1.333 +prdone: 1.334 + PR_Cleanup (); 1.335 + return retval; 1.336 +}