tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 }