123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- /* -*- 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/. */
- #include "nsPK11TokenDB.h"
- #include <string.h>
- #include "ScopedNSSTypes.h"
- #include "mozilla/Casting.h"
- #include "mozilla/Unused.h"
- #include "nsIMutableArray.h"
- #include "nsISupports.h"
- #include "nsNSSComponent.h"
- #include "nsPromiseFlatString.h"
- #include "nsReadableUtils.h"
- #include "nsServiceManagerUtils.h"
- #include "prerror.h"
- #include "secerr.h"
- extern mozilla::LazyLogModule gPIPNSSLog;
- NS_IMPL_ISUPPORTS(nsPK11Token, nsIPK11Token)
- nsPK11Token::nsPK11Token(PK11SlotInfo* slot)
- : mUIContext(new PipUIContext())
- {
- MOZ_ASSERT(slot);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return;
- mSlot.reset(PK11_ReferenceSlot(slot));
- mSeries = PK11_GetSlotSeries(slot);
- Unused << refreshTokenInfo(locker);
- }
- nsresult
- nsPK11Token::refreshTokenInfo(const nsNSSShutDownPreventionLock& /*proofOfLock*/)
- {
- mTokenName = PK11_GetTokenName(mSlot.get());
- CK_TOKEN_INFO tokInfo;
- nsresult rv = MapSECStatus(PK11_GetTokenInfo(mSlot.get(), &tokInfo));
- if (NS_FAILED(rv)) {
- return rv;
- }
- // Set the Label field
- const char* ccLabel = mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(tokInfo.label);
- mTokenLabel.Assign(ccLabel, strnlen(ccLabel, sizeof(tokInfo.label)));
- mTokenLabel.Trim(" ", false, true);
- // Set the Manufacturer field
- const char* ccManID =
- mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(tokInfo.manufacturerID);
- mTokenManufacturerID.Assign(
- ccManID,
- strnlen(ccManID, sizeof(tokInfo.manufacturerID)));
- mTokenManufacturerID.Trim(" ", false, true);
- // Set the Hardware Version field
- mTokenHWVersion.Truncate();
- mTokenHWVersion.AppendInt(tokInfo.hardwareVersion.major);
- mTokenHWVersion.Append('.');
- mTokenHWVersion.AppendInt(tokInfo.hardwareVersion.minor);
- // Set the Firmware Version field
- mTokenFWVersion.Truncate();
- mTokenFWVersion.AppendInt(tokInfo.firmwareVersion.major);
- mTokenFWVersion.Append('.');
- mTokenFWVersion.AppendInt(tokInfo.firmwareVersion.minor);
- // Set the Serial Number field
- const char* ccSerial =
- mozilla::BitwiseCast<char*, CK_CHAR*>(tokInfo.serialNumber);
- mTokenSerialNum.Assign(ccSerial,
- strnlen(ccSerial, sizeof(tokInfo.serialNumber)));
- mTokenSerialNum.Trim(" ", false, true);
- return NS_OK;
- }
- nsPK11Token::~nsPK11Token()
- {
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return;
- }
- destructorSafeDestroyNSSReference();
- shutdown(ShutdownCalledFrom::Object);
- }
- void
- nsPK11Token::virtualDestroyNSSReference()
- {
- destructorSafeDestroyNSSReference();
- }
- void
- nsPK11Token::destructorSafeDestroyNSSReference()
- {
- mSlot = nullptr;
- }
- nsresult
- nsPK11Token::GetAttributeHelper(const nsACString& attribute,
- /*out*/ nsACString& xpcomOutParam)
- {
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
- // Handle removals/insertions.
- if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
- nsresult rv = refreshTokenInfo(locker);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- xpcomOutParam = attribute;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::GetTokenName(/*out*/ nsACString& tokenName)
- {
- return GetAttributeHelper(mTokenName, tokenName);
- }
- NS_IMETHODIMP
- nsPK11Token::GetTokenLabel(/*out*/ nsACString& tokenLabel)
- {
- return GetAttributeHelper(mTokenLabel, tokenLabel);
- }
- NS_IMETHODIMP
- nsPK11Token::GetTokenManID(/*out*/ nsACString& tokenManufacturerID)
- {
- return GetAttributeHelper(mTokenManufacturerID, tokenManufacturerID);
- }
- NS_IMETHODIMP
- nsPK11Token::GetTokenHWVersion(/*out*/ nsACString& tokenHWVersion)
- {
- return GetAttributeHelper(mTokenHWVersion, tokenHWVersion);
- }
- NS_IMETHODIMP
- nsPK11Token::GetTokenFWVersion(/*out*/ nsACString& tokenFWVersion)
- {
- return GetAttributeHelper(mTokenFWVersion, tokenFWVersion);
- }
- NS_IMETHODIMP
- nsPK11Token::GetTokenSerialNumber(/*out*/ nsACString& tokenSerialNum)
- {
- return GetAttributeHelper(mTokenSerialNum, tokenSerialNum);
- }
- NS_IMETHODIMP
- nsPK11Token::IsLoggedIn(bool* _retval)
- {
- NS_ENSURE_ARG_POINTER(_retval);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- *_retval = PK11_IsLoggedIn(mSlot.get(), 0);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::Login(bool force)
- {
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- nsresult rv;
- bool test;
- rv = this->NeedsLogin(&test);
- if (NS_FAILED(rv)) return rv;
- if (test && force) {
- rv = this->LogoutSimple();
- if (NS_FAILED(rv)) return rv;
- }
- rv = setPassword(mSlot.get(), mUIContext, locker);
- if (NS_FAILED(rv)) return rv;
- return MapSECStatus(PK11_Authenticate(mSlot.get(), true, mUIContext));
- }
- NS_IMETHODIMP
- nsPK11Token::LogoutSimple()
- {
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- // PK11_Logout() can fail if the user wasn't logged in beforehand. We want
- // this method to succeed even in this case, so we ignore the return value.
- Unused << PK11_Logout(mSlot.get());
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::LogoutAndDropAuthenticatedResources()
- {
- static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
- nsresult rv = LogoutSimple();
- if (NS_FAILED(rv))
- return rv;
- nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
- if (NS_FAILED(rv))
- return rv;
- return nssComponent->LogoutAuthenticatedPK11();
- }
- NS_IMETHODIMP
- nsPK11Token::Reset()
- {
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- return MapSECStatus(PK11_ResetToken(mSlot.get(), nullptr));
- }
- NS_IMETHODIMP
- nsPK11Token::GetMinimumPasswordLength(int32_t* aMinimumPasswordLength)
- {
- NS_ENSURE_ARG_POINTER(aMinimumPasswordLength);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- *aMinimumPasswordLength = PK11_GetMinimumPwdLength(mSlot.get());
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::GetNeedsUserInit(bool* aNeedsUserInit)
- {
- NS_ENSURE_ARG_POINTER(aNeedsUserInit);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- *aNeedsUserInit = PK11_NeedUserInit(mSlot.get());
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::CheckPassword(const nsACString& password, bool* _retval)
- {
- NS_ENSURE_ARG_POINTER(_retval);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- SECStatus srv =
- PK11_CheckUserPassword(mSlot.get(), PromiseFlatCString(password).get());
- if (srv != SECSuccess) {
- *_retval = false;
- PRErrorCode error = PR_GetError();
- if (error != SEC_ERROR_BAD_PASSWORD) {
- /* something really bad happened - throw an exception */
- return mozilla::psm::GetXPCOMFromNSSError(error);
- }
- } else {
- *_retval = true;
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::InitPassword(const nsACString& initialPassword)
- {
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- return MapSECStatus(
- PK11_InitPin(mSlot.get(), "", PromiseFlatCString(initialPassword).get()));
- }
- NS_IMETHODIMP
- nsPK11Token::GetAskPasswordTimes(int32_t* askTimes)
- {
- NS_ENSURE_ARG_POINTER(askTimes);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- int askTimeout;
- PK11_GetSlotPWValues(mSlot.get(), askTimes, &askTimeout);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::GetAskPasswordTimeout(int32_t* askTimeout)
- {
- NS_ENSURE_ARG_POINTER(askTimeout);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- int askTimes;
- PK11_GetSlotPWValues(mSlot.get(), &askTimes, askTimeout);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::SetAskPasswordDefaults(const int32_t askTimes,
- const int32_t askTimeout)
- {
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- PK11_SetSlotPWValues(mSlot.get(), askTimes, askTimeout);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::ChangePassword(const nsACString& oldPassword,
- const nsACString& newPassword)
- {
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- // PK11_ChangePW() has different semantics for the empty string and for
- // nullptr. In order to support this difference, we need to check IsVoid() to
- // find out if our caller supplied null/undefined args or just empty strings.
- // See Bug 447589.
- return MapSECStatus(PK11_ChangePW(
- mSlot.get(),
- oldPassword.IsVoid() ? nullptr : PromiseFlatCString(oldPassword).get(),
- newPassword.IsVoid() ? nullptr : PromiseFlatCString(newPassword).get()));
- }
- NS_IMETHODIMP
- nsPK11Token::IsHardwareToken(bool* _retval)
- {
- NS_ENSURE_ARG_POINTER(_retval);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- *_retval = PK11_IsHW(mSlot.get());
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::NeedsLogin(bool* _retval)
- {
- NS_ENSURE_ARG_POINTER(_retval);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- *_retval = PK11_NeedLogin(mSlot.get());
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11Token::IsFriendly(bool* _retval)
- {
- NS_ENSURE_ARG_POINTER(_retval);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown())
- return NS_ERROR_NOT_AVAILABLE;
- *_retval = PK11_IsFriendly(mSlot.get());
- return NS_OK;
- }
- /*=========================================================*/
- NS_IMPL_ISUPPORTS(nsPK11TokenDB, nsIPK11TokenDB)
- nsPK11TokenDB::nsPK11TokenDB()
- {
- }
- nsPK11TokenDB::~nsPK11TokenDB()
- {
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return;
- }
- shutdown(ShutdownCalledFrom::Object);
- }
- NS_IMETHODIMP
- nsPK11TokenDB::GetInternalKeyToken(nsIPK11Token** _retval)
- {
- NS_ENSURE_ARG_POINTER(_retval);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
- UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
- if (!slot) {
- return NS_ERROR_FAILURE;
- }
- nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot.get());
- token.forget(_retval);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11TokenDB::FindTokenByName(const nsACString& tokenName,
- /*out*/ nsIPK11Token** _retval)
- {
- NS_ENSURE_ARG_POINTER(_retval);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
- UniquePK11SlotInfo slot(
- PK11_FindSlotByName(PromiseFlatCString(tokenName).get()));
- if (!slot) {
- return NS_ERROR_FAILURE;
- }
- nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot.get());
- token.forget(_retval);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsPK11TokenDB::ListTokens(nsISimpleEnumerator** _retval)
- {
- NS_ENSURE_ARG_POINTER(_retval);
- nsNSSShutDownPreventionLock locker;
- if (isAlreadyShutDown()) {
- return NS_ERROR_NOT_AVAILABLE;
- }
- nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
- if (!array) {
- return NS_ERROR_FAILURE;
- }
- *_retval = nullptr;
- UniquePK11SlotList list(
- PK11_GetAllTokens(CKM_INVALID_MECHANISM, false, false, 0));
- if (!list) {
- return NS_ERROR_FAILURE;
- }
- for (PK11SlotListElement* le = PK11_GetFirstSafe(list.get()); le;
- le = PK11_GetNextSafe(list.get(), le, false)) {
- nsCOMPtr<nsIPK11Token> token = new nsPK11Token(le->slot);
- nsresult rv = array->AppendElement(token, false);
- if (NS_FAILED(rv)) {
- return rv;
- }
- }
- return array->Enumerate(_retval);
- }
|