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