| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  | /*! @file
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This file offers a C++ access to the PCSC library. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @id $Id$ | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | //       1         2         3         4         5         6         7         8
 | 
					
						
							|  |  |  | // 45678901234567890123456789012345678901234567890123456789012345678901234567890
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef PCSC_HXX
 | 
					
						
							|  |  |  | #define PCSC_HXX
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-14 13:31:27 +00:00
										 |  |  | #ifndef PCSC_LOG
 | 
					
						
							|  |  |  | //! Declare PCSC_LOG before #include in your code, if you want logging.
 | 
					
						
							|  |  |  | /*! PCSC_LOG passes its argument to a stream, so your definition must
 | 
					
						
							|  |  |  |     behave so that the argument can be streamed. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Example, use std::log: | 
					
						
							|  |  |  |     @code | 
					
						
							|  |  |  |     #define PCSC_LOG(x) std::clog<<x<<" ("<<__PRETTY_FUNCTION__<<')'<<std::endl
 | 
					
						
							|  |  |  |     #include <pcsc.hxx>
 | 
					
						
							|  |  |  |     @endcode | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     Example, use qDebug(): | 
					
						
							|  |  |  |     @code | 
					
						
							|  |  |  |     #define PCSC_LOG(x) qDebug()<<x
 | 
					
						
							|  |  |  |     #include <pcsc.hxx>
 | 
					
						
							|  |  |  |     @endcode */ | 
					
						
							|  |  |  | #define PCSC_LOG(x) // if unset, do nothing
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-21 07:43:32 +00:00
										 |  |  | #include <cryptaux.hxx>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  | #include <string>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  | #ifdef WIN32
 | 
					
						
							| 
									
										
										
										
											2009-10-21 08:52:04 +00:00
										 |  |  |   #undef UNICODE
 | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  |   #include <WinSCard.h>
 | 
					
						
							| 
									
										
										
										
											2009-10-21 08:52:04 +00:00
										 |  |  |   #undef ERROR
 | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |   #ifndef MAX_ATR_SIZE
 | 
					
						
							|  |  |  |     #define MAX_ATR_SIZE 33
 | 
					
						
							|  |  |  |   #endif
 | 
					
						
							| 
									
										
										
										
											2009-08-19 13:42:45 +00:00
										 |  |  |   namespace pcsc { | 
					
						
							| 
									
										
										
										
											2010-08-03 13:48:47 +00:00
										 |  |  |      | 
					
						
							| 
									
										
										
										
											2009-10-21 08:52:04 +00:00
										 |  |  |     #ifdef UNICODE
 | 
					
						
							|  |  |  |       inline std::wstring strconv(std::string s) { | 
					
						
							|  |  |  |         return std::wstring(s.begin(), s.end()); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       inline std::string strconv(std::wstring s) { | 
					
						
							|  |  |  |         return std::string(s.begin(), s.end()); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       typedef wchar_t char_t; | 
					
						
							|  |  |  |       typedef std::wstring string; | 
					
						
							|  |  |  |     #else
 | 
					
						
							|  |  |  |       inline const std::string& strconv(const std::string& s) { | 
					
						
							|  |  |  |         return s; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       typedef char char_t; | 
					
						
							|  |  |  |       typedef std::string string; | 
					
						
							|  |  |  |     #endif
 | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |   #include <PCSC/pcsclite.h>
 | 
					
						
							|  |  |  |   #include <PCSC/wintypes.h>
 | 
					
						
							| 
									
										
										
										
											2009-08-19 13:42:45 +00:00
										 |  |  |   #include <PCSC/winscard.h>
 | 
					
						
							|  |  |  |   namespace pcsc { | 
					
						
							| 
									
										
										
										
											2009-10-07 07:22:20 +00:00
										 |  |  |     inline const std::string& strconv(const std::string& s) { | 
					
						
							| 
									
										
										
										
											2009-08-19 13:42:45 +00:00
										 |  |  |       return s; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     typedef char char_t; | 
					
						
							|  |  |  |     typedef std::string string; | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |   } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <boost/shared_ptr.hpp>
 | 
					
						
							|  |  |  | #include <vector>
 | 
					
						
							|  |  |  | #include <map>
 | 
					
						
							|  |  |  | #include <memory>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-03 13:48:47 +00:00
										 |  |  | namespace pcsc { | 
					
						
							|  |  |  |   std::string version(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  | #include <sstream>
 | 
					
						
							|  |  |  | #include <iomanip>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-18 11:41:30 +00:00
										 |  |  | /*! @defgroup gpcsc C++ Wrapper around pcsc-lite API
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     This library is a C++ wrapper to the awful pcsc-lite interface. | 
					
						
							|  |  |  |     The reason for this wrapper is to get a nice object oriented | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |     interface written in C++ manner and using standard types and so to | 
					
						
							|  |  |  |     avoid the ugly M$-C-quirks. This interface is memory clean. | 
					
						
							|  |  |  |     @todo: Not implemented, not supported: | 
					
						
							|  |  |  |         - SCardGetStatusChange(hContext, 0, rgReaderStates, 1); | 
					
						
							|  |  |  |         - SCardReconnect(hCard, SCARD_SHARE_SHARED, | 
					
						
							|  |  |  |                          SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, | 
					
						
							|  |  |  |                          SCARD_LEAVE_CARD, | 
					
						
							|  |  |  |                          &dwActiveProtocol); | 
					
						
							|  |  |  |         - several other | 
					
						
							|  |  |  |     I do not need these, and I don't know the usecase where they are | 
					
						
							|  |  |  |     required.  If you need something that is not yet supported, please | 
					
						
							|  |  |  |     let me know, what you need and why. Then I'll add it so that it | 
					
						
							|  |  |  |     best fits the common needs. */ | 
					
						
							| 
									
										
										
										
											2009-09-18 11:41:30 +00:00
										 |  |  | //@{
 | 
					
						
							|  |  |  | /*! @defgroup pcsclib PCSC C++ Library */ | 
					
						
							|  |  |  | /*! @defgroup pcscexceptions PCSC Exceptions */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //! @see gpcsc
 | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  | namespace pcsc { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   //============================================================================
 | 
					
						
							| 
									
										
										
										
											2009-09-29 07:24:04 +00:00
										 |  |  |   //! @addtogroup pcscexceptions
 | 
					
						
							| 
									
										
										
										
											2009-09-18 11:41:30 +00:00
										 |  |  |   //@{
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   //----------------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |   class exception: public std::exception { | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  |       exception(const std::string& reason) throw(): _what("pcsc: "+reason) {} | 
					
						
							|  |  |  |       ~exception() throw() {} | 
					
						
							|  |  |  |       const char* what() const throw() { | 
					
						
							|  |  |  |         return _what.c_str(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |       std::string _what; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   //----------------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2009-07-09 12:28:10 +00:00
										 |  |  |   class not_implemented: public exception { | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |     public: | 
					
						
							|  |  |  |       not_implemented(const std::string& reason) throw(): | 
					
						
							|  |  |  |           exception("feature is not implemented:\n"+reason) { | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  |   //----------------------------------------------------------------------------
 | 
					
						
							| 
									
										
										
										
											2009-07-09 12:28:10 +00:00
										 |  |  |   class access_error: public exception { | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |     public: | 
					
						
							|  |  |  |       access_error(const std::string& reason) throw(): | 
					
						
							|  |  |  |           exception("smardcard access error:\n"+reason) { | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2009-10-07 07:22:20 +00:00
										 |  |  |   //----------------------------------------------------------------------------
 | 
					
						
							|  |  |  |   class runtime_error: public exception { | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  |       runtime_error(const std::string& reason, const std::string& data) throw(): | 
					
						
							|  |  |  |           exception("runtime error,\n"+reason+":\n"+crypto::hex(data)) {} | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2010-09-27 06:53:25 +00:00
										 |  |  |   //----------------------------------------------------------------------------
 | 
					
						
							|  |  |  |   class neesting_error: public exception { | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  |       neesting_error() throw(): | 
					
						
							|  |  |  |           exception("neesting error: more endTransaction than beginTransaction") | 
					
						
							|  |  |  |       {} | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2009-09-18 11:41:30 +00:00
										 |  |  |   //@}
 | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-18 11:41:30 +00:00
										 |  |  |   //! @addtogroup pcsclib
 | 
					
						
							|  |  |  |   //@{
 | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |   //============================================================================
 | 
					
						
							|  |  |  |   class Connection { | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       //...............................................................typedefs
 | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //------------------------------------------------------------------Reader
 | 
					
						
							|  |  |  |       friend class Reader; | 
					
						
							|  |  |  |       class Reader { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //............................................................typedefs
 | 
					
						
							|  |  |  |         public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           friend class Transaction; | 
					
						
							|  |  |  |           //! Scoped transaction.
 | 
					
						
							|  |  |  |           /*! This is a scoped transaction. That means, the
 | 
					
						
							| 
									
										
										
										
											2010-09-27 06:53:25 +00:00
										 |  |  |               transaction is started in the constructor and ended in | 
					
						
							|  |  |  |               the destructor, unless it is already ended before.  In | 
					
						
							|  |  |  |               case of an exception or leaving the block, the | 
					
						
							|  |  |  |               transaction is always cleaned up. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |               There's a neesting counter to make sure, transaction is | 
					
						
							|  |  |  |               started only once and ended only once, even though the | 
					
						
							|  |  |  |               locking can be neested. | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |               @code | 
					
						
							|  |  |  |               pcsc::Connection c; | 
					
						
							|  |  |  |               { | 
					
						
							|  |  |  |               Transaction t(c.reader("name")); | 
					
						
							|  |  |  |               [...] // do some stuff, possible exceptions thrown
 | 
					
						
							| 
									
										
										
										
											2010-09-27 06:53:25 +00:00
										 |  |  |               if (problem) return; // automatically ended
 | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |               [...] | 
					
						
							| 
									
										
										
										
											2010-09-27 06:53:25 +00:00
										 |  |  |               t.end(); // ended if we reach this line
 | 
					
						
							|  |  |  |               [...] | 
					
						
							|  |  |  |               } // also ended, unless commit reaced
 | 
					
						
							|  |  |  |               @endcode */ | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           class Transaction { | 
					
						
							|  |  |  |             public: | 
					
						
							|  |  |  |               //! Begins a transaction.
 | 
					
						
							|  |  |  |               /*! @note Please note that the Reader is required in the
 | 
					
						
							|  |  |  |                   destructor und must therefore live longer than the | 
					
						
							|  |  |  |                   Transaction instance. */ | 
					
						
							|  |  |  |               Transaction(Reader& r): _reader(r), _running(true) { | 
					
						
							|  |  |  |                 _reader.beginTransaction(); | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               //! Cancels the transaction if not yet finished.
 | 
					
						
							|  |  |  |               ~Transaction() try { | 
					
						
							| 
									
										
										
										
											2010-09-27 06:53:25 +00:00
										 |  |  |                 end(); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |               } catch (...) { | 
					
						
							|  |  |  |                 if (!std::uncaught_exception()) throw; | 
					
						
							|  |  |  |               } | 
					
						
							| 
									
										
										
										
											2010-09-27 06:53:25 +00:00
										 |  |  |               //! Ends the running transaction.
 | 
					
						
							|  |  |  |               void end() { | 
					
						
							|  |  |  |                 if (_running) _reader.endTransaction(); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |                 _running = false; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |             private: | 
					
						
							|  |  |  |               Reader& _reader; | 
					
						
							|  |  |  |               bool _running; | 
					
						
							|  |  |  |           }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //! State and attribute list of a reader.
 | 
					
						
							|  |  |  |           class Status { | 
					
						
							|  |  |  |             public: | 
					
						
							| 
									
										
										
										
											2009-10-07 07:22:20 +00:00
										 |  |  |               Status(unsigned long s, const std::string& a): state(s), atr(a) {} | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |               const unsigned long state; | 
					
						
							| 
									
										
										
										
											2009-10-07 07:22:20 +00:00
										 |  |  |               const std::string atr; | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           }; | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |           //.............................................................methods
 | 
					
						
							|  |  |  |         public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //! Disconnects connection.
 | 
					
						
							|  |  |  |           ~Reader() { | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  |             _state = SCardDisconnect(_id, SCARD_RESET_CARD); | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             if (!std::uncaught_exception()) | 
					
						
							|  |  |  |               _connection.check("disconnect smartcard"); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //! Get reader status.
 | 
					
						
							|  |  |  |           Status status() { | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |             DWORD dummy(0); | 
					
						
							|  |  |  |             DWORD s; | 
					
						
							| 
									
										
										
										
											2011-03-29 12:54:00 +00:00
										 |  |  |             DWORD len(MAX_ATR_SIZE); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |             unsigned char a[len]; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             check(SCardStatus(_id, 0, &dummy, &s, &_protocol, a, &len), | 
					
						
							|  |  |  |                   "query smartcard status"); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |             return Status(s, std::string((char*)a, len)); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //! Transmit data to reader.
 | 
					
						
							| 
									
										
										
										
											2009-10-07 07:22:20 +00:00
										 |  |  |           /*! @note Take care: Stings may contain embedded @c 0. */ | 
					
						
							|  |  |  |           std::string transmit(char cla, char ins, char p1, char p2, | 
					
						
							|  |  |  |                                const std::string& lc = std::string(), | 
					
						
							|  |  |  |                                unsigned char le = 253) { | 
					
						
							|  |  |  |             std::string claInsP1P2; | 
					
						
							|  |  |  |             claInsP1P2.push_back(cla); | 
					
						
							|  |  |  |             claInsP1P2.push_back(ins); | 
					
						
							|  |  |  |             claInsP1P2.push_back(p1); | 
					
						
							|  |  |  |             claInsP1P2.push_back(p2); | 
					
						
							|  |  |  |             assert(claInsP1P2.size()==4); | 
					
						
							|  |  |  |             return transmit(claInsP1P2, lc, le); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2009-10-14 13:31:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |           //! Transmit data to reader.
 | 
					
						
							|  |  |  |           /*! @note Take care: Stings may contain embedded @c 0. */ | 
					
						
							|  |  |  |           std::string transmit(char cla, char ins, char p1, char p2, | 
					
						
							|  |  |  |                                unsigned char le) { | 
					
						
							|  |  |  |             std::string claInsP1P2; | 
					
						
							|  |  |  |             claInsP1P2.push_back(cla); | 
					
						
							|  |  |  |             claInsP1P2.push_back(ins); | 
					
						
							|  |  |  |             claInsP1P2.push_back(p1); | 
					
						
							|  |  |  |             claInsP1P2.push_back(p2); | 
					
						
							|  |  |  |             assert(claInsP1P2.size()==4); | 
					
						
							|  |  |  |             return transmit(claInsP1P2, std::string(), le); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2009-10-07 07:22:20 +00:00
										 |  |  |            | 
					
						
							|  |  |  |           //! Transmit data to reader.
 | 
					
						
							|  |  |  |           /*! @note Take care: Stings may contain embedded @c 0. */ | 
					
						
							|  |  |  |           std::string transmit(char cla, char ins, char p1, char p2, | 
					
						
							|  |  |  |                                const char* lc, int len, | 
					
						
							|  |  |  |                                unsigned char le = 253) { | 
					
						
							|  |  |  |             std::string claInsP1P2; | 
					
						
							|  |  |  |             claInsP1P2.push_back(cla); | 
					
						
							|  |  |  |             claInsP1P2.push_back(ins); | 
					
						
							|  |  |  |             claInsP1P2.push_back(p1); | 
					
						
							|  |  |  |             claInsP1P2.push_back(p2); | 
					
						
							|  |  |  |             assert(claInsP1P2.size()==4); | 
					
						
							|  |  |  |             return transmit(claInsP1P2, std::string(lc, len), le); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |            | 
					
						
							|  |  |  |           //! Transmit data to reader.
 | 
					
						
							|  |  |  |           /*! @note Take care: Stings may contain embedded @c 0.
 | 
					
						
							|  |  |  |               @note Prefer the transmit methods that passes @c cla, @c | 
					
						
							|  |  |  |                     ins, @c p1 and @c p2 separate.*/ | 
					
						
							|  |  |  |           std::string transmit(const std::string& claInsP1P2, | 
					
						
							|  |  |  |                                const std::string& lc, | 
					
						
							|  |  |  |                                unsigned char le = 253) { | 
					
						
							|  |  |  |             if (claInsP1P2.size()!=4) | 
					
						
							|  |  |  |               throw runtime_error("transmit: claInsP1P2 must be 4 byte", | 
					
						
							|  |  |  |                                   claInsP1P2); | 
					
						
							|  |  |  |             if (lc.size()>255) throw runtime_error("transmit: lc too long", lc); | 
					
						
							|  |  |  |             std::string msg(claInsP1P2); | 
					
						
							|  |  |  |             if (lc.size()) (msg+=(char)lc.size())+=lc; | 
					
						
							|  |  |  |             msg+=le; | 
					
						
							|  |  |  |             return transmit(msg); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |            | 
					
						
							|  |  |  |           //! Transmit data to reader.
 | 
					
						
							|  |  |  |           /*! @note Take care: Stings may contain embedded @c 0.
 | 
					
						
							|  |  |  |               @note Prefer the transmit methods that passes @c cla, @c | 
					
						
							|  |  |  |                     ins, @c p1 and @c p2 separate.*/ | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           std::string transmit(std::string in) { | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |             DWORD len(1024); // arbitrary
 | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |             unsigned char buff[len]; | 
					
						
							|  |  |  |             SCARD_IO_REQUEST rPci; | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  |             rPci.dwProtocol  = pci()->dwProtocol; | 
					
						
							|  |  |  |             rPci.cbPciLength = sizeof(rPci); | 
					
						
							| 
									
										
										
										
											2009-10-14 13:31:27 +00:00
										 |  |  |             PCSC_LOG("SCardTransmit: "<<crypto::hex(in)); | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  |             check(SCardTransmit(_id, &rPci, | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |                                 (unsigned char*)in.c_str(), in.size(), | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  |                                 0, buff, &len), | 
					
						
							| 
									
										
										
										
											2009-09-21 07:43:32 +00:00
										 |  |  |                   "smartcard transmit message "+crypto::hex(in)); | 
					
						
							| 
									
										
										
										
											2009-10-14 13:31:27 +00:00
										 |  |  |             PCSC_LOG(" -> "<<crypto::hex(std::string((char*)buff, len))); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |             return std::string((char*)buff, len); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //! @c false if last operation was not successful
 | 
					
						
							|  |  |  |           operator bool() const { | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |             //  Values are 32 bit values layed out as follows:
 | 
					
						
							|  |  |  |             //   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
 | 
					
						
							|  |  |  |             //   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
 | 
					
						
							|  |  |  |             //   ---+-+-+-----------------------+-------------------------------
 | 
					
						
							|  |  |  |             //   Sev|C|R|     Facility          |               Code            
 | 
					
						
							|  |  |  |             //   ---+-+-+-----------------------+-------------------------------
 | 
					
						
							|  |  |  |             //  where Sev - is the severity code
 | 
					
						
							|  |  |  |             //          00 - Success
 | 
					
						
							|  |  |  |             //          01 - Informational
 | 
					
						
							|  |  |  |             //          10 - Warning
 | 
					
						
							|  |  |  |             //          11 - Error
 | 
					
						
							|  |  |  |             // So everything with Sev=00 is successful
 | 
					
						
							|  |  |  |             // theoretically even with Sev=01, but that's still rejected
 | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  |             //return (_state>>30&3)==0;
 | 
					
						
							|  |  |  |             return _state==SCARD_S_SUCCESS; | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           } | 
					
						
							|  |  |  |            | 
					
						
							|  |  |  |           //...........................................................variables
 | 
					
						
							|  |  |  |         public: | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |           const std::string name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //.............................................................methods
 | 
					
						
							|  |  |  |         private: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //! Use scoped transactions with @ref Transaction
 | 
					
						
							| 
									
										
										
										
											2010-09-27 06:53:25 +00:00
										 |  |  |           /*! Calls @c SCardBeginTransaction unless it's already inside
 | 
					
						
							|  |  |  |               a transaction. */ | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           void beginTransaction() { | 
					
						
							| 
									
										
										
										
											2010-09-27 06:53:25 +00:00
										 |  |  |             if (++_neesting==1) | 
					
						
							|  |  |  |               check(SCardBeginTransaction(_id), "smartcard begin transaction"); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //! Use scoped transactions with @ref Transaction
 | 
					
						
							| 
									
										
										
										
											2010-09-27 06:53:25 +00:00
										 |  |  |           /*! Calls @c SCardEndTransaction if it's inside a transaction.
 | 
					
						
							|  |  |  |                | 
					
						
							|  |  |  |               @throws neesting_error if there are more calls to @c | 
					
						
							|  |  |  |               endTransaction than to @c beginTransaction. */ | 
					
						
							|  |  |  |           void endTransaction() { | 
					
						
							|  |  |  |             if (--_neesting==0) | 
					
						
							|  |  |  |               check(SCardEndTransaction(_id, SCARD_LEAVE_CARD), | 
					
						
							|  |  |  |                     "smartcard end transaction"); | 
					
						
							|  |  |  |             else if (_neesting<0) { | 
					
						
							|  |  |  |               _neesting = 0; | 
					
						
							|  |  |  |               throw neesting_error(); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           /*! @throw not_implemented if _protocol is unknown. */ | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |           const SCARD_IO_REQUEST* pci() { | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |             switch(_protocol) { | 
					
						
							|  |  |  |               case SCARD_PROTOCOL_T0: return SCARD_PCI_T0; | 
					
						
							|  |  |  |               case SCARD_PROTOCOL_T1: return SCARD_PCI_T1; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (_connection._exc) throw not_implemented("unknown protocol"); | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |            | 
					
						
							|  |  |  |           //! Sets state and throws an exception if neccessary.
 | 
					
						
							|  |  |  |           /*! @throw access_error if it is instanciated for exceptions and
 | 
					
						
							|  |  |  |               an error occured in the last command. */ | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |           bool check(long state, const std::string context="") { | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |             _state = state; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             return _connection.check(state, context); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //! Only Connection is allowed to instanciate.
 | 
					
						
							|  |  |  |           friend class Connection; | 
					
						
							|  |  |  |            | 
					
						
							|  |  |  |           //! Establishes a connection to the given named cardreader
 | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  |           Reader(const std::string& nm, Connection& c, | 
					
						
							|  |  |  |                  DWORD mode=SCARD_SHARE_SHARED, | 
					
						
							|  |  |  |                  DWORD protocol=SCARD_PROTOCOL_T1): | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |               name(nm), _connection(c) { | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |             check(SCardConnect(_connection._id, strconv(name).c_str(), | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  |                                mode, protocol, | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |                                &_id, &_protocol), | 
					
						
							| 
									
										
										
										
											2009-10-07 07:22:20 +00:00
										 |  |  |                   "connect smartcard \""+name); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //! forbidden
 | 
					
						
							|  |  |  |           Reader(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //! forbidden
 | 
					
						
							|  |  |  |           Reader(const Reader&); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           //...........................................................variables
 | 
					
						
							|  |  |  |         private: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           Connection& _connection; | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |           SCARDHANDLE _id; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |           DWORD _state; | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |           DWORD _protocol; | 
					
						
							| 
									
										
										
										
											2010-09-27 06:53:25 +00:00
										 |  |  |           static int _neesting; | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |        | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  |       //------------------------------------------------------------------Reader
 | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       enum Scope { | 
					
						
							|  |  |  |         USER     = SCARD_SCOPE_USER, | 
					
						
							|  |  |  |         TERMINAL = SCARD_SCOPE_TERMINAL, | 
					
						
							|  |  |  |         SYSTEM   = SCARD_SCOPE_SYSTEM | 
					
						
							|  |  |  |       }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       typedef std::vector<std::string> Strings; | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       //................................................................methods
 | 
					
						
							|  |  |  |     public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //! Opens a connection (establishes a smartcard context)
 | 
					
						
							|  |  |  |       /*! The errorhandling is defined with the @c exceptions flag:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           Using exceptions: | 
					
						
							|  |  |  |           @code | 
					
						
							|  |  |  |           try { | 
					
						
							|  |  |  |             pcsc::Connection c; // standard with exceptions
 | 
					
						
							|  |  |  |             pcsc::Connection::Strings r(c.scan()); | 
					
						
							|  |  |  |           } catch (std::exception& x) { | 
					
						
							|  |  |  |             std::cout<<"Error with message: "<<x.what()<<std::endl; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           @endcode | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           Without exceptions: | 
					
						
							|  |  |  |           @code | 
					
						
							|  |  |  |           pcsc::Connection c(SYSTEM, false); | 
					
						
							|  |  |  |           if (!c) std::cout<<"Error with message: "<<c.error()<<std::endl; | 
					
						
							|  |  |  |           pcsc::Connection::Strings r(c.scan()); | 
					
						
							|  |  |  |           if (!c) std::cout<<"Error with message: "<<c.error()<<std::endl; | 
					
						
							|  |  |  |           @endcode | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           Recommendation: Use exceptions! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           @param s defines the scope of the connection | 
					
						
							|  |  |  |           @param exceptions | 
					
						
							|  |  |  |             - @c true:  class throws exceptions in case of an error | 
					
						
							|  |  |  |             - @c false: no exceptions, check your instance after each | 
					
						
							|  |  |  |                         operation */ | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  |       Connection(Scope s=USER, bool exceptions=true): | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           _exc(exceptions), _id(0), | 
					
						
							|  |  |  |           _state(SCardEstablishContext(s, 0, 0, &_id)) { | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |         check("establish smartcard context"); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //! Closes the connection (releases the smartcard context)
 | 
					
						
							|  |  |  |       ~Connection() { | 
					
						
							|  |  |  |         _state = SCardReleaseContext(_id); | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |         if (!std::uncaught_exception()) check("smartcard release context"); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //! Scans for available readers from a specified list of groups.
 | 
					
						
							|  |  |  |       /*! Defaults to all groups. */ | 
					
						
							|  |  |  |       Strings scan(const Strings& groups = Strings()) { | 
					
						
							|  |  |  |         Strings res; | 
					
						
							|  |  |  |         std::string grp(join(groups)); | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |         DWORD num(0); | 
					
						
							| 
									
										
										
										
											2009-08-25 14:05:41 +00:00
										 |  |  |         if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0, 0, | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |                                     &num), | 
					
						
							| 
									
										
										
										
											2009-08-25 14:05:41 +00:00
										 |  |  |                    "smartcard get size of readers of groups "+grp)) | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           return res; | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |         std::auto_ptr<char_t> nm(new char_t[num]); | 
					
						
							| 
									
										
										
										
											2009-08-25 14:05:41 +00:00
										 |  |  |         if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0, | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |                                     nm.get(), &num), | 
					
						
							| 
									
										
										
										
											2009-08-25 14:05:41 +00:00
										 |  |  |                    "smartcard list reader names of groups "+grp)) | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |           return res; | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |         return res = split(strconv(string(nm.get(), num-1))); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //! 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. */ | 
					
						
							|  |  |  |       Reader& reader(const std::string& name) { | 
					
						
							|  |  |  |         if (_reader.find(name)==_reader.end()) | 
					
						
							|  |  |  |           _reader.insert(std::make_pair(name, new Reader(name, *this))); | 
					
						
							|  |  |  |         return *_reader.find(name)->second; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //! 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) { | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //! @c false if last operation was not successful
 | 
					
						
							|  |  |  |       operator bool() const { | 
					
						
							| 
									
										
										
										
											2009-07-16 07:23:46 +00:00
										 |  |  |         //return (_state>>30&3)==0;
 | 
					
						
							|  |  |  |         return _state==SCARD_S_SUCCESS; | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //! Get the describing text of the last error
 | 
					
						
							|  |  |  |       std::string error() const { | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |         std::stringstream ss; | 
					
						
							| 
									
										
										
										
											2009-07-13 13:51:02 +00:00
										 |  |  |         switch (_state) { | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_CANCELLED: | 
					
						
							|  |  |  |             ss<<"The action was canceled by an SCardCancel request."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_CANT_DISPOSE: | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |             ss<<"The system could not dispose of the media in the requested" | 
					
						
							|  |  |  |               <<" manner."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_CARD_UNSUPPORTED: | 
					
						
							|  |  |  |             ss<<"The smart card does not meet minimal requirements for" | 
					
						
							|  |  |  |               <<" support."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_DUPLICATE_READER: | 
					
						
							|  |  |  |             ss<<"The reader driver did not produce a unique reader name."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_INSUFFICIENT_BUFFER: | 
					
						
							|  |  |  |             ss<<"The data buffer for returned data is too small for the" | 
					
						
							|  |  |  |               <<" returned data."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_INVALID_ATR: | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |             ss<<"An ATR string obtained from the registry is not a valid" | 
					
						
							|  |  |  |               <<" ATR string."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_INVALID_HANDLE: | 
					
						
							|  |  |  |             ss<<"The supplied handle was not valid."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_INVALID_PARAMETER: | 
					
						
							|  |  |  |             ss<<"One or more of the supplied parameters could not be properly" | 
					
						
							|  |  |  |               <<" interpreted."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_INVALID_TARGET: | 
					
						
							|  |  |  |             ss<<"Registry startup information is missing or not valid."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_INVALID_VALUE: | 
					
						
							|  |  |  |             ss<<"One or more of the supplied parameters values could not" | 
					
						
							|  |  |  |               <<" be properly interpreted."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_NOT_READY: | 
					
						
							|  |  |  |             ss<<"The reader or smart card is not ready to accept commands."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_NOT_TRANSACTED: | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |             ss<<"An attempt was made to end a nonexistent transaction."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_NO_MEMORY: | 
					
						
							|  |  |  |             ss<<"Not enough memory available to complete this command."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_NO_SERVICE: | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |             ss<<"The smart card resource manager is not running."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_NO_SMARTCARD: | 
					
						
							|  |  |  |             ss<<"The operation requires a smart card, but no smart card" | 
					
						
							|  |  |  |               <<" is currently in the device."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_PCI_TOO_SMALL: | 
					
						
							|  |  |  |             ss<<"The PCI receive buffer was too small."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_PROTO_MISMATCH: | 
					
						
							|  |  |  |             ss<<"The requested protocols are incompatible with the protocol" | 
					
						
							|  |  |  |               <<" currently in use with the smart card."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_READER_UNAVAILABLE: | 
					
						
							|  |  |  |             ss<<"The specified reader is not currently available for use."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_READER_UNSUPPORTED: | 
					
						
							|  |  |  |             ss<<"The reader driver does not meet minimal requirements for" | 
					
						
							|  |  |  |               <<" support."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_SERVICE_STOPPED: | 
					
						
							|  |  |  |             ss<<"The smart card resource manager has shut down."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_SHARING_VIOLATION: | 
					
						
							|  |  |  |             ss<<"The smart card cannot be accessed because of other outstanding" | 
					
						
							|  |  |  |               <<" connections."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_SYSTEM_CANCELLED: | 
					
						
							|  |  |  |             ss<<"The action was cancelled by the system, presumably to log" | 
					
						
							|  |  |  |               <<" off or shut down."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_TIMEOUT: | 
					
						
							|  |  |  |             ss<<"The user-specified time-out value has expired."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_UNKNOWN_CARD: | 
					
						
							|  |  |  |             ss<<"The specified smart card name is not recognized."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_UNKNOWN_READER: | 
					
						
							|  |  |  |             ss<<"The specified reader name is not recognized."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_E_UNSUPPORTED_FEATURE: | 
					
						
							|  |  |  |             ss<<"This smart card does not support the requested feature."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_F_COMM_ERROR: | 
					
						
							|  |  |  |             ss<<"An internal communications error has been detected."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_F_INTERNAL_ERROR: | 
					
						
							|  |  |  |             ss<<"An internal consistency check failed."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_F_UNKNOWN_ERROR: | 
					
						
							|  |  |  |             ss<<"An internal error has been detected, but the source is" | 
					
						
							|  |  |  |               <<" unknown."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_F_WAITED_TOO_LONG: | 
					
						
							|  |  |  |             ss<<"An internal consistency timer has expired."; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_S_SUCCESS: | 
					
						
							|  |  |  |             ss<<"No error was encountered."; | 
					
						
							| 
									
										
										
										
											2009-07-13 13:51:02 +00:00
										 |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_W_REMOVED_CARD: | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |             ss<<"The smart card has been removed, so that further communication" | 
					
						
							|  |  |  |               <<" is not possible."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_W_RESET_CARD: | 
					
						
							|  |  |  |             ss<<"The smart card was reset."; | 
					
						
							| 
									
										
										
										
											2009-07-13 13:51:02 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_W_UNPOWERED_CARD: | 
					
						
							|  |  |  |             ss<<"Power has been removed from the smart card, so that" | 
					
						
							|  |  |  |               <<" further communication is not possible."; | 
					
						
							| 
									
										
										
										
											2009-07-13 13:51:02 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_W_UNRESPONSIVE_CARD: | 
					
						
							|  |  |  |             ss<<"The smart card is not responding to a reset."; | 
					
						
							| 
									
										
										
										
											2009-07-13 13:51:02 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_W_UNSUPPORTED_CARD: | 
					
						
							|  |  |  |             ss<<"The reader cannot communicate with the smart card," | 
					
						
							|  |  |  |               <<" due to ATR configuration conflicts."; | 
					
						
							| 
									
										
										
										
											2009-07-13 13:51:02 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-09-01 10:01:45 +00:00
										 |  |  | #ifndef __APPLE__
 | 
					
						
							|  |  |  |           case SCARD_E_NO_READERS_AVAILABLE: | 
					
						
							|  |  |  |             ss<<"No smart card reader is available."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-08-31 13:59:23 +00:00
										 |  |  | #ifdef WIN32
 | 
					
						
							|  |  |  |           case ERROR_BROKEN_PIPE: | 
					
						
							|  |  |  |             ss<<"The client attempted a smart card operation in a" | 
					
						
							|  |  |  |               <<" remote session, such as a client session running" | 
					
						
							|  |  |  |               <<" on a terminal server, and the operating system in" | 
					
						
							|  |  |  |               <<" use does not support smart card redirection."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_BAD_SEEK: | 
					
						
							|  |  |  |             ss<<"There was an error trying to set the smart card file" | 
					
						
							|  |  |  |               <<" object pointer."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_CERTIFICATE_UNAVAILABLE: | 
					
						
							|  |  |  |             ss<<"The requested certificate could not be obtained."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_COMM_DATA_LOST: | 
					
						
							|  |  |  |             ss<<"A communications error with the smart card has been detected."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_DIR_NOT_FOUND: | 
					
						
							|  |  |  |             ss<<"The specified directory does not exist in the smart card."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_FILE_NOT_FOUND: | 
					
						
							|  |  |  |             ss<<"The specified file does not exist in the smart card."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_ICC_CREATEORDER: | 
					
						
							|  |  |  |             ss<<"The requested order of object creation is not supported."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_ICC_INSTALLATION: | 
					
						
							|  |  |  |             ss<<"No primary provider can be found for the smart card."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_INVALID_CHV: | 
					
						
							|  |  |  |             ss<<"The supplied PIN is incorrect."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_NO_ACCESS: | 
					
						
							|  |  |  |             ss<<"Access is denied to this file."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_NO_DIR: | 
					
						
							|  |  |  |             ss<<"The supplied path does not represent a smart card directory."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_NO_FILE: | 
					
						
							|  |  |  |             ss<<"The supplied path does not represent a smart card file."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_NO_KEY_CONTAINER: | 
					
						
							|  |  |  |             ss<<"The requested key container does not exist on the smart card."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_NO_SUCH_CERTIFICATE: | 
					
						
							|  |  |  |             ss<<"The requested certificate does not exist."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_SERVER_TOO_BUSY: | 
					
						
							|  |  |  |             ss<<"The Smart card resource manager is too busy to complete this" | 
					
						
							|  |  |  |               <<" operation."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_UNEXPECTED: | 
					
						
							|  |  |  |             ss<<"An unexpected card error has occurred."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_UNKNOWN_RES_MNG: | 
					
						
							|  |  |  |             ss<<"An unrecognized error code was returned from a layered" | 
					
						
							|  |  |  |               <<" component."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_E_WRITE_TOO_MANY: | 
					
						
							|  |  |  |             ss<<"The smartcard does not have enough memory to store the" | 
					
						
							|  |  |  |               <<" information."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_P_SHUTDOWN: | 
					
						
							|  |  |  |             ss<<"The operation has been aborted to allow the server application" | 
					
						
							|  |  |  |               <<" to exit."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_W_CANCELLED_BY_USER: | 
					
						
							|  |  |  |             ss<<"The action was cancelled by the user."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_W_CARD_NOT_AUTHENTICATED: | 
					
						
							|  |  |  |             ss<<"No PIN was presented to the smart card."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_W_CHV_BLOCKED: | 
					
						
							|  |  |  |             ss<<"The card cannot be accessed because the maximum number" | 
					
						
							|  |  |  |               <<" of PIN entry attempts has been reached."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_W_EOF: | 
					
						
							|  |  |  |             ss<<"The end of the smart card file has been reached."; | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |           case SCARD_W_SECURITY_VIOLATION: | 
					
						
							|  |  |  |             ss<<"Access was denied because of a security violation."; | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |           case SCARD_W_WRONG_CHV: | 
					
						
							|  |  |  |             ss<<"The card cannot be accessed because the wrong PIN was" | 
					
						
							|  |  |  |               <<" presented."; | 
					
						
							| 
									
										
										
										
											2009-07-13 13:51:02 +00:00
										 |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-08-31 13:59:23 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2009-07-13 13:51:02 +00:00
										 |  |  |           default: | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |             ss<<"unknown PCSC state=0x" | 
					
						
							|  |  |  |               <<std::hex<<std::setfill('0')<<std::setw(8)<<_state; | 
					
						
							|  |  |  |             switch (_state>>30) { | 
					
						
							|  |  |  |               case 0: ss<<" means SUCCESS"; break; | 
					
						
							|  |  |  |               case 1: ss<<" means INFORMATIONAL"; break; | 
					
						
							|  |  |  |               case 2: ss<<" means WARNING"; break; | 
					
						
							|  |  |  |               case 3: ss<<" means ERROR"; break; | 
					
						
							|  |  |  |               default: ss<<" illegal value"; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             ss<<" C="<<(_state>>29&1); | 
					
						
							|  |  |  |             ss<<" R="<<(_state>>28&1); | 
					
						
							|  |  |  |             ss<<" Facility=0x"<<std::hex<<std::setfill('0')<<std::setw(3) | 
					
						
							|  |  |  |               <<(_state>>16&0xfff); | 
					
						
							|  |  |  |             ss<<" Code=0x"<<std::hex<<std::setfill('0')<<std::setw(4) | 
					
						
							|  |  |  |               <<(_state&0xffff); | 
					
						
							| 
									
										
										
										
											2009-07-13 13:51:02 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |         return ss.str(); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       //................................................................methods
 | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       //! Sets state and throws an exception if neccessary.
 | 
					
						
							|  |  |  |       /*! @throw access_error if it is instanciated for exceptions and
 | 
					
						
							|  |  |  |           an error occured in the last command. */ | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |       bool check(long state, const std::string& context="") { | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |         _state = state; | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |         return check(context); | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       //! Throws an exception if neccessary.
 | 
					
						
							|  |  |  |       /*! @throw access_error if it is instanciated for exceptions and
 | 
					
						
							|  |  |  |           an error occured in the last command. */ | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |       bool check(const std::string& context="") { | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |         if (_exc&&!*this) | 
					
						
							| 
									
										
										
										
											2009-07-14 09:16:59 +00:00
										 |  |  |           if (context.size()) | 
					
						
							|  |  |  |             throw access_error(context+": "+error()); | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             throw access_error(error()); | 
					
						
							| 
									
										
										
										
											2009-07-14 11:48:27 +00:00
										 |  |  |         return *this; | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       //! Splits a buffer with 0 separators into a vector of strings.
 | 
					
						
							|  |  |  |       Strings split(const std::string& in) { | 
					
						
							|  |  |  |         Strings res; | 
					
						
							| 
									
										
										
										
											2009-08-25 14:05:41 +00:00
										 |  |  |         for (std::string::size_type pos(0); pos<in.size() && in[pos]!=0; | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |              pos+=res.rbegin()->size()+1) | 
					
						
							|  |  |  |           res.push_back(in.substr(pos).c_str()); | 
					
						
							|  |  |  |         return res; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       //!  Joins a vector of strings into a  buffer with 0 separators.
 | 
					
						
							|  |  |  |       std::string join(const Strings& in) { | 
					
						
							|  |  |  |         std::string res; | 
					
						
							| 
									
										
										
										
											2009-08-25 14:05:41 +00:00
										 |  |  |         if (in.size()) { | 
					
						
							|  |  |  |           for (Strings::const_iterator it(in.begin()); | 
					
						
							|  |  |  |                it!=in.end(); ++it) | 
					
						
							|  |  |  |             res+=*it+'\0'; | 
					
						
							|  |  |  |           res+='\0'; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |         return res; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       //..............................................................variables
 | 
					
						
							|  |  |  |     private: | 
					
						
							|  |  |  |        | 
					
						
							|  |  |  |       bool _exc; | 
					
						
							| 
									
										
										
										
											2009-07-10 10:02:33 +00:00
										 |  |  |       SCARDCONTEXT _id; | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  |       long _state; | 
					
						
							|  |  |  |       std::map<std::string, boost::shared_ptr<Reader> > _reader; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-18 11:41:30 +00:00
										 |  |  |   //@}
 | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-09-18 11:41:30 +00:00
										 |  |  | //@}
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-17 12:30:45 +00:00
										 |  |  | #endif
 |