summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Fiveash <will.fiveash@oracle.com>2010-07-28 17:47:31 -0500
committerWill Fiveash <will.fiveash@oracle.com>2010-07-28 17:47:31 -0500
commit488060a6285c53d78d4e5360e7db00d6d544d960 (patch)
tree8f11bd03cfd23c63d3c454da46c69335bac6b854
parent700f2bdf63820e30238ab3d63d8f6b61d731ff54 (diff)
downloadillumos-gate-488060a6285c53d78d4e5360e7db00d6d544d960.tar.gz
6929628 pkinit preauth plugin needs interface so caller can provide PIN
-rw-r--r--exception_lists/copyright3
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h5
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c9
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c81
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h1
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c14
-rw-r--r--usr/src/lib/pam_modules/krb5/krb5_authenticate.c74
7 files changed, 129 insertions, 58 deletions
diff --git a/exception_lists/copyright b/exception_lists/copyright
index d6ef84ddbd..1014305753 100644
--- a/exception_lists/copyright
+++ b/exception_lists/copyright
@@ -304,14 +304,11 @@ usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c
usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.h
usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.c
usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.h
-usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c
usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto.h
-usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c
usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_lib.c
usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_matching.c
usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_profile.c
usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_srv.c
-usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h
usr/src/lib/krb5/ss/copyright.h
usr/src/lib/krb5/ss/mit-sipb-copyright.h
usr/src/lib/krb5/ss/options.c
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h
index 9ae77a2a5f..3614c618bf 100644
--- a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h
@@ -28,6 +28,10 @@
* SUCH DAMAGES.
*/
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
#ifndef _PKINIT_H
#define _PKINIT_H
@@ -196,6 +200,7 @@ typedef struct _pkinit_identity_opts {
char *token_label;
char *cert_id_string;
char *cert_label;
+ char *PIN; /* Solaris Kerberos */
#endif
} pkinit_identity_opts;
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c
index 296d051708..c06a66dc8c 100644
--- a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c
@@ -28,6 +28,10 @@
* SUCH DAMAGES.
*/
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
@@ -1472,6 +1476,11 @@ handle_gic_opt(krb5_context context,
pkiDebug("Setting flag to use RSA_PROTOCOL\n");
plgctx->opts->dh_or_rsa = RSA_PROTOCOL;
}
+ } else if (strcmp(attr, "PIN") == 0) {
+ /* Solaris Kerberos: handle our PIN attr */
+ plgctx->idopts->PIN = strdup(value);
+ if (plgctx->idopts->PIN == NULL)
+ return ENOMEM;
}
return 0;
}
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c
index b22675eaab..d73efc201a 100644
--- a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -769,6 +769,7 @@ pkinit_init_pkcs11(pkinit_identity_crypto_context ctx)
ctx->slotid = PK_NOSLOT;
ctx->token_label = NULL;
ctx->cert_label = NULL;
+ ctx->PIN = NULL;
ctx->session = CK_INVALID_HANDLE;
ctx->p11 = NULL;
ctx->p11flags = 0; /* Solaris Kerberos */
@@ -811,6 +812,10 @@ pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)
free(ctx->cert_id);
if (ctx->cert_label != NULL)
free(ctx->cert_label);
+ if (ctx->PIN != NULL) {
+ (void) memset(ctx->PIN, 0, strlen(ctx->PIN));
+ free(ctx->PIN);
+ }
#endif
}
@@ -3363,6 +3368,10 @@ pkinit_C_UnloadModule(void *handle)
return CKR_OK;
}
+/*
+ * Solaris Kerberos: this function was changed to support a PIN being passed
+ * in. If that is the case the user will not be prompted for their PIN.
+ */
static krb5_error_code
pkinit_login(krb5_context context,
pkinit_identity_crypto_context id_cryptoctx,
@@ -3378,6 +3387,15 @@ pkinit_login(krb5_context context,
if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
rdat.data = NULL;
rdat.length = 0;
+ } else if (id_cryptoctx->PIN != NULL) {
+ if ((rdat.data = strdup(id_cryptoctx->PIN)) == NULL)
+ return (ENOMEM);
+ /*
+ * Don't include NULL string terminator in length calculation as this
+ * PIN is passed to the C_Login function and only the text chars should
+ * be considered to be the PIN.
+ */
+ rdat.length = strlen(id_cryptoctx->PIN);
} else {
unsigned char *lastnonwspc, *iterp; /* Solaris Kerberos - trim token label */
int count;
@@ -3409,8 +3427,12 @@ pkinit_login(krb5_context context,
(void) strlcat(prompt, gettext(" (Warning: PIN final try)"), prompt_len);
else if (tip->flags & CKF_USER_PIN_COUNT_LOW)
(void) strlcat(prompt, gettext(" (Warning: PIN count low)"), prompt_len);
- rdat.data = (char *)malloc(tip->ulMaxPinLen + 2);
+ rdat.data = malloc(tip->ulMaxPinLen + 2);
rdat.length = tip->ulMaxPinLen + 1;
+ /*
+ * Note that the prompter function will set rdat.length such that the
+ * NULL terminator is not included
+ */
kprompt.prompt = prompt;
kprompt.hidden = 1;
@@ -3421,7 +3443,7 @@ pkinit_login(krb5_context context,
k5int_set_prompt_types(context, &prompt_type);
r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
NULL, NULL, 1, &kprompt);
- k5int_set_prompt_types(context, 0);
+ k5int_set_prompt_types(context, NULL);
free(prompt);
}
@@ -3441,8 +3463,10 @@ pkinit_login(krb5_context context,
id_cryptoctx->p11flags |= C_LOGIN_DONE;
}
}
- if (rdat.data)
+ if (rdat.data) {
+ (void) memset(rdat.data, 0, rdat.length);
free(rdat.data);
+ }
return r;
}
@@ -4105,27 +4129,33 @@ pkinit_get_certs_pkcs12(krb5_context context,
pkiDebug("Initial PKCS12_parse with no password failed\n");
- (void) memset(prompt_reply, '\0', sizeof(prompt_reply));
- rdat.data = prompt_reply;
- rdat.length = sizeof(prompt_reply);
-
- r = snprintf(prompt_string, sizeof(prompt_string), "%s %s",
- prompt_prefix, idopts->cert_filename);
- if (r >= sizeof(prompt_string)) {
- pkiDebug("Prompt string, '%s %s', is too long!\n",
- prompt_prefix, idopts->cert_filename);
- goto cleanup;
+ if (id_cryptoctx->PIN != NULL) {
+ /* Solaris Kerberos: use PIN if set */
+ rdat.data = id_cryptoctx->PIN;
+ /* note rdat.length isn't needed in this case */
+ } else {
+ (void) memset(prompt_reply, '\0', sizeof(prompt_reply));
+ rdat.data = prompt_reply;
+ rdat.length = sizeof(prompt_reply);
+
+ r = snprintf(prompt_string, sizeof(prompt_string), "%s %s",
+ prompt_prefix, idopts->cert_filename);
+ if (r >= sizeof(prompt_string)) {
+ pkiDebug("Prompt string, '%s %s', is too long!\n",
+ prompt_prefix, idopts->cert_filename);
+ goto cleanup;
+ }
+ kprompt.prompt = prompt_string;
+ kprompt.hidden = 1;
+ kprompt.reply = &rdat;
+ prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
+
+ /* PROMPTER_INVOCATION */
+ k5int_set_prompt_types(context, &prompt_type);
+ r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
+ NULL, NULL, 1, &kprompt);
+ k5int_set_prompt_types(context, NULL);
}
- kprompt.prompt = prompt_string;
- kprompt.hidden = 1;
- kprompt.reply = &rdat;
- prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
-
- /* PROMPTER_INVOCATION */
- k5int_set_prompt_types(context, &prompt_type);
- r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
- NULL, NULL, 1, &kprompt);
- k5int_set_prompt_types(context, 0);
ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL);
if (ret == 0) {
@@ -4389,6 +4419,11 @@ pkinit_get_certs_pkcs11(krb5_context context,
if (id_cryptoctx->cert_label == NULL)
return ENOMEM;
}
+ if (idopts->PIN != NULL) {
+ id_cryptoctx->PIN = strdup(idopts->PIN);
+ if (id_cryptoctx->PIN == NULL)
+ return ENOMEM;
+ }
/* Convert the ascii cert_id string into a binary blob */
/*
* Solaris Kerberos:
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h
index 289c3d060a..1eb60263ec 100644
--- a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h
@@ -80,6 +80,7 @@ struct _pkinit_identity_crypto_context {
CK_SLOT_ID slotid;
char *token_label;
char *cert_label;
+ char *PIN; /* Solaris Kerberos: */
/* These are crypto-specific */
void *p11_module;
CK_SESSION_HANDLE session;
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c
index e4a6470523..7656b8eb4e 100644
--- a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c
@@ -28,6 +28,10 @@
* SUCH DAMAGES.
*/
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
#include <errno.h>
#include <string.h>
#include <stdio.h>
@@ -136,6 +140,7 @@ pkinit_init_identity_opts(pkinit_identity_opts **idopts)
opts->token_label = NULL;
opts->cert_id_string = NULL;
opts->cert_label = NULL;
+ opts->PIN = NULL;
#endif
*idopts = opts;
@@ -219,6 +224,11 @@ pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
if (newopts->cert_label == NULL)
goto cleanup;
}
+ if (src_opts->PIN != NULL) {
+ newopts->PIN = strdup(src_opts->PIN);
+ if (newopts->PIN == NULL)
+ goto cleanup;
+ }
#endif
@@ -255,6 +265,10 @@ pkinit_fini_identity_opts(pkinit_identity_opts *idopts)
free(idopts->cert_id_string);
if (idopts->cert_label != NULL)
free(idopts->cert_label);
+ if (idopts->PIN != NULL) {
+ (void) memset(idopts->PIN, 0, strlen(idopts->PIN));
+ free(idopts->PIN);
+ }
#endif
free(idopts);
}
diff --git a/usr/src/lib/pam_modules/krb5/krb5_authenticate.c b/usr/src/lib/pam_modules/krb5/krb5_authenticate.c
index ce56893697..28194f1873 100644
--- a/usr/src/lib/pam_modules/krb5/krb5_authenticate.c
+++ b/usr/src/lib/pam_modules/krb5/krb5_authenticate.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <security/pam_appl.h>
@@ -499,7 +498,7 @@ attempt_krb5_auth(
KRB5_TGS_NAME_SIZE,
KRB5_TGS_NAME
};
- krb5_get_init_creds_opt opts;
+ krb5_get_init_creds_opt *opts = NULL;
krb5_kdc_rep *as_reply = NULL;
/*
* "result" should not be assigned PAM_SUCCESS unless
@@ -515,8 +514,6 @@ attempt_krb5_auth(
"PAM-KRB5 (auth): attempt_krb5_auth: start: user='%s'",
user ? user : "<null>");
- krb5_get_init_creds_opt_init(&opts);
-
/* need to free context with krb5_free_context */
if (code = krb5_init_secure_context(&kmd->kcontext)) {
__pam_log(LOG_AUTH | LOG_ERR,
@@ -632,35 +629,44 @@ attempt_krb5_auth(
} else
my_creds->times.renew_till = 0;
- krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime);
+ code = krb5_get_init_creds_opt_alloc(kmd->kcontext, &opts);
+ if (code != 0) {
+ __pam_log(LOG_AUTH | LOG_ERR,
+ "Error allocating gic opts: %s",
+ error_message(code));
+ result = PAM_SYSTEM_ERR;
+ goto out;
+ }
+
+ krb5_get_init_creds_opt_set_tkt_life(opts, lifetime);
if (proxiable_flag) { /* Set in config file */
if (kmd->debug)
__pam_log(LOG_AUTH | LOG_DEBUG,
"PAM-KRB5 (auth): Proxiable tickets "
"requested");
- krb5_get_init_creds_opt_set_proxiable(&opts, TRUE);
+ krb5_get_init_creds_opt_set_proxiable(opts, TRUE);
}
if (forwardable_flag) {
if (kmd->debug)
__pam_log(LOG_AUTH | LOG_DEBUG,
"PAM-KRB5 (auth): Forwardable tickets "
"requested");
- krb5_get_init_creds_opt_set_forwardable(&opts, TRUE);
+ krb5_get_init_creds_opt_set_forwardable(opts, TRUE);
}
if (renewable_flag) {
if (kmd->debug)
__pam_log(LOG_AUTH | LOG_DEBUG,
"PAM-KRB5 (auth): Renewable tickets "
"requested");
- krb5_get_init_creds_opt_set_renew_life(&opts, rlife);
+ krb5_get_init_creds_opt_set_renew_life(opts, rlife);
}
if (no_address_flag) {
if (kmd->debug)
__pam_log(LOG_AUTH | LOG_DEBUG,
"PAM-KRB5 (auth): Addressless tickets "
"requested");
- krb5_get_init_creds_opt_set_address_list(&opts, NULL);
+ krb5_get_init_creds_opt_set_address_list(opts, NULL);
}
/*
@@ -686,28 +692,30 @@ attempt_krb5_auth(
KRB5_PADATA_PK_AS_REQ,
KRB5_PADATA_PK_AS_REQ_OLD
};
- krb5_get_init_creds_opt_set_preauth_list(&opts, pk_pa_list, 2);
+ krb5_get_init_creds_opt_set_preauth_list(opts, pk_pa_list, 2);
- if (*krb5_pass == NULL) {
- /* let preauth plugin prompt for PIN */
- code = __krb5_get_init_creds_password(kmd->kcontext,
- my_creds,
- me,
- NULL, /* clear text passwd */
- pam_krb5_prompter, /* prompter */
- pamh, /* prompter data */
- 0, /* start time */
- NULL, /* defaults to krbtgt@REALM */
- &opts,
- &as_reply);
+ if (*krb5_pass == NULL || strlen(*krb5_pass) != 0) {
+ if (*krb5_pass != NULL) {
+ /* treat the krb5_pass as a PIN */
+ code = krb5_get_init_creds_opt_set_pa(
+ kmd->kcontext, opts, "PIN", *krb5_pass);
+ }
+
+ if (!code) {
+ code = __krb5_get_init_creds_password(
+ kmd->kcontext,
+ my_creds,
+ me,
+ NULL, /* clear text passwd */
+ pam_krb5_prompter, /* prompter */
+ pamh, /* prompter data */
+ 0, /* start time */
+ NULL, /* defaults to krbtgt@REALM */
+ opts,
+ &as_reply);
+ }
} else {
- /*
- * krb pkinit does not support setting the PIN so we
- * punt on trying to use krb5_pass as the PIN for now.
- * Note that once this is supported by pkinit the code
- * should make sure krb5_pass isn't empty and if it is
- * then that's an error.
- */
+ /* invalid PIN */
code = KRB5KRB_AP_ERR_BAD_INTEGRITY;
}
} else {
@@ -725,7 +733,7 @@ attempt_krb5_auth(
KRB5_PADATA_ENC_TIMESTAMP
};
- krb5_get_init_creds_opt_set_preauth_list(&opts,
+ krb5_get_init_creds_opt_set_preauth_list(opts,
pk_pa_list, 1);
/*
@@ -743,7 +751,7 @@ attempt_krb5_auth(
NULL, /* data */
0, /* start time */
NULL, /* defaults to krbtgt@REALM */
- &opts,
+ opts,
&as_reply);
}
}
@@ -951,6 +959,8 @@ out:
krb5_free_context(kmd->kcontext);
kmd->kcontext = NULL;
}
+ if (opts)
+ krb5_get_init_creds_opt_free(kmd->kcontext, opts);
if (kmd->debug)
__pam_log(LOG_AUTH | LOG_DEBUG,