nsPK11TokenDB.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  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. #include <string.h>
  8. #include "ScopedNSSTypes.h"
  9. #include "mozilla/Casting.h"
  10. #include "mozilla/Unused.h"
  11. #include "nsIMutableArray.h"
  12. #include "nsISupports.h"
  13. #include "nsNSSComponent.h"
  14. #include "nsPromiseFlatString.h"
  15. #include "nsReadableUtils.h"
  16. #include "nsServiceManagerUtils.h"
  17. #include "prerror.h"
  18. #include "secerr.h"
  19. extern mozilla::LazyLogModule gPIPNSSLog;
  20. NS_IMPL_ISUPPORTS(nsPK11Token, nsIPK11Token)
  21. nsPK11Token::nsPK11Token(PK11SlotInfo* slot)
  22. : mUIContext(new PipUIContext())
  23. {
  24. MOZ_ASSERT(slot);
  25. nsNSSShutDownPreventionLock locker;
  26. if (isAlreadyShutDown())
  27. return;
  28. mSlot.reset(PK11_ReferenceSlot(slot));
  29. mSeries = PK11_GetSlotSeries(slot);
  30. Unused << refreshTokenInfo(locker);
  31. }
  32. nsresult
  33. nsPK11Token::refreshTokenInfo(const nsNSSShutDownPreventionLock& /*proofOfLock*/)
  34. {
  35. mTokenName = PK11_GetTokenName(mSlot.get());
  36. CK_TOKEN_INFO tokInfo;
  37. nsresult rv = MapSECStatus(PK11_GetTokenInfo(mSlot.get(), &tokInfo));
  38. if (NS_FAILED(rv)) {
  39. return rv;
  40. }
  41. // Set the Label field
  42. const char* ccLabel = mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(tokInfo.label);
  43. mTokenLabel.Assign(ccLabel, strnlen(ccLabel, sizeof(tokInfo.label)));
  44. mTokenLabel.Trim(" ", false, true);
  45. // Set the Manufacturer field
  46. const char* ccManID =
  47. mozilla::BitwiseCast<char*, CK_UTF8CHAR*>(tokInfo.manufacturerID);
  48. mTokenManufacturerID.Assign(
  49. ccManID,
  50. strnlen(ccManID, sizeof(tokInfo.manufacturerID)));
  51. mTokenManufacturerID.Trim(" ", false, true);
  52. // Set the Hardware Version field
  53. mTokenHWVersion.Truncate();
  54. mTokenHWVersion.AppendInt(tokInfo.hardwareVersion.major);
  55. mTokenHWVersion.Append('.');
  56. mTokenHWVersion.AppendInt(tokInfo.hardwareVersion.minor);
  57. // Set the Firmware Version field
  58. mTokenFWVersion.Truncate();
  59. mTokenFWVersion.AppendInt(tokInfo.firmwareVersion.major);
  60. mTokenFWVersion.Append('.');
  61. mTokenFWVersion.AppendInt(tokInfo.firmwareVersion.minor);
  62. // Set the Serial Number field
  63. const char* ccSerial =
  64. mozilla::BitwiseCast<char*, CK_CHAR*>(tokInfo.serialNumber);
  65. mTokenSerialNum.Assign(ccSerial,
  66. strnlen(ccSerial, sizeof(tokInfo.serialNumber)));
  67. mTokenSerialNum.Trim(" ", false, true);
  68. return NS_OK;
  69. }
  70. nsPK11Token::~nsPK11Token()
  71. {
  72. nsNSSShutDownPreventionLock locker;
  73. if (isAlreadyShutDown()) {
  74. return;
  75. }
  76. destructorSafeDestroyNSSReference();
  77. shutdown(ShutdownCalledFrom::Object);
  78. }
  79. void
  80. nsPK11Token::virtualDestroyNSSReference()
  81. {
  82. destructorSafeDestroyNSSReference();
  83. }
  84. void
  85. nsPK11Token::destructorSafeDestroyNSSReference()
  86. {
  87. mSlot = nullptr;
  88. }
  89. nsresult
  90. nsPK11Token::GetAttributeHelper(const nsACString& attribute,
  91. /*out*/ nsACString& xpcomOutParam)
  92. {
  93. nsNSSShutDownPreventionLock locker;
  94. if (isAlreadyShutDown()) {
  95. return NS_ERROR_NOT_AVAILABLE;
  96. }
  97. // Handle removals/insertions.
  98. if (PK11_GetSlotSeries(mSlot.get()) != mSeries) {
  99. nsresult rv = refreshTokenInfo(locker);
  100. if (NS_FAILED(rv)) {
  101. return rv;
  102. }
  103. }
  104. xpcomOutParam = attribute;
  105. return NS_OK;
  106. }
  107. NS_IMETHODIMP
  108. nsPK11Token::GetTokenName(/*out*/ nsACString& tokenName)
  109. {
  110. return GetAttributeHelper(mTokenName, tokenName);
  111. }
  112. NS_IMETHODIMP
  113. nsPK11Token::GetTokenLabel(/*out*/ nsACString& tokenLabel)
  114. {
  115. return GetAttributeHelper(mTokenLabel, tokenLabel);
  116. }
  117. NS_IMETHODIMP
  118. nsPK11Token::GetTokenManID(/*out*/ nsACString& tokenManufacturerID)
  119. {
  120. return GetAttributeHelper(mTokenManufacturerID, tokenManufacturerID);
  121. }
  122. NS_IMETHODIMP
  123. nsPK11Token::GetTokenHWVersion(/*out*/ nsACString& tokenHWVersion)
  124. {
  125. return GetAttributeHelper(mTokenHWVersion, tokenHWVersion);
  126. }
  127. NS_IMETHODIMP
  128. nsPK11Token::GetTokenFWVersion(/*out*/ nsACString& tokenFWVersion)
  129. {
  130. return GetAttributeHelper(mTokenFWVersion, tokenFWVersion);
  131. }
  132. NS_IMETHODIMP
  133. nsPK11Token::GetTokenSerialNumber(/*out*/ nsACString& tokenSerialNum)
  134. {
  135. return GetAttributeHelper(mTokenSerialNum, tokenSerialNum);
  136. }
  137. NS_IMETHODIMP
  138. nsPK11Token::IsLoggedIn(bool* _retval)
  139. {
  140. NS_ENSURE_ARG_POINTER(_retval);
  141. nsNSSShutDownPreventionLock locker;
  142. if (isAlreadyShutDown())
  143. return NS_ERROR_NOT_AVAILABLE;
  144. *_retval = PK11_IsLoggedIn(mSlot.get(), 0);
  145. return NS_OK;
  146. }
  147. NS_IMETHODIMP
  148. nsPK11Token::Login(bool force)
  149. {
  150. nsNSSShutDownPreventionLock locker;
  151. if (isAlreadyShutDown())
  152. return NS_ERROR_NOT_AVAILABLE;
  153. nsresult rv;
  154. bool test;
  155. rv = this->NeedsLogin(&test);
  156. if (NS_FAILED(rv)) return rv;
  157. if (test && force) {
  158. rv = this->LogoutSimple();
  159. if (NS_FAILED(rv)) return rv;
  160. }
  161. rv = setPassword(mSlot.get(), mUIContext, locker);
  162. if (NS_FAILED(rv)) return rv;
  163. return MapSECStatus(PK11_Authenticate(mSlot.get(), true, mUIContext));
  164. }
  165. NS_IMETHODIMP
  166. nsPK11Token::LogoutSimple()
  167. {
  168. nsNSSShutDownPreventionLock locker;
  169. if (isAlreadyShutDown())
  170. return NS_ERROR_NOT_AVAILABLE;
  171. // PK11_Logout() can fail if the user wasn't logged in beforehand. We want
  172. // this method to succeed even in this case, so we ignore the return value.
  173. Unused << PK11_Logout(mSlot.get());
  174. return NS_OK;
  175. }
  176. NS_IMETHODIMP
  177. nsPK11Token::LogoutAndDropAuthenticatedResources()
  178. {
  179. static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  180. nsresult rv = LogoutSimple();
  181. if (NS_FAILED(rv))
  182. return rv;
  183. nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  184. if (NS_FAILED(rv))
  185. return rv;
  186. return nssComponent->LogoutAuthenticatedPK11();
  187. }
  188. NS_IMETHODIMP
  189. nsPK11Token::Reset()
  190. {
  191. nsNSSShutDownPreventionLock locker;
  192. if (isAlreadyShutDown())
  193. return NS_ERROR_NOT_AVAILABLE;
  194. return MapSECStatus(PK11_ResetToken(mSlot.get(), nullptr));
  195. }
  196. NS_IMETHODIMP
  197. nsPK11Token::GetMinimumPasswordLength(int32_t* aMinimumPasswordLength)
  198. {
  199. NS_ENSURE_ARG_POINTER(aMinimumPasswordLength);
  200. nsNSSShutDownPreventionLock locker;
  201. if (isAlreadyShutDown())
  202. return NS_ERROR_NOT_AVAILABLE;
  203. *aMinimumPasswordLength = PK11_GetMinimumPwdLength(mSlot.get());
  204. return NS_OK;
  205. }
  206. NS_IMETHODIMP
  207. nsPK11Token::GetNeedsUserInit(bool* aNeedsUserInit)
  208. {
  209. NS_ENSURE_ARG_POINTER(aNeedsUserInit);
  210. nsNSSShutDownPreventionLock locker;
  211. if (isAlreadyShutDown())
  212. return NS_ERROR_NOT_AVAILABLE;
  213. *aNeedsUserInit = PK11_NeedUserInit(mSlot.get());
  214. return NS_OK;
  215. }
  216. NS_IMETHODIMP
  217. nsPK11Token::CheckPassword(const nsACString& password, bool* _retval)
  218. {
  219. NS_ENSURE_ARG_POINTER(_retval);
  220. nsNSSShutDownPreventionLock locker;
  221. if (isAlreadyShutDown())
  222. return NS_ERROR_NOT_AVAILABLE;
  223. SECStatus srv =
  224. PK11_CheckUserPassword(mSlot.get(), PromiseFlatCString(password).get());
  225. if (srv != SECSuccess) {
  226. *_retval = false;
  227. PRErrorCode error = PR_GetError();
  228. if (error != SEC_ERROR_BAD_PASSWORD) {
  229. /* something really bad happened - throw an exception */
  230. return mozilla::psm::GetXPCOMFromNSSError(error);
  231. }
  232. } else {
  233. *_retval = true;
  234. }
  235. return NS_OK;
  236. }
  237. NS_IMETHODIMP
  238. nsPK11Token::InitPassword(const nsACString& initialPassword)
  239. {
  240. nsNSSShutDownPreventionLock locker;
  241. if (isAlreadyShutDown())
  242. return NS_ERROR_NOT_AVAILABLE;
  243. return MapSECStatus(
  244. PK11_InitPin(mSlot.get(), "", PromiseFlatCString(initialPassword).get()));
  245. }
  246. NS_IMETHODIMP
  247. nsPK11Token::GetAskPasswordTimes(int32_t* askTimes)
  248. {
  249. NS_ENSURE_ARG_POINTER(askTimes);
  250. nsNSSShutDownPreventionLock locker;
  251. if (isAlreadyShutDown())
  252. return NS_ERROR_NOT_AVAILABLE;
  253. int askTimeout;
  254. PK11_GetSlotPWValues(mSlot.get(), askTimes, &askTimeout);
  255. return NS_OK;
  256. }
  257. NS_IMETHODIMP
  258. nsPK11Token::GetAskPasswordTimeout(int32_t* askTimeout)
  259. {
  260. NS_ENSURE_ARG_POINTER(askTimeout);
  261. nsNSSShutDownPreventionLock locker;
  262. if (isAlreadyShutDown())
  263. return NS_ERROR_NOT_AVAILABLE;
  264. int askTimes;
  265. PK11_GetSlotPWValues(mSlot.get(), &askTimes, askTimeout);
  266. return NS_OK;
  267. }
  268. NS_IMETHODIMP
  269. nsPK11Token::SetAskPasswordDefaults(const int32_t askTimes,
  270. const int32_t askTimeout)
  271. {
  272. nsNSSShutDownPreventionLock locker;
  273. if (isAlreadyShutDown())
  274. return NS_ERROR_NOT_AVAILABLE;
  275. PK11_SetSlotPWValues(mSlot.get(), askTimes, askTimeout);
  276. return NS_OK;
  277. }
  278. NS_IMETHODIMP
  279. nsPK11Token::ChangePassword(const nsACString& oldPassword,
  280. const nsACString& newPassword)
  281. {
  282. nsNSSShutDownPreventionLock locker;
  283. if (isAlreadyShutDown())
  284. return NS_ERROR_NOT_AVAILABLE;
  285. // PK11_ChangePW() has different semantics for the empty string and for
  286. // nullptr. In order to support this difference, we need to check IsVoid() to
  287. // find out if our caller supplied null/undefined args or just empty strings.
  288. // See Bug 447589.
  289. return MapSECStatus(PK11_ChangePW(
  290. mSlot.get(),
  291. oldPassword.IsVoid() ? nullptr : PromiseFlatCString(oldPassword).get(),
  292. newPassword.IsVoid() ? nullptr : PromiseFlatCString(newPassword).get()));
  293. }
  294. NS_IMETHODIMP
  295. nsPK11Token::IsHardwareToken(bool* _retval)
  296. {
  297. NS_ENSURE_ARG_POINTER(_retval);
  298. nsNSSShutDownPreventionLock locker;
  299. if (isAlreadyShutDown())
  300. return NS_ERROR_NOT_AVAILABLE;
  301. *_retval = PK11_IsHW(mSlot.get());
  302. return NS_OK;
  303. }
  304. NS_IMETHODIMP
  305. nsPK11Token::NeedsLogin(bool* _retval)
  306. {
  307. NS_ENSURE_ARG_POINTER(_retval);
  308. nsNSSShutDownPreventionLock locker;
  309. if (isAlreadyShutDown())
  310. return NS_ERROR_NOT_AVAILABLE;
  311. *_retval = PK11_NeedLogin(mSlot.get());
  312. return NS_OK;
  313. }
  314. NS_IMETHODIMP
  315. nsPK11Token::IsFriendly(bool* _retval)
  316. {
  317. NS_ENSURE_ARG_POINTER(_retval);
  318. nsNSSShutDownPreventionLock locker;
  319. if (isAlreadyShutDown())
  320. return NS_ERROR_NOT_AVAILABLE;
  321. *_retval = PK11_IsFriendly(mSlot.get());
  322. return NS_OK;
  323. }
  324. /*=========================================================*/
  325. NS_IMPL_ISUPPORTS(nsPK11TokenDB, nsIPK11TokenDB)
  326. nsPK11TokenDB::nsPK11TokenDB()
  327. {
  328. }
  329. nsPK11TokenDB::~nsPK11TokenDB()
  330. {
  331. nsNSSShutDownPreventionLock locker;
  332. if (isAlreadyShutDown()) {
  333. return;
  334. }
  335. shutdown(ShutdownCalledFrom::Object);
  336. }
  337. NS_IMETHODIMP
  338. nsPK11TokenDB::GetInternalKeyToken(nsIPK11Token** _retval)
  339. {
  340. NS_ENSURE_ARG_POINTER(_retval);
  341. nsNSSShutDownPreventionLock locker;
  342. if (isAlreadyShutDown()) {
  343. return NS_ERROR_NOT_AVAILABLE;
  344. }
  345. UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
  346. if (!slot) {
  347. return NS_ERROR_FAILURE;
  348. }
  349. nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot.get());
  350. token.forget(_retval);
  351. return NS_OK;
  352. }
  353. NS_IMETHODIMP
  354. nsPK11TokenDB::FindTokenByName(const nsACString& tokenName,
  355. /*out*/ nsIPK11Token** _retval)
  356. {
  357. NS_ENSURE_ARG_POINTER(_retval);
  358. nsNSSShutDownPreventionLock locker;
  359. if (isAlreadyShutDown()) {
  360. return NS_ERROR_NOT_AVAILABLE;
  361. }
  362. UniquePK11SlotInfo slot(
  363. PK11_FindSlotByName(PromiseFlatCString(tokenName).get()));
  364. if (!slot) {
  365. return NS_ERROR_FAILURE;
  366. }
  367. nsCOMPtr<nsIPK11Token> token = new nsPK11Token(slot.get());
  368. token.forget(_retval);
  369. return NS_OK;
  370. }
  371. NS_IMETHODIMP
  372. nsPK11TokenDB::ListTokens(nsISimpleEnumerator** _retval)
  373. {
  374. NS_ENSURE_ARG_POINTER(_retval);
  375. nsNSSShutDownPreventionLock locker;
  376. if (isAlreadyShutDown()) {
  377. return NS_ERROR_NOT_AVAILABLE;
  378. }
  379. nsCOMPtr<nsIMutableArray> array = do_CreateInstance(NS_ARRAY_CONTRACTID);
  380. if (!array) {
  381. return NS_ERROR_FAILURE;
  382. }
  383. *_retval = nullptr;
  384. UniquePK11SlotList list(
  385. PK11_GetAllTokens(CKM_INVALID_MECHANISM, false, false, 0));
  386. if (!list) {
  387. return NS_ERROR_FAILURE;
  388. }
  389. for (PK11SlotListElement* le = PK11_GetFirstSafe(list.get()); le;
  390. le = PK11_GetNextSafe(list.get(), le, false)) {
  391. nsCOMPtr<nsIPK11Token> token = new nsPK11Token(le->slot);
  392. nsresult rv = array->AppendElement(token, false);
  393. if (NS_FAILED(rv)) {
  394. return rv;
  395. }
  396. }
  397. return array->Enumerate(_retval);
  398. }