/* * Creates a vector of driver bundle info structures from the hot-plug driver * directory. * * Returns NULL on error and a pointer to an allocated HPDriver vector on * success. The caller must free the HPDriver with a call to * HPDriversRelease(). */ static HPDriverVector HPDriversGetFromDirectory(const char *driverBundlePath) { int i; #ifdef DEBUG_HOTPLUG Log2(PCSC_LOG_DEBUG, "Entering HPDriversGetFromDirectory: %s", driverBundlePath); #endif int readersNumber = 0; HPDriverVector bundleVector = NULL; CFArrayRef bundleArray; CFStringRef driverBundlePathString = CFStringCreateWithCString(kCFAllocatorDefault, driverBundlePath, kCFStringEncodingMacRoman); CFURLRef pluginUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, driverBundlePathString, kCFURLPOSIXPathStyle, TRUE); CFRelease(driverBundlePathString); if (!pluginUrl) { Log1(PCSC_LOG_ERROR, "error getting plugin directory URL"); return NULL; } bundleArray = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault, pluginUrl, NULL); if (!bundleArray) { Log1(PCSC_LOG_ERROR, "error getting plugin directory bundles"); return NULL; } CFRelease(pluginUrl); size_t bundleArraySize = CFArrayGetCount(bundleArray); /* get the number of readers (including aliases) */ for (i = 0; i < bundleArraySize; i++) { CFBundleRef currBundle = (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i); CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle); const void * blobValue = CFDictionaryGetValue(dict, CFSTR(PCSCLITE_HP_MANUKEY_NAME)); if (!blobValue) { Log1(PCSC_LOG_ERROR, "error getting vendor ID from bundle"); return NULL; } if (CFGetTypeID(blobValue) == CFArrayGetTypeID()) { /* alias found, each reader count as 1 */ CFArrayRef propertyArray = blobValue; readersNumber += CFArrayGetCount(propertyArray); } else /* No alias, only one reader supported */ readersNumber++; } #ifdef DEBUG_HOTPLUG Log2(PCSC_LOG_DEBUG, "Total of %d readers supported", readersNumber); #endif /* The last entry is an end marker (m_vendorId = 0) * see checks in HPDriversMatchUSBDevices:503 * and HPDriverVectorRelease:376 */ readersNumber++; bundleVector = (HPDriver *) calloc(readersNumber, sizeof(HPDriver)); if (!bundleVector) { Log1(PCSC_LOG_ERROR, "memory allocation failure"); return NULL; } HPDriver *driverBundle = bundleVector; for (i = 0; i < bundleArraySize; i++) { CFBundleRef currBundle = (CFBundleRef) CFArrayGetValueAtIndex(bundleArray, i); CFDictionaryRef dict = CFBundleGetInfoDictionary(currBundle); CFURLRef bundleUrl = CFBundleCopyBundleURL(currBundle); CFStringRef bundlePath = CFURLCopyPath(bundleUrl); driverBundle->m_libPath = strdup(CFStringGetCStringPtr(bundlePath, CFStringGetSystemEncoding())); const void * blobValue = CFDictionaryGetValue(dict, CFSTR(PCSCLITE_HP_MANUKEY_NAME)); if (!blobValue) { Log1(PCSC_LOG_ERROR, "error getting vendor ID from bundle"); return bundleVector; } if (CFGetTypeID(blobValue) == CFArrayGetTypeID()) { CFArrayRef vendorArray = blobValue; CFArrayRef productArray; CFArrayRef friendlyNameArray; char *libPath = driverBundle->m_libPath; #ifdef DEBUG_HOTPLUG Log2(PCSC_LOG_DEBUG, "Driver with aliases: %s", libPath); #endif /* get list of ProductID */ productArray = CFDictionaryGetValue(dict, CFSTR(PCSCLITE_HP_PRODKEY_NAME)); if (!productArray) { Log1(PCSC_LOG_ERROR, "error getting product ID from bundle"); return bundleVector; } /* get list of FriendlyName */ friendlyNameArray = CFDictionaryGetValue(dict, CFSTR(PCSCLITE_HP_NAMEKEY_NAME)); if (!friendlyNameArray) { Log1(PCSC_LOG_ERROR, "error getting product ID from bundle"); return bundleVector; } int reader_nb = CFArrayGetCount(vendorArray); if (reader_nb != CFArrayGetCount(productArray)) { Log3(PCSC_LOG_ERROR, "Malformed Info.plist: %d vendors and %d products", reader_nb, CFArrayGetCount(productArray)); return bundleVector; } if (reader_nb != CFArrayGetCount(friendlyNameArray)) { Log3(PCSC_LOG_ERROR, "Malformed Info.plist: %d vendors and %d friendlynames", reader_nb, CFArrayGetCount(friendlyNameArray)); return bundleVector; } int j; for (j=0; j<reader_nb; j++) { CFStringRef strValue = CFArrayGetValueAtIndex(vendorArray, j); driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue, CFStringGetSystemEncoding()), NULL, 16); strValue = CFArrayGetValueAtIndex(productArray, j); driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue, CFStringGetSystemEncoding()), NULL, 16); strValue = CFArrayGetValueAtIndex(friendlyNameArray, j); const char *cstr = CFStringGetCStringPtr(strValue, CFStringGetSystemEncoding()); driverBundle->m_friendlyName = strdup(cstr); if (!driverBundle->m_libPath) driverBundle->m_libPath = strdup(libPath); #ifdef DEBUG_HOTPLUG Log2(PCSC_LOG_DEBUG, "VendorID: 0x%04X", driverBundle->m_vendorId); Log2(PCSC_LOG_DEBUG, "ProductID: 0x%04X", driverBundle->m_productId); Log2(PCSC_LOG_DEBUG, "Friendly name: %s", driverBundle->m_friendlyName); Log2(PCSC_LOG_DEBUG, "Driver: %s", driverBundle->m_libPath); #endif /* go to next bundle in the vector */ driverBundle++; } } else { CFStringRef strValue = blobValue; #ifdef DEBUG_HOTPLUG Log3(PCSC_LOG_DEBUG, "Driver without alias: %s", driverBundle, driverBundle->m_libPath); #endif driverBundle->m_vendorId = strtoul(CFStringGetCStringPtr(strValue, CFStringGetSystemEncoding()), NULL, 16); strValue = (CFStringRef) CFDictionaryGetValue(dict, CFSTR(PCSCLITE_HP_PRODKEY_NAME)); if (!strValue) { Log1(PCSC_LOG_ERROR, "error getting product ID from bundle"); return bundleVector; } driverBundle->m_productId = strtoul(CFStringGetCStringPtr(strValue, CFStringGetSystemEncoding()), NULL, 16); strValue = (CFStringRef) CFDictionaryGetValue(dict, CFSTR(PCSCLITE_HP_NAMEKEY_NAME)); if (!strValue) { Log1(PCSC_LOG_ERROR, "error getting product friendly name from bundle"); driverBundle->m_friendlyName = strdup("unnamed device"); } else { const char *cstr = CFStringGetCStringPtr(strValue, CFStringGetSystemEncoding()); driverBundle->m_friendlyName = strdup(cstr); } #ifdef DEBUG_HOTPLUG Log2(PCSC_LOG_DEBUG, "VendorID: 0x%04X", driverBundle->m_vendorId); Log2(PCSC_LOG_DEBUG, "ProductID: 0x%04X", driverBundle->m_productId); Log2(PCSC_LOG_DEBUG, "Friendly name: %s", driverBundle->m_friendlyName); Log2(PCSC_LOG_DEBUG, "Driver: %s", driverBundle->m_libPath); #endif /* go to next bundle in the vector */ driverBundle++; } } CFRelease(bundleArray); return bundleVector; }
LONG RFAddReader(const char *readerNameLong, int port, const char *library, const char *device) { DWORD dwContext = 0, dwGetSize; UCHAR ucGetData[1], ucThread[1]; LONG rv, parentNode; int i, j; int lrv = 0; char *readerName = NULL; if ((readerNameLong == NULL) || (library == NULL) || (device == NULL)) return SCARD_E_INVALID_VALUE; /* allocate memory that is automatically freed */ readerName = alloca(strlen(readerNameLong)+1); strcpy(readerName, readerNameLong); /* Reader name too long? also count " 00 00"*/ if (strlen(readerName) > MAX_READERNAME - sizeof(" 00 00")) { Log3(PCSC_LOG_ERROR, "Reader name too long: %zd chars instead of max %zd. Truncating!", strlen(readerName), MAX_READERNAME - sizeof(" 00 00")); readerName[MAX_READERNAME - sizeof(" 00 00")] = '\0'; } /* Same name, same port - duplicate reader cannot be used */ if (dwNumReadersContexts != 0) { for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) { if (sReadersContexts[i]->vHandle != 0) { char lpcStripReader[MAX_READERNAME]; int tmplen; /* get the reader name without the reader and slot numbers */ strncpy(lpcStripReader, sReadersContexts[i]->readerState->readerName, sizeof(lpcStripReader)); tmplen = strlen(lpcStripReader); lpcStripReader[tmplen - 6] = 0; if ((strcmp(readerName, lpcStripReader) == 0) && (port == sReadersContexts[i]->port)) { Log1(PCSC_LOG_ERROR, "Duplicate reader found."); return SCARD_E_DUPLICATE_READER; } } } } /* We must find an empty slot to put the reader structure */ for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) { if (sReadersContexts[i]->vHandle == 0) { dwContext = i; break; } } if (i == PCSCLITE_MAX_READERS_CONTEXTS) { /* No more spots left return */ return SCARD_E_NO_MEMORY; } /* Check and set the readername to see if it must be enumerated */ parentNode = RFSetReaderName(sReadersContexts[dwContext], readerName, library, port); if (parentNode < -1) return SCARD_E_NO_MEMORY; sReadersContexts[dwContext]->library = strdup(library); sReadersContexts[dwContext]->device = strdup(device); sReadersContexts[dwContext]->version = 0; sReadersContexts[dwContext]->port = port; sReadersContexts[dwContext]->mMutex = NULL; sReadersContexts[dwContext]->contexts = 0; sReadersContexts[dwContext]->pthThread = 0; sReadersContexts[dwContext]->hLockId = 0; sReadersContexts[dwContext]->LockCount = 0; sReadersContexts[dwContext]->vHandle = NULL; sReadersContexts[dwContext]->pFeeds = NULL; sReadersContexts[dwContext]->pMutex = NULL; sReadersContexts[dwContext]->pthCardEvent = NULL; lrv = list_init(&sReadersContexts[dwContext]->handlesList); if (lrv < 0) { Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv); return SCARD_E_NO_MEMORY; } lrv = list_attributes_seeker(&sReadersContexts[dwContext]->handlesList, RDR_CLIHANDLES_seeker); if (lrv < 0) { Log2(PCSC_LOG_CRITICAL, "list_attributes_seeker failed with return value: %d", lrv); return SCARD_E_NO_MEMORY; } (void)pthread_mutex_init(&sReadersContexts[dwContext]->handlesList_lock, NULL); (void)pthread_mutex_init(&sReadersContexts[dwContext]->powerState_lock, NULL); sReadersContexts[dwContext]->powerState = POWER_STATE_UNPOWERED; /* reference count */ (void)pthread_mutex_init(&sReadersContexts[dwContext]->reference_lock, NULL); sReadersContexts[dwContext]->reference = 1; /* If a clone to this reader exists take some values from that clone */ if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS) { sReadersContexts[dwContext]->pFeeds = sReadersContexts[parentNode]->pFeeds; *(sReadersContexts[dwContext])->pFeeds += 1; sReadersContexts[dwContext]->vHandle = sReadersContexts[parentNode]->vHandle; sReadersContexts[dwContext]->mMutex = sReadersContexts[parentNode]->mMutex; sReadersContexts[dwContext]->pMutex = sReadersContexts[parentNode]->pMutex; /* Call on the parent driver to see if it is thread safe */ dwGetSize = sizeof(ucThread); rv = IFDGetCapabilities(sReadersContexts[parentNode], TAG_IFD_THREAD_SAFE, &dwGetSize, ucThread); if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1) { Log1(PCSC_LOG_INFO, "Driver is thread safe"); sReadersContexts[dwContext]->mMutex = NULL; sReadersContexts[dwContext]->pMutex = NULL; } else *(sReadersContexts[dwContext])->pMutex += 1; } if (sReadersContexts[dwContext]->pFeeds == NULL) { sReadersContexts[dwContext]->pFeeds = malloc(sizeof(int)); /* Initialize pFeeds to 1, otherwise multiple cloned readers will cause pcscd to crash when RFUnloadReader unloads the driver library and there are still devices attached using it --mikeg*/ *(sReadersContexts[dwContext])->pFeeds = 1; } if (sReadersContexts[dwContext]->mMutex == 0) { sReadersContexts[dwContext]->mMutex = malloc(sizeof(pthread_mutex_t)); (void)pthread_mutex_init(sReadersContexts[dwContext]->mMutex, NULL); } if (sReadersContexts[dwContext]->pMutex == NULL) { sReadersContexts[dwContext]->pMutex = malloc(sizeof(int)); *(sReadersContexts[dwContext])->pMutex = 1; } dwNumReadersContexts += 1; rv = RFInitializeReader(sReadersContexts[dwContext]); if (rv != SCARD_S_SUCCESS) { /* Cannot connect to reader. Exit gracefully */ Log2(PCSC_LOG_ERROR, "%s init failed.", readerName); (void)RFRemoveReader(readerName, port); return rv; } /* asynchronous card movement? */ { RESPONSECODE (*fct)(DWORD, int) = NULL; dwGetSize = sizeof(fct); rv = IFDGetCapabilities(sReadersContexts[dwContext], TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct); if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct))) { Log1(PCSC_LOG_INFO, "Using the pcscd polling thread"); } else { sReadersContexts[dwContext]->pthCardEvent = fct; Log1(PCSC_LOG_INFO, "Using the reader polling thread"); } rv = EHSpawnEventHandler(sReadersContexts[dwContext]); if (rv != SCARD_S_SUCCESS) { Log2(PCSC_LOG_ERROR, "%s init failed.", readerName); (void)RFRemoveReader(readerName, port); return rv; } } /* Call on the driver to see if there are multiple slots */ dwGetSize = sizeof(ucGetData); rv = IFDGetCapabilities((sReadersContexts[dwContext]), TAG_IFD_SLOTS_NUMBER, &dwGetSize, ucGetData); if (rv != IFD_SUCCESS || dwGetSize != 1 || ucGetData[0] == 0) /* Reader does not have this defined. Must be a single slot * reader so we can just return SCARD_S_SUCCESS. */ return SCARD_S_SUCCESS; if (rv == IFD_SUCCESS && dwGetSize == 1 && ucGetData[0] == 1) /* Reader has this defined and it only has one slot */ return SCARD_S_SUCCESS; /* * Check the number of slots and create a different * structure for each one accordingly */ /* Initialize the rest of the slots */ for (j = 1; j < ucGetData[0]; j++) { char *tmpReader = NULL; DWORD dwContextB = 0; RESPONSECODE (*fct)(DWORD, int) = NULL; /* We must find an empty spot to put the reader structure */ for (i = 0; i < PCSCLITE_MAX_READERS_CONTEXTS; i++) { if (sReadersContexts[i]->vHandle == 0) { dwContextB = i; break; } } if (i == PCSCLITE_MAX_READERS_CONTEXTS) { /* No more slot left return */ RFRemoveReader(readerName, port); return SCARD_E_NO_MEMORY; } /* Copy the previous reader name and increment the slot number */ tmpReader = sReadersContexts[dwContextB]->readerState->readerName; (void)strlcpy(tmpReader, sReadersContexts[dwContext]->readerState->readerName, sizeof(sReadersContexts[dwContextB]->readerState->readerName)); snprintf(tmpReader + strlen(tmpReader) - 2, 3, "%02X", j); sReadersContexts[dwContextB]->library = sReadersContexts[dwContext]->library; sReadersContexts[dwContextB]->device = sReadersContexts[dwContext]->device; sReadersContexts[dwContextB]->version = sReadersContexts[dwContext]->version; sReadersContexts[dwContextB]->port = sReadersContexts[dwContext]->port; sReadersContexts[dwContextB]->vHandle = sReadersContexts[dwContext]->vHandle; sReadersContexts[dwContextB]->mMutex = sReadersContexts[dwContext]->mMutex; sReadersContexts[dwContextB]->pMutex = sReadersContexts[dwContext]->pMutex; sReadersContexts[dwContextB]->slot = sReadersContexts[dwContext]->slot + j; sReadersContexts[dwContextB]->pthCardEvent = NULL; /* * Added by Dave - slots did not have a pFeeds * parameter so it was by luck they were working */ sReadersContexts[dwContextB]->pFeeds = sReadersContexts[dwContext]->pFeeds; /* Added by Dave for multiple slots */ *(sReadersContexts[dwContextB])->pFeeds += 1; sReadersContexts[dwContextB]->contexts = 0; sReadersContexts[dwContextB]->hLockId = 0; sReadersContexts[dwContextB]->LockCount = 0; lrv = list_init(&sReadersContexts[dwContextB]->handlesList); if (lrv < 0) { Log2(PCSC_LOG_CRITICAL, "list_init failed with return value: %d", lrv); return SCARD_E_NO_MEMORY; } lrv = list_attributes_seeker(&sReadersContexts[dwContextB]->handlesList, RDR_CLIHANDLES_seeker); if (lrv < 0) { Log2(PCSC_LOG_CRITICAL, "list_attributes_seeker failed with return value: %d", lrv); return SCARD_E_NO_MEMORY; } (void)pthread_mutex_init(&sReadersContexts[dwContextB]->handlesList_lock, NULL); (void)pthread_mutex_init(&sReadersContexts[dwContextB]->powerState_lock, NULL); sReadersContexts[dwContextB]->powerState = POWER_STATE_UNPOWERED; /* reference count */ (void)pthread_mutex_init(&sReadersContexts[dwContextB]->reference_lock, NULL); sReadersContexts[dwContextB]->reference = 1; /* Call on the parent driver to see if the slots are thread safe */ dwGetSize = sizeof(ucThread); rv = IFDGetCapabilities((sReadersContexts[dwContext]), TAG_IFD_SLOT_THREAD_SAFE, &dwGetSize, ucThread); if (rv == IFD_SUCCESS && dwGetSize == 1 && ucThread[0] == 1) { Log1(PCSC_LOG_INFO, "Driver is slot thread safe"); sReadersContexts[dwContextB]->library = strdup(sReadersContexts[dwContext]->library); sReadersContexts[dwContextB]->device = strdup(sReadersContexts[dwContext]->device); sReadersContexts[dwContextB]->mMutex = malloc(sizeof(pthread_mutex_t)); (void)pthread_mutex_init(sReadersContexts[dwContextB]->mMutex, NULL); sReadersContexts[dwContextB]->pMutex = malloc(sizeof(int)); *(sReadersContexts[dwContextB])->pMutex = 1; } else *(sReadersContexts[dwContextB])->pMutex += 1; dwNumReadersContexts += 1; rv = RFInitializeReader(sReadersContexts[dwContextB]); if (rv != SCARD_S_SUCCESS) { /* Cannot connect to slot. Exit gracefully */ (void)RFRemoveReader(readerName, port); return rv; } /* asynchronous card movement? */ dwGetSize = sizeof(fct); rv = IFDGetCapabilities((sReadersContexts[dwContextB]), TAG_IFD_POLLING_THREAD_WITH_TIMEOUT, &dwGetSize, (PUCHAR)&fct); if ((rv != SCARD_S_SUCCESS) || (dwGetSize != sizeof(fct))) { Log1(PCSC_LOG_INFO, "Using the pcscd polling thread"); } else { sReadersContexts[dwContextB]->pthCardEvent = fct; Log1(PCSC_LOG_INFO, "Using the reader polling thread"); } rv = EHSpawnEventHandler(sReadersContexts[dwContextB]); if (rv != SCARD_S_SUCCESS) { Log2(PCSC_LOG_ERROR, "%s init failed.", readerName); (void)RFRemoveReader(readerName, port); return rv; } } return SCARD_S_SUCCESS; }
int main(int argc, char **argv) { int rv; char setToForeground; char HotPlug; char *newReaderConfig; struct stat fStatBuf; int opt; #ifdef HAVE_GETOPT_LONG int option_index = 0; static struct option long_options[] = { {"config", 1, 0, 'c'}, {"foreground", 0, 0, 'f'}, {"help", 0, 0, 'h'}, {"version", 0, 0, 'v'}, {"apdu", 0, 0, 'a'}, {"debug", 0, 0, 'd'}, {"info", 0, 0, 0}, {"error", 0, 0, 'e'}, {"critical", 0, 0, 'C'}, {"hotplug", 0, 0, 'H'}, {"force-reader-polling", optional_argument, 0, 0}, {0, 0, 0, 0} }; #endif #define OPT_STRING "c:fdhvaeCH" rv = 0; newReaderConfig = NULL; setToForeground = 0; HotPlug = 0; globalArgv = argv; /* * test the version */ if (strcmp(PCSCLITE_VERSION_NUMBER, VERSION) != 0) { printf("BUILD ERROR: The release version number PCSCLITE_VERSION_NUMBER\n"); printf(" in pcsclite.h (%s) does not match the release version number\n", PCSCLITE_VERSION_NUMBER); printf(" generated in config.h (%s) (see configure.in).\n", VERSION); return EXIT_FAILURE; } /* * By default we create a daemon (not connected to any output) * The log will go to wherever securityd log output goes. */ DebugLogSetLogType(DEBUGLOG_NO_DEBUG); /* * Handle any command line arguments */ #ifdef HAVE_GETOPT_LONG while ((opt = getopt_long (argc, argv, OPT_STRING, long_options, &option_index)) != -1) { #else while ((opt = getopt (argc, argv, OPT_STRING)) != -1) { #endif switch (opt) { #ifdef HAVE_GETOPT_LONG case 0: if (strcmp(long_options[option_index].name, "force-reader-polling") == 0) HPForceReaderPolling = optarg ? abs(atoi(optarg)) : 1; break; #endif case 'c': Log2(PCSC_LOG_INFO, "using new config file: %s", optarg); newReaderConfig = optarg; break; case 'f': setToForeground = 1; /* debug to stderr instead of default syslog */ Log1(PCSC_LOG_INFO, "pcscd set to foreground with debug send to stderr"); break; case 'd': DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG); DebugLogSetLevel(PCSC_LOG_DEBUG); break; case 'e': DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG); DebugLogSetLevel(PCSC_LOG_ERROR); break; case 'C': DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG); DebugLogSetLevel(PCSC_LOG_CRITICAL); break; case 'h': print_usage (argv[0]); return EXIT_SUCCESS; case 'v': print_version (); return EXIT_SUCCESS; case 'a': DebugLogSetCategory(DEBUG_CATEGORY_APDU); break; case 'H': /* debug to stderr instead of default syslog */ DebugLogSetLogType(DEBUGLOG_STDERR_DEBUG); HotPlug = 1; break; default: print_usage (argv[0]); return EXIT_FAILURE; } } if (argv[optind]) { printf("Unknown option: %s\n\n", argv[optind]); print_usage(argv[0]); return EXIT_SUCCESS; } /* If this run of pcscd has the hotplug option, just send a signal to the running one and exit */ if (HotPlug) return ProcessHotplugRequest(); /* * test the presence of /var/run/pcsc.comm */ rv = SYS_Stat(PCSCLITE_CSOCK_NAME, &fStatBuf); if (rv == 0) { #ifdef USE_RUN_PID pid_t pid; /* read the pid file to get the old pid and test if the old pcscd is * still running */ pid = GetDaemonPid(); if (pid != -1) { if (kill(pid, 0) == 0) { Log2(PCSC_LOG_CRITICAL, "Another pcscd (pid: %d) seems to be running.", pid); Log1(PCSC_LOG_CRITICAL, "Remove " USE_RUN_PID " if pcscd is not running to clear this message."); return EXIT_FAILURE; } else /* the old pcscd is dead. Do some cleanup */ clean_temp_files(); } #else { Log1(PCSC_LOG_CRITICAL, "file " PCSCLITE_CSOCK_NAME " already exists."); Log1(PCSC_LOG_CRITICAL, "Maybe another pcscd is running?"); Log1(PCSC_LOG_CRITICAL, "Remove " PCSCLITE_CSOCK_NAME "if pcscd is not running to clear this message."); return EXIT_FAILURE; } #endif } /* * If this is set to one the user has asked it not to fork */ if (!setToForeground) { if (SYS_Daemon(0, 0)) Log2(PCSC_LOG_CRITICAL, "SYS_Daemon() failed: %s", strerror(errno)); } /* * cleanly remove /tmp/pcsc when exiting */ signal(SIGQUIT, signal_trap); signal(SIGTERM, signal_trap); signal(SIGINT, signal_trap); signal(SIGHUP, signal_trap); #ifdef USE_RUN_PID /* * Record our pid to make it easier * to kill the correct pcscd */ { FILE *f; if ((f = fopen(USE_RUN_PID, "wb")) != NULL) { fprintf(f, "%u\n", (unsigned) getpid()); fclose(f); } } #endif /* * If PCSCLITE_IPC_DIR does not exist then create it */ rv = SYS_Stat(PCSCLITE_IPC_DIR, &fStatBuf); if (rv < 0) { rv = SYS_Mkdir(PCSCLITE_IPC_DIR, S_ISVTX | S_IRWXO | S_IRWXG | S_IRWXU); if (rv != 0) { Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_IPC_DIR ": %s", strerror(errno)); return EXIT_FAILURE; } } /* cleanly remove /var/run/pcsc.* files when exiting */ if (atexit(at_exit)) Log2(PCSC_LOG_CRITICAL, "atexit() failed: %s", strerror(errno)); /* * Allocate memory for reader structures */ RFAllocateReaderSpace(); /* Grab the information from the reader.conf. If a file has been specified and there is any error, consider it fatal. If no file was explicitly specified, ignore if file not present. DBUpdateReaders returns: 1 if config file can't be opened -1 if config file is broken 0 if all good We skip this step if running in 64 bit mode, as serial readers are considered legacy code. */ rv = RFStartSerialReaders(newReaderConfig?newReaderConfig:PCSCLITE_READER_CONFIG); if (rv == -1) { Log3(PCSC_LOG_CRITICAL, "invalid file %s: %s", newReaderConfig, strerror(errno)); at_exit(); } else if ((rv == 1) && newReaderConfig) { Log3(PCSC_LOG_CRITICAL, "file %s can't be opened: %s", newReaderConfig, strerror(errno)); at_exit(); } /* * Set the default globals */ g_rgSCardT0Pci.dwProtocol = SCARD_PROTOCOL_T0; g_rgSCardT1Pci.dwProtocol = SCARD_PROTOCOL_T1; g_rgSCardRawPci.dwProtocol = SCARD_PROTOCOL_RAW; Log1(PCSC_LOG_INFO, "pcsc-lite " VERSION " daemon ready."); /* * post initialistion */ Init = 0; /* * signal_trap() does just set a global variable used by the main loop */ signal(SIGQUIT, signal_trap); signal(SIGTERM, signal_trap); signal(SIGINT, signal_trap); signal(SIGHUP, signal_trap); signal(SIGUSR1, signal_reload); SVCServiceRunLoop(); Log1(PCSC_LOG_ERROR, "SVCServiceRunLoop returned"); return EXIT_FAILURE; } void at_exit(void) { Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR); clean_temp_files(); SYS_Exit(EXIT_SUCCESS); }
static int dds_op_extended( Operation *op, SlapReply *rs ) { slap_overinst *on = (slap_overinst *)op->o_bd->bd_info; dds_info_t *di = on->on_bi.bi_private; if ( DDS_OFF( di ) ) { return SLAP_CB_CONTINUE; } if ( bvmatch( &op->ore_reqoid, &slap_EXOP_REFRESH ) ) { Entry *e = NULL; time_t ttl; BackendDB db = *op->o_bd; SlapReply rs2 = { REP_RESULT }; Operation op2 = *op; slap_callback sc = { 0 }; Modifications ttlmod = { { 0 } }; struct berval ttlvalues[ 2 ]; char ttlbuf[STRLENOF("31557600") + 1]; rs->sr_err = slap_parse_refresh( op->ore_reqdata, NULL, &ttl, &rs->sr_text, NULL ); assert( rs->sr_err == LDAP_SUCCESS ); if ( ttl <= 0 || ttl > DDS_RF2589_MAX_TTL ) { rs->sr_err = LDAP_PROTOCOL_ERROR; rs->sr_text = "invalid time-to-live for dynamicObject"; return rs->sr_err; } if ( ttl > di->di_max_ttl ) { /* FIXME: I don't understand if this has to be an error, * or an indication that the requested Ttl has been * shortened to di->di_max_ttl >= 1 day */ rs->sr_err = LDAP_SIZELIMIT_EXCEEDED; rs->sr_text = "time-to-live for dynamicObject exceeds limit"; return rs->sr_err; } if ( di->di_min_ttl && ttl < di->di_min_ttl ) { ttl = di->di_min_ttl; } /* This does not apply to multi-master case */ if ( !( !SLAP_SINGLE_SHADOW( op->o_bd ) || be_isupdate( op ) ) ) { /* we SHOULD return a referral in this case */ BerVarray defref = op->o_bd->be_update_refs ? op->o_bd->be_update_refs : default_referral; if ( defref != NULL ) { rs->sr_ref = referral_rewrite( op->o_bd->be_update_refs, NULL, NULL, LDAP_SCOPE_DEFAULT ); if ( rs->sr_ref ) { rs->sr_flags |= REP_REF_MUSTBEFREED; } else { rs->sr_ref = defref; } rs->sr_err = LDAP_REFERRAL; } else { rs->sr_text = "shadow context; no update referral"; rs->sr_err = LDAP_UNWILLING_TO_PERFORM; } return rs->sr_err; } assert( !BER_BVISNULL( &op->o_req_ndn ) ); /* check if exists but not dynamicObject */ op->o_bd->bd_info = (BackendInfo *)on->on_info; rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn, slap_schema.si_oc_dynamicObject, NULL, 0, &e ); if ( rs->sr_err != LDAP_SUCCESS ) { rs->sr_err = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &e ); if ( rs->sr_err == LDAP_SUCCESS && e != NULL ) { /* return referral only if "disclose" * is granted on the object */ if ( ! access_allowed( op, e, slap_schema.si_ad_entry, NULL, ACL_DISCLOSE, NULL ) ) { rs->sr_err = LDAP_NO_SUCH_OBJECT; } else { rs->sr_err = LDAP_OBJECT_CLASS_VIOLATION; rs->sr_text = "refresh operation only applies to dynamic objects"; } be_entry_release_r( op, e ); } else { rs->sr_err = LDAP_NO_SUCH_OBJECT; } return rs->sr_err; } else if ( e != NULL ) { be_entry_release_r( op, e ); } /* we require manage privileges on the entryTtl, * and fake a Relax control */ op2.o_tag = LDAP_REQ_MODIFY; op2.o_bd = &db; db.bd_info = (BackendInfo *)on->on_info; op2.o_callback = ≻ sc.sc_response = slap_null_cb; op2.o_relax = SLAP_CONTROL_CRITICAL; op2.orm_modlist = &ttlmod; ttlmod.sml_op = LDAP_MOD_REPLACE; ttlmod.sml_flags = SLAP_MOD_MANAGING; ttlmod.sml_desc = slap_schema.si_ad_entryTtl; ttlmod.sml_values = ttlvalues; ttlmod.sml_numvals = 1; ttlvalues[ 0 ].bv_val = ttlbuf; ttlvalues[ 0 ].bv_len = snprintf( ttlbuf, sizeof( ttlbuf ), "%ld", ttl ); BER_BVZERO( &ttlvalues[ 1 ] ); /* the entryExpireTimestamp is added by modify */ rs->sr_err = op2.o_bd->be_modify( &op2, &rs2 ); if ( ttlmod.sml_next != NULL ) { slap_mods_free( ttlmod.sml_next, 1 ); } if ( rs->sr_err == LDAP_SUCCESS ) { int rc; BerElementBuffer berbuf; BerElement *ber = (BerElement *)&berbuf; if ( rs->sr_err == LDAP_SUCCESS ) { ber_init_w_nullc( ber, LBER_USE_DER ); rc = ber_printf( ber, "{tiN}", LDAP_TAG_EXOP_REFRESH_RES_TTL, (int)ttl ); if ( rc < 0 ) { rs->sr_err = LDAP_OTHER; rs->sr_text = "internal error"; } else { (void)ber_flatten( ber, &rs->sr_rspdata ); rs->sr_rspoid = ch_strdup( slap_EXOP_REFRESH.bv_val ); Log3( LDAP_DEBUG_TRACE, LDAP_LEVEL_INFO, "%s REFRESH dn=\"%s\" TTL=%ld\n", op->o_log_prefix, op->o_req_ndn.bv_val, ttl ); } ber_free_buf( ber ); } } return rs->sr_err; } return SLAP_CB_CONTINUE; }