]> git.saurik.com Git - apple/securityd.git/blob - src/pcscmonitor.cpp
bd98ce292b27eee79d0e83a51e6b011289f433ea
[apple/securityd.git] / src / pcscmonitor.cpp
1 /*
2 * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26
27 //
28 // pcscmonitor - use PCSC to monitor smartcard reader/card state for securityd
29 //
30 // PCSCMonitor is the "glue" between PCSC and the securityd objects representing
31 // smartcard-related things. Its job is to translate real-world events into
32 // securityd-speak.
33 // Inputs are primarily security notifications sent from pcscd. We can also use
34 // MachServer-based timers to do things periodically or after some delay, though
35 // periodic actions are discouraged for the obvious reasons.
36 //
37 #include "pcscmonitor.h"
38
39
40 //
41 // Construct a PCSCMonitor.
42 // We strongly assume there's only one of us around here.
43 //
44 // Note that by construction, we *are* a notification Listener.
45 // The (unique index) port we use is zero (the null port), since we're
46 // not actually delivering the event anywhere (else).
47 //
48 PCSCMonitor::PCSCMonitor(Server &srv)
49 : Listener(kNotificationDomainPCSC, SecurityServer::kNotificationAllEvents),
50 server(srv)
51 {
52 // initial reader poll
53 if (mSession.isOpen()) {
54 pollReaders();
55 // server.setTimer(this, Time::Interval(5));
56
57 // setup complete
58 secdebug("sc", "pcsc monitor initialized");
59 }
60 }
61
62
63 PCSCMonitor::~PCSCMonitor()
64 {
65 }
66
67
68 //
69 // (Re)poll PCSC for smartcard status
70 //
71 void PCSCMonitor::pollReaders()
72 {
73 // enumerate readers
74 vector<string> names; // will hold reader name C strings throughout
75 mSession.listReaders(names);
76 size_t count = names.size();
77 secdebug("sc", "%ld reader(s) in system", count);
78
79 // inquire into reader state
80 vector<PCSC::ReaderState> states(count); // reader status array (PCSC style)
81 for (unsigned int n = 0; n < count; n++) {
82 PCSC::ReaderState &state = states[n];
83 ReaderMap::iterator it = mReaders.find(names[n]);
84 if (it == mReaders.end()) { // new reader
85 state.clearPod();
86 state.name(names[n].c_str());
87 // lastKnown(PCSC_STATE_UNKNOWN)
88 // userData<Reader>() = NULL
89 } else {
90 state = it->second->pcscState();
91 state.name(names[n].c_str()); // OUR pointer
92 state.lastKnown(state.state());
93 state.userData<Reader>() = it->second;
94 }
95 }
96 mSession.statusChange(states);
97 #if DEBUGDUMP
98 if (Debug::dumping("sc"))
99 for (unsigned int n = 0; n < count; n++)
100 states[n].dump();
101 #endif
102
103 // make set of previously known reader objects (to catch those who disappeared)
104 set<Reader *> current;
105 copy_second(mReaders.begin(), mReaders.end(), inserter(current, current.end()));
106
107 // match state array against them
108 for (unsigned int n = 0; n < count; n++) {
109 PCSC::ReaderState &state = states[n];
110 if (Reader *reader = state.userData<Reader>()) {
111 // if PCSC flags a change, notify the Reader
112 if (state.changed())
113 reader->update(state);
114 // accounted for this reader
115 current.erase(reader);
116 } else {
117 RefPointer<Reader> newReader = new Reader(state);
118 mReaders.insert(make_pair(state.name(), newReader));
119 }
120 }
121
122 // now deal with dead readers
123 for (set<Reader *>::iterator it = current.begin(); it != current.end(); it++) {
124 secdebug("sc", "killing reader %s", (*it)->name().c_str());
125 (*it)->kill(); // prepare to die
126 mReaders.erase((*it)->name()); // remove from reader map
127 }
128 }
129
130
131 //
132 // Event notifier.
133 // These events are sent by pcscd for our (sole) benefit.
134 //
135 void PCSCMonitor::notifyMe(SecurityServer::NotificationDomain domain,
136 SecurityServer::NotificationEvent event, const CssmData &data)
137 {
138 //@@@ need some kind of locking, of course...
139 pollReaders();
140 //server.setTimer(this, Time::Interval(0.5));
141 //secdebug("adhoc", "pcsc change event");
142 }
143
144
145 //
146 // Timer action.
147 //
148 void PCSCMonitor::action()
149 {
150 // not used at the moment; timer is not scheduled
151 }