diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index b160bed2..68957ac0 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -44,6 +44,8 @@ #define SC_ERROR_BUFFER_TOO_SMALL -1017 #define SC_ERROR_CARD_NOT_PRESENT -1018 #define SC_ERROR_RESOURCE_MANAGER -1019 +#define SC_ERROR_CARD_REMOVED -1020 +#define SC_ERROR_INVALID_PIN_LENGTH -1021 #define SC_APDU_CASE_NONE 0 #define SC_APDU_CASE_1 1 @@ -117,8 +119,9 @@ struct sc_file { struct sc_card { int class; struct sc_context *context; + SCARDHANDLE pcsc_card; - const char *reader; + int reader; char atr[SC_MAX_ATR_SIZE]; int atr_len; @@ -170,8 +173,15 @@ int sc_destroy_context(struct sc_context *ctx); int sc_connect_card(struct sc_context *ctx, int reader, struct sc_card **card); int sc_disconnect_card(struct sc_card *card); + +/* Checks if a card is present on the supplied reader + * Returns: 1 if card present, 0 if card absent and < 0 in case of an error */ int sc_detect_card(struct sc_context *ctx, int reader); -/* timeout of -1 means forever, reader of -1 means all readers */ + +/* Waits for card insertion on the supplied reader + * timeout of -1 means forever, reader of -1 means all readers + * Returns: 1 if a card was found, 0 if timeout occured + * and < 0 in case of an error */ int sc_wait_for_card(struct sc_context *ctx, int reader, int timeout); int sc_lock(struct sc_card *card); diff --git a/src/libopensc/pkcs15-cert.c b/src/libopensc/pkcs15-cert.c index 9acd6b4d..d4ae7f61 100644 --- a/src/libopensc/pkcs15-cert.c +++ b/src/libopensc/pkcs15-cert.c @@ -129,27 +129,35 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card, struct sc_file file; char *data = NULL; struct sc_pkcs15_cert *cert; - char fname[50]; + char fname[150]; u8 buf[2048]; + FILE *crtf = NULL; int cert_found = 0; - + char *homedir; assert(p15card != NULL && info != NULL && cert_out != NULL); +#if 1 /* FIXME: Remove this kludge */ - sprintf(fname, "/tmp/fineid-%02X.crt", info->id.value[0]); + homedir = getenv("HOME"); + if (homedir == NULL) + goto no_cert; + sprintf(fname, "%s/.eid/%s_%02X.crt", homedir, p15card->label, info->id.value[0]); crtf = fopen(fname, "r"); - if (crtf != NULL) { - r = fread(buf, 1, sizeof(buf), crtf); - if (r > 0) { - data = malloc(r); - memcpy(data, buf, r); - len = r; - cert_found = 1; - } - fclose(crtf); + if (crtf == NULL) + goto no_cert; + + r = fread(buf, 1, sizeof(buf), crtf); + if (r > 0) { + data = malloc(r); + memcpy(data, buf, r); + len = r; + cert_found = 1; } + fclose(crtf); +no_cert: +#endif if (!cert_found) { r = sc_select_file(p15card->card, &file, &info->path, SC_SELECT_FILE_BY_PATH); @@ -165,11 +173,13 @@ int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card, } len = r; /* FIXME: kludge! */ +#if 1 crtf = fopen(fname, "w"); if (crtf != NULL) { fwrite(data, len, 1, crtf); fclose(crtf); } +#endif } cert = malloc(sizeof(struct sc_pkcs15_cert)); if (cert == NULL) { diff --git a/src/libopensc/pkcs15-pin.c b/src/libopensc/pkcs15-pin.c index 155c939c..c740e530 100644 --- a/src/libopensc/pkcs15-pin.c +++ b/src/libopensc/pkcs15-pin.c @@ -171,7 +171,7 @@ int sc_pkcs15_verify_pin(struct sc_pkcs15_card *p15card, if (pin->magic != SC_PKCS15_PIN_MAGIC) return SC_ERROR_OBJECT_NOT_VALID; if (pinlen > pin->stored_length || pinlen < pin->min_length) - return SC_ERROR_INVALID_ARGUMENTS; + return SC_ERROR_INVALID_PIN_LENGTH; card = p15card->card; r = sc_select_file(card, &file, &pin->path, SC_SELECT_FILE_BY_PATH); diff --git a/src/libopensc/sc.c b/src/libopensc/sc.c index ffdbb773..5ba6ea10 100644 --- a/src/libopensc/sc.c +++ b/src/libopensc/sc.c @@ -174,9 +174,19 @@ static int sc_transceive_t0(struct sc_card *card, struct sc_apdu *apdu) rv = SCardTransmit(card->pcsc_card, &sSendPci, s, dwSendLength, &sRecvPci, r, &dwRecvLength); if (rv != SCARD_S_SUCCESS) { - fprintf(stderr, "SCardTransmit failed with 0x%08x\n", - (int) rv); - return SC_ERROR_TRANSMIT_FAILED; + switch (rv) { + case SCARD_W_REMOVED_CARD: + return SC_ERROR_CARD_REMOVED; + case SCARD_E_NOT_TRANSACTED: + if (sc_detect_card(card->context, card->reader) != 1) + return SC_ERROR_CARD_REMOVED; + return SC_ERROR_TRANSMIT_FAILED; + default: + if (sc_debug) { + fprintf(stderr, "SCardTransmit returned 0x%08lX.\n", rv); + return SC_ERROR_TRANSMIT_FAILED; + } + } } apdu->resplen = dwRecvLength; memcpy(apdu->resp, r, dwRecvLength); @@ -530,7 +540,6 @@ int sc_wait_for_card(struct sc_context *ctx, int reader, int timeout) return 0; } - int sc_establish_context(struct sc_context **ctx_out) { struct sc_context *ctx; @@ -658,6 +667,8 @@ int sc_connect_card(struct sc_context *ctx, free(card); return -1; /* FIXME */ } + card->reader = reader; + card->context = ctx; card->pcsc_card = card_handle; i = rgReaderStates[0].cbAtr; if (i >= SC_MAX_ATR_SIZE) @@ -671,7 +682,6 @@ int sc_connect_card(struct sc_context *ctx, } else { card->class = 0; /* FIXME */ } - card->reader = ctx->readers[reader]; *card_out = card; return 0; @@ -703,8 +713,12 @@ const char *sc_strerror(int error) "PIN code incorrect", "Security status not satisfied", "Error connecting to Resource Manager", + "Invalid ASN.1 object", "Buffer too small", - + "Card not present", + "Error with Resource Manager", + "Card removed", + "Invalid PIN length" }; int nr_errors = sizeof(errors) / sizeof(errors[0]); diff --git a/src/pam/README b/src/pam/README new file mode 100644 index 00000000..7d0fa780 --- /dev/null +++ b/src/pam/README @@ -0,0 +1,14 @@ + +Steps required to make the PAM module work: + +1. Compile and link the pam_pkcs15.so shared library. +2. Copy pam_pkcs.so to /lib/security. +3. Edit /etc/pam.d/login file. Add the following line before the + pam_unix.so (on Debian) or pam_pwdb.so (on Red Hat) entry: + auth sufficient /lib/security/pam_pkcs15.so +4. Copy your PEM encoded certificate to a file in your home directory + called '.eid/authorized_certificates'. + NOTE: You can use the 'certtest' program to get the PEM encoded + certificate. +5. Try to login with your card in the reader. + diff --git a/src/pam/pam_pkcs15.c b/src/pam/pam_pkcs15.c index 327f97a2..f733959d 100644 --- a/src/pam/pam_pkcs15.c +++ b/src/pam/pam_pkcs15.c @@ -305,7 +305,9 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, con DBG(printf("Verifying PIN code...\n")); r = sc_pkcs15_verify_pin(p15card, &p15card->pin_info[0], password, strlen(password)); if (r) { - printf("PIN code verification failed: %s\n", sc_strerror(r)); + DBG(printf("PIN code verification failed: %s\n", sc_strerror(r))); + if (r == SC_ERROR_CARD_REMOVED) + printf("SmartCard removed.\n"); goto end; } DBG(printf("Awright! PIN code correct!\n")); diff --git a/src/tests/p15dump.c b/src/tests/p15dump.c index 2a7887e5..bca09ace 100644 --- a/src/tests/p15dump.c +++ b/src/tests/p15dump.c @@ -99,5 +99,6 @@ int main(int argc, char *argv[]) printf("\n"); sc_asn1_print_tags(cert->data, cert->data_len); } + sc_test_cleanup(); return 0; }