17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53bfb48feSsemery * Common Development and Distribution License (the "License").
63bfb48feSsemery * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
228ce3ffdfSPeter Shoults * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
24*cbea7acaSDominik Hassler *
25*cbea7acaSDominik Hassler * Copyright 2023 OmniOS Community Edition (OmniOSce) Association.
267c478bd9Sstevel@tonic-gate */
277c478bd9Sstevel@tonic-gate
287c478bd9Sstevel@tonic-gate #include <kadm5/admin.h>
297c478bd9Sstevel@tonic-gate #include <krb5.h>
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <security/pam_appl.h>
327c478bd9Sstevel@tonic-gate #include <security/pam_modules.h>
337c478bd9Sstevel@tonic-gate #include <security/pam_impl.h>
347c478bd9Sstevel@tonic-gate #include <syslog.h>
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate #include <stdio.h>
377c478bd9Sstevel@tonic-gate #include <stdlib.h>
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
397c478bd9Sstevel@tonic-gate #include <pwd.h>
407c478bd9Sstevel@tonic-gate #include <libintl.h>
417c478bd9Sstevel@tonic-gate #include <netdb.h>
427c478bd9Sstevel@tonic-gate #include "utils.h"
437c478bd9Sstevel@tonic-gate #include <shadow.h>
447c478bd9Sstevel@tonic-gate
457c478bd9Sstevel@tonic-gate #include "krb5_repository.h"
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate #define KRB5_AUTOMIGRATE_DATA "SUNW-KRB5-AUTOMIGRATE-DATA"
487c478bd9Sstevel@tonic-gate
493125ebfcSsemery #define min(a, b) ((a) < (b) ? (a) : (b))
503125ebfcSsemery
517c478bd9Sstevel@tonic-gate /*
527c478bd9Sstevel@tonic-gate * pam_sm_acct_mgmt main account managment routine.
537c478bd9Sstevel@tonic-gate */
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate static int
fetch_princ_entry(krb5_module_data_t * kmd,const char * princ_str,kadm5_principal_ent_rec * prent,int debug)567c478bd9Sstevel@tonic-gate fetch_princ_entry(
573125ebfcSsemery krb5_module_data_t *kmd,
58*cbea7acaSDominik Hassler const char *princ_str,
597c478bd9Sstevel@tonic-gate kadm5_principal_ent_rec *prent, /* out */
607c478bd9Sstevel@tonic-gate int debug)
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate {
637c478bd9Sstevel@tonic-gate kadm5_ret_t code;
647c478bd9Sstevel@tonic-gate krb5_principal princ = 0;
657c478bd9Sstevel@tonic-gate char admin_realm[1024];
667c478bd9Sstevel@tonic-gate char kprinc[2*MAXHOSTNAMELEN];
673125ebfcSsemery char *cpw_service, *password;
687c478bd9Sstevel@tonic-gate void *server_handle;
697c478bd9Sstevel@tonic-gate krb5_context context;
707c478bd9Sstevel@tonic-gate kadm5_config_params params;
717c478bd9Sstevel@tonic-gate
723125ebfcSsemery password = kmd->password;
733125ebfcSsemery context = kmd->kcontext;
747c478bd9Sstevel@tonic-gate
75*cbea7acaSDominik Hassler if ((code = get_kmd_kuser(context, princ_str,
763125ebfcSsemery kprinc, 2 * MAXHOSTNAMELEN)) != 0) {
777c478bd9Sstevel@tonic-gate return (code);
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate code = krb5_parse_name(context, kprinc, &princ);
817c478bd9Sstevel@tonic-gate if (code != 0) {
827c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate if (strlen(password) == 0) {
867c478bd9Sstevel@tonic-gate krb5_free_principal(context, princ);
877c478bd9Sstevel@tonic-gate if (debug)
883bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
897c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): fetch_princ_entry: pwlen=0");
907c478bd9Sstevel@tonic-gate return (PAM_AUTH_ERR);
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate
937c478bd9Sstevel@tonic-gate (void) strlcpy(admin_realm,
947c478bd9Sstevel@tonic-gate krb5_princ_realm(context, princ)->data,
957c478bd9Sstevel@tonic-gate sizeof (admin_realm));
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate (void) memset((char *)¶ms, 0, sizeof (params));
987c478bd9Sstevel@tonic-gate params.mask |= KADM5_CONFIG_REALM;
997c478bd9Sstevel@tonic-gate params.realm = admin_realm;
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate if (kadm5_get_cpw_host_srv_name(context, admin_realm, &cpw_service)) {
1023bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR,
1037c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): unable to get host based "
1043bfb48feSsemery "service name for realm '%s'",
1057c478bd9Sstevel@tonic-gate admin_realm);
1067c478bd9Sstevel@tonic-gate krb5_free_principal(context, princ);
1077c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate code = kadm5_init_with_password(kprinc, password, cpw_service,
1117c478bd9Sstevel@tonic-gate ¶ms, KADM5_STRUCT_VERSION,
11254925bf6Swillf KADM5_API_VERSION_2, NULL,
11354925bf6Swillf &server_handle);
1147c478bd9Sstevel@tonic-gate if (code != 0) {
1157c478bd9Sstevel@tonic-gate if (debug)
1163bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
1177c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): fetch_princ_entry: "
1187c478bd9Sstevel@tonic-gate "init_with_pw failed: code = %d", code);
1197c478bd9Sstevel@tonic-gate krb5_free_principal(context, princ);
1207c478bd9Sstevel@tonic-gate return ((code == KADM5_BAD_PASSWORD) ?
1217c478bd9Sstevel@tonic-gate PAM_AUTH_ERR : PAM_SYSTEM_ERR);
1227c478bd9Sstevel@tonic-gate }
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate if (_kadm5_get_kpasswd_protocol(server_handle) != KRB5_CHGPWD_RPCSEC) {
1257c478bd9Sstevel@tonic-gate if (debug)
1263bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
1277c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): fetch_princ_entry: "
1287c478bd9Sstevel@tonic-gate "non-RPCSEC_GSS chpw server, can't get "
1297c478bd9Sstevel@tonic-gate "princ entry");
1307c478bd9Sstevel@tonic-gate (void) kadm5_destroy(server_handle);
1317c478bd9Sstevel@tonic-gate krb5_free_principal(context, princ);
1327c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR);
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate code = kadm5_get_principal(server_handle, princ, prent,
1367c478bd9Sstevel@tonic-gate KADM5_PRINCIPAL_NORMAL_MASK);
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate if (code != 0) {
1397c478bd9Sstevel@tonic-gate (void) kadm5_destroy(server_handle);
1407c478bd9Sstevel@tonic-gate krb5_free_principal(context, princ);
1417c478bd9Sstevel@tonic-gate return ((code == KADM5_UNK_PRINC) ?
1427c478bd9Sstevel@tonic-gate PAM_USER_UNKNOWN : PAM_SYSTEM_ERR);
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate
1457c478bd9Sstevel@tonic-gate (void) kadm5_destroy(server_handle);
1467c478bd9Sstevel@tonic-gate krb5_free_principal(context, princ);
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate return (PAM_SUCCESS);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate * exp_warn
1537c478bd9Sstevel@tonic-gate *
1543125ebfcSsemery * Warn the user if their pw is set to expire.
1557c478bd9Sstevel@tonic-gate *
1563125ebfcSsemery * We first check to see if the KDC had set any account or password
1573125ebfcSsemery * expiration information in the key expiration field. If this was
1583125ebfcSsemery * not set then we must assume that the KDC could be broken and revert
1593125ebfcSsemery * to fetching pw/account expiration information from kadm. We can not
1603125ebfcSsemery * determine the difference between broken KDCs that do not send key-exp
1613125ebfcSsemery * vs. principals that do not have an expiration policy. The up-shot
1623125ebfcSsemery * is that pam_krb5 will probably not be stacked for acct mgmt if the
1633125ebfcSsemery * environment does not have an exp policy, avoiding the second exchange
1643125ebfcSsemery * using the kadm protocol.
1657c478bd9Sstevel@tonic-gate */
1667c478bd9Sstevel@tonic-gate static int
exp_warn(pam_handle_t * pamh,const char * user,krb5_module_data_t * kmd,int debug)1677c478bd9Sstevel@tonic-gate exp_warn(
1687c478bd9Sstevel@tonic-gate pam_handle_t *pamh,
169*cbea7acaSDominik Hassler const char *user,
1703125ebfcSsemery krb5_module_data_t *kmd,
1717c478bd9Sstevel@tonic-gate int debug)
1727c478bd9Sstevel@tonic-gate
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate int err;
1757c478bd9Sstevel@tonic-gate kadm5_principal_ent_rec prent;
1763125ebfcSsemery krb5_timestamp now, days, expiration;
1773125ebfcSsemery char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE], *password;
1783125ebfcSsemery krb5_error_code code;
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate if (debug)
1813bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
1827c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): exp_warn start: user = '%s'",
1837c478bd9Sstevel@tonic-gate user ? user : "<null>");
1847c478bd9Sstevel@tonic-gate
1853125ebfcSsemery password = kmd->password;
1863125ebfcSsemery
1877c478bd9Sstevel@tonic-gate if (!pamh || !user || !password) {
1887c478bd9Sstevel@tonic-gate err = PAM_SERVICE_ERR;
189f12178a9Sps57422 goto exit;
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate
192f12178a9Sps57422 /*
1938ce3ffdfSPeter Shoults * If we error out from krb5_init_secure_context, then just set error
1948ce3ffdfSPeter Shoults * code, check to see about debug message and exit out of routine as the
195f12178a9Sps57422 * context could not possibly have been setup.
196f12178a9Sps57422 */
197f12178a9Sps57422
1988ce3ffdfSPeter Shoults if (code = krb5_init_secure_context(&kmd->kcontext)) {
1993125ebfcSsemery err = PAM_SYSTEM_ERR;
2003125ebfcSsemery if (debug)
2013125ebfcSsemery __pam_log(LOG_AUTH | LOG_ERR, "PAM-KRB5 (acct): "
2028ce3ffdfSPeter Shoults "krb5_init_secure_context failed: code=%d",
2033125ebfcSsemery code);
204f12178a9Sps57422 goto exit;
2053125ebfcSsemery }
2063125ebfcSsemery if (code = krb5_timeofday(kmd->kcontext, &now)) {
2073125ebfcSsemery err = PAM_SYSTEM_ERR;
2083125ebfcSsemery if (debug)
2093125ebfcSsemery __pam_log(LOG_AUTH | LOG_ERR,
2103125ebfcSsemery "PAM-KRB5 (acct): krb5_timeofday failed: code=%d",
2113125ebfcSsemery code);
2123125ebfcSsemery goto out;
2133125ebfcSsemery }
2143125ebfcSsemery
2153125ebfcSsemery if (kmd->expiration != 0) {
2163125ebfcSsemery expiration = kmd->expiration;
2173125ebfcSsemery } else {
2187c478bd9Sstevel@tonic-gate (void) memset(&prent, 0, sizeof (prent));
2193125ebfcSsemery if ((err = fetch_princ_entry(kmd, user, &prent, debug))
2203125ebfcSsemery != PAM_SUCCESS) {
2217c478bd9Sstevel@tonic-gate if (debug)
2223bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
2237c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): exp_warn: fetch_pr failed %d",
2247c478bd9Sstevel@tonic-gate err);
2257c478bd9Sstevel@tonic-gate goto out;
2267c478bd9Sstevel@tonic-gate }
2273125ebfcSsemery if (prent.princ_expire_time != 0 && prent.pw_expiration != 0)
2283125ebfcSsemery expiration = min(prent.princ_expire_time,
2293125ebfcSsemery prent.pw_expiration);
2303125ebfcSsemery else
2313125ebfcSsemery expiration = prent.princ_expire_time ?
2323125ebfcSsemery prent.princ_expire_time : prent.pw_expiration;
2333125ebfcSsemery }
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate if (debug)
2363bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
2373125ebfcSsemery "PAM-KRB5 (acct): exp_warn: "
2383125ebfcSsemery "princ/pw_exp exp=%ld, now =%ld, days=%ld",
2393125ebfcSsemery expiration,
2403125ebfcSsemery now,
2413125ebfcSsemery expiration > 0
2423125ebfcSsemery ? ((expiration - now) / DAY)
2437c478bd9Sstevel@tonic-gate : 0);
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate /* warn user if principal's pw is set to expire */
2463125ebfcSsemery if (expiration > 0) {
2473125ebfcSsemery days = (expiration - now) / DAY;
2487c478bd9Sstevel@tonic-gate if (days <= 0)
2497c478bd9Sstevel@tonic-gate (void) snprintf(messages[0],
2507c478bd9Sstevel@tonic-gate sizeof (messages[0]),
2517c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
2523125ebfcSsemery "Your Kerberos account/password will expire "
2533125ebfcSsemery "within 24 hours.\n"));
2547c478bd9Sstevel@tonic-gate else if (days == 1)
2557c478bd9Sstevel@tonic-gate (void) snprintf(messages[0],
2567c478bd9Sstevel@tonic-gate sizeof (messages[0]),
2577c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
2583125ebfcSsemery "Your Kerberos account/password will expire "
2593125ebfcSsemery "in 1 day.\n"));
2607c478bd9Sstevel@tonic-gate else
2617c478bd9Sstevel@tonic-gate (void) snprintf(messages[0],
2627c478bd9Sstevel@tonic-gate sizeof (messages[0]),
2637c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
2643125ebfcSsemery "Your Kerberos account/password will expire in "
2653125ebfcSsemery "%d days.\n"),
2667c478bd9Sstevel@tonic-gate (int)days);
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate (void) __pam_display_msg(pamh, PAM_TEXT_INFO, 1,
2697c478bd9Sstevel@tonic-gate messages, NULL);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate /* things went smooth */
2737c478bd9Sstevel@tonic-gate err = PAM_SUCCESS;
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate out:
276f12178a9Sps57422
277f12178a9Sps57422 if (kmd->kcontext) {
278f12178a9Sps57422 krb5_free_context(kmd->kcontext);
279f12178a9Sps57422 kmd->kcontext = NULL;
280f12178a9Sps57422 }
281f12178a9Sps57422
282f12178a9Sps57422 exit:
283f12178a9Sps57422
2847c478bd9Sstevel@tonic-gate if (debug)
2853bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
2867c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): exp_warn end: err = %d", err);
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate return (err);
2897c478bd9Sstevel@tonic-gate }
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate /*
2927c478bd9Sstevel@tonic-gate * pam_krb5 acct_mgmt
2937c478bd9Sstevel@tonic-gate *
2947c478bd9Sstevel@tonic-gate * we do
2957c478bd9Sstevel@tonic-gate * - check if pw expired (flag set in auth)
2967c478bd9Sstevel@tonic-gate * - warn user if pw is set to expire
2977c478bd9Sstevel@tonic-gate *
2987c478bd9Sstevel@tonic-gate * notes
2997c478bd9Sstevel@tonic-gate * - we require the auth module to have already run (sets module data)
3007c478bd9Sstevel@tonic-gate * - we don't worry about an expired princ cuz if that's the case,
3017c478bd9Sstevel@tonic-gate * auth would have failed
3027c478bd9Sstevel@tonic-gate */
3037c478bd9Sstevel@tonic-gate int
pam_sm_acct_mgmt(pam_handle_t * pamh,int flags,int argc,const char ** argv)304*cbea7acaSDominik Hassler pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
3057c478bd9Sstevel@tonic-gate {
306*cbea7acaSDominik Hassler const char *user = NULL;
3077c478bd9Sstevel@tonic-gate char *userdata = NULL;
3087c478bd9Sstevel@tonic-gate int err;
3097c478bd9Sstevel@tonic-gate int i;
3107c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd = NULL;
3117c478bd9Sstevel@tonic-gate char messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
3127c478bd9Sstevel@tonic-gate int debug = 0; /* pam.conf entry option */
3137c478bd9Sstevel@tonic-gate int nowarn = 0; /* pam.conf entry option, no expire warnings */
314*cbea7acaSDominik Hassler const pam_repository_t *rep_data = NULL;
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) {
3177c478bd9Sstevel@tonic-gate if (strcasecmp(argv[i], "debug") == 0)
3187c478bd9Sstevel@tonic-gate debug = 1;
3197c478bd9Sstevel@tonic-gate else if (strcasecmp(argv[i], "nowarn") == 0) {
3207c478bd9Sstevel@tonic-gate nowarn = 1;
3217c478bd9Sstevel@tonic-gate flags = flags | PAM_SILENT;
3227c478bd9Sstevel@tonic-gate } else {
3233bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR,
3247c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): illegal option %s",
3257c478bd9Sstevel@tonic-gate argv[i]);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate }
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate if (debug)
3303bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
3317c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): debug=%d, nowarn=%d",
3327c478bd9Sstevel@tonic-gate debug, nowarn);
3337c478bd9Sstevel@tonic-gate
334*cbea7acaSDominik Hassler (void) pam_get_item(pamh, PAM_REPOSITORY, (const void **)&rep_data);
3353bfb48feSsemery
3367c478bd9Sstevel@tonic-gate if (rep_data != NULL) {
3377c478bd9Sstevel@tonic-gate /*
3387c478bd9Sstevel@tonic-gate * If the repository is not ours,
3397c478bd9Sstevel@tonic-gate * return PAM_IGNORE.
3407c478bd9Sstevel@tonic-gate */
3417c478bd9Sstevel@tonic-gate if (strcmp(rep_data->type, KRB5_REPOSITORY_NAME) != 0) {
3427c478bd9Sstevel@tonic-gate if (debug)
3433bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
3443bfb48feSsemery "PAM-KRB5 (acct): wrong"
3457c478bd9Sstevel@tonic-gate "repository found (%s), returning "
3467c478bd9Sstevel@tonic-gate "PAM_IGNORE", rep_data->type);
3477c478bd9Sstevel@tonic-gate return (PAM_IGNORE);
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate
3527c478bd9Sstevel@tonic-gate /* get user name */
353*cbea7acaSDominik Hassler (void) pam_get_item(pamh, PAM_USER, (const void **)&user);
3547c478bd9Sstevel@tonic-gate
3553bfb48feSsemery if (user == NULL || *user == '\0') {
3567c478bd9Sstevel@tonic-gate err = PAM_USER_UNKNOWN;
3577c478bd9Sstevel@tonic-gate goto out;
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate /* get pam_krb5_migrate specific data */
3617c478bd9Sstevel@tonic-gate err = pam_get_data(pamh, KRB5_AUTOMIGRATE_DATA,
3627c478bd9Sstevel@tonic-gate (const void **)&userdata);
3637c478bd9Sstevel@tonic-gate if (err != PAM_SUCCESS) {
3647c478bd9Sstevel@tonic-gate if (debug)
3653bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, "PAM-KRB5 (acct): "
3663bfb48feSsemery "no module data for KRB5_AUTOMIGRATE_DATA");
3677c478bd9Sstevel@tonic-gate } else {
3687c478bd9Sstevel@tonic-gate /*
3697c478bd9Sstevel@tonic-gate * We try and reauthenticate, since this user has a
3707c478bd9Sstevel@tonic-gate * newly created krb5 principal via the pam_krb5_migrate
3717c478bd9Sstevel@tonic-gate * auth module. That way, this new user will have fresh
3727c478bd9Sstevel@tonic-gate * creds (assuming pam_sm_authenticate() succeeds).
3737c478bd9Sstevel@tonic-gate */
3747c478bd9Sstevel@tonic-gate if (strcmp(user, userdata) == 0)
375*cbea7acaSDominik Hassler (void) pam_sm_authenticate(pamh, flags, argc, argv);
3767c478bd9Sstevel@tonic-gate else
3777c478bd9Sstevel@tonic-gate if (debug)
3783bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
3797c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): PAM_USER %s"
3803bfb48feSsemery "does not match user %s from pam_get_data()",
3817c478bd9Sstevel@tonic-gate user, (char *)userdata);
3827c478bd9Sstevel@tonic-gate }
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate /* get krb5 module data */
3857c478bd9Sstevel@tonic-gate if ((err = pam_get_data(pamh, KRB5_DATA, (const void **)&kmd))
3867c478bd9Sstevel@tonic-gate != PAM_SUCCESS) {
3877c478bd9Sstevel@tonic-gate if (err == PAM_NO_MODULE_DATA) {
3887c478bd9Sstevel@tonic-gate /*
3897c478bd9Sstevel@tonic-gate * pam_auth never called (possible config
390ed19839eSsemery * error; no pam_krb5 auth entry in pam.conf),
3917c478bd9Sstevel@tonic-gate */
392ed19839eSsemery if (debug) {
3933bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
3947c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): no module data");
395ed19839eSsemery }
3967c478bd9Sstevel@tonic-gate err = PAM_IGNORE;
3977c478bd9Sstevel@tonic-gate goto out;
3987c478bd9Sstevel@tonic-gate } else {
3993bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR,
4007c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): get module"
4013bfb48feSsemery " data failed: err=%d",
4027c478bd9Sstevel@tonic-gate err);
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate goto out;
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate debug = debug || kmd->debug;
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate * auth mod set status to ignore, most likely cuz root key is
4117c478bd9Sstevel@tonic-gate * in keytab, so skip other checks and return ignore
4127c478bd9Sstevel@tonic-gate */
4137c478bd9Sstevel@tonic-gate if (kmd->auth_status == PAM_IGNORE) {
4147c478bd9Sstevel@tonic-gate if (debug)
4153bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
4167c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): kmd auth_status is IGNORE");
4177c478bd9Sstevel@tonic-gate err = PAM_IGNORE;
4187c478bd9Sstevel@tonic-gate goto out;
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate /*
422ed19839eSsemery * If there is no Kerberos related user and there is authentication
423ed19839eSsemery * data, this means that while the user has successfully passed
424ed19839eSsemery * authentication, Kerberos is not the account authority because there
425ed19839eSsemery * is no valid Kerberos principal. PAM_IGNORE is returned since
426ed19839eSsemery * Kerberos is not authoritative for this user. Other modules in the
427ed19839eSsemery * account stack will need to determine the success or failure for this
428ed19839eSsemery * user.
4293bfb48feSsemery */
4303bfb48feSsemery if (kmd->auth_status == PAM_USER_UNKNOWN) {
4313bfb48feSsemery if (debug)
4323bfb48feSsemery syslog(LOG_DEBUG,
4333bfb48feSsemery "PAM-KRB5 (acct): kmd auth_status is USER UNKNOWN");
434ed19839eSsemery err = PAM_IGNORE;
4353bfb48feSsemery goto out;
4363bfb48feSsemery }
4373bfb48feSsemery
4383bfb48feSsemery /*
4397c478bd9Sstevel@tonic-gate * age_status will be set to PAM_NEW_AUTHTOK_REQD in pam_krb5's
4407c478bd9Sstevel@tonic-gate * 'auth' if the user's key/pw has expired and needs to be changed
4417c478bd9Sstevel@tonic-gate */
4427c478bd9Sstevel@tonic-gate if (kmd->age_status == PAM_NEW_AUTHTOK_REQD) {
4437c478bd9Sstevel@tonic-gate if (!nowarn) {
4447c478bd9Sstevel@tonic-gate (void) snprintf(messages[0], sizeof (messages[0]),
4457c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN,
4467c478bd9Sstevel@tonic-gate "Your Kerberos password has expired.\n"));
4477c478bd9Sstevel@tonic-gate (void) __pam_display_msg(pamh, PAM_TEXT_INFO,
4487c478bd9Sstevel@tonic-gate 1, messages, NULL);
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate err = PAM_NEW_AUTHTOK_REQD;
4517c478bd9Sstevel@tonic-gate goto out;
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate
454ed19839eSsemery if (kmd->auth_status == PAM_SUCCESS && !(flags & PAM_SILENT) &&
455ed19839eSsemery !nowarn && kmd->password) {
4567c478bd9Sstevel@tonic-gate /* if we fail, let it slide, it's only a warning brah */
4573125ebfcSsemery (void) exp_warn(pamh, user, kmd, debug);
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate
4603bfb48feSsemery /*
461ed19839eSsemery * If Kerberos is treated as optional in the PAM stack, it is possible
462ed19839eSsemery * that there is a KRB5_DATA item and a non-Kerberos account authority.
463ed19839eSsemery * In that case, PAM_IGNORE is returned.
4643bfb48feSsemery */
465ed19839eSsemery err = kmd->auth_status != PAM_SUCCESS ? PAM_IGNORE : kmd->auth_status;
4667c478bd9Sstevel@tonic-gate
4677c478bd9Sstevel@tonic-gate out:
4687c478bd9Sstevel@tonic-gate if (debug)
4693bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG,
4707c478bd9Sstevel@tonic-gate "PAM-KRB5 (acct): end: %s", pam_strerror(pamh, err));
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate return (err);
4737c478bd9Sstevel@tonic-gate }
474