Back to index

lightning-sunbird  0.9+nobinonly
nsPK11TokenDB.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 2001
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Terry Hayes <thayes@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 #include "nsISupports.h"
00040 #include "nsIPK11TokenDB.h"
00041 #include "prerror.h"
00042 #include "secerr.h"
00043 #include "nsReadableUtils.h"
00044 #include "nsNSSComponent.h"
00045 
00046 #include "nsPK11TokenDB.h"
00047 
00048 #ifdef PR_LOGGING
00049 extern PRLogModuleInfo* gPIPNSSLog;
00050 #endif
00051 
00052 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
00053 
00054 NS_IMPL_ISUPPORTS1(nsPK11Token, nsIPK11Token)
00055 
00056 nsPK11Token::nsPK11Token(PK11SlotInfo *slot)
00057 {
00058   nsNSSShutDownPreventionLock locker;
00059   if (isAlreadyShutDown())
00060     return;
00061 
00062   PK11_ReferenceSlot(slot);
00063   mSlot = slot;
00064   mSeries = PK11_GetSlotSeries(slot);
00065 
00066   refreshTokenInfo();
00067   mUIContext = new PipUIContext();
00068 }
00069 
00070 void  
00071 nsPK11Token::refreshTokenInfo()
00072 {
00073   mTokenName = NS_ConvertUTF8toUTF16(PK11_GetTokenName(mSlot));
00074 
00075   SECStatus srv;
00076 
00077   CK_TOKEN_INFO tok_info;
00078   srv = PK11_GetTokenInfo(mSlot, &tok_info);
00079   if (srv == SECSuccess) {
00080     // Set the Label field
00081 
00082     const char *ccLabel = (const char*)tok_info.label;
00083     const nsACString &cLabel = Substring(
00084       ccLabel, 
00085       ccLabel+PL_strnlen(ccLabel, sizeof(tok_info.label)));
00086     mTokenLabel = NS_ConvertUTF8toUCS2(cLabel);
00087     mTokenLabel.Trim(" ", PR_FALSE, PR_TRUE);
00088 
00089     // Set the Manufacturer field
00090     const char *ccManID = (const char*)tok_info.manufacturerID;
00091     const nsACString &cManID = Substring(
00092       ccManID, 
00093       ccManID+PL_strnlen(ccManID, sizeof(tok_info.manufacturerID)));
00094     mTokenManID = NS_ConvertUTF8toUCS2(cManID);
00095     mTokenManID.Trim(" ", PR_FALSE, PR_TRUE);
00096 
00097     // Set the Hardware Version field
00098     mTokenHWVersion.AppendInt(tok_info.hardwareVersion.major);
00099     mTokenHWVersion.AppendLiteral(".");
00100     mTokenHWVersion.AppendInt(tok_info.hardwareVersion.minor);
00101     // Set the Firmware Version field
00102     mTokenFWVersion.AppendInt(tok_info.firmwareVersion.major);
00103     mTokenFWVersion.AppendLiteral(".");
00104     mTokenFWVersion.AppendInt(tok_info.firmwareVersion.minor);
00105     // Set the Serial Number field
00106     const char *ccSerial = (const char*)tok_info.serialNumber;
00107     const nsACString &cSerial = Substring(
00108       ccSerial, 
00109       ccSerial+PL_strnlen(ccSerial, sizeof(tok_info.serialNumber)));
00110     mTokenSerialNum = NS_ConvertUTF8toUCS2(cSerial);
00111     mTokenSerialNum.Trim(" ", PR_FALSE, PR_TRUE);
00112   }
00113 
00114 }
00115 
00116 nsPK11Token::~nsPK11Token()
00117 {
00118   nsNSSShutDownPreventionLock locker;
00119   if (isAlreadyShutDown())
00120     return;
00121 
00122   destructorSafeDestroyNSSReference();
00123   shutdown(calledFromObject);
00124 }
00125 
00126 void nsPK11Token::virtualDestroyNSSReference()
00127 {
00128   destructorSafeDestroyNSSReference();
00129 }
00130 
00131 void nsPK11Token::destructorSafeDestroyNSSReference()
00132 {
00133   if (isAlreadyShutDown())
00134     return;
00135 
00136   if (mSlot) {
00137     PK11_FreeSlot(mSlot);
00138     mSlot = nsnull;
00139   }
00140 }
00141 
00142 /* readonly attribute wstring tokenName; */
00143 NS_IMETHODIMP nsPK11Token::GetTokenName(PRUnichar * *aTokenName)
00144 {
00145   // handle removals/insertions
00146   if (mSeries != PK11_GetSlotSeries(mSlot)) {
00147     refreshTokenInfo();
00148   }
00149   *aTokenName = ToNewUnicode(mTokenName);
00150   if (!*aTokenName) return NS_ERROR_OUT_OF_MEMORY;
00151 
00152   return NS_OK;
00153 }
00154 
00155 /* readonly attribute wstring tokenDesc; */
00156 NS_IMETHODIMP nsPK11Token::GetTokenLabel(PRUnichar **aTokLabel)
00157 {
00158   // handle removals/insertions
00159   if (mSeries != PK11_GetSlotSeries(mSlot)) {
00160     refreshTokenInfo();
00161   }
00162   *aTokLabel = ToNewUnicode(mTokenLabel);
00163   if (!*aTokLabel) return NS_ERROR_OUT_OF_MEMORY;
00164   return NS_OK;
00165 }
00166 
00167 /* readonly attribute wstring tokenManID; */
00168 NS_IMETHODIMP nsPK11Token::GetTokenManID(PRUnichar **aTokManID)
00169 {
00170   // handle removals/insertions
00171   if (mSeries != PK11_GetSlotSeries(mSlot)) {
00172     refreshTokenInfo();
00173   }
00174   *aTokManID = ToNewUnicode(mTokenManID);
00175   if (!*aTokManID) return NS_ERROR_OUT_OF_MEMORY;
00176   return NS_OK;
00177 }
00178 
00179 /* readonly attribute wstring tokenHWVersion; */
00180 NS_IMETHODIMP nsPK11Token::GetTokenHWVersion(PRUnichar **aTokHWVersion)
00181 {
00182   // handle removals/insertions
00183   if (mSeries != PK11_GetSlotSeries(mSlot)) {
00184     refreshTokenInfo();
00185   }
00186   *aTokHWVersion = ToNewUnicode(mTokenHWVersion);
00187   if (!*aTokHWVersion) return NS_ERROR_OUT_OF_MEMORY;
00188   return NS_OK;
00189 }
00190 
00191 /* readonly attribute wstring tokenFWVersion; */
00192 NS_IMETHODIMP nsPK11Token::GetTokenFWVersion(PRUnichar **aTokFWVersion)
00193 {
00194   // handle removals/insertions
00195   if (mSeries != PK11_GetSlotSeries(mSlot)) {
00196     refreshTokenInfo();
00197   }
00198   *aTokFWVersion = ToNewUnicode(mTokenFWVersion);
00199   if (!*aTokFWVersion) return NS_ERROR_OUT_OF_MEMORY;
00200   return NS_OK;
00201 }
00202 
00203 /* readonly attribute wstring tokenSerialNumber; */
00204 NS_IMETHODIMP nsPK11Token::GetTokenSerialNumber(PRUnichar **aTokSerialNum)
00205 {
00206   // handle removals/insertions
00207   if (mSeries != PK11_GetSlotSeries(mSlot)) {
00208     refreshTokenInfo();
00209   }
00210   *aTokSerialNum = ToNewUnicode(mTokenSerialNum);
00211   if (!*aTokSerialNum) return NS_ERROR_OUT_OF_MEMORY;
00212   return NS_OK;
00213 }
00214 
00215 /* boolean isLoggedIn (); */
00216 NS_IMETHODIMP nsPK11Token::IsLoggedIn(PRBool *_retval)
00217 {
00218   nsNSSShutDownPreventionLock locker;
00219   if (isAlreadyShutDown())
00220     return NS_ERROR_NOT_AVAILABLE;
00221 
00222   nsresult rv = NS_OK;
00223 
00224   *_retval = PK11_IsLoggedIn(mSlot, 0);
00225 
00226   return rv;
00227 }
00228 
00229 /* void logout (in boolean force); */
00230 NS_IMETHODIMP 
00231 nsPK11Token::Login(PRBool force)
00232 {
00233   nsNSSShutDownPreventionLock locker;
00234   if (isAlreadyShutDown())
00235     return NS_ERROR_NOT_AVAILABLE;
00236 
00237   nsresult rv;
00238   SECStatus srv;
00239   PRBool test;
00240   rv = this->NeedsLogin(&test);
00241   if (NS_FAILED(rv)) return rv;
00242   if (test && force) {
00243     rv = this->LogoutSimple();
00244     if (NS_FAILED(rv)) return rv;
00245   }
00246   rv = setPassword(mSlot, mUIContext);
00247   if (NS_FAILED(rv)) return rv;
00248   srv = PK11_Authenticate(mSlot, PR_TRUE, mUIContext);
00249   return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
00250 }
00251 
00252 NS_IMETHODIMP nsPK11Token::LogoutSimple()
00253 {
00254   nsNSSShutDownPreventionLock locker;
00255   if (isAlreadyShutDown())
00256     return NS_ERROR_NOT_AVAILABLE;
00257 
00258   // PK11_MapError sets CKR_USER_NOT_LOGGED_IN to SEC_ERROR_LIBRARY_FAILURE,
00259   // so not going to learn anything here by a failure.  Treat it like void.
00260   PK11_Logout(mSlot);
00261   return NS_OK;
00262 }
00263 
00264 NS_IMETHODIMP nsPK11Token::LogoutAndDropAuthenticatedResources()
00265 {
00266   nsresult rv = LogoutSimple();
00267 
00268   if (NS_FAILED(rv))
00269     return rv;
00270 
00271   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
00272   if (NS_FAILED(rv))
00273     return rv;
00274 
00275   return nssComponent->LogoutAuthenticatedPK11();
00276 }
00277 
00278 /* void reset (); */
00279 NS_IMETHODIMP nsPK11Token::Reset()
00280 {
00281   nsNSSShutDownPreventionLock locker;
00282   if (isAlreadyShutDown())
00283     return NS_ERROR_NOT_AVAILABLE;
00284 
00285   PK11_ResetToken(mSlot, 0);
00286   return NS_OK;
00287 }
00288 
00289 /* readonly attribute long minimumPasswordLength; */
00290 NS_IMETHODIMP nsPK11Token::GetMinimumPasswordLength(PRInt32 *aMinimumPasswordLength)
00291 {
00292   nsNSSShutDownPreventionLock locker;
00293   if (isAlreadyShutDown())
00294     return NS_ERROR_NOT_AVAILABLE;
00295 
00296   *aMinimumPasswordLength = PK11_GetMinimumPwdLength(mSlot);
00297 
00298   return NS_OK;
00299 }
00300 
00301 /* readonly attribute boolean needsUserInit; */
00302 NS_IMETHODIMP nsPK11Token::GetNeedsUserInit(PRBool *aNeedsUserInit)
00303 {
00304   nsNSSShutDownPreventionLock locker;
00305   if (isAlreadyShutDown())
00306     return NS_ERROR_NOT_AVAILABLE;
00307 
00308   *aNeedsUserInit = PK11_NeedUserInit(mSlot);
00309   return NS_OK;
00310 }
00311 
00312 /* boolean checkPassword (in wstring password); */
00313 NS_IMETHODIMP nsPK11Token::CheckPassword(const PRUnichar *password, PRBool *_retval)
00314 {
00315   nsNSSShutDownPreventionLock locker;
00316   if (isAlreadyShutDown())
00317     return NS_ERROR_NOT_AVAILABLE;
00318 
00319   SECStatus srv;
00320   PRInt32 prerr;
00321   NS_ConvertUCS2toUTF8 aUtf8Password(password);
00322   srv = PK11_CheckUserPassword(mSlot, 
00323                   NS_CONST_CAST(char *, aUtf8Password.get()));
00324   if (srv != SECSuccess) {
00325     *_retval =  PR_FALSE;
00326     prerr = PR_GetError();
00327     if (prerr != SEC_ERROR_BAD_PASSWORD) {
00328       /* something really bad happened - throw an exception */
00329       return NS_ERROR_FAILURE;
00330     }
00331   } else {
00332     *_retval =  PR_TRUE;
00333   }
00334   return NS_OK;
00335 }
00336 
00337 /* void initPassword (in wstring initialPassword); */
00338 NS_IMETHODIMP nsPK11Token::InitPassword(const PRUnichar *initialPassword)
00339 {
00340   nsNSSShutDownPreventionLock locker;
00341   if (isAlreadyShutDown())
00342     return NS_ERROR_NOT_AVAILABLE;
00343 
00344     nsresult rv = NS_OK;
00345     SECStatus status;
00346 
00347     NS_ConvertUCS2toUTF8 aUtf8InitialPassword(initialPassword);
00348     status = PK11_InitPin(mSlot, "", NS_CONST_CAST(char*, aUtf8InitialPassword.get()));
00349     if (status == SECFailure) { rv = NS_ERROR_FAILURE; goto done; }
00350 
00351 done:
00352     return rv;
00353 }
00354 
00355 /* long getAskPasswordTimes(); */
00356 NS_IMETHODIMP 
00357 nsPK11Token::GetAskPasswordTimes(PRInt32 *rvAskTimes)
00358 {
00359   nsNSSShutDownPreventionLock locker;
00360   if (isAlreadyShutDown())
00361     return NS_ERROR_NOT_AVAILABLE;
00362 
00363     int askTimes, askTimeout;
00364     PK11_GetSlotPWValues(mSlot, &askTimes, &askTimeout);
00365     *rvAskTimes = askTimes;
00366     return NS_OK;
00367 }
00368 
00369 /* long getAskPasswordTimeout(); */
00370 NS_IMETHODIMP 
00371 nsPK11Token::GetAskPasswordTimeout(PRInt32 *rvAskTimeout)
00372 {
00373   nsNSSShutDownPreventionLock locker;
00374   if (isAlreadyShutDown())
00375     return NS_ERROR_NOT_AVAILABLE;
00376 
00377     int askTimes, askTimeout;
00378     PK11_GetSlotPWValues(mSlot, &askTimes, &askTimeout);
00379     *rvAskTimeout = askTimeout;
00380     return NS_OK;
00381 }
00382 
00383 /* void setAskPasswordDefaults(in unsigned long askTimes,
00384  *                             in unsigned long timeout);
00385  */
00386 NS_IMETHODIMP 
00387 nsPK11Token::SetAskPasswordDefaults(const PRInt32 askTimes,
00388                                     const PRInt32 askTimeout)
00389 {
00390   nsNSSShutDownPreventionLock locker;
00391   if (isAlreadyShutDown())
00392     return NS_ERROR_NOT_AVAILABLE;
00393 
00394     PK11_SetSlotPWValues(mSlot, askTimes, askTimeout);
00395     return NS_OK;
00396 }
00397 
00398 /* void changePassword (in wstring oldPassword, in wstring newPassword); */
00399 NS_IMETHODIMP nsPK11Token::ChangePassword(const PRUnichar *oldPassword, const PRUnichar *newPassword)
00400 {
00401   nsNSSShutDownPreventionLock locker;
00402   if (isAlreadyShutDown())
00403     return NS_ERROR_NOT_AVAILABLE;
00404 
00405   SECStatus rv;
00406   NS_ConvertUCS2toUTF8 aUtf8OldPassword(oldPassword);
00407   NS_ConvertUCS2toUTF8 aUtf8NewPassword(newPassword);
00408   rv = PK11_ChangePW(mSlot, 
00409                NS_CONST_CAST(char *, aUtf8OldPassword.get()), 
00410                NS_CONST_CAST(char *, aUtf8NewPassword.get()));
00411   return (rv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
00412 }
00413 
00414 /* boolean isHardwareToken (); */
00415 NS_IMETHODIMP nsPK11Token::IsHardwareToken(PRBool *_retval)
00416 {
00417   nsNSSShutDownPreventionLock locker;
00418   if (isAlreadyShutDown())
00419     return NS_ERROR_NOT_AVAILABLE;
00420 
00421   nsresult rv = NS_OK;
00422 
00423   *_retval = PK11_IsHW(mSlot);
00424 
00425   return rv;
00426 }
00427 
00428 /* boolean needsLogin (); */
00429 NS_IMETHODIMP nsPK11Token::NeedsLogin(PRBool *_retval)
00430 {
00431   nsNSSShutDownPreventionLock locker;
00432   if (isAlreadyShutDown())
00433     return NS_ERROR_NOT_AVAILABLE;
00434 
00435   nsresult rv = NS_OK;
00436 
00437   *_retval = PK11_NeedLogin(mSlot);
00438 
00439   return rv;
00440 }
00441 
00442 /* boolean isFriendly (); */
00443 NS_IMETHODIMP nsPK11Token::IsFriendly(PRBool *_retval)
00444 {
00445   nsNSSShutDownPreventionLock locker;
00446   if (isAlreadyShutDown())
00447     return NS_ERROR_NOT_AVAILABLE;
00448 
00449   nsresult rv = NS_OK;
00450 
00451   *_retval = PK11_IsFriendly(mSlot);
00452 
00453   return rv;
00454 }
00455 
00456 /*=========================================================*/
00457 
00458 NS_IMPL_ISUPPORTS1(nsPK11TokenDB, nsIPK11TokenDB)
00459 
00460 nsPK11TokenDB::nsPK11TokenDB()
00461 {
00462   /* member initializers and constructor code */
00463 }
00464 
00465 nsPK11TokenDB::~nsPK11TokenDB()
00466 {
00467   /* destructor code */
00468 }
00469 
00470 /* nsIPK11Token getInternalKeyToken (); */
00471 NS_IMETHODIMP nsPK11TokenDB::GetInternalKeyToken(nsIPK11Token **_retval)
00472 {
00473   nsNSSShutDownPreventionLock locker;
00474   nsresult rv = NS_OK;
00475   PK11SlotInfo *slot = 0;
00476   nsCOMPtr<nsIPK11Token> token;
00477 
00478   slot = PK11_GetInternalKeySlot();
00479   if (!slot) { rv = NS_ERROR_FAILURE; goto done; }
00480 
00481   token = new nsPK11Token(slot);
00482   if (!token) { rv = NS_ERROR_OUT_OF_MEMORY; goto done; }
00483 
00484   *_retval = token;
00485   NS_ADDREF(*_retval);
00486 
00487 done:
00488   if (slot) PK11_FreeSlot(slot);
00489   return rv;
00490 }
00491 
00492 /* nsIPK11Token findTokenByName (in wchar tokenName); */
00493 NS_IMETHODIMP nsPK11TokenDB::
00494 FindTokenByName(const PRUnichar* tokenName, nsIPK11Token **_retval)
00495 {
00496   nsNSSShutDownPreventionLock locker;
00497   nsresult rv = NS_OK;
00498   PK11SlotInfo *slot = 0;
00499   NS_ConvertUCS2toUTF8 aUtf8TokenName(tokenName);
00500   slot = PK11_FindSlotByName(NS_CONST_CAST(char*, aUtf8TokenName.get()));
00501   if (!slot) { rv = NS_ERROR_FAILURE; goto done; }
00502 
00503   *_retval = new nsPK11Token(slot);
00504   if (!*_retval) { rv = NS_ERROR_OUT_OF_MEMORY; goto done; }
00505 
00506   NS_ADDREF(*_retval);
00507 
00508 done:
00509   if (slot) PK11_FreeSlot(slot);
00510   return rv;
00511 }
00512 
00513 /* nsIEnumerator listTokens (); */
00514 NS_IMETHODIMP nsPK11TokenDB::ListTokens(nsIEnumerator* *_retval)
00515 {
00516   nsNSSShutDownPreventionLock locker;
00517   nsresult rv = NS_OK;
00518   nsCOMPtr<nsISupportsArray> array;
00519   PK11SlotList *list = 0;
00520   PK11SlotListElement *le;
00521 
00522   rv = NS_NewISupportsArray(getter_AddRefs(array));
00523   if (NS_FAILED(rv)) { goto done; }
00524 
00525   /* List all tokens, creating PK11Token objects and putting them
00526    * into the array.
00527    */
00528   list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, 0);
00529   if (!list) { rv = NS_ERROR_FAILURE; goto done; }
00530 
00531   for (le = PK11_GetFirstSafe(list); le; le = PK11_GetNextSafe(list, le, PR_FALSE)) {
00532     nsCOMPtr<nsIPK11Token> token = new nsPK11Token(le->slot);
00533 
00534     array->AppendElement(token);
00535   }
00536 
00537   rv = array->Enumerate(_retval);
00538 
00539 done:
00540   if (list) PK11_FreeSlotList(list);
00541   return rv;
00542 }
00543