bug in session managing, redesign: removed smart resources, don't allow to copy sessions; refs #7
This commit is contained in:
182
src/cryptoki.hxx
182
src/cryptoki.hxx
@@ -86,119 +86,6 @@ namespace pcsc {
|
|||||||
//! @see gcryptoki
|
//! @see gcryptoki
|
||||||
namespace cryptoki {
|
namespace cryptoki {
|
||||||
|
|
||||||
//! @todo copy in own library
|
|
||||||
/*! Inherit from SmartResource,
|
|
||||||
and overwrite free(). You must call destruct() in your destructor. */
|
|
||||||
class SmartResource {
|
|
||||||
public:
|
|
||||||
SmartResource(): _cnt(0), _destructed(false) {
|
|
||||||
incr();
|
|
||||||
}
|
|
||||||
//! must be called in copy constructor of children!
|
|
||||||
SmartResource(const SmartResource& o): _cnt(o._cnt), _destructed(false) {
|
|
||||||
incr();
|
|
||||||
}
|
|
||||||
~SmartResource() {
|
|
||||||
assert(_destructed); // child must call destruct() in destructor
|
|
||||||
}
|
|
||||||
//! must be called in assignment constructor of children!
|
|
||||||
SmartResource& operator=(const SmartResource& o) {
|
|
||||||
decr();
|
|
||||||
_cnt = o._cnt;
|
|
||||||
incr();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
//! Overwrite to free your resource.
|
|
||||||
virtual void free() = 0;
|
|
||||||
//! You must call it in your destructor!
|
|
||||||
void destruct() {
|
|
||||||
if (_destructed) return; // only once
|
|
||||||
decr();
|
|
||||||
_destructed = true;
|
|
||||||
}
|
|
||||||
//! Seldom needed, mostly automatic.
|
|
||||||
void incr() {
|
|
||||||
if (!_cnt) _cnt = new unsigned int(0);
|
|
||||||
++*_cnt;
|
|
||||||
assert(_cnt);
|
|
||||||
}
|
|
||||||
//! Seldom needed, mostly automatic.
|
|
||||||
void decr() {
|
|
||||||
if (!_cnt || --*_cnt) return;
|
|
||||||
delete _cnt; _cnt = 0;
|
|
||||||
free();
|
|
||||||
}
|
|
||||||
//! Seldom needed, mostly automatic.
|
|
||||||
/*! Used in complete reassign of resource from outside.
|
|
||||||
Call incr() after assignment. */
|
|
||||||
void clear() {
|
|
||||||
decr();
|
|
||||||
_cnt = 0;
|
|
||||||
}
|
|
||||||
//! Reads the internal counter (for testing and debugging only);
|
|
||||||
int cnt() {
|
|
||||||
assert(_cnt);
|
|
||||||
return *_cnt;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
unsigned int *_cnt;
|
|
||||||
bool _destructed;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> class SharedPointer: public SmartResource {
|
|
||||||
public:
|
|
||||||
SharedPointer(): _p(0) {}
|
|
||||||
SharedPointer(const SharedPointer& o): SmartResource(o), _p(o._p) {}
|
|
||||||
SharedPointer(T* p): _p(p) {}
|
|
||||||
SharedPointer& operator=(const SharedPointer& o) {
|
|
||||||
return reset(o);
|
|
||||||
}
|
|
||||||
SharedPointer& operator=(T* p) {
|
|
||||||
return reset(p);
|
|
||||||
}
|
|
||||||
~SharedPointer() {
|
|
||||||
destruct();
|
|
||||||
}
|
|
||||||
T* const operator->() {
|
|
||||||
return get();
|
|
||||||
}
|
|
||||||
const T* const operator->() const {
|
|
||||||
return get();
|
|
||||||
}
|
|
||||||
const T& operator*() const {
|
|
||||||
return *get();
|
|
||||||
}
|
|
||||||
T& operator*() {
|
|
||||||
return *get();
|
|
||||||
}
|
|
||||||
SharedPointer& reset(const SharedPointer& o) {
|
|
||||||
SmartResource::operator=(o);
|
|
||||||
_p = o._p;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
SharedPointer& reset(T* p = 0) {
|
|
||||||
clear();
|
|
||||||
_p = p;
|
|
||||||
incr();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
const T* const get() const {
|
|
||||||
assert(_p);
|
|
||||||
return _p;
|
|
||||||
}
|
|
||||||
T* const get() {
|
|
||||||
assert(_p);
|
|
||||||
return _p;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
void free() {
|
|
||||||
delete _p; _p=0;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
T* _p;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! @addtogroup cryptokitypes
|
//! @addtogroup cryptokitypes
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
@@ -1000,7 +887,7 @@ namespace cryptoki {
|
|||||||
|
|
||||||
//! Session Management
|
//! Session Management
|
||||||
//! Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID);
|
//! Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID);
|
||||||
class Session: public SmartResource {
|
class Session {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
friend class Login;
|
friend class Login;
|
||||||
@@ -1015,6 +902,9 @@ namespace cryptoki {
|
|||||||
CK_RV _res;
|
CK_RV _res;
|
||||||
|
|
||||||
Session(); // forbidden
|
Session(); // forbidden
|
||||||
|
Session(const Session& o); // no-copy
|
||||||
|
Session& operator=(const Session& o); // no-copy
|
||||||
|
|
||||||
|
|
||||||
bool check(CK_RV result, const std::string& context="") {
|
bool check(CK_RV result, const std::string& context="") {
|
||||||
CRYPTOKI_LOG("log");
|
CRYPTOKI_LOG("log");
|
||||||
@@ -1026,26 +916,31 @@ namespace cryptoki {
|
|||||||
throw access_error(error());
|
throw access_error(error());
|
||||||
return _res==CKR_OK;
|
return _res==CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free() {
|
void free() {
|
||||||
CRYPTOKI_LOG("log");
|
CRYPTOKI_LOG("log");
|
||||||
try {
|
try {
|
||||||
//! closes login.
|
//! closes login.
|
||||||
_login.reset();
|
logout();
|
||||||
|
} catch (...) { // still try to close session
|
||||||
//! calls @c C_CloseSession
|
//! calls @c C_CloseSession
|
||||||
check(_slot._init->_fn->C_CloseSession(_session),
|
try {
|
||||||
CRYPTOKI_FN_LOG("C_CloseSession"));
|
check(_slot._init->_fn->C_CloseSession(_session),
|
||||||
} catch (...) {
|
CRYPTOKI_FN_LOG("C_CloseSession"));
|
||||||
if (!std::uncaught_exception()) throw;
|
} catch (...) {} // only report first problem
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
//! calls @c C_CloseSession
|
||||||
|
check(_slot._init->_fn->C_CloseSession(_session),
|
||||||
|
CRYPTOKI_FN_LOG("C_CloseSession"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Opens a new session.
|
//! Opens a new session.
|
||||||
/*! @param slot slot to open a session on */
|
/*! @param slot slot to open a session on */
|
||||||
Session(Slot& slot, bool rw=false):
|
Session(Slot& slot, bool rw=false):
|
||||||
_slot(slot), _session(0), _res(CKR_OK) {
|
_slot(slot), _session(0), _res(CKR_OK), _login(0) {
|
||||||
CRYPTOKI_LOG("log");
|
CRYPTOKI_LOG("log");
|
||||||
//! calls @c C_OpenSession
|
//! calls @c C_OpenSession
|
||||||
check(_slot._init->_fn->C_OpenSession
|
check(_slot._init->_fn->C_OpenSession
|
||||||
@@ -1055,25 +950,13 @@ namespace cryptoki {
|
|||||||
//! @todo pass parameter
|
//! @todo pass parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
Session(const Session& o):
|
~Session() try {
|
||||||
SmartResource(o),
|
|
||||||
_slot(o._slot), _session(o._session), _res(o._res) {
|
|
||||||
CRYPTOKI_LOG("log");
|
CRYPTOKI_LOG("log");
|
||||||
}
|
free();
|
||||||
|
} catch (...) {
|
||||||
~Session() {
|
if (!std::uncaught_exception()) throw;
|
||||||
CRYPTOKI_LOG("log");
|
|
||||||
destruct();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Session& operator=(const Session& o) {
|
|
||||||
CRYPTOKI_LOG("log");
|
|
||||||
SmartResource::operator=(o);
|
|
||||||
_slot = o._slot;
|
|
||||||
_session = o._session;
|
|
||||||
_res = o._res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @name Comfortable Access
|
/*! @name Comfortable Access
|
||||||
|
|
||||||
Use these methods in favour of the Low Level Cryptoki
|
Use these methods in favour of the Low Level Cryptoki
|
||||||
@@ -1310,13 +1193,22 @@ namespace cryptoki {
|
|||||||
|
|
||||||
void login(const std::string& pin, CK_USER_TYPE userType=CKU_USER) {
|
void login(const std::string& pin, CK_USER_TYPE userType=CKU_USER) {
|
||||||
CRYPTOKI_LOG("log");
|
CRYPTOKI_LOG("log");
|
||||||
_login = SharedPointer<Login>(new Login(*this, pin, userType));
|
delete _login;
|
||||||
|
_login = new Login(*this, pin, userType);
|
||||||
}
|
}
|
||||||
|
|
||||||
void logout() {
|
void logout() {
|
||||||
CRYPTOKI_LOG("log");
|
CRYPTOKI_LOG("log");
|
||||||
_login.reset();
|
try {
|
||||||
|
delete _login;
|
||||||
|
_login = 0;
|
||||||
|
} catch (...) {
|
||||||
|
_login = 0;
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SharedPointer<Login> _login;
|
|
||||||
|
Login* _login;
|
||||||
|
|
||||||
/*! @todo Not implemented:
|
/*! @todo Not implemented:
|
||||||
@code
|
@code
|
||||||
@@ -1458,7 +1350,7 @@ namespace cryptoki {
|
|||||||
friend class Session;
|
friend class Session;
|
||||||
|
|
||||||
CK_OBJECT_HANDLE _object;
|
CK_OBJECT_HANDLE _object;
|
||||||
Session _session;
|
Session& _session;
|
||||||
CK_RV _res;
|
CK_RV _res;
|
||||||
|
|
||||||
bool check(CK_RV result, const std::string& context="") {
|
bool check(CK_RV result, const std::string& context="") {
|
||||||
@@ -1472,11 +1364,9 @@ namespace cryptoki {
|
|||||||
return _res==CKR_OK;
|
return _res==CKR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object() {
|
Object(); // forbidden
|
||||||
CRYPTOKI_LOG("log");
|
|
||||||
}
|
|
||||||
|
|
||||||
Object(const Session& session, CK_OBJECT_HANDLE obj):
|
Object(Session& session, CK_OBJECT_HANDLE obj):
|
||||||
_session(session), _object(obj), _res(CKR_OK) {
|
_session(session), _object(obj), _res(CKR_OK) {
|
||||||
CRYPTOKI_LOG("log");
|
CRYPTOKI_LOG("log");
|
||||||
}
|
}
|
||||||
|
@@ -192,7 +192,7 @@ namespace pcsc {
|
|||||||
}
|
}
|
||||||
//! Cancels the transaction if not yet finished.
|
//! Cancels the transaction if not yet finished.
|
||||||
~Transaction() try {
|
~Transaction() try {
|
||||||
if (_running) cancel();
|
cancel();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
if (!std::uncaught_exception()) throw;
|
if (!std::uncaught_exception()) throw;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user