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 5a0709436Smp * Common Development and Distribution License (the "License"). 6a0709436Smp * 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 /* 22*3bfb48feSsemery * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 297c478bd9Sstevel@tonic-gate #include <security/pam_modules.h> 307c478bd9Sstevel@tonic-gate #include <security/pam_impl.h> 317c478bd9Sstevel@tonic-gate #include <string.h> 327c478bd9Sstevel@tonic-gate #include <stdio.h> 337c478bd9Sstevel@tonic-gate #include <stdlib.h> 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate #include <sys/stat.h> 367c478bd9Sstevel@tonic-gate #include <pwd.h> 377c478bd9Sstevel@tonic-gate #include <syslog.h> 387c478bd9Sstevel@tonic-gate #include <libintl.h> 397c478bd9Sstevel@tonic-gate #include <k5-int.h> 407c478bd9Sstevel@tonic-gate #include "profile/prof_int.h" 417c478bd9Sstevel@tonic-gate #include <netdb.h> 427c478bd9Sstevel@tonic-gate #include <ctype.h> 437c478bd9Sstevel@tonic-gate #include "utils.h" 447c478bd9Sstevel@tonic-gate #include "krb5_repository.h" 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #define KRB5_DEFAULT_OPTIONS 0 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate int forwardable_flag = 0; 497c478bd9Sstevel@tonic-gate int renewable_flag = 0; 507c478bd9Sstevel@tonic-gate int proxiable_flag = 0; 517c478bd9Sstevel@tonic-gate int no_address_flag = 0; 527c478bd9Sstevel@tonic-gate profile_options_boolean config_option[] = { 537c478bd9Sstevel@tonic-gate { "forwardable", &forwardable_flag, 0 }, 547c478bd9Sstevel@tonic-gate { "renewable", &renewable_flag, 0 }, 557c478bd9Sstevel@tonic-gate { "proxiable", &proxiable_flag, 0 }, 567c478bd9Sstevel@tonic-gate { "no_addresses", &no_address_flag, 0 }, 577c478bd9Sstevel@tonic-gate { NULL, NULL, 0 } 587c478bd9Sstevel@tonic-gate }; 597c478bd9Sstevel@tonic-gate char *renew_timeval; 607c478bd9Sstevel@tonic-gate char *life_timeval; 617c478bd9Sstevel@tonic-gate profile_option_strings config_times[] = { 627c478bd9Sstevel@tonic-gate { "max_life", &life_timeval, 0 }, 637c478bd9Sstevel@tonic-gate { "max_renewable_life", &renew_timeval, 0 }, 647c478bd9Sstevel@tonic-gate { NULL, NULL, 0 } 657c478bd9Sstevel@tonic-gate }; 667c478bd9Sstevel@tonic-gate char *realmdef[] = { "realms", NULL, NULL, NULL }; 677c478bd9Sstevel@tonic-gate char *appdef[] = { "appdefaults", "kinit", NULL }; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate #define krb_realm (*(realmdef + 1)) 707c478bd9Sstevel@tonic-gate 712278144aSsemery int attempt_krb5_auth(krb5_module_data_t *, char *, char **, boolean_t); 727c478bd9Sstevel@tonic-gate void krb5_cleanup(pam_handle_t *, void *, int); 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate extern errcode_t profile_get_options_boolean(); 757c478bd9Sstevel@tonic-gate extern errcode_t profile_get_options_string(); 762278144aSsemery extern int krb5_verifypw(char *, char *, int); 777c478bd9Sstevel@tonic-gate extern krb5_error_code krb5_verify_init_creds(krb5_context, 787c478bd9Sstevel@tonic-gate krb5_creds *, krb5_principal, krb5_keytab, krb5_ccache *, 797c478bd9Sstevel@tonic-gate krb5_verify_init_creds_opt *); 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate /* 827c478bd9Sstevel@tonic-gate * pam_sm_authenticate - Authenticate user 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate int 857c478bd9Sstevel@tonic-gate pam_sm_authenticate( 867c478bd9Sstevel@tonic-gate pam_handle_t *pamh, 877c478bd9Sstevel@tonic-gate int flags, 887c478bd9Sstevel@tonic-gate int argc, 897c478bd9Sstevel@tonic-gate const char **argv) 907c478bd9Sstevel@tonic-gate { 910be37caaSsemery char *user = NULL; 927c478bd9Sstevel@tonic-gate int err; 937c478bd9Sstevel@tonic-gate int result = PAM_AUTH_ERR; 947c478bd9Sstevel@tonic-gate /* pam.conf options */ 957c478bd9Sstevel@tonic-gate int debug = 0; 967c478bd9Sstevel@tonic-gate int warn = 1; 977c478bd9Sstevel@tonic-gate /* return an error on password expire */ 987c478bd9Sstevel@tonic-gate int err_on_exp = 0; 997c478bd9Sstevel@tonic-gate int i; 1007c478bd9Sstevel@tonic-gate char *password = NULL; 1017c478bd9Sstevel@tonic-gate uid_t pw_uid; 1027c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd = NULL; 1037c478bd9Sstevel@tonic-gate krb5_repository_data_t *krb5_data = NULL; 1047c478bd9Sstevel@tonic-gate pam_repository_t *rep_data = NULL; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 1077c478bd9Sstevel@tonic-gate if (strcmp(argv[i], "debug") == 0) { 1087c478bd9Sstevel@tonic-gate debug = 1; 1097c478bd9Sstevel@tonic-gate } else if (strcmp(argv[i], "nowarn") == 0) { 1107c478bd9Sstevel@tonic-gate warn = 0; 1117c478bd9Sstevel@tonic-gate } else if (strcmp(argv[i], "err_on_exp") == 0) { 1127c478bd9Sstevel@tonic-gate err_on_exp = 1; 1137c478bd9Sstevel@tonic-gate } else { 114*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 115*3bfb48feSsemery "PAM-KRB5 (auth) unrecognized option %s", 1167c478bd9Sstevel@tonic-gate argv[i]); 1177c478bd9Sstevel@tonic-gate } 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate if (flags & PAM_SILENT) warn = 0; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate if (debug) 122*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 1237c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): pam_sm_authenticate flags=%d", 1247c478bd9Sstevel@tonic-gate flags); 1257c478bd9Sstevel@tonic-gate 1260be37caaSsemery (void) pam_get_item(pamh, PAM_USER, (void**) &user); 1277c478bd9Sstevel@tonic-gate 128a0e56b0eSsemery if (user == NULL || *user == '\0') { 1297c478bd9Sstevel@tonic-gate if (debug) 130*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 131*3bfb48feSsemery "PAM-KRB5 (auth): user empty or null"); 132a0e56b0eSsemery return (PAM_USER_UNKNOWN); 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* make sure a password entry exists for this user */ 1360be37caaSsemery if (!get_pw_uid(user, &pw_uid)) 1370be37caaSsemery return (PAM_USER_UNKNOWN); 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* 1407c478bd9Sstevel@tonic-gate * pam_get_data could fail if we are being called for the first time 1417c478bd9Sstevel@tonic-gate * or if the module is not found, PAM_NO_MODULE_DATA is not an error 1427c478bd9Sstevel@tonic-gate */ 1437c478bd9Sstevel@tonic-gate err = pam_get_data(pamh, KRB5_DATA, (const void**)&kmd); 1447c478bd9Sstevel@tonic-gate if (!(err == PAM_SUCCESS || err == PAM_NO_MODULE_DATA)) 145*3bfb48feSsemery return (PAM_SYSTEM_ERR); 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate if (kmd == NULL) { 1487c478bd9Sstevel@tonic-gate kmd = calloc(1, sizeof (krb5_module_data_t)); 1497c478bd9Sstevel@tonic-gate if (kmd == NULL) { 1507c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 1517c478bd9Sstevel@tonic-gate goto out; 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate err = pam_set_data(pamh, KRB5_DATA, kmd, &krb5_cleanup); 1557c478bd9Sstevel@tonic-gate if (err != PAM_SUCCESS) { 1567c478bd9Sstevel@tonic-gate free(kmd); 1577c478bd9Sstevel@tonic-gate result = err; 1587c478bd9Sstevel@tonic-gate goto out; 1597c478bd9Sstevel@tonic-gate } 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate if (!kmd->env) { 1637c478bd9Sstevel@tonic-gate char buffer[512]; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate if (snprintf(buffer, sizeof (buffer), 1667c478bd9Sstevel@tonic-gate "%s=FILE:/tmp/krb5cc_%d", 1677c478bd9Sstevel@tonic-gate KRB5_ENV_CCNAME, (int)pw_uid) >= sizeof (buffer)) { 1687c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 1697c478bd9Sstevel@tonic-gate goto out; 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* we MUST copy this to the heap for the putenv to work! */ 1737c478bd9Sstevel@tonic-gate kmd->env = strdup(buffer); 1747c478bd9Sstevel@tonic-gate if (!kmd->env) { 1757c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 1767c478bd9Sstevel@tonic-gate goto out; 1777c478bd9Sstevel@tonic-gate } else { 1787c478bd9Sstevel@tonic-gate if (putenv(kmd->env)) { 1797c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 1807c478bd9Sstevel@tonic-gate goto out; 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate } 1847c478bd9Sstevel@tonic-gate 185*3bfb48feSsemery if ((kmd->user = strdup(user)) == NULL) { 186*3bfb48feSsemery result = PAM_BUF_ERR; 187*3bfb48feSsemery goto out; 188*3bfb48feSsemery } 189*3bfb48feSsemery 1907c478bd9Sstevel@tonic-gate kmd->auth_status = PAM_AUTH_ERR; 1917c478bd9Sstevel@tonic-gate kmd->debug = debug; 1927c478bd9Sstevel@tonic-gate kmd->warn = warn; 1937c478bd9Sstevel@tonic-gate kmd->err_on_exp = err_on_exp; 1947c478bd9Sstevel@tonic-gate kmd->ccache = NULL; 1957c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 1967c478bd9Sstevel@tonic-gate kmd->password = NULL; 1977c478bd9Sstevel@tonic-gate kmd->age_status = PAM_SUCCESS; 1987c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gate /* 2017c478bd9Sstevel@tonic-gate * For apps that already did krb5 auth exchange... 2027c478bd9Sstevel@tonic-gate * Now that we've created the kmd structure, we can 2037c478bd9Sstevel@tonic-gate * return SUCCESS. 'kmd' may be needed later by other 2047c478bd9Sstevel@tonic-gate * PAM functions, thats why we wait until this point to 2057c478bd9Sstevel@tonic-gate * return. 2067c478bd9Sstevel@tonic-gate */ 2070be37caaSsemery (void) pam_get_item(pamh, PAM_REPOSITORY, (void **)&rep_data); 2087c478bd9Sstevel@tonic-gate 2097c478bd9Sstevel@tonic-gate if (rep_data != NULL) { 2107c478bd9Sstevel@tonic-gate if (strcmp(rep_data->type, KRB5_REPOSITORY_NAME) != 0) { 2117c478bd9Sstevel@tonic-gate if (debug) 212*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 213*3bfb48feSsemery "PAM-KRB5 (auth): wrong" 2147c478bd9Sstevel@tonic-gate "repository found (%s), returning " 2157c478bd9Sstevel@tonic-gate "PAM_IGNORE", rep_data->type); 2167c478bd9Sstevel@tonic-gate return (PAM_IGNORE); 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate if (rep_data->scope_len == sizeof (krb5_repository_data_t)) { 2197c478bd9Sstevel@tonic-gate krb5_data = (krb5_repository_data_t *)rep_data->scope; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate if (krb5_data->flags == 2227c478bd9Sstevel@tonic-gate SUNW_PAM_KRB5_ALREADY_AUTHENTICATED && 2237c478bd9Sstevel@tonic-gate krb5_data->principal != NULL && 2247c478bd9Sstevel@tonic-gate strlen(krb5_data->principal)) { 2257c478bd9Sstevel@tonic-gate if (debug) 226*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2277c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Principal " 2287c478bd9Sstevel@tonic-gate "%s already authenticated", 2297c478bd9Sstevel@tonic-gate krb5_data->principal); 2307c478bd9Sstevel@tonic-gate kmd->auth_status = PAM_SUCCESS; 2317c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 2327c478bd9Sstevel@tonic-gate } 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate } 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate /* 2377c478bd9Sstevel@tonic-gate * if root key exists in the keytab, it's a random key so no 2387c478bd9Sstevel@tonic-gate * need to prompt for pw and we just return IGNORE. 2397c478bd9Sstevel@tonic-gate * 2407c478bd9Sstevel@tonic-gate * note we don't need to force a prompt for pw as authtok_get 2417c478bd9Sstevel@tonic-gate * is required to be stacked above this module. 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate if ((strcmp(user, ROOT_UNAME) == 0) && 2447c478bd9Sstevel@tonic-gate key_in_keytab(user, debug)) { 2457c478bd9Sstevel@tonic-gate if (debug) 246*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2477c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): " 2487c478bd9Sstevel@tonic-gate "key for '%s' in keytab, returning IGNORE", user); 2497c478bd9Sstevel@tonic-gate result = PAM_IGNORE; 2507c478bd9Sstevel@tonic-gate goto out; 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2530be37caaSsemery (void) pam_get_item(pamh, PAM_AUTHTOK, (void **)&password); 2547c478bd9Sstevel@tonic-gate 2552278144aSsemery result = attempt_krb5_auth(kmd, user, &password, 1); 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate out: 2587c478bd9Sstevel@tonic-gate if (kmd) { 2597c478bd9Sstevel@tonic-gate if (debug) 260*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2617c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): pam_sm_auth finalize" 2627c478bd9Sstevel@tonic-gate " ccname env, result =%d, env ='%s'," 2637c478bd9Sstevel@tonic-gate " age = %d, status = %d", 2647c478bd9Sstevel@tonic-gate result, kmd->env ? kmd->env : "<null>", 2657c478bd9Sstevel@tonic-gate kmd->age_status, kmd->auth_status); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate if (kmd->env && 2687c478bd9Sstevel@tonic-gate !(kmd->age_status == PAM_NEW_AUTHTOK_REQD && 2697c478bd9Sstevel@tonic-gate kmd->auth_status == PAM_SUCCESS)) { 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate if (result == PAM_SUCCESS) { 2737c478bd9Sstevel@tonic-gate /* 2747c478bd9Sstevel@tonic-gate * Put ccname into the pamh so that login 2757c478bd9Sstevel@tonic-gate * apps can pick this up when they run 2767c478bd9Sstevel@tonic-gate * pam_getenvlist(). 2777c478bd9Sstevel@tonic-gate */ 2787c478bd9Sstevel@tonic-gate if ((result = pam_putenv(pamh, kmd->env)) 2797c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 2807c478bd9Sstevel@tonic-gate /* should not happen but... */ 281*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 2827c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth):" 283*3bfb48feSsemery " pam_putenv failed: result: %d", 2847c478bd9Sstevel@tonic-gate result); 2857c478bd9Sstevel@tonic-gate goto cleanupccname; 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate } else { 2887c478bd9Sstevel@tonic-gate cleanupccname: 2897c478bd9Sstevel@tonic-gate /* for lack of a Solaris unputenv() */ 2907c478bd9Sstevel@tonic-gate krb5_unsetenv(KRB5_ENV_CCNAME); 2917c478bd9Sstevel@tonic-gate free(kmd->env); 2927c478bd9Sstevel@tonic-gate kmd->env = NULL; 2937c478bd9Sstevel@tonic-gate } 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate kmd->auth_status = result; 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate if (debug) 299*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3007c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): end: %s", pam_strerror(pamh, result)); 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate return (result); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate int 3067c478bd9Sstevel@tonic-gate attempt_krb5_auth( 3077c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd, 3087c478bd9Sstevel@tonic-gate char *user, 3097c478bd9Sstevel@tonic-gate char **krb5_pass, 3100be37caaSsemery boolean_t verify_tik) 3117c478bd9Sstevel@tonic-gate { 3127c478bd9Sstevel@tonic-gate krb5_principal me = NULL; 3137c478bd9Sstevel@tonic-gate krb5_principal server = NULL; 3147c478bd9Sstevel@tonic-gate krb5_creds *my_creds; 3157c478bd9Sstevel@tonic-gate krb5_timestamp now; 3167c478bd9Sstevel@tonic-gate krb5_error_code code = 0; 3177c478bd9Sstevel@tonic-gate char kuser[2*MAXHOSTNAMELEN]; 3187c478bd9Sstevel@tonic-gate krb5_deltat lifetime; 3197c478bd9Sstevel@tonic-gate krb5_deltat rlife; 3207c478bd9Sstevel@tonic-gate krb5_deltat krb5_max_duration; 3217c478bd9Sstevel@tonic-gate int options = KRB5_DEFAULT_OPTIONS; 3227c478bd9Sstevel@tonic-gate krb5_data tgtname = { 3237c478bd9Sstevel@tonic-gate 0, 3247c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE, 3257c478bd9Sstevel@tonic-gate KRB5_TGS_NAME 3267c478bd9Sstevel@tonic-gate }; 3277c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt opts; 3287c478bd9Sstevel@tonic-gate /* 3297c478bd9Sstevel@tonic-gate * "result" should not be assigned PAM_SUCCESS unless 3307c478bd9Sstevel@tonic-gate * authentication has succeeded and there are no other errors. 3317c478bd9Sstevel@tonic-gate * 3327c478bd9Sstevel@tonic-gate * "code" is sometimes used for PAM codes, sometimes for krb5 3337c478bd9Sstevel@tonic-gate * codes. Be careful. 3347c478bd9Sstevel@tonic-gate */ 3357c478bd9Sstevel@tonic-gate int result = PAM_AUTH_ERR; 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate if (kmd->debug) 338*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3397c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: start: user='%s'", 3407c478bd9Sstevel@tonic-gate user ? user : "<null>"); 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_init(&opts); 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* need to free context with krb5_free_context */ 3457c478bd9Sstevel@tonic-gate if (code = krb5_init_context(&kmd->kcontext)) { 346*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 3477c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Error initializing " 348*3bfb48feSsemery "krb5: %s", 3497c478bd9Sstevel@tonic-gate error_message(code)); 3507c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate if ((code = get_kmd_kuser(kmd->kcontext, (const char *)user, kuser, 3547c478bd9Sstevel@tonic-gate 2*MAXHOSTNAMELEN)) != 0) { 3557c478bd9Sstevel@tonic-gate /* get_kmd_kuser returns proper PAM error statuses */ 3567c478bd9Sstevel@tonic-gate return (code); 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate if ((code = krb5_parse_name(kmd->kcontext, kuser, &me)) != 0) { 3607c478bd9Sstevel@tonic-gate krb5_free_context(kmd->kcontext); 3617c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 362*3bfb48feSsemery return (PAM_SYSTEM_ERR); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate /* call krb5_free_cred_contents() on error */ 3667c478bd9Sstevel@tonic-gate my_creds = &kmd->initcreds; 3677c478bd9Sstevel@tonic-gate 368*3bfb48feSsemery if ((code = 369*3bfb48feSsemery krb5_copy_principal(kmd->kcontext, me, &my_creds->client))) { 370*3bfb48feSsemery result = PAM_SYSTEM_ERR; 371*3bfb48feSsemery goto out_err; 372*3bfb48feSsemery } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate if (code = krb5_build_principal_ext(kmd->kcontext, &server, 3757c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 3767c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 3777c478bd9Sstevel@tonic-gate tgtname.length, tgtname.data, 3787c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 3797c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 0)) { 380*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 381*3bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth: " 382*3bfb48feSsemery "krb5_build_princ_ext failed: %s", 383*3bfb48feSsemery error_message(code)); 384*3bfb48feSsemery result = PAM_SYSTEM_ERR; 3857c478bd9Sstevel@tonic-gate goto out; 3867c478bd9Sstevel@tonic-gate } 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate if (code = krb5_copy_principal(kmd->kcontext, server, 3897c478bd9Sstevel@tonic-gate &my_creds->server)) { 390*3bfb48feSsemery result = PAM_SYSTEM_ERR; 3917c478bd9Sstevel@tonic-gate goto out_err; 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate if (code = krb5_timeofday(kmd->kcontext, &now)) { 395*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 396*3bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth: " 397*3bfb48feSsemery "krb5_timeofday failed: %s", 398*3bfb48feSsemery error_message(code)); 399*3bfb48feSsemery result = PAM_SYSTEM_ERR; 4007c478bd9Sstevel@tonic-gate goto out; 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /* 4047c478bd9Sstevel@tonic-gate * set the values for lifetime and rlife to be the maximum 4057c478bd9Sstevel@tonic-gate * possible 4067c478bd9Sstevel@tonic-gate */ 4077c478bd9Sstevel@tonic-gate krb5_max_duration = KRB5_KDB_EXPIRATION - now - 60*60; 4087c478bd9Sstevel@tonic-gate lifetime = krb5_max_duration; 4097c478bd9Sstevel@tonic-gate rlife = krb5_max_duration; 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate /* 4127c478bd9Sstevel@tonic-gate * Let us get the values for various options 4137c478bd9Sstevel@tonic-gate * from Kerberos configuration file 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate krb_realm = krb5_princ_realm(kmd->kcontext, me)->data; 4177c478bd9Sstevel@tonic-gate profile_get_options_boolean(kmd->kcontext->profile, 4187c478bd9Sstevel@tonic-gate realmdef, config_option); 4197c478bd9Sstevel@tonic-gate profile_get_options_boolean(kmd->kcontext->profile, 4207c478bd9Sstevel@tonic-gate appdef, config_option); 4217c478bd9Sstevel@tonic-gate profile_get_options_string(kmd->kcontext->profile, 4227c478bd9Sstevel@tonic-gate realmdef, config_times); 4237c478bd9Sstevel@tonic-gate profile_get_options_string(kmd->kcontext->profile, 4247c478bd9Sstevel@tonic-gate appdef, config_times); 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate if (renew_timeval) { 4277c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(renew_timeval, &rlife); 4287c478bd9Sstevel@tonic-gate if (code != 0 || rlife == 0 || rlife > krb5_max_duration) { 429*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4307c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Bad max_renewable_life " 431*3bfb48feSsemery " value '%s' in Kerberos config file", 4327c478bd9Sstevel@tonic-gate renew_timeval); 4337c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 4347c478bd9Sstevel@tonic-gate goto out; 4357c478bd9Sstevel@tonic-gate } 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate if (life_timeval) { 4387c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(life_timeval, &lifetime); 4397c478bd9Sstevel@tonic-gate if (code != 0 || lifetime == 0 || 4407c478bd9Sstevel@tonic-gate lifetime > krb5_max_duration) { 441*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 442*3bfb48feSsemery "lifetime value '%s' in Kerberos config file", 4437c478bd9Sstevel@tonic-gate life_timeval); 4447c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 4457c478bd9Sstevel@tonic-gate goto out; 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate } 4487c478bd9Sstevel@tonic-gate /* start timer when request gets to KDC */ 4497c478bd9Sstevel@tonic-gate my_creds->times.starttime = 0; 4507c478bd9Sstevel@tonic-gate my_creds->times.endtime = now + lifetime; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate if (options & KDC_OPT_RENEWABLE) { 4537c478bd9Sstevel@tonic-gate my_creds->times.renew_till = now + rlife; 4547c478bd9Sstevel@tonic-gate } else 4557c478bd9Sstevel@tonic-gate my_creds->times.renew_till = 0; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime); 4587c478bd9Sstevel@tonic-gate 4597c478bd9Sstevel@tonic-gate if (proxiable_flag) { /* Set in config file */ 4607c478bd9Sstevel@tonic-gate if (kmd->debug) 461*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4627c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Proxiable tickets " 463*3bfb48feSsemery "requested"); 4647c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_proxiable(&opts, TRUE); 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate if (forwardable_flag) { 4677c478bd9Sstevel@tonic-gate if (kmd->debug) 468*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4697c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Forwardable tickets " 470*3bfb48feSsemery "requested"); 4717c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_forwardable(&opts, TRUE); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate if (renewable_flag) { 4747c478bd9Sstevel@tonic-gate if (kmd->debug) 475*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4767c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Renewable tickets " 477*3bfb48feSsemery "requested"); 4787c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_renew_life(&opts, rlife); 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate if (no_address_flag) { 4817c478bd9Sstevel@tonic-gate if (kmd->debug) 482*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4837c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Addressless tickets " 484*3bfb48feSsemery "requested"); 4857c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_address_list(&opts, NULL); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate /* 4897c478bd9Sstevel@tonic-gate * mech_krb5 interprets empty passwords as NULL passwords 4907c478bd9Sstevel@tonic-gate * and tries to read a password from stdin. Since we are in 4917c478bd9Sstevel@tonic-gate * pam this is bad and should not be allowed. 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate if (*krb5_pass == NULL || strlen(*krb5_pass) == 0) { 4947c478bd9Sstevel@tonic-gate code = KRB5KRB_AP_ERR_BAD_INTEGRITY; 4957c478bd9Sstevel@tonic-gate } else { 4967c478bd9Sstevel@tonic-gate code = krb5_get_init_creds_password(kmd->kcontext, 4977c478bd9Sstevel@tonic-gate my_creds, 4987c478bd9Sstevel@tonic-gate me, 4997c478bd9Sstevel@tonic-gate *krb5_pass, /* clear text passwd */ 5007c478bd9Sstevel@tonic-gate NULL, /* prompter */ 5017c478bd9Sstevel@tonic-gate NULL, /* data */ 5027c478bd9Sstevel@tonic-gate 0, /* start time */ 5037c478bd9Sstevel@tonic-gate NULL, /* defaults to krbtgt@REALM */ 5047c478bd9Sstevel@tonic-gate &opts); 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate if (kmd->debug) 508*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 5097c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: " 5107c478bd9Sstevel@tonic-gate "krb5_get_init_creds_password returns: %s", 5117c478bd9Sstevel@tonic-gate code == 0 ? "SUCCESS" : error_message(code)); 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate switch (code) { 5147c478bd9Sstevel@tonic-gate case 0: 5157c478bd9Sstevel@tonic-gate /* got a tgt, let's verify it */ 5167c478bd9Sstevel@tonic-gate if (verify_tik) { 5177c478bd9Sstevel@tonic-gate krb5_verify_init_creds_opt vopts; 5187c478bd9Sstevel@tonic-gate 519a0709436Smp krb5_principal sp = NULL; 520a0709436Smp char kt_name[MAX_KEYTAB_NAME_LEN]; 521a0709436Smp char *fqdn; 522a0709436Smp 5237c478bd9Sstevel@tonic-gate krb5_verify_init_creds_opt_init(&vopts); 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate code = krb5_verify_init_creds(kmd->kcontext, 5267c478bd9Sstevel@tonic-gate my_creds, 5277c478bd9Sstevel@tonic-gate NULL, /* defaults to host/localhost@REALM */ 5287c478bd9Sstevel@tonic-gate NULL, 5297c478bd9Sstevel@tonic-gate NULL, 5307c478bd9Sstevel@tonic-gate &vopts); 5317c478bd9Sstevel@tonic-gate 5327c478bd9Sstevel@tonic-gate if (code) { 5337c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 5347c478bd9Sstevel@tonic-gate 5350be37caaSsemery /* 5360be37caaSsemery * Give a better error message when the 5370be37caaSsemery * keytable entry isn't found or the keytab 5380be37caaSsemery * file cannot be found. 5390be37caaSsemery */ 540a0709436Smp if (krb5_sname_to_principal(kmd->kcontext, NULL, 541a0709436Smp NULL, KRB5_NT_SRV_HST, &sp)) 542a0709436Smp fqdn = "<fqdn>"; 543a0709436Smp else 544a0709436Smp fqdn = sp->data[1].data; 545a0709436Smp 546a0709436Smp if (krb5_kt_default_name(kmd->kcontext, kt_name, 547a0709436Smp sizeof (kt_name))) 548a0709436Smp (void) strncpy(kt_name, 549a0709436Smp "default keytab", 550a0709436Smp sizeof (kt_name)); 551a0709436Smp 552a0709436Smp switch (code) { 553a0709436Smp case KRB5_KT_NOTFOUND: 554*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 555a0709436Smp "PAM-KRB5 (auth): " 556a0709436Smp "krb5_verify_init_creds failed:" 557a0709436Smp " Key table entry \"host/%s\"" 558*3bfb48feSsemery " not found in %s", 559a0709436Smp fqdn, kt_name); 560a0709436Smp break; 561a0709436Smp case ENOENT: 562*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 563a0709436Smp "PAM-KRB5 (auth): " 564a0709436Smp "krb5_verify_init_creds failed:" 565a0709436Smp " Keytab file \"%s\"" 566*3bfb48feSsemery " does not exist.\n", 567a0709436Smp kt_name); 568a0709436Smp break; 569a0709436Smp default: 570*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 571a0709436Smp "PAM-KRB5 (auth): " 572a0709436Smp "krb5_verify_init_creds failed:" 573*3bfb48feSsemery " %s", 574a0709436Smp error_message(code)); 575a0709436Smp break; 576a0709436Smp } 577a0709436Smp 578a0709436Smp if (sp) 579a0709436Smp krb5_free_principal(kmd->kcontext, sp); 5807c478bd9Sstevel@tonic-gate } 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate break; 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: 5857c478bd9Sstevel@tonic-gate /* 5867c478bd9Sstevel@tonic-gate * Since this principal is not part of the local 5877c478bd9Sstevel@tonic-gate * Kerberos realm, we just return PAM_USER_UNKNOWN. 5887c478bd9Sstevel@tonic-gate */ 5897c478bd9Sstevel@tonic-gate result = PAM_USER_UNKNOWN; 5907c478bd9Sstevel@tonic-gate 5917c478bd9Sstevel@tonic-gate if (kmd->debug) 592*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 593*3bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth:" 5947c478bd9Sstevel@tonic-gate " User is not part of the local Kerberos" 5957c478bd9Sstevel@tonic-gate " realm: %s", error_message(code)); 5967c478bd9Sstevel@tonic-gate break; 5977c478bd9Sstevel@tonic-gate 5987c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_PREAUTH_FAILED: 5997c478bd9Sstevel@tonic-gate case KRB5KRB_AP_ERR_BAD_INTEGRITY: 6007c478bd9Sstevel@tonic-gate /* 6017c478bd9Sstevel@tonic-gate * We could be trying the password from a previous 6027c478bd9Sstevel@tonic-gate * pam authentication module, but we don't want to 6037c478bd9Sstevel@tonic-gate * generate an error if the unix password is different 6047c478bd9Sstevel@tonic-gate * than the Kerberos password... 6057c478bd9Sstevel@tonic-gate */ 6067c478bd9Sstevel@tonic-gate break; 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_KEY_EXP: 6097c478bd9Sstevel@tonic-gate if (!kmd->err_on_exp) { 6107c478bd9Sstevel@tonic-gate /* 6117c478bd9Sstevel@tonic-gate * Request a tik for changepw service 6127c478bd9Sstevel@tonic-gate * and it will tell us if pw is good or not. 6137c478bd9Sstevel@tonic-gate */ 6142278144aSsemery code = krb5_verifypw(kuser, *krb5_pass, kmd->debug); 6157c478bd9Sstevel@tonic-gate 6167c478bd9Sstevel@tonic-gate if (kmd->debug) 617*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6187c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: " 6192278144aSsemery "verifypw %d", code); 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate if (code == 0) { 6227c478bd9Sstevel@tonic-gate /* pw is good, set age status for acct_mgmt */ 6237c478bd9Sstevel@tonic-gate kmd->age_status = PAM_NEW_AUTHTOK_REQD; 6247c478bd9Sstevel@tonic-gate } 6257c478bd9Sstevel@tonic-gate } 6267c478bd9Sstevel@tonic-gate break; 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate default: 6297c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 6307c478bd9Sstevel@tonic-gate if (kmd->debug) 631*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 632*3bfb48feSsemery "PAM-KRB5 (auth): error %d - %s", 6337c478bd9Sstevel@tonic-gate code, error_message(code)); 6347c478bd9Sstevel@tonic-gate break; 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate if (code == 0) { 6387c478bd9Sstevel@tonic-gate /* 6397c478bd9Sstevel@tonic-gate * success for the entered pw 6407c478bd9Sstevel@tonic-gate * 6417c478bd9Sstevel@tonic-gate * we can't rely on the pw in PAM_AUTHTOK 6427c478bd9Sstevel@tonic-gate * to be the (correct) krb5 one so 6437c478bd9Sstevel@tonic-gate * store krb5 pw in module data for 6447c478bd9Sstevel@tonic-gate * use in acct_mgmt 6457c478bd9Sstevel@tonic-gate */ 6467c478bd9Sstevel@tonic-gate if (!(kmd->password = strdup(*krb5_pass))) { 647*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, "Cannot strdup password"); 6487c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 6497c478bd9Sstevel@tonic-gate goto out_err; 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate result = PAM_SUCCESS; 6527c478bd9Sstevel@tonic-gate goto out; 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate out_err: 6567c478bd9Sstevel@tonic-gate /* jump (or reach) here if error and cred cache has been init */ 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate if (kmd->debug) 659*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6607c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): clearing initcreds in " 6617c478bd9Sstevel@tonic-gate "pam_authenticate()"); 6627c478bd9Sstevel@tonic-gate 6637c478bd9Sstevel@tonic-gate krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 6647c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate out: 6677c478bd9Sstevel@tonic-gate if (server) 6687c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, server); 6697c478bd9Sstevel@tonic-gate if (me) 6707c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, me); 6717c478bd9Sstevel@tonic-gate if (kmd->kcontext) { 6727c478bd9Sstevel@tonic-gate krb5_free_context(kmd->kcontext); 6737c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate if (kmd->debug) 677*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6787c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth returning %d", 6797c478bd9Sstevel@tonic-gate result); 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate return (kmd->auth_status = result); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 6857c478bd9Sstevel@tonic-gate void 6867c478bd9Sstevel@tonic-gate krb5_cleanup(pam_handle_t *pamh, void *data, int pam_status) 6877c478bd9Sstevel@tonic-gate { 6887c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd = (krb5_module_data_t *)data; 6897c478bd9Sstevel@tonic-gate 6907c478bd9Sstevel@tonic-gate if (kmd == NULL) 6917c478bd9Sstevel@tonic-gate return; 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate if (kmd->debug) { 694*3bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 695*3bfb48feSsemery "PAM-KRB5 (auth): krb5_cleanup auth_status = %d", 6967c478bd9Sstevel@tonic-gate kmd->auth_status); 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate /* 7007c478bd9Sstevel@tonic-gate * if pam_status is PAM_SUCCESS, clean up based on value in 7017c478bd9Sstevel@tonic-gate * auth_status, otherwise just purge the context 7027c478bd9Sstevel@tonic-gate */ 7037c478bd9Sstevel@tonic-gate if ((pam_status == PAM_SUCCESS) && 7047c478bd9Sstevel@tonic-gate (kmd->auth_status == PAM_SUCCESS) && kmd->ccache) 7057c478bd9Sstevel@tonic-gate krb5_cc_close(kmd->kcontext, kmd->ccache); 7067c478bd9Sstevel@tonic-gate 7077c478bd9Sstevel@tonic-gate if (kmd->password) { 7087c478bd9Sstevel@tonic-gate (void) memset(kmd->password, 0, strlen(kmd->password)); 7097c478bd9Sstevel@tonic-gate free(kmd->password); 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate 712*3bfb48feSsemery if (kmd->user != NULL) 713*3bfb48feSsemery free(kmd->user); 714*3bfb48feSsemery 7157c478bd9Sstevel@tonic-gate if ((pam_status != PAM_SUCCESS) || 7167c478bd9Sstevel@tonic-gate (kmd->auth_status != PAM_SUCCESS)) { 7177c478bd9Sstevel@tonic-gate krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 7187c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate free(kmd); 7227c478bd9Sstevel@tonic-gate } 723