bug fixes and reference counters (prevents hanging); refs #28

master
Marc Wäckerlin 11 years ago
parent d5038341d2
commit 50647d461b
  1. 2
      src/cardos.hxx
  2. 2
      src/cryptaux.hxx
  3. 50
      src/cryptoki.hxx
  4. 8
      src/openssl.hxx
  5. 83
      src/pcsc.hxx

@ -170,7 +170,7 @@ namespace cardos {
_tag = content[0]; _tag = content[0];
_length = content[1]; _length = content[1];
_value = content.substr(2, _length); _value = content.substr(2, _length);
if (_length+2>content.size()) if (std::string::size_type(_length)+2>content.size())
throw wrong_dataformat(content, "not a BER, content size too" throw wrong_dataformat(content, "not a BER, content size too"
" small: \""+crypto::binToHex(_value)+"\""); " small: \""+crypto::binToHex(_value)+"\"");
if (tagType()==END_OF_CONTENT) return; // done if (tagType()==END_OF_CONTENT) return; // done

@ -114,7 +114,7 @@ namespace crypto {
if (!data.size()) if (!data.size())
return "<empty>"; return "<empty>";
else if (data.find_first_not_of(VALID_CHARS)<data.size()) else if (data.find_first_not_of(VALID_CHARS)<data.size())
return hexTxt(data); return hexTxt(data, len);
else else
return "\""+data+"\""; return "\""+data+"\"";
} }

@ -277,9 +277,9 @@ namespace cryptoki {
// //! Map Attribute Class to type // //! Map Attribute Class to type
// /*! @todo to be completed ... */ // /*! @todo to be completed ... */
// #define CRYPTOKI_DECLARE_ATTR(ATTR_ID, TYPE) \ // #define CRYPTOKI_DECLARE_ATTR(ATTR_ID, TYPE) \//
// template<> class AttributeType<ATTR_ID> { \ // template<> class AttributeType<ATTR_ID> { \//
// public: typedef TYPE Type; \ // public: typedef TYPE Type; \//
// } // }
// template<CK_ATTRIBUTE_TYPE Attribute> class AttributeType {}; // template<CK_ATTRIBUTE_TYPE Attribute> class AttributeType {};
// CRYPTOKI_DECLARE_ATTR(CKA_CLASS, CK_OBJECT_CLASS); // CRYPTOKI_DECLARE_ATTR(CKA_CLASS, CK_OBJECT_CLASS);
@ -611,6 +611,8 @@ namespace cryptoki {
/// Load Cryptoki Library for use with Smart Card. /// Load Cryptoki Library for use with Smart Card.
class Library { class Library {
friend class Slot;
public: public:
//! Initialize for a given library (default cryptoki) //! Initialize for a given library (default cryptoki)
@ -623,6 +625,12 @@ namespace cryptoki {
_init(library, exc) { _init(library, exc) {
CRYPTOLOG("log"); CRYPTOLOG("log");
} }
protected:
Library() {
CRYPTOLOG("log");
}
public: public:
@ -778,13 +786,27 @@ namespace cryptoki {
CRYPTOLOG("ID="<<_slot); CRYPTOLOG("ID="<<_slot);
} }
Slot(): _slot(0), _res(-1) {
CRYPTOLOG("ID="<<_slot);
}
Slot& operator=(const Slot& o) {
_library = o._library;
_slot = o._slot;
_res = o._res;
CRYPTOLOG("ID="<<_slot);
return *this;
}
bool check(CK_RV result, const std::string& context="") { bool check(CK_RV result, const std::string& context="") {
_res = result; _res = result;
if (_library.exc() && !*this) if (_library.exc() && !*this) {
if (!context.empty()) if (!context.empty()) {
throw access_error(context+": "+error()); throw access_error(context+": "+error());
else } else {
throw access_error(error()); throw access_error(error());
}
}
return _res==CKR_OK; return _res==CKR_OK;
} }
@ -940,11 +962,13 @@ namespace cryptoki {
bool check(CK_RV result, const std::string& context="") { bool check(CK_RV result, const std::string& context="") {
_res = result; _res = result;
if (_slot._library.exc() && !*this) if (_slot._library.exc() && !*this) {
if (!context.empty()) if (!context.empty()) {
throw access_error(context+": "+error()); throw access_error(context+": "+error());
else } else {
throw access_error(error()); throw access_error(error());
}
}
return _res==CKR_OK; return _res==CKR_OK;
} }
@ -1343,11 +1367,13 @@ namespace cryptoki {
bool check(CK_RV result, const std::string& context="") { bool check(CK_RV result, const std::string& context="") {
_res = result; _res = result;
if (_session._slot._library.exc() && !*this) if (_session._slot._library.exc() && !*this) {
if (!context.empty()) if (!context.empty()) {
throw access_error(context+": "+error()); throw access_error(context+": "+error());
else } else {
throw access_error(error()); throw access_error(error());
}
}
return _res==CKR_OK; return _res==CKR_OK;
} }

@ -1282,7 +1282,7 @@ namespace openssl {
operator bool() const { operator bool() const {
CRYPTOLOG("log"); CRYPTOLOG("log");
return _bio>0; return _bio;
} }
TCP& operator>>(std::string& s) { TCP& operator>>(std::string& s) {
@ -1302,7 +1302,7 @@ namespace openssl {
open? */ open? */
std::string read() { std::string read() {
CRYPTOLOG("log"); CRYPTOLOG("log");
if (_bio<=0) throw tcp_closed_connection(); if (!_bio) throw tcp_closed_connection();
const int BUFF_SZ(1024); const int BUFF_SZ(1024);
char buff[BUFF_SZ]; char buff[BUFF_SZ];
int x(BIO_read(_bio, buff, BUFF_SZ)); int x(BIO_read(_bio, buff, BUFF_SZ));
@ -1319,7 +1319,7 @@ namespace openssl {
TCP& write(const std::string& s) { TCP& write(const std::string& s) {
CRYPTOLOG("log"); CRYPTOLOG("log");
if (_bio<=0) throw tcp_closed_connection(); if (!_bio) throw tcp_closed_connection();
unsigned int x(BIO_write(_bio, s.begin().operator->(), s.size())); unsigned int x(BIO_write(_bio, s.begin().operator->(), s.size()));
if (x<=0) if (x<=0)
if (BIO_should_retry(_bio)) return write(s); if (BIO_should_retry(_bio)) return write(s);
@ -1333,7 +1333,7 @@ namespace openssl {
virtual TCP& close() { virtual TCP& close() {
CRYPTOLOG("log"); CRYPTOLOG("log");
if (_bio>0) BIO_free_all(_bio); if (_bio) BIO_free_all(_bio);
_bio = 0; _bio = 0;
return *this; return *this;
} }

@ -490,13 +490,26 @@ namespace pcsc {
- @c false: no exceptions, check your instance after each - @c false: no exceptions, check your instance after each
operation */ operation */
Connection(Scope s=USER, bool exceptions=true): Connection(Scope s=USER, bool exceptions=true):
_connectionlifetime(new ConnectionLifetime(s, exceptions)) { _connectionlifetime(connectionlifetime(s, exceptions)) {
++connectionlifetimecounter();
CRYPTOLOG("Connection Counter is now: "<<connectionlifetimecounter());
check("establish smartcard context"); check("establish smartcard context");
} }
Connection(const Connection& o) {
++connectionlifetimecounter();
*this = o;
}
//! Closes the connection (releases the smartcard context) //! Closes the connection (releases the smartcard context)
~Connection() { ~Connection() {
// connection is closed, when last _connectionlifetime is destructed // connection is closed, when _connectionlifetime is destructed
if (--connectionlifetimecounter()==0) {
CRYPTOLOG("Delete Connection");
delete connectionlifetime();
connectionlifetime()=0;
}
CRYPTOLOG("Connection Counter is now: "<<connectionlifetimecounter());
} }
//! Scans for available readers from a specified list of groups. //! Scans for available readers from a specified list of groups.
@ -529,17 +542,15 @@ namespace pcsc {
/*! First use scan() to get a list of readers, then open a /*! First use scan() to get a list of readers, then open a
connection to the reader, then access it. */ connection to the reader, then access it. */
mrw::Shared<Reader> reader(const std::string& name) { mrw::Shared<Reader> reader(const std::string& name) {
if (_readers.find(name)==_readers.end()) return _connectionlifetime->reader(name, this);
_readers.insert(std::make_pair(name, new Reader(name, *this)));
return _readers.find(name)->second;
} }
//! Close connection of a named reader. // //! Close connection of a named reader.
/*! If you access the same reader through raeder() later, the // /*! If you access the same reader through raeder() later, the
connection will be reestablished. */ // connection will be reestablished. */
void close(const std::string& s) { // void close(const std::string& s) {
} // }
//! Find all readers with a given ATR. //! Find all readers with a given ATR.
/*! @param atr full or partial ATR to match to the reader's ATR /*! @param atr full or partial ATR to match to the reader's ATR
@ -638,17 +649,21 @@ namespace pcsc {
/*! @throw access_error if it is instanciated for exceptions and /*! @throw access_error if it is instanciated for exceptions and
an error occured in the last command. */ an error occured in the last command. */
bool check(const std::string& context="") { bool check(const std::string& context="") {
if (_exc&&!*this) if (_exc&&!*this) {
if (context.size()) if (context.size()) {
if (_state==SCARD_W_WRONG_CHV) if (_state==SCARD_W_WRONG_CHV) {
throw wrong_pin(context+": "+error()); throw wrong_pin(context+": "+error());
else } else {
throw access_error(context+": "+error()); throw access_error(context+": "+error());
else }
if (_state==SCARD_W_WRONG_CHV) } else {
if (_state==SCARD_W_WRONG_CHV) {
throw wrong_pin(error()); throw wrong_pin(error());
else } else {
throw access_error(error()); throw access_error(error());
}
}
}
return *this; return *this;
} }
@ -906,23 +921,47 @@ namespace pcsc {
return _exc; return _exc;
} }
//! Get a reader, open a connection if not already open.
/*! First use scan() to get a list of readers, then open a
connection to the reader, then access it. */
mrw::Shared<Reader> reader(const std::string& name, Connection* c) {
CRYPTOLOG("get reader: "<<name<<" from "<<(void*)&_readers);
if (_readers.find(name)==_readers.end())
_readers.insert(std::make_pair(name, new Reader(name, *c)));
return _readers.find(name)->second;
}
private: private:
bool _exc; bool _exc;
SCARDCONTEXT _id; SCARDCONTEXT _id;
long _state; long _state;
};
//! Readers are closed when the last shared object is destructed
//! Readers are closed when the last shared object is destructed std::map<std::string, mrw::Shared<Reader> > _readers;
std::map<std::string, mrw::Shared<Reader> > _readers; };
//! Connection is closed when the last shared object is destructed //! Connection is closed when the last shared object is destructed
/*! Handling the connection lifetime in a separate shared object /*! Handling the connection lifetime in a separate shared object
allows to copy connections and still make sure, that the allows to copy connections and still make sure, that the
lifetime of the connection is as long as all copied opbjects lifetime of the connection is as long as all copied opbjects
live. */ live. */
mrw::Shared<ConnectionLifetime> _connectionlifetime; static ConnectionLifetime*&
connectionlifetime(Scope s=USER, bool exc=true) {
static ConnectionLifetime* instance(0);
if (instance==0) {
CRYPTOLOG("New Connection");
instance = new ConnectionLifetime(s, exc);
}
return instance;
}
static int& connectionlifetimecounter() {
static int instance(0);
return instance;
}
ConnectionLifetime* _connectionlifetime;
}; };

Loading…
Cancel
Save