diff options
Diffstat (limited to 'security/manager/pki/nsNSSDialogs.cpp')
-rw-r--r-- | security/manager/pki/nsNSSDialogs.cpp | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/security/manager/pki/nsNSSDialogs.cpp b/security/manager/pki/nsNSSDialogs.cpp new file mode 100644 index 000000000..831bce57e --- /dev/null +++ b/security/manager/pki/nsNSSDialogs.cpp @@ -0,0 +1,441 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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/. */ + +/* + * Dialog services for PIP. + */ + +#include "nsNSSDialogs.h" + +#include "mozIDOMWindow.h" +#include "nsArray.h" +#include "nsEmbedCID.h" +#include "nsHashPropertyBag.h" +#include "nsIDialogParamBlock.h" +#include "nsIInterfaceRequestor.h" +#include "nsIInterfaceRequestorUtils.h" +#include "nsIKeygenThread.h" +#include "nsIPromptService.h" +#include "nsIProtectedAuthThread.h" +#include "nsIWindowWatcher.h" +#include "nsIX509CertDB.h" +#include "nsIX509Cert.h" +#include "nsNSSDialogHelper.h" +#include "nsString.h" +#include "nsVariant.h" + +#define PIPSTRING_BUNDLE_URL "chrome://pippki/locale/pippki.properties" + +nsNSSDialogs::nsNSSDialogs() +{ +} + +nsNSSDialogs::~nsNSSDialogs() +{ +} + +NS_IMPL_ISUPPORTS(nsNSSDialogs, nsITokenPasswordDialogs, + nsICertificateDialogs, + nsIClientAuthDialogs, + nsITokenDialogs, + nsIGeneratingKeypairInfoDialogs) + +nsresult +nsNSSDialogs::Init() +{ + nsresult rv; + + nsCOMPtr<nsIStringBundleService> service = + do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = service->CreateBundle(PIPSTRING_BUNDLE_URL, + getter_AddRefs(mPIPStringBundle)); + return rv; +} + +nsresult +nsNSSDialogs::SetPassword(nsIInterfaceRequestor *ctx, + const char16_t *tokenName, bool* _canceled) +{ + nsresult rv; + + *_canceled = false; + + // Get the parent window for the dialog + nsCOMPtr<mozIDOMWindowProxy> parent = do_GetInterface(ctx); + + nsCOMPtr<nsIDialogParamBlock> block = + do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID); + if (!block) return NS_ERROR_FAILURE; + + rv = block->SetString(1, tokenName); + if (NS_FAILED(rv)) return rv; + + rv = nsNSSDialogHelper::openDialog(parent, + "chrome://pippki/content/changepassword.xul", + block); + + if (NS_FAILED(rv)) return rv; + + int32_t status; + + rv = block->GetInt(1, &status); + if (NS_FAILED(rv)) return rv; + + *_canceled = (status == 0)?true:false; + + return rv; +} + +NS_IMETHODIMP +nsNSSDialogs::ConfirmDownloadCACert(nsIInterfaceRequestor* ctx, + nsIX509Cert* cert, + /*out*/ uint32_t* trust, + /*out*/ bool* importConfirmed) +{ + // |ctx| is allowed to be null. + NS_ENSURE_ARG(cert); + NS_ENSURE_ARG(trust); + NS_ENSURE_ARG(importConfirmed); + + nsCOMPtr<nsIMutableArray> argArray = nsArrayBase::Create(); + if (!argArray) { + return NS_ERROR_FAILURE; + } + + nsresult rv = argArray->AppendElement(cert, false); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr<nsIWritablePropertyBag2> retVals = new nsHashPropertyBag(); + rv = argArray->AppendElement(retVals, false); + if (NS_FAILED(rv)) { + return rv; + } + + // Get the parent window for the dialog + nsCOMPtr<mozIDOMWindowProxy> parent = do_GetInterface(ctx); + rv = nsNSSDialogHelper::openDialog(parent, + "chrome://pippki/content/downloadcert.xul", + argArray); + if (NS_FAILED(rv)) { + return rv; + } + + rv = retVals->GetPropertyAsBool(NS_LITERAL_STRING("importConfirmed"), + importConfirmed); + if (NS_FAILED(rv)) { + return rv; + } + + *trust = nsIX509CertDB::UNTRUSTED; + if (!*importConfirmed) { + return NS_OK; + } + + bool trustForSSL = false; + rv = retVals->GetPropertyAsBool(NS_LITERAL_STRING("trustForSSL"), + &trustForSSL); + if (NS_FAILED(rv)) { + return rv; + } + bool trustForEmail = false; + rv = retVals->GetPropertyAsBool(NS_LITERAL_STRING("trustForEmail"), + &trustForEmail); + if (NS_FAILED(rv)) { + return rv; + } + bool trustForObjSign = false; + rv = retVals->GetPropertyAsBool(NS_LITERAL_STRING("trustForObjSign"), + &trustForObjSign); + if (NS_FAILED(rv)) { + return rv; + } + + *trust |= trustForSSL ? nsIX509CertDB::TRUSTED_SSL : 0; + *trust |= trustForEmail ? nsIX509CertDB::TRUSTED_EMAIL : 0; + *trust |= trustForObjSign ? nsIX509CertDB::TRUSTED_OBJSIGN : 0; + + return NS_OK; +} + +NS_IMETHODIMP +nsNSSDialogs::ChooseCertificate(nsIInterfaceRequestor* ctx, + const nsACString& hostname, + int32_t port, + const nsACString& organization, + const nsACString& issuerOrg, + nsIArray* certList, + /*out*/ uint32_t* selectedIndex, + /*out*/ bool* certificateChosen) +{ + NS_ENSURE_ARG_POINTER(ctx); + NS_ENSURE_ARG_POINTER(certList); + NS_ENSURE_ARG_POINTER(selectedIndex); + NS_ENSURE_ARG_POINTER(certificateChosen); + + *certificateChosen = false; + + nsCOMPtr<nsIMutableArray> argArray = nsArrayBase::Create(); + if (!argArray) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr<nsIWritableVariant> hostnameVariant = new nsVariant(); + nsresult rv = hostnameVariant->SetAsAUTF8String(hostname); + if (NS_FAILED(rv)) { + return rv; + } + rv = argArray->AppendElement(hostnameVariant, false); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr<nsIWritableVariant> organizationVariant = new nsVariant(); + rv = organizationVariant->SetAsAUTF8String(organization); + if (NS_FAILED(rv)) { + return rv; + } + rv = argArray->AppendElement(organizationVariant, false); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr<nsIWritableVariant> issuerOrgVariant = new nsVariant(); + rv = issuerOrgVariant->SetAsAUTF8String(issuerOrg); + if (NS_FAILED(rv)) { + return rv; + } + rv = argArray->AppendElement(issuerOrgVariant, false); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr<nsIWritableVariant> portVariant = new nsVariant(); + rv = portVariant->SetAsInt32(port); + if (NS_FAILED(rv)) { + return rv; + } + rv = argArray->AppendElement(portVariant, false); + if (NS_FAILED(rv)) { + return rv; + } + + rv = argArray->AppendElement(certList, false); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr<nsIWritablePropertyBag2> retVals = new nsHashPropertyBag(); + rv = argArray->AppendElement(retVals, false); + if (NS_FAILED(rv)) { + return rv; + } + + rv = nsNSSDialogHelper::openDialog(nullptr, + "chrome://pippki/content/clientauthask.xul", + argArray); + if (NS_FAILED(rv)) { + return rv; + } + + nsCOMPtr<nsIClientAuthUserDecision> extraResult = do_QueryInterface(ctx); + if (extraResult) { + bool rememberSelection = false; + rv = retVals->GetPropertyAsBool(NS_LITERAL_STRING("rememberSelection"), + &rememberSelection); + if (NS_SUCCEEDED(rv)) { + extraResult->SetRememberClientAuthCertificate(rememberSelection); + } + } + + rv = retVals->GetPropertyAsBool(NS_LITERAL_STRING("certChosen"), + certificateChosen); + if (NS_FAILED(rv)) { + return rv; + } + if (*certificateChosen) { + rv = retVals->GetPropertyAsUint32(NS_LITERAL_STRING("selectedIndex"), + selectedIndex); + if (NS_FAILED(rv)) { + return rv; + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsNSSDialogs::SetPKCS12FilePassword(nsIInterfaceRequestor* ctx, + /*out*/ nsAString& password, + /*out*/ bool* confirmedPassword) +{ + // |ctx| is allowed to be null. + NS_ENSURE_ARG(confirmedPassword); + + // Get the parent window for the dialog + nsCOMPtr<mozIDOMWindowProxy> parent = do_GetInterface(ctx); + nsCOMPtr<nsIWritablePropertyBag2> retVals = new nsHashPropertyBag(); + nsresult rv = + nsNSSDialogHelper::openDialog(parent, + "chrome://pippki/content/setp12password.xul", + retVals); + if (NS_FAILED(rv)) { + return rv; + } + + rv = retVals->GetPropertyAsBool(NS_LITERAL_STRING("confirmedPassword"), + confirmedPassword); + if (NS_FAILED(rv)) { + return rv; + } + + if (!*confirmedPassword) { + return NS_OK; + } + + return retVals->GetPropertyAsAString(NS_LITERAL_STRING("password"), password); +} + +NS_IMETHODIMP +nsNSSDialogs::GetPKCS12FilePassword(nsIInterfaceRequestor* ctx, + nsAString& _password, + bool* _retval) +{ + *_retval = false; + + nsCOMPtr<nsIPromptService> promptSvc( + do_GetService(NS_PROMPTSERVICE_CONTRACTID)); + if (!promptSvc) { + return NS_ERROR_FAILURE; + } + + nsAutoString msg; + nsresult rv = mPIPStringBundle->GetStringFromName( + u"getPKCS12FilePasswordMessage", getter_Copies(msg)); + if (NS_FAILED(rv)) { + return rv; + } + + // Get the parent window for the dialog + nsCOMPtr<mozIDOMWindowProxy> parent = do_GetInterface(ctx); + bool ignored = false; + char16_t* pwTemp = nullptr; + rv = promptSvc->PromptPassword(parent, nullptr, msg.get(), &pwTemp, nullptr, + &ignored, _retval); + if (NS_FAILED(rv)) { + return rv; + } + + if (*_retval) { + _password.Assign(pwTemp); + free(pwTemp); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsNSSDialogs::ViewCert(nsIInterfaceRequestor* ctx, nsIX509Cert* cert) +{ + // |ctx| is allowed to be null. + NS_ENSURE_ARG(cert); + + // Get the parent window for the dialog + nsCOMPtr<mozIDOMWindowProxy> parent = do_GetInterface(ctx); + return nsNSSDialogHelper::openDialog(parent, + "chrome://pippki/content/certViewer.xul", + cert, + false /*modal*/); +} + +NS_IMETHODIMP +nsNSSDialogs::DisplayGeneratingKeypairInfo(nsIInterfaceRequestor *aCtx, nsIKeygenThread *runnable) +{ + nsresult rv; + + // Get the parent window for the dialog + nsCOMPtr<mozIDOMWindowProxy> parent = do_GetInterface(aCtx); + + rv = nsNSSDialogHelper::openDialog(parent, + "chrome://pippki/content/createCertInfo.xul", + runnable); + return rv; +} + +NS_IMETHODIMP +nsNSSDialogs::ChooseToken(nsIInterfaceRequestor *aCtx, const char16_t **aTokenList, uint32_t aCount, char16_t **aTokenChosen, bool *aCanceled) { + nsresult rv; + uint32_t i; + + *aCanceled = false; + + nsCOMPtr<nsIDialogParamBlock> block = + do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID); + if (!block) return NS_ERROR_FAILURE; + + block->SetNumberStrings(aCount); + + for (i = 0; i < aCount; i++) { + rv = block->SetString(i, aTokenList[i]); + if (NS_FAILED(rv)) return rv; + } + + rv = block->SetInt(0, aCount); + if (NS_FAILED(rv)) return rv; + + rv = nsNSSDialogHelper::openDialog(nullptr, + "chrome://pippki/content/choosetoken.xul", + block); + if (NS_FAILED(rv)) return rv; + + int32_t status; + + rv = block->GetInt(0, &status); + if (NS_FAILED(rv)) return rv; + + *aCanceled = (status == 0)?true:false; + if (!*aCanceled) { + // retrieve the nickname + rv = block->GetString(0, aTokenChosen); + } + return rv; +} + +NS_IMETHODIMP +nsNSSDialogs::DisplayProtectedAuth(nsIInterfaceRequestor *aCtx, nsIProtectedAuthThread *runnable) +{ + // We cannot use nsNSSDialogHelper here. We cannot allow close widget + // in the window because protected authentication is interruptible + // from user interface and changing nsNSSDialogHelper's static variable + // would not be thread-safe + + nsresult rv = NS_ERROR_FAILURE; + + // Get the parent window for the dialog + nsCOMPtr<mozIDOMWindowProxy> parent = do_GetInterface(aCtx); + + nsCOMPtr<nsIWindowWatcher> windowWatcher = + do_GetService("@mozilla.org/embedcomp/window-watcher;1", &rv); + if (NS_FAILED(rv)) + return rv; + + if (!parent) { + windowWatcher->GetActiveWindow(getter_AddRefs(parent)); + } + + nsCOMPtr<mozIDOMWindowProxy> newWindow; + rv = windowWatcher->OpenWindow(parent, + "chrome://pippki/content/protectedAuth.xul", + "_blank", + "centerscreen,chrome,modal,titlebar,close=no", + runnable, + getter_AddRefs(newWindow)); + + return rv; +} |