- added README for PAM module

- added a few error messages
- fixed certificate caching (which is still kludgy)


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@44 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
jey 2001-11-17 15:48:10 +00:00
parent 1194017d5a
commit e53cfa4595
7 changed files with 73 additions and 22 deletions

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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]);

14
src/pam/README Normal file
View File

@ -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.

View File

@ -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"));

View File

@ -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;
}