Beispiel #1
0
int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out)
{
	sc_card_t *card;
	sc_context_t *ctx;
	struct sc_card_driver *driver;
	int i, r = 0, idx, connected = 0;

	if (card_out == NULL || reader == NULL)
		return SC_ERROR_INVALID_ARGUMENTS;
	ctx = reader->ctx;
	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
	if (reader->ops->connect == NULL)
		LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);

	card = sc_card_new(ctx);
	if (card == NULL)
		LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
	r = reader->ops->connect(reader);
	if (r)
		goto err;

	connected = 1;
	card->reader = reader;
	card->ctx = ctx;

	if (reader->flags & SC_READER_ENABLE_ESCAPE)
		sc_detect_escape_cmds(reader);

	memcpy(&card->atr, &reader->atr, sizeof(card->atr));
	memcpy(&card->uid, &reader->uid, sizeof(card->uid));

	_sc_parse_atr(reader);

	/* See if the ATR matches any ATR specified in the config file */
	if ((driver = ctx->forced_driver) == NULL) {
		sc_log(ctx, "matching configured ATRs");
		for (i = 0; ctx->card_drivers[i] != NULL; i++) {
			driver = ctx->card_drivers[i];

			if (driver->atr_map == NULL ||
			    !strcmp(driver->short_name, "default")) {
				driver = NULL;
				continue;
			}
			sc_log(ctx, "trying driver '%s'", driver->short_name);
			idx = _sc_match_atr(card, driver->atr_map, NULL);
			if (idx >= 0) {
				struct sc_atr_table *src = &driver->atr_map[idx];

				sc_log(ctx, "matched driver '%s'", driver->name);
				/* It's up to card driver to notice these correctly */
				card->name = src->name;
				card->type = src->type;
				card->flags = src->flags;
				break;
			}
			driver = NULL;
		}
	}

	if (driver != NULL) {
		/* Forced driver, or matched via ATR mapping from config file */
		card->driver = driver;

		memcpy(card->ops, card->driver->ops, sizeof(struct sc_card_operations));
		if (card->ops->match_card != NULL)
			if (card->ops->match_card(card) != 1)
				sc_log(ctx, "driver '%s' match_card() failed: %s (will continue anyway)", card->driver->name, sc_strerror(r));

		if (card->ops->init != NULL) {
			r = card->ops->init(card);
			if (r) {
				sc_log(ctx, "driver '%s' init() failed: %s", card->driver->name, sc_strerror(r));
				goto err;
			}
		}
	}
	else {
		sc_card_t uninitialized = *card;
		sc_log(ctx, "matching built-in ATRs");
		for (i = 0; ctx->card_drivers[i] != NULL; i++) {
			/* FIXME If we had a clean API description, we'd propably get a
			 * cleaner implementation of the driver's match_card and init,
			 * which should normally *not* modify the card object if
			 * unsuccessful. However, after years of relentless hacking, reality
			 * is different: The card object is changed in virtually every card
			 * driver so in order to prevent unwanted interaction, we reset the
			 * card object here and hope that the card driver at least doesn't
			 * allocate any internal ressources that need to be freed. If we
			 * had more time, we should refactor the existing code to not
			 * modify sc_card_t until complete success (possibly by combining
			 * `match_card()` and `init()`) */
			*card = uninitialized;

			struct sc_card_driver *drv = ctx->card_drivers[i];
			const struct sc_card_operations *ops = drv->ops;

			sc_log(ctx, "trying driver '%s'", drv->short_name);
			if (ops == NULL || ops->match_card == NULL)   {
				continue;
			}
			else if (!(ctx->flags & SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER)
				   	&& !strcmp("default", drv->short_name))   {
				sc_log(ctx , "ignore 'default' card driver");
				continue;
			}

			/* Needed if match_card() needs to talk with the card (e.g. card-muscle) */
			*card->ops = *ops;
			if (ops->match_card(card) != 1)
				continue;
			sc_log(ctx, "matched: %s", drv->name);
			memcpy(card->ops, ops, sizeof(struct sc_card_operations));
			card->driver = drv;
			r = ops->init(card);
			if (r) {
				sc_log(ctx, "driver '%s' init() failed: %s", drv->name, sc_strerror(r));
				if (r == SC_ERROR_INVALID_CARD) {
					card->driver = NULL;
					continue;
				}
				goto err;
			}
			break;
		}
	}
	if (card->driver == NULL) {
		sc_log(ctx, "unable to find driver for inserted card");
		r = SC_ERROR_INVALID_CARD;
		goto err;
	}
	if (card->name == NULL)
		card->name = card->driver->name;

	/* initialize max_send_size/max_recv_size to a meaningful value */
	card->max_recv_size = sc_get_max_recv_size(card);
	card->max_send_size = sc_get_max_send_size(card);

	sc_log(ctx,
	       "card info name:'%s', type:%i, flags:0x%lX, max_send/recv_size:%"SC_FORMAT_LEN_SIZE_T"u/%"SC_FORMAT_LEN_SIZE_T"u",
	       card->name, card->type, card->flags, card->max_send_size,
	       card->max_recv_size);

#ifdef ENABLE_SM
        /* Check, if secure messaging module present. */
	r = sc_card_sm_check(card);
	if (r)   {
		sc_log(ctx, "cannot load secure messaging module");
		goto err;
	}
#endif
	*card_out = card;

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
err:
	if (connected)
		reader->ops->disconnect(reader);
	if (card != NULL)
		sc_card_free(card);
	LOG_FUNC_RETURN(ctx, r);
}
Beispiel #2
0
int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out)
{
	sc_card_t *card;
	sc_context_t *ctx;
	struct sc_card_driver *driver;
	int i, r = 0, idx, connected = 0;

	if (card_out == NULL || reader == NULL)
		return SC_ERROR_INVALID_ARGUMENTS;
	ctx = reader->ctx;
	SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
	if (reader->ops->connect == NULL)
		LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);

	card = sc_card_new(ctx);
	if (card == NULL)
		LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
	r = reader->ops->connect(reader);
	if (r)
		goto err;

	connected = 1;
	card->reader = reader;
	card->ctx = ctx;

	memcpy(&card->atr, &reader->atr, sizeof(card->atr));

	_sc_parse_atr(reader);

	/* See if the ATR matches any ATR specified in the config file */
	if ((driver = ctx->forced_driver) == NULL) {
		sc_log(ctx, "matching configured ATRs");
		for (i = 0; ctx->card_drivers[i] != NULL; i++) {
			driver = ctx->card_drivers[i];

			if (driver->atr_map == NULL ||
			    !strcmp(driver->short_name, "default")) {
				driver = NULL;
				continue;
			}
			sc_log(ctx, "trying driver '%s'", driver->short_name);
			idx = _sc_match_atr(card, driver->atr_map, NULL);
			if (idx >= 0) {
				struct sc_atr_table *src = &driver->atr_map[idx];

				sc_log(ctx, "matched driver '%s'", driver->name);
				/* It's up to card driver to notice these correctly */
				card->name = src->name;
				card->type = src->type;
				card->flags = src->flags;
				break;
			}
			driver = NULL;
		}
	}

	if (driver != NULL) {
		/* Forced driver, or matched via ATR mapping from config file */
		card->driver = driver;

		memcpy(card->ops, card->driver->ops, sizeof(struct sc_card_operations));
		if (card->ops->match_card != NULL)
			if (card->ops->match_card(card) != 1)
				sc_log(ctx, "driver '%s' match_card() failed: %s (will continue anyway)", card->driver->name, sc_strerror(r));

		if (card->ops->init != NULL) {
			r = card->ops->init(card);
			if (r) {
				sc_log(ctx, "driver '%s' init() failed: %s", card->driver->name, sc_strerror(r));
				goto err;
			}
		}
	}
	else {
		sc_log(ctx, "matching built-in ATRs");
		for (i = 0; ctx->card_drivers[i] != NULL; i++) {
			struct sc_card_driver *drv = ctx->card_drivers[i];
			const struct sc_card_operations *ops = drv->ops;

			sc_log(ctx, "trying driver '%s'", drv->short_name);
			if (ops == NULL || ops->match_card == NULL)   {
				continue;
			}
			else if (!(ctx->flags & SC_CTX_FLAG_ENABLE_DEFAULT_DRIVER)
				   	&& !strcmp("default", drv->short_name))   {
				sc_log(ctx , "ignore 'default' card driver");
				continue;
			}

			/* Needed if match_card() needs to talk with the card (e.g. card-muscle) */
			*card->ops = *ops;
			if (ops->match_card(card) != 1)
				continue;
			sc_log(ctx, "matched: %s", drv->name);
			memcpy(card->ops, ops, sizeof(struct sc_card_operations));
			card->driver = drv;
			r = ops->init(card);
			if (r) {
				sc_log(ctx, "driver '%s' init() failed: %s", drv->name, sc_strerror(r));
				if (r == SC_ERROR_INVALID_CARD) {
					card->driver = NULL;
					continue;
				}
				goto err;
			}
			break;
		}
	}
	if (card->driver == NULL) {
		sc_log(ctx, "unable to find driver for inserted card");
		r = SC_ERROR_INVALID_CARD;
		goto err;
	}
	if (card->name == NULL)
		card->name = card->driver->name;

	/* initialize max_send_size/max_recv_size to a meaningfull value */
	card->max_recv_size = sc_get_max_recv_size(card);
	card->max_send_size = sc_get_max_send_size(card);

	sc_log(ctx, "card info name:'%s', type:%i, flags:0x%X, max_send/recv_size:%i/%i",
		card->name, card->type, card->flags, card->max_send_size, card->max_recv_size);

#ifdef ENABLE_SM
        /* Check, if secure messaging module present. */
	r = sc_card_sm_check(card);
	if (r)   {
		sc_log(ctx, "cannot load secure messaging module");
		goto err;
	}
#endif
	*card_out = card;

	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
err:
	if (connected)
		reader->ops->disconnect(reader);
	if (card != NULL)
		sc_card_free(card);
	LOG_FUNC_RETURN(ctx, r);
}