+ try {
+ // this might take a while...
+ Server::active().longTermActivity();
+ referent(slot);
+ mState = slot.pcscState();
+
+ if (tokend == NULL) {
+ // no pre-determined Tokend - search for one
+ if (!(tokend = chooseTokend())) {
+ secdebug("token", "%p no token daemons available - faulting this card", this);
+ fault(false); // throws
+ }
+ }
+
+ // take Token lock and hold throughout insertion
+ StLock<Mutex> _(*this);
+
+ Syslog::debug("token inserted into reader %s", slot.name().c_str());
+ secdebug("token", "%p begin insertion into slot %p (reader %s)",
+ this, &slot, slot.name().c_str());
+
+ // tell the tokend object to relay faults to us
+ tokend->faultRelay(this);
+
+ // locate or establish cache directories
+ if (tokend->hasTokenUid()) {
+ secdebug("token", "%p using %s (score=%d, uid=\"%s\")",
+ this, tokend->bundlePath().c_str(), tokend->score(), tokend->tokenUid().c_str());
+ mCache = new TokenCache::Token(reader().cache,
+ tokend->bundleIdentifier() + ":" + tokend->tokenUid());
+ } else {
+ secdebug("token", "%p using %s (score=%d, temporary)",
+ this, tokend->bundlePath().c_str(), tokend->score());
+ mCache = new TokenCache::Token(reader().cache);
+ }
+ secdebug("token", "%p token cache at %s", this, mCache->root().c_str());
+
+ // here's the primary parameters of the new subservice
+ mGuid = gGuidAppleSdCSPDL;
+ mSubservice = mCache->subservice();
+
+ // establish work areas with tokend
+ char mdsDirectory[PATH_MAX];
+ char printName[PATH_MAX];
+ tokend->establish(mGuid, mSubservice,
+ (mCache->type() != TokenCache::Token::existing ? kSecTokendEstablishNewCache : 0) | kSecTokendEstablishMakeMDS,
+ mCache->cachePath().c_str(), mCache->workPath().c_str(),
+ mdsDirectory, printName);
+
+ // establish print name
+ if (mCache->type() == TokenCache::Token::existing) {
+ mPrintName = mCache->printName();
+ if (mPrintName.empty())
+ mPrintName = printName;
+ } else
+ mPrintName = printName;
+ if (mPrintName.empty()) {
+ // last resort - new card and tokend didn't give us one
+ snprintf(printName, sizeof(printName), "smart card #%d", mSubservice);
+ mPrintName = printName;
+ }
+ if (mCache->type() != TokenCache::Token::existing)
+ mCache->printName(mPrintName); // store in cache
+
+ // install MDS
+ secdebug("token", "%p installing MDS from %s(%s)", this,
+ tokend->bundlePath().c_str(),
+ mdsDirectory[0] ? mdsDirectory : "ALL");
+ string holdGuid = mGuid.toString(); // extend lifetime of std::string
+ string holdTokenUid;
+ if (tokend->hasTokenUid())
+ holdTokenUid = tokend->tokenUid();
+ string holdPrintName = this->printName();
+ MDS_InstallDefaults mdsDefaults = {
+ holdGuid.c_str(),
+ mSubservice,
+ holdTokenUid.c_str(),
+ holdPrintName.c_str()
+ };
+ mds().install(&mdsDefaults,
+ tokend->bundlePath().c_str(),
+ mdsDirectory[0] ? mdsDirectory : NULL,
+ NULL);
+
+ {
+ // commit to insertion
+ StLock<Mutex> _(mSSIDLock);
+ assert(mSubservices.find(mSubservice) == mSubservices.end());
+ mSubservices.insert(make_pair(mSubservice, this));
+ }
+
+ // assign mTokend right before notification - mustn't be set if
+ // anything goes wrong during insertion
+ mTokend = tokend;
+
+ notify(kNotificationCDSAInsertion);
+
+ Syslog::notice("reader %s inserted token \"%s\" (%s) subservice %ld using driver %s",
+ slot.name().c_str(), mPrintName.c_str(),
+ mTokend->hasTokenUid() ? mTokend->tokenUid().c_str() : "NO UID",
+ mSubservice, mTokend->bundleIdentifier().c_str());
+ secdebug("token", "%p inserted as %s:%d", this, mGuid.toString().c_str(), mSubservice);
+ } catch (const CommonError &err) {
+ Syslog::notice("token in reader %s cannot be used (error %ld)", slot.name().c_str(), err.osStatus());
+ secdebug("token", "exception during insertion processing");
+ fault(false);
+ } catch (...) {
+ // exception thrown during insertion processing. Mark faulted
+ Syslog::notice("token in reader %s cannot be used", slot.name().c_str());
+ secdebug("token", "exception during insertion processing");
+ fault(false);
+ }