예제 #1
0
LONG IFDControl(READER_CONTEXT * rContext, DWORD ControlCode,
	LPCVOID TxBuffer, DWORD TxLength, LPVOID RxBuffer, DWORD RxLength,
	LPDWORD BytesReturned)
{
	RESPONSECODE rv = IFD_SUCCESS;

#ifndef PCSCLITE_STATIC_DRIVER
	RESPONSECODE(*IFDH_control) (DWORD, DWORD, LPCVOID, DWORD, LPVOID, DWORD, LPDWORD);
#endif

	if (rContext->version < IFD_HVERSION_3_0)
		return SCARD_E_UNSUPPORTED_FEATURE;

#ifndef PCSCLITE_STATIC_DRIVER
	IFDH_control = rContext->psFunctions.psFunctions_v3.pvfControl;
#endif

	/* LOCK THIS CODE REGION */
	(void)pthread_mutex_lock(rContext->mMutex);

#ifndef PCSCLITE_STATIC_DRIVER
	rv = (*IFDH_control) (rContext->slot, ControlCode, TxBuffer,
		TxLength, RxBuffer, RxLength, BytesReturned);
#elif defined(IFDHANDLERv3)
	rv = IFDHControl(rContext->slot, ControlCode, TxBuffer,
		TxLength, RxBuffer, RxLength, BytesReturned);
#endif

	/* END OF LOCKED REGION */
	(void)pthread_mutex_unlock(rContext->mMutex);

	if (rv == IFD_SUCCESS)
		return SCARD_S_SUCCESS;
	else
	{
		Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
		Log3(PCSC_LOG_DEBUG, "ControlCode: 0x%.8lX BytesReturned: %ld",
			ControlCode, *BytesReturned);
		LogXxd(PCSC_LOG_DEBUG, "TxBuffer ", TxBuffer, TxLength);
		LogXxd(PCSC_LOG_DEBUG, "RxBuffer ", RxBuffer, *BytesReturned);

		if (rv == IFD_NO_SUCH_DEVICE)
		{
			(void)SendHotplugSignal();
			return SCARD_E_READER_UNAVAILABLE;
		}

		if ((IFD_ERROR_NOT_SUPPORTED == rv) || (IFD_NOT_SUPPORTED == rv))
			return SCARD_E_UNSUPPORTED_FEATURE;

        if (IFD_ERROR_INSUFFICIENT_BUFFER ==rv)
            return SCARD_E_INSUFFICIENT_BUFFER;

		return SCARD_E_NOT_TRANSACTED;
	}
}
예제 #2
0
int ProcessHotplugRequest()
{
#ifdef USE_RUN_PID

	/* read the pid file to get the old pid and test if the old pcscd is
	 * still running
	 */
	if (GetDaemonPid() != -1)
		return SendHotplugSignal();

	Log1(PCSC_LOG_CRITICAL, "file " USE_RUN_PID " does not exist");
	Log1(PCSC_LOG_CRITICAL,	"Perhaps pcscd is not running?");
#else
	struct stat tmpStat;
	if (SYS_Stat(PCSCLITE_CSOCK_NAME, &tmpStat) == 0)	// socket file exists, so maybe pcscd is running
		return SendHotplugSignal();
	Log1(PCSC_LOG_CRITICAL, "pcscd was not configured with --enable-runpid=FILE");
#endif
	Log1(PCSC_LOG_CRITICAL, "Hotplug failed");
	return EXIT_FAILURE;
}
예제 #3
0
/**
 * Transmit an APDU to the ICC.
 */
LONG IFDTransmit(READER_CONTEXT * rContext, SCARD_IO_HEADER pioTxPci,
	PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer,
	PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
{
	RESPONSECODE rv;

#ifndef PCSCLITE_STATIC_DRIVER
	RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR,
		DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
#endif

	/* log the APDU */
	DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength);

#ifndef PCSCLITE_STATIC_DRIVER
	IFDH_transmit_to_icc =
		rContext->psFunctions.psFunctions_v2.pvfTransmitToICC;
#endif

	/* LOCK THIS CODE REGION */
	(void)pthread_mutex_lock(rContext->mMutex);

#ifndef PCSCLITE_STATIC_DRIVER
	rv = (*IFDH_transmit_to_icc) (rContext->slot, pioTxPci, (LPBYTE)
		pucTxBuffer, dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
#else
	rv = IFDHTransmitToICC(rContext->slot, pioTxPci,
		(LPBYTE) pucTxBuffer, dwTxLength,
		pucRxBuffer, pdwRxLength, pioRxPci);
#endif

	/* END OF LOCKED REGION */
	(void)pthread_mutex_unlock(rContext->mMutex);

	/* log the returned status word */
	DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength);

	if (rv == IFD_SUCCESS)
		return SCARD_S_SUCCESS;
	else
	{
		Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);

		if (rv == IFD_NO_SUCH_DEVICE)
		{
			(void)SendHotplugSignal();
			return SCARD_E_READER_UNAVAILABLE;
		}

		return SCARD_E_NOT_TRANSACTED;
	}
}
예제 #4
0
/**
 * Provide statistical information about the IFD and ICC including insertions,
 * atr, powering status/etc.
 */
LONG IFDStatusICC(READER_CONTEXT * rContext, PDWORD pdwStatus)
{
	RESPONSECODE rv;
	DWORD dwCardStatus = 0;

#ifndef PCSCLITE_STATIC_DRIVER
	RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL;

	IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence;
#endif

	/* LOCK THIS CODE REGION */
	(void)pthread_mutex_lock(rContext->mMutex);

#ifndef PCSCLITE_STATIC_DRIVER
	rv = (*IFDH_icc_presence) (rContext->slot);
#else
	rv = IFDHICCPresence(rContext->slot);
#endif

	/* END OF LOCKED REGION */
	(void)pthread_mutex_unlock(rContext->mMutex);

	if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
		dwCardStatus |= SCARD_PRESENT;
	else
		if (rv == IFD_ICC_NOT_PRESENT)
			dwCardStatus |= SCARD_ABSENT;
		else
		{
			Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
			*pdwStatus = SCARD_UNKNOWN;

			if (rv == IFD_NO_SUCH_DEVICE)
			{
				(void)SendHotplugSignal();
				return SCARD_E_READER_UNAVAILABLE;
			}

			return SCARD_E_NOT_TRANSACTED;
		}

	*pdwStatus = dwCardStatus;

	return SCARD_S_SUCCESS;
}
예제 #5
0
int main(int argc, char **argv)
{
	int rv;
	char setToForeground;
	char HotPlug;
	char *newReaderConfig;
	struct stat fStatBuf;
	int customMaxThreadCounter = 0;
	int customMaxReaderHandles = 0;
	int customMaxThreadCardHandles = 0;
	int opt;
	int limited_rights = FALSE;
	int r;
#ifdef HAVE_GETOPT_LONG
	int option_index = 0;
	static struct option long_options[] = {
		{"config", 1, NULL, 'c'},
		{"foreground", 0, NULL, 'f'},
		{"color", 0, NULL, 'T'},
		{"help", 0, NULL, 'h'},
		{"version", 0, NULL, 'v'},
		{"apdu", 0, NULL, 'a'},
		{"debug", 0, NULL, 'd'},
		{"info", 0, NULL, 0},
		{"error", 0, NULL, 'e'},
		{"critical", 0, NULL, 'C'},
		{"hotplug", 0, NULL, 'H'},
		{"force-reader-polling", optional_argument, NULL, 0},
		{"max-thread", 1, NULL, 't'},
		{"max-card-handle-per-thread", 1, NULL, 's'},
		{"max-card-handle-per-reader", 1, NULL, 'r'},
		{"auto-exit", 0, NULL, 'x'},
		{"reader-name-no-serial", 0, NULL, 'S'},
		{"reader-name-no-interface", 0, NULL, 'I'},
		{NULL, 0, NULL, 0}
	};
#endif
#define OPT_STRING "c:fTdhvaeCHt:r:s:xSI"

	newReaderConfig = NULL;
	setToForeground = FALSE;
	HotPlug = FALSE;

	/*
	 * 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)
	 * so log to syslog to have error messages.
	 */
	DebugLogSetLogType(DEBUGLOG_SYSLOG_DEBUG);

	/* if the process is setuid or setgid it may have some restrictions */
	limited_rights = (getgid() != getegid()) && (getuid() != 0);

	/*
	 * 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':
				if (limited_rights)
				{
					Log1(PCSC_LOG_CRITICAL, "Can't use a user specified config file");
					return EXIT_FAILURE;
				}
				Log2(PCSC_LOG_INFO, "using new config file: %s", optarg);
				newReaderConfig = optarg;
				break;

			case 'f':
				setToForeground = TRUE;
				/* debug to stdout instead of default syslog */
				DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
				Log1(PCSC_LOG_INFO,
					"pcscd set to foreground with debug send to stdout");
				break;

			case 'T':
				DebugLogSetLogType(DEBUGLOG_STDOUT_COLOR_DEBUG);
				Log1(PCSC_LOG_INFO, "Force colored logs");
				break;

			case 'd':
				DebugLogSetLevel(PCSC_LOG_DEBUG);
				break;

			case 'e':
				DebugLogSetLevel(PCSC_LOG_ERROR);
				break;

			case 'C':
				DebugLogSetLevel(PCSC_LOG_CRITICAL);
				break;

			case 'h':
				print_usage (argv[0]);
				return EXIT_SUCCESS;

			case 'v':
				print_version ();
				return EXIT_SUCCESS;

			case 'a':
				if (limited_rights)
				{
					Log1(PCSC_LOG_CRITICAL, "Can't log APDU (restricted)");
					return EXIT_FAILURE;
				}
				(void)DebugLogSetCategory(DEBUG_CATEGORY_APDU);
				break;

			case 'H':
				/* debug to stdout instead of default syslog */
				DebugLogSetLogType(DEBUGLOG_STDOUT_DEBUG);
				HotPlug = TRUE;
				break;

			case 't':
				customMaxThreadCounter = optarg ? atoi(optarg) : 0;
				if (limited_rights && (customMaxThreadCounter < PCSC_MAX_CONTEXT_THREADS))
					customMaxThreadCounter = PCSC_MAX_CONTEXT_THREADS;
				Log2(PCSC_LOG_INFO, "setting customMaxThreadCounter to: %d",
					customMaxThreadCounter);
				break;

			case 'r':
				customMaxReaderHandles = optarg ? atoi(optarg) : 0;
				if (limited_rights && (customMaxReaderHandles < PCSC_MAX_READER_HANDLES))
					customMaxReaderHandles = PCSC_MAX_READER_HANDLES;
				Log2(PCSC_LOG_INFO, "setting customMaxReaderHandles to: %d",
					customMaxReaderHandles);
				break;

			case 's':
				customMaxThreadCardHandles = optarg ? atoi(optarg) : 0;
				if (limited_rights && (customMaxThreadCardHandles < PCSC_MAX_CONTEXT_CARD_HANDLES))
					customMaxThreadCardHandles = PCSC_MAX_CONTEXT_CARD_HANDLES;
				Log2(PCSC_LOG_INFO, "setting customMaxThreadCardHandles to: %d",
					customMaxThreadCardHandles);
				break;

			case 'x':
				AutoExit = TRUE;
				Log2(PCSC_LOG_INFO, "Auto exit after %d seconds of inactivity",
					TIME_BEFORE_SUICIDE);
				break;

			case 'S':
				Add_Serial_In_Name = FALSE;
				break;

			case 'I':
				Add_Interface_In_Name = FALSE;
				break;

			default:
				print_usage (argv[0]);
				return EXIT_FAILURE;
		}

	}

	if (argv[optind])
	{
		printf("Unknown option: %s\n", argv[optind]);
		print_usage(argv[0]);
		return EXIT_FAILURE;
	}

	/*
	 * Check if systemd passed us any file descriptors
	 */
	rv = sd_listen_fds(0);
	if (rv > 1)
	{
		Log1(PCSC_LOG_CRITICAL, "Too many file descriptors received");
		return EXIT_FAILURE;
	}
	else
	{
		if (rv == 1)
		{
			SocketActivated = TRUE;
			Log1(PCSC_LOG_INFO, "Started by systemd");
		}
		else
			SocketActivated = FALSE;
	}

	/*
	 * test the presence of /var/run/pcscd/pcscd.comm
	 */

	rv = stat(PCSCLITE_CSOCK_NAME, &fStatBuf);

	if (rv == 0)
	{
		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 (HotPlug)
				return SendHotplugSignal();

			rv = kill(pid, 0);
			if (0 == rv)
			{
				Log1(PCSC_LOG_CRITICAL,
					"file " PCSCLITE_CSOCK_NAME " already exists.");
				Log2(PCSC_LOG_CRITICAL,
					"Another pcscd (pid: %d) seems to be running.", pid);
				return EXIT_FAILURE;
			}
			else
				if (ESRCH == errno)
				{
					/* the old pcscd is dead. make some cleanup */
					clean_temp_files();
				}
				else
				{
					/* permission denied or other error */
					Log2(PCSC_LOG_CRITICAL, "kill failed: %s", strerror(errno));
					return EXIT_FAILURE;
				}
		}
		else
		{
			if (HotPlug)
			{
				Log1(PCSC_LOG_CRITICAL, "file " PCSCLITE_RUN_PID " do not exist");
				Log1(PCSC_LOG_CRITICAL, "Hotplug failed");
				return EXIT_FAILURE;
			}
		}
	}
	else
		if (HotPlug)
		{
			Log1(PCSC_LOG_CRITICAL, "Hotplug failed: pcscd is not running");
			return EXIT_FAILURE;
		}

	/* like in daemon(3): changes the current working directory to the
	 * root ("/") */
	r = chdir("/");
	if (r < 0)
	{
		Log2(PCSC_LOG_CRITICAL, "chdir() failed: %s", strerror(errno));
		return EXIT_FAILURE;
	}

	/*
	 * If this is set to one the user has asked it not to fork
	 */
	if (!setToForeground)
	{
		int pid;
		int fd;

		if (pipe(pipefd) == -1)
		{
			Log2(PCSC_LOG_CRITICAL, "pipe() failed: %s", strerror(errno));
			return EXIT_FAILURE;
		}

		pid = fork();
		if (-1 == pid)
		{
			Log2(PCSC_LOG_CRITICAL, "fork() failed: %s", strerror(errno));
			return EXIT_FAILURE;
		}

		/* like in daemon(3): redirect standard input, standard output
		 * and standard error to /dev/null */
		fd = open("/dev/null", O_RDWR);
		if (fd != -1)
		{
			dup2(fd, STDIN_FILENO);
			dup2(fd, STDOUT_FILENO);
			dup2(fd, STDERR_FILENO);

			/* do not close stdin, stdout or stderr */
			if (fd > 2)
				close(fd);
		}

		if (pid)
		/* in the father */
		{
			char buf;
			int ret;

			/* close write side */
			close(pipefd[1]);

			/* wait for the son to write the return code */
			ret = read(pipefd[0], &buf, 1);
			if (ret <= 0)
				return 2;

			close(pipefd[0]);

			/* exit code */
			return buf;
		}
		else
		/* in the son */
		{
			/* close read side */
			close(pipefd[0]);
		}
	}

	/*
	 * cleanly remove /var/run/pcscd/files when exiting
	 * signal_trap() does just set a global variable used by the main loop
	 */
	(void)signal(SIGQUIT, signal_trap);
	(void)signal(SIGTERM, signal_trap); /* default kill signal & init round 1 */
	(void)signal(SIGINT, signal_trap);	/* sent by Ctrl-C */

	/* exits on SIGALARM to allow pcscd to suicide if not used */
	(void)signal(SIGALRM, signal_trap);

	/*
	 * If PCSCLITE_IPC_DIR does not exist then create it
	 */
	{
		int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;

		rv = mkdir(PCSCLITE_IPC_DIR, mode);
		if ((rv != 0) && (errno != EEXIST))
		{
			Log2(PCSC_LOG_CRITICAL,
				"cannot create " PCSCLITE_IPC_DIR ": %s", strerror(errno));
			return EXIT_FAILURE;
		}

		/* set mode so that the directory is world readable and
		 * executable even is umask is restrictive
		 * The directory containes files used by libpcsclite */
		(void)chmod(PCSCLITE_IPC_DIR, mode);
	}

	/*
	 * Allocate memory for reader structures
	 */
	rv = RFAllocateReaderSpace(customMaxReaderHandles);
	if (SCARD_S_SUCCESS != rv)
		at_exit();

#ifdef USE_SERIAL
	/*
	 * Grab the information from the reader.conf
	 */
	if (newReaderConfig)
	{
		rv = RFStartSerialReaders(newReaderConfig);
		if (rv != 0)
		{
			Log3(PCSC_LOG_CRITICAL, "invalid file %s: %s", newReaderConfig,
				strerror(errno));
			at_exit();
		}
	}
	else
	{
		rv = RFStartSerialReaders(PCSCLITE_CONFIG_DIR);
		if (rv == -1)
			at_exit();
	}
#endif

	Log1(PCSC_LOG_INFO, "pcsc-lite " VERSION " daemon ready.");

	/*
	 * Record our pid to make it easier
	 * to kill the correct pcscd
	 *
	 * Do not fork after this point or the stored pid will be wrong
	 */
	{
		int f;
		int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

		f = open(PCSCLITE_RUN_PID, O_RDWR | O_CREAT, mode);
		if (f != -1)
		{
			char pid[PID_ASCII_SIZE];
			ssize_t rr;

			(void)snprintf(pid, sizeof(pid), "%u\n", (unsigned) getpid());
			rr = write(f, pid, strlen(pid) + 1);
			if (rr < 0)
			{
				Log2(PCSC_LOG_CRITICAL,
					"writing " PCSCLITE_RUN_PID " failed: %s",
					strerror(errno));
			}
			(void)close(f);

			/* set mode so that the file is world readable even is umask is
			 * restrictive
			 * The file is used by libpcsclite */
			(void)chmod(PCSCLITE_RUN_PID, mode);
		}
		else
			Log2(PCSC_LOG_CRITICAL, "cannot create " PCSCLITE_RUN_PID ": %s",
				strerror(errno));
	}

	/*
	 * post initialistion
	 */
	Init = FALSE;

	/*
	 * Hotplug rescan
	 */
	(void)signal(SIGUSR1, signal_reload);

	/*
	 * Initialize the comm structure
	 */
	if (SocketActivated)
		rv = ListenExistingSocket(SD_LISTEN_FDS_START + 0);
	else
		rv = InitializeSocket();

	if (rv)
	{
		Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
		at_exit();
	}

	/*
	 * Initialize the contexts structure
	 */
	rv = ContextsInitialize(customMaxThreadCounter, customMaxThreadCardHandles);

	if (rv == -1)
	{
		Log1(PCSC_LOG_CRITICAL, "Error initializing pcscd.");
		at_exit();
	}

	(void)signal(SIGPIPE, SIG_IGN);
	(void)signal(SIGHUP, SIG_IGN);	/* needed for Solaris. The signal is sent
				 * when the shell is existed */

#if !defined(PCSCLITE_STATIC_DRIVER) && defined(USE_USB)
	/*
	 * Set up the search for USB/PCMCIA devices
	 */
	rv = HPSearchHotPluggables();
#ifndef USE_SERIAL
	if (rv)
		at_exit();
#endif

	rv = HPRegisterForHotplugEvents();
	if (rv)
	{
		Log1(PCSC_LOG_ERROR, "HPRegisterForHotplugEvents failed");
		at_exit();
	}

	RFWaitForReaderInit();
#endif

	/*
	 * Set up the power management callback routine
	 */
	(void)PMRegisterForPowerEvents();

	/* initialisation succeeded */
	if (pipefd[1] >= 0)
	{
		char buf = 0;
		ssize_t rr;

		/* write a 0 (success) to father process */
		rr = write(pipefd[1], &buf, 1);
		if (rr < 0)
		{
			Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
		}
		close(pipefd[1]);
	}

	SVCServiceRunLoop();

	Log1(PCSC_LOG_ERROR, "SVCServiceRunLoop returned");
	return EXIT_FAILURE;
}

static void at_exit(void)
{
	Log1(PCSC_LOG_INFO, "cleaning " PCSCLITE_IPC_DIR);

	clean_temp_files();

	if (pipefd[1] >= 0)
	{
		char buf;
		ssize_t r;

		/* write the error code to father process */
		buf = ExitValue;
		r = write(pipefd[1], &buf, 1);
		if (r < 0)
		{
			Log2(PCSC_LOG_ERROR, "write() failed: %s", strerror(errno));
		}
		close(pipefd[1]);
	}

	exit(ExitValue);
}
예제 #6
0
/**
 * Transmit an APDU to the ICC.
 */
LONG IFDTransmit(PREADER_CONTEXT rContext, SCARD_IO_HEADER pioTxPci,
	PUCHAR pucTxBuffer, DWORD dwTxLength, PUCHAR pucRxBuffer,
	PDWORD pdwRxLength, PSCARD_IO_HEADER pioRxPci)
{
	RESPONSECODE rv = IFD_SUCCESS;
	UCHAR ucValue[1] = "\x00";

#ifndef PCSCLITE_STATIC_DRIVER
	RESPONSECODE(*IFD_transmit_to_icc) (SCARD_IO_HEADER, PUCHAR, DWORD,
		/*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
	RESPONSECODE(*IFDH_transmit_to_icc) (DWORD, SCARD_IO_HEADER, PUCHAR,
		DWORD, /*@out@*/ PUCHAR, PDWORD, PSCARD_IO_HEADER) = NULL;
#endif

	/* log the APDU */
	DebugLogCategory(DEBUG_CATEGORY_APDU, pucTxBuffer, dwTxLength);

#ifndef PCSCLITE_STATIC_DRIVER
	if (rContext->dwVersion == IFD_HVERSION_1_0)
		IFD_transmit_to_icc =
			rContext->psFunctions.psFunctions_v1.pvfTransmitToICC;
	else
		IFDH_transmit_to_icc =
			rContext->psFunctions.psFunctions_v2.pvfTransmitToICC;
#endif

	/* LOCK THIS CODE REGION */
	(void)SYS_MutexLock(rContext->mMutex);

#ifndef PCSCLITE_STATIC_DRIVER
	if (rContext->dwVersion == IFD_HVERSION_1_0)
	{
		ucValue[0] = rContext->dwSlot;
		(void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
		rv = (*IFD_transmit_to_icc) (pioTxPci, (LPBYTE) pucTxBuffer,
			dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
	}
	else
		rv = (*IFDH_transmit_to_icc) (rContext->dwSlot, pioTxPci,
			(LPBYTE) pucTxBuffer, dwTxLength,
			pucRxBuffer, pdwRxLength, pioRxPci);
#else
	if (rContext->dwVersion == IFD_HVERSION_1_0)
	{
		ucValue[0] = rContext->dwSlot;
		(void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
		rv = IFD_Transmit_to_ICC(pioTxPci, (LPBYTE) pucTxBuffer,
			dwTxLength, pucRxBuffer, pdwRxLength, pioRxPci);
	}
	else
		rv = IFDHTransmitToICC(rContext->dwSlot, pioTxPci,
			(LPBYTE) pucTxBuffer, dwTxLength,
			pucRxBuffer, pdwRxLength, pioRxPci);
#endif

	/* END OF LOCKED REGION */
	(void)SYS_MutexUnLock(rContext->mMutex);

	/* log the returned status word */
	DebugLogCategory(DEBUG_CATEGORY_SW, pucRxBuffer, *pdwRxLength);

	if (rv == IFD_SUCCESS)
		return SCARD_S_SUCCESS;
	else
	{
		Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);

		if (rv == IFD_NO_SUCH_DEVICE)
		{
			(void)SendHotplugSignal();
			return SCARD_E_READER_UNAVAILABLE;
		}

		return SCARD_E_NOT_TRANSACTED;
	}
}
예제 #7
0
/**
 * Provide statistical information about the IFD and ICC including insertions,
 * atr, powering status/etc.
 */
LONG IFDStatusICC(PREADER_CONTEXT rContext, PDWORD pdwStatus,
	PUCHAR pucAtr, PDWORD pdwAtrLen)
{
	RESPONSECODE rv = IFD_SUCCESS;
	DWORD dwTag = 0, dwCardStatus = 0;
	SMARTCARD_EXTENSION sSmartCard;
	UCHAR ucValue[1] = "\x00";

#ifndef PCSCLITE_STATIC_DRIVER
	RESPONSECODE(*IFD_is_icc_present) (void) = NULL;
	RESPONSECODE(*IFDH_icc_presence) (DWORD) = NULL;
	RESPONSECODE(*IFD_get_capabilities) (DWORD, /*@out@*/ PUCHAR) = NULL;

	if (rContext->dwVersion == IFD_HVERSION_1_0)
	{
		IFD_is_icc_present =
			rContext->psFunctions.psFunctions_v1.pvfICCPresence;
		IFD_get_capabilities =
			rContext->psFunctions.psFunctions_v1.pvfGetCapabilities;
	}
	else
		IFDH_icc_presence = rContext->psFunctions.psFunctions_v2.pvfICCPresence;
#endif

	/* LOCK THIS CODE REGION */
	(void)SYS_MutexLock(rContext->mMutex);

#ifndef PCSCLITE_STATIC_DRIVER
	if (rContext->dwVersion == IFD_HVERSION_1_0)
	{
		ucValue[0] = rContext->dwSlot;
		(void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
		rv = (*IFD_is_icc_present) ();
	}
	else
		rv = (*IFDH_icc_presence) (rContext->dwSlot);
#else
	if (rContext->dwVersion == IFD_HVERSION_1_0)
	{
		ucValue[0] = rContext->dwSlot;
		(void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
		rv = IFD_Is_ICC_Present();
	}
	else
		rv = IFDHICCPresence(rContext->dwSlot);
#endif

	/* END OF LOCKED REGION */
	(void)SYS_MutexUnLock(rContext->mMutex);

	if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
		dwCardStatus |= SCARD_PRESENT;
	else
		if (rv == IFD_ICC_NOT_PRESENT)
			dwCardStatus |= SCARD_ABSENT;
		else
		{
			Log2(PCSC_LOG_ERROR, "Card not transacted: %ld", rv);
			*pdwStatus = SCARD_UNKNOWN;

			if (rv == IFD_NO_SUCH_DEVICE)
			{
				(void)SendHotplugSignal();
				return SCARD_E_READER_UNAVAILABLE;
			}

			return SCARD_E_NOT_TRANSACTED;
		}

	/*
	 * Now lets get the ATR and process it if IFD Handler version 1.0.
	 * IFD Handler version 2.0 does this immediately after reset/power up
	 * to conserve resources
	 */

	if (rContext->dwVersion == IFD_HVERSION_1_0)
	{
		if (rv == IFD_SUCCESS || rv == IFD_ICC_PRESENT)
		{
			short ret;

			dwTag = TAG_IFD_ATR;

			/* LOCK THIS CODE REGION */
			(void)SYS_MutexLock(rContext->mMutex);

			ucValue[0] = rContext->dwSlot;
			(void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);

#ifndef PCSCLITE_STATIC_DRIVER
			rv = (*IFD_get_capabilities) (dwTag, pucAtr);
#else
			rv = IFD_Get_Capabilities(dwTag, pucAtr);
#endif

			/* END OF LOCKED REGION */
			(void)SYS_MutexUnLock(rContext->mMutex);

			/*
			 * FIX :: This is a temporary way to return the correct size
			 * of the ATR since most of the drivers return MAX_ATR_SIZE
			 */

			ret = ATRDecodeAtr(&sSmartCard, pucAtr, MAX_ATR_SIZE);

			/*
			 * Might be a memory card without an ATR
			 */
			if (ret == 0)
				*pdwAtrLen = 0;
			else
				*pdwAtrLen = sSmartCard.ATR.Length;
		}
		else
		{
			/*
			 * No card is inserted - Atr length is 0
			 */
			*pdwAtrLen = 0;
		}
		/*
		 * End of FIX
		 */
	}

	*pdwStatus = dwCardStatus;

	return SCARD_S_SUCCESS;
}
예제 #8
0
/**
 * Power up/down or reset's an ICC located in the IFD.
 */
LONG IFDPowerICC(PREADER_CONTEXT rContext, DWORD dwAction,
	PUCHAR pucAtr, PDWORD pdwAtrLen)
{
	RESPONSECODE rv;
	short ret;
	SMARTCARD_EXTENSION sSmartCard;
	DWORD dwStatus;
	UCHAR ucValue[1];

#ifndef PCSCLITE_STATIC_DRIVER
	RESPONSECODE(*IFD_power_icc) (DWORD) = NULL;
	RESPONSECODE(*IFDH_power_icc) (DWORD, DWORD, PUCHAR, PDWORD) = NULL;
#endif

	/*
	 * Zero out everything
	 */
	rv = IFD_SUCCESS;
	dwStatus = 0;
	ucValue[0] = 0;

	/*
	 * Check that the card is inserted first
	 */
	(void)IFDStatusICC(rContext, &dwStatus, pucAtr, pdwAtrLen);

	if (dwStatus & SCARD_ABSENT)
		return SCARD_W_REMOVED_CARD;
#ifndef PCSCLITE_STATIC_DRIVER
	if (rContext->dwVersion == IFD_HVERSION_1_0)
		IFD_power_icc = rContext->psFunctions.psFunctions_v1.pvfPowerICC;
	else
		IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC;
#endif

	/* LOCK THIS CODE REGION */
	(void)SYS_MutexLock(rContext->mMutex);

#ifndef PCSCLITE_STATIC_DRIVER
	if (rContext->dwVersion == IFD_HVERSION_1_0)
	{
		ucValue[0] = rContext->dwSlot;
		(void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
		rv = (*IFD_power_icc) (dwAction);
	}
	else
	{
		rv = (*IFDH_power_icc) (rContext->dwSlot, dwAction,
			pucAtr, pdwAtrLen);

		ret = ATRDecodeAtr(&sSmartCard, pucAtr, *pdwAtrLen);
	}
#else
	if (rContext->dwVersion == IFD_HVERSION_1_0)
	{
		ucValue[0] = rContext->dwSlot;
		(void)IFDSetCapabilities(rContext, TAG_IFD_SLOTNUM, 1, ucValue);
		rv = IFD_Power_ICC(dwAction);
	}
	else
		rv = IFDHPowerICC(rContext->dwSlot, dwAction, pucAtr, pdwAtrLen);
#endif

	/* END OF LOCKED REGION */
	(void)SYS_MutexUnLock(rContext->mMutex);

	/* use clean values in case of error */
	if (rv != IFD_SUCCESS)
	{
		*pdwAtrLen = 0;
		pucAtr[0] = '\0';

		if (rv == IFD_NO_SUCH_DEVICE)
		{
			(void)SendHotplugSignal();
			return SCARD_E_READER_UNAVAILABLE;
		}

		return SCARD_E_NOT_TRANSACTED;
	}

	/*
	 * Get the ATR and it's length
	 */
	if (rContext->dwVersion == IFD_HVERSION_1_0)
		(void)IFDStatusICC(rContext, &dwStatus, pucAtr, pdwAtrLen);

	return rv;
}
예제 #9
0
/**
 * Power up/down or reset's an ICC located in the IFD.
 */
LONG IFDPowerICC(READER_CONTEXT * rContext, DWORD dwAction,
	PUCHAR pucAtr, PDWORD pdwAtrLen)
{
	RESPONSECODE rv;
	DWORD dwStatus;
	UCHAR dummyAtr[MAX_ATR_SIZE];
	DWORD dummyAtrLen = sizeof(dummyAtr);

#ifndef PCSCLITE_STATIC_DRIVER
	RESPONSECODE(*IFDH_power_icc) (DWORD, DWORD, PUCHAR, PDWORD) = NULL;
#endif

	/*
	 * Zero out everything
	 */
	dwStatus = 0;

	if (NULL == pucAtr)
		pucAtr = dummyAtr;
	if (NULL == pdwAtrLen)
		pdwAtrLen = &dummyAtrLen;

	/*
	 * Check that the card is inserted first
	 */
	rv = IFDStatusICC(rContext, &dwStatus);
	if (rv != IFD_SUCCESS)
	{
		if (rv == IFD_NO_SUCH_DEVICE)
			return SCARD_E_READER_UNAVAILABLE;

		return SCARD_E_NOT_TRANSACTED;
	}

	if (dwStatus & SCARD_ABSENT)
		return SCARD_W_REMOVED_CARD;
#ifndef PCSCLITE_STATIC_DRIVER
	IFDH_power_icc = rContext->psFunctions.psFunctions_v2.pvfPowerICC;
#endif

	/* LOCK THIS CODE REGION */
	(void)pthread_mutex_lock(rContext->mMutex);

#ifndef PCSCLITE_STATIC_DRIVER
	rv = (*IFDH_power_icc) (rContext->slot, dwAction, pucAtr, pdwAtrLen);
#else
	rv = IFDHPowerICC(rContext->slot, dwAction, pucAtr, pdwAtrLen);
#endif

	/* END OF LOCKED REGION */
	(void)pthread_mutex_unlock(rContext->mMutex);

	/* use clean values in case of error */
	if (rv != IFD_SUCCESS)
	{
		*pdwAtrLen = 0;
		pucAtr[0] = '\0';

		if (rv == IFD_NO_SUCH_DEVICE)
		{
			(void)SendHotplugSignal();
			return SCARD_E_READER_UNAVAILABLE;
		}

		return SCARD_E_NOT_TRANSACTED;
	}

	return rv;
}