1/* 2 * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// pcscmonitor - use PCSC to monitor smartcard reader/card state for securityd 27// 28#ifndef _H_PCSCDMONITOR 29#define _H_PCSCDMONITOR 30 31#include <MacTypes.h> 32#include <security_utilities/powerwatch.h> 33#include <security_utilities/pcsc++.h> 34#include <security_utilities/refcount.h> 35#include <security_utilities/iodevices.h> 36#include <security_utilities/threading.h> 37#include <securityd_client/ssclient.h> 38 39#include "pcscdserver.h" 40#include "PCSCDevice.h" 41#include "PCSCDriverBundles.h" 42 43typedef int32_t (*addDeviceCallback)(const char *name, uint32_t address, const char *pathLibrary, const char *pathDevice); 44typedef int32_t (*removeDeviceCallback)(const char *name, uint32_t address); 45typedef int32_t (*willSleepCallback)(); 46typedef int32_t (*isWakingCallback)(); 47 48#if defined(__cplusplus) 49 50class PCSCDMonitor; 51 52class TerminationNoticeReceiver : public IOKit::NotificationPort::Receiver 53{ 54public: 55 TerminationNoticeReceiver(PCSCDMonitor &parent) : mParent(parent) {} 56 virtual ~TerminationNoticeReceiver(); 57 58 virtual void ioChange(IOKit::DeviceIterator &iterator); 59 virtual void ioServiceChange(void *refCon, io_service_t service, //IOServiceInterestCallback 60 natural_t messageType, void *messageArgument); 61 62 virtual PCSCDMonitor &parent() { return mParent; } 63 64private: 65 PCSCDMonitor &mParent; 66}; 67 68// 69// A PCSCMonitor uses PCSC to monitor the state of smartcard readers and 70// tokens (cards) in the system, and dispatches messages and events to the 71// various related players in securityd. There should be at most one of these 72// objects active within securityd. 73// 74class PCSCDMonitor : 75 private MachPlusPlus::MachServer::Timer, 76 private IOKit::NotificationPort::Receiver, 77 private MachPlusPlus::PowerWatcher 78{ 79public: 80 81 friend class TerminationNoticeReceiver; 82 83 PCSCDMonitor(PCSCD::Server &server, PCSCD::DriverBundles &drivers); 84 void setCallbacks(addDeviceCallback theAddDeviceCallback, removeDeviceCallback theRemoveDeviceCallback, 85 willSleepCallback theWillSleepCallback, isWakingCallback theIsWakingCallback) 86 { mAddDeviceCallback = theAddDeviceCallback; mRemoveDeviceCallback = theRemoveDeviceCallback; 87 mWillSleepCallback = theWillSleepCallback; mIsWakingCallback = theIsWakingCallback; } 88 89 static void postNotification(const SecurityServer::NotificationEvent event); 90 91 void systemAwakeAndReadyCheck(); 92 93protected: 94 95 PCSCD::Server &server; 96 PCSCD::DriverBundles &drivers; 97 addDeviceCallback mAddDeviceCallback; 98 removeDeviceCallback mRemoveDeviceCallback; 99 willSleepCallback mWillSleepCallback; 100 isWakingCallback mIsWakingCallback; 101 102protected: 103 // MachServer::Timer 104 void action(); 105 106 // NotificationPort::Receiver 107 void ioChange(IOKit::DeviceIterator &iterator); 108 void ioServiceChange(void *refCon, io_service_t service, natural_t messageType, void *messageArgument); 109 110 // PowerWatcher 111 void systemWillSleep(); 112 void systemIsWaking(); 113 114protected: 115 void scheduleTimer(bool enable); 116 void initialSetup(); 117 void noDeviceTimeout(); 118 119 enum DeviceSupport 120 { 121 impossible, // certain this is not a smartcard 122 definite, // definitely a smartcard device 123 possible // perhaps... we're not sure 124 }; 125 DeviceSupport deviceSupport(const IOKit::Device &dev); 126 127 void addDevice(const IOKit::Device &dev); 128 void removeDevice(io_service_t service, uint32_t address); 129 void removeDeviceByName(const IOKit::Device &dev); 130 bool hasLegacyDriver(const IOKit::Device &dev); 131 bool isExcludedDevice(const IOKit::Device &dev); 132 void scheduleAddInterestNotification(io_service_t serviceOfInterest); 133 void addInterestNotification(); 134 void removeAllDevices(); 135 void AddIOKitNotifications(); 136 void RemoveIOKitNotifications(); 137 void rescanExistingDevices(); 138 139 typedef std::map<uint32_t, RefPointer<PCSCD::Device> > DeviceMap; 140 DeviceMap mDevices; 141 142 mutable Mutex mDeviceMapLock; 143 144 void insert(pair<uint32_t, RefPointer<PCSCD::Device> > devicepair) { StLock<Mutex> _(mDeviceMapLock); mDevices.insert(devicepair); } 145 void remove(DeviceMap::iterator it) { StLock<Mutex> _(mDeviceMapLock); mDevices.erase(it); } 146 147private: 148 void (PCSCDMonitor::*mTimerAction)(); // what to do when our timer fires 149 bool mGoingToSleep; // between sleep and wakeup; special timer handling 150 151 mutable Mutex mLock; 152 153 IOKit::MachPortNotificationPort mIOKitNotifier; // IOKit connection 154 TerminationNoticeReceiver mTerminationNoticeReceiver; 155 156 io_object_t mRemoveNotification; 157 io_service_t mServiceOfInterest; 158 159 bool mSleepWakePeriod; 160 mutable Mutex mSleepWakePeriodLock; 161 mutable Mutex mWakeConditionLock; 162 Condition mWakeConditionVariable; 163 bool isSleepWakePeriod() const; 164 void sleepWakePeriod(bool isASleepWakePeriod); 165 void setSystemIsAwakeCondition(bool isAwake); 166 167 bool findDevice(const IOKit::Device &dev, DeviceMap::iterator &it); 168 bool findDeviceByName(const IOKit::Device &dev, DeviceMap::iterator &outit); 169 void updateDevice(const IOKit::Device &dev); 170 void setDeviceProperties(const IOKit::Device &dev, PCSCD::Device &device); 171 172 static void getVendorAndProductID(const IOKit::Device &dev, uint32_t &vendorID, uint32_t &productID, bool &isPCCard); 173 static bool deviceIsPCCard(const IOKit::Device &dev); 174 static bool deviceIsPCCard(io_service_t service); 175 static bool deviceAddress(io_service_t service, uint32_t &address); 176 static bool deviceAddress(const IOKit::Device &dev, uint32_t &address); 177 static bool deviceMemoryAddress(const IOKit::Device &dev, uint32_t &address); 178 static bool deviceMemoryAddress(io_service_t service, uint32_t &address); 179 static bool deviceMemoryAddressCore(CFArrayRef cfDeviceMemory, std::string path, uint32_t &address); 180 static bool addressFromPath(std::string path, uint32_t &address); 181 182 // debug 183 void setDebugPropertiesForDevice(const IOKit::Device &dev, PCSCD::Device* newDevice); 184 static void displayPropertiesOfDevice(const IOKit::Device &dev); 185 static void displayPropertiesOfDevice(io_service_t service); 186 void dumpDevices(); 187}; 188 189#endif /* __cplusplus__ */ 190 191#endif //_H_PCSCDMONITOR 192 193