Ludovic Rousseau wrote:
On 12/04/07, Robert Relyea <[EMAIL PROTECTED]> wrote:
I just did an update, and a clean checkout, and it looks like the new
files didn't get added to the repository.
Exact. "svn diff" did not show them.
I also modified src/common/Makefile.am to include them in the .tar.gz
generated by "make dist".
Now corrected with revision 244
Thanks!
Here's patch installment 2 of 3.
This patch adds some new semantics to allow pam_pkcs11 to play nice in
both command line and gui applications. The heart of this change adds
three new configuration options.
card_only:
1. If card only is set, pam_pkcs11 does not prompt for the user name
if the token is inserted, but gets the user name from the token.
2. If a token is inserted, it must be used to log in with, failure to
unlock the token, or validate the certs will cause login to fail.
3. If we logged in using a smart card, we must now authenticate using
that same smart card.
4. card_only is required to activate the remaining 2 options. If
card_only is not set, the current pam_pkcs11 semantics apply (with the
exception of some prompt name changes and the environment variables
described below).
wait_for_token:
wait_for_token is only meaningful if card_only is set.
if wait_for_token is set, then pam_pkcs11 will block waiting for an
appropriate token to be inserted. An appropriate token is:
1) a token that is inserted in the slot specified for login in the
config
file (if no slot is specified a token inserted in any slot).
2) a token which matches the token used to log in initially. (only
applies
if you are logged in and you used a token to do so).
screen_savers:
is a list of screen saver services. This list is only parsed if
card_only is
set. Basically the screen saver will bypass pam_pkcs11 if a token was not
used to login (The basic idea is you always unlock the screen saver with
the same mechanism you used to login).
The other major change is the addition of new environment variables:
PKCS11_LOGIN_TOKEN_NAME - the name of the token used to log into the system.
PKCS11_LOGIN_CERT_ISSUER - the issuer of the cert used to log in
(rendered as
a human readable string).
PKCS11_LOGIN_CERT_SERIAL - the serial number of the cert used to log in
(rendered as colon separated hex value).
These environment variables are set at initial login.
pam_pkcs11 uses PKCS_LOGIN_TOKEN_NAME to determine whether or not it
needs to
use a specific token to log into.
screen savers use this environment variable to determine
if it needs to kick in on token removal (this allows screen savers to be
picky about when to kick in -- they don't have to kick in if you insert or
remove a token that wasn't used to log into).
pam_krb uses the PKCS11_LOGIN_CERT_ISSUER and PKCS11_LOGIN_CERT_SERIAL to
determine which specific certificate was used to login in (issuer/serial
number
uniquely identifies a certificate).
Typical usage for the patch:
For a normal (card_only) case, your pam line would look like:
auth [success=ok authinfo_unavail=2 ignore=2 default=die]
pam_pkcs11.so
For the case where you want to require the smart card as part of the
authentication, your pam config line would look like:
auth [success=ok ignore=2 default=die] pam_pkcs11.so wait_for_card
If you share your pam_config file with all our services, you can restrict
which services require smart card login with a pam_succeed_if before your
pam_pkcs11 line:
auth [success=3 default=ignore] pam_succeed_if.so service notin
login:gdm:xdm:kdm:xscreensaver:gnome-screensaver:kscreensaver quiet use_uid
--------------------------------------------------
The patch itself, file by file:
src/pam_pkcs11/pam_pkcs11.c -
Most of the patch is in here. The implementation of the environment
variables
and new options are in this patch. In addition to the these, the patch has
the following change:
1) a bug fix for passing the password on in the pam_stack (required to
pam_krb
to successfully implement pkinit).
2) use the pam_syslog() function instead of syslog().
3) use of pam_prompt to allow gui apps to display important information.
src/pam_pkcs11/pam_config.[ch] -
parse the new options in pam_pkcs11.conf.
src/tools/pkcs11_setup.c -
src/tools/Makefile.am
This is a new tool to allow command line editting of pam_pkcs11.conf and
pkcs11_eventmgr.conf. It only supports adding insertion/removal actions and
changing the default token. We don't actually use it any more, but it
may have
utility to others. I think the command may need some work to be more
general.
It's purpose is to allow perl/python/your favorite scripting language access
to display and modify portions of the pam_pkcs11.conf file. (Feel free
to drop
it if you like, I've included it for completeness).
src/tools/pkcs11_eventmgr.c -
bug fix for a crash if module loading fails.
src/common/cert_info.c
Add the ability to fetch the certificate serial number when using the
open ssl
library.
src/common/pkcs11_lib.[ch]
Add find_slot_by_number_and_label() which optionally adds the token name as
part of the slot selection criteria. Used by pam_pkcs11 in the case we are
authenticating after we have already logged in.
Add wait_for_token() which waits until an approriate token is inserted. Used
to implement the wait_for_token option.
src/common/strings.c
Fix bug in bin2hex where it would trash the heap if asked to output a string
for a zero length buffer.
Index: src/pam_pkcs11/pam_pkcs11.c
===================================================================
--- src/pam_pkcs11/pam_pkcs11.c (revision 264)
+++ src/pam_pkcs11/pam_pkcs11.c (working copy)
@@ -26,6 +26,7 @@
#endif
#include <security/pam_appl.h>
#include <security/pam_modules.h>
+#include <security/pam_ext.h>
#include <syslog.h>
#include <ctype.h>
#include <string.h>
@@ -35,6 +36,7 @@
#include "../common/error.h"
#include "../common/pkcs11_lib.h"
#include "../common/cert_vfy.h"
+#include "../common/cert_info.h"
#include "../common/cert_st.h"
#include "pam_config.h"
#include "mapper_mgr.h"
@@ -102,7 +104,7 @@
free(&resp[0]);
/* save password if variable nitem is set */
if ((nitem == PAM_AUTHTOK) || (nitem == PAM_OLDAUTHTOK)) {
- rv = pam_set_item(pamh, nitem, pwd);
+ rv = pam_set_item(pamh, nitem, *pwd);
if (rv != PAM_SUCCESS)
return rv;
}
@@ -114,11 +116,13 @@
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
int i, rv;
- const char *user;
+ const char *user = NULL;
char *password;
- char password_prompt[64];
+ char password_prompt[70];
unsigned int slot_num = 0;
+ int is_a_screen_saver = 0;
struct configuration_st *configuration;
+ int pkcs11_pam_fail = PAM_AUTHINFO_UNAVAIL;
pkcs11_handle_t *ph;
cert_object_t *chosen_cert = NULL;
@@ -127,6 +131,10 @@
unsigned char random_value[128];
unsigned char *signature;
unsigned long signature_length;
+ /* enough space to hold an issuer DN */
+ char env_temp[256] = "";
+ char **issuer, **serial;
+ const char *login_token_name = NULL;
/* first of all check whether debugging should be enabled */
for (i = 0; i < argc; i++)
@@ -140,8 +148,6 @@
ERR("Error setting configuration parameters");
return PAM_AUTHINFO_UNAVAIL;
}
- /* open log */
- openlog(LOGNAME, LOG_CONS | LOG_PID, LOG_AUTHPRIV);
/* fail if we are using a remote server
* local login: DISPLAY=:0
@@ -152,7 +158,8 @@
if (display && (display[0] != ':') && (display[0] != '\0'))
{
ERR1("Remote login (from %s) is not (yet) supported", display);
- syslog(LOG_ERR, "Remote login (from %s) is not (yet) supported",
+ pam_syslog(pamh, LOG_ERR,
+ "Remote login (from %s) is not (yet) supported",
display);
return PAM_AUTHINFO_UNAVAIL;
}
@@ -162,24 +169,74 @@
rv = crypto_init(&configuration->policy);
if (rv != 0) {
ERR("Failed to initialize crypto");
- syslog(LOG_ERR, "Failed to initialize crypto");
+ pam_syslog(pamh,LOG_ERR, "Failed to initialize crypto");
return PAM_AUTHINFO_UNAVAIL;
}
- /* get user name */
- rv = pam_get_user(pamh, &user, NULL);
- if (rv != PAM_SUCCESS) {
- syslog(LOG_ERR, "pam_get_user() failed %s", pam_strerror(pamh, rv));
- return PAM_USER_UNKNOWN;
+
+ /*
+ * card_only means:
+ * 1) always get the userid from the certificate.
+ * 2) don't prompt for the user name if the card is present.
+ * 3) if the token is present, then we must use the cardAuth mechanism.
+ *
+ * wait_for_card means:
+ * 1) nothing if card_only isn't set
+ * 2) if logged in, block in pam conversation until the token used for login
+ * is inserted
+ * 3) if not logged in, block until a token that could be used for logging
in
+ * is inserted
+ * right now, logged in means PKC11_LOGIN_TOKEN_NAME is set,
+ * but we could something else later (like set some per-user state in
+ * a pam session module keyed off uid)
+ */
+ if (configuration->card_only) {
+ char *service;
+ if (configuration->screen_savers) {
+ DBG("Is it a screen saver?");
+ rv = pam_get_item(pamh, PAM_SERVICE, (const void **) &service);
+ for (i=0; configuration->screen_savers[i]; i++) {
+ if (strcmp(configuration->screen_savers[i], service) == 0) {
+ is_a_screen_saver = 1;
+ break;
+ }
+ }
+ }
+
+ pkcs11_pam_fail = PAM_CRED_INSUFFICIENT;
+
+ /* look to see if username is already set */
+ rv = pam_get_item(pamh, PAM_USER, (const void **) &user);
+ if (user) {
+ DBG1("explicit username = [%s]", user);
+ }
+ } else {
+ pam_prompt(pamh, PAM_TEXT_INFO, NULL,
+ "Please insert your smart card or enter your username.");
+ /* get user name */
+ rv = pam_get_user(pamh, &user, NULL);
+
+ if (rv != PAM_SUCCESS) {
+ pam_syslog(pamh, LOG_ERR,
+ "pam_get_user() failed %s", pam_strerror(pamh, rv));
+ return PAM_USER_UNKNOWN;
+ }
+ DBG1("username = [%s]", user);
}
- DBG1("username = [%s]", user);
+ login_token_name = getenv("PKCS11_LOGIN_TOKEN_NAME");
+ /* if we are using a screen saver, and we didn't log in using the smart card
+ * drop to the next pam module. */
+ if (is_a_screen_saver && !login_token_name) {
+ return PAM_IGNORE;
+ }
+
/* load pkcs #11 module */
DBG("loading pkcs #11 module...");
rv = load_pkcs11_module(configuration->pkcs11_modulepath, &ph);
if (rv != 0) {
ERR1("load_pkcs11_module() failed: %s", get_error());
- syslog(LOG_ERR, "load_pkcs11_module() failed: %s", get_error());
+ pam_syslog(pamh, LOG_ERR, "load_pkcs11_module() failed: %s", get_error());
return PAM_AUTHINFO_UNAVAIL;
}
@@ -189,39 +246,86 @@
if (rv != 0) {
release_pkcs11_module(ph);
ERR1("init_pkcs11_module() failed: %s", get_error());
- syslog(LOG_ERR, "init_pkcs11_module() failed: %s", get_error());
+ pam_syslog(pamh, LOG_ERR, "init_pkcs11_module() failed: %s", get_error());
return PAM_AUTHINFO_UNAVAIL;
}
/* open pkcs #11 session */
- rv = find_slot_by_number(ph, configuration->slot_num, &slot_num);
+ rv = find_slot_by_number_and_label(ph, configuration->slot_num,
+ login_token_name, &slot_num);
if (rv != 0) {
- release_pkcs11_module(ph);
- ERR("no token available");
- syslog(LOG_ERR, "no token available");
- return PAM_AUTHINFO_UNAVAIL;
+ ERR("no suitable token available");
+ pam_syslog(pamh, LOG_ERR, "no suitable token available");
+
+ if (!configuration->card_only) {
+ release_pkcs11_module(ph);
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ /* we must have a smart card, either because we've configured it as such,
+ * or because we used one to log in */
+ if (login_token_name || configuration->wait_for_card) {
+ if (login_token_name) {
+ sprintf(password_prompt,
+ "Please insert your smart card called \"%.32s\".",
+ login_token_name);
+ pam_prompt(pamh, PAM_TEXT_INFO, NULL, password_prompt);
+ } else {
+ pam_prompt(pamh, PAM_TEXT_INFO, NULL,
+ "Please insert your smart card.");
+ }
+ rv = wait_for_token(ph, configuration->slot_num,
+ login_token_name, &slot_num);
+ if (rv != 0) {
+ release_pkcs11_module(ph);
+ return pkcs11_pam_fail;
+ }
+ } else if (user) {
+ /* we have a user and no smart card, go to the next pam module */
+ release_pkcs11_module(ph);
+ return PAM_AUTHINFO_UNAVAIL;
+ } else {
+ /* we haven't prompted for the user yet, get the user and see if
+ * the smart card has been inserted in the mean time */
+ pam_prompt(pamh, PAM_TEXT_INFO, NULL,
+ "Please insert your smart card or enter username.");
+ rv = pam_get_user(pamh, &user, NULL);
+
+ /* check one last time for the smart card before bouncing to the next
+ * module */
+ rv = find_slot_by_number(ph, configuration->slot_num, &slot_num);
+ if (rv != 0) {
+ /* user gave us a user id and no smart card go to next module */
+ release_pkcs11_module(ph);
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+ }
+ } else {
+ pam_prompt(pamh, PAM_TEXT_INFO, NULL, "Smart card inserted. ");
}
rv = open_pkcs11_session(ph, slot_num);
if (rv != 0) {
release_pkcs11_module(ph);
ERR1("open_pkcs11_session() failed: %s", get_error());
- syslog(LOG_ERR, "open_pkcs11_session() failed: %s", get_error());
- return PAM_AUTHINFO_UNAVAIL;
+ pam_syslog(pamh, LOG_ERR, "open_pkcs11_session() failed: %s", get_error());
+ return pkcs11_pam_fail;
}
/* get password */
- sprintf(password_prompt, "PIN for token %.32s: ", get_slot_label(ph));
+ sprintf(password_prompt, "Welcome %.32s!", get_slot_label(ph));
+ pam_prompt(pamh, PAM_TEXT_INFO, NULL, password_prompt);
if (configuration->use_first_pass) {
rv = pam_get_pwd(pamh, &password, NULL, PAM_AUTHTOK, 0);
} else if (configuration->try_first_pass) {
- rv = pam_get_pwd(pamh, &password, password_prompt, PAM_AUTHTOK,
PAM_AUTHTOK);
+ rv = pam_get_pwd(pamh, &password, "Smart card password:", PAM_AUTHTOK,
PAM_AUTHTOK);
} else {
- rv = pam_get_pwd(pamh, &password, password_prompt, 0, PAM_AUTHTOK);
+ rv = pam_get_pwd(pamh, &password, "Smart card password:", 0, PAM_AUTHTOK);
}
if (rv != PAM_SUCCESS) {
release_pkcs11_module(ph);
- syslog(LOG_ERR, "pam_get_pwd() failed: %s", pam_strerror(pamh, rv));
- return PAM_AUTHINFO_UNAVAIL;
+ pam_syslog(pamh, LOG_ERR,
+ "pam_get_pwd() failed: %s", pam_strerror(pamh, rv));
+ return pkcs11_pam_fail;
}
#ifndef DEBUG_HIDE_PASSWORD
DBG1("password = [%s]", password);
@@ -232,7 +336,8 @@
release_pkcs11_module(ph);
memset(password, 0, strlen(password));
free(password);
- syslog(LOG_ERR, "password length is zero but the 'nullok' argument was not
defined.");
+ pam_syslog(pamh, LOG_ERR,
+ "password length is zero but the 'nullok' argument was not defined.");
return PAM_AUTH_ERR;
}
@@ -245,14 +350,14 @@
free(password);
if (rv != 0) {
ERR1("open_pkcs11_login() failed: %s", get_error());
- syslog(LOG_ERR, "open_pkcs11_login() failed: %s", get_error());
+ pam_syslog(pamh, LOG_ERR, "open_pkcs11_login() failed: %s", get_error());
goto auth_failed_nopw;
}
cert_list = get_certificate_list(ph, &ncert);
if (rv<0) {
ERR1("get_certificate_list() failed: %s", get_error());
- syslog(LOG_ERR, "get_certificate_list() failed: %s", get_error());
+ pam_syslog(pamh, LOG_ERR, "get_certificate_list() failed: %s",
get_error());
goto auth_failed_nopw;
}
@@ -261,7 +366,7 @@
/* find a valid and matching certificates */
for (i = 0; i < ncert; i++) {
- X509 *x509 = get_X509_certificate(cert_list[i]);
+ X509 *x509 = (X509 *)get_X509_certificate(cert_list[i]);
if (!x509 ) continue; /* sanity check */
DBG1("verifing the certificate #%d", i + 1);
@@ -269,7 +374,8 @@
rv = verify_certificate(x509,&configuration->policy);
if (rv < 0) {
ERR1("verify_certificate() failed: %s", get_error());
- syslog(LOG_ERR, "verify_certificate() failed: %s", get_error());
+ pam_syslog(pamh, LOG_ERR,
+ "verify_certificate() failed: %s", get_error());
goto auth_failed_nopw;
} else if (rv != 1) {
ERR1("verify_certificate() failed: %s", get_error());
@@ -287,7 +393,8 @@
user=find_user(x509);
if (!user) {
ERR2("find_user() failed: %s on cert #%d", get_error(),i+1);
- syslog(LOG_ERR,"find_user() failed: %s on cert #%d",get_error(),i+1);
+ pam_syslog(pamh, LOG_ERR,
+ "find_user() failed: %s on cert #%d",get_error(),i+1);
continue; /* try on next certificate */
} else {
DBG1("certificate is valid and matches user %s",user);
@@ -295,7 +402,8 @@
rv = pam_set_item(pamh, PAM_USER,(const void *)user);
if (rv != PAM_SUCCESS) {
ERR1("pam_set_item() failed %s", pam_strerror(pamh, rv));
- syslog(LOG_ERR, "pam_set_item() failed %s", pam_strerror(pamh, rv));
+ pam_syslog(pamh, LOG_ERR,
+ "pam_set_item() failed %s", pam_strerror(pamh, rv));
goto auth_failed_nopw;
}
chosen_cert = cert_list[i];
@@ -307,7 +415,7 @@
rv = match_user(x509, user);
if (rv < 0) { /* match error; abort and return */
ERR1("match_user() failed: %s", get_error());
- syslog(LOG_ERR, "match_user() failed: %s", get_error());
+ pam_syslog(pamh, LOG_ERR, "match_user() failed: %s", get_error());
goto auth_failed_nopw;
} else if (rv == 0) { /* match didn't success */
DBG("certificate is valid bus does not match the user");
@@ -323,7 +431,8 @@
/* now myCert points to our found certificate or null if no user found */
if (!chosen_cert) {
ERR("no valid certificate which meets all requirements found");
- syslog(LOG_ERR, "no valid certificate which meets all requirements found");
+ pam_syslog(pamh, LOG_ERR,
+ "no valid certificate which meets all requirements found");
goto auth_failed_nopw;
}
@@ -335,7 +444,8 @@
rv = get_private_key(ph);
if (rv != 0) {
ERR1("get_private_key() failed: %s", get_error());
- syslog(LOG_ERR, "get_private_key() failed: %s", get_error());
+ pam_syslog(pamh, LOG_ERR,
+ "get_private_key() failed: %s", get_error());
goto auth_failed_nopw;
}
#endif
@@ -344,7 +454,7 @@
rv = get_random_value(random_value, sizeof(random_value));
if (rv != 0) {
ERR1("get_random_value() failed: %s", get_error());
- syslog(LOG_ERR, "get_random_value() failed: %s", get_error());
+ pam_syslog(pamh, LOG_ERR, "get_random_value() failed: %s", get_error());
goto auth_failed_nopw;
}
@@ -354,20 +464,22 @@
&signature, &signature_length);
if (rv != 0) {
ERR1("sign_value() failed: %s", get_error());
- syslog(LOG_ERR, "sign_value() failed: %s", get_error());
+ pam_syslog(pamh, LOG_ERR, "sign_value() failed: %s", get_error());
goto auth_failed_nopw;
}
/* verify the signature */
DBG("verifying signature...");
- rv = verify_signature(get_X509_certificate(chosen_cert),
+ rv = verify_signature((X509 *)get_X509_certificate(chosen_cert),
random_value, sizeof(random_value), signature, signature_length);
- if (signature != NULL) free(signature);
+ if (signature != NULL) {
+ free(signature);
+ }
if (rv != 0) {
close_pkcs11_session(ph);
release_pkcs11_module(ph);
ERR1("verify_signature() failed: %s", get_error());
- syslog(LOG_ERR, "verify_signature() failed: %s", get_error());
+ pam_syslog(pamh, LOG_ERR, "verify_signature() failed: %s", get_error());
return PAM_AUTH_ERR;
}
@@ -375,13 +487,69 @@
DBG("Skipping signature check");
}
+ /*
+ * fill in the environment variables.
+ */
+ snprintf(env_temp, sizeof(env_temp) - 1,
+ "PKCS11_LOGIN_TOKEN_NAME=%.*s",
+ (sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_TOKEN_NAME="),
+ get_slot_label(ph));
+ rv = pam_putenv(pamh, env_temp);
+
+ if (rv != PAM_SUCCESS) {
+ ERR1("could not put token name in environment: %s",
+ pam_strerror(pamh, rv));
+ pam_syslog(pamh, LOG_ERR, "could not put token name in environment: %s",
+ pam_strerror(pamh, rv));
+ }
+
+ issuer = cert_info((X509 *)get_X509_certificate(chosen_cert), CERT_ISSUER,
+ ALGORITHM_NULL);
+ if (issuer) {
+ snprintf(env_temp, sizeof(env_temp) - 1,
+ "PKCS11_LOGIN_CERT_ISSUER=%.*s",
+ (sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_CERT_ISSUER="),
+ issuer[0]);
+ rv = pam_putenv(pamh, env_temp);
+ } else {
+ ERR("couldn't get certificate issuer.");
+ pam_syslog(pamh, LOG_ERR, "couldn't get certificate issuer.");
+ }
+
+ if (rv != PAM_SUCCESS) {
+ ERR1("could not put cert issuer in environment: %s",
+ pam_strerror(pamh, rv));
+ pam_syslog(pamh, LOG_ERR, "could not put cert issuer in environment: %s",
+ pam_strerror(pamh, rv));
+ }
+
+ serial = cert_info((X509 *)get_X509_certificate(chosen_cert), CERT_SERIAL,
+ ALGORITHM_NULL);
+ if (serial) {
+ snprintf(env_temp, sizeof(env_temp) - 1,
+ "PKCS11_LOGIN_CERT_SERIAL=%.*s",
+ (sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_CERT_SERIAL="),
+ serial[0]);
+ rv = pam_putenv(pamh, env_temp);
+ } else {
+ ERR("couldn't get certificate serial number.");
+ pam_syslog(pamh, LOG_ERR, "couldn't get certificate serial number.");
+ }
+
+ if (rv != PAM_SUCCESS) {
+ ERR1("could not put cert serial in environment: %s",
+ pam_strerror(pamh, rv));
+ pam_syslog(pamh, LOG_ERR, "could not put cert serial in environment: %s",
+ pam_strerror(pamh, rv));
+ }
+
/* close pkcs #11 session */
rv = close_pkcs11_session(ph);
if (rv != 0) {
release_pkcs11_module(ph);
ERR1("close_pkcs11_session() failed: %s", get_error());
- syslog(LOG_ERR, "close_pkcs11_module() failed: %s", get_error());
- return PAM_AUTHINFO_UNAVAIL;
+ pam_syslog(pamh, LOG_ERR, "close_pkcs11_module() failed: %s", get_error());
+ return pkcs11_pam_fail;
}
/* release pkcs #11 module */
@@ -399,7 +567,7 @@
unload_mappers();
close_pkcs11_session(ph);
release_pkcs11_module(ph);
- return PAM_AUTHINFO_UNAVAIL;
+ return pkcs11_pam_fail;
}
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const
char **argv)
@@ -412,36 +580,40 @@
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const
char **argv)
{
ERR("Warning: Function pm_sm_acct_mgmt() is not implemented in this module");
- openlog(LOGNAME, LOG_CONS | LOG_PID, LOG_AUTHPRIV);
- syslog(LOG_WARNING, "Function pm_sm_acct_mgmt() is not implemented in this
module");
- closelog();
+ pam_syslog(pamh, LOG_WARNING,
+ "Function pm_sm_acct_mgmt() is not implemented in this module");
return PAM_SERVICE_ERR;
}
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
ERR("Warning: Function pam_sm_open_session() is not implemented in this
module");
- openlog(LOGNAME, LOG_CONS | LOG_PID, LOG_AUTHPRIV);
- syslog(LOG_WARNING, "Function pm_sm_open_session() is not implemented in
this module");
- closelog();
+ pam_syslog(pamh, LOG_WARNING,
+ "Function pm_sm_open_session() is not implemented in this
module");
return PAM_SERVICE_ERR;
}
PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc,
const char **argv)
{
ERR("Warning: Function pam_sm_close_session() is not implemented in this
module");
- openlog(LOGNAME, LOG_CONS | LOG_PID, LOG_AUTHPRIV);
- syslog(LOG_WARNING, "Function pm_sm_close_session() is not implemented in
this module");
- closelog();
+ pam_syslog(pamh, LOG_WARNING,
+ "Function pm_sm_close_session() is not implemented in this module");
return PAM_SERVICE_ERR;
}
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const
char **argv)
{
+ char *login_token_name;
+
ERR("Warning: Function pam_sm_chauthtok() is not implemented in this
module");
- openlog(LOGNAME, LOG_CONS | LOG_PID, LOG_AUTHPRIV);
- syslog(LOG_WARNING, "Function pam_sm_chauthtok() is not implemented in this
module");
- closelog();
+ pam_syslog(pamh, LOG_WARNING,
+ "Function pam_sm_chauthtok() is not implemented in this module");
+
+ login_token_name = getenv("PKCS11_LOGIN_TOKEN_NAME");
+ if (login_token_name && (flags & PAM_PRELIM_CHECK)) {
+ pam_prompt(pamh, PAM_TEXT_INFO, NULL,
+ "Cannot change the password on your smart card.");
+ }
return PAM_SERVICE_ERR;
}
Index: src/pam_pkcs11/pam_config.c
===================================================================
--- src/pam_pkcs11/pam_config.c (revision 264)
+++ src/pam_pkcs11/pam_config.c (working copy)
@@ -39,8 +39,11 @@
0, /* int try_first_pass; */
0, /* int use_first_pass; */
0, /* int use_authok; */
+ 0, /* int card_only; */
+ 0, /* int wait_for_card; */
"default", /* const char *pkcs11_module; */
"/etc/pam_pkcs11/pkcs11_module.so",/* const char *pkcs11_module_path;
*/
+ NULL, /* screen savers */
0, /* int slot_num; */
0, /* support threads */
/* cert policy; */
@@ -55,6 +58,8 @@
DBG1("try_first_pass %d",configuration.try_first_pass);
DBG1("use_first_pass %d", configuration.use_first_pass);
DBG1("use_authok %d", configuration.use_authok);
+ DBG1("card_only %d", configuration.card_only);
+ DBG1("wait_for_card %d", configuration.wait_for_card);
DBG1("pkcs11_module %s",configuration.pkcs11_module);
DBG1("slot_num %d",configuration.slot_num);
DBG1("ca_dir %s",configuration.policy.ca_dir);
@@ -75,6 +80,8 @@
scconf_block **pkcs11_mblocks,*pkcs11_mblk;
const scconf_list *mapper_list;
const scconf_list *policy_list;
+ const scconf_list *screen_saver_list;
+ const scconf_list *tmp;
scconf_context *ctx;
const scconf_block *root;
configuration.ctx = scconf_new(configuration.config_file);
@@ -105,6 +112,10 @@
scconf_get_bool(root,"try_first_pass",configuration.try_first_pass);
configuration.use_authok =
scconf_get_bool(root,"use_authok",configuration.use_authok);
+ configuration.card_only =
+ scconf_get_bool(root,"card_only",configuration.card_only);
+ configuration.wait_for_card =
+ scconf_get_bool(root,"wait_for_card",configuration.wait_for_card);
configuration.pkcs11_module = ( char * )
scconf_get_str(root,"use_pkcs11_module",configuration.pkcs11_module);
/* search pkcs11 module options */
@@ -155,6 +166,18 @@
policy_list= policy_list->next;
}
}
+ screen_saver_list = scconf_find_list(root,"screen_savers");
+ if (screen_saver_list) {
+ int count,i;
+ for (count=0, tmp=screen_saver_list; tmp ; tmp=tmp->next, count++);
+
+ configuration.screen_savers =
+ (char **) malloc((count+1)*sizeof(char *));
+ for (i=0, tmp=screen_saver_list; tmp; tmp=tmp->next, i++) {
+ configuration.screen_savers[i] = (char *)tmp->data;
+ }
+ configuration.screen_savers[count] = 0;
+ }
/* now obtain and initialize mapper list */
mapper_list = scconf_find_list(root,"use_mappers");
if (!mapper_list) {
@@ -187,8 +210,8 @@
parse_config_file();
/* display_config(); */
/* finally parse provided arguments */
- /* skip argv[0] :-) */
- for (i = 1; i < argc; i++) {
+ /* dont skip argv[0] */
+ for (i = 0; i < argc; i++) {
if (strcmp("nullok", argv[i]) == 0) {
configuration.nullok = 1;
continue;
@@ -201,6 +224,14 @@
configuration.use_first_pass = 1;
continue;
}
+ if (strcmp("wait_for_card", argv[i]) == 0) {
+ configuration.wait_for_card = 1;
+ continue;
+ }
+ if (strcmp("dont_wait_for_card", argv[i]) == 0) {
+ configuration.wait_for_card = 0;
+ continue;
+ }
if (strcmp("debug", argv[i]) == 0) {
configuration.debug = 1;
set_debug_level(1);
Index: src/pam_pkcs11/pam_config.h
===================================================================
--- src/pam_pkcs11/pam_config.h (revision 264)
+++ src/pam_pkcs11/pam_config.h (working copy)
@@ -33,8 +33,11 @@
int try_first_pass;
int use_first_pass;
int use_authok;
+ int card_only;
+ int wait_for_card;
char *pkcs11_module;
char *pkcs11_modulepath;
+ char **screen_savers;
int slot_num;
int support_threads;
cert_policy policy;
Index: src/tools/pkcs11_setup.c
===================================================================
--- src/tools/pkcs11_setup.c (revision 0)
+++ src/tools/pkcs11_setup.c (revision 0)
@@ -0,0 +1,519 @@
+/*
+ * PKCS#11 Card viewer tool
+ * Copyright (C) 2006 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include "../scconf/scconf.h"
+#include "../common/debug.h"
+#include "../common/error.h"
+
+#define PAM_PKCS11_CONF "/etc/pam_pkcs11/pam_pkcs11.conf"
+#define EVENTMGR_CONF "/etc/pam_pkcs11/pkcs11_eventmgr.conf"
+
+static const char Ins_action[] = "ins_action=";
+static const char Rm_action[] = "rm_action=";
+static const char Use_module[] = "use_module=";
+static const char List_modules[] = "list_modules";
+
+enum params { INS_ACTION, RM_ACTION, USE_MODULE, LIST_MODULES };
+
+static const char const *param_names[] = { Ins_action, Rm_action, Use_module,
List_modules };
+static int pn_sizes[] = { sizeof(Ins_action), sizeof(Rm_action),
sizeof(Use_module), sizeof(List_modules) };
+
+#define NUM_PARAMS (sizeof(param_names)/sizeof(param_names[0]))
+
+const char *scconf_replace_str(scconf_block * block, const char *option, const
char *value)
+{
+ scconf_list *list = NULL;
+ scconf_item *item;
+
+ scconf_list_add(&list, value);
+ item = scconf_item_add(NULL, block, NULL, SCCONF_ITEM_TYPE_VALUE, option,
list);
+
+ /* now clear out the item list */
+ scconf_list_destroy(item->value.list);
+ item->value.list = list; /* adopt */
+ return value;
+}
+
+int scconf_replace_str_list(scconf_block * block, const char *option, const
char *value)
+{
+ scconf_list *list = NULL;
+ scconf_item *item;
+ char *lstitem = NULL;
+ char *next;
+
+ while (value != NULL) {
+ if ((next=strchr(value, ',')) != NULL) {
+ lstitem = strndup(value, next-value);
+ next++;
+ }
+ else {
+ lstitem = strdup(value);
+ }
+ if (lstitem == NULL)
+ return 1;
+ scconf_list_add(&list, lstitem);
+ value = next;
+ free(lstitem);
+ }
+
+ item = scconf_item_add(NULL, block, NULL, SCCONF_ITEM_TYPE_VALUE, option,
list);
+
+ /* now clear out the item list */
+ scconf_list_destroy(item->value.list);
+ item->value.list = list; /* adopt */
+ return 0;
+}
+
+int list_modules(void)
+{
+ const scconf_block *pam_pkcs11;
+ scconf_block **pkcs11_blocks;
+ scconf_context *ctx = NULL;
+ int i;
+ int result = 1;
+
+ /*
+ * loop through looking for smart card entries
+ */
+ ctx = scconf_new(PAM_PKCS11_CONF);
+ if (ctx == NULL) {
+ goto bail;
+ }
+ if (scconf_parse(ctx) <= 0 ) {
+ goto bail;
+ }
+ pam_pkcs11 = scconf_find_block(ctx, NULL, "pam_pkcs11");
+ if (!pam_pkcs11) {
+ goto bail;
+ }
+ pkcs11_blocks = scconf_find_blocks(ctx, pam_pkcs11, "pkcs11_module", NULL);
+ if (!pkcs11_blocks) {
+ goto bail;
+ }
+
+ /* list only those smart cards which are actually installed */
+ for (i=0; pkcs11_blocks[i]; i++) {
+ void *libhandle;
+ const char *path =
+ scconf_get_str(pkcs11_blocks[i], "module", NULL);
+ /* check to see if the module exists on the system */
+ if (!path || *path == 0) {
+ continue;
+ }
+ /* verify the module exists */
+ if ((libhandle=dlopen(path, RTLD_LAZY)) != NULL) {
+ dlclose(libhandle);
+ if (pkcs11_blocks[i] && pkcs11_blocks[i]->name
+ && pkcs11_blocks[i]->name->data) {
+ printf("%s\n", pkcs11_blocks[i]->name->data);
+ }
+ }
+ }
+
+ result = 0;
+
+bail:
+ if (ctx) {
+ scconf_free(ctx);
+ }
+ return result;
+}
+
+int print_default_module(void)
+{
+ const scconf_block *pam_pkcs11;
+ scconf_context *ctx = NULL;
+ int result = 1;
+
+ /*
+ * read the base pam_pkcs11.conf
+ */
+ ctx = scconf_new(PAM_PKCS11_CONF);
+ if (ctx == NULL) {
+ goto bail;
+ }
+ if (scconf_parse(ctx) <= 0) {
+ goto bail;
+ }
+ pam_pkcs11 = scconf_find_block(ctx, NULL, "pam_pkcs11");
+ if (!pam_pkcs11) {
+ goto bail;
+ }
+ printf("%s\n", scconf_get_str(pam_pkcs11, "use_pkcs11_module", ""));
+ result = 0;
+
+ bail:
+ if (ctx) {
+ scconf_free(ctx);
+ }
+ ctx = NULL;
+
+ return result;
+}
+
+int set_default_module(const char *mod)
+{
+ scconf_block *pam_pkcs11, *pkcs11_eventmgr;
+ scconf_block **modules = NULL;
+ scconf_context *ctx = NULL;
+ scconf_context *ectx = NULL;
+ const char *lib = NULL;
+ int result = 1;
+
+ /*
+ * write out pam_pkcs11.conf
+ */
+ ctx = scconf_new(PAM_PKCS11_CONF);
+ if (ctx == NULL) {
+ goto bail;
+ }
+ if (scconf_parse(ctx) <= 0) {
+ goto bail;
+ }
+ pam_pkcs11 = (scconf_block *)scconf_find_block(ctx, NULL, "pam_pkcs11");
+ if (!pam_pkcs11) {
+ goto bail;
+ }
+ scconf_replace_str(pam_pkcs11, "use_pkcs11_module", mod);
+
+ modules = scconf_find_blocks(ctx, pam_pkcs11, "pkcs11_module", mod);
+ if (!modules || !modules[0]) {
+ goto bail;
+ }
+ lib = scconf_get_str(modules[0], "module", NULL);
+ if (!lib) {
+ goto bail;
+ }
+ result = scconf_write(ctx, NULL);
+ if (result != 0) {
+ goto bail;
+ }
+
+ ectx = scconf_new(EVENTMGR_CONF);
+ if (ectx == NULL) {
+ goto bail;
+ }
+ if (scconf_parse(ectx) <= 0) {
+ goto bail;
+ }
+ pkcs11_eventmgr = (scconf_block *)
+ scconf_find_block(ectx, NULL, "pkcs11_eventmgr");
+ if (!pkcs11_eventmgr) {
+ goto bail;
+ }
+ scconf_replace_str(pkcs11_eventmgr, "pkcs11_module", lib);
+ result = scconf_write(ectx, NULL);
+
+bail:
+ if (modules) {
+ free(modules);
+ }
+ if (ctx) {
+ scconf_free(ctx);
+ }
+ if (ectx) {
+ scconf_free(ectx);
+ }
+
+ return result;
+}
+
+int print_card_insert_action(void)
+{
+ const scconf_block *pkcs11_eventmgr;
+ scconf_block **event_blocks = NULL;
+ scconf_context *ctx = NULL;
+ const scconf_list *actionList = NULL;
+ int result = 1;
+
+ /*
+ * read the pkcs11_eventmgr.conf to get our action
+ */
+ ctx = scconf_new(EVENTMGR_CONF);
+ if (ctx == NULL) {
+ goto bail;
+ }
+ if (scconf_parse(ctx) <= 0) {
+ goto bail;
+ }
+ pkcs11_eventmgr = scconf_find_block(ctx, NULL, "pkcs11_eventmgr");
+ if (!pkcs11_eventmgr) {
+ goto bail;
+ }
+ event_blocks = scconf_find_blocks(ctx, pkcs11_eventmgr, "event",
+ "card_insert");
+ if (!event_blocks || !event_blocks[0]) {
+ goto bail;
+ }
+ actionList = scconf_find_list(event_blocks[0],"action");
+ if (actionList) {
+ char *lst = scconf_list_strdup(actionList, "\n");
+ if (lst != NULL) {
+ printf("%s\n", lst);
+ free(lst);
+ }
+ }
+ result = 0;
+
+bail:
+ if (event_blocks) {
+ free(event_blocks);
+ }
+ if (ctx) {
+ scconf_free(ctx);
+ }
+
+ return result;
+}
+
+int set_card_insert_action(const char *act)
+{
+ scconf_block *pkcs11_eventmgr;
+ scconf_block **insert_blocks = NULL;
+ scconf_context *ctx = NULL;
+ int result = 1;
+
+ /*
+ * write out pkcs11_eventmgr.conf
+ */
+ ctx = scconf_new(EVENTMGR_CONF);
+ if (ctx == NULL) {
+ goto bail;
+ }
+ if (scconf_parse(ctx) <= 0) {
+ goto bail;
+ }
+ pkcs11_eventmgr = (scconf_block *)
+ scconf_find_block(ctx, NULL, "pkcs11_eventmgr");
+ if (!pkcs11_eventmgr) {
+ goto bail;
+ }
+ insert_blocks = scconf_find_blocks(ctx, pkcs11_eventmgr,
+ "event", "card_insert");
+ if (!insert_blocks || !insert_blocks[0]) {
+ goto bail;
+ }
+
+ scconf_replace_str_list(insert_blocks[0], "action", act);
+
+ result = scconf_write(ctx, NULL);
+
+bail:
+ if (insert_blocks) {
+ free(insert_blocks);
+ }
+ if (ctx) {
+ scconf_free(ctx);
+ }
+ return result;
+}
+
+int print_card_remove_action(void)
+{
+ const scconf_block *pkcs11_eventmgr;
+ scconf_block **event_blocks = NULL;
+ scconf_context *ctx = NULL;
+ const scconf_list *actionList = NULL;
+ int result = 1;
+
+ /*
+ * read the pkcs11_eventmgr.conf to get our action
+ */
+ ctx = scconf_new(EVENTMGR_CONF);
+ if (ctx == NULL) {
+ goto bail;
+ }
+ if (scconf_parse(ctx) <= 0) {
+ goto bail;
+ }
+ pkcs11_eventmgr = scconf_find_block(ctx, NULL, "pkcs11_eventmgr");
+ if (!pkcs11_eventmgr) {
+ goto bail;
+ }
+ event_blocks = scconf_find_blocks(ctx, pkcs11_eventmgr, "event",
+ "card_remove");
+ if (!event_blocks || !event_blocks[0]) {
+ goto bail;
+ }
+ actionList = scconf_find_list(event_blocks[0],"action");
+ if (actionList) {
+ char *lst = scconf_list_strdup(actionList, "\n");
+ if (lst != NULL) {
+ printf("%s\n", lst);
+ free(lst);
+ }
+ }
+ result = 0;
+
+bail:
+ if (event_blocks) {
+ free(event_blocks);
+ }
+ if (ctx) {
+ scconf_free(ctx);
+ }
+
+ return result;
+}
+
+int set_card_remove_action(const char *act)
+{
+ scconf_block *pkcs11_eventmgr;
+ scconf_block **insert_blocks = NULL;
+ scconf_context *ctx = NULL;
+ int result = 1;
+
+ /*
+ * write out pkcs11_eventmgr.conf
+ */
+ ctx = scconf_new(EVENTMGR_CONF);
+ if (ctx == NULL) {
+ goto bail;
+ }
+ if (scconf_parse(ctx) <= 0) {
+ goto bail;
+ }
+ pkcs11_eventmgr = (scconf_block *)
+ scconf_find_block(ctx, NULL, "pkcs11_eventmgr");
+ if (!pkcs11_eventmgr) {
+ goto bail;
+ }
+ insert_blocks = scconf_find_blocks(ctx, pkcs11_eventmgr,
+ "event", "card_remove");
+ if (!insert_blocks || !insert_blocks[0]) {
+ goto bail;
+ }
+
+ scconf_replace_str_list(insert_blocks[0], "action", act);
+
+ result = scconf_write(ctx, NULL);
+
+bail:
+ if (insert_blocks) {
+ free(insert_blocks);
+ }
+ if (ctx) {
+ scconf_free(ctx);
+ }
+ return result;
+}
+
+int main(int argc, const char **argv)
+{
+ int i;
+ int pname;
+ const char *params[NUM_PARAMS];
+
+ memset(params, '\0', sizeof(params));
+
+ for (i = 1; i < argc; i++) {
+ for (pname = 0; pname < NUM_PARAMS; pname++) {
+ if (param_names[pname][pn_sizes[pname]-2] == '=') {
+ if (strncmp(argv[i], param_names[pname], pn_sizes[pname]-1) ==
0) {
+ params[pname] = argv[i] + pn_sizes[pname] - 1;
+ }
+ else if (strncmp(argv[i], param_names[pname],
pn_sizes[pname]-2) == 0
+ && argv[i][pn_sizes[pname]-2] == '\0') {
+ params[pname] = (void *)1;
+ }
+ }
+ else {
+ if (strcmp(argv[i], param_names[pname]) == 0) {
+ params[pname] = (void *)1;
+ }
+ }
+ }
+ }
+
+ for (pname = 0; pname < NUM_PARAMS; pname++) {
+ if (params[pname] != NULL)
+ break;
+ }
+
+ if (pname == NUM_PARAMS) {
+ DBG("No correct parameter specified");
+ printf("usage: pkcs11_setup [list_modules]
[use_module[=<module_name>]]\n"
+ "
[ins_action[=<executable,executable,...>]]\n"
+ "
[rm_action[=<executable,executable,...>]]\n");
+ }
+
+ if (params[LIST_MODULES] != NULL) {
+ DBG("List modules:");
+ return list_modules();
+ }
+ else {
+ if (params[USE_MODULE] == (void *)1) {
+ DBG("Print default module:");
+ if ((i=print_default_module()) != 0) {
+ DBG1("Print default module failed with: %d", i);
+ return i;
+ }
+ return 0;
+ }
+ else if (params[USE_MODULE] != NULL) {
+ DBG1("Set default module: %s", params[USE_MODULE]);
+ if ((i=set_default_module(params[USE_MODULE])) != 0) {
+ DBG1("Set default module failed with: %d", i);
+ return i;
+ }
+ }
+ if (params[INS_ACTION] == (void *)1) {
+ DBG("Print card insert action:");
+ if ((i=print_card_insert_action()) != 0) {
+ DBG1("Print card insert action failed with: %d", i);
+ return i;
+ }
+ return 0;
+ }
+ else if (params[INS_ACTION] != NULL) {
+ DBG1("Set card insert action: %s", params[INS_ACTION]);
+ if ((i=set_card_insert_action(params[INS_ACTION])) != 0) {
+ DBG1("Set card insert action failed with: %d", i);
+ return i;
+ }
+ }
+ if (params[RM_ACTION] == (void *)1) {
+ DBG("Print card remove action:");
+ if ((i=print_card_remove_action()) != 0) {
+ DBG1("Set card remove action failed with: %d", i);
+ return i;
+ }
+ return 0;
+ }
+ else if (params[RM_ACTION] != NULL) {
+ DBG1("Set card remove action: %s", params[RM_ACTION]);
+ if ((i=set_card_remove_action(params[RM_ACTION])) != 0) {
+ DBG1("Set card remove action failed with: %d", i);
+ return i;
+ }
+ }
+ }
+ DBG("Process completed");
+ return 0;
+}
Index: src/tools/Makefile.am
===================================================================
--- src/tools/Makefile.am (revision 264)
+++ src/tools/Makefile.am (working copy)
@@ -8,11 +8,11 @@
AM_LDFLAGS = $(PCSC_LIBS)
if HAVE_PCSC
-bin_PROGRAMS = card_eventmgr pkcs11_eventmgr pklogin_finder pkcs11_inspect
pkcs11_listcerts
+bin_PROGRAMS = card_eventmgr pkcs11_eventmgr pklogin_finder pkcs11_inspect
pkcs11_listcerts pkcs11_setup
card_eventmgr_SOURCES = card_eventmgr.c
card_eventmgr_LDADD = $(LIBSCCONF) $(LIBCOMMON)
else
-bin_PROGRAMS = pkcs11_eventmgr pklogin_finder pkcs11_inspect pkcs11_listcerts
+bin_PROGRAMS = pkcs11_eventmgr pklogin_finder pkcs11_inspect pkcs11_listcerts
pkcs11_setup
endif
pklogin_finder_SOURCES = pklogin_finder.c
@@ -26,3 +26,6 @@
pkcs11_inspect_SOURCES = pkcs11_inspect.c
pkcs11_inspect_LDADD = $(FINDER_OBJS) $(LIBMAPPERS)
+
+pkcs11_setup_SOURCES = pkcs11_setup.c
+pkcs11_setup_LDADD = $(LIBSCCONF) $(LIBCOMMON)
Index: src/tools/pkcs11_eventmgr.c
===================================================================
--- src/tools/pkcs11_eventmgr.c (revision 264)
+++ src/tools/pkcs11_eventmgr.c (working copy)
@@ -31,7 +31,7 @@
#include "../common/error.h"
#ifdef HAVE_NSS
-#include <nss/secmod.h>
+#include <secmod.h>
#endif
#define DEF_POLLING 1 /* 1 second timeout */
@@ -404,7 +404,10 @@
moduleSpec, pkcs11_module);
module = SECMOD_LoadUserModule(moduleSpec, NULL, 0);
free(moduleSpec);
- if (!module) {
+ if (!module || module->loaded == 0) {
+ if (module) {
+ SECMOD_DestroyModule(module);
+ }
DBG("Failed to load SmartCard software");
return 1;
}
Index: src/common/cert_info.c
===================================================================
--- src/common/cert_info.c (revision 264)
+++ src/common/cert_info.c (working copy)
@@ -747,6 +747,34 @@
return entries;
}
+/*
+* Return certificate in PEM format
+*/
+static char **cert_info_serial_number(X509 *x509) {
+ static char *entries[2] = { NULL,NULL };
+ ASN1_INTEGER *serial = X509_get_serialNumber(x509);
+ int len;
+ char *buffer = NULL, *tmp_ptr;
+
+ len = i2c_ASN1_INTEGER(serial, NULL);
+
+ if (len < 0) {
+ return NULL;
+ }
+ buffer = malloc(len);
+ if (buffer == NULL) {
+ return NULL;
+ }
+
+ /* i2c_ASN1_INTEGER "kindly" increments our pointer by len,
+ * give it a temp ptr it can tweak to it's hearts content */
+ tmp_ptr = buffer;
+ len = i2c_ASN1_INTEGER(serial, &tmp_ptr);
+ entries[0] = bin2hex(buffer,len);
+ free(buffer);
+ return entries;
+}
+
/**
* request info on certificate
* @param x509 Certificate to parse
@@ -768,7 +796,7 @@
return cert_info_issuer(x509);
case CERT_SERIAL : /* Certificate serial number */
/* fix me */
- return NULL;
+ return cert_info_serial_number(x509);
case CERT_KPN : /* Kerberos principal name */
return cert_info_kpn(x509);
case CERT_EMAIL : /* Certificate e-mail */
Index: src/common/pkcs11_lib.c
===================================================================
--- src/common/pkcs11_lib.c (revision 264)
+++ src/common/pkcs11_lib.c (working copy)
@@ -81,9 +81,14 @@
#include "ocsp.h"
#include <unistd.h>
#include <errno.h>
+#include "syslog.h"
#include "cert_vfy.h"
+#ifndef PAM_PKCS11_POLL_TIME
+#define PAM_PKCS11_POLL_TIME 500 /* ms */
+#endif
+
struct pkcs11_handle_str {
SECMODModule *module;
PRBool is_user_module;
@@ -290,6 +295,96 @@
return -1;
}
+/*
+ * find a slot by it's slot number or label. If slot number is '0' any
+ * slot is ok.
+ */
+int find_slot_by_number_and_label(pkcs11_handle_t *h,
+ int wanted_slot_id,
+ const char *wanted_slot_label,
+ unsigned int *slot_num)
+{
+ int rv;
+ const char *slot_label = NULL;
+ PK11SlotInfo *slot = NULL;
+
+ /* we want a specific slot id, or we don't kare about the label */
+ if ((wanted_slot_label == NULL) || (wanted_slot_id != 0)) {
+ rv = find_slot_by_number(h, wanted_slot_id, slot_num);
+
+ /* if we don't care about the label, or we failed, we're done */
+ if ((wanted_slot_label == NULL) || (rv != 0)) {
+ return rv;
+ }
+
+ /* verify it's the label we want */
+ slot_label = PK11_GetTokenName(h->slot);
+
+ if ((slot_label != NULL) &&
+ (strcmp (wanted_slot_label, slot_label) == 0)) {
+ return 0;
+ }
+ return -1;
+ }
+
+ /* we want a specific slot by label only */
+ slot = PK11_FindSlotByName(wanted_slot_label);
+ if (!slot) {
+ return -1;
+ }
+
+ /* make sure it's in the right module */
+ if (h->module) {
+ if (h->module != PK11_GetModule(slot)) {
+ PK11_FreeSlot(slot);
+ return -1;
+ }
+ } else {
+ /* no module was specified, use the one slot came in */
+ h->module = SECMOD_ReferenceModule(PK11_GetModule(slot));
+ }
+ h->slot = slot; /* Adopt the reference */
+ *slot_num = PK11_GetSlotID(h->slot);
+ return 0;
+}
+
+int wait_for_token(pkcs11_handle_t *h,
+ int wanted_slot_id,
+ const char *wanted_slot_label,
+ unsigned int *slot_num)
+{
+ int rv;
+
+ rv = -1;
+ do {
+ /* see if the card we're looking for is inserted */
+ rv = find_slot_by_number_and_label (h, wanted_slot_id, wanted_slot_label,
+ slot_num);
+ if (rv != 0) {
+ PK11SlotInfo *slot;
+ PRIntervalTime slot_poll_interval; /* only for legacy hardware */
+
+ /* if the card is not inserted, then block until something happens */
+ slot_poll_interval = PR_MillisecondsToInterval(PAM_PKCS11_POLL_TIME);
+ slot = SECMOD_WaitForAnyTokenEvent(h->module, 0 /* flags */,
+ slot_poll_interval);
+
+ /* unexpected error */
+ if (slot == NULL) {
+ break;
+ }
+
+ /* something happened, continue loop and check if the card
+ * we're looking for is inserted
+ */
+ PK11_FreeSlot(slot);
+ continue;
+ }
+ } while (rv != 0);
+
+ return rv;
+}
+
void release_pkcs11_module(pkcs11_handle_t *h)
{
SECStatus rv;
@@ -383,6 +478,8 @@
return PK11_GetTokenName(h->slot);
}
+
+
cert_object_t **get_certificate_list(pkcs11_handle_t *h, int *count)
{
CERTCertList * certList;
@@ -692,10 +789,50 @@
return 0;
}
+static int
+refresh_slots(pkcs11_handle_t *h)
+{
+ CK_ULONG i;
+ int j;
+
+ for (i = 0; i < h->slot_count; i++) {
+ CK_SLOT_INFO sinfo;
+ CK_TOKEN_INFO tinfo;
+ CK_RV rv;
+
+ DBG1("slot %d:", i + 1);
+ rv = h->fl->C_GetSlotInfo(h->slots[i].id, &sinfo);
+ if (rv != CKR_OK) {
+ set_error("C_GetSlotInfo() failed: %x", rv);
+ return -1;
+ }
+ DBG1("- description: %.64s", sinfo.slotDescription);
+ DBG1("- manufacturer: %.32s", sinfo.manufacturerID);
+ DBG1("- flags: %04lx", sinfo.flags);
+ if (sinfo.flags & CKF_TOKEN_PRESENT) {
+ DBG("- token:");
+ rv = h->fl->C_GetTokenInfo(h->slots[i].id, &tinfo);
+ if (rv != CKR_OK) {
+ set_error("C_GetTokenInfo() failed: %x", rv);
+ return -1;
+ }
+ DBG1(" - label: %.32s", tinfo.label);
+ DBG1(" - manufacturer: %.32s", tinfo.manufacturerID);
+ DBG1(" - model: %.16s", tinfo.model);
+ DBG1(" - serial: %.16s", tinfo.serialNumber);
+ DBG1(" - flags: %04lx", tinfo.flags);
+ h->slots[i].token_present = TRUE;
+ memcpy(h->slots[i].label, tinfo.label, 32);
+ for (j = 31; h->slots[i].label[j] == ' '; j--) h->slots[i].label[j] = 0;
+ }
+ }
+ return 0;
+}
+
int init_pkcs11_module(pkcs11_handle_t *h,int flag)
{
int rv;
- CK_ULONG i, j;
+ CK_ULONG i;
CK_SLOT_ID_PTR slots;
CK_INFO info;
CK_C_INITIALIZE_ARGS initArgs;
@@ -763,40 +900,10 @@
DBG1("number of slots (b): %d", h->slot_count);
/* show some information about the slots/tokens and setup slot info */
for (i = 0; i < h->slot_count; i++) {
- CK_SLOT_INFO sinfo;
- CK_TOKEN_INFO tinfo;
-
- DBG1("slot %d:", i + 1);
- rv = h->fl->C_GetSlotInfo(slots[i], &sinfo);
- if (rv != CKR_OK) {
- free(slots);
- set_error("C_GetSlotInfo() failed: %x", rv);
- return -1;
- }
h->slots[i].id = slots[i];
- DBG1("- description: %.64s", sinfo.slotDescription);
- DBG1("- manufacturer: %.32s", sinfo.manufacturerID);
- DBG1("- flags: %04lx", sinfo.flags);
- if (sinfo.flags & CKF_TOKEN_PRESENT) {
- DBG("- token:");
- rv = h->fl->C_GetTokenInfo(slots[i], &tinfo);
- if (rv != CKR_OK) {
- free(slots);
- set_error("C_GetTokenInfo() failed: %x", rv);
- return -1;
- }
- DBG1(" - label: %.32s", tinfo.label);
- DBG1(" - manufacturer: %.32s", tinfo.manufacturerID);
- DBG1(" - model: %.16s", tinfo.model);
- DBG1(" - serial: %.16s", tinfo.serialNumber);
- DBG1(" - flags: %04lx", tinfo.flags);
- h->slots[i].token_present = TRUE;
- memcpy(h->slots[i].label, tinfo.label, 32);
- for (j = 31; h->slots[i].label[j] == ' '; j--) h->slots[i].label[j] = 0;
- }
}
free(slots);
- return 0;
+ return refresh_slots(h);
}
void release_pkcs11_module(pkcs11_handle_t *h)
@@ -832,7 +939,71 @@
return 0;
}
+int find_slot_by_number_and_label(pkcs11_handle_t *h,
+ int wanted_slot_id,
+ const char *wanted_slot_label,
+ unsigned int *slot_num)
+{
+ unsigned int slot_index;
+ int rv;
+ const char *slot_label = NULL;
+ /* we want a specific slot id, or we don't kare about the label */
+ if ((wanted_slot_label == NULL) || (wanted_slot_id != 0)) {
+ rv = find_slot_by_number(h, wanted_slot_id, slot_num);
+
+ /* if we don't care about the label, or we failed, we're done */
+ if ((wanted_slot_label == NULL) || (rv != 0)) {
+ return rv;
+ }
+
+ /* verify it's the label we want */
+ slot_label = h->slots[*slot_num].label;
+
+ if ((slot_label != NULL) &&
+ (strcmp (wanted_slot_label, slot_label) == 0)) {
+ return 0;
+ }
+ return -1;
+ }
+
+ /* look up the slot by it's label from the list */
+ for (slot_index = 0; slot_index < h->slot_count; slot_index++) {
+ if (h->slots[slot_index].token_present) {
+ slot_label = h->slots[slot_index].label;
+ if ((slot_label != NULL) &&
+ (strcmp (wanted_slot_label, slot_label) == 0)) {
+ *slot_num = slot_index;
+ return 0;
+ }
+ }
+ }
+ return -1;
+}
+
+int wait_for_token(pkcs11_handle_t *h,
+ int wanted_slot_id,
+ const char *wanted_slot_label,
+ unsigned int *slot_num)
+{
+ int rv;
+
+ rv = -1;
+ do {
+ /* see if the card we're looking for is inserted */
+ rv = find_slot_by_number_and_label (h, wanted_slot_id, wanted_slot_label,
+ slot_num);
+ if (rv != 0) {
+ /* could call C_WaitForSlotEvent, for now just poll */
+ sleep(10);
+ refresh_slots(h);
+ continue;
+ }
+ } while (rv != 0);
+
+ return rv;
+}
+
int open_pkcs11_session(pkcs11_handle_t *h, unsigned int slot)
{
int rv;
@@ -852,6 +1023,7 @@
return 0;
}
+
int pkcs11_login(pkcs11_handle_t *h, char *password)
{
int rv;
Index: src/common/strings.c
===================================================================
--- src/common/strings.c (revision 264)
+++ src/common/strings.c (working copy)
@@ -83,6 +83,10 @@
char *pt;
char *res= (char *) malloc(1+3*len);
if (!res) return NULL;
+ if (len == 0) {
+ *res = 0;
+ return res;
+ }
for(i=0,pt=res;i<len;i++,pt+=3){
sprintf(pt,"%02X:",binstr[i]);
}
Index: src/common/pkcs11_lib.h
===================================================================
--- src/common/pkcs11_lib.h (revision 264)
+++ src/common/pkcs11_lib.h (working copy)
@@ -33,7 +33,14 @@
PKCS11_EXTERN int init_pkcs11_module(pkcs11_handle_t *h,int flag);
PKCS11_EXTERN int find_slot_by_number(pkcs11_handle_t *h,int slot_num,
unsigned int *slot);
+PKCS11_EXTERN int find_slot_by_number_and_label(pkcs11_handle_t *h,
+ int slot_num, const char *slot_label,
+ unsigned int *slot);
PKCS11_EXTERN const char *get_slot_label(pkcs11_handle_t *h);
+PKCS11_EXTERN int wait_for_token(pkcs11_handle_t *h,
+ int wanted_slot_num,
+ const char *wanted_slot_label,
+ unsigned int *slot);
PKCS11_EXTERN const X509 *get_X509_certificate(cert_object_t *cert);
PKCS11_EXTERN void release_pkcs11_module(pkcs11_handle_t *h);
PKCS11_EXTERN int open_pkcs11_session(pkcs11_handle_t *h, unsigned int slot);
_______________________________________________
opensc-devel mailing list
[EMAIL PROTECTED]
http://www.opensc-project.org/mailman/listinfo/opensc-devel