security/manager/ssl/src/nsPK11TokenDB.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/manager/ssl/src/nsPK11TokenDB.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,510 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + *
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +#include "nsISupports.h"
    1.10 +#include "nsISupportsArray.h"
    1.11 +#include "nsIPK11TokenDB.h"
    1.12 +#include "prerror.h"
    1.13 +#include "secerr.h"
    1.14 +#include "nsReadableUtils.h"
    1.15 +#include "nsNSSComponent.h"
    1.16 +#include "nsServiceManagerUtils.h"
    1.17 +
    1.18 +#include "nsPK11TokenDB.h"
    1.19 +
    1.20 +#ifdef PR_LOGGING
    1.21 +extern PRLogModuleInfo* gPIPNSSLog;
    1.22 +#endif
    1.23 +
    1.24 +NS_IMPL_ISUPPORTS(nsPK11Token, nsIPK11Token)
    1.25 +
    1.26 +nsPK11Token::nsPK11Token(PK11SlotInfo *slot)
    1.27 +{
    1.28 +  nsNSSShutDownPreventionLock locker;
    1.29 +  if (isAlreadyShutDown())
    1.30 +    return;
    1.31 +
    1.32 +  PK11_ReferenceSlot(slot);
    1.33 +  mSlot = slot;
    1.34 +  mSeries = PK11_GetSlotSeries(slot);
    1.35 +
    1.36 +  refreshTokenInfo();
    1.37 +  mUIContext = new PipUIContext();
    1.38 +}
    1.39 +
    1.40 +void  
    1.41 +nsPK11Token::refreshTokenInfo()
    1.42 +{
    1.43 +  mTokenName = NS_ConvertUTF8toUTF16(PK11_GetTokenName(mSlot));
    1.44 +
    1.45 +  SECStatus srv;
    1.46 +
    1.47 +  CK_TOKEN_INFO tok_info;
    1.48 +  srv = PK11_GetTokenInfo(mSlot, &tok_info);
    1.49 +  if (srv == SECSuccess) {
    1.50 +    // Set the Label field
    1.51 +
    1.52 +    const char *ccLabel = (const char*)tok_info.label;
    1.53 +    const nsACString &cLabel = Substring(
    1.54 +      ccLabel, 
    1.55 +      ccLabel+PL_strnlen(ccLabel, sizeof(tok_info.label)));
    1.56 +    mTokenLabel = NS_ConvertUTF8toUTF16(cLabel);
    1.57 +    mTokenLabel.Trim(" ", false, true);
    1.58 +
    1.59 +    // Set the Manufacturer field
    1.60 +    const char *ccManID = (const char*)tok_info.manufacturerID;
    1.61 +    const nsACString &cManID = Substring(
    1.62 +      ccManID, 
    1.63 +      ccManID+PL_strnlen(ccManID, sizeof(tok_info.manufacturerID)));
    1.64 +    mTokenManID = NS_ConvertUTF8toUTF16(cManID);
    1.65 +    mTokenManID.Trim(" ", false, true);
    1.66 +
    1.67 +    // Set the Hardware Version field
    1.68 +    mTokenHWVersion.AppendInt(tok_info.hardwareVersion.major);
    1.69 +    mTokenHWVersion.AppendLiteral(".");
    1.70 +    mTokenHWVersion.AppendInt(tok_info.hardwareVersion.minor);
    1.71 +    // Set the Firmware Version field
    1.72 +    mTokenFWVersion.AppendInt(tok_info.firmwareVersion.major);
    1.73 +    mTokenFWVersion.AppendLiteral(".");
    1.74 +    mTokenFWVersion.AppendInt(tok_info.firmwareVersion.minor);
    1.75 +    // Set the Serial Number field
    1.76 +    const char *ccSerial = (const char*)tok_info.serialNumber;
    1.77 +    const nsACString &cSerial = Substring(
    1.78 +      ccSerial, 
    1.79 +      ccSerial+PL_strnlen(ccSerial, sizeof(tok_info.serialNumber)));
    1.80 +    mTokenSerialNum = NS_ConvertUTF8toUTF16(cSerial);
    1.81 +    mTokenSerialNum.Trim(" ", false, true);
    1.82 +  }
    1.83 +
    1.84 +}
    1.85 +
    1.86 +nsPK11Token::~nsPK11Token()
    1.87 +{
    1.88 +  nsNSSShutDownPreventionLock locker;
    1.89 +  if (isAlreadyShutDown()) {
    1.90 +    return;
    1.91 +  }
    1.92 +  destructorSafeDestroyNSSReference();
    1.93 +  shutdown(calledFromObject);
    1.94 +}
    1.95 +
    1.96 +void nsPK11Token::virtualDestroyNSSReference()
    1.97 +{
    1.98 +  destructorSafeDestroyNSSReference();
    1.99 +}
   1.100 +
   1.101 +void nsPK11Token::destructorSafeDestroyNSSReference()
   1.102 +{
   1.103 +  if (mSlot) {
   1.104 +    PK11_FreeSlot(mSlot);
   1.105 +    mSlot = nullptr;
   1.106 +  }
   1.107 +}
   1.108 +
   1.109 +/* readonly attribute wstring tokenName; */
   1.110 +NS_IMETHODIMP nsPK11Token::GetTokenName(char16_t * *aTokenName)
   1.111 +{
   1.112 +  // handle removals/insertions
   1.113 +  if (mSeries != PK11_GetSlotSeries(mSlot)) {
   1.114 +    refreshTokenInfo();
   1.115 +  }
   1.116 +  *aTokenName = ToNewUnicode(mTokenName);
   1.117 +  if (!*aTokenName) return NS_ERROR_OUT_OF_MEMORY;
   1.118 +
   1.119 +  return NS_OK;
   1.120 +}
   1.121 +
   1.122 +/* readonly attribute wstring tokenDesc; */
   1.123 +NS_IMETHODIMP nsPK11Token::GetTokenLabel(char16_t **aTokLabel)
   1.124 +{
   1.125 +  // handle removals/insertions
   1.126 +  if (mSeries != PK11_GetSlotSeries(mSlot)) {
   1.127 +    refreshTokenInfo();
   1.128 +  }
   1.129 +  *aTokLabel = ToNewUnicode(mTokenLabel);
   1.130 +  if (!*aTokLabel) return NS_ERROR_OUT_OF_MEMORY;
   1.131 +  return NS_OK;
   1.132 +}
   1.133 +
   1.134 +/* readonly attribute wstring tokenManID; */
   1.135 +NS_IMETHODIMP nsPK11Token::GetTokenManID(char16_t **aTokManID)
   1.136 +{
   1.137 +  // handle removals/insertions
   1.138 +  if (mSeries != PK11_GetSlotSeries(mSlot)) {
   1.139 +    refreshTokenInfo();
   1.140 +  }
   1.141 +  *aTokManID = ToNewUnicode(mTokenManID);
   1.142 +  if (!*aTokManID) return NS_ERROR_OUT_OF_MEMORY;
   1.143 +  return NS_OK;
   1.144 +}
   1.145 +
   1.146 +/* readonly attribute wstring tokenHWVersion; */
   1.147 +NS_IMETHODIMP nsPK11Token::GetTokenHWVersion(char16_t **aTokHWVersion)
   1.148 +{
   1.149 +  // handle removals/insertions
   1.150 +  if (mSeries != PK11_GetSlotSeries(mSlot)) {
   1.151 +    refreshTokenInfo();
   1.152 +  }
   1.153 +  *aTokHWVersion = ToNewUnicode(mTokenHWVersion);
   1.154 +  if (!*aTokHWVersion) return NS_ERROR_OUT_OF_MEMORY;
   1.155 +  return NS_OK;
   1.156 +}
   1.157 +
   1.158 +/* readonly attribute wstring tokenFWVersion; */
   1.159 +NS_IMETHODIMP nsPK11Token::GetTokenFWVersion(char16_t **aTokFWVersion)
   1.160 +{
   1.161 +  // handle removals/insertions
   1.162 +  if (mSeries != PK11_GetSlotSeries(mSlot)) {
   1.163 +    refreshTokenInfo();
   1.164 +  }
   1.165 +  *aTokFWVersion = ToNewUnicode(mTokenFWVersion);
   1.166 +  if (!*aTokFWVersion) return NS_ERROR_OUT_OF_MEMORY;
   1.167 +  return NS_OK;
   1.168 +}
   1.169 +
   1.170 +/* readonly attribute wstring tokenSerialNumber; */
   1.171 +NS_IMETHODIMP nsPK11Token::GetTokenSerialNumber(char16_t **aTokSerialNum)
   1.172 +{
   1.173 +  // handle removals/insertions
   1.174 +  if (mSeries != PK11_GetSlotSeries(mSlot)) {
   1.175 +    refreshTokenInfo();
   1.176 +  }
   1.177 +  *aTokSerialNum = ToNewUnicode(mTokenSerialNum);
   1.178 +  if (!*aTokSerialNum) return NS_ERROR_OUT_OF_MEMORY;
   1.179 +  return NS_OK;
   1.180 +}
   1.181 +
   1.182 +/* boolean isLoggedIn (); */
   1.183 +NS_IMETHODIMP nsPK11Token::IsLoggedIn(bool *_retval)
   1.184 +{
   1.185 +  nsNSSShutDownPreventionLock locker;
   1.186 +  if (isAlreadyShutDown())
   1.187 +    return NS_ERROR_NOT_AVAILABLE;
   1.188 +
   1.189 +  nsresult rv = NS_OK;
   1.190 +
   1.191 +  *_retval = PK11_IsLoggedIn(mSlot, 0);
   1.192 +
   1.193 +  return rv;
   1.194 +}
   1.195 +
   1.196 +/* void logout (in boolean force); */
   1.197 +NS_IMETHODIMP 
   1.198 +nsPK11Token::Login(bool force)
   1.199 +{
   1.200 +  nsNSSShutDownPreventionLock locker;
   1.201 +  if (isAlreadyShutDown())
   1.202 +    return NS_ERROR_NOT_AVAILABLE;
   1.203 +
   1.204 +  nsresult rv;
   1.205 +  SECStatus srv;
   1.206 +  bool test;
   1.207 +  rv = this->NeedsLogin(&test);
   1.208 +  if (NS_FAILED(rv)) return rv;
   1.209 +  if (test && force) {
   1.210 +    rv = this->LogoutSimple();
   1.211 +    if (NS_FAILED(rv)) return rv;
   1.212 +  }
   1.213 +  rv = setPassword(mSlot, mUIContext);
   1.214 +  if (NS_FAILED(rv)) return rv;
   1.215 +  srv = PK11_Authenticate(mSlot, true, mUIContext);
   1.216 +  return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
   1.217 +}
   1.218 +
   1.219 +NS_IMETHODIMP nsPK11Token::LogoutSimple()
   1.220 +{
   1.221 +  nsNSSShutDownPreventionLock locker;
   1.222 +  if (isAlreadyShutDown())
   1.223 +    return NS_ERROR_NOT_AVAILABLE;
   1.224 +
   1.225 +  // PK11_MapError sets CKR_USER_NOT_LOGGED_IN to SEC_ERROR_LIBRARY_FAILURE,
   1.226 +  // so not going to learn anything here by a failure.  Treat it like void.
   1.227 +  PK11_Logout(mSlot);
   1.228 +  return NS_OK;
   1.229 +}
   1.230 +
   1.231 +NS_IMETHODIMP nsPK11Token::LogoutAndDropAuthenticatedResources()
   1.232 +{
   1.233 +  static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
   1.234 +
   1.235 +  nsresult rv = LogoutSimple();
   1.236 +
   1.237 +  if (NS_FAILED(rv))
   1.238 +    return rv;
   1.239 +
   1.240 +  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
   1.241 +  if (NS_FAILED(rv))
   1.242 +    return rv;
   1.243 +
   1.244 +  return nssComponent->LogoutAuthenticatedPK11();
   1.245 +}
   1.246 +
   1.247 +/* void reset (); */
   1.248 +NS_IMETHODIMP nsPK11Token::Reset()
   1.249 +{
   1.250 +  nsNSSShutDownPreventionLock locker;
   1.251 +  if (isAlreadyShutDown())
   1.252 +    return NS_ERROR_NOT_AVAILABLE;
   1.253 +
   1.254 +  PK11_ResetToken(mSlot, 0);
   1.255 +  return NS_OK;
   1.256 +}
   1.257 +
   1.258 +/* readonly attribute long minimumPasswordLength; */
   1.259 +NS_IMETHODIMP nsPK11Token::GetMinimumPasswordLength(int32_t *aMinimumPasswordLength)
   1.260 +{
   1.261 +  nsNSSShutDownPreventionLock locker;
   1.262 +  if (isAlreadyShutDown())
   1.263 +    return NS_ERROR_NOT_AVAILABLE;
   1.264 +
   1.265 +  *aMinimumPasswordLength = PK11_GetMinimumPwdLength(mSlot);
   1.266 +
   1.267 +  return NS_OK;
   1.268 +}
   1.269 +
   1.270 +/* readonly attribute boolean needsUserInit; */
   1.271 +NS_IMETHODIMP nsPK11Token::GetNeedsUserInit(bool *aNeedsUserInit)
   1.272 +{
   1.273 +  nsNSSShutDownPreventionLock locker;
   1.274 +  if (isAlreadyShutDown())
   1.275 +    return NS_ERROR_NOT_AVAILABLE;
   1.276 +
   1.277 +  *aNeedsUserInit = PK11_NeedUserInit(mSlot);
   1.278 +  return NS_OK;
   1.279 +}
   1.280 +
   1.281 +/* boolean checkPassword (in wstring password); */
   1.282 +NS_IMETHODIMP nsPK11Token::CheckPassword(const char16_t *password, bool *_retval)
   1.283 +{
   1.284 +  nsNSSShutDownPreventionLock locker;
   1.285 +  if (isAlreadyShutDown())
   1.286 +    return NS_ERROR_NOT_AVAILABLE;
   1.287 +
   1.288 +  SECStatus srv;
   1.289 +  int32_t prerr;
   1.290 +  NS_ConvertUTF16toUTF8 aUtf8Password(password);
   1.291 +  srv = PK11_CheckUserPassword(mSlot, 
   1.292 +                  const_cast<char *>(aUtf8Password.get()));
   1.293 +  if (srv != SECSuccess) {
   1.294 +    *_retval =  false;
   1.295 +    prerr = PR_GetError();
   1.296 +    if (prerr != SEC_ERROR_BAD_PASSWORD) {
   1.297 +      /* something really bad happened - throw an exception */
   1.298 +      return NS_ERROR_FAILURE;
   1.299 +    }
   1.300 +  } else {
   1.301 +    *_retval =  true;
   1.302 +  }
   1.303 +  return NS_OK;
   1.304 +}
   1.305 +
   1.306 +/* void initPassword (in wstring initialPassword); */
   1.307 +NS_IMETHODIMP nsPK11Token::InitPassword(const char16_t *initialPassword)
   1.308 +{
   1.309 +  nsNSSShutDownPreventionLock locker;
   1.310 +  if (isAlreadyShutDown())
   1.311 +    return NS_ERROR_NOT_AVAILABLE;
   1.312 +
   1.313 +    nsresult rv = NS_OK;
   1.314 +    SECStatus status;
   1.315 +
   1.316 +    NS_ConvertUTF16toUTF8 aUtf8InitialPassword(initialPassword);
   1.317 +    status = PK11_InitPin(mSlot, "", const_cast<char*>(aUtf8InitialPassword.get()));
   1.318 +    if (status == SECFailure) { rv = NS_ERROR_FAILURE; goto done; }
   1.319 +
   1.320 +done:
   1.321 +    return rv;
   1.322 +}
   1.323 +
   1.324 +/* long getAskPasswordTimes(); */
   1.325 +NS_IMETHODIMP 
   1.326 +nsPK11Token::GetAskPasswordTimes(int32_t *rvAskTimes)
   1.327 +{
   1.328 +  nsNSSShutDownPreventionLock locker;
   1.329 +  if (isAlreadyShutDown())
   1.330 +    return NS_ERROR_NOT_AVAILABLE;
   1.331 +
   1.332 +    int askTimes, askTimeout;
   1.333 +    PK11_GetSlotPWValues(mSlot, &askTimes, &askTimeout);
   1.334 +    *rvAskTimes = askTimes;
   1.335 +    return NS_OK;
   1.336 +}
   1.337 +
   1.338 +/* long getAskPasswordTimeout(); */
   1.339 +NS_IMETHODIMP 
   1.340 +nsPK11Token::GetAskPasswordTimeout(int32_t *rvAskTimeout)
   1.341 +{
   1.342 +  nsNSSShutDownPreventionLock locker;
   1.343 +  if (isAlreadyShutDown())
   1.344 +    return NS_ERROR_NOT_AVAILABLE;
   1.345 +
   1.346 +    int askTimes, askTimeout;
   1.347 +    PK11_GetSlotPWValues(mSlot, &askTimes, &askTimeout);
   1.348 +    *rvAskTimeout = askTimeout;
   1.349 +    return NS_OK;
   1.350 +}
   1.351 +
   1.352 +/* void setAskPasswordDefaults(in unsigned long askTimes,
   1.353 + *                             in unsigned long timeout);
   1.354 + */
   1.355 +NS_IMETHODIMP 
   1.356 +nsPK11Token::SetAskPasswordDefaults(const int32_t askTimes,
   1.357 +                                    const int32_t askTimeout)
   1.358 +{
   1.359 +  nsNSSShutDownPreventionLock locker;
   1.360 +  if (isAlreadyShutDown())
   1.361 +    return NS_ERROR_NOT_AVAILABLE;
   1.362 +
   1.363 +    PK11_SetSlotPWValues(mSlot, askTimes, askTimeout);
   1.364 +    return NS_OK;
   1.365 +}
   1.366 +
   1.367 +/* void changePassword (in wstring oldPassword, in wstring newPassword); */
   1.368 +NS_IMETHODIMP nsPK11Token::ChangePassword(const char16_t *oldPassword, const char16_t *newPassword)
   1.369 +{
   1.370 +  nsNSSShutDownPreventionLock locker;
   1.371 +  if (isAlreadyShutDown())
   1.372 +    return NS_ERROR_NOT_AVAILABLE;
   1.373 +
   1.374 +  SECStatus rv;
   1.375 +  NS_ConvertUTF16toUTF8 aUtf8OldPassword(oldPassword);
   1.376 +  NS_ConvertUTF16toUTF8 aUtf8NewPassword(newPassword);
   1.377 +
   1.378 +  rv = PK11_ChangePW(mSlot, 
   1.379 +         (oldPassword ? const_cast<char *>(aUtf8OldPassword.get()) : nullptr),
   1.380 +         (newPassword ? const_cast<char *>(aUtf8NewPassword.get()) : nullptr));
   1.381 +  return (rv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
   1.382 +}
   1.383 +
   1.384 +/* boolean isHardwareToken (); */
   1.385 +NS_IMETHODIMP nsPK11Token::IsHardwareToken(bool *_retval)
   1.386 +{
   1.387 +  nsNSSShutDownPreventionLock locker;
   1.388 +  if (isAlreadyShutDown())
   1.389 +    return NS_ERROR_NOT_AVAILABLE;
   1.390 +
   1.391 +  nsresult rv = NS_OK;
   1.392 +
   1.393 +  *_retval = PK11_IsHW(mSlot);
   1.394 +
   1.395 +  return rv;
   1.396 +}
   1.397 +
   1.398 +/* boolean needsLogin (); */
   1.399 +NS_IMETHODIMP nsPK11Token::NeedsLogin(bool *_retval)
   1.400 +{
   1.401 +  nsNSSShutDownPreventionLock locker;
   1.402 +  if (isAlreadyShutDown())
   1.403 +    return NS_ERROR_NOT_AVAILABLE;
   1.404 +
   1.405 +  nsresult rv = NS_OK;
   1.406 +
   1.407 +  *_retval = PK11_NeedLogin(mSlot);
   1.408 +
   1.409 +  return rv;
   1.410 +}
   1.411 +
   1.412 +/* boolean isFriendly (); */
   1.413 +NS_IMETHODIMP nsPK11Token::IsFriendly(bool *_retval)
   1.414 +{
   1.415 +  nsNSSShutDownPreventionLock locker;
   1.416 +  if (isAlreadyShutDown())
   1.417 +    return NS_ERROR_NOT_AVAILABLE;
   1.418 +
   1.419 +  nsresult rv = NS_OK;
   1.420 +
   1.421 +  *_retval = PK11_IsFriendly(mSlot);
   1.422 +
   1.423 +  return rv;
   1.424 +}
   1.425 +
   1.426 +/*=========================================================*/
   1.427 +
   1.428 +NS_IMPL_ISUPPORTS(nsPK11TokenDB, nsIPK11TokenDB)
   1.429 +
   1.430 +nsPK11TokenDB::nsPK11TokenDB()
   1.431 +{
   1.432 +  /* member initializers and constructor code */
   1.433 +}
   1.434 +
   1.435 +nsPK11TokenDB::~nsPK11TokenDB()
   1.436 +{
   1.437 +  /* destructor code */
   1.438 +}
   1.439 +
   1.440 +/* nsIPK11Token getInternalKeyToken (); */
   1.441 +NS_IMETHODIMP nsPK11TokenDB::GetInternalKeyToken(nsIPK11Token **_retval)
   1.442 +{
   1.443 +  nsNSSShutDownPreventionLock locker;
   1.444 +  nsresult rv = NS_OK;
   1.445 +  PK11SlotInfo *slot = 0;
   1.446 +  nsCOMPtr<nsIPK11Token> token;
   1.447 +
   1.448 +  slot = PK11_GetInternalKeySlot();
   1.449 +  if (!slot) { rv = NS_ERROR_FAILURE; goto done; }
   1.450 +
   1.451 +  token = new nsPK11Token(slot);
   1.452 +  *_retval = token;
   1.453 +  NS_ADDREF(*_retval);
   1.454 +
   1.455 +done:
   1.456 +  if (slot) PK11_FreeSlot(slot);
   1.457 +  return rv;
   1.458 +}
   1.459 +
   1.460 +/* nsIPK11Token findTokenByName (in wchar tokenName); */
   1.461 +NS_IMETHODIMP nsPK11TokenDB::
   1.462 +FindTokenByName(const char16_t* tokenName, nsIPK11Token **_retval)
   1.463 +{
   1.464 +  nsNSSShutDownPreventionLock locker;
   1.465 +  nsresult rv = NS_OK;
   1.466 +  PK11SlotInfo *slot = 0;
   1.467 +  NS_ConvertUTF16toUTF8 aUtf8TokenName(tokenName);
   1.468 +  slot = PK11_FindSlotByName(const_cast<char*>(aUtf8TokenName.get()));
   1.469 +  if (!slot) { rv = NS_ERROR_FAILURE; goto done; }
   1.470 +
   1.471 +  *_retval = new nsPK11Token(slot);
   1.472 +  NS_ADDREF(*_retval);
   1.473 +
   1.474 +done:
   1.475 +  if (slot) PK11_FreeSlot(slot);
   1.476 +  return rv;
   1.477 +}
   1.478 +
   1.479 +/* nsIEnumerator listTokens (); */
   1.480 +NS_IMETHODIMP nsPK11TokenDB::ListTokens(nsIEnumerator* *_retval)
   1.481 +{
   1.482 +  nsNSSShutDownPreventionLock locker;
   1.483 +  nsCOMPtr<nsISupportsArray> array;
   1.484 +  PK11SlotList *list = 0;
   1.485 +  PK11SlotListElement *le;
   1.486 +
   1.487 +  *_retval = nullptr;
   1.488 +  nsresult rv = NS_NewISupportsArray(getter_AddRefs(array));
   1.489 +  if (NS_FAILED(rv)) { goto done; }
   1.490 +
   1.491 +  /* List all tokens, creating PK11Token objects and putting them
   1.492 +   * into the array.
   1.493 +   */
   1.494 +  list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, false, false, 0);
   1.495 +  if (!list) { rv = NS_ERROR_FAILURE; goto done; }
   1.496 +
   1.497 +  for (le = PK11_GetFirstSafe(list); le; le = PK11_GetNextSafe(list, le, false)) {
   1.498 +    nsCOMPtr<nsIPK11Token> token = new nsPK11Token(le->slot);
   1.499 +    rv = array->AppendElement(token);
   1.500 +    if (NS_FAILED(rv)) {
   1.501 +      PK11_FreeSlotListElement(list, le);
   1.502 +      rv = NS_ERROR_OUT_OF_MEMORY;
   1.503 +      goto done;
   1.504 +    }
   1.505 +  }
   1.506 +
   1.507 +  rv = array->Enumerate(_retval);
   1.508 +
   1.509 +done:
   1.510 +  if (list) PK11_FreeSlotList(list);
   1.511 +  return rv;
   1.512 +}
   1.513 +

mercurial