summaryrefslogtreecommitdiffstats
path: root/dom/wifi/WifiCertService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/wifi/WifiCertService.cpp')
-rw-r--r--dom/wifi/WifiCertService.cpp536
1 files changed, 0 insertions, 536 deletions
diff --git a/dom/wifi/WifiCertService.cpp b/dom/wifi/WifiCertService.cpp
deleted file mode 100644
index 85e0d2f5b..000000000
--- a/dom/wifi/WifiCertService.cpp
+++ /dev/null
@@ -1,536 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-#include "WifiCertService.h"
-
-#include "mozilla/ClearOnShutdown.h"
-#include "mozilla/EndianUtils.h"
-#include "mozilla/ModuleUtils.h"
-#include "mozilla/RefPtr.h"
-#include "mozilla/dom/File.h"
-#include "mozilla/dom/ToJSValue.h"
-#include "cert.h"
-#include "certdb.h"
-#include "CryptoTask.h"
-#include "nsIDOMBlob.h"
-#include "nsIWifiService.h"
-#include "nsNetUtil.h"
-#include "nsIInputStream.h"
-#include "nsServiceManagerUtils.h"
-#include "nsXULAppAPI.h"
-#include "ScopedNSSTypes.h"
-
-#define NS_WIFICERTSERVICE_CID \
- { 0x83585afd, 0x0e11, 0x43aa, {0x83, 0x46, 0xf3, 0x4d, 0x97, 0x5e, 0x46, 0x77} }
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-namespace mozilla {
-
-// The singleton Wifi Cert service, to be used on the main thread.
-StaticRefPtr<WifiCertService> gWifiCertService;
-
-class ImportCertTask final: public CryptoTask
-{
-public:
- ImportCertTask(int32_t aId, Blob* aCertBlob,
- const nsAString& aCertPassword,
- const nsAString& aCertNickname)
- : mBlob(aCertBlob)
- , mPassword(aCertPassword)
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- mResult.mId = aId;
- mResult.mStatus = 0;
- mResult.mUsageFlag = 0;
- mResult.mNickname = aCertNickname;
- }
-
-private:
- virtual void ReleaseNSSResources() {}
-
- virtual nsresult CalculateResult() override
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- // read data from blob.
- nsCString blobBuf;
- nsresult rv = ReadBlob(blobBuf);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- char* buf;
- uint32_t size = blobBuf.GetMutableData(&buf);
- if (size == 0) {
- return NS_ERROR_OUT_OF_MEMORY;
- }
-
- // Try import as DER format first.
- rv = ImportDERBlob(buf, size);
- if (NS_SUCCEEDED(rv)) {
- return rv;
- }
-
- // Try import as PKCS#12 format.
- return ImportPKCS12Blob(buf, size, mPassword);
- }
-
- virtual void CallCallback(nsresult rv)
- {
- if (NS_FAILED(rv)) {
- mResult.mStatus = -1;
- }
- gWifiCertService->DispatchResult(mResult);
- }
-
- nsresult ImportDERBlob(char* buf, uint32_t size)
- {
- // Create certificate object.
- ScopedCERTCertificate cert(CERT_DecodeCertFromPackage(buf, size));
- if (!cert) {
- return MapSECStatus(SECFailure);
- }
-
- // Import certificate.
- return ImportCert(cert);
- }
-
- static SECItem*
- HandleNicknameCollision(SECItem* aOldNickname, PRBool* aCancel, void* aWincx)
- {
- const char* dummyName = "Imported User Cert";
- const size_t dummyNameLen = strlen(dummyName);
- SECItem* newNick = ::SECITEM_AllocItem(nullptr, nullptr, dummyNameLen + 1);
- if (!newNick) {
- return nullptr;
- }
-
- newNick->type = siAsciiString;
- // Dummy name, will be renamed later.
- memcpy(newNick->data, dummyName, dummyNameLen + 1);
- newNick->len = dummyNameLen;
-
- return newNick;
- }
-
- static SECStatus
- HandleNicknameUpdate(const CERTCertificate *aCert,
- const SECItem *default_nickname,
- SECItem **new_nickname,
- void *arg)
- {
- WifiCertServiceResultOptions *result = (WifiCertServiceResultOptions *)arg;
-
- nsCString userNickname;
- CopyUTF16toUTF8(result->mNickname, userNickname);
-
- nsCString fullNickname;
- if (aCert->isRoot && (aCert->nsCertType & NS_CERT_TYPE_SSL_CA)) {
- // Accept self-signed SSL CA as server certificate.
- fullNickname.AssignLiteral("WIFI_SERVERCERT_");
- fullNickname += userNickname;
- result->mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_SERVER;
- } else if (aCert->nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
- // User Certificate
- fullNickname.AssignLiteral("WIFI_USERCERT_");
- fullNickname += userNickname;
- result->mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_USER;
- }
- char* nickname;
- uint32_t length = fullNickname.GetMutableData(&nickname);
-
- SECItem* newNick = ::SECITEM_AllocItem(nullptr, nullptr, length + 1);
- if (!newNick) {
- return SECFailure;
- }
-
- newNick->type = siAsciiString;
- memcpy(newNick->data, nickname, length + 1);
- newNick->len = length;
-
- *new_nickname = newNick;
- return SECSuccess;
- }
-
- nsresult ImportPKCS12Blob(char* buf, uint32_t size, const nsAString& aPassword)
- {
- nsString password(aPassword);
-
- // password is null-terminated wide-char string.
- // passwordItem is required to be big-endian form of password, stored in char
- // array, including the null-termination.
- uint32_t length = password.Length() + 1;
- ScopedSECItem passwordItem(
- ::SECITEM_AllocItem(nullptr, nullptr, length * sizeof(nsString::char_type)));
-
- if (!passwordItem) {
- return NS_ERROR_FAILURE;
- }
-
- mozilla::NativeEndian::copyAndSwapToBigEndian(passwordItem->data,
- password.BeginReading(),
- length);
- // Create a decoder.
- ScopedSEC_PKCS12DecoderContext p12dcx(SEC_PKCS12DecoderStart(
- passwordItem, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr,
- nullptr));
-
- if (!p12dcx) {
- return NS_ERROR_FAILURE;
- }
-
- // Assign data to decorder.
- SECStatus srv = SEC_PKCS12DecoderUpdate(p12dcx,
- reinterpret_cast<unsigned char*>(buf),
- size);
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- // Verify certificates.
- srv = SEC_PKCS12DecoderVerify(p12dcx);
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- // Set certificate nickname and usage flag.
- srv = SEC_PKCS12DecoderRenameCertNicknames(p12dcx, HandleNicknameUpdate,
- &mResult);
-
- // Validate certificates.
- srv = SEC_PKCS12DecoderValidateBags(p12dcx, HandleNicknameCollision);
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- // Initialize slot.
- ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
- if (!slot) {
- return NS_ERROR_FAILURE;
- }
- if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
- srv = PK11_InitPin(slot, "", "");
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
- }
-
- // Import cert and key.
- srv = SEC_PKCS12DecoderImportBags(p12dcx);
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- // User certificate must be imported from PKCS#12.
- return (mResult.mUsageFlag & nsIWifiCertService::WIFI_CERT_USAGE_FLAG_USER)
- ? NS_OK : NS_ERROR_FAILURE;
- }
-
- nsresult ReadBlob(/*out*/ nsCString& aBuf)
- {
- NS_ENSURE_ARG_POINTER(mBlob);
-
- static const uint64_t MAX_FILE_SIZE = 16384;
-
- ErrorResult rv;
- uint64_t size = mBlob->GetSize(rv);
- if (NS_WARN_IF(rv.Failed())) {
- return rv.StealNSResult();
- }
-
- if (size > MAX_FILE_SIZE) {
- return NS_ERROR_FILE_TOO_BIG;
- }
-
- nsCOMPtr<nsIInputStream> inputStream;
- mBlob->GetInternalStream(getter_AddRefs(inputStream), rv);
- if (NS_WARN_IF(rv.Failed())) {
- return rv.StealNSResult();
- }
-
- rv = NS_ReadInputStreamToString(inputStream, aBuf, (uint32_t)size);
- if (NS_WARN_IF(rv.Failed())) {
- return rv.StealNSResult();
- }
-
- return NS_OK;
- }
-
- nsresult ImportCert(CERTCertificate* aCert)
- {
- nsCString userNickname, fullNickname;
-
- CopyUTF16toUTF8(mResult.mNickname, userNickname);
- // Determine certificate nickname by adding prefix according to its type.
- if (aCert->isRoot && (aCert->nsCertType & NS_CERT_TYPE_SSL_CA)) {
- // Accept self-signed SSL CA as server certificate.
- fullNickname.AssignLiteral("WIFI_SERVERCERT_");
- fullNickname += userNickname;
- mResult.mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_SERVER;
- } else if (aCert->nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
- // User Certificate
- fullNickname.AssignLiteral("WIFI_USERCERT_");
- fullNickname += userNickname;
- mResult.mUsageFlag |= nsIWifiCertService::WIFI_CERT_USAGE_FLAG_USER;
- } else {
- return NS_ERROR_ABORT;
- }
-
- char* nickname;
- uint32_t length;
- length = fullNickname.GetMutableData(&nickname);
- if (length == 0) {
- return NS_ERROR_UNEXPECTED;
- }
-
- // Import certificate, duplicated nickname will cause error.
- SECStatus srv = CERT_AddTempCertToPerm(aCert, nickname, nullptr);
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- return NS_OK;
- }
-
- RefPtr<Blob> mBlob;
- nsString mPassword;
- WifiCertServiceResultOptions mResult;
-};
-
-class DeleteCertTask final: public CryptoTask
-{
-public:
- DeleteCertTask(int32_t aId, const nsAString& aCertNickname)
- {
- MOZ_ASSERT(NS_IsMainThread());
-
- mResult.mId = aId;
- mResult.mStatus = 0;
- mResult.mUsageFlag = 0;
- mResult.mNickname = aCertNickname;
- }
-
-private:
- virtual void ReleaseNSSResources() {}
-
- virtual nsresult CalculateResult() override
- {
- MOZ_ASSERT(!NS_IsMainThread());
-
- nsCString userNickname;
- CopyUTF16toUTF8(mResult.mNickname, userNickname);
-
- // Delete server certificate.
- nsCString serverCertName("WIFI_SERVERCERT_", 16);
- serverCertName += userNickname;
- nsresult rv = deleteCert(serverCertName);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- // Delete user certificate and private key.
- nsCString userCertName("WIFI_USERCERT_", 14);
- userCertName += userNickname;
- rv = deleteCert(userCertName);
- if (NS_FAILED(rv)) {
- return rv;
- }
-
- return NS_OK;
- }
-
- nsresult deleteCert(const nsCString &aCertNickname)
- {
- ScopedCERTCertificate cert(
- CERT_FindCertByNickname(CERT_GetDefaultCertDB(), aCertNickname.get())
- );
- // Because we delete certificates in blind, so it's acceptable to delete
- // a non-exist certificate.
- if (!cert) {
- return NS_OK;
- }
-
- ScopedPK11SlotInfo slot(
- PK11_KeyForCertExists(cert, nullptr, nullptr)
- );
-
- SECStatus srv;
- if (slot) {
- // Delete private key along with certificate.
- srv = PK11_DeleteTokenCertAndKey(cert, nullptr);
- } else {
- srv = SEC_DeletePermCertificate(cert);
- }
-
- if (srv != SECSuccess) {
- return MapSECStatus(srv);
- }
-
- return NS_OK;
- }
-
- virtual void CallCallback(nsresult rv)
- {
- if (NS_FAILED(rv)) {
- mResult.mStatus = -1;
- }
- gWifiCertService->DispatchResult(mResult);
- }
-
- WifiCertServiceResultOptions mResult;
-};
-
-NS_IMPL_ISUPPORTS(WifiCertService, nsIWifiCertService)
-
-NS_IMETHODIMP
-WifiCertService::Start(nsIWifiEventListener* aListener)
-{
- MOZ_ASSERT(aListener);
-
- mListener = aListener;
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
-WifiCertService::Shutdown()
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- mListener = nullptr;
-
- return NS_OK;
-}
-
-void
-WifiCertService::DispatchResult(const WifiCertServiceResultOptions& aOptions)
-{
- MOZ_ASSERT(NS_IsMainThread());
-
- mozilla::AutoSafeJSContext cx;
- JS::RootedValue val(cx);
- nsCString dummyInterface;
-
- if (!ToJSValue(cx, aOptions, &val)) {
- return;
- }
-
- // Certll the listener with a JS value.
- mListener->OnCommand(val, dummyInterface);
-}
-
-WifiCertService::WifiCertService()
-{
- MOZ_ASSERT(NS_IsMainThread());
- MOZ_ASSERT(!gWifiCertService);
-}
-
-WifiCertService::~WifiCertService()
-{
- MOZ_ASSERT(!gWifiCertService);
-
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return;
- }
- shutdown(ShutdownCalledFrom::Object);
-}
-
-already_AddRefed<WifiCertService>
-WifiCertService::FactoryCreate()
-{
- if (!XRE_IsParentProcess()) {
- return nullptr;
- }
-
- MOZ_ASSERT(NS_IsMainThread());
-
- if (!gWifiCertService) {
- gWifiCertService = new WifiCertService();
- ClearOnShutdown(&gWifiCertService);
- }
-
- RefPtr<WifiCertService> service = gWifiCertService.get();
- return service.forget();
-}
-
-NS_IMETHODIMP
-WifiCertService::ImportCert(int32_t aId, nsIDOMBlob* aCertBlob,
- const nsAString& aCertPassword,
- const nsAString& aCertNickname)
-{
- RefPtr<Blob> blob = static_cast<Blob*>(aCertBlob);
- RefPtr<CryptoTask> task = new ImportCertTask(aId, blob, aCertPassword,
- aCertNickname);
- return task->Dispatch("WifiImportCert");
-}
-
-NS_IMETHODIMP
-WifiCertService::DeleteCert(int32_t aId, const nsAString& aCertNickname)
-{
- RefPtr<CryptoTask> task = new DeleteCertTask(aId, aCertNickname);
- return task->Dispatch("WifiDeleteCert");
-}
-
-NS_IMETHODIMP
-WifiCertService::HasPrivateKey(const nsAString& aCertNickname, bool *aHasKey)
-{
- *aHasKey = false;
-
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
-
- nsCString certNickname;
- CopyUTF16toUTF8(aCertNickname, certNickname);
-
- ScopedCERTCertificate cert(
- CERT_FindCertByNickname(CERT_GetDefaultCertDB(), certNickname.get())
- );
- if (!cert) {
- return NS_OK;
- }
-
- ScopedPK11SlotInfo slot(
- PK11_KeyForCertExists(cert, nullptr, nullptr)
- );
- if (slot) {
- *aHasKey = true;
- }
-
- return NS_OK;
-}
-
-NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(WifiCertService,
- WifiCertService::FactoryCreate)
-
-NS_DEFINE_NAMED_CID(NS_WIFICERTSERVICE_CID);
-
-static const mozilla::Module::CIDEntry kWifiCertServiceCIDs[] = {
- { &kNS_WIFICERTSERVICE_CID, false, nullptr, WifiCertServiceConstructor },
- { nullptr }
-};
-
-static const mozilla::Module::ContractIDEntry kWifiCertServiceContracts[] = {
- { "@mozilla.org/wifi/certservice;1", &kNS_WIFICERTSERVICE_CID },
- { nullptr }
-};
-
-static const mozilla::Module kWifiCertServiceModule = {
- mozilla::Module::kVersion,
- kWifiCertServiceCIDs,
- kWifiCertServiceContracts,
- nullptr
-};
-
-} // namespace mozilla
-
-NSMODULE_DEFN(WifiCertServiceModule) = &kWifiCertServiceModule;