bug fixes and reference counters (prevents hanging); refs #28
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
79
src/pcsc.hxx
79
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: "<<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;
|
||||
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user