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 +