From bc90a7d57a4130504f9be1edb5d7f11516ba30cf Mon Sep 17 00:00:00 2001 From: "thayes%netscape.com" Date: Wed, 17 May 2000 05:49:24 +0000 Subject: [PATCH] Initial version of "fake" SDR implementation --- extensions/psm-glue/src/nsFSDR.cpp | 1035 ++++++++++++++++++++++++++++ extensions/psm-glue/src/nsFSDR.h | 60 ++ 2 files changed, 1095 insertions(+) create mode 100644 extensions/psm-glue/src/nsFSDR.cpp create mode 100644 extensions/psm-glue/src/nsFSDR.h diff --git a/extensions/psm-glue/src/nsFSDR.cpp b/extensions/psm-glue/src/nsFSDR.cpp new file mode 100644 index 000000000000..96b88ee0a8a2 --- /dev/null +++ b/extensions/psm-glue/src/nsFSDR.cpp @@ -0,0 +1,1035 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * thayes@netscape.com + */ + +#include "stdlib.h" +#include "plstr.h" +#include "nsIAllocator.h" +#include "nsIServiceManager.h" + +#include "nsISecretDecoderRing.h" + +#include "cmtcmn.h" +#include "nsIPSMComponent.h" + +#include "nsFSDR.h" + +/********************************************************************************* +**************************** MASTER PASSWORD FUNCTIONS *************************** +*********************************************************************************/ + +#include "nsNetUtil.h" +#include "nsFileStream.h" +#include "nsINetSupportDialogService.h" +#include "nsIStringBundle.h" +#include "nsIFileSpec.h" +#include "nsFileLocations.h" +#include "prmem.h" +#include "prprf.h" +#include "ntypes.h" +#include "nsIPref.h" + +static NS_DEFINE_IID(kIIOServiceIID, NS_IIOSERVICE_IID); +static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); +static NS_DEFINE_IID(kIStringBundleServiceIID, NS_ISTRINGBUNDLESERVICE_IID); +static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); +static NS_DEFINE_IID(kIPrefServiceIID, NS_IPREF_IID); +static NS_DEFINE_IID(kPrefServiceCID, NS_PREF_CID); +static NS_DEFINE_CID(kNetSupportDialogCID, NS_NETSUPPORTDIALOG_CID); + +#define HEADER_VERSION_1 "#2b" + +#define PROPERTIES_URL "chrome://communicator/locale/wallet/wallet.properties" + +/**************************** LOCALIZATION ***************************/ + +PRUnichar * +Wallet_Localize(char* genericString) { + nsresult ret; + nsAutoString v; + + /* create a URL for the string resource file */ + nsIIOService* pNetService = nsnull; + ret = nsServiceManager::GetService(kIOServiceCID, kIIOServiceIID, + (nsISupports**) &pNetService); + + if (NS_FAILED(ret)) { + printf("cannot get net service\n"); + return v.ToNewUnicode(); + } + nsIURI *url = nsnull; + + nsIURI *uri = nsnull; + ret = pNetService->NewURI(PROPERTIES_URL, nsnull, &uri); + if (NS_FAILED(ret)) { + printf("cannot create URI\n"); + nsServiceManager::ReleaseService(kIOServiceCID, pNetService); + return v.ToNewUnicode(); + } + + ret = uri->QueryInterface(NS_GET_IID(nsIURI), (void**)&url); + NS_RELEASE(uri); + nsServiceManager::ReleaseService(kIOServiceCID, pNetService); + + if (NS_FAILED(ret)) { + printf("cannot create URL\n"); + return v.ToNewUnicode(); + } + + /* create a bundle for the localization */ + nsIStringBundleService* pStringService = nsnull; + ret = nsServiceManager::GetService(kStringBundleServiceCID, + kIStringBundleServiceIID, (nsISupports**) &pStringService); + if (NS_FAILED(ret)) { + printf("cannot get string service\n"); + NS_RELEASE(url); + return v.ToNewUnicode(); + } + nsILocale* locale = nsnull; + nsIStringBundle* bundle = nsnull; + char* spec = nsnull; + ret = url->GetSpec(&spec); + NS_RELEASE(url); + if (NS_FAILED(ret)) { + printf("cannot get url spec\n"); + nsServiceManager::ReleaseService(kStringBundleServiceCID, pStringService); + nsCRT::free(spec); + return v.ToNewUnicode(); + } + ret = pStringService->CreateBundle(spec, locale, &bundle); + nsCRT::free(spec); + if (NS_FAILED(ret)) { + printf("cannot create instance\n"); + nsServiceManager::ReleaseService(kStringBundleServiceCID, pStringService); + return v.ToNewUnicode(); + } + nsServiceManager::ReleaseService(kStringBundleServiceCID, pStringService); + + /* localize the given string */ + nsAutoString strtmp; strtmp.AssignWithConversion(genericString); + const PRUnichar *ptrtmp = strtmp.GetUnicode(); + PRUnichar *ptrv = nsnull; + ret = bundle->GetStringFromName(ptrtmp, &ptrv); + NS_RELEASE(bundle); + if (NS_FAILED(ret)) { + printf("cannot get string from name\n"); + return v.ToNewUnicode(); + } + v = ptrv; + nsCRT::free(ptrv); + return v.ToNewUnicode(); +} + +/**************************** DIALOGS ***************************/ + +PRBool +Wallet_Confirm(PRUnichar * szMessage) +{ + PRBool retval = PR_TRUE; /* default value */ + + nsresult res; + NS_WITH_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, &res); + if (NS_FAILED(res)) { + return retval; + } + + const nsAutoString message = szMessage; + retval = PR_FALSE; /* in case user exits dialog by clicking X */ +/* res = dialog->Confirm(nsnull, message.GetUnicode(), &retval); */ + res = dialog->Confirm(message.GetUnicode(), &retval); + return retval; +} + +nsresult +wallet_GetString(nsAutoString& result, PRUnichar * szMessage, PRUnichar * szMessage1) +{ + /* doing wrap manually because of bug 27732 */ + PRInt32 i=0; + while (szMessage[i] != '\0') { + if (szMessage[i] == '#') { + szMessage[i] = '\n'; + } + i++; + } + + nsAutoString password; + nsresult res; + NS_WITH_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, &res); + if (NS_FAILED(res)) { + return res; + } + + PRUnichar* pwd = NULL; + PRInt32 buttonPressed = 1; /* in case user exits dialog by clickin X */ + PRUnichar * prompt_string = Wallet_Localize("PromptForPassword"); + + res = dialog->UniversalDialog( + NULL, /* title message */ + prompt_string, /* title text in top line of window */ + szMessage, /* this is the main message */ + NULL, /* This is the checkbox message */ + NULL, /* first button text, becomes OK by default */ + NULL, /* second button text, becomes CANCEL by default */ + NULL, /* third button text */ + NULL, /* fourth button text */ + szMessage1, /* first edit field label */ + NULL, /* second edit field label */ + &pwd, /* first edit field initial and final value */ + NULL, /* second edit field initial and final value */ + NULL, /* icon: question mark by default */ + NULL, /* initial and final value of checkbox */ + 2, /* number of buttons */ + 1, /* number of edit fields */ + 1, /* is first edit field a password field */ + &buttonPressed); + + Recycle(prompt_string); + + if (NS_FAILED(res)) { + return res; + } + password = pwd; + delete[] pwd; + + if (buttonPressed == 0) { + result = password; + return NS_OK; + } else { + return NS_ERROR_FAILURE; /* user pressed cancel */ + } +} + +nsresult +wallet_GetDoubleString(nsAutoString& result, PRUnichar * szMessage, PRUnichar * szMessage1, PRUnichar * szMessage2, PRBool& matched) +{ + /* doing wrap manually because of bug 27732 */ + PRInt32 i=0; + while (szMessage[i] != '\0') { + if (szMessage[i] == '#') { + szMessage[i] = '\n'; + } + i++; + } + + nsAutoString password, password2; + nsresult res; + NS_WITH_SERVICE(nsIPrompt, dialog, kNetSupportDialogCID, &res); + if (NS_FAILED(res)) { + return res; + } + + PRUnichar* pwd = NULL; + PRUnichar* pwd2 = NULL; + PRInt32 buttonPressed = 1; /* in case user exits dialog by clickin X */ + PRUnichar * prompt_string = Wallet_Localize("PromptForPassword"); + + res = dialog->UniversalDialog( + NULL, /* title message */ + prompt_string, /* title text in top line of window */ + szMessage, /* this is the main message */ + NULL, /* This is the checkbox message */ + NULL, /* first button text, becomes OK by default */ + NULL, /* second button text, becomes CANCEL by default */ + NULL, /* third button text */ + NULL, /* fourth button text */ + szMessage1, /* first edit field label */ + szMessage2, /* second edit field label */ + &pwd, /* first edit field initial and final value */ + &pwd2, /* second edit field initial and final value */ + NULL, /* icon: question mark by default */ + NULL, /* initial and final value of checkbox */ + 2, /* number of buttons */ + 2, /* number of edit fields */ + 1, /* is first edit field a password field */ + &buttonPressed); + + Recycle(prompt_string); + + if (NS_FAILED(res)) { + return res; + } + password = pwd; + password2 = pwd2; + delete[] pwd; + delete[] pwd2; + matched = (password == password2); + + if (buttonPressed == 0) { + result = password; + return NS_OK; + } else { + return NS_ERROR_FAILURE; /* user pressed cancel */ + } +} + +/************************ PREFERENCES ***************************************/ + +static const char *pref_WalletKeyFileName = "wallet.KeyFileName"; + +void +SI_GetCharPref(const char * prefname, char** aPrefvalue) { + nsresult ret; + nsCOMPtr pPrefService = do_GetService(kPrefServiceCID, &ret); + if (!NS_FAILED(ret)) { + ret = pPrefService->CopyCharPref(prefname, aPrefvalue); + if (NS_FAILED(ret)) { + *aPrefvalue = nsnull; + } + } else { + *aPrefvalue = nsnull; + } +} + + void +SI_SetCharPref(const char * prefname, const char * prefvalue) { + nsresult ret; + nsCOMPtr pPrefService = do_GetService(kPrefServiceCID, &ret); + if (!NS_FAILED(ret)) { + ret = pPrefService->SetCharPref(prefname, prefvalue); + if (!NS_FAILED(ret)) { + ret = pPrefService->SavePrefFile(); + } + } +} + +/************************ UTILITIES *****************************************/ + +nsresult Wallet_ProfileDirectory(nsFileSpec& dirSpec) { + /* return the profile */ + nsIFileSpec* spec = + NS_LocateFileOrDirectory(nsSpecialFileSpec::App_UserProfileDirectory50); + if (!spec) { + return NS_ERROR_FAILURE; + } + nsresult res = spec->GetFileSpec(&dirSpec); + NS_RELEASE(spec); + return res; +} + +char * +Wallet_RandomName(char* suffix) +{ + /* pick the current time as the random number */ + time_t curTime = time(NULL); + + /* take 8 least-significant digits + three-digit suffix as the file name */ + char name[13]; + PR_snprintf(name, 13, "%lu.%s", (curTime%100000000), suffix); + return PL_strdup(name); +} + +void +Wallet_Put(nsOutputFileStream strm, PRUnichar c) { + strm.put((char)c); +} + +PRUnichar +Wallet_Get(nsInputFileStream strm) { + return (strm.get() & 0xFF); +} + +PRInt32 +wallet_GetLine(nsInputFileStream strm, nsAutoString& line) { + + /* read the line */ + line.SetLength(0); + PRUnichar c; + for (;;) { + c = Wallet_Get(strm); + if (c == '\n') { + break; + } + + /* note that eof is not set until we read past the end of the file */ + if (strm.eof()) { + return -1; + } + + if (c != '\r') { + line += c; + } + } + + return NS_OK; +} + +void +wallet_PutLine(nsOutputFileStream strm, const nsAutoString& line) +{ + for (PRUint32 i=0; i0, "Master Password was never established"); + if (gKey.Length() > 0 ) { + return gKey.CharAt((PRInt32)(writeCount % gKey.Length())); + } else { + return '~'; /* What else can we do? We can't recover from this. */ + } +} + +PRBool +Wallet_KeyTimedOut() { + time_t curTime = time(NULL); + if (Wallet_IsKeySet() && (curTime >= gKeyExpiresTime)) { + Wallet_InitKeySet(PR_FALSE); + return PR_TRUE; + } + return PR_FALSE; +} + +void +Wallet_KeyResetTime() { + if (Wallet_IsKeySet()) { + gKeyExpiresTime = time(NULL) + keyDuration; + } +} + +void +WLLT_ExpirePassword() { + if (Wallet_IsKeySet()) { + gKeyExpiresTime = time(NULL); + } +} + +PRBool +Wallet_CancelKey() { + return gKeyCancel; +} + + void +wallet_InitKeyFileName() { + static PRBool namesInitialized = PR_FALSE; + if (!namesInitialized) { + SI_GetCharPref(pref_WalletKeyFileName, &gKeyFileName); + if (!gKeyFileName) { + gKeyFileName = Wallet_RandomName("k"); + SI_SetCharPref(pref_WalletKeyFileName, gKeyFileName); + } + namesInitialized = PR_TRUE; + } +} + +/* returns -1 if key does not exist, 0 if key is of length 0, 1 otherwise */ +PRInt32 +Wallet_KeySize() { + wallet_InitKeyFileName(); + nsFileSpec dirSpec; + nsresult rv = Wallet_ProfileDirectory(dirSpec); + if (NS_FAILED(rv)) { + return -1; + } + nsInputFileStream strm(dirSpec + gKeyFileName); + if (!strm.is_open()) { + return -1; + } else { +#define BUFSIZE 128 + char buffer[BUFSIZE]; + PRInt32 count; + count = strm.read(buffer, BUFSIZE); + strm.close(); + nsAutoString temp; temp.AssignWithConversion(buffer); + PRInt32 start = 0; + for (PRInt32 i=0; i<1; i++) { /* skip over the one-line header */ + start = temp.FindChar('\n', PR_FALSE, start); + if (start == -1) { + return -1; /* this should never happen, but just in case */ + } + start++; + } + return ((start < count) ? 1 : 0); + } +} + +PRBool +wallet_ReadKeyFile(PRBool useDefaultKey) { + PRInt32 writeCount = 0; + + if (useDefaultKey && (Wallet_KeySize() == 0) ) { + Wallet_InitKeySet(PR_TRUE); + return PR_TRUE; + } + + nsFileSpec dirSpec; + nsresult rval = Wallet_ProfileDirectory(dirSpec); + if (NS_FAILED(rval)) { + gKeyCancel = PR_TRUE; + return PR_FALSE; + } + nsInputFileStream strm(dirSpec + gKeyFileName); + writeCount = 0; + + /* read the header */ + nsAutoString format; + if (NS_FAILED(wallet_GetLine(strm, format))) { + return PR_FALSE; + } + if (!format.EqualsWithConversion(HEADER_VERSION_1)) { + /* something's wrong */ + return PR_FALSE; + } + + /* + * Note that eof() is not set until after we read past the end of the file. That + * is why the following code reads a character and immediately after the read + * checks for eof() + */ + + for (PRUint32 j = 1; j < gKey.Length(); j++) { + if (Wallet_Get(strm) != ((gKey.CharAt(j))^Wallet_GetKey(writeCount++)) + || strm.eof()) { + strm.close(); + Wallet_InitKeySet(PR_FALSE); + gKey.SetLength(0); + gKeyCancel = PR_FALSE; + return PR_FALSE; + } + } + if (gKey.Length() != 0) { + if (Wallet_Get(strm) != ((gKey.CharAt(0))^Wallet_GetKey(writeCount++)) + || strm.eof()) { + strm.close(); + Wallet_InitKeySet(PR_FALSE); + gKey.SetLength(0); + gKeyCancel = PR_FALSE; + return PR_FALSE; + } + } + + Wallet_Get(strm); /* to get past the end of the file so eof() will get set */ + PRBool rv = strm.eof(); + strm.close(); + if (rv) { + Wallet_InitKeySet(PR_TRUE); + gKeyExpiresTime = time(NULL) + keyDuration; + return PR_TRUE; + } else { + Wallet_InitKeySet(PR_FALSE); + gKey.SetLength(0); + gKeyCancel = PR_FALSE; + return PR_FALSE; + } +} + +PRBool +wallet_WriteKeyFile(PRBool useDefaultKey) { + PRInt32 writeCount = 0; + + nsFileSpec dirSpec; + nsresult rval = Wallet_ProfileDirectory(dirSpec); + if (NS_FAILED(rval)) { + gKeyCancel = PR_TRUE; + return PR_FALSE; + } + + nsOutputFileStream strm2(dirSpec + gKeyFileName); + if (!strm2.is_open()) { + gKey.SetLength(0); + gKeyCancel = PR_TRUE; + return PR_FALSE; + } + + /* write out the header information */ + { + nsAutoString temp1; + temp1.AssignWithConversion(HEADER_VERSION_1); + wallet_PutLine(strm2, temp1); + } + + /* If we store the key obscured by the key itself, then the result will be zero + * for all keys (since we are using XOR to obscure). So instead we store + * key[1..n],key[0] obscured by the actual key. + */ + + if (!useDefaultKey && (gKey.Length() != 0)) { + for (PRUint32 i = 1; i < gKey.Length(); i++) { + Wallet_Put(strm2, (gKey.CharAt(i))^Wallet_GetKey(writeCount++)); + } + Wallet_Put(strm2, (gKey.CharAt(0))^Wallet_GetKey(writeCount++)); + } + strm2.flush(); + strm2.close(); + Wallet_InitKeySet(PR_TRUE); + return PR_TRUE; +} + +PRBool +Wallet_SetKey(PRBool isNewkey) { + nsresult res; + if (Wallet_IsKeySet() && !isNewkey) { + return PR_TRUE; + } + nsAutoString newkey; + PRBool useDefaultKey = PR_FALSE; + + if (Wallet_KeySize() < 0) { /* no key has yet been established */ + + PRUnichar * message = Wallet_Localize("firstPassword"); + PRUnichar * message1 = Wallet_Localize("enterPassword"); + PRUnichar * message2 = Wallet_Localize("confirmPassword"); + PRUnichar * mismatch = Wallet_Localize("confirmFailed_TryAgain?"); + PRBool matched; + for (;;) { + res = wallet_GetDoubleString(newkey, message, message1, message2, matched); + if (NS_SUCCEEDED(res) && matched) { + break; /* break out of loop if both passwords matched */ + } + /* password confirmation failed, ask user if he wants to try again */ + if (NS_FAILED(res) || (!Wallet_Confirm(mismatch))) { + Recycle(mismatch); + Recycle(message); + Recycle(message1); + Recycle(message2); + gKeyCancel = PR_TRUE; + return FALSE; /* user does not want to try again */ + } + } + PR_FREEIF(mismatch); + PR_FREEIF(message); + Recycle(message1); + PR_FREEIF(message2); + + } else { /* key has previously been established */ + PRUnichar * message; + PRUnichar * message1 = Wallet_Localize("enterPassword"); + PRUnichar * message2 = Wallet_Localize("confirmPassword"); + PRUnichar * mismatch = Wallet_Localize("confirmFailed_TryAgain?"); + PRBool matched; + if (isNewkey) { /* user is changing his key */ + message = Wallet_Localize("newPassword"); + } else { + message = Wallet_Localize("password"); + } + if ((Wallet_KeySize() == 0) && !isNewkey) { /* prev-established key is default key */ + useDefaultKey = PR_TRUE; + newkey.AssignWithConversion("~"); + } else { /* ask the user for his key */ + if (isNewkey) { /* user is changing his password */ + for (;;) { + res = wallet_GetDoubleString(newkey, message, message1, message2, matched); + if (!NS_FAILED(res) && matched) { + break; /* break out of loop if both passwords matched */ + } + /* password confirmation failed, ask user if he wants to try again */ + if (NS_FAILED(res) || (!Wallet_Confirm(mismatch))) { + Recycle(mismatch); + Recycle(message); + Recycle(message1); + Recycle(message2); + gKeyCancel = PR_TRUE; + return FALSE; /* user does not want to try again */ + } + } + } else { + res = wallet_GetString(newkey, message, message1); + } + if (NS_FAILED(res)) { + Recycle(message); + Recycle(message1); + Recycle(message2); + Recycle(mismatch); + gKeyCancel = PR_TRUE; + return PR_FALSE; /* user pressed cancel -- does not want to enter a new key */ + } + } + Recycle(message); + Recycle(message1); + Recycle(message2); + Recycle(mismatch); + } + + if (newkey.Length() == 0) { /* user entered a zero-length key */ + if ((Wallet_KeySize() < 0) || isNewkey ){ + /* no key file existed before or using is changing the key */ + useDefaultKey = PR_TRUE; + newkey.AssignWithConversion("~"); /* use zero-length key */ + } + } + Wallet_InitKeySet(PR_TRUE); + gKey = newkey; + + if (isNewkey || (Wallet_KeySize() < 0)) { + /* Either key is to be changed or the file containing the saved key doesn't exist */ + /* In either case we need to (re)create and re(write) the file */ + return wallet_WriteKeyFile(useDefaultKey); + } else { + /* file of saved key existed so see if it matches the key the user typed in */ + + if (!wallet_ReadKeyFile(useDefaultKey)) { + return PR_FALSE; + } + + /* it matched */ + return PR_TRUE; + } +} + +/********************************************************************************* +************************ END OF MASTER PASSWORD FUNCTIONS ************************ +*********************************************************************************/ + + +NS_IMPL_ISUPPORTS1(nsFSecretDecoderRing, nsISecretDecoderRing) + +nsFSecretDecoderRing::nsFSecretDecoderRing() +{ + NS_INIT_ISUPPORTS(); + + mPSM = NULL; +} + +nsFSecretDecoderRing::~nsFSecretDecoderRing() +{ + if (mPSM) mPSM->Release(); +} + +/* Init the new instance */ +nsresult nsFSecretDecoderRing:: +init() +{ + nsresult rv; + nsISupports *psm; + + rv = nsServiceManager::GetService(kPSMComponentProgID, NS_GET_IID(nsIPSMComponent), + &psm); + if (rv != NS_OK) goto loser; /* Should promote error */ + + mPSM = (nsIPSMComponent *)psm; + +loser: + return rv; +} + +PRBool +encryptCheck() { + static PRBool wallet_keyInitialized = PR_FALSE; + + /* see if key has timed out */ + if (Wallet_KeyTimedOut()) { + wallet_keyInitialized = PR_FALSE; + } + + if (!wallet_keyInitialized) { + PRUnichar * message = Wallet_Localize("IncorrectKey_TryAgain?"); + while (!Wallet_SetKey(PR_FALSE)) { + if (Wallet_CancelKey() || (Wallet_KeySize() < 0) || !Wallet_Confirm(message)) { + Recycle(message); + return PR_FALSE; + } + } + Recycle(message); + wallet_keyInitialized = PR_TRUE; + } + + /* restart key timeout period */ + Wallet_KeyResetTime(); + return PR_TRUE; +} + + +/* [noscript] long encrypt (in buffer data, in long dataLen, out buffer result); */ +NS_IMETHODIMP nsFSecretDecoderRing:: +Encrypt(unsigned char * data, PRInt32 dataLen, unsigned char * *result, PRInt32 *_retval) +{ + nsresult rv = NS_OK; + unsigned char *r = 0; + CMT_CONTROL *control; + CMTStatus status; + CMUint32 cLen; + + if (data == nsnull || result == nsnull || _retval == nsnull) { + rv = NS_ERROR_INVALID_POINTER; + goto loser; + } + + /* Check object initialization */ + NS_ASSERTION(mPSM != nsnull, "SDR object not initialized"); + if (mPSM == nsnull) { rv = NS_ERROR_NOT_INITIALIZED; goto loser; } + + + + + /* Get the control connect to use for the request */ + rv = mPSM->GetControlConnection(&control); + if (rv != NS_OK) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; } + + status = CMT_SDREncrypt(control, (void *)0, (const unsigned char *)0, 0, + data, dataLen, result, &cLen); + if (status != CMTSuccess) { rv = NS_ERROR_FAILURE; goto loser; } /* XXX */ + + /* Copy returned data to nsAllocator buffer ? */ + *_retval = cLen; + +loser: + return rv; +} + +/* [noscript] long decrypt (in buffer data, in long dataLen, out buffer result); */ +NS_IMETHODIMP nsFSecretDecoderRing:: +Decrypt(unsigned char * data, PRInt32 dataLen, unsigned char * *result, PRInt32 *_retval) +{ + nsresult rv = NS_OK; + CMTStatus status; + CMT_CONTROL *control; + CMUint32 len; + + if (data == nsnull || result == nsnull || _retval == nsnull) { + rv = NS_ERROR_INVALID_POINTER; + goto loser; + } + + /* Check object initialization */ + NS_ASSERTION(mPSM != nsnull, "SDR object not initialized"); + if (mPSM == nsnull) { rv = NS_ERROR_NOT_INITIALIZED; goto loser; } + + /* Get the control connection */ + rv = mPSM->GetControlConnection(&control); + if (rv != NS_OK) { rv = NS_ERROR_NOT_AVAILABLE; goto loser; } + + /* Call PSM to decrypt the value */ + status = CMT_SDRDecrypt(control, (void *)0, data, dataLen, result, &len); + if (status != CMTSuccess) { rv = NS_ERROR_FAILURE; goto loser; } /* Promote? */ + + /* Copy returned data to nsAllocator buffer ? */ + *_retval = len; + +loser: + return rv; +} + +/* string encryptString (in string text); */ +NS_IMETHODIMP nsFSecretDecoderRing:: +EncryptString(const char *text, char **_retval) +{ + if (!encryptCheck()) { + return NS_ERROR_FAILURE; + } + +//// *_retval = (char *)PR_Malloc( PL_strlen("Encrypted:") + PL_strlen(text) + 1); +//// PL_strcpy(*_retval, "Encrypted:"); +//// PL_strcat(*_retval, text); +// *_retval = PL_strdup(text); +// for (PRUint32 i=0; i> 4); + (*_retval)[2*i+1] = '0' | (ret & 0x0F); + } + (*_retval)[2*PL_strlen(text)] = '\0'; + + return NS_OK; + + nsresult rv = NS_OK; + unsigned char *encrypted = 0; + PRInt32 eLen; + + if (text == nsnull || _retval == nsnull) { + rv = NS_ERROR_INVALID_POINTER; + goto loser; + } + + rv = Encrypt((unsigned char *)text, PL_strlen(text), &encrypted, &eLen); + if (rv != NS_OK) { goto loser; } + + rv = encode(encrypted, eLen, _retval); + +loser: + if (encrypted) nsAllocator::Free(encrypted); + + return rv; +} + +/* string decryptString (in string crypt); */ +NS_IMETHODIMP nsFSecretDecoderRing:: +DecryptString(const char *crypt, char **_retval) +{ + if (!encryptCheck()) { + return NS_ERROR_FAILURE; + } + +//// if (PL_strncmp(crypt, "Encrypted:", PL_strlen("Encrypted:")) != 0) { +//// return NS_ERROR_FAILURE; +//// } +// *_retval = PL_strdup(crypt); +// for (PRUint32 i=0; i + * Steve Morse + */ + +#ifndef _NSFSDR_H_ +#define _NSFSDR_H_ + +#include "nsISecretDecoderRing.h" + +// =============================================== +// nsFSecretDecoderRing - "fake" implementation of nsISecretDecoderRing +// =============================================== + +#define NS_FSDR_CLASSNAME "Fake Secret Decoder Ring" +#define NS_FSDR_CID \ + { 0x1ee28720, 0x2b93, 0x11d4, { 0xa0, 0xa4, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } + +#define NS_FSDR_PROGID "netscape.security.fsdr" + +class nsFSecretDecoderRing : public nsISecretDecoderRing +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISECRETDECODERRING + + nsFSecretDecoderRing(); + virtual ~nsFSecretDecoderRing(); + + nsresult init(); + +private: + nsIPSMComponent *mPSM; + + static const char *kPSMComponentProgID; + + nsresult encode(const unsigned char *data, PRInt32 dataLen, char **_retval); + nsresult decode(const char *data, unsigned char **result, PRInt32 * _retval); +}; + +#endif /* _NSFSDR_H_ */