Back to index

lightning-sunbird  0.9+nobinonly
pwdecrypt.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  * Test program for SDR (Secret Decoder Ring) functions.
00039  *
00040  * $Id: pwdecrypt.c,v 1.4 2005/11/15 23:40:18 nelsonb%netscape.com Exp $
00041  */
00042 
00043 #include "nspr.h"
00044 #include "string.h"
00045 #include "nss.h"
00046 #include "secutil.h"
00047 #include "cert.h"
00048 #include "pk11func.h"
00049 #include "nssb64.h"
00050 
00051 #include "plgetopt.h"
00052 #include "pk11sdr.h"
00053 
00054 #define DEFAULT_VALUE "Test"
00055 
00056 static void
00057 synopsis (char *program_name)
00058 {
00059     PRFileDesc *pr_stderr;
00060 
00061     pr_stderr = PR_STDERR;
00062     PR_fprintf (pr_stderr, "Usage:");
00063     PR_fprintf (pr_stderr,
00064        "\t%s [-i <input-file>] [-o <output-file>] [-d <dir>] [-l logfile]\n",
00065               program_name);
00066 }
00067 
00068 
00069 static void
00070 short_usage (char *program_name)
00071 {
00072     PR_fprintf (PR_STDERR,
00073               "Type %s -H for more detailed descriptions\n",
00074               program_name);
00075     synopsis (program_name);
00076 }
00077 
00078 
00079 static void
00080 long_usage (char *program_name)
00081 {
00082     PRFileDesc *pr_stderr;
00083 
00084     pr_stderr = PR_STDERR;
00085     synopsis (program_name);
00086     PR_fprintf (pr_stderr, "\nDecode encrypted passwords (and other data).\n");
00087     PR_fprintf (pr_stderr, 
00088        "This program reads in standard configuration files looking\n"
00089        "for base 64 encoded data. Data that looks like it's base 64 encode\n"
00090        "is decoded an passed to the NSS SDR code. If the decode and decrypt\n"
00091        "is successful, then decrypted data is outputted in place of the\n"
00092        "original base 64 data. If the decode or decrypt fails, the original\n"
00093        "data is written and the reason for failure is logged to the \n"
00094        "optional logfile.\n");
00095     PR_fprintf (pr_stderr,
00096               "  %-13s Read stream including encrypted data from "
00097                "\"read_file\"\n",
00098               "-i read_file");
00099     PR_fprintf (pr_stderr,
00100               "  %-13s Write results to \"write_file\"\n",
00101               "-o write_file");
00102     PR_fprintf (pr_stderr,
00103               "  %-13s Find security databases in \"dbdir\"\n",
00104               "-d dbdir");
00105     PR_fprintf (pr_stderr,
00106               "  %-13s Log failed decrypt/decode attempts to \"log_file\"\n",
00107               "-l log_file");
00108 }
00109 
00110 /*
00111  * base64 table only used to identify the end of a base64 string 
00112  */
00113 static unsigned char b64[256] = {
00114 /*   0: */        0,      0,      0,      0,      0,      0,      0,      0,
00115 /*   8: */        0,      0,      0,      0,      0,      0,      0,      0,
00116 /*  16: */        0,      0,      0,      0,      0,      0,      0,      0,
00117 /*  24: */        0,      0,      0,      0,      0,      0,      0,      0,
00118 /*  32: */        0,      0,      0,      0,      0,      0,      0,      0,
00119 /*  40: */        0,      0,      0,      1,      0,      0,      0,      1,
00120 /*  48: */        1,      1,      1,      1,      1,      1,      1,      1,
00121 /*  56: */        1,      1,      0,      0,      0,      0,      0,      0,
00122 /*  64: */        0,      1,      1,      1,      1,      1,      1,      1,
00123 /*  72: */        1,      1,      1,      1,      1,      1,      1,      1,
00124 /*  80: */        1,      1,      1,      1,      1,      1,      1,      1,
00125 /*  88: */        1,      1,      1,      0,      0,      0,      0,      0,
00126 /*  96: */        0,      1,      1,      1,      1,      1,      1,      1,
00127 /* 104: */        1,      1,      1,      1,      1,      1,      1,      1,
00128 /* 112: */        1,      1,      1,      1,      1,      1,      1,      1,
00129 /* 120: */        1,      1,      1,      0,      0,      0,      0,      0,
00130 /* 128: */        0,      0,      0,      0,      0,      0,      0,      0
00131 };
00132 
00133 enum {
00134    false = 0,
00135    true = 1
00136 } bool;
00137 
00138 int
00139 isatobchar(int c) { return b64[c] != 0; }
00140 
00141 
00142 #define MAX_STRING 256
00143 int
00144 getData(FILE *inFile,char **inString) {
00145     int len = 0;
00146     int space = MAX_STRING;
00147     int oneequal = false;
00148     int c;
00149     char *string = (char *) malloc(space);
00150 
00151     string[len++]='M';
00152 
00153     while ((c = getc(inFile)) != EOF) {
00154        if (len >= space) {
00155            char *newString;
00156 
00157            space *= 2;
00158            newString = (char *)realloc(string,space);
00159            if (newString == NULL) {
00160               ungetc(c,inFile);
00161               break;
00162            }
00163            string = newString;
00164        }
00165        string[len++] = c;
00166        if (!isatobchar(c)) {
00167           if (c == '=') {
00168               if (oneequal) {
00169                   break;
00170               }
00171               oneequal = true;
00172               continue;
00173           } else {
00174               ungetc(c,inFile);
00175               len--;
00176               break;
00177           }
00178        }
00179        if (oneequal) {
00180           ungetc(c,inFile);
00181           len--;
00182           break;
00183        }
00184     }
00185     if (len >= space) {
00186        space += 2;
00187        string = (char *)realloc(string,space);
00188     }
00189     string[len++] = 0;
00190     *inString = string;
00191     return true;
00192 }
00193 
00194 int
00195 main (int argc, char **argv)
00196 {
00197     int               retval = 0;  /* 0 - test succeeded.  -1 - test failed */
00198     SECStatus  rv;
00199     PLOptState       *optstate;
00200     char      *program_name;
00201     char  *input_file = NULL;      /* read encrypted data from here (or create) */
00202     char  *output_file = NULL;     /* write new encrypted data here */
00203     char  *log_file = NULL; /* write new encrypted data here */
00204     FILE      *inFile = stdin;
00205     FILE      *outFile = stdout;
00206     FILE      *logFile = NULL;
00207     PLOptStatus optstatus;
00208     SECItem   result;
00209     int              c;
00210 
00211     result.data = 0;
00212 
00213     program_name = PL_strrchr(argv[0], '/');
00214     program_name = program_name ? (program_name + 1) : argv[0];
00215 
00216     optstate = PL_CreateOptState (argc, argv, "Hd:i:o:l:?");
00217     if (optstate == NULL) {
00218        SECU_PrintError (program_name, "PL_CreateOptState failed");
00219        return 1;
00220     }
00221 
00222     while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
00223        switch (optstate->option) {
00224          case '?':
00225            short_usage (program_name);
00226            return 1;
00227 
00228          case 'H':
00229            long_usage (program_name);
00230            return 1;
00231 
00232          case 'd':
00233            SECU_ConfigDirectory(optstate->value);
00234            break;
00235 
00236           case 'i':
00237             input_file = PL_strdup(optstate->value);
00238             break;
00239 
00240           case 'o':
00241             output_file = PL_strdup(optstate->value);
00242             break;
00243 
00244           case 'l':
00245             log_file = PL_strdup(optstate->value);
00246             break;
00247 
00248        }
00249     }
00250     PL_DestroyOptState(optstate);
00251     if (optstatus == PL_OPT_BAD) {
00252        short_usage (program_name);
00253        return 1;
00254     }
00255 
00256     if (input_file) {
00257       inFile = fopen(input_file,"r");
00258       if (inFile == NULL) {
00259        perror(input_file);
00260        return 1;
00261       }
00262       PR_Free(input_file);
00263     }
00264     if (output_file) {
00265       outFile = fopen(output_file,"w+");
00266       if (outFile == NULL) {
00267        perror(output_file);
00268        return 1;
00269       }
00270       PR_Free(output_file);
00271     }
00272     if (log_file) {
00273       logFile = fopen(log_file,"w+");
00274       if (logFile == NULL) {
00275        perror(log_file);
00276        return 1;
00277       }
00278       PR_Free(log_file);
00279     }
00280 
00281     /*
00282      * Initialize the Security libraries.
00283      */
00284     PK11_SetPasswordFunc(SECU_GetModulePassword);
00285     rv = NSS_Init(SECU_ConfigDirectory(NULL));
00286     if (rv != SECSuccess) {
00287        SECU_PrintError (program_name, "NSS_Init failed");
00288        retval = 1;
00289        goto prdone;
00290     }
00291 
00292     /* Get the encrypted result, either from the input file
00293      * or from encrypting the plaintext value
00294      */
00295 
00296     while ((c = getc(inFile)) != EOF) {
00297        if (c == 'M') {
00298           char *dataString = NULL;
00299           SECItem *inText;
00300 
00301           rv = getData(inFile, &dataString);
00302           if (!rv) {
00303               fputs(dataString,outFile);
00304               free(dataString);
00305               continue;
00306           }
00307           inText = NSSBase64_DecodeBuffer(NULL, NULL, dataString,
00308                                                  strlen(dataString));
00309           if ((inText == NULL) || (inText->len == 0)) {
00310               if (logFile) {
00311                   fprintf(logFile,"Base 64 decode failed on <%s>\n",
00312                                                         dataString);
00313                   fprintf(logFile," Error %x: %s\n",PORT_GetError(),
00314                      SECU_Strerror(PORT_GetError()));
00315               }
00316               fputs(dataString,outFile);
00317               free(dataString);
00318               continue;
00319           }
00320           result.data = NULL;
00321           result.len  = 0;
00322           rv = PK11SDR_Decrypt(inText, &result, NULL);
00323           SECITEM_FreeItem(inText, PR_TRUE);
00324           if (rv != SECSuccess) {
00325               if (logFile) {
00326                   fprintf(logFile,"SDR decrypt failed on <%s>\n",
00327                                                         dataString);
00328                   fprintf(logFile," Error %x: %s\n",PORT_GetError(),
00329                      SECU_Strerror(PORT_GetError()));
00330               }
00331               fputs(dataString,outFile);
00332               free(dataString);
00333               SECITEM_ZfreeItem(&result, PR_FALSE);
00334               continue;
00335           }
00336           /* result buffer has no extra space for a NULL */
00337           fprintf(outFile, "%.*s", result.len, result.data);
00338           SECITEM_ZfreeItem(&result, PR_FALSE);
00339          } else {
00340           putc(c,outFile);
00341          }
00342     }
00343 
00344     fclose(outFile);
00345     fclose(inFile);
00346     if (logFile) {
00347        fclose(logFile);
00348     }
00349 
00350     if (NSS_Shutdown() != SECSuccess) {
00351        SECU_PrintError (program_name, "NSS_Shutdown failed");
00352        exit(1);
00353     }
00354 
00355 prdone:
00356     PR_Cleanup ();
00357     return retval;
00358 }