Group :: System/Base
RPM: pam_pkcs11
Main Changelog Spec Patches Sources Download Gear Bugs and FR Repocop
Patch: pam_pkcs11-0.6.9-setpin.patch
Download
Download
src/common/pkcs11_lib.c | 34 +++-
src/common/pkcs11_lib.h | 3 +-
src/pam_pkcs11/pam_pkcs11.c | 403 +++++++++++++++++++++++++++++++++++--------
src/tools/pkcs11_inspect.c | 2 +-
src/tools/pkcs11_listcerts.c | 2 +-
src/tools/pklogin_finder.c | 2 +-
6 files changed, 361 insertions(+), 85 deletions(-)
diff --git a/src/common/pkcs11_lib.c b/src/common/pkcs11_lib.c
index 1ca184c..d548b6e 100644
--- a/src/common/pkcs11_lib.c
+++ b/src/common/pkcs11_lib.c
@@ -1401,21 +1401,29 @@ int wait_for_token(pkcs11_handle_t *h,
return rv;
}
-int open_pkcs11_session(pkcs11_handle_t *h, unsigned int slot)
+int open_pkcs11_session(pkcs11_handle_t *h, unsigned int slot, int rw)
{
int rv;
-
- DBG1("opening a new PKCS #11 session for slot %d", slot + 1);
+
+ DBG2("opening a new %s PKCS #11 session for slot %d",
+ rw ? "R/W" : "RO", slot + 1);
if (slot >= h->slot_count) {
set_error("invalid slot number %d", slot);
return -1;
}
- /* open a readonly user-session */
- rv = h->fl->C_OpenSession(h->slots[slot].id, CKF_SERIAL_SESSION, NULL, NULL, &h->session);
+
+ unsigned int flags = CKF_SERIAL_SESSION;
+ if ( rw ) {
+ flags |= CKF_RW_SESSION;
+ }
+ DBG1("C_OpenSession flags: 0x%08lX", flags);
+
+ rv = h->fl->C_OpenSession(h->slots[slot].id, flags, NULL, NULL, &h->session);
if (rv != CKR_OK) {
set_error("C_OpenSession() failed: 0x%08lX", rv);
return -1;
}
+
h->current_slot = slot;
return 0;
}
@@ -1436,6 +1444,22 @@ int pkcs11_login(pkcs11_handle_t *h, char *password)
return 0;
}
+int pkcs11_setpin(pkcs11_handle_t *h, char *old_pass, char *new_pass)
+{
+ int rv;
+
+ rv = h->fl->C_SetPIN( h->session, old_pass, strlen(old_pass),
+ new_pass, strlen(new_pass) );
+
+ if ( rv != CKR_OK ) {
+ DBG1("C_SetPIN() failed: 0x%08lX", rv);
+ set_error("C_SetPIN() failed: 0x%08lX", rv);
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
int get_slot_login_required(pkcs11_handle_t *h)
{
int rv;
diff --git a/src/common/pkcs11_lib.h b/src/common/pkcs11_lib.h
index 628caa1..3d8c277 100644
--- a/src/common/pkcs11_lib.h
+++ b/src/common/pkcs11_lib.h
@@ -54,7 +54,7 @@ PKCS11_EXTERN int wait_for_token_by_slotlabel(pkcs11_handle_t *h,
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);
+PKCS11_EXTERN int open_pkcs11_session(pkcs11_handle_t *h, unsigned int slot, int rw);
PKCS11_EXTERN int close_pkcs11_session(pkcs11_handle_t *h);
PKCS11_EXTERN int pkcs11_login(pkcs11_handle_t *h, char *password);
PKCS11_EXTERN int pkcs11_pass_login(pkcs11_handle_t *h, int nullok);
@@ -68,6 +68,7 @@ PKCS11_EXTERN int sign_value(pkcs11_handle_t *h, cert_object_t *,
unsigned char *data, unsigned long length,
unsigned char **signature, unsigned long *signature_length);
PKCS11_EXTERN int get_random_value(unsigned char *data, int length);
+PKCS11_EXTERN int pkcs11_setpin(pkcs11_handle_t *h, char *old_pass, char *new_pass);
#undef PKCS11_EXTERN
diff --git a/src/pam_pkcs11/pam_pkcs11.c b/src/pam_pkcs11/pam_pkcs11.c
index a8be0af..1e4b15c 100644
--- a/src/pam_pkcs11/pam_pkcs11.c
+++ b/src/pam_pkcs11/pam_pkcs11.c
@@ -149,7 +149,7 @@ static int pam_pkcs11_prompt(const pam_handle_t *pamh, int style, char **resp, c
/*
- * Gets the users password. Depending whether it was already asked, either
+ * Gets the user password. Depending whether it was already asked, either
* a prompt is shown or the old value is returned.
*/
static int pam_get_pwd(pam_handle_t *pamh, char **pwd, char *text, int oitem, int nitem)
@@ -204,6 +204,163 @@ static int pam_get_pwd(pam_handle_t *pamh, char **pwd, char *text, int oitem, in
return PAM_CRED_INSUFFICIENT;
}
+static void _get_pwd_error( pam_handle_t *pamh,
+ struct configuration_st *configuration,
+ int rv )
+{
+ if (!configuration->quiet) {
+ pam_prompt(pamh, PAM_ERROR_MSG , NULL,
+ _("Error 2316: password could not be read"));
+ sleep(configuration->err_display_time);
+ }
+ pam_syslog(pamh, LOG_ERR,
+ "pam_get_pwd() failed: %s", pam_strerror(pamh, rv));
+}
+
+static int check_pwd( pam_handle_t *pamh,
+ struct configuration_st *configuration,
+ char *password )
+{
+#ifdef DEBUG_SHOW_PASSWORD
+ DBG1("password = [%s]", password);
+#endif
+
+ /* check password length */
+ if ( !configuration->nullok && strlen(password) == 0 ) {
+ memset(password, 0, strlen(password));
+ pam_syslog(pamh, LOG_ERR,
+ "password length is zero but the 'nullok' " \
+ "argument was not defined.");
+ if (!configuration->quiet) {
+ pam_prompt(pamh, PAM_ERROR_MSG , NULL,
+ _("Error 2318: Empty smartcard PIN not allowed."));
+ sleep(configuration->err_display_time);
+ }
+ return PAM_AUTH_ERR;
+ }
+
+ return 0;
+}
+
+static int pkcs11_module_load_init( pam_handle_t *pamh,
+ struct configuration_st *configuration,
+ pkcs11_handle_t **ph )
+{
+ int rv;
+
+ /* load pkcs #11 module */
+ DBG("loading pkcs #11 module...");
+ rv = load_pkcs11_module(configuration->pkcs11_modulepath, ph);
+
+ if (rv != 0) {
+ ERR2("load_pkcs11_module() failed loading %s: %s",
+ configuration->pkcs11_modulepath, get_error());
+ if (!configuration->quiet) {
+ pam_syslog(pamh, LOG_ERR,
+ "load_pkcs11_module() failed loading %s: %s",
+ configuration->pkcs11_modulepath, get_error());
+ pam_prompt(pamh, PAM_ERROR_MSG , NULL,
+ _("Error 2302: PKCS#11 module failed loading"));
+ sleep(configuration->err_display_time);
+ }
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ /* initialise pkcs #11 module */
+ DBG("initializing pkcs #11 module...");
+ rv = init_pkcs11_module( *ph, configuration->support_threads );
+
+ if (rv != 0) {
+ release_pkcs11_module( *ph );
+ ERR1("init_pkcs11_module() failed: %s", get_error());
+ if (!configuration->quiet) {
+ pam_syslog(pamh, LOG_ERR,
+ "init_pkcs11_module() failed: %s",
+ get_error());
+ pam_prompt(pamh, PAM_ERROR_MSG , NULL,
+ _("Error 2304: PKCS#11 module could not be initialized"));
+ sleep(configuration->err_display_time);
+ }
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ return rv;
+}
+
+static int pkcs11_find_slot( pam_handle_t *pamh,
+ struct configuration_st *configuration,
+ const char *login_token_name,
+ pkcs11_handle_t *ph,
+ unsigned int *slot_num )
+{
+ int rv = -1;
+
+ if (configuration->slot_description != NULL) {
+ rv = find_slot_by_slotlabel_and_tokenlabel(
+ ph,
+ configuration->slot_description,
+ login_token_name,
+ slot_num
+ );
+ } else if (configuration->slot_num != -1) {
+ rv = find_slot_by_number_and_label(ph, configuration->slot_num,
+ login_token_name, slot_num);
+ }
+
+ if (rv != 0) {
+ ERR("no suitable token available");
+ if (!configuration->quiet) {
+ pam_syslog(pamh, LOG_ERR, "no suitable token available");
+ pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2306: No suitable token available"));
+ sleep(configuration->err_display_time);
+ }
+ }
+
+ return rv;
+}
+
+static int pkcs11_open_session( pam_handle_t *pamh,
+ struct configuration_st *configuration,
+ pkcs11_handle_t *ph,
+ unsigned int slot_num,
+ int rw )
+{
+ int rv;
+
+ rv = open_pkcs11_session( ph, slot_num, rw );
+
+ if (rv != 0) {
+ ERR1("open_pkcs11_session() failed: %s", get_error());
+ if (!configuration->quiet) {
+ pam_syslog(pamh, LOG_ERR, "open_pkcs11_session() failed: %s", get_error());
+ pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2312: open PKCS#11 session failed"));
+ sleep(configuration->err_display_time);
+ }
+ }
+
+ return rv;
+}
+
+static int pkcs11_close_session( pam_handle_t *pamh,
+ struct configuration_st *configuration,
+ pkcs11_handle_t *ph )
+{
+ int rv;
+
+ rv = close_pkcs11_session(ph);
+
+ if (rv != 0) {
+ ERR1("close_pkcs11_session() failed: %s", get_error());
+ if (!configuration->quiet) {
+ pam_syslog(pamh, LOG_ERR, "close_pkcs11_module() failed: %s", get_error());
+ pam_prompt(pamh, PAM_ERROR_MSG , NULL, ("Error 2344: Closing PKCS#11 session failed"));
+ sleep(configuration->err_display_time);
+ }
+ }
+
+ return rv;
+}
+
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
int i, rv;
@@ -342,43 +499,12 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, cons
return PAM_IGNORE;
}
- /* load pkcs #11 module */
- DBG("loading pkcs #11 module...");
- rv = load_pkcs11_module(configuration->pkcs11_modulepath, &ph);
- if (rv != 0) {
- ERR2("load_pkcs11_module() failed loading %s: %s",
- configuration->pkcs11_modulepath, get_error());
- if (!configuration->quiet) {
- pam_syslog(pamh, LOG_ERR, "load_pkcs11_module() failed loading %s: %s",
- configuration->pkcs11_modulepath, get_error());
- pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2302: PKCS#11 module failed loading"));
- sleep(configuration->err_display_time);
- }
- return PAM_AUTHINFO_UNAVAIL;
- }
-
- /* initialise pkcs #11 module */
- DBG("initialising pkcs #11 module...");
- rv = init_pkcs11_module(ph,configuration->support_threads);
- if (rv != 0) {
- release_pkcs11_module(ph);
- ERR1("init_pkcs11_module() failed: %s", get_error());
- if (!configuration->quiet) {
- pam_syslog(pamh, LOG_ERR, "init_pkcs11_module() failed: %s", get_error());
- pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2304: PKCS#11 module could not be initialized"));
- sleep(configuration->err_display_time);
- }
- return PAM_AUTHINFO_UNAVAIL;
+ rv = pkcs11_module_load_init( pamh, configuration, &ph );
+ if ( rv != 0 ) {
+ return rv;
}
- /* open pkcs #11 session */
- if (configuration->slot_description != NULL) {
- rv = find_slot_by_slotlabel_and_tokenlabel(ph,
- configuration->slot_description, login_token_name, &slot_num);
- } else if (configuration->slot_num != -1) {
- rv = find_slot_by_number_and_label(ph, configuration->slot_num,
- login_token_name, &slot_num);
- }
+ rv = pkcs11_find_slot( pamh, configuration, login_token_name, ph, &slot_num );
if (!configuration->card_only || !login_token_name) {
/* Allow to pass to the next module if the auth isn't
@@ -462,14 +588,9 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, cons
pam_prompt(pamh, PAM_TEXT_INFO, NULL,
_("%s found."), _(configuration->token_type));
}
- rv = open_pkcs11_session(ph, slot_num);
+
+ rv = pkcs11_open_session( pamh, configuration, ph, slot_num, 0 );
if (rv != 0) {
- ERR1("open_pkcs11_session() failed: %s", get_error());
- if (!configuration->quiet) {
- pam_syslog(pamh, LOG_ERR, "open_pkcs11_session() failed: %s", get_error());
- pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2312: open PKCS#11 session failed"));
- sleep(configuration->err_display_time);
- }
release_pkcs11_module(ph);
return pkcs11_pam_fail;
}
@@ -676,31 +797,17 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, cons
} else {
rv = pam_get_pwd(pamh, &password, password_prompt, 0, PAM_AUTHTOK);
}
+
if (rv != PAM_SUCCESS) {
- if (!configuration->quiet) {
- pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2316: password could not be read"));
- sleep(configuration->err_display_time);
- }
+ _get_pwd_error( pamh, configuration, rv );
release_pkcs11_module(ph);
- pam_syslog(pamh, LOG_ERR,
- "pam_get_pwd() failed: %s", pam_strerror(pamh, rv));
return pkcs11_pam_fail;
}
-#ifdef DEBUG_SHOW_PASSWORD
- DBG1("password = [%s]", password);
-#endif
- /* check password length */
- if (!configuration->nullok && strlen(password) == 0) {
+ rv = check_pwd( pamh, configuration, password );
+ if ( rv != 0) {
release_pkcs11_module(ph);
- memset(password, 0, strlen(password));
free(password);
- pam_syslog(pamh, LOG_ERR,
- "password length is zero but the 'nullok' argument was not defined.");
- if (!configuration->quiet) {
- pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2318: Empty smartcard PIN not allowed."));
- sleep(configuration->err_display_time);
- }
return PAM_AUTH_ERR;
}
}
@@ -865,15 +972,9 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, cons
unload_mappers();
/* close pkcs #11 session */
- rv = close_pkcs11_session(ph);
+ rv = pkcs11_close_session( pamh, configuration, ph );
if (rv != 0) {
release_pkcs11_module(ph);
- ERR1("close_pkcs11_session() failed: %s", get_error());
- if (!configuration->quiet) {
- pam_syslog(pamh, LOG_ERR, "close_pkcs11_module() failed: %s", get_error());
- pam_prompt(pamh, PAM_ERROR_MSG , NULL, ("Error 2344: Closing PKCS#11 session failed"));
- sleep(configuration->err_display_time);
- }
return pkcs11_pam_fail;
}
@@ -936,16 +1037,166 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const c
{
char *login_token_name;
- ERR("Warning: Function pam_sm_chauthtok() is not implemented in this module");
- 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."));
+ if (login_token_name) {
+ char *old_pass;
+ char *new_pass;
+ int rv; unsigned int slot_num;
+ struct configuration_st *configuration;
+ pkcs11_handle_t *ph;
+
+ if (flags & PAM_PRELIM_CHECK) {
+ return PAM_SUCCESS;
+ }
+
+ configuration = pk_configure(argc,argv);
+ if (!configuration ) {
+ ERR("Error setting configuration parameters");
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ rv = pkcs11_module_load_init( pamh, configuration, &ph );
+ if ( rv != 0 ) {
+ return rv;
+ }
+
+ rv = pkcs11_find_slot( pamh, configuration, login_token_name, ph, &slot_num );
+ if ( rv != 0 ) {
+ release_pkcs11_module(ph);
+ if ( configuration->card_only ) {
+ return PAM_AUTHINFO_UNAVAIL;
+ } else {
+ return PAM_IGNORE;
+ }
+ }
+
+ rv = pkcs11_open_session( pamh, configuration, ph, slot_num, 1 );
+ if (rv != 0) {
+ release_pkcs11_module(ph);
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ rv = get_slot_protected_authentication_path( ph );
+ if ((-1 == rv) || (0 == rv)) {
+ /* no CKF_PROTECTED_AUTHENTICATION_PATH */
+ char password_prompt[128];
+ char *confirm;
+
+ /* Old PIN */
+ snprintf(password_prompt, sizeof(password_prompt),
+ _("Old %s PIN: "), _(configuration->token_type));
+ rv = pam_get_pwd(pamh, &old_pass, password_prompt,
+ 0, PAM_AUTHTOK);
+
+ if (rv != PAM_SUCCESS) {
+ _get_pwd_error( pamh, configuration, rv );
+ release_pkcs11_module(ph);
+ return PAM_AUTHTOK_RECOVERY_ERR;
+ }
+
+ rv = check_pwd( pamh, configuration, old_pass );
+ if ( rv != 0 ) {
+ release_pkcs11_module(ph);
+ free(old_pass);
+ return PAM_AUTHTOK_RECOVERY_ERR;
+ }
+
+ /* New PIN */
+ snprintf(password_prompt, sizeof(password_prompt),
+ _("New %s PIN: "), _(configuration->token_type));
+ rv = pam_get_pwd(pamh, &new_pass, password_prompt,
+ 0, PAM_AUTHTOK);
+
+ if (rv != PAM_SUCCESS) {
+ _get_pwd_error( pamh, configuration, rv );
+ release_pkcs11_module(ph);
+ return PAM_AUTHTOK_ERR;
+ }
+
+ rv = check_pwd( pamh, configuration, new_pass );
+ if ( rv != 0 ) {
+ release_pkcs11_module(ph);
+ memset( old_pass, 0, strlen(old_pass) );
+ free( old_pass );
+ free( new_pass );
+ return PAM_AUTHTOK_ERR;
+ }
+
+ /* Confirm new PIN */
+ snprintf(password_prompt, sizeof(password_prompt),
+ _("Confirm new PIN: "));
+ rv = pam_get_pwd(pamh, &confirm, password_prompt,
+ 0, PAM_AUTHTOK);
+
+ if (rv != PAM_SUCCESS) {
+ _get_pwd_error( pamh, configuration, rv );
+ release_pkcs11_module(ph);
+ memset( old_pass, 0, strlen(old_pass) );
+ free( old_pass );
+ memset( new_pass, 0, strlen(new_pass) );
+ free( new_pass );
+ return PAM_AUTHTOK_ERR;
+ }
+
+ if ( strcmp(new_pass, confirm) != 0 ) {
+ ERR("Confirm PIN mismatch");
+ if (!configuration->quiet) {
+ pam_syslog(pamh, LOG_ERR, "Confirm PIN mismatch");
+ pam_prompt(pamh, PAM_ERROR_MSG , NULL,
+ _("Confirm PIN mismatch"));
+ sleep(configuration->err_display_time);
+ }
+ release_pkcs11_module(ph);
+ memset( old_pass, 0, strlen(old_pass) );
+ free( old_pass );
+ memset( new_pass, 0, strlen(new_pass) );
+ free( new_pass );
+ memset( confirm, 0, strlen(confirm) );
+ free( confirm );
+ return PAM_AUTHTOK_ERR;
+ } else {
+ memset( confirm, 0, strlen(confirm) );
+ free( confirm );
+ }
+ } else {
+ pam_prompt(pamh, PAM_TEXT_INFO, NULL,
+ _("Now use the pinpad to change your %s PIN"),
+ _(configuration->token_type));
+ old_pass = NULL;
+ new_pass = NULL;
+ }
+
+ rv = pkcs11_login( ph, old_pass );
+ if ( rv == 0 ) {
+ rv = pkcs11_setpin( ph, old_pass, new_pass );
+ }
+ pkcs11_close_session( pamh, configuration, ph );
+ release_pkcs11_module( ph );
+
+ if ( old_pass ) {
+ memset( old_pass, 0, strlen(old_pass) );
+ free( old_pass );
+ }
+ if ( new_pass) {
+ memset( new_pass, 0, strlen(new_pass) );
+ free( new_pass );
+ }
+
+ if ( rv == 0 ) {
+ return PAM_SUCCESS;
+ } else {
+ ERR("C_SetPIN error");
+ if (!configuration->quiet) {
+ pam_syslog(pamh, LOG_ERR, "C_SetPIN error");
+ pam_prompt(pamh, PAM_ERROR_MSG , NULL,
+ _("Error: Unable to set new PIN"));
+ sleep(configuration->err_display_time);
+ }
+ return PAM_AUTHTOK_ERR;
+ }
+ } else {
+ return PAM_IGNORE;
}
- return PAM_SERVICE_ERR;
}
#ifdef PAM_STATIC
diff --git a/src/tools/pkcs11_inspect.c b/src/tools/pkcs11_inspect.c
index 6aac407..3cc0021 100644
--- a/src/tools/pkcs11_inspect.c
+++ b/src/tools/pkcs11_inspect.c
@@ -96,7 +96,7 @@ int main(int argc, const char **argv) {
return 1;
}
- rv = open_pkcs11_session(ph, slot_num);
+ rv = open_pkcs11_session(ph, slot_num, 0);
if (rv != 0) {
release_pkcs11_module(ph);
ERR1("open_pkcs11_session() failed: %s", get_error());
diff --git a/src/tools/pkcs11_listcerts.c b/src/tools/pkcs11_listcerts.c
index 726addf..e8b693a 100644
--- a/src/tools/pkcs11_listcerts.c
+++ b/src/tools/pkcs11_listcerts.c
@@ -95,7 +95,7 @@ int main(int argc, const char **argv) {
return 1;
}
- rv = open_pkcs11_session(ph, slot_num);
+ rv = open_pkcs11_session(ph, slot_num, 0);
if (rv != 0) {
release_pkcs11_module(ph);
DBG1("open_pkcs11_session() failed: %s", get_error());
diff --git a/src/tools/pklogin_finder.c b/src/tools/pklogin_finder.c
index 9ef04b9..e03b131 100644
--- a/src/tools/pklogin_finder.c
+++ b/src/tools/pklogin_finder.c
@@ -95,7 +95,7 @@ int main(int argc, const char **argv) {
DBG("no token available");
return 1;
}
- rv = open_pkcs11_session(ph, slot_num);
+ rv = open_pkcs11_session(ph, slot_num, 0);
if (rv != 0) {
release_pkcs11_module(ph);
DBG1("open_pkcs11_session() failed: %s", get_error());