LCOV - code coverage report
Current view: top level - security/manager/ssl - nsPK11TokenDB.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 51 241 21.2 %
Date: 2017-07-14 16:53:18 Functions: 11 41 26.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  *
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : #include "nsPK11TokenDB.h"
       7             : 
       8             : #include <string.h>
       9             : 
      10             : #include "ScopedNSSTypes.h"
      11             : #include "mozilla/Casting.h"
      12             : #include "mozilla/Unused.h"
      13             : #include "nsIMutableArray.h"
      14             : #include "nsISupports.h"
      15             : #include "nsNSSComponent.h"
      16             : #include "nsPromiseFlatString.h"
      17             : #include "nsReadableUtils.h"
      18             : #include "nsServiceManagerUtils.h"
      19             : #include "prerror.h"
      20             : #include "secerr.h"
      21             : 
      22             : extern mozilla::LazyLogModule gPIPNSSLog;
      23             : 
      24          17 : NS_IMPL_ISUPPORTS(nsPK11Token, nsIPK11Token)
      25             : 
      26           1 : nsPK11Token::nsPK11Token(PK11SlotInfo* slot)
      27           2 :   : mUIContext(new PipUIContext())
      28             : {
      29           1 :   MOZ_ASSERT(slot);
      30             : 
      31           2 :   nsNSSShutDownPreventionLock locker;
      32           1 :   if (isAlreadyShutDown())
      33           0 :     return;
      34             : 
      35           1 :   mSlot.reset(PK11_ReferenceSlot(slot));
      36           1 :   mSeries = PK11_GetSlotSeries(slot);
      37             : 
      38           1 :   Unused << refreshTokenInfo(locker);
      39             : }
      40             : 
      41             : nsresult
      42           1 : nsPK11Token::refreshTokenInfo(const nsNSSShutDownPreventionLock& /*proofOfLock*/)
      43             : {
      44           1 :   mTokenName = PK11_GetTokenName(mSlot.get());
      45             : 
      46             :   CK_TOKEN_INFO tokInfo;
      47           1 :   nsresult rv = MapSECStatus(PK11_GetTokenInfo(mSlot.get(), &tokInfo));
      48           1 :   if (NS_FAILED(rv)) {
      49           0 :     return rv;
      50             :   }
      51             : 
      52             :   // Set the Label field
      53           1 :   const char* ccLabel = mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(tokInfo.label);
      54           1 :   mTokenLabel.Assign(ccLabel, strnlen(ccLabel, sizeof(tokInfo.label)));
      55           1 :   mTokenLabel.Trim(" ", false, true);
      56             : 
      57             :   // Set the Manufacturer field
      58             :   const char* ccManID =
      59           1 :     mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(tokInfo.manufacturerID);
      60           1 :   mTokenManufacturerID.Assign(
      61             :     ccManID,
      62           2 :     strnlen(ccManID, sizeof(tokInfo.manufacturerID)));
      63           1 :   mTokenManufacturerID.Trim(" ", false, true);
      64             : 
      65             :   // Set the Hardware Version field
      66           1 :   mTokenHWVersion.Truncate();
      67           1 :   mTokenHWVersion.AppendInt(tokInfo.hardwareVersion.major);
      68           1 :   mTokenHWVersion.Append('.');
      69           1 :   mTokenHWVersion.AppendInt(tokInfo.hardwareVersion.minor);
      70             : 
      71             :   // Set the Firmware Version field
      72           1 :   mTokenFWVersion.Truncate();
      73           1 :   mTokenFWVersion.AppendInt(tokInfo.firmwareVersion.major);
      74           1 :   mTokenFWVersion.Append('.');
      75           1 :   mTokenFWVersion.AppendInt(tokInfo.firmwareVersion.minor);
      76             : 
      77             :   // Set the Serial Number field
      78             :   const char* ccSerial =
      79           1 :     mozilla::BitwiseCast<char*, CK_CHAR*>(tokInfo.serialNumber);
      80           1 :   mTokenSerialNum.Assign(ccSerial,
      81           2 :                          strnlen(ccSerial, sizeof(tokInfo.serialNumber)));
      82           1 :   mTokenSerialNum.Trim(" ", false, true);
      83             : 
      84           1 :   return NS_OK;
      85             : }
      86             : 
      87           0 : nsPK11Token::~nsPK11Token()
      88             : {
      89           0 :   nsNSSShutDownPreventionLock locker;
      90           0 :   if (isAlreadyShutDown()) {
      91           0 :     return;
      92             :   }
      93           0 :   destructorSafeDestroyNSSReference();
      94           0 :   shutdown(ShutdownCalledFrom::Object);
      95           0 : }
      96             : 
      97             : void
      98           0 : nsPK11Token::virtualDestroyNSSReference()
      99             : {
     100           0 :   destructorSafeDestroyNSSReference();
     101           0 : }
     102             : 
     103             : void
     104           0 : nsPK11Token::destructorSafeDestroyNSSReference()
     105             : {
     106           0 :   mSlot = nullptr;
     107           0 : }
     108             : 
     109             : nsresult
     110           0 : nsPK11Token::GetAttributeHelper(const nsACString& attribute,
     111             :                         /*out*/ nsACString& xpcomOutParam)
     112             : {
     113           0 :   nsNSSShutDownPreventionLock locker;
     114           0 :   if (isAlreadyShutDown()) {
     115           0 :     return NS_ERROR_NOT_AVAILABLE;
     116             :   }
     117             : 
     118             :   // Handle removals/insertions.
     119           0 :   if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
     120           0 :     nsresult rv = refreshTokenInfo(locker);
     121           0 :     if (NS_FAILED(rv)) {
     122           0 :       return rv;
     123             :     }
     124             :   }
     125             : 
     126           0 :   xpcomOutParam = attribute;
     127           0 :   return NS_OK;
     128             : }
     129             : 
     130             : NS_IMETHODIMP
     131           0 : nsPK11Token::GetTokenName(/*out*/ nsACString& tokenName)
     132             : {
     133           0 :   return GetAttributeHelper(mTokenName, tokenName);
     134             : }
     135             : 
     136             : NS_IMETHODIMP
     137           0 : nsPK11Token::GetTokenLabel(/*out*/ nsACString& tokenLabel)
     138             : {
     139           0 :   return GetAttributeHelper(mTokenLabel, tokenLabel);
     140             : }
     141             : 
     142             : NS_IMETHODIMP
     143           0 : nsPK11Token::GetTokenManID(/*out*/ nsACString& tokenManufacturerID)
     144             : {
     145           0 :   return GetAttributeHelper(mTokenManufacturerID, tokenManufacturerID);
     146             : }
     147             : 
     148             : NS_IMETHODIMP
     149           0 : nsPK11Token::GetTokenHWVersion(/*out*/ nsACString& tokenHWVersion)
     150             : {
     151           0 :   return GetAttributeHelper(mTokenHWVersion, tokenHWVersion);
     152             : }
     153             : 
     154             : NS_IMETHODIMP
     155           0 : nsPK11Token::GetTokenFWVersion(/*out*/ nsACString& tokenFWVersion)
     156             : {
     157           0 :   return GetAttributeHelper(mTokenFWVersion, tokenFWVersion);
     158             : }
     159             : 
     160             : NS_IMETHODIMP
     161           0 : nsPK11Token::GetTokenSerialNumber(/*out*/ nsACString& tokenSerialNum)
     162             : {
     163           0 :   return GetAttributeHelper(mTokenSerialNum, tokenSerialNum);
     164             : }
     165             : 
     166             : NS_IMETHODIMP
     167           0 : nsPK11Token::IsLoggedIn(bool* _retval)
     168             : {
     169           0 :   NS_ENSURE_ARG_POINTER(_retval);
     170             : 
     171           0 :   nsNSSShutDownPreventionLock locker;
     172           0 :   if (isAlreadyShutDown())
     173           0 :     return NS_ERROR_NOT_AVAILABLE;
     174             : 
     175           0 :   *_retval = PK11_IsLoggedIn(mSlot.get(), 0);
     176             : 
     177           0 :   return NS_OK;
     178             : }
     179             : 
     180             : NS_IMETHODIMP
     181           0 : nsPK11Token::Login(bool force)
     182             : {
     183           0 :   nsNSSShutDownPreventionLock locker;
     184           0 :   if (isAlreadyShutDown())
     185           0 :     return NS_ERROR_NOT_AVAILABLE;
     186             : 
     187             :   nsresult rv;
     188             :   bool test;
     189           0 :   rv = this->NeedsLogin(&test);
     190           0 :   if (NS_FAILED(rv)) return rv;
     191           0 :   if (test && force) {
     192           0 :     rv = this->LogoutSimple();
     193           0 :     if (NS_FAILED(rv)) return rv;
     194             :   }
     195           0 :   rv = setPassword(mSlot.get(), mUIContext, locker);
     196           0 :   if (NS_FAILED(rv)) return rv;
     197             : 
     198           0 :   return MapSECStatus(PK11_Authenticate(mSlot.get(), true, mUIContext));
     199             : }
     200             : 
     201             : NS_IMETHODIMP
     202           0 : nsPK11Token::LogoutSimple()
     203             : {
     204           0 :   nsNSSShutDownPreventionLock locker;
     205           0 :   if (isAlreadyShutDown())
     206           0 :     return NS_ERROR_NOT_AVAILABLE;
     207             : 
     208             :   // PK11_Logout() can fail if the user wasn't logged in beforehand. We want
     209             :   // this method to succeed even in this case, so we ignore the return value.
     210           0 :   Unused << PK11_Logout(mSlot.get());
     211           0 :   return NS_OK;
     212             : }
     213             : 
     214             : NS_IMETHODIMP
     215           0 : nsPK11Token::LogoutAndDropAuthenticatedResources()
     216             : {
     217             :   static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
     218             : 
     219           0 :   nsresult rv = LogoutSimple();
     220             : 
     221           0 :   if (NS_FAILED(rv))
     222           0 :     return rv;
     223             : 
     224           0 :   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
     225           0 :   if (NS_FAILED(rv))
     226           0 :     return rv;
     227             : 
     228           0 :   return nssComponent->LogoutAuthenticatedPK11();
     229             : }
     230             : 
     231             : NS_IMETHODIMP
     232           0 : nsPK11Token::Reset()
     233             : {
     234           0 :   nsNSSShutDownPreventionLock locker;
     235           0 :   if (isAlreadyShutDown())
     236           0 :     return NS_ERROR_NOT_AVAILABLE;
     237             : 
     238           0 :   return MapSECStatus(PK11_ResetToken(mSlot.get(), nullptr));
     239             : }
     240             : 
     241             : NS_IMETHODIMP
     242           0 : nsPK11Token::GetMinimumPasswordLength(int32_t* aMinimumPasswordLength)
     243             : {
     244           0 :   NS_ENSURE_ARG_POINTER(aMinimumPasswordLength);
     245             : 
     246           0 :   nsNSSShutDownPreventionLock locker;
     247           0 :   if (isAlreadyShutDown())
     248           0 :     return NS_ERROR_NOT_AVAILABLE;
     249             : 
     250           0 :   *aMinimumPasswordLength = PK11_GetMinimumPwdLength(mSlot.get());
     251             : 
     252           0 :   return NS_OK;
     253             : }
     254             : 
     255             : NS_IMETHODIMP
     256           1 : nsPK11Token::GetNeedsUserInit(bool* aNeedsUserInit)
     257             : {
     258           1 :   NS_ENSURE_ARG_POINTER(aNeedsUserInit);
     259             : 
     260           2 :   nsNSSShutDownPreventionLock locker;
     261           1 :   if (isAlreadyShutDown())
     262           0 :     return NS_ERROR_NOT_AVAILABLE;
     263             : 
     264           1 :   *aNeedsUserInit = PK11_NeedUserInit(mSlot.get());
     265           1 :   return NS_OK;
     266             : }
     267             : 
     268             : NS_IMETHODIMP
     269           0 : nsPK11Token::CheckPassword(const nsACString& password, bool* _retval)
     270             : {
     271           0 :   NS_ENSURE_ARG_POINTER(_retval);
     272             : 
     273           0 :   nsNSSShutDownPreventionLock locker;
     274           0 :   if (isAlreadyShutDown())
     275           0 :     return NS_ERROR_NOT_AVAILABLE;
     276             : 
     277             :   SECStatus srv =
     278           0 :     PK11_CheckUserPassword(mSlot.get(), PromiseFlatCString(password).get());
     279           0 :   if (srv != SECSuccess) {
     280           0 :     *_retval =  false;
     281           0 :     PRErrorCode error = PR_GetError();
     282           0 :     if (error != SEC_ERROR_BAD_PASSWORD) {
     283             :       /* something really bad happened - throw an exception */
     284           0 :       return mozilla::psm::GetXPCOMFromNSSError(error);
     285             :     }
     286             :   } else {
     287           0 :     *_retval =  true;
     288             :   }
     289           0 :   return NS_OK;
     290             : }
     291             : 
     292             : NS_IMETHODIMP
     293           0 : nsPK11Token::InitPassword(const nsACString& initialPassword)
     294             : {
     295           0 :   nsNSSShutDownPreventionLock locker;
     296           0 :   if (isAlreadyShutDown())
     297           0 :     return NS_ERROR_NOT_AVAILABLE;
     298             : 
     299           0 :   return MapSECStatus(
     300           0 :     PK11_InitPin(mSlot.get(), "", PromiseFlatCString(initialPassword).get()));
     301             : }
     302             : 
     303             : NS_IMETHODIMP
     304           0 : nsPK11Token::GetAskPasswordTimes(int32_t* askTimes)
     305             : {
     306           0 :   NS_ENSURE_ARG_POINTER(askTimes);
     307             : 
     308           0 :   nsNSSShutDownPreventionLock locker;
     309           0 :   if (isAlreadyShutDown())
     310           0 :     return NS_ERROR_NOT_AVAILABLE;
     311             : 
     312             :   int askTimeout;
     313           0 :   PK11_GetSlotPWValues(mSlot.get(), askTimes, &askTimeout);
     314           0 :   return NS_OK;
     315             : }
     316             : 
     317             : NS_IMETHODIMP
     318           0 : nsPK11Token::GetAskPasswordTimeout(int32_t* askTimeout)
     319             : {
     320           0 :   NS_ENSURE_ARG_POINTER(askTimeout);
     321             : 
     322           0 :   nsNSSShutDownPreventionLock locker;
     323           0 :   if (isAlreadyShutDown())
     324           0 :     return NS_ERROR_NOT_AVAILABLE;
     325             : 
     326             :   int askTimes;
     327           0 :   PK11_GetSlotPWValues(mSlot.get(), &askTimes, askTimeout);
     328           0 :   return NS_OK;
     329             : }
     330             : 
     331             : NS_IMETHODIMP
     332           0 : nsPK11Token::SetAskPasswordDefaults(const int32_t askTimes,
     333             :                                     const int32_t askTimeout)
     334             : {
     335           0 :   nsNSSShutDownPreventionLock locker;
     336           0 :   if (isAlreadyShutDown())
     337           0 :     return NS_ERROR_NOT_AVAILABLE;
     338             : 
     339           0 :   PK11_SetSlotPWValues(mSlot.get(), askTimes, askTimeout);
     340           0 :   return NS_OK;
     341             : }
     342             : 
     343             : NS_IMETHODIMP
     344           0 : nsPK11Token::ChangePassword(const nsACString& oldPassword,
     345             :                             const nsACString& newPassword)
     346             : {
     347           0 :   nsNSSShutDownPreventionLock locker;
     348           0 :   if (isAlreadyShutDown())
     349           0 :     return NS_ERROR_NOT_AVAILABLE;
     350             : 
     351             :   // PK11_ChangePW() has different semantics for the empty string and for
     352             :   // nullptr. In order to support this difference, we need to check IsVoid() to
     353             :   // find out if our caller supplied null/undefined args or just empty strings.
     354             :   // See Bug 447589.
     355           0 :   return MapSECStatus(PK11_ChangePW(
     356             :     mSlot.get(),
     357           0 :     oldPassword.IsVoid() ? nullptr : PromiseFlatCString(oldPassword).get(),
     358           0 :     newPassword.IsVoid() ? nullptr : PromiseFlatCString(newPassword).get()));
     359             : }
     360             : 
     361             : NS_IMETHODIMP
     362           0 : nsPK11Token::GetHasPassword(bool* hasPassword)
     363             : {
     364           0 :   NS_ENSURE_ARG_POINTER(hasPassword);
     365             : 
     366           0 :   nsNSSShutDownPreventionLock locker;
     367           0 :   if (isAlreadyShutDown()) {
     368           0 :     return NS_ERROR_NOT_AVAILABLE;
     369             :   }
     370             : 
     371             :   // PK11_NeedLogin returns true if the token is currently configured to require
     372             :   // the user to log in (whether or not the user is actually logged in makes no
     373             :   // difference).
     374           0 :   *hasPassword = PK11_NeedLogin(mSlot.get()) && !PK11_NeedUserInit(mSlot.get());
     375           0 :   return NS_OK;
     376             : }
     377             : 
     378             : NS_IMETHODIMP
     379           0 : nsPK11Token::IsHardwareToken(bool* _retval)
     380             : {
     381           0 :   NS_ENSURE_ARG_POINTER(_retval);
     382             : 
     383           0 :   nsNSSShutDownPreventionLock locker;
     384           0 :   if (isAlreadyShutDown())
     385           0 :     return NS_ERROR_NOT_AVAILABLE;
     386             : 
     387           0 :   *_retval = PK11_IsHW(mSlot.get());
     388             : 
     389           0 :   return NS_OK;
     390             : }
     391             : 
     392             : NS_IMETHODIMP
     393           0 : nsPK11Token::NeedsLogin(bool* _retval)
     394             : {
     395           0 :   NS_ENSURE_ARG_POINTER(_retval);
     396             : 
     397           0 :   nsNSSShutDownPreventionLock locker;
     398           0 :   if (isAlreadyShutDown())
     399           0 :     return NS_ERROR_NOT_AVAILABLE;
     400             : 
     401           0 :   *_retval = PK11_NeedLogin(mSlot.get());
     402             : 
     403           0 :   return NS_OK;
     404             : }
     405             : 
     406             : /*=========================================================*/
     407             : 
     408          18 : NS_IMPL_ISUPPORTS(nsPK11TokenDB, nsIPK11TokenDB)
     409             : 
     410           1 : nsPK11TokenDB::nsPK11TokenDB()
     411             : {
     412           1 : }
     413             : 
     414           0 : nsPK11TokenDB::~nsPK11TokenDB()
     415             : {
     416           0 :   nsNSSShutDownPreventionLock locker;
     417           0 :   if (isAlreadyShutDown()) {
     418           0 :     return;
     419             :   }
     420             : 
     421           0 :   shutdown(ShutdownCalledFrom::Object);
     422           0 : }
     423             : 
     424             : NS_IMETHODIMP
     425           1 : nsPK11TokenDB::GetInternalKeyToken(nsIPK11Token** _retval)
     426             : {
     427           1 :   NS_ENSURE_ARG_POINTER(_retval);
     428             : 
     429           2 :   nsNSSShutDownPreventionLock locker;
     430           1 :   if (isAlreadyShutDown()) {
     431           0 :     return NS_ERROR_NOT_AVAILABLE;
     432             :   }
     433             : 
     434           2 :   UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
     435           1 :   if (!slot) {
     436           0 :     return NS_ERROR_FAILURE;
     437             :   }
     438             : 
     439           3 :   nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot.get());
     440           1 :   token.forget(_retval);
     441             : 
     442           1 :   return NS_OK;
     443             : }
     444             : 
     445             : NS_IMETHODIMP
     446           0 : nsPK11TokenDB::FindTokenByName(const nsACString& tokenName,
     447             :                        /*out*/ nsIPK11Token** _retval)
     448             : {
     449           0 :   NS_ENSURE_ARG_POINTER(_retval);
     450             : 
     451           0 :   nsNSSShutDownPreventionLock locker;
     452           0 :   if (isAlreadyShutDown()) {
     453           0 :     return NS_ERROR_NOT_AVAILABLE;
     454             :   }
     455             : 
     456           0 :   if (tokenName.IsEmpty()) {
     457           0 :     return NS_ERROR_ILLEGAL_VALUE;
     458             :   }
     459             : 
     460             :   UniquePK11SlotInfo slot(
     461           0 :     PK11_FindSlotByName(PromiseFlatCString(tokenName).get()));
     462           0 :   if (!slot) {
     463           0 :     return NS_ERROR_FAILURE;
     464             :   }
     465             : 
     466           0 :   nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot.get());
     467           0 :   token.forget(_retval);
     468             : 
     469           0 :   return NS_OK;
     470             : }
     471             : 
     472             : NS_IMETHODIMP
     473           0 : nsPK11TokenDB::ListTokens(nsISimpleEnumerator** _retval)
     474             : {
     475           0 :   NS_ENSURE_ARG_POINTER(_retval);
     476             : 
     477           0 :   nsNSSShutDownPreventionLock locker;
     478           0 :   if (isAlreadyShutDown()) {
     479           0 :     return NS_ERROR_NOT_AVAILABLE;
     480             :   }
     481             : 
     482           0 :   nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
     483           0 :   if (!array) {
     484           0 :     return NS_ERROR_FAILURE;
     485             :   }
     486             : 
     487           0 :   *_retval = nullptr;
     488             : 
     489             :   UniquePK11SlotList list(
     490           0 :     PK11_GetAllTokens(CKM_INVALID_MECHANISM, false, false, 0));
     491           0 :   if (!list) {
     492           0 :     return NS_ERROR_FAILURE;
     493             :   }
     494             : 
     495           0 :   for (PK11SlotListElement* le = PK11_GetFirstSafe(list.get()); le;
     496           0 :        le = PK11_GetNextSafe(list.get(), le, false)) {
     497           0 :     nsCOMPtr<nsIPK11Token> token = new nsPK11Token(le->slot);
     498           0 :     nsresult rv = array->AppendElement(token, false);
     499           0 :     if (NS_FAILED(rv)) {
     500           0 :       return rv;
     501             :     }
     502             :   }
     503             : 
     504           0 :   return array->Enumerate(_retval);
     505             : }

Generated by: LCOV version 1.13