diff options
| author | semery <none@none> | 2007-02-13 10:15:31 -0800 |
|---|---|---|
| committer | semery <none@none> | 2007-02-13 10:15:31 -0800 |
| commit | 3125ebfc35130d243e775dc38a6a59be4df0b137 (patch) | |
| tree | 35a9f1bc94fa3d99936bd154bc74a408ae96d1ab /usr/src/lib/pam_modules/krb5 | |
| parent | fa871852ed0075b7564289cb07481ed343bb162f (diff) | |
| download | illumos-joyent-3125ebfc35130d243e775dc38a6a59be4df0b137.tar.gz | |
6394510 error table is out of whack
6497698 krb5kdc(1) should also provide password expiration information
6497703 pam_krb5(5) should interpret the key expiration field to display expiration warning information
6514446 pam_dhkeys prompts for secure RPC password when neither LOCAL or DES credentials exist
6515558 Pre-s10 client's keytab file are generated incorrectly when auth princ == target princ
6523684 Memory rcache function doesn't acquire the right locks
Diffstat (limited to 'usr/src/lib/pam_modules/krb5')
| -rw-r--r-- | usr/src/lib/pam_modules/krb5/krb5_acct_mgmt.c | 118 | ||||
| -rw-r--r-- | usr/src/lib/pam_modules/krb5/krb5_authenticate.c | 23 | ||||
| -rw-r--r-- | usr/src/lib/pam_modules/krb5/utils.h | 1 |
3 files changed, 94 insertions, 48 deletions
diff --git a/usr/src/lib/pam_modules/krb5/krb5_acct_mgmt.c b/usr/src/lib/pam_modules/krb5/krb5_acct_mgmt.c index d838613187..b2fc5168c2 100644 --- a/usr/src/lib/pam_modules/krb5/krb5_acct_mgmt.c +++ b/usr/src/lib/pam_modules/krb5/krb5_acct_mgmt.c @@ -47,16 +47,17 @@ #define KRB5_AUTOMIGRATE_DATA "SUNW-KRB5-AUTOMIGRATE-DATA" +#define min(a, b) ((a) < (b) ? (a) : (b)) + /* * pam_sm_acct_mgmt main account managment routine. */ static int fetch_princ_entry( + krb5_module_data_t *kmd, char *princ_str, - char *password, kadm5_principal_ent_rec *prent, /* out */ - krb5_timestamp *now, /* out */ int debug) { @@ -64,17 +65,16 @@ fetch_princ_entry( krb5_principal princ = 0; char admin_realm[1024]; char kprinc[2*MAXHOSTNAMELEN]; - char *cpw_service; + char *cpw_service, *password; void *server_handle; krb5_context context; kadm5_config_params params; - if (code = krb5_init_context(&context)) { - return (PAM_SYSTEM_ERR); - } + password = kmd->password; + context = kmd->kcontext; - if ((code = get_kmd_kuser(context, (const char *)princ_str, kprinc, - 2*MAXHOSTNAMELEN)) != 0) { + if ((code = get_kmd_kuser(context, (const char *)princ_str, + kprinc, 2*MAXHOSTNAMELEN)) != 0) { return (code); } @@ -148,16 +148,6 @@ fetch_princ_entry( PAM_USER_UNKNOWN : PAM_SYSTEM_ERR); } - if (code = krb5_timeofday(context, now)) { - (void) kadm5_destroy(server_handle); - krb5_free_principal(context, princ); - krb5_free_context(context); - __pam_log(LOG_AUTH | LOG_ERR, - "PAM-KRB5 (acct): krb5_timeofday fail: code=%d", - code); - return (PAM_SYSTEM_ERR); - } - (void) kadm5_destroy(server_handle); krb5_free_principal(context, princ); krb5_free_context(context); @@ -168,76 +158,112 @@ fetch_princ_entry( /* * exp_warn * - * warn the user if her pw is set to expire + * Warn the user if their pw is set to expire. * - * We use the kadm protocol and chpw svc to fetch the user's KDC db - * entry. The user's default perms on the KDC db should allow this. - * Note since the SEAM kadm API uses rpcsec_gss (which is diff from - * what MS and MIT 1.2 and before uses), this probably only works - * with a SEAM KDC. + * We first check to see if the KDC had set any account or password + * expiration information in the key expiration field. If this was + * not set then we must assume that the KDC could be broken and revert + * to fetching pw/account expiration information from kadm. We can not + * determine the difference between broken KDCs that do not send key-exp + * vs. principals that do not have an expiration policy. The up-shot + * is that pam_krb5 will probably not be stacked for acct mgmt if the + * environment does not have an exp policy, avoiding the second exchange + * using the kadm protocol. */ - static int exp_warn( pam_handle_t *pamh, char *user, - char *password, + krb5_module_data_t *kmd, int debug) { int err; kadm5_principal_ent_rec prent; - krb5_timestamp now, days; - char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE]; + krb5_timestamp now, days, expiration; + char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE], *password; + krb5_error_code code; if (debug) __pam_log(LOG_AUTH | LOG_DEBUG, "PAM-KRB5 (acct): exp_warn start: user = '%s'", user ? user : "<null>"); + password = kmd->password; + if (!pamh || !user || !password) { err = PAM_SERVICE_ERR; goto out; } - (void) memset(&prent, 0, sizeof (prent)); - if ((err = fetch_princ_entry(user, password, &prent, - &now, debug)) != PAM_SUCCESS) { + if (code = krb5_init_context(&kmd->kcontext)) { + err = PAM_SYSTEM_ERR; if (debug) - __pam_log(LOG_AUTH | LOG_DEBUG, - "PAM-KRB5 (acct): exp_warn: fetch_pr failed %d", - err); + __pam_log(LOG_AUTH | LOG_ERR, "PAM-KRB5 (acct): " + "krb5_init_context failed: code=%d", + code); goto out; } + if (code = krb5_timeofday(kmd->kcontext, &now)) { + err = PAM_SYSTEM_ERR; + if (debug) + __pam_log(LOG_AUTH | LOG_ERR, + "PAM-KRB5 (acct): krb5_timeofday failed: code=%d", + code); + goto out; + } + + if (kmd->expiration != 0) { + expiration = kmd->expiration; + } else { + (void) memset(&prent, 0, sizeof (prent)); + if ((err = fetch_princ_entry(kmd, user, &prent, debug)) + != PAM_SUCCESS) { + if (debug) + __pam_log(LOG_AUTH | LOG_DEBUG, + "PAM-KRB5 (acct): exp_warn: fetch_pr failed %d", + err); + goto out; + } + if (prent.princ_expire_time != 0 && prent.pw_expiration != 0) + expiration = min(prent.princ_expire_time, + prent.pw_expiration); + else + expiration = prent.princ_expire_time ? + prent.princ_expire_time : prent.pw_expiration; + } if (debug) __pam_log(LOG_AUTH | LOG_DEBUG, - "PAM-KRB5 (acct): exp_warn: fetch_princ success:" - " princ exp=%ld pw_exp = %ld, now =%ld, days=%ld", - prent.princ_expire_time, - prent.pw_expiration, now, - prent.pw_expiration > 0 - ? ((prent.pw_expiration - now) / DAY) + "PAM-KRB5 (acct): exp_warn: " + "princ/pw_exp exp=%ld, now =%ld, days=%ld", + expiration, + now, + expiration > 0 + ? ((expiration - now) / DAY) : 0); /* warn user if principal's pw is set to expire */ - if (prent.pw_expiration > 0) { - days = (prent.pw_expiration - now) / DAY; + if (expiration > 0) { + days = (expiration - now) / DAY; if (days <= 0) (void) snprintf(messages[0], sizeof (messages[0]), dgettext(TEXT_DOMAIN, - "Your Kerberos password will expire within 24 hours.\n")); + "Your Kerberos account/password will expire " + "within 24 hours.\n")); else if (days == 1) (void) snprintf(messages[0], sizeof (messages[0]), dgettext(TEXT_DOMAIN, - "Your Kerberos password will expire in 1 day.\n")); + "Your Kerberos account/password will expire " + "in 1 day.\n")); else (void) snprintf(messages[0], sizeof (messages[0]), dgettext(TEXT_DOMAIN, - "Your Kerberos password will expire in %d days.\n"), + "Your Kerberos account/password will expire in " + "%d days.\n"), (int)days); (void) __pam_display_msg(pamh, PAM_TEXT_INFO, 1, @@ -423,7 +449,7 @@ pam_sm_acct_mgmt( if (!(flags & PAM_SILENT) && !nowarn && kmd->password) { /* if we fail, let it slide, it's only a warning brah */ - (void) exp_warn(pamh, user, kmd->password, debug); + (void) exp_warn(pamh, user, kmd, debug); } /* diff --git a/usr/src/lib/pam_modules/krb5/krb5_authenticate.c b/usr/src/lib/pam_modules/krb5/krb5_authenticate.c index aec4b426b7..eb0ac73162 100644 --- a/usr/src/lib/pam_modules/krb5/krb5_authenticate.c +++ b/usr/src/lib/pam_modules/krb5/krb5_authenticate.c @@ -77,6 +77,10 @@ extern int krb5_verifypw(char *, char *, int); extern krb5_error_code krb5_verify_init_creds(krb5_context, krb5_creds *, krb5_principal, krb5_keytab, krb5_ccache *, krb5_verify_init_creds_opt *); +extern krb5_error_code __krb5_get_init_creds_password(krb5_context, + krb5_creds *, krb5_principal, char *, krb5_prompter_fct, void *, + krb5_deltat, char *, krb5_get_init_creds_opt *, + krb5_kdc_rep **); /* * pam_sm_authenticate - Authenticate user @@ -325,6 +329,7 @@ attempt_krb5_auth( KRB5_TGS_NAME }; krb5_get_init_creds_opt opts; + krb5_kdc_rep *as_reply = NULL; /* * "result" should not be assigned PAM_SUCCESS unless * authentication has succeeded and there are no other errors. @@ -493,7 +498,14 @@ attempt_krb5_auth( if (*krb5_pass == NULL || strlen(*krb5_pass) == 0) { code = KRB5KRB_AP_ERR_BAD_INTEGRITY; } else { - code = krb5_get_init_creds_password(kmd->kcontext, + + /* + * We call our own private version of gic_pwd, because we need + * more information, such as password/account expiration, that + * is found in the as_reply. The "prompter" interface is not + * granular enough for PAM to make use of. + */ + code = __krb5_get_init_creds_password(kmd->kcontext, my_creds, me, *krb5_pass, /* clear text passwd */ @@ -501,7 +513,8 @@ attempt_krb5_auth( NULL, /* data */ 0, /* start time */ NULL, /* defaults to krbtgt@REALM */ - &opts); + &opts, + &as_reply); } if (kmd->debug) @@ -579,6 +592,10 @@ attempt_krb5_auth( krb5_free_principal(kmd->kcontext, sp); } } + + if (code == 0) + kmd->expiration = as_reply->enc_part2->key_exp; + break; case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: @@ -668,6 +685,8 @@ out: krb5_free_principal(kmd->kcontext, server); if (me) krb5_free_principal(kmd->kcontext, me); + if (as_reply) + krb5_free_kdc_rep(kmd->kcontext, as_reply); if (kmd->kcontext) { krb5_free_context(kmd->kcontext); kmd->kcontext = NULL; diff --git a/usr/src/lib/pam_modules/krb5/utils.h b/usr/src/lib/pam_modules/krb5/utils.h index a976a5ced6..ddc9136d90 100644 --- a/usr/src/lib/pam_modules/krb5/utils.h +++ b/usr/src/lib/pam_modules/krb5/utils.h @@ -53,6 +53,7 @@ typedef struct { /* pam_authenticate() */ char *password; int age_status; + krb5_timestamp expiration; } krb5_module_data_t; int get_pw_uid(char *, uid_t *); |
