summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsemery <none@none>2008-04-25 21:33:18 -0700
committersemery <none@none>2008-04-25 21:33:18 -0700
commit47fc6f3c5b3c55e162497f2704e8a30366037e6d (patch)
tree5279f86bd7b1d7ea30f1a822b2656487326e8722
parentc6c65e5445ba6bc005f3da488bddd36494d26e65 (diff)
downloadillumos-joyent-47fc6f3c5b3c55e162497f2704e8a30366037e6d.tar.gz
6455225 pam_krb5 should overwrite ccache with new credentials when handling pam_setcred(PAM_REFRESH_CRED)
6642279 kdcmgr has to run twice if the pw file option is used and an existing db is present
-rwxr-xr-xusr/src/cmd/krb5/kadmin/kdcmgr/kdcmgr.sh7
-rw-r--r--usr/src/lib/pam_modules/krb5/krb5_setcred.c208
2 files changed, 49 insertions, 166 deletions
diff --git a/usr/src/cmd/krb5/kadmin/kdcmgr/kdcmgr.sh b/usr/src/cmd/krb5/kadmin/kdcmgr/kdcmgr.sh
index 6c5b5b1374..9e5260ba04 100755
--- a/usr/src/cmd/krb5/kadmin/kdcmgr/kdcmgr.sh
+++ b/usr/src/cmd/krb5/kadmin/kdcmgr/kdcmgr.sh
@@ -19,7 +19,7 @@
#
# CDDL HEADER END
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# ident "%Z%%M% %I% %E% SMI"
@@ -542,8 +542,6 @@ function destroy_kdc {
printf "$(gettext "yes")\n" | kdb5_util destroy > /dev/null 2>&1
rm -f $KRB5KT $KADM5KT
-
- cleanup 0
}
function kadm5_acl_configed {
@@ -693,7 +691,8 @@ case "$*" in
"create slave") slave=yes;;
destroy) d_option=yes
kill_daemons
- destroy_kdc;;
+ destroy_kdc
+ cleanup 0;;
status) status_kdc;;
*) usage;;
esac
diff --git a/usr/src/lib/pam_modules/krb5/krb5_setcred.c b/usr/src/lib/pam_modules/krb5/krb5_setcred.c
index d292744a4e..b13f8883d6 100644
--- a/usr/src/lib/pam_modules/krb5/krb5_setcred.c
+++ b/usr/src/lib/pam_modules/krb5/krb5_setcred.c
@@ -55,8 +55,6 @@ static int attempt_refresh_cred(krb5_module_data_t *, char *, int);
static int attempt_delete_initcred(krb5_module_data_t *);
static krb5_error_code krb5_renew_tgt(krb5_module_data_t *, krb5_principal,
krb5_principal, int);
-static krb5_boolean creds_match(krb5_context, const krb5_creds *,
- const krb5_creds *);
extern uint_t kwarn_add_warning(char *, int);
extern uint_t kwarn_del_warning(char *);
@@ -76,7 +74,6 @@ pam_sm_setcred(
int debug = 0;
krb5_module_data_t *kmd = NULL;
char *user = NULL;
- int result;
krb5_repository_data_t *krb5_data = NULL;
pam_repository_t *rep_data = NULL;
@@ -127,10 +124,16 @@ pam_sm_setcred(
kmd = calloc(1, sizeof (krb5_module_data_t));
- if (kmd == NULL) {
- result = PAM_BUF_ERR;
- return (result);
- }
+ if (kmd == NULL)
+ return (PAM_BUF_ERR);
+
+
+ /*
+ * Need to initialize auth_status here to
+ * PAM_AUTHINFO_UNAVAIL else there is a false positive
+ * of PAM_SUCCESS.
+ */
+ kmd->auth_status = PAM_AUTHINFO_UNAVAIL;
if ((err = pam_set_data(pamh, KRB5_DATA,
kmd, &krb5_cleanup)) != PAM_SUCCESS) {
@@ -155,7 +158,7 @@ pam_sm_setcred(
"PAM-KRB5 (setcred): kmd structure"
" gotten but is NULL for user %s", user);
}
- err = PAM_CRED_UNAVAIL;
+ err = PAM_SYSTEM_ERR;
goto out;
}
@@ -295,15 +298,6 @@ attempt_refresh_cred(
KRB5_TGS_NAME
};
- /* User must have passed pam_authenticate() */
- if (kmd->auth_status != PAM_SUCCESS) {
- if (kmd->debug)
- __pam_log(LOG_AUTH | LOG_DEBUG,
- "PAM-KRB5 (setcred): unable to "
- "setcreds, not authenticated!");
- return (PAM_CRED_UNAVAIL);
- }
-
/* Create a new context here. */
if (krb5_init_context(&kmd->kcontext) != 0) {
if (kmd->debug)
@@ -355,10 +349,15 @@ attempt_refresh_cred(
/*
* This code will update the credential matching "server" in the user's
* credential cache. The flag may be set to one of:
- * PAM_ESTABLISH_CRED - Create a new cred cache if one doesnt exist,
- * else refresh the existing one.
- * PAM_REINITIALIZE_CRED - destroy current cred cache and create a new one
- * PAM_REFRESH_CRED - update the existing cred cache (default action)
+ * PAM_ESTABLISH_CRED - If we have new credentials then create a new cred cache
+ * with these credentials else return failure.
+ * PAM_REINITIALIZE_CRED - Destroy current cred cache and create a new one.
+ * PAM_REFRESH_CRED - If we have new credentials then create a new cred cache
+ * with these credentials else attempt to renew the credentials.
+ *
+ * Note for the PAM_ESTABLISH_CRED and PAM_REFRESH_CRED flags that if a new
+ * credential does exist from the previous auth pass then this will overwrite
+ * any existing credentials in the credential cache.
*/
static krb5_error_code
krb5_renew_tgt(
@@ -371,12 +370,6 @@ krb5_renew_tgt(
krb5_creds creds;
krb5_creds *renewed_cred = NULL;
char *client_name = NULL;
- typedef struct _cred_node {
- krb5_creds *creds;
- struct _cred_node *next;
- } cred_node;
- cred_node *cred_list_head = NULL;
- cred_node *fetched = NULL;
#define my_creds (kmd->initcreds)
@@ -468,147 +461,52 @@ krb5_renew_tgt(
}
} else {
/*
- * Creds already exist, update them if possible.
+ * Default credentials already exist, update them if possible.
* We got here either with the ESTABLISH or REFRESH flag.
*
- * The credential cache does exist, and we are going to
- * read in each cred, looking for our own. When we find
- * a matching credential, we will update it, and store it.
- * Any nonmatching credentials are stored as is.
- *
* Rules:
- * TGT must exist in cache to get to this point.
- * if flag == ESTABLISH
- * refresh it if possible, else overwrite
- * with new TGT, other tickets in cache remain
- * unchanged.
- * else if flag == REFRESH
- * refresh it if possible, else return error.
- * - Will not work if "R" flag is not set in
- * original cred, we dont want to 2nd guess the
- * intention of the person who created the
- * existing TGT.
+ * - If the prior auth pass was successful then store the new
+ * credentials in the cache, regardless of which flag.
*
+ * - Else if REFRESH flag is used and there are no new
+ * credentials then attempt to refresh the existing credentials.
+ *
+ * - Note, refresh will not work if "R" flag is not set in
+ * original credential. We don't want to 2nd guess the
+ * intention of the person who created the existing credential.
*/
- krb5_cc_cursor cursor;
- krb5_creds nextcred;
- boolean_t found = 0;
-
- if ((retval = krb5_cc_start_seq_get(kmd->kcontext,
- kmd->ccache, &cursor)) != 0)
- goto cleanup_creds;
-
- while ((krb5_cc_next_cred(kmd->kcontext, kmd->ccache,
- &cursor, &nextcred) == 0)) {
- /* if two creds match, we just update the first */
- if ((!found) && (creds_match(kmd->kcontext,
- &nextcred, &creds))) {
- /*
- * Mark it as found, don't store it
- * in the list or else it will be
- * stored twice later.
- */
- found = 1;
- } else {
- /*
- * Add a new node to the list
- * of creds that must be replaced
- * in the cache later.
- */
- cred_node *newnode = (cred_node *)malloc(
- sizeof (cred_node));
- if (newnode == NULL) {
- retval = ENOMEM;
- goto cleanup_creds;
- }
- newnode->creds = NULL;
- newnode->next = NULL;
-
- if (cred_list_head == NULL) {
- cred_list_head = newnode;
- fetched = cred_list_head;
- } else {
- fetched->next = newnode;
- fetched = fetched->next;
- }
- retval = krb5_copy_creds(kmd->kcontext,
- &nextcred, &fetched->creds);
- if (retval)
- goto cleanup_creds;
- }
- }
-
- if ((retval = krb5_cc_end_seq_get(kmd->kcontext,
- kmd->ccache, &cursor)) != 0)
- goto cleanup_creds;
-
- /*
- * If we found a matching cred, renew it.
- * This destroys the credential cache, if and only
- * if it passes.
- */
- if (found &&
- (retval = krb5_get_credentials_renew(kmd->kcontext,
- 0, kmd->ccache, &creds, &renewed_cred))) {
- if (kmd->debug)
- __pam_log(LOG_AUTH | LOG_DEBUG,
- "PAM-KRB5 (setcred): krb5_get_credentials"
- "_renew(update) failed: %s",
- error_message((errcode_t)retval));
+ if ((kmd->auth_status != PAM_SUCCESS) &&
+ (flag & PAM_REFRESH_CRED)) {
/*
* If we only wanted to refresh the creds but failed
* due to expiration, lack of "R" flag, or other
- * problems, return an error. If we were trying to
- * establish new creds, add them to the cache.
+ * problems, return an error.
*/
- if ((retval = krb5_cc_initialize(kmd->kcontext,
- kmd->ccache, me)) != 0) {
- goto cleanup_creds;
- } else if ((retval = krb5_cc_store_cred(kmd->kcontext,
- kmd->ccache, &my_creds)) != 0) {
+ if (retval = krb5_get_credentials_renew(kmd->kcontext,
+ 0, kmd->ccache, &creds, &renewed_cred)) {
+ if (kmd->debug)
+ __pam_log(LOG_AUTH | LOG_DEBUG,
+ "PAM-KRB5 (setcred): "
+ "krb5_get_credentials"
+ "_renew(update) failed: %s",
+ error_message((errcode_t)retval));
goto cleanup_creds;
}
- }
- /*
- * If no matching creds were found, we must
- * initialize the cache before we can store stuff
- * in it.
- */
- if (!found) {
+ } else {
+ /*
+ * If we have new creds, add them to the cache.
+ */
if ((retval = krb5_cc_initialize(kmd->kcontext,
kmd->ccache, me)) != 0) {
goto cleanup_creds;
- }
- }
-
- /* now store all the other tickets */
- fetched = cred_list_head;
- while (fetched != NULL) {
- retval = krb5_cc_store_cred(kmd->kcontext,
- kmd->ccache, fetched->creds);
- fetched = fetched->next;
- if (retval) {
- if (kmd->debug)
- __pam_log(LOG_AUTH | LOG_DEBUG,
- "PAM-KRB5(setcred): "
- "krb5_cc_store_cred() "
- "failed: %s",
- error_message((errcode_t)retval));
+ } else if ((retval = krb5_cc_store_cred(kmd->kcontext,
+ kmd->ccache, &my_creds)) != 0) {
goto cleanup_creds;
}
}
}
cleanup_creds:
- /* Cleanup the list of creds read from the cache if necessary */
- fetched = cred_list_head;
- while (fetched != NULL) {
- cred_node *old = fetched;
- /* Free the contents and the cred structure itself */
- krb5_free_creds(kmd->kcontext, fetched->creds);
- fetched = fetched->next;
- free(old);
- }
if ((retval == 0) && (client_name != NULL)) {
/*
@@ -695,20 +593,6 @@ error:
return (retval);
}
-static krb5_boolean
-creds_match(krb5_context ctx, const krb5_creds *mcreds,
- const krb5_creds *creds)
-{
- char *s1, *s2, *c1, *c2;
- krb5_unparse_name(ctx, mcreds->client, &c1);
- krb5_unparse_name(ctx, mcreds->server, &s1);
- krb5_unparse_name(ctx, creds->client, &c2);
- krb5_unparse_name(ctx, creds->server, &s2);
-
- return (krb5_principal_compare(ctx, mcreds->client, creds->client) &&
- krb5_principal_compare(ctx, mcreds->server, creds->server));
-}
-
/*
* Delete the user's credentials for this session
*/