security/manager/ssl/src/nsPK11TokenDB.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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 "nsISupports.h"
     7 #include "nsISupportsArray.h"
     8 #include "nsIPK11TokenDB.h"
     9 #include "prerror.h"
    10 #include "secerr.h"
    11 #include "nsReadableUtils.h"
    12 #include "nsNSSComponent.h"
    13 #include "nsServiceManagerUtils.h"
    15 #include "nsPK11TokenDB.h"
    17 #ifdef PR_LOGGING
    18 extern PRLogModuleInfo* gPIPNSSLog;
    19 #endif
    21 NS_IMPL_ISUPPORTS(nsPK11Token, nsIPK11Token)
    23 nsPK11Token::nsPK11Token(PK11SlotInfo *slot)
    24 {
    25   nsNSSShutDownPreventionLock locker;
    26   if (isAlreadyShutDown())
    27     return;
    29   PK11_ReferenceSlot(slot);
    30   mSlot = slot;
    31   mSeries = PK11_GetSlotSeries(slot);
    33   refreshTokenInfo();
    34   mUIContext = new PipUIContext();
    35 }
    37 void  
    38 nsPK11Token::refreshTokenInfo()
    39 {
    40   mTokenName = NS_ConvertUTF8toUTF16(PK11_GetTokenName(mSlot));
    42   SECStatus srv;
    44   CK_TOKEN_INFO tok_info;
    45   srv = PK11_GetTokenInfo(mSlot, &tok_info);
    46   if (srv == SECSuccess) {
    47     // Set the Label field
    49     const char *ccLabel = (const char*)tok_info.label;
    50     const nsACString &cLabel = Substring(
    51       ccLabel, 
    52       ccLabel+PL_strnlen(ccLabel, sizeof(tok_info.label)));
    53     mTokenLabel = NS_ConvertUTF8toUTF16(cLabel);
    54     mTokenLabel.Trim(" ", false, true);
    56     // Set the Manufacturer field
    57     const char *ccManID = (const char*)tok_info.manufacturerID;
    58     const nsACString &cManID = Substring(
    59       ccManID, 
    60       ccManID+PL_strnlen(ccManID, sizeof(tok_info.manufacturerID)));
    61     mTokenManID = NS_ConvertUTF8toUTF16(cManID);
    62     mTokenManID.Trim(" ", false, true);
    64     // Set the Hardware Version field
    65     mTokenHWVersion.AppendInt(tok_info.hardwareVersion.major);
    66     mTokenHWVersion.AppendLiteral(".");
    67     mTokenHWVersion.AppendInt(tok_info.hardwareVersion.minor);
    68     // Set the Firmware Version field
    69     mTokenFWVersion.AppendInt(tok_info.firmwareVersion.major);
    70     mTokenFWVersion.AppendLiteral(".");
    71     mTokenFWVersion.AppendInt(tok_info.firmwareVersion.minor);
    72     // Set the Serial Number field
    73     const char *ccSerial = (const char*)tok_info.serialNumber;
    74     const nsACString &cSerial = Substring(
    75       ccSerial, 
    76       ccSerial+PL_strnlen(ccSerial, sizeof(tok_info.serialNumber)));
    77     mTokenSerialNum = NS_ConvertUTF8toUTF16(cSerial);
    78     mTokenSerialNum.Trim(" ", false, true);
    79   }
    81 }
    83 nsPK11Token::~nsPK11Token()
    84 {
    85   nsNSSShutDownPreventionLock locker;
    86   if (isAlreadyShutDown()) {
    87     return;
    88   }
    89   destructorSafeDestroyNSSReference();
    90   shutdown(calledFromObject);
    91 }
    93 void nsPK11Token::virtualDestroyNSSReference()
    94 {
    95   destructorSafeDestroyNSSReference();
    96 }
    98 void nsPK11Token::destructorSafeDestroyNSSReference()
    99 {
   100   if (mSlot) {
   101     PK11_FreeSlot(mSlot);
   102     mSlot = nullptr;
   103   }
   104 }
   106 /* readonly attribute wstring tokenName; */
   107 NS_IMETHODIMP nsPK11Token::GetTokenName(char16_t * *aTokenName)
   108 {
   109   // handle removals/insertions
   110   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   111     refreshTokenInfo();
   112   }
   113   *aTokenName = ToNewUnicode(mTokenName);
   114   if (!*aTokenName) return NS_ERROR_OUT_OF_MEMORY;
   116   return NS_OK;
   117 }
   119 /* readonly attribute wstring tokenDesc; */
   120 NS_IMETHODIMP nsPK11Token::GetTokenLabel(char16_t **aTokLabel)
   121 {
   122   // handle removals/insertions
   123   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   124     refreshTokenInfo();
   125   }
   126   *aTokLabel = ToNewUnicode(mTokenLabel);
   127   if (!*aTokLabel) return NS_ERROR_OUT_OF_MEMORY;
   128   return NS_OK;
   129 }
   131 /* readonly attribute wstring tokenManID; */
   132 NS_IMETHODIMP nsPK11Token::GetTokenManID(char16_t **aTokManID)
   133 {
   134   // handle removals/insertions
   135   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   136     refreshTokenInfo();
   137   }
   138   *aTokManID = ToNewUnicode(mTokenManID);
   139   if (!*aTokManID) return NS_ERROR_OUT_OF_MEMORY;
   140   return NS_OK;
   141 }
   143 /* readonly attribute wstring tokenHWVersion; */
   144 NS_IMETHODIMP nsPK11Token::GetTokenHWVersion(char16_t **aTokHWVersion)
   145 {
   146   // handle removals/insertions
   147   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   148     refreshTokenInfo();
   149   }
   150   *aTokHWVersion = ToNewUnicode(mTokenHWVersion);
   151   if (!*aTokHWVersion) return NS_ERROR_OUT_OF_MEMORY;
   152   return NS_OK;
   153 }
   155 /* readonly attribute wstring tokenFWVersion; */
   156 NS_IMETHODIMP nsPK11Token::GetTokenFWVersion(char16_t **aTokFWVersion)
   157 {
   158   // handle removals/insertions
   159   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   160     refreshTokenInfo();
   161   }
   162   *aTokFWVersion = ToNewUnicode(mTokenFWVersion);
   163   if (!*aTokFWVersion) return NS_ERROR_OUT_OF_MEMORY;
   164   return NS_OK;
   165 }
   167 /* readonly attribute wstring tokenSerialNumber; */
   168 NS_IMETHODIMP nsPK11Token::GetTokenSerialNumber(char16_t **aTokSerialNum)
   169 {
   170   // handle removals/insertions
   171   if (mSeries != PK11_GetSlotSeries(mSlot)) {
   172     refreshTokenInfo();
   173   }
   174   *aTokSerialNum = ToNewUnicode(mTokenSerialNum);
   175   if (!*aTokSerialNum) return NS_ERROR_OUT_OF_MEMORY;
   176   return NS_OK;
   177 }
   179 /* boolean isLoggedIn (); */
   180 NS_IMETHODIMP nsPK11Token::IsLoggedIn(bool *_retval)
   181 {
   182   nsNSSShutDownPreventionLock locker;
   183   if (isAlreadyShutDown())
   184     return NS_ERROR_NOT_AVAILABLE;
   186   nsresult rv = NS_OK;
   188   *_retval = PK11_IsLoggedIn(mSlot, 0);
   190   return rv;
   191 }
   193 /* void logout (in boolean force); */
   194 NS_IMETHODIMP 
   195 nsPK11Token::Login(bool force)
   196 {
   197   nsNSSShutDownPreventionLock locker;
   198   if (isAlreadyShutDown())
   199     return NS_ERROR_NOT_AVAILABLE;
   201   nsresult rv;
   202   SECStatus srv;
   203   bool test;
   204   rv = this->NeedsLogin(&test);
   205   if (NS_FAILED(rv)) return rv;
   206   if (test && force) {
   207     rv = this->LogoutSimple();
   208     if (NS_FAILED(rv)) return rv;
   209   }
   210   rv = setPassword(mSlot, mUIContext);
   211   if (NS_FAILED(rv)) return rv;
   212   srv = PK11_Authenticate(mSlot, true, mUIContext);
   213   return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
   214 }
   216 NS_IMETHODIMP nsPK11Token::LogoutSimple()
   217 {
   218   nsNSSShutDownPreventionLock locker;
   219   if (isAlreadyShutDown())
   220     return NS_ERROR_NOT_AVAILABLE;
   222   // PK11_MapError sets CKR_USER_NOT_LOGGED_IN to SEC_ERROR_LIBRARY_FAILURE,
   223   // so not going to learn anything here by a failure.  Treat it like void.
   224   PK11_Logout(mSlot);
   225   return NS_OK;
   226 }
   228 NS_IMETHODIMP nsPK11Token::LogoutAndDropAuthenticatedResources()
   229 {
   230   static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
   232   nsresult rv = LogoutSimple();
   234   if (NS_FAILED(rv))
   235     return rv;
   237   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
   238   if (NS_FAILED(rv))
   239     return rv;
   241   return nssComponent->LogoutAuthenticatedPK11();
   242 }
   244 /* void reset (); */
   245 NS_IMETHODIMP nsPK11Token::Reset()
   246 {
   247   nsNSSShutDownPreventionLock locker;
   248   if (isAlreadyShutDown())
   249     return NS_ERROR_NOT_AVAILABLE;
   251   PK11_ResetToken(mSlot, 0);
   252   return NS_OK;
   253 }
   255 /* readonly attribute long minimumPasswordLength; */
   256 NS_IMETHODIMP nsPK11Token::GetMinimumPasswordLength(int32_t *aMinimumPasswordLength)
   257 {
   258   nsNSSShutDownPreventionLock locker;
   259   if (isAlreadyShutDown())
   260     return NS_ERROR_NOT_AVAILABLE;
   262   *aMinimumPasswordLength = PK11_GetMinimumPwdLength(mSlot);
   264   return NS_OK;
   265 }
   267 /* readonly attribute boolean needsUserInit; */
   268 NS_IMETHODIMP nsPK11Token::GetNeedsUserInit(bool *aNeedsUserInit)
   269 {
   270   nsNSSShutDownPreventionLock locker;
   271   if (isAlreadyShutDown())
   272     return NS_ERROR_NOT_AVAILABLE;
   274   *aNeedsUserInit = PK11_NeedUserInit(mSlot);
   275   return NS_OK;
   276 }
   278 /* boolean checkPassword (in wstring password); */
   279 NS_IMETHODIMP nsPK11Token::CheckPassword(const char16_t *password, bool *_retval)
   280 {
   281   nsNSSShutDownPreventionLock locker;
   282   if (isAlreadyShutDown())
   283     return NS_ERROR_NOT_AVAILABLE;
   285   SECStatus srv;
   286   int32_t prerr;
   287   NS_ConvertUTF16toUTF8 aUtf8Password(password);
   288   srv = PK11_CheckUserPassword(mSlot, 
   289                   const_cast<char *>(aUtf8Password.get()));
   290   if (srv != SECSuccess) {
   291     *_retval =  false;
   292     prerr = PR_GetError();
   293     if (prerr != SEC_ERROR_BAD_PASSWORD) {
   294       /* something really bad happened - throw an exception */
   295       return NS_ERROR_FAILURE;
   296     }
   297   } else {
   298     *_retval =  true;
   299   }
   300   return NS_OK;
   301 }
   303 /* void initPassword (in wstring initialPassword); */
   304 NS_IMETHODIMP nsPK11Token::InitPassword(const char16_t *initialPassword)
   305 {
   306   nsNSSShutDownPreventionLock locker;
   307   if (isAlreadyShutDown())
   308     return NS_ERROR_NOT_AVAILABLE;
   310     nsresult rv = NS_OK;
   311     SECStatus status;
   313     NS_ConvertUTF16toUTF8 aUtf8InitialPassword(initialPassword);
   314     status = PK11_InitPin(mSlot, "", const_cast<char*>(aUtf8InitialPassword.get()));
   315     if (status == SECFailure) { rv = NS_ERROR_FAILURE; goto done; }
   317 done:
   318     return rv;
   319 }
   321 /* long getAskPasswordTimes(); */
   322 NS_IMETHODIMP 
   323 nsPK11Token::GetAskPasswordTimes(int32_t *rvAskTimes)
   324 {
   325   nsNSSShutDownPreventionLock locker;
   326   if (isAlreadyShutDown())
   327     return NS_ERROR_NOT_AVAILABLE;
   329     int askTimes, askTimeout;
   330     PK11_GetSlotPWValues(mSlot, &askTimes, &askTimeout);
   331     *rvAskTimes = askTimes;
   332     return NS_OK;
   333 }
   335 /* long getAskPasswordTimeout(); */
   336 NS_IMETHODIMP 
   337 nsPK11Token::GetAskPasswordTimeout(int32_t *rvAskTimeout)
   338 {
   339   nsNSSShutDownPreventionLock locker;
   340   if (isAlreadyShutDown())
   341     return NS_ERROR_NOT_AVAILABLE;
   343     int askTimes, askTimeout;
   344     PK11_GetSlotPWValues(mSlot, &askTimes, &askTimeout);
   345     *rvAskTimeout = askTimeout;
   346     return NS_OK;
   347 }
   349 /* void setAskPasswordDefaults(in unsigned long askTimes,
   350  *                             in unsigned long timeout);
   351  */
   352 NS_IMETHODIMP 
   353 nsPK11Token::SetAskPasswordDefaults(const int32_t askTimes,
   354                                     const int32_t askTimeout)
   355 {
   356   nsNSSShutDownPreventionLock locker;
   357   if (isAlreadyShutDown())
   358     return NS_ERROR_NOT_AVAILABLE;
   360     PK11_SetSlotPWValues(mSlot, askTimes, askTimeout);
   361     return NS_OK;
   362 }
   364 /* void changePassword (in wstring oldPassword, in wstring newPassword); */
   365 NS_IMETHODIMP nsPK11Token::ChangePassword(const char16_t *oldPassword, const char16_t *newPassword)
   366 {
   367   nsNSSShutDownPreventionLock locker;
   368   if (isAlreadyShutDown())
   369     return NS_ERROR_NOT_AVAILABLE;
   371   SECStatus rv;
   372   NS_ConvertUTF16toUTF8 aUtf8OldPassword(oldPassword);
   373   NS_ConvertUTF16toUTF8 aUtf8NewPassword(newPassword);
   375   rv = PK11_ChangePW(mSlot, 
   376          (oldPassword ? const_cast<char *>(aUtf8OldPassword.get()) : nullptr),
   377          (newPassword ? const_cast<char *>(aUtf8NewPassword.get()) : nullptr));
   378   return (rv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
   379 }
   381 /* boolean isHardwareToken (); */
   382 NS_IMETHODIMP nsPK11Token::IsHardwareToken(bool *_retval)
   383 {
   384   nsNSSShutDownPreventionLock locker;
   385   if (isAlreadyShutDown())
   386     return NS_ERROR_NOT_AVAILABLE;
   388   nsresult rv = NS_OK;
   390   *_retval = PK11_IsHW(mSlot);
   392   return rv;
   393 }
   395 /* boolean needsLogin (); */
   396 NS_IMETHODIMP nsPK11Token::NeedsLogin(bool *_retval)
   397 {
   398   nsNSSShutDownPreventionLock locker;
   399   if (isAlreadyShutDown())
   400     return NS_ERROR_NOT_AVAILABLE;
   402   nsresult rv = NS_OK;
   404   *_retval = PK11_NeedLogin(mSlot);
   406   return rv;
   407 }
   409 /* boolean isFriendly (); */
   410 NS_IMETHODIMP nsPK11Token::IsFriendly(bool *_retval)
   411 {
   412   nsNSSShutDownPreventionLock locker;
   413   if (isAlreadyShutDown())
   414     return NS_ERROR_NOT_AVAILABLE;
   416   nsresult rv = NS_OK;
   418   *_retval = PK11_IsFriendly(mSlot);
   420   return rv;
   421 }
   423 /*=========================================================*/
   425 NS_IMPL_ISUPPORTS(nsPK11TokenDB, nsIPK11TokenDB)
   427 nsPK11TokenDB::nsPK11TokenDB()
   428 {
   429   /* member initializers and constructor code */
   430 }
   432 nsPK11TokenDB::~nsPK11TokenDB()
   433 {
   434   /* destructor code */
   435 }
   437 /* nsIPK11Token getInternalKeyToken (); */
   438 NS_IMETHODIMP nsPK11TokenDB::GetInternalKeyToken(nsIPK11Token **_retval)
   439 {
   440   nsNSSShutDownPreventionLock locker;
   441   nsresult rv = NS_OK;
   442   PK11SlotInfo *slot = 0;
   443   nsCOMPtr<nsIPK11Token> token;
   445   slot = PK11_GetInternalKeySlot();
   446   if (!slot) { rv = NS_ERROR_FAILURE; goto done; }
   448   token = new nsPK11Token(slot);
   449   *_retval = token;
   450   NS_ADDREF(*_retval);
   452 done:
   453   if (slot) PK11_FreeSlot(slot);
   454   return rv;
   455 }
   457 /* nsIPK11Token findTokenByName (in wchar tokenName); */
   458 NS_IMETHODIMP nsPK11TokenDB::
   459 FindTokenByName(const char16_t* tokenName, nsIPK11Token **_retval)
   460 {
   461   nsNSSShutDownPreventionLock locker;
   462   nsresult rv = NS_OK;
   463   PK11SlotInfo *slot = 0;
   464   NS_ConvertUTF16toUTF8 aUtf8TokenName(tokenName);
   465   slot = PK11_FindSlotByName(const_cast<char*>(aUtf8TokenName.get()));
   466   if (!slot) { rv = NS_ERROR_FAILURE; goto done; }
   468   *_retval = new nsPK11Token(slot);
   469   NS_ADDREF(*_retval);
   471 done:
   472   if (slot) PK11_FreeSlot(slot);
   473   return rv;
   474 }
   476 /* nsIEnumerator listTokens (); */
   477 NS_IMETHODIMP nsPK11TokenDB::ListTokens(nsIEnumerator* *_retval)
   478 {
   479   nsNSSShutDownPreventionLock locker;
   480   nsCOMPtr<nsISupportsArray> array;
   481   PK11SlotList *list = 0;
   482   PK11SlotListElement *le;
   484   *_retval = nullptr;
   485   nsresult rv = NS_NewISupportsArray(getter_AddRefs(array));
   486   if (NS_FAILED(rv)) { goto done; }
   488   /* List all tokens, creating PK11Token objects and putting them
   489    * into the array.
   490    */
   491   list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, false, false, 0);
   492   if (!list) { rv = NS_ERROR_FAILURE; goto done; }
   494   for (le = PK11_GetFirstSafe(list); le; le = PK11_GetNextSafe(list, le, false)) {
   495     nsCOMPtr<nsIPK11Token> token = new nsPK11Token(le->slot);
   496     rv = array->AppendElement(token);
   497     if (NS_FAILED(rv)) {
   498       PK11_FreeSlotListElement(list, le);
   499       rv = NS_ERROR_OUT_OF_MEMORY;
   500       goto done;
   501     }
   502   }
   504   rv = array->Enumerate(_retval);
   506 done:
   507   if (list) PK11_FreeSlotList(list);
   508   return rv;
   509 }

mercurial