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. 79
      src/pcsc.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

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

@ -277,9 +277,9 @@ namespace cryptoki {
// //! Map Attribute Class to type
// /*! @todo to be completed ... */
// #define CRYPTOKI_DECLARE_ATTR(ATTR_ID, TYPE) \
// template<> class AttributeType<ATTR_ID> { \
// public: typedef TYPE Type; \
// #define CRYPTOKI_DECLARE_ATTR(ATTR_ID, TYPE) \//
// template<> class AttributeType<ATTR_ID> { \//
// public: typedef TYPE Type; \//
// }
// template<CK_ATTRIBUTE_TYPE Attribute> 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)
@ -624,6 +626,12 @@ namespace cryptoki {
CRYPTOLOG("log");
}
protected:
Library() {
CRYPTOLOG("log");
}
public:
class Init {
@ -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;
}

@ -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;
}

@ -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: "<<connectionlifetimecounter());
check("establish smartcard context");
}
Connection(const Connection& o) {
++connectionlifetimecounter();
*this = o;
}
//! Closes the connection (releases the smartcard context)
~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.
@ -529,17 +542,15 @@ namespace pcsc {
/*! 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) {
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> 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:
bool _exc;
SCARDCONTEXT _id;
long _state;
};
//! Readers are closed when the last shared object is destructed
std::map<std::string, mrw::Shared<Reader> > _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> _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