10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53391Ssemery * Common Development and Distribution License (the "License").
63391Ssemery * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*8991SPeter.Shoults@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #include <kadm5/admin.h>
270Sstevel@tonic-gate #include <krb5.h>
280Sstevel@tonic-gate
290Sstevel@tonic-gate #include <security/pam_appl.h>
300Sstevel@tonic-gate #include <security/pam_modules.h>
310Sstevel@tonic-gate #include <security/pam_impl.h>
320Sstevel@tonic-gate #include <syslog.h>
330Sstevel@tonic-gate #include <string.h>
340Sstevel@tonic-gate #include <stdio.h>
350Sstevel@tonic-gate #include <stdlib.h>
360Sstevel@tonic-gate #include <sys/types.h>
370Sstevel@tonic-gate #include <pwd.h>
380Sstevel@tonic-gate #include <libintl.h>
390Sstevel@tonic-gate #include <netdb.h>
400Sstevel@tonic-gate #include "utils.h"
410Sstevel@tonic-gate #include <shadow.h>
420Sstevel@tonic-gate
430Sstevel@tonic-gate #include "krb5_repository.h"
440Sstevel@tonic-gate
450Sstevel@tonic-gate #define KRB5_AUTOMIGRATE_DATA "SUNW-KRB5-AUTOMIGRATE-DATA"
460Sstevel@tonic-gate
473641Ssemery #define min(a, b) ((a) < (b) ? (a) : (b))
483641Ssemery
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate * pam_sm_acct_mgmt main account managment routine.
510Sstevel@tonic-gate */
520Sstevel@tonic-gate
530Sstevel@tonic-gate static int
fetch_princ_entry(krb5_module_data_t * kmd,char * princ_str,kadm5_principal_ent_rec * prent,int debug)540Sstevel@tonic-gate fetch_princ_entry(
553641Ssemery krb5_module_data_t *kmd,
560Sstevel@tonic-gate char *princ_str,
570Sstevel@tonic-gate kadm5_principal_ent_rec *prent, /* out */
580Sstevel@tonic-gate int debug)
590Sstevel@tonic-gate
600Sstevel@tonic-gate {
610Sstevel@tonic-gate kadm5_ret_t code;
620Sstevel@tonic-gate krb5_principal princ = 0;
630Sstevel@tonic-gate char admin_realm[1024];
640Sstevel@tonic-gate char kprinc[2*MAXHOSTNAMELEN];
653641Ssemery char *cpw_service, *password;
660Sstevel@tonic-gate void *server_handle;
670Sstevel@tonic-gate krb5_context context;
680Sstevel@tonic-gate kadm5_config_params params;
690Sstevel@tonic-gate
703641Ssemery password = kmd->password;
713641Ssemery context = kmd->kcontext;
720Sstevel@tonic-gate
733641Ssemery if ((code = get_kmd_kuser(context, (const char *)princ_str,
743641Ssemery kprinc, 2*MAXHOSTNAMELEN)) != 0) {
750Sstevel@tonic-gate return (code);
760Sstevel@tonic-gate }
770Sstevel@tonic-gate
780Sstevel@tonic-gate code = krb5_parse_name(context, kprinc, &princ);
790Sstevel@tonic-gate if (code != 0) {
800Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
810Sstevel@tonic-gate }
820Sstevel@tonic-gate
830Sstevel@tonic-gate if (strlen(password) == 0) {
840Sstevel@tonic-gate krb5_free_principal(context, princ);
850Sstevel@tonic-gate if (debug)
863391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
870Sstevel@tonic-gate "PAM-KRB5 (acct): fetch_princ_entry: pwlen=0");
880Sstevel@tonic-gate return (PAM_AUTH_ERR);
890Sstevel@tonic-gate }
900Sstevel@tonic-gate
910Sstevel@tonic-gate (void) strlcpy(admin_realm,
920Sstevel@tonic-gate krb5_princ_realm(context, princ)->data,
930Sstevel@tonic-gate sizeof (admin_realm));
940Sstevel@tonic-gate
950Sstevel@tonic-gate (void) memset((char *)¶ms, 0, sizeof (params));
960Sstevel@tonic-gate params.mask |= KADM5_CONFIG_REALM;
970Sstevel@tonic-gate params.realm = admin_realm;
980Sstevel@tonic-gate
990Sstevel@tonic-gate if (kadm5_get_cpw_host_srv_name(context, admin_realm, &cpw_service)) {
1003391Ssemery __pam_log(LOG_AUTH | LOG_ERR,
1010Sstevel@tonic-gate "PAM-KRB5 (acct): unable to get host based "
1023391Ssemery "service name for realm '%s'",
1030Sstevel@tonic-gate admin_realm);
1040Sstevel@tonic-gate krb5_free_principal(context, princ);
1050Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
1060Sstevel@tonic-gate }
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate code = kadm5_init_with_password(kprinc, password, cpw_service,
1090Sstevel@tonic-gate ¶ms, KADM5_STRUCT_VERSION,
1104960Swillf KADM5_API_VERSION_2, NULL,
1114960Swillf &server_handle);
1120Sstevel@tonic-gate if (code != 0) {
1130Sstevel@tonic-gate if (debug)
1143391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
1150Sstevel@tonic-gate "PAM-KRB5 (acct): fetch_princ_entry: "
1160Sstevel@tonic-gate "init_with_pw failed: code = %d", code);
1170Sstevel@tonic-gate krb5_free_principal(context, princ);
1180Sstevel@tonic-gate return ((code == KADM5_BAD_PASSWORD) ?
1190Sstevel@tonic-gate PAM_AUTH_ERR : PAM_SYSTEM_ERR);
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate if (_kadm5_get_kpasswd_protocol(server_handle) != KRB5_CHGPWD_RPCSEC) {
1230Sstevel@tonic-gate if (debug)
1243391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
1250Sstevel@tonic-gate "PAM-KRB5 (acct): fetch_princ_entry: "
1260Sstevel@tonic-gate "non-RPCSEC_GSS chpw server, can't get "
1270Sstevel@tonic-gate "princ entry");
1280Sstevel@tonic-gate (void) kadm5_destroy(server_handle);
1290Sstevel@tonic-gate krb5_free_principal(context, princ);
1300Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate code = kadm5_get_principal(server_handle, princ, prent,
1340Sstevel@tonic-gate KADM5_PRINCIPAL_NORMAL_MASK);
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate if (code != 0) {
1370Sstevel@tonic-gate (void) kadm5_destroy(server_handle);
1380Sstevel@tonic-gate krb5_free_principal(context, princ);
1390Sstevel@tonic-gate return ((code == KADM5_UNK_PRINC) ?
1400Sstevel@tonic-gate PAM_USER_UNKNOWN : PAM_SYSTEM_ERR);
1410Sstevel@tonic-gate }
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate (void) kadm5_destroy(server_handle);
1440Sstevel@tonic-gate krb5_free_principal(context, princ);
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate return (PAM_SUCCESS);
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate /*
1500Sstevel@tonic-gate * exp_warn
1510Sstevel@tonic-gate *
1523641Ssemery * Warn the user if their pw is set to expire.
1530Sstevel@tonic-gate *
1543641Ssemery * We first check to see if the KDC had set any account or password
1553641Ssemery * expiration information in the key expiration field. If this was
1563641Ssemery * not set then we must assume that the KDC could be broken and revert
1573641Ssemery * to fetching pw/account expiration information from kadm. We can not
1583641Ssemery * determine the difference between broken KDCs that do not send key-exp
1593641Ssemery * vs. principals that do not have an expiration policy. The up-shot
1603641Ssemery * is that pam_krb5 will probably not be stacked for acct mgmt if the
1613641Ssemery * environment does not have an exp policy, avoiding the second exchange
1623641Ssemery * using the kadm protocol.
1630Sstevel@tonic-gate */
1640Sstevel@tonic-gate static int
exp_warn(pam_handle_t * pamh,char * user,krb5_module_data_t * kmd,int debug)1650Sstevel@tonic-gate exp_warn(
1660Sstevel@tonic-gate pam_handle_t *pamh,
1670Sstevel@tonic-gate char *user,
1683641Ssemery krb5_module_data_t *kmd,
1690Sstevel@tonic-gate int debug)
1700Sstevel@tonic-gate
1710Sstevel@tonic-gate {
1720Sstevel@tonic-gate int err;
1730Sstevel@tonic-gate kadm5_principal_ent_rec prent;
1743641Ssemery krb5_timestamp now, days, expiration;
1753641Ssemery char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE], *password;
1763641Ssemery krb5_error_code code;
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate if (debug)
1793391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
1800Sstevel@tonic-gate "PAM-KRB5 (acct): exp_warn start: user = '%s'",
1810Sstevel@tonic-gate user ? user : "<null>");
1820Sstevel@tonic-gate
1833641Ssemery password = kmd->password;
1843641Ssemery
1850Sstevel@tonic-gate if (!pamh || !user || !password) {
1860Sstevel@tonic-gate err = PAM_SERVICE_ERR;
1874252Sps57422 goto exit;
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate
1904252Sps57422 /*
191*8991SPeter.Shoults@Sun.COM * If we error out from krb5_init_secure_context, then just set error
192*8991SPeter.Shoults@Sun.COM * code, check to see about debug message and exit out of routine as the
1934252Sps57422 * context could not possibly have been setup.
1944252Sps57422 */
1954252Sps57422
196*8991SPeter.Shoults@Sun.COM if (code = krb5_init_secure_context(&kmd->kcontext)) {
1973641Ssemery err = PAM_SYSTEM_ERR;
1983641Ssemery if (debug)
1993641Ssemery __pam_log(LOG_AUTH | LOG_ERR, "PAM-KRB5 (acct): "
200*8991SPeter.Shoults@Sun.COM "krb5_init_secure_context failed: code=%d",
2013641Ssemery code);
2024252Sps57422 goto exit;
2033641Ssemery }
2043641Ssemery if (code = krb5_timeofday(kmd->kcontext, &now)) {
2053641Ssemery err = PAM_SYSTEM_ERR;
2060Sstevel@tonic-gate if (debug)
2073641Ssemery __pam_log(LOG_AUTH | LOG_ERR,
2083641Ssemery "PAM-KRB5 (acct): krb5_timeofday failed: code=%d",
2093641Ssemery code);
2100Sstevel@tonic-gate goto out;
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate
2133641Ssemery if (kmd->expiration != 0) {
2143641Ssemery expiration = kmd->expiration;
2153641Ssemery } else {
2163641Ssemery (void) memset(&prent, 0, sizeof (prent));
2173641Ssemery if ((err = fetch_princ_entry(kmd, user, &prent, debug))
2183641Ssemery != PAM_SUCCESS) {
2193641Ssemery if (debug)
2203641Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
2213641Ssemery "PAM-KRB5 (acct): exp_warn: fetch_pr failed %d",
2223641Ssemery err);
2233641Ssemery goto out;
2243641Ssemery }
2253641Ssemery if (prent.princ_expire_time != 0 && prent.pw_expiration != 0)
2263641Ssemery expiration = min(prent.princ_expire_time,
2273641Ssemery prent.pw_expiration);
2283641Ssemery else
2293641Ssemery expiration = prent.princ_expire_time ?
2303641Ssemery prent.princ_expire_time : prent.pw_expiration;
2313641Ssemery }
2323641Ssemery
2330Sstevel@tonic-gate if (debug)
2343391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
2353641Ssemery "PAM-KRB5 (acct): exp_warn: "
2363641Ssemery "princ/pw_exp exp=%ld, now =%ld, days=%ld",
2373641Ssemery expiration,
2383641Ssemery now,
2393641Ssemery expiration > 0
2403641Ssemery ? ((expiration - now) / DAY)
2410Sstevel@tonic-gate : 0);
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate /* warn user if principal's pw is set to expire */
2443641Ssemery if (expiration > 0) {
2453641Ssemery days = (expiration - now) / DAY;
2460Sstevel@tonic-gate if (days <= 0)
2470Sstevel@tonic-gate (void) snprintf(messages[0],
2480Sstevel@tonic-gate sizeof (messages[0]),
2490Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
2503641Ssemery "Your Kerberos account/password will expire "
2513641Ssemery "within 24 hours.\n"));
2520Sstevel@tonic-gate else if (days == 1)
2530Sstevel@tonic-gate (void) snprintf(messages[0],
2540Sstevel@tonic-gate sizeof (messages[0]),
2550Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
2563641Ssemery "Your Kerberos account/password will expire "
2573641Ssemery "in 1 day.\n"));
2580Sstevel@tonic-gate else
2590Sstevel@tonic-gate (void) snprintf(messages[0],
2600Sstevel@tonic-gate sizeof (messages[0]),
2610Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
2623641Ssemery "Your Kerberos account/password will expire in "
2633641Ssemery "%d days.\n"),
2640Sstevel@tonic-gate (int)days);
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate (void) __pam_display_msg(pamh, PAM_TEXT_INFO, 1,
2670Sstevel@tonic-gate messages, NULL);
2680Sstevel@tonic-gate }
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate /* things went smooth */
2710Sstevel@tonic-gate err = PAM_SUCCESS;
2720Sstevel@tonic-gate
2730Sstevel@tonic-gate out:
2744252Sps57422
2754252Sps57422 if (kmd->kcontext) {
2764252Sps57422 krb5_free_context(kmd->kcontext);
2774252Sps57422 kmd->kcontext = NULL;
2784252Sps57422 }
2794252Sps57422
2804252Sps57422 exit:
2814252Sps57422
2820Sstevel@tonic-gate if (debug)
2833391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
2840Sstevel@tonic-gate "PAM-KRB5 (acct): exp_warn end: err = %d", err);
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate return (err);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate /*
2900Sstevel@tonic-gate * pam_krb5 acct_mgmt
2910Sstevel@tonic-gate *
2920Sstevel@tonic-gate * we do
2930Sstevel@tonic-gate * - check if pw expired (flag set in auth)
2940Sstevel@tonic-gate * - warn user if pw is set to expire
2950Sstevel@tonic-gate *
2960Sstevel@tonic-gate * notes
2970Sstevel@tonic-gate * - we require the auth module to have already run (sets module data)
2980Sstevel@tonic-gate * - we don't worry about an expired princ cuz if that's the case,
2990Sstevel@tonic-gate * auth would have failed
3000Sstevel@tonic-gate */
3010Sstevel@tonic-gate int
pam_sm_acct_mgmt(pam_handle_t * pamh,int flags,int argc,const char ** argv)3020Sstevel@tonic-gate pam_sm_acct_mgmt(
3030Sstevel@tonic-gate pam_handle_t *pamh,
3040Sstevel@tonic-gate int flags,
3050Sstevel@tonic-gate int argc,
3060Sstevel@tonic-gate const char **argv)
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate {
3090Sstevel@tonic-gate char *user = NULL;
3100Sstevel@tonic-gate char *userdata = NULL;
3110Sstevel@tonic-gate int err;
3120Sstevel@tonic-gate int i;
3130Sstevel@tonic-gate krb5_module_data_t *kmd = NULL;
3140Sstevel@tonic-gate char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
3150Sstevel@tonic-gate int debug = 0; /* pam.conf entry option */
3160Sstevel@tonic-gate int nowarn = 0; /* pam.conf entry option, no expire warnings */
3170Sstevel@tonic-gate pam_repository_t *rep_data = NULL;
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate for (i = 0; i < argc; i++) {
3200Sstevel@tonic-gate if (strcasecmp(argv[i], "debug") == 0)
3210Sstevel@tonic-gate debug = 1;
3220Sstevel@tonic-gate else if (strcasecmp(argv[i], "nowarn") == 0) {
3230Sstevel@tonic-gate nowarn = 1;
3240Sstevel@tonic-gate flags = flags | PAM_SILENT;
3250Sstevel@tonic-gate } else {
3263391Ssemery __pam_log(LOG_AUTH | LOG_ERR,
3270Sstevel@tonic-gate "PAM-KRB5 (acct): illegal option %s",
3280Sstevel@tonic-gate argv[i]);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate if (debug)
3333391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
3340Sstevel@tonic-gate "PAM-KRB5 (acct): debug=%d, nowarn=%d",
3350Sstevel@tonic-gate debug, nowarn);
3360Sstevel@tonic-gate
3373391Ssemery (void) pam_get_item(pamh, PAM_REPOSITORY, (void **)&rep_data);
3383391Ssemery
3390Sstevel@tonic-gate if (rep_data != NULL) {
3400Sstevel@tonic-gate /*
3410Sstevel@tonic-gate * If the repository is not ours,
3420Sstevel@tonic-gate * return PAM_IGNORE.
3430Sstevel@tonic-gate */
3440Sstevel@tonic-gate if (strcmp(rep_data->type, KRB5_REPOSITORY_NAME) != 0) {
3450Sstevel@tonic-gate if (debug)
3463391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
3473391Ssemery "PAM-KRB5 (acct): wrong"
3480Sstevel@tonic-gate "repository found (%s), returning "
3490Sstevel@tonic-gate "PAM_IGNORE", rep_data->type);
3500Sstevel@tonic-gate return (PAM_IGNORE);
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate
3550Sstevel@tonic-gate /* get user name */
3563391Ssemery (void) pam_get_item(pamh, PAM_USER, (void **) &user);
3570Sstevel@tonic-gate
3583391Ssemery if (user == NULL || *user == '\0') {
3590Sstevel@tonic-gate err = PAM_USER_UNKNOWN;
3600Sstevel@tonic-gate goto out;
3610Sstevel@tonic-gate }
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate /* get pam_krb5_migrate specific data */
3640Sstevel@tonic-gate err = pam_get_data(pamh, KRB5_AUTOMIGRATE_DATA,
3650Sstevel@tonic-gate (const void **)&userdata);
3660Sstevel@tonic-gate if (err != PAM_SUCCESS) {
3670Sstevel@tonic-gate if (debug)
3683391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG, "PAM-KRB5 (acct): "
3693391Ssemery "no module data for KRB5_AUTOMIGRATE_DATA");
3700Sstevel@tonic-gate } else {
3710Sstevel@tonic-gate /*
3720Sstevel@tonic-gate * We try and reauthenticate, since this user has a
3730Sstevel@tonic-gate * newly created krb5 principal via the pam_krb5_migrate
3740Sstevel@tonic-gate * auth module. That way, this new user will have fresh
3750Sstevel@tonic-gate * creds (assuming pam_sm_authenticate() succeeds).
3760Sstevel@tonic-gate */
3770Sstevel@tonic-gate if (strcmp(user, userdata) == 0)
3780Sstevel@tonic-gate (void) pam_sm_authenticate(pamh, flags, argc,
3790Sstevel@tonic-gate (const char **)argv);
3800Sstevel@tonic-gate else
3810Sstevel@tonic-gate if (debug)
3823391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
3830Sstevel@tonic-gate "PAM-KRB5 (acct): PAM_USER %s"
3843391Ssemery "does not match user %s from pam_get_data()",
3850Sstevel@tonic-gate user, (char *)userdata);
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate
3880Sstevel@tonic-gate /* get krb5 module data */
3890Sstevel@tonic-gate if ((err = pam_get_data(pamh, KRB5_DATA, (const void **)&kmd))
3900Sstevel@tonic-gate != PAM_SUCCESS) {
3910Sstevel@tonic-gate if (err == PAM_NO_MODULE_DATA) {
3920Sstevel@tonic-gate /*
3930Sstevel@tonic-gate * pam_auth never called (possible config
3943740Ssemery * error; no pam_krb5 auth entry in pam.conf),
3950Sstevel@tonic-gate */
3963740Ssemery if (debug) {
3973391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
3980Sstevel@tonic-gate "PAM-KRB5 (acct): no module data");
3993740Ssemery }
4000Sstevel@tonic-gate err = PAM_IGNORE;
4010Sstevel@tonic-gate goto out;
4020Sstevel@tonic-gate } else {
4033391Ssemery __pam_log(LOG_AUTH | LOG_ERR,
4040Sstevel@tonic-gate "PAM-KRB5 (acct): get module"
4053391Ssemery " data failed: err=%d",
4060Sstevel@tonic-gate err);
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate goto out;
4090Sstevel@tonic-gate }
4100Sstevel@tonic-gate
4110Sstevel@tonic-gate debug = debug || kmd->debug;
4120Sstevel@tonic-gate
4130Sstevel@tonic-gate /*
4140Sstevel@tonic-gate * auth mod set status to ignore, most likely cuz root key is
4150Sstevel@tonic-gate * in keytab, so skip other checks and return ignore
4160Sstevel@tonic-gate */
4170Sstevel@tonic-gate if (kmd->auth_status == PAM_IGNORE) {
4180Sstevel@tonic-gate if (debug)
4193391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
4200Sstevel@tonic-gate "PAM-KRB5 (acct): kmd auth_status is IGNORE");
4210Sstevel@tonic-gate err = PAM_IGNORE;
4220Sstevel@tonic-gate goto out;
4230Sstevel@tonic-gate }
4240Sstevel@tonic-gate
4250Sstevel@tonic-gate /*
4263740Ssemery * If there is no Kerberos related user and there is authentication
4273740Ssemery * data, this means that while the user has successfully passed
4283740Ssemery * authentication, Kerberos is not the account authority because there
4293740Ssemery * is no valid Kerberos principal. PAM_IGNORE is returned since
4303740Ssemery * Kerberos is not authoritative for this user. Other modules in the
4313740Ssemery * account stack will need to determine the success or failure for this
4323740Ssemery * user.
4333391Ssemery */
4343391Ssemery if (kmd->auth_status == PAM_USER_UNKNOWN) {
4353391Ssemery if (debug)
4363391Ssemery syslog(LOG_DEBUG,
4373391Ssemery "PAM-KRB5 (acct): kmd auth_status is USER UNKNOWN");
4383740Ssemery err = PAM_IGNORE;
4393391Ssemery goto out;
4403391Ssemery }
4413391Ssemery
4423391Ssemery /*
4430Sstevel@tonic-gate * age_status will be set to PAM_NEW_AUTHTOK_REQD in pam_krb5's
4440Sstevel@tonic-gate * 'auth' if the user's key/pw has expired and needs to be changed
4450Sstevel@tonic-gate */
4460Sstevel@tonic-gate if (kmd->age_status == PAM_NEW_AUTHTOK_REQD) {
4470Sstevel@tonic-gate if (!nowarn) {
4480Sstevel@tonic-gate (void) snprintf(messages[0], sizeof (messages[0]),
4490Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
4500Sstevel@tonic-gate "Your Kerberos password has expired.\n"));
4510Sstevel@tonic-gate (void) __pam_display_msg(pamh, PAM_TEXT_INFO,
4520Sstevel@tonic-gate 1, messages, NULL);
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate err = PAM_NEW_AUTHTOK_REQD;
4550Sstevel@tonic-gate goto out;
4560Sstevel@tonic-gate }
4570Sstevel@tonic-gate
4583740Ssemery if (kmd->auth_status == PAM_SUCCESS && !(flags & PAM_SILENT) &&
4593740Ssemery !nowarn && kmd->password) {
4600Sstevel@tonic-gate /* if we fail, let it slide, it's only a warning brah */
4613641Ssemery (void) exp_warn(pamh, user, kmd, debug);
4620Sstevel@tonic-gate }
4630Sstevel@tonic-gate
4643391Ssemery /*
4653740Ssemery * If Kerberos is treated as optional in the PAM stack, it is possible
4663740Ssemery * that there is a KRB5_DATA item and a non-Kerberos account authority.
4673740Ssemery * In that case, PAM_IGNORE is returned.
4683391Ssemery */
4693740Ssemery err = kmd->auth_status != PAM_SUCCESS ? PAM_IGNORE : kmd->auth_status;
4700Sstevel@tonic-gate
4710Sstevel@tonic-gate out:
4720Sstevel@tonic-gate if (debug)
4733391Ssemery __pam_log(LOG_AUTH | LOG_DEBUG,
4740Sstevel@tonic-gate "PAM-KRB5 (acct): end: %s", pam_strerror(pamh, err));
4750Sstevel@tonic-gate
4760Sstevel@tonic-gate return (err);
4770Sstevel@tonic-gate }
478