From 50647d461b6d03e814ca375c40d8747cd8c6ec05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=A4ckerlin?= Date: Mon, 11 Nov 2013 11:49:09 +0000 Subject: [PATCH] bug fixes and reference counters (prevents hanging); refs #28 --- src/cardos.hxx | 2 +- src/cryptaux.hxx | 2 +- src/cryptoki.hxx | 50 ++++++++++++++++++++++------- src/openssl.hxx | 8 ++--- src/pcsc.hxx | 83 +++++++++++++++++++++++++++++++++++------------- 5 files changed, 105 insertions(+), 40 deletions(-) diff --git a/src/cardos.hxx b/src/cardos.hxx index 7f8045f..569a9f3 100644 --- a/src/cardos.hxx +++ b/src/cardos.hxx @@ -170,7 +170,7 @@ namespace cardos { _tag = content[0]; _length = content[1]; _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" " small: \""+crypto::binToHex(_value)+"\""); if (tagType()==END_OF_CONTENT) return; // done diff --git a/src/cryptaux.hxx b/src/cryptaux.hxx index 318184c..307911e 100644 --- a/src/cryptaux.hxx +++ b/src/cryptaux.hxx @@ -114,7 +114,7 @@ namespace crypto { if (!data.size()) return ""; else if (data.find_first_not_of(VALID_CHARS) class AttributeType { \ -// public: typedef TYPE Type; \ +// #define CRYPTOKI_DECLARE_ATTR(ATTR_ID, TYPE) \// +// template<> class AttributeType { \// +// public: typedef TYPE Type; \// // } // template class AttributeType {}; // CRYPTOKI_DECLARE_ATTR(CKA_CLASS, CK_OBJECT_CLASS); @@ -611,6 +611,8 @@ namespace cryptoki { /// Load Cryptoki Library for use with Smart Card. class Library { + friend class Slot; + public: //! Initialize for a given library (default cryptoki) @@ -623,6 +625,12 @@ namespace cryptoki { _init(library, exc) { CRYPTOLOG("log"); } + + protected: + + Library() { + CRYPTOLOG("log"); + } public: @@ -778,13 +786,27 @@ namespace cryptoki { 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="") { _res = result; - if (_library.exc() && !*this) - if (!context.empty()) + if (_library.exc() && !*this) { + if (!context.empty()) { throw access_error(context+": "+error()); - else + } else { throw access_error(error()); + } + } return _res==CKR_OK; } @@ -940,11 +962,13 @@ namespace cryptoki { bool check(CK_RV result, const std::string& context="") { _res = result; - if (_slot._library.exc() && !*this) - if (!context.empty()) + if (_slot._library.exc() && !*this) { + if (!context.empty()) { throw access_error(context+": "+error()); - else + } else { throw access_error(error()); + } + } return _res==CKR_OK; } @@ -1343,11 +1367,13 @@ namespace cryptoki { bool check(CK_RV result, const std::string& context="") { _res = result; - if (_session._slot._library.exc() && !*this) - if (!context.empty()) + if (_session._slot._library.exc() && !*this) { + if (!context.empty()) { throw access_error(context+": "+error()); - else + } else { throw access_error(error()); + } + } return _res==CKR_OK; } diff --git a/src/openssl.hxx b/src/openssl.hxx index a026363..d23a8cd 100644 --- a/src/openssl.hxx +++ b/src/openssl.hxx @@ -1282,7 +1282,7 @@ namespace openssl { operator bool() const { CRYPTOLOG("log"); - return _bio>0; + return _bio; } TCP& operator>>(std::string& s) { @@ -1302,7 +1302,7 @@ namespace openssl { open? */ std::string read() { CRYPTOLOG("log"); - if (_bio<=0) throw tcp_closed_connection(); + if (!_bio) throw tcp_closed_connection(); const int BUFF_SZ(1024); char buff[BUFF_SZ]; int x(BIO_read(_bio, buff, BUFF_SZ)); @@ -1319,7 +1319,7 @@ namespace openssl { TCP& write(const std::string& s) { 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())); if (x<=0) if (BIO_should_retry(_bio)) return write(s); @@ -1333,7 +1333,7 @@ namespace openssl { virtual TCP& close() { CRYPTOLOG("log"); - if (_bio>0) BIO_free_all(_bio); + if (_bio) BIO_free_all(_bio); _bio = 0; return *this; } diff --git a/src/pcsc.hxx b/src/pcsc.hxx index 58eec68..83026fd 100644 --- a/src/pcsc.hxx +++ b/src/pcsc.hxx @@ -490,13 +490,26 @@ namespace pcsc { - @c false: no exceptions, check your instance after each operation */ Connection(Scope s=USER, bool exceptions=true): - _connectionlifetime(new ConnectionLifetime(s, exceptions)) { + _connectionlifetime(connectionlifetime(s, exceptions)) { + ++connectionlifetimecounter(); + CRYPTOLOG("Connection Counter is now: "< reader(const std::string& name) { - if (_readers.find(name)==_readers.end()) - _readers.insert(std::make_pair(name, new Reader(name, *this))); - return _readers.find(name)->second; + return _connectionlifetime->reader(name, this); } - //! Close connection of a named reader. - /*! If you access the same reader through raeder() later, the - connection will be reestablished. */ - void close(const std::string& s) { + // //! Close connection of a named reader. + // /*! If you access the same reader through raeder() later, the + // connection will be reestablished. */ + // void close(const std::string& s) { - } + // } //! Find all readers with a given 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 an error occured in the last command. */ bool check(const std::string& context="") { - if (_exc&&!*this) - if (context.size()) - if (_state==SCARD_W_WRONG_CHV) + if (_exc&&!*this) { + if (context.size()) { + if (_state==SCARD_W_WRONG_CHV) { throw wrong_pin(context+": "+error()); - else + } else { throw access_error(context+": "+error()); - else - if (_state==SCARD_W_WRONG_CHV) + } + } else { + if (_state==SCARD_W_WRONG_CHV) { throw wrong_pin(error()); - else + } else { throw access_error(error()); + } + } + } return *this; } @@ -906,23 +921,47 @@ namespace pcsc { 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(const std::string& name, Connection* c) { + CRYPTOLOG("get reader: "<second; + } + private: bool _exc; SCARDCONTEXT _id; long _state; - }; - - //! Readers are closed when the last shared object is destructed - std::map > _readers; + //! Readers are closed when the last shared object is destructed + std::map > _readers; + }; //! Connection is closed when the last shared object is destructed /*! Handling the connection lifetime in a separate shared object allows to copy connections and still make sure, that the lifetime of the connection is as long as all copied opbjects live. */ - mrw::Shared _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; };