From 31ebb6568fd8557ba184b38481887e540cbf5647 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Tue, 25 Aug 2015 00:25:25 -0500 Subject: [PATCH] Add preliminary cryptographic card support to TDEHWLib --- tdecore/tdehw/CMakeLists.txt | 10 +- tdecore/tdehw/tdecryptographiccarddevice.cpp | 296 ++++++++++++++++++ tdecore/tdehw/tdecryptographiccarddevice.h | 82 +++++ .../tdecryptographiccarddevice_private.h | 59 ++++ tdecore/tdehw/tdehardwaredevices.cpp | 3 +- tdecore/tdehw/tdehardwaredevices.h | 1 + 6 files changed, 448 insertions(+), 3 deletions(-) create mode 100644 tdecore/tdehw/tdecryptographiccarddevice.cpp create mode 100644 tdecore/tdehw/tdecryptographiccarddevice.h create mode 100644 tdecore/tdehw/tdecryptographiccarddevice_private.h diff --git a/tdecore/tdehw/CMakeLists.txt b/tdecore/tdehw/CMakeLists.txt index f9354ecfb..229ecc2fd 100644 --- a/tdecore/tdehw/CMakeLists.txt +++ b/tdecore/tdehw/CMakeLists.txt @@ -56,6 +56,12 @@ if( WITH_CONSOLEKIT ) add_definitions( -DWITH_CONSOLEKIT ) endif( ) +if( WITH_PCSC ) + add_definitions( -DWITH_PCSC ) + list( APPEND TDEHW_CUSTOM_INCLUDE_DIRS ${PCSCLITE_INCLUDE_DIRS} ) + list( APPEND TDEHW_CUSTOM_LIBRARIES ${PCSCLITE_LIBRARIES} ) +endif( ) + if( WITH_NETWORK_MANAGER_BACKEND ) list( APPEND TDEHW_CUSTOM_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/networkbackends/network-manager ) list( APPEND TDEHW_CUSTOM_LIBRARIES network_manager_backend-static ) @@ -83,7 +89,7 @@ install( FILES tdehardwaredevices.h tdenetworkconnections.h tdegenericdevice.h tdestoragedevice.h tdecpudevice.h tdebatterydevice.h tdemainspowerdevice.h tdenetworkdevice.h tdebacklightdevice.h tdemonitordevice.h tdesensordevice.h tderootsystemdevice.h tdeeventdevice.h tdeinputdevice.h - tdehwcommontypes.h + tdecryptographiccarddevice.h tdehwcommontypes.h DESTINATION ${INCLUDE_INSTALL_DIR} ) @@ -96,7 +102,7 @@ set( ${target}_SRCS tdestoragedevice.cpp tdecpudevice.cpp tdebatterydevice.cpp tdemainspowerdevice.cpp tdenetworkdevice.cpp tdebacklightdevice.cpp tdemonitordevice.cpp tdesensordevice.cpp tderootsystemdevice.cpp - tdeeventdevice.cpp tdeinputdevice.cpp + tdeeventdevice.cpp tdeinputdevice.cpp tdecryptographiccarddevice.cpp ) tde_add_library( ${target} STATIC_PIC AUTOMOC diff --git a/tdecore/tdehw/tdecryptographiccarddevice.cpp b/tdecore/tdehw/tdecryptographiccarddevice.cpp new file mode 100644 index 000000000..9c827a1f6 --- /dev/null +++ b/tdecore/tdehw/tdecryptographiccarddevice.cpp @@ -0,0 +1,296 @@ +/* This file is part of the TDE libraries + Copyright (C) 2015 Timothy Pearson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "tdecryptographiccarddevice_private.h" +#include "tdecryptographiccarddevice.h" + +#include +#include +#include +#include +#include + +#include "tdeglobal.h" +#include "tdelocale.h" + +#include "tdehardwaredevices.h" + +#include "config.h" + +// 1 second +#define PCSC_POLL_TIMEOUT_S 1000 + +/* FIXME + * This is incomplete + */ +static TQString pcsc_error_code_to_string(long errcode) { + if (errcode == SCARD_W_UNPOWERED_CARD) { + return i18n("card not powered on"); + } + else if (errcode == SCARD_E_PROTO_MISMATCH) { + return i18n("protocol mismatch"); + } + else { + return TQString::null; + } +} + +CryptoCardDeviceWatcher::CryptoCardDeviceWatcher() { + m_readerStates = NULL; +} + +CryptoCardDeviceWatcher::~CryptoCardDeviceWatcher() { + free(m_readerStates); +} + +void CryptoCardDeviceWatcher::run() { +#ifdef WITH_PCSC + bool first_loop; + unsigned int i; + long ret; + + DWORD dword_readers; + LPSTR lpstring_readers = NULL; + + TQStringList readers; + + first_loop = true; + m_terminationRequested = false; + + TQEventLoop* eventLoop = TQApplication::eventLoop(); + if (!eventLoop) return; + + ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &m_cardContext); + if (ret != SCARD_S_SUCCESS) { + printf("TDECryptographicCardDevice: PCSC SCardEstablishContext cannot connect to resource manager (%lX)", ret); + eventLoop->exit(0); + return; + } + + ret = SCardListReaders(m_cardContext, NULL, NULL, &dword_readers); + if (ret == SCARD_S_SUCCESS) { + lpstring_readers = (LPSTR)malloc(sizeof(char)*dword_readers); + if (lpstring_readers == NULL) { + printf("TDECryptographicCardDevice: insufficient memory, aborting"); + eventLoop->exit(0); + return; + } + + ret = SCardListReaders(m_cardContext, NULL, lpstring_readers, &dword_readers); + if (ret == SCARD_S_SUCCESS) { + /* Extract reader names from the null separated string */ + char *ptr = lpstring_readers; + while (*ptr != '\0') { + readers.append(ptr); + ptr += strlen(ptr)+1; + } + + free(lpstring_readers); + + m_readerStates = (SCARD_READERSTATE*)calloc(readers.count(), sizeof(*m_readerStates)); + if (m_readerStates == NULL) { + printf("TDECryptographicCardDevice: insufficient memory, aborting"); + free(lpstring_readers); + eventLoop->exit(0); + return; + } + + for (i=0; iexit(0); + return; + } + + for (i=0; ifriendlyName())) { + continue; + } + + if (first_loop) { + if (m_readerStates[i].dwEventState & SCARD_STATE_PRESENT) { + // sleep(1); // Allow the card to settle + statusChanged("PRESENT", getCardATR(readers[i])); + } + first_loop = false; + } + if (m_readerStates[i].dwEventState & SCARD_STATE_CHANGED) { + if ((m_readerStates[i].dwCurrentState & SCARD_STATE_PRESENT) + && (m_readerStates[i].dwEventState & SCARD_STATE_EMPTY)) { + statusChanged("REMOVED", TQString::null); + } + else if ((m_readerStates[i].dwCurrentState & SCARD_STATE_EMPTY) + && (m_readerStates[i].dwEventState & SCARD_STATE_PRESENT)) { + // sleep(1); // Allow the card to settle + statusChanged("INSERTED", getCardATR(readers[i])); + } + m_readerStates[i].dwCurrentState = m_readerStates[i].dwEventState; + } + else { + continue; + } + } + ret = SCardGetStatusChange(m_cardContext, PCSC_POLL_TIMEOUT_S, m_readerStates, readers.count()); + } + } + } + + eventLoop->exit(0); +#endif +} + +void CryptoCardDeviceWatcher::requestTermination() { + m_terminationRequested = true; +} + +TQString CryptoCardDeviceWatcher::getCardATR(TQString readerName) { + unsigned int i; + long ret; + TQString atr_formatted; + SCARDHANDLE hCard = 0; + DWORD dwActiveProtocol = 0; + DWORD cByte = 0; + + ret = SCardConnect(m_cardContext, readerName.ascii(), SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCard, &dwActiveProtocol); + if (ret == SCARD_S_SUCCESS) { + ret = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, NULL, &cByte); + if (ret == SCARD_S_SUCCESS) { + char* data = new char[cByte]; + ret = SCardGetAttrib(hCard, SCARD_ATTR_ATR_STRING, (LPBYTE)data, &cByte); + atr_formatted = TQString::null; + for (i=0; icardDevice = this; + m_watcherObject->moveToThread(m_watcherThread); + TQObject::connect(m_watcherObject, SIGNAL(statusChanged(TQString,TQString)), this, SLOT(cardStatusChanged(TQString,TQString))); + TQTimer::singleShot(0, m_watcherObject, SLOT(run())); + + m_watcherThread->start(); + } + else { + if (m_watcherObject) { + m_watcherObject->requestTermination(); + delete m_watcherObject; + m_watcherObject = NULL; + } + if (m_watcherThread) { + m_watcherThread->wait(); + delete m_watcherThread; + m_watcherThread = NULL; + } + } +#endif +} + +int TDECryptographicCardDevice::cardPresent() { + if (m_watcherObject && m_watcherThread) { + if (m_cardPresent) + return 1; + else + return 0; + } + else { + return -1; + } +} + +TQString TDECryptographicCardDevice::cardATR() { + if (m_watcherObject && m_watcherThread) { + if (m_cardPresent) + return m_cardATR; + else + return TQString::null; + } + else { + return TQString::null; + } +} + +void TDECryptographicCardDevice::cardStatusChanged(TQString status, TQString atr) { + if (status == "INSERTED") { + m_cardPresent = true; + m_cardATR = atr; + emit(cardInserted()); + } + else if (status == "REMOVED") { + m_cardPresent = false; + m_cardATR = atr; + emit(cardRemoved()); + } + else if (status == "PRESENT") { + m_cardATR = atr; + m_cardPresent = true; + } +} + +#include "tdecryptographiccarddevice.moc" +#include "tdecryptographiccarddevice_private.moc" diff --git a/tdecore/tdehw/tdecryptographiccarddevice.h b/tdecore/tdehw/tdecryptographiccarddevice.h new file mode 100644 index 000000000..7d7a8dafc --- /dev/null +++ b/tdecore/tdehw/tdecryptographiccarddevice.h @@ -0,0 +1,82 @@ + +/* This file is part of the TDE libraries + Copyright (C) 2015 Timothy Pearson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _TDECRYPTOGRAPHICCARDDEVICE_H +#define _TDECRYPTOGRAPHICCARDDEVICE_H + +#include "tdegenericdevice.h" + +class TQEventLoopThread; +class CryptoCardDeviceWatcher; + +class TDECORE_EXPORT TDECryptographicCardDevice : public TDEGenericDevice +{ + Q_OBJECT + + public: + /** + * Constructor. + * @param Device type + */ + TDECryptographicCardDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn=TQString::null); + + /** + * Destructor. + */ + ~TDECryptographicCardDevice(); + + /** + * Enable / disable monitoring of insert / remove events. + * @param enable true to enable, false to disable. + */ + void enableCardMonitoring(bool enable); + + /** + * If monitoring of insert / remove events is enabled, + * return whether or not a card is present. + * @return -1 if status unknown, 0 if card not present, + * 1 if card is present. + */ + int cardPresent(); + + /** + * If monitoring of insert / remove events is enabled, + * and a card has been inserted, return the card's ATR. + * @return TQString::null if no card or card status unknown. + */ + TQString cardATR(); + + public slots: + void cardStatusChanged(TQString status, TQString atr); + + signals: + void cardInserted(); + void cardRemoved(); + + private: + TQEventLoopThread *m_watcherThread; + CryptoCardDeviceWatcher *m_watcherObject; + + bool m_cardPresent; + TQString m_cardATR; + + friend class TDEHardwareDevices; +}; + +#endif // _TDECRYPTOGRAPHICCARDDEVICE_H diff --git a/tdecore/tdehw/tdecryptographiccarddevice_private.h b/tdecore/tdehw/tdecryptographiccarddevice_private.h new file mode 100644 index 000000000..a82fe1ae5 --- /dev/null +++ b/tdecore/tdehw/tdecryptographiccarddevice_private.h @@ -0,0 +1,59 @@ + +/* This file is part of the TDE libraries + Copyright (C) 2015 Timothy Pearson + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _TDECRYPTOGRAPHICCARDDEVICE_PRIVATE_H +#define _TDECRYPTOGRAPHICCARDDEVICE_PRIVATE_H + +#include "tdegenericdevice.h" + +#ifdef WITH_PCSC + #include + #include + #include + #include +#endif + +class TDECryptographicCardDevice; + +class CryptoCardDeviceWatcher : public TQObject +{ + TQ_OBJECT + + public: + CryptoCardDeviceWatcher(); + ~CryptoCardDeviceWatcher(); + + public slots: + void run(); + void requestTermination(); + TQString getCardATR(TQString readerName); + + signals: + void statusChanged(TQString, TQString); + + public: + TDECryptographicCardDevice *cardDevice; + + private: + bool m_terminationRequested; + SCARDCONTEXT m_cardContext; + SCARD_READERSTATE *m_readerStates; +}; + +#endif // _TDECRYPTOGRAPHICCARDDEVICE_PRIVATE_H \ No newline at end of file diff --git a/tdecore/tdehw/tdehardwaredevices.cpp b/tdecore/tdehw/tdehardwaredevices.cpp index d2fd7e2f3..e3608e11c 100644 --- a/tdecore/tdehw/tdehardwaredevices.cpp +++ b/tdecore/tdehw/tdehardwaredevices.cpp @@ -66,6 +66,7 @@ extern "C" { #include "tderootsystemdevice.h" #include "tdeeventdevice.h" #include "tdeinputdevice.h" +#include "tdecryptographiccarddevice.h" // Compile-time configuration #include "config.h" @@ -2297,7 +2298,7 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD } if (usbInterfaceClass == 11) { // Smart Card Reader - if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::CryptographicCard); + if (!device) device = new TDECryptographicCardDevice(TDEGenericDeviceType::CryptographicCard); } if ((usbInterfaceClass == 6) && (usbInterfaceSubClass == 1) && (usbInterfaceProtocol == 1)) { // PictBridge diff --git a/tdecore/tdehw/tdehardwaredevices.h b/tdecore/tdehw/tdehardwaredevices.h index 6592b8b10..2d5aeafac 100644 --- a/tdecore/tdehw/tdehardwaredevices.h +++ b/tdecore/tdehw/tdehardwaredevices.h @@ -53,6 +53,7 @@ extern "C" { #include "tderootsystemdevice.h" #include "tdeeventdevice.h" #include "tdeinputdevice.h" +#include "tdecryptographiccarddevice.h" /** * Hardware Device Access and Monitoring Library