bug in session managing, redesign: removed smart resources, don't allow to copy sessions; refs #7

master
Marc Wäckerlin 14 years ago
parent dcc9a84734
commit e4671ed7a2
  1. 182
      src/cryptoki.hxx
  2. 2
      src/pcsc.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;
} }

Loading…
Cancel
Save