security/nss/cmd/pwdecrypt/pwdecrypt.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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

mercurial