diff -r 000000000000 -r 6474c204b198 security/nss/cmd/pwdecrypt/pwdecrypt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/security/nss/cmd/pwdecrypt/pwdecrypt.c Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,333 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test program for SDR (Secret Decoder Ring) functions. + */ + +#include "nspr.h" +#include "string.h" +#include "nss.h" +#include "secutil.h" +#include "cert.h" +#include "pk11func.h" +#include "nssb64.h" + +#include "plgetopt.h" +#include "pk11sdr.h" + +#define DEFAULT_VALUE "Test" + +static void +synopsis (char *program_name) +{ + PRFileDesc *pr_stderr; + + pr_stderr = PR_STDERR; + PR_fprintf (pr_stderr, + "Usage:\t%s [-i ] [-o ] [-d ]\n" + " \t[-l logfile] [-p pwd] [-f pwfile]\n", program_name); +} + + +static void +short_usage (char *program_name) +{ + PR_fprintf (PR_STDERR, + "Type %s -H for more detailed descriptions\n", + program_name); + synopsis (program_name); +} + + +static void +long_usage (char *program_name) +{ + PRFileDesc *pr_stderr; + + pr_stderr = PR_STDERR; + synopsis (program_name); + PR_fprintf (pr_stderr, "\nDecode encrypted passwords (and other data).\n"); + PR_fprintf (pr_stderr, + "This program reads in standard configuration files looking\n" + "for base 64 encoded data. Data that looks like it's base 64 encode\n" + "is decoded an passed to the NSS SDR code. If the decode and decrypt\n" + "is successful, then decrypted data is outputted in place of the\n" + "original base 64 data. If the decode or decrypt fails, the original\n" + "data is written and the reason for failure is logged to the \n" + "optional logfile.\n"); + PR_fprintf (pr_stderr, + " %-13s Read stream including encrypted data from " + "\"read_file\"\n", + "-i read_file"); + PR_fprintf (pr_stderr, + " %-13s Write results to \"write_file\"\n", + "-o write_file"); + PR_fprintf (pr_stderr, + " %-13s Find security databases in \"dbdir\"\n", + "-d dbdir"); + PR_fprintf (pr_stderr, + " %-13s Log failed decrypt/decode attempts to \"log_file\"\n", + "-l log_file"); + PR_fprintf (pr_stderr, + " %-13s Token password\n", + "-p pwd"); + PR_fprintf (pr_stderr, + " %-13s Password file\n", + "-f pwfile"); +} + +/* + * base64 table only used to identify the end of a base64 string + */ +static unsigned char b64[256] = { +/* 00: */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 08: */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 10: */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 18: */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 20: */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 28: */ 0, 0, 0, 1, 0, 0, 0, 1, +/* 30: */ 1, 1, 1, 1, 1, 1, 1, 1, +/* 38: */ 1, 1, 0, 0, 0, 0, 0, 0, +/* 40: */ 0, 1, 1, 1, 1, 1, 1, 1, +/* 48: */ 1, 1, 1, 1, 1, 1, 1, 1, +/* 50: */ 1, 1, 1, 1, 1, 1, 1, 1, +/* 58: */ 1, 1, 1, 0, 0, 0, 0, 0, +/* 60: */ 0, 1, 1, 1, 1, 1, 1, 1, +/* 68: */ 1, 1, 1, 1, 1, 1, 1, 1, +/* 70: */ 1, 1, 1, 1, 1, 1, 1, 1, +/* 78: */ 1, 1, 1, 0, 0, 0, 0, 0, +}; + +enum { + false = 0, + true = 1 +} bool; + +#define isatobchar(c) (b64[c]) + +#define MAX_STRING 8192 + +int +isBase64(char *inString) +{ + unsigned int i; + unsigned char c; + + for (i = 0; (c = inString[i]) != 0 && isatobchar(c); ++i) + ; + if (c == '=') { + while ((c = inString[++i]) == '=') + ; /* skip trailing '=' characters */ + } + if (c && c != '\n' && c != '\r') + return false; + if (i == 0 || i % 4) + return false; + return true; +} + +void +doDecrypt(char * dataString, FILE *outFile, FILE *logFile, secuPWData *pwdata) +{ + int strLen = strlen(dataString); + SECItem *decoded = NSSBase64_DecodeBuffer(NULL, NULL, dataString, strLen); + SECStatus rv; + int err; + SECItem result = { siBuffer, NULL, 0 }; + + if ((decoded == NULL) || (decoded->len == 0)) { + if (logFile) { + err = PORT_GetError(); + fprintf(logFile,"Base 64 decode failed on <%s>\n", dataString); + fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err)); + } + fputs(dataString, outFile); + if (decoded) + SECITEM_FreeItem(decoded, PR_TRUE); + return; + } + + rv = PK11SDR_Decrypt(decoded, &result, pwdata); + SECITEM_ZfreeItem(decoded, PR_TRUE); + if (rv == SECSuccess) { + /* result buffer has no extra space for a NULL */ + fprintf(outFile, "Decrypted: \"%.*s\"\n", result.len, result.data); + SECITEM_ZfreeItem(&result, PR_FALSE); + return; + } + /* Encryption failed. output raw input. */ + if (logFile) { + err = PORT_GetError(); + fprintf(logFile,"SDR decrypt failed on <%s>\n", dataString); + fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err)); + } + fputs(dataString,outFile); +} + +void +doDecode(char * dataString, FILE *outFile, FILE *logFile) +{ + int strLen = strlen(dataString + 1); + SECItem *decoded; + + decoded = NSSBase64_DecodeBuffer(NULL, NULL, dataString + 1, strLen); + if ((decoded == NULL) || (decoded->len == 0)) { + if (logFile) { + int err = PORT_GetError(); + fprintf(logFile,"Base 64 decode failed on <%s>\n", dataString + 1); + fprintf(logFile," Error %d: %s\n", err, SECU_Strerror(err)); + } + fputs(dataString, outFile); + if (decoded) + SECITEM_FreeItem(decoded, PR_TRUE); + return; + } + fprintf(outFile, "Decoded: \"%.*s\"\n", decoded->len, decoded->data); + SECITEM_ZfreeItem(decoded, PR_TRUE); +} + +char dataString[MAX_STRING + 1]; + +int +main (int argc, char **argv) +{ + int retval = 0; /* 0 - test succeeded. -1 - test failed */ + SECStatus rv; + PLOptState *optstate; + char *program_name; + char *input_file = NULL; /* read encrypted data from here (or create) */ + char *output_file = NULL; /* write new encrypted data here */ + char *log_file = NULL; /* write new encrypted data here */ + FILE *inFile = stdin; + FILE *outFile = stdout; + FILE *logFile = NULL; + PLOptStatus optstatus; + secuPWData pwdata = { PW_NONE, NULL }; + + + program_name = PL_strrchr(argv[0], '/'); + program_name = program_name ? (program_name + 1) : argv[0]; + + optstate = PL_CreateOptState (argc, argv, "Hd:f:i:o:l:p:?"); + if (optstate == NULL) { + SECU_PrintError (program_name, "PL_CreateOptState failed"); + return 1; + } + + while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) { + switch (optstate->option) { + case '?': + short_usage (program_name); + return 1; + + case 'H': + long_usage (program_name); + return 1; + + case 'd': + SECU_ConfigDirectory(optstate->value); + break; + + case 'i': + input_file = PL_strdup(optstate->value); + break; + + case 'o': + output_file = PL_strdup(optstate->value); + break; + + case 'l': + log_file = PL_strdup(optstate->value); + break; + + case 'f': + pwdata.source = PW_FROMFILE; + pwdata.data = PL_strdup(optstate->value); + break; + + case 'p': + pwdata.source = PW_PLAINTEXT; + pwdata.data = PL_strdup(optstate->value); + break; + + } + } + PL_DestroyOptState(optstate); + if (optstatus == PL_OPT_BAD) { + short_usage (program_name); + return 1; + } + + if (input_file) { + inFile = fopen(input_file,"r"); + if (inFile == NULL) { + perror(input_file); + return 1; + } + PR_Free(input_file); + } + if (output_file) { + outFile = fopen(output_file,"w+"); + if (outFile == NULL) { + perror(output_file); + return 1; + } + PR_Free(output_file); + } + if (log_file) { + if (log_file[0] == '-') + logFile = stderr; + else + logFile = fopen(log_file,"w+"); + if (logFile == NULL) { + perror(log_file); + return 1; + } + PR_Free(log_file); + } + + /* + * Initialize the Security libraries. + */ + PK11_SetPasswordFunc(SECU_GetModulePassword); + rv = NSS_Init(SECU_ConfigDirectory(NULL)); + if (rv != SECSuccess) { + SECU_PrintError (program_name, "NSS_Init failed"); + retval = 1; + goto prdone; + } + + /* Get the encrypted result, either from the input file + * or from encrypting the plaintext value + */ + while (fgets(dataString, sizeof dataString, inFile)) { + unsigned char c = dataString[0]; + + if (c == 'M' && isBase64(dataString)) { + doDecrypt(dataString, outFile, logFile, &pwdata); + } else if (c == '~' && isBase64(dataString + 1)) { + doDecode(dataString, outFile, logFile); + } else { + fputs(dataString, outFile); + } + } + if (pwdata.data) + PR_Free(pwdata.data); + + fclose(outFile); + fclose(inFile); + if (logFile && logFile != stderr) { + fclose(logFile); + } + + if (NSS_Shutdown() != SECSuccess) { + SECU_PrintError (program_name, "NSS_Shutdown failed"); + exit(1); + } + +prdone: + PR_Cleanup (); + return retval; +}