summaryrefslogtreecommitdiff
path: root/usr/src/lib/pam_modules/krb5
diff options
context:
space:
mode:
authorsemery <none@none>2007-02-13 10:15:31 -0800
committersemery <none@none>2007-02-13 10:15:31 -0800
commit3125ebfc35130d243e775dc38a6a59be4df0b137 (patch)
tree35a9f1bc94fa3d99936bd154bc74a408ae96d1ab /usr/src/lib/pam_modules/krb5
parentfa871852ed0075b7564289cb07481ed343bb162f (diff)
downloadillumos-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.c118
-rw-r--r--usr/src/lib/pam_modules/krb5/krb5_authenticate.c23
-rw-r--r--usr/src/lib/pam_modules/krb5/utils.h1
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 *);