bug fixes and reference counters (prevents hanging); refs #28
This commit is contained in:
@@ -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)
|
||||||
@@ -624,6 +626,12 @@ namespace cryptoki {
|
|||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
Library() {
|
||||||
|
CRYPTOLOG("log");
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
class Init {
|
class Init {
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
83
src/pcsc.hxx
83
src/pcsc.hxx
@@ -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
|
||||||
|
std::map<std::string, mrw::Shared<Reader> > _readers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//! 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
|
//! 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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user