2 * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
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
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.
23 * @APPLE_LICENSE_HEADER_END@
28 // pcscmonitor - use PCSC to monitor smartcard reader/card state for securityd
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
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.
37 #include "pcscmonitor.h"
41 // Construct a PCSCMonitor.
42 // We strongly assume there's only one of us around here.
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).
48 PCSCMonitor::PCSCMonitor(Server
&srv
)
49 : Listener(kNotificationDomainPCSC
, SecurityServer::kNotificationAllEvents
),
52 // initial reader poll
53 if (mSession
.isOpen()) {
55 // server.setTimer(this, Time::Interval(5));
58 secdebug("sc", "pcsc monitor initialized");
63 PCSCMonitor::~PCSCMonitor()
69 // (Re)poll PCSC for smartcard status
71 void PCSCMonitor::pollReaders()
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
);
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
86 state
.name(names
[n
].c_str());
87 // lastKnown(PCSC_STATE_UNKNOWN)
88 // userData<Reader>() = NULL
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
;
96 mSession
.statusChange(states
);
98 if (Debug::dumping("sc"))
99 for (unsigned int n
= 0; n
< count
; n
++)
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()));
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
113 reader
->update(state
);
114 // accounted for this reader
115 current
.erase(reader
);
117 RefPointer
<Reader
> newReader
= new Reader(state
);
118 mReaders
.insert(make_pair(state
.name(), newReader
));
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
133 // These events are sent by pcscd for our (sole) benefit.
135 void PCSCMonitor::notifyMe(SecurityServer::NotificationDomain domain
,
136 SecurityServer::NotificationEvent event
, const CssmData
&data
)
138 //@@@ need some kind of locking, of course...
140 //server.setTimer(this, Time::Interval(0.5));
141 //secdebug("adhoc", "pcsc change event");
148 void PCSCMonitor::action()
150 // not used at the moment; timer is not scheduled