Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
8.4 KiB

  1. // AccessTok.cpp -- Access Token class definition
  2. // (c) Copyright Schlumberger Technology Corp., unpublished work, created
  3. // 1999. This computer program includes Confidential, Proprietary
  4. // Information and is a Trade Secret of Schlumberger Technology Corp. All
  5. // use, disclosure, and/or reproduction is prohibited unless authorized
  6. // in writing. All Rights Reserved.
  7. #include "NoWarning.h"
  8. #include "ForceLib.h"
  9. #include <limits>
  10. #include <memory>
  11. #include <WinError.h>
  12. #include <scuOsExc.h>
  13. #include "Blob.h"
  14. #include "AccessTok.h"
  15. using namespace std;
  16. /////////////////////////// LOCAL/HELPER /////////////////////////////////
  17. namespace
  18. {
  19. const char PinPad = '\xFF';
  20. void
  21. DoAuthenticate(HCardContext const &rhcardctx,
  22. string const &rsPin)
  23. {
  24. rhcardctx->Card()->AuthenticateUser(rsPin);
  25. }
  26. string
  27. ToAscii(string const &rsHexPin)
  28. {
  29. string::size_type cNewLength = rsHexPin.size() / 2;
  30. string sAsciiPin;
  31. sAsciiPin.reserve(AccessToken::MaxPinLength);
  32. for (size_t i = 0; i < cNewLength; i++)
  33. {
  34. for (size_t j = 0; j < 2; j++)
  35. {
  36. BYTE b;
  37. if (isxdigit(rsHexPin[2*i+j]))
  38. {
  39. if (isdigit(rsHexPin[2*i+j]))
  40. b = rsHexPin[2*i+j] - '0';
  41. else
  42. {
  43. if (isupper(rsHexPin[2*i+j]))
  44. b = rsHexPin[2*i+j] - 'A' + 0x0A;
  45. else
  46. b = rsHexPin[2*i+j] - 'a' + 0x0A;
  47. }
  48. }
  49. else
  50. throw scu::OsException(ERROR_INVALID_PARAMETER);
  51. if (0 == j)
  52. sAsciiPin[i] = b << (numeric_limits<BYTE>::digits / 2);
  53. else
  54. sAsciiPin[i] |= b;
  55. }
  56. }
  57. return sAsciiPin;
  58. }
  59. }
  60. /////////////////////////// PUBLIC /////////////////////////////////
  61. // Types
  62. // C'tors/D'tors
  63. AccessToken::AccessToken(HCardContext const &rhcardctx,
  64. LoginIdentity const &rlid)
  65. : m_hcardctx(rhcardctx),
  66. m_lid(rlid),
  67. m_hpc(0),
  68. m_sPin()
  69. {
  70. // TO DO: Support Administrator and Manufacturing PINs
  71. switch (m_lid)
  72. {
  73. case User:
  74. break;
  75. case Administrator:
  76. // TO DO: Support authenticating admin (aut 0)
  77. throw scu::OsException(E_NOTIMPL);
  78. case Manufacturer:
  79. // TO DO: Support authenticating manufacturer (aut ?)
  80. throw scu::OsException(E_NOTIMPL);
  81. default:
  82. throw scu::OsException(ERROR_INVALID_PARAMETER);
  83. }
  84. m_sPin.reserve(MaxPinLength);
  85. }
  86. AccessToken::AccessToken(AccessToken const &rhs)
  87. : m_hcardctx(rhs.m_hcardctx),
  88. m_lid(rhs.m_lid),
  89. m_hpc(0), // doesn't commute
  90. m_sPin(rhs.m_sPin)
  91. {}
  92. AccessToken::~AccessToken()
  93. {
  94. try
  95. {
  96. FlushPin();
  97. }
  98. catch (...)
  99. {
  100. }
  101. }
  102. // Operators
  103. // Operations
  104. void
  105. AccessToken::Authenticate()
  106. {
  107. // Only the user pin (CHV) is supported.
  108. DWORD dwError = ERROR_SUCCESS;
  109. BYTE bPin[MaxPinLength];
  110. DWORD cbPin = sizeof bPin / sizeof *bPin;
  111. if ((0 == m_hpc) || (0 != m_sPin.length()))
  112. {
  113. // The MS pin cache is either uninitialized (empty) or a new
  114. // pin supplied. Authenticate using requested pin, having the MS pin
  115. // cache library update the cache if authentication succeeds.
  116. memcpy(bPin, m_sPin.data(), cbPin);
  117. PINCACHE_PINS pcpins = {
  118. cbPin,
  119. bPin,
  120. 0,
  121. 0
  122. };
  123. dwError = PinCacheAdd(&m_hpc, &pcpins, VerifyPin, this);
  124. if (ERROR_SUCCESS != dwError)
  125. {
  126. m_sPin.erase();
  127. if (Exception())
  128. PropagateException();
  129. else
  130. throw scu::OsException(dwError);
  131. }
  132. }
  133. else
  134. {
  135. // The MS pin cache must already be initialized at this point.
  136. // Retrieve it and authenticate.
  137. dwError = PinCacheQuery(m_hpc, bPin, &cbPin);
  138. if (ERROR_SUCCESS != dwError)
  139. throw scu::OsException(dwError);
  140. Blob blbPin(bPin, cbPin);
  141. DoAuthenticate(m_hcardctx, AsString(blbPin));
  142. m_sPin = AsString(blbPin); // cache in case changing pin
  143. }
  144. }
  145. void
  146. AccessToken::ChangePin(AccessToken const &ratNew)
  147. {
  148. DWORD dwError = ERROR_SUCCESS;
  149. BYTE bPin[MaxPinLength];
  150. DWORD cbPin = sizeof bPin / sizeof bPin[0];
  151. memcpy(bPin, m_sPin.data(), MaxPinLength);
  152. BYTE bNewPin[MaxPinLength];
  153. DWORD cbNewPin = sizeof bNewPin / sizeof bNewPin[0];
  154. memcpy(bNewPin, ratNew.m_sPin.data(), MaxPinLength);
  155. PINCACHE_PINS pcpins = {
  156. cbPin,
  157. bPin,
  158. cbNewPin,
  159. bNewPin
  160. };
  161. dwError = PinCacheAdd(&m_hpc, &pcpins, ChangeCardPin, this);
  162. if (ERROR_SUCCESS != dwError)
  163. {
  164. if (Exception())
  165. PropagateException();
  166. else
  167. throw scu::OsException(dwError);
  168. }
  169. m_sPin = ratNew.m_sPin; // cache the new pin
  170. }
  171. void
  172. AccessToken::ClearPin()
  173. {
  174. m_sPin.erase();
  175. }
  176. void
  177. AccessToken::FlushPin()
  178. {
  179. PinCacheFlush(&m_hpc);
  180. ClearPin();
  181. }
  182. void
  183. AccessToken::Pin(string const &rsPin,
  184. bool fInHex)
  185. {
  186. if (fInHex)
  187. m_sPin = ToAscii(rsPin);
  188. else
  189. m_sPin = rsPin;
  190. if (m_sPin.length() > MaxPinLength)
  191. throw scu::OsException(ERROR_INVALID_PARAMETER);
  192. if (m_sPin.length() < MaxPinLength) // always pad the pin
  193. m_sPin.append(MaxPinLength - m_sPin.length(), PinPad);
  194. }
  195. // Access
  196. HCardContext
  197. AccessToken::CardContext() const
  198. {
  199. return m_hcardctx;
  200. }
  201. LoginIdentity
  202. AccessToken::Identity() const
  203. {
  204. return m_lid;
  205. }
  206. string
  207. AccessToken::Pin() const
  208. {
  209. return m_sPin;
  210. }
  211. // Predicates
  212. bool
  213. AccessToken::PinIsCached() const
  214. {
  215. DWORD cbPin;
  216. DWORD dwError = PinCacheQuery(m_hpc, 0, &cbPin);
  217. bool fIsCached = (0 != cbPin);
  218. return fIsCached;
  219. }
  220. // Static Variables
  221. /////////////////////////// PROTECTED /////////////////////////////////
  222. // C'tors/D'tors
  223. // Operators
  224. // Operations
  225. // Access
  226. // Predicates
  227. // Static Variables
  228. /////////////////////////// PRIVATE /////////////////////////////////
  229. // C'tors/D'tors
  230. // Operators
  231. // Operations
  232. DWORD
  233. AccessToken::ChangeCardPin(PPINCACHE_PINS pPins,
  234. PVOID pvCallbackCtx)
  235. {
  236. AccessToken *pat = reinterpret_cast<AccessToken *>(pvCallbackCtx);
  237. DWORD dwError = ERROR_SUCCESS;
  238. EXCCTX_TRY
  239. {
  240. pat->ClearException();
  241. Blob blbPin(pPins->pbCurrentPin, pPins->cbCurrentPin);
  242. Blob blbNewPin(pPins->pbNewPin, pPins->cbNewPin);
  243. pat->m_hcardctx->Card()->ChangePIN(AsString(blbPin),
  244. AsString(blbNewPin));
  245. }
  246. EXCCTX_CATCH(pat, false);
  247. if (pat->Exception())
  248. dwError = E_FAIL;
  249. return dwError;
  250. }
  251. DWORD
  252. AccessToken::VerifyPin(PPINCACHE_PINS pPins,
  253. PVOID pvCallbackCtx)
  254. {
  255. AccessToken *pat = reinterpret_cast<AccessToken *>(pvCallbackCtx);
  256. DWORD dwError = ERROR_SUCCESS;
  257. EXCCTX_TRY
  258. {
  259. pat->ClearException();
  260. Blob blbPin(pPins->pbCurrentPin, pPins->cbCurrentPin);
  261. DoAuthenticate(pat->m_hcardctx, AsString(blbPin));
  262. }
  263. EXCCTX_CATCH(pat, false);
  264. if (pat->Exception())
  265. dwError = E_FAIL;
  266. return dwError;
  267. }
  268. // Access
  269. // Predicates
  270. // Static Variables