diff options
Diffstat (limited to 'security/nss/cmd/pwdecrypt/pwdecrypt.c')
-rw-r--r-- | security/nss/cmd/pwdecrypt/pwdecrypt.c | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/security/nss/cmd/pwdecrypt/pwdecrypt.c b/security/nss/cmd/pwdecrypt/pwdecrypt.c new file mode 100644 index 000000000..02a676e54 --- /dev/null +++ b/security/nss/cmd/pwdecrypt/pwdecrypt.c @@ -0,0 +1,330 @@ +/* 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 <input-file>] [-o <output-file>] [-d <dir>]\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; +} |