|
|
// AccessTok.cpp -- Access Token class definition
// (c) Copyright Schlumberger Technology Corp., unpublished work, created
// 1999. This computer program includes Confidential, Proprietary
// Information and is a Trade Secret of Schlumberger Technology Corp. All
// use, disclosure, and/or reproduction is prohibited unless authorized
// in writing. All Rights Reserved.
#include "NoWarning.h"
#include "ForceLib.h"
#include <limits>
#include <memory>
#include <WinError.h>
#include <scuOsExc.h>
#include "Blob.h"
#include "AccessTok.h"
using namespace std;
/////////////////////////// LOCAL/HELPER /////////////////////////////////
namespace { const char PinPad = '\xFF';
void DoAuthenticate(HCardContext const &rhcardctx, string const &rsPin) { rhcardctx->Card()->AuthenticateUser(rsPin); }
string ToAscii(string const &rsHexPin) { string::size_type cNewLength = rsHexPin.size() / 2;
string sAsciiPin; sAsciiPin.reserve(AccessToken::MaxPinLength);
for (size_t i = 0; i < cNewLength; i++) { for (size_t j = 0; j < 2; j++) { BYTE b;
if (isxdigit(rsHexPin[2*i+j])) { if (isdigit(rsHexPin[2*i+j])) b = rsHexPin[2*i+j] - '0'; else { if (isupper(rsHexPin[2*i+j])) b = rsHexPin[2*i+j] - 'A' + 0x0A; else b = rsHexPin[2*i+j] - 'a' + 0x0A; } } else throw scu::OsException(ERROR_INVALID_PARAMETER);
if (0 == j) sAsciiPin[i] = b << (numeric_limits<BYTE>::digits / 2); else sAsciiPin[i] |= b; } }
return sAsciiPin; }
}
/////////////////////////// PUBLIC /////////////////////////////////
// Types
// C'tors/D'tors
AccessToken::AccessToken(HCardContext const &rhcardctx, LoginIdentity const &rlid) : m_hcardctx(rhcardctx), m_lid(rlid), m_hpc(0), m_sPin() { // TO DO: Support Administrator and Manufacturing PINs
switch (m_lid) { case User: break;
case Administrator: // TO DO: Support authenticating admin (aut 0)
throw scu::OsException(E_NOTIMPL);
case Manufacturer: // TO DO: Support authenticating manufacturer (aut ?)
throw scu::OsException(E_NOTIMPL);
default: throw scu::OsException(ERROR_INVALID_PARAMETER); }
m_sPin.reserve(MaxPinLength); }
AccessToken::AccessToken(AccessToken const &rhs) : m_hcardctx(rhs.m_hcardctx), m_lid(rhs.m_lid), m_hpc(0), // doesn't commute
m_sPin(rhs.m_sPin) {}
AccessToken::~AccessToken() { try { FlushPin(); }
catch (...) { } }
// Operators
// Operations
void AccessToken::Authenticate() { // Only the user pin (CHV) is supported.
DWORD dwError = ERROR_SUCCESS; BYTE bPin[MaxPinLength]; DWORD cbPin = sizeof bPin / sizeof *bPin; if ((0 == m_hpc) || (0 != m_sPin.length())) { // The MS pin cache is either uninitialized (empty) or a new
// pin supplied. Authenticate using requested pin, having the MS pin
// cache library update the cache if authentication succeeds.
memcpy(bPin, m_sPin.data(), cbPin); PINCACHE_PINS pcpins = { cbPin, bPin, 0, 0 };
dwError = PinCacheAdd(&m_hpc, &pcpins, VerifyPin, this); if (ERROR_SUCCESS != dwError) { m_sPin.erase(); if (Exception()) PropagateException(); else throw scu::OsException(dwError); } } else { // The MS pin cache must already be initialized at this point.
// Retrieve it and authenticate.
dwError = PinCacheQuery(m_hpc, bPin, &cbPin); if (ERROR_SUCCESS != dwError) throw scu::OsException(dwError);
Blob blbPin(bPin, cbPin); DoAuthenticate(m_hcardctx, AsString(blbPin)); m_sPin = AsString(blbPin); // cache in case changing pin
} }
void AccessToken::ChangePin(AccessToken const &ratNew) { DWORD dwError = ERROR_SUCCESS;
BYTE bPin[MaxPinLength]; DWORD cbPin = sizeof bPin / sizeof bPin[0]; memcpy(bPin, m_sPin.data(), MaxPinLength);
BYTE bNewPin[MaxPinLength]; DWORD cbNewPin = sizeof bNewPin / sizeof bNewPin[0]; memcpy(bNewPin, ratNew.m_sPin.data(), MaxPinLength);
PINCACHE_PINS pcpins = { cbPin, bPin, cbNewPin, bNewPin };
dwError = PinCacheAdd(&m_hpc, &pcpins, ChangeCardPin, this); if (ERROR_SUCCESS != dwError) { if (Exception()) PropagateException(); else throw scu::OsException(dwError); }
m_sPin = ratNew.m_sPin; // cache the new pin
}
void AccessToken::ClearPin() { m_sPin.erase(); }
void AccessToken::FlushPin() { PinCacheFlush(&m_hpc);
ClearPin(); }
void AccessToken::Pin(string const &rsPin, bool fInHex) { if (fInHex) m_sPin = ToAscii(rsPin); else m_sPin = rsPin;
if (m_sPin.length() > MaxPinLength) throw scu::OsException(ERROR_INVALID_PARAMETER);
if (m_sPin.length() < MaxPinLength) // always pad the pin
m_sPin.append(MaxPinLength - m_sPin.length(), PinPad); }
// Access
HCardContext AccessToken::CardContext() const { return m_hcardctx; }
LoginIdentity AccessToken::Identity() const { return m_lid; }
string AccessToken::Pin() const { return m_sPin; }
// Predicates
bool AccessToken::PinIsCached() const { DWORD cbPin; DWORD dwError = PinCacheQuery(m_hpc, 0, &cbPin); bool fIsCached = (0 != cbPin);
return fIsCached; }
// Static Variables
/////////////////////////// PROTECTED /////////////////////////////////
// C'tors/D'tors
// Operators
// Operations
// Access
// Predicates
// Static Variables
/////////////////////////// PRIVATE /////////////////////////////////
// C'tors/D'tors
// Operators
// Operations
DWORD AccessToken::ChangeCardPin(PPINCACHE_PINS pPins, PVOID pvCallbackCtx) { AccessToken *pat = reinterpret_cast<AccessToken *>(pvCallbackCtx); DWORD dwError = ERROR_SUCCESS;
EXCCTX_TRY { pat->ClearException();
Blob blbPin(pPins->pbCurrentPin, pPins->cbCurrentPin); Blob blbNewPin(pPins->pbNewPin, pPins->cbNewPin); pat->m_hcardctx->Card()->ChangePIN(AsString(blbPin), AsString(blbNewPin)); }
EXCCTX_CATCH(pat, false);
if (pat->Exception()) dwError = E_FAIL;
return dwError; }
DWORD AccessToken::VerifyPin(PPINCACHE_PINS pPins, PVOID pvCallbackCtx) { AccessToken *pat = reinterpret_cast<AccessToken *>(pvCallbackCtx); DWORD dwError = ERROR_SUCCESS;
EXCCTX_TRY { pat->ClearException();
Blob blbPin(pPins->pbCurrentPin, pPins->cbCurrentPin); DoAuthenticate(pat->m_hcardctx, AsString(blbPin)); }
EXCCTX_CATCH(pat, false);
if (pat->Exception()) dwError = E_FAIL;
return dwError; } // Access
// Predicates
// Static Variables
|