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 /* 223bfb48feSsemery * 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 *); 80*3125ebfcSsemery extern krb5_error_code __krb5_get_init_creds_password(krb5_context, 81*3125ebfcSsemery krb5_creds *, krb5_principal, char *, krb5_prompter_fct, void *, 82*3125ebfcSsemery krb5_deltat, char *, krb5_get_init_creds_opt *, 83*3125ebfcSsemery krb5_kdc_rep **); 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate /* 867c478bd9Sstevel@tonic-gate * pam_sm_authenticate - Authenticate user 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate int 897c478bd9Sstevel@tonic-gate pam_sm_authenticate( 907c478bd9Sstevel@tonic-gate pam_handle_t *pamh, 917c478bd9Sstevel@tonic-gate int flags, 927c478bd9Sstevel@tonic-gate int argc, 937c478bd9Sstevel@tonic-gate const char **argv) 947c478bd9Sstevel@tonic-gate { 950be37caaSsemery char *user = NULL; 967c478bd9Sstevel@tonic-gate int err; 977c478bd9Sstevel@tonic-gate int result = PAM_AUTH_ERR; 987c478bd9Sstevel@tonic-gate /* pam.conf options */ 997c478bd9Sstevel@tonic-gate int debug = 0; 1007c478bd9Sstevel@tonic-gate int warn = 1; 1017c478bd9Sstevel@tonic-gate /* return an error on password expire */ 1027c478bd9Sstevel@tonic-gate int err_on_exp = 0; 1037c478bd9Sstevel@tonic-gate int i; 1047c478bd9Sstevel@tonic-gate char *password = NULL; 1057c478bd9Sstevel@tonic-gate uid_t pw_uid; 1067c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd = NULL; 1077c478bd9Sstevel@tonic-gate krb5_repository_data_t *krb5_data = NULL; 1087c478bd9Sstevel@tonic-gate pam_repository_t *rep_data = NULL; 1097c478bd9Sstevel@tonic-gate 1107c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 1117c478bd9Sstevel@tonic-gate if (strcmp(argv[i], "debug") == 0) { 1127c478bd9Sstevel@tonic-gate debug = 1; 1137c478bd9Sstevel@tonic-gate } else if (strcmp(argv[i], "nowarn") == 0) { 1147c478bd9Sstevel@tonic-gate warn = 0; 1157c478bd9Sstevel@tonic-gate } else if (strcmp(argv[i], "err_on_exp") == 0) { 1167c478bd9Sstevel@tonic-gate err_on_exp = 1; 1177c478bd9Sstevel@tonic-gate } else { 1183bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 1193bfb48feSsemery "PAM-KRB5 (auth) unrecognized option %s", 1207c478bd9Sstevel@tonic-gate argv[i]); 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate if (flags & PAM_SILENT) warn = 0; 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate if (debug) 1263bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 1277c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): pam_sm_authenticate flags=%d", 1287c478bd9Sstevel@tonic-gate flags); 1297c478bd9Sstevel@tonic-gate 1300be37caaSsemery (void) pam_get_item(pamh, PAM_USER, (void**) &user); 1317c478bd9Sstevel@tonic-gate 132a0e56b0eSsemery if (user == NULL || *user == '\0') { 1337c478bd9Sstevel@tonic-gate if (debug) 1343bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 1353bfb48feSsemery "PAM-KRB5 (auth): user empty or null"); 136a0e56b0eSsemery return (PAM_USER_UNKNOWN); 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate /* make sure a password entry exists for this user */ 1400be37caaSsemery if (!get_pw_uid(user, &pw_uid)) 1410be37caaSsemery return (PAM_USER_UNKNOWN); 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* 1447c478bd9Sstevel@tonic-gate * pam_get_data could fail if we are being called for the first time 1457c478bd9Sstevel@tonic-gate * or if the module is not found, PAM_NO_MODULE_DATA is not an error 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate err = pam_get_data(pamh, KRB5_DATA, (const void**)&kmd); 1487c478bd9Sstevel@tonic-gate if (!(err == PAM_SUCCESS || err == PAM_NO_MODULE_DATA)) 1493bfb48feSsemery return (PAM_SYSTEM_ERR); 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate if (kmd == NULL) { 1527c478bd9Sstevel@tonic-gate kmd = calloc(1, sizeof (krb5_module_data_t)); 1537c478bd9Sstevel@tonic-gate if (kmd == NULL) { 1547c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 1557c478bd9Sstevel@tonic-gate goto out; 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate err = pam_set_data(pamh, KRB5_DATA, kmd, &krb5_cleanup); 1597c478bd9Sstevel@tonic-gate if (err != PAM_SUCCESS) { 1607c478bd9Sstevel@tonic-gate free(kmd); 1617c478bd9Sstevel@tonic-gate result = err; 1627c478bd9Sstevel@tonic-gate goto out; 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate if (!kmd->env) { 1677c478bd9Sstevel@tonic-gate char buffer[512]; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate if (snprintf(buffer, sizeof (buffer), 1707c478bd9Sstevel@tonic-gate "%s=FILE:/tmp/krb5cc_%d", 1717c478bd9Sstevel@tonic-gate KRB5_ENV_CCNAME, (int)pw_uid) >= sizeof (buffer)) { 1727c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 1737c478bd9Sstevel@tonic-gate goto out; 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate /* we MUST copy this to the heap for the putenv to work! */ 1777c478bd9Sstevel@tonic-gate kmd->env = strdup(buffer); 1787c478bd9Sstevel@tonic-gate if (!kmd->env) { 1797c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 1807c478bd9Sstevel@tonic-gate goto out; 1817c478bd9Sstevel@tonic-gate } else { 1827c478bd9Sstevel@tonic-gate if (putenv(kmd->env)) { 1837c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 1847c478bd9Sstevel@tonic-gate goto out; 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate } 1887c478bd9Sstevel@tonic-gate 1893bfb48feSsemery if ((kmd->user = strdup(user)) == NULL) { 1903bfb48feSsemery result = PAM_BUF_ERR; 1913bfb48feSsemery goto out; 1923bfb48feSsemery } 1933bfb48feSsemery 1947c478bd9Sstevel@tonic-gate kmd->auth_status = PAM_AUTH_ERR; 1957c478bd9Sstevel@tonic-gate kmd->debug = debug; 1967c478bd9Sstevel@tonic-gate kmd->warn = warn; 1977c478bd9Sstevel@tonic-gate kmd->err_on_exp = err_on_exp; 1987c478bd9Sstevel@tonic-gate kmd->ccache = NULL; 1997c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 2007c478bd9Sstevel@tonic-gate kmd->password = NULL; 2017c478bd9Sstevel@tonic-gate kmd->age_status = PAM_SUCCESS; 2027c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate /* 2057c478bd9Sstevel@tonic-gate * For apps that already did krb5 auth exchange... 2067c478bd9Sstevel@tonic-gate * Now that we've created the kmd structure, we can 2077c478bd9Sstevel@tonic-gate * return SUCCESS. 'kmd' may be needed later by other 2087c478bd9Sstevel@tonic-gate * PAM functions, thats why we wait until this point to 2097c478bd9Sstevel@tonic-gate * return. 2107c478bd9Sstevel@tonic-gate */ 2110be37caaSsemery (void) pam_get_item(pamh, PAM_REPOSITORY, (void **)&rep_data); 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate if (rep_data != NULL) { 2147c478bd9Sstevel@tonic-gate if (strcmp(rep_data->type, KRB5_REPOSITORY_NAME) != 0) { 2157c478bd9Sstevel@tonic-gate if (debug) 2163bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2173bfb48feSsemery "PAM-KRB5 (auth): wrong" 2187c478bd9Sstevel@tonic-gate "repository found (%s), returning " 2197c478bd9Sstevel@tonic-gate "PAM_IGNORE", rep_data->type); 2207c478bd9Sstevel@tonic-gate return (PAM_IGNORE); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate if (rep_data->scope_len == sizeof (krb5_repository_data_t)) { 2237c478bd9Sstevel@tonic-gate krb5_data = (krb5_repository_data_t *)rep_data->scope; 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if (krb5_data->flags == 2267c478bd9Sstevel@tonic-gate SUNW_PAM_KRB5_ALREADY_AUTHENTICATED && 2277c478bd9Sstevel@tonic-gate krb5_data->principal != NULL && 2287c478bd9Sstevel@tonic-gate strlen(krb5_data->principal)) { 2297c478bd9Sstevel@tonic-gate if (debug) 2303bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2317c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Principal " 2327c478bd9Sstevel@tonic-gate "%s already authenticated", 2337c478bd9Sstevel@tonic-gate krb5_data->principal); 2347c478bd9Sstevel@tonic-gate kmd->auth_status = PAM_SUCCESS; 2357c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* 2417c478bd9Sstevel@tonic-gate * if root key exists in the keytab, it's a random key so no 2427c478bd9Sstevel@tonic-gate * need to prompt for pw and we just return IGNORE. 2437c478bd9Sstevel@tonic-gate * 2447c478bd9Sstevel@tonic-gate * note we don't need to force a prompt for pw as authtok_get 2457c478bd9Sstevel@tonic-gate * is required to be stacked above this module. 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate if ((strcmp(user, ROOT_UNAME) == 0) && 2487c478bd9Sstevel@tonic-gate key_in_keytab(user, debug)) { 2497c478bd9Sstevel@tonic-gate if (debug) 2503bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2517c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): " 2527c478bd9Sstevel@tonic-gate "key for '%s' in keytab, returning IGNORE", user); 2537c478bd9Sstevel@tonic-gate result = PAM_IGNORE; 2547c478bd9Sstevel@tonic-gate goto out; 2557c478bd9Sstevel@tonic-gate } 2567c478bd9Sstevel@tonic-gate 2570be37caaSsemery (void) pam_get_item(pamh, PAM_AUTHTOK, (void **)&password); 2587c478bd9Sstevel@tonic-gate 2592278144aSsemery result = attempt_krb5_auth(kmd, user, &password, 1); 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate out: 2627c478bd9Sstevel@tonic-gate if (kmd) { 2637c478bd9Sstevel@tonic-gate if (debug) 2643bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2657c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): pam_sm_auth finalize" 2667c478bd9Sstevel@tonic-gate " ccname env, result =%d, env ='%s'," 2677c478bd9Sstevel@tonic-gate " age = %d, status = %d", 2687c478bd9Sstevel@tonic-gate result, kmd->env ? kmd->env : "<null>", 2697c478bd9Sstevel@tonic-gate kmd->age_status, kmd->auth_status); 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate if (kmd->env && 2727c478bd9Sstevel@tonic-gate !(kmd->age_status == PAM_NEW_AUTHTOK_REQD && 2737c478bd9Sstevel@tonic-gate kmd->auth_status == PAM_SUCCESS)) { 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (result == PAM_SUCCESS) { 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * Put ccname into the pamh so that login 2797c478bd9Sstevel@tonic-gate * apps can pick this up when they run 2807c478bd9Sstevel@tonic-gate * pam_getenvlist(). 2817c478bd9Sstevel@tonic-gate */ 2827c478bd9Sstevel@tonic-gate if ((result = pam_putenv(pamh, kmd->env)) 2837c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 2847c478bd9Sstevel@tonic-gate /* should not happen but... */ 2853bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 2867c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth):" 2873bfb48feSsemery " pam_putenv failed: result: %d", 2887c478bd9Sstevel@tonic-gate result); 2897c478bd9Sstevel@tonic-gate goto cleanupccname; 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate } else { 2927c478bd9Sstevel@tonic-gate cleanupccname: 2937c478bd9Sstevel@tonic-gate /* for lack of a Solaris unputenv() */ 2947c478bd9Sstevel@tonic-gate krb5_unsetenv(KRB5_ENV_CCNAME); 2957c478bd9Sstevel@tonic-gate free(kmd->env); 2967c478bd9Sstevel@tonic-gate kmd->env = NULL; 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate kmd->auth_status = result; 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate if (debug) 3033bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3047c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): end: %s", pam_strerror(pamh, result)); 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate return (result); 3077c478bd9Sstevel@tonic-gate } 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate int 3107c478bd9Sstevel@tonic-gate attempt_krb5_auth( 3117c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd, 3127c478bd9Sstevel@tonic-gate char *user, 3137c478bd9Sstevel@tonic-gate char **krb5_pass, 3140be37caaSsemery boolean_t verify_tik) 3157c478bd9Sstevel@tonic-gate { 3167c478bd9Sstevel@tonic-gate krb5_principal me = NULL; 3177c478bd9Sstevel@tonic-gate krb5_principal server = NULL; 3187c478bd9Sstevel@tonic-gate krb5_creds *my_creds; 3197c478bd9Sstevel@tonic-gate krb5_timestamp now; 3207c478bd9Sstevel@tonic-gate krb5_error_code code = 0; 3217c478bd9Sstevel@tonic-gate char kuser[2*MAXHOSTNAMELEN]; 3227c478bd9Sstevel@tonic-gate krb5_deltat lifetime; 3237c478bd9Sstevel@tonic-gate krb5_deltat rlife; 3247c478bd9Sstevel@tonic-gate krb5_deltat krb5_max_duration; 3257c478bd9Sstevel@tonic-gate int options = KRB5_DEFAULT_OPTIONS; 3267c478bd9Sstevel@tonic-gate krb5_data tgtname = { 3277c478bd9Sstevel@tonic-gate 0, 3287c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE, 3297c478bd9Sstevel@tonic-gate KRB5_TGS_NAME 3307c478bd9Sstevel@tonic-gate }; 3317c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt opts; 332*3125ebfcSsemery krb5_kdc_rep *as_reply = NULL; 3337c478bd9Sstevel@tonic-gate /* 3347c478bd9Sstevel@tonic-gate * "result" should not be assigned PAM_SUCCESS unless 3357c478bd9Sstevel@tonic-gate * authentication has succeeded and there are no other errors. 3367c478bd9Sstevel@tonic-gate * 3377c478bd9Sstevel@tonic-gate * "code" is sometimes used for PAM codes, sometimes for krb5 3387c478bd9Sstevel@tonic-gate * codes. Be careful. 3397c478bd9Sstevel@tonic-gate */ 3407c478bd9Sstevel@tonic-gate int result = PAM_AUTH_ERR; 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate if (kmd->debug) 3433bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3447c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: start: user='%s'", 3457c478bd9Sstevel@tonic-gate user ? user : "<null>"); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_init(&opts); 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* need to free context with krb5_free_context */ 3507c478bd9Sstevel@tonic-gate if (code = krb5_init_context(&kmd->kcontext)) { 3513bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 3527c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Error initializing " 3533bfb48feSsemery "krb5: %s", 3547c478bd9Sstevel@tonic-gate error_message(code)); 3557c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 3567c478bd9Sstevel@tonic-gate } 3577c478bd9Sstevel@tonic-gate 3587c478bd9Sstevel@tonic-gate if ((code = get_kmd_kuser(kmd->kcontext, (const char *)user, kuser, 3597c478bd9Sstevel@tonic-gate 2*MAXHOSTNAMELEN)) != 0) { 3607c478bd9Sstevel@tonic-gate /* get_kmd_kuser returns proper PAM error statuses */ 3617c478bd9Sstevel@tonic-gate return (code); 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate if ((code = krb5_parse_name(kmd->kcontext, kuser, &me)) != 0) { 3657c478bd9Sstevel@tonic-gate krb5_free_context(kmd->kcontext); 3667c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 3673bfb48feSsemery return (PAM_SYSTEM_ERR); 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate 3707c478bd9Sstevel@tonic-gate /* call krb5_free_cred_contents() on error */ 3717c478bd9Sstevel@tonic-gate my_creds = &kmd->initcreds; 3727c478bd9Sstevel@tonic-gate 3733bfb48feSsemery if ((code = 3743bfb48feSsemery krb5_copy_principal(kmd->kcontext, me, &my_creds->client))) { 3753bfb48feSsemery result = PAM_SYSTEM_ERR; 3763bfb48feSsemery goto out_err; 3773bfb48feSsemery } 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate if (code = krb5_build_principal_ext(kmd->kcontext, &server, 3807c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 3817c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 3827c478bd9Sstevel@tonic-gate tgtname.length, tgtname.data, 3837c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 3847c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 0)) { 3853bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 3863bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth: " 3873bfb48feSsemery "krb5_build_princ_ext failed: %s", 3883bfb48feSsemery error_message(code)); 3893bfb48feSsemery result = PAM_SYSTEM_ERR; 3907c478bd9Sstevel@tonic-gate goto out; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate if (code = krb5_copy_principal(kmd->kcontext, server, 3947c478bd9Sstevel@tonic-gate &my_creds->server)) { 3953bfb48feSsemery result = PAM_SYSTEM_ERR; 3967c478bd9Sstevel@tonic-gate goto out_err; 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate if (code = krb5_timeofday(kmd->kcontext, &now)) { 4003bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4013bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth: " 4023bfb48feSsemery "krb5_timeofday failed: %s", 4033bfb48feSsemery error_message(code)); 4043bfb48feSsemery result = PAM_SYSTEM_ERR; 4057c478bd9Sstevel@tonic-gate goto out; 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate 4087c478bd9Sstevel@tonic-gate /* 4097c478bd9Sstevel@tonic-gate * set the values for lifetime and rlife to be the maximum 4107c478bd9Sstevel@tonic-gate * possible 4117c478bd9Sstevel@tonic-gate */ 4127c478bd9Sstevel@tonic-gate krb5_max_duration = KRB5_KDB_EXPIRATION - now - 60*60; 4137c478bd9Sstevel@tonic-gate lifetime = krb5_max_duration; 4147c478bd9Sstevel@tonic-gate rlife = krb5_max_duration; 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* 4177c478bd9Sstevel@tonic-gate * Let us get the values for various options 4187c478bd9Sstevel@tonic-gate * from Kerberos configuration file 4197c478bd9Sstevel@tonic-gate */ 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate krb_realm = krb5_princ_realm(kmd->kcontext, me)->data; 4227c478bd9Sstevel@tonic-gate profile_get_options_boolean(kmd->kcontext->profile, 4237c478bd9Sstevel@tonic-gate realmdef, config_option); 4247c478bd9Sstevel@tonic-gate profile_get_options_boolean(kmd->kcontext->profile, 4257c478bd9Sstevel@tonic-gate appdef, config_option); 4267c478bd9Sstevel@tonic-gate profile_get_options_string(kmd->kcontext->profile, 4277c478bd9Sstevel@tonic-gate realmdef, config_times); 4287c478bd9Sstevel@tonic-gate profile_get_options_string(kmd->kcontext->profile, 4297c478bd9Sstevel@tonic-gate appdef, config_times); 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate if (renew_timeval) { 4327c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(renew_timeval, &rlife); 4337c478bd9Sstevel@tonic-gate if (code != 0 || rlife == 0 || rlife > krb5_max_duration) { 4343bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4357c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Bad max_renewable_life " 4363bfb48feSsemery " value '%s' in Kerberos config file", 4377c478bd9Sstevel@tonic-gate renew_timeval); 4387c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 4397c478bd9Sstevel@tonic-gate goto out; 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate if (life_timeval) { 4437c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(life_timeval, &lifetime); 4447c478bd9Sstevel@tonic-gate if (code != 0 || lifetime == 0 || 4457c478bd9Sstevel@tonic-gate lifetime > krb5_max_duration) { 4463bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4473bfb48feSsemery "lifetime value '%s' in Kerberos config file", 4487c478bd9Sstevel@tonic-gate life_timeval); 4497c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 4507c478bd9Sstevel@tonic-gate goto out; 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate /* start timer when request gets to KDC */ 4547c478bd9Sstevel@tonic-gate my_creds->times.starttime = 0; 4557c478bd9Sstevel@tonic-gate my_creds->times.endtime = now + lifetime; 4567c478bd9Sstevel@tonic-gate 4577c478bd9Sstevel@tonic-gate if (options & KDC_OPT_RENEWABLE) { 4587c478bd9Sstevel@tonic-gate my_creds->times.renew_till = now + rlife; 4597c478bd9Sstevel@tonic-gate } else 4607c478bd9Sstevel@tonic-gate my_creds->times.renew_till = 0; 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime); 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate if (proxiable_flag) { /* Set in config file */ 4657c478bd9Sstevel@tonic-gate if (kmd->debug) 4663bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4677c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Proxiable tickets " 4683bfb48feSsemery "requested"); 4697c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_proxiable(&opts, TRUE); 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate if (forwardable_flag) { 4727c478bd9Sstevel@tonic-gate if (kmd->debug) 4733bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4747c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Forwardable tickets " 4753bfb48feSsemery "requested"); 4767c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_forwardable(&opts, TRUE); 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate if (renewable_flag) { 4797c478bd9Sstevel@tonic-gate if (kmd->debug) 4803bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4817c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Renewable tickets " 4823bfb48feSsemery "requested"); 4837c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_renew_life(&opts, rlife); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate if (no_address_flag) { 4867c478bd9Sstevel@tonic-gate if (kmd->debug) 4873bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4887c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Addressless tickets " 4893bfb48feSsemery "requested"); 4907c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_address_list(&opts, NULL); 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* 4947c478bd9Sstevel@tonic-gate * mech_krb5 interprets empty passwords as NULL passwords 4957c478bd9Sstevel@tonic-gate * and tries to read a password from stdin. Since we are in 4967c478bd9Sstevel@tonic-gate * pam this is bad and should not be allowed. 4977c478bd9Sstevel@tonic-gate */ 4987c478bd9Sstevel@tonic-gate if (*krb5_pass == NULL || strlen(*krb5_pass) == 0) { 4997c478bd9Sstevel@tonic-gate code = KRB5KRB_AP_ERR_BAD_INTEGRITY; 5007c478bd9Sstevel@tonic-gate } else { 501*3125ebfcSsemery 502*3125ebfcSsemery /* 503*3125ebfcSsemery * We call our own private version of gic_pwd, because we need 504*3125ebfcSsemery * more information, such as password/account expiration, that 505*3125ebfcSsemery * is found in the as_reply. The "prompter" interface is not 506*3125ebfcSsemery * granular enough for PAM to make use of. 507*3125ebfcSsemery */ 508*3125ebfcSsemery code = __krb5_get_init_creds_password(kmd->kcontext, 5097c478bd9Sstevel@tonic-gate my_creds, 5107c478bd9Sstevel@tonic-gate me, 5117c478bd9Sstevel@tonic-gate *krb5_pass, /* clear text passwd */ 5127c478bd9Sstevel@tonic-gate NULL, /* prompter */ 5137c478bd9Sstevel@tonic-gate NULL, /* data */ 5147c478bd9Sstevel@tonic-gate 0, /* start time */ 5157c478bd9Sstevel@tonic-gate NULL, /* defaults to krbtgt@REALM */ 516*3125ebfcSsemery &opts, 517*3125ebfcSsemery &as_reply); 5187c478bd9Sstevel@tonic-gate } 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if (kmd->debug) 5213bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 5227c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: " 5237c478bd9Sstevel@tonic-gate "krb5_get_init_creds_password returns: %s", 5247c478bd9Sstevel@tonic-gate code == 0 ? "SUCCESS" : error_message(code)); 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate switch (code) { 5277c478bd9Sstevel@tonic-gate case 0: 5287c478bd9Sstevel@tonic-gate /* got a tgt, let's verify it */ 5297c478bd9Sstevel@tonic-gate if (verify_tik) { 5307c478bd9Sstevel@tonic-gate krb5_verify_init_creds_opt vopts; 5317c478bd9Sstevel@tonic-gate 532a0709436Smp krb5_principal sp = NULL; 533a0709436Smp char kt_name[MAX_KEYTAB_NAME_LEN]; 534a0709436Smp char *fqdn; 535a0709436Smp 5367c478bd9Sstevel@tonic-gate krb5_verify_init_creds_opt_init(&vopts); 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate code = krb5_verify_init_creds(kmd->kcontext, 5397c478bd9Sstevel@tonic-gate my_creds, 5407c478bd9Sstevel@tonic-gate NULL, /* defaults to host/localhost@REALM */ 5417c478bd9Sstevel@tonic-gate NULL, 5427c478bd9Sstevel@tonic-gate NULL, 5437c478bd9Sstevel@tonic-gate &vopts); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate if (code) { 5467c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 5477c478bd9Sstevel@tonic-gate 5480be37caaSsemery /* 5490be37caaSsemery * Give a better error message when the 5500be37caaSsemery * keytable entry isn't found or the keytab 5510be37caaSsemery * file cannot be found. 5520be37caaSsemery */ 553a0709436Smp if (krb5_sname_to_principal(kmd->kcontext, NULL, 554a0709436Smp NULL, KRB5_NT_SRV_HST, &sp)) 555a0709436Smp fqdn = "<fqdn>"; 556a0709436Smp else 557a0709436Smp fqdn = sp->data[1].data; 558a0709436Smp 559a0709436Smp if (krb5_kt_default_name(kmd->kcontext, kt_name, 560a0709436Smp sizeof (kt_name))) 561a0709436Smp (void) strncpy(kt_name, 562a0709436Smp "default keytab", 563a0709436Smp sizeof (kt_name)); 564a0709436Smp 565a0709436Smp switch (code) { 566a0709436Smp case KRB5_KT_NOTFOUND: 5673bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 568a0709436Smp "PAM-KRB5 (auth): " 569a0709436Smp "krb5_verify_init_creds failed:" 570a0709436Smp " Key table entry \"host/%s\"" 5713bfb48feSsemery " not found in %s", 572a0709436Smp fqdn, kt_name); 573a0709436Smp break; 574a0709436Smp case ENOENT: 5753bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 576a0709436Smp "PAM-KRB5 (auth): " 577a0709436Smp "krb5_verify_init_creds failed:" 578a0709436Smp " Keytab file \"%s\"" 5793bfb48feSsemery " does not exist.\n", 580a0709436Smp kt_name); 581a0709436Smp break; 582a0709436Smp default: 5833bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 584a0709436Smp "PAM-KRB5 (auth): " 585a0709436Smp "krb5_verify_init_creds failed:" 5863bfb48feSsemery " %s", 587a0709436Smp error_message(code)); 588a0709436Smp break; 589a0709436Smp } 590a0709436Smp 591a0709436Smp if (sp) 592a0709436Smp krb5_free_principal(kmd->kcontext, sp); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate } 595*3125ebfcSsemery 596*3125ebfcSsemery if (code == 0) 597*3125ebfcSsemery kmd->expiration = as_reply->enc_part2->key_exp; 598*3125ebfcSsemery 5997c478bd9Sstevel@tonic-gate break; 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: 6027c478bd9Sstevel@tonic-gate /* 6037c478bd9Sstevel@tonic-gate * Since this principal is not part of the local 6047c478bd9Sstevel@tonic-gate * Kerberos realm, we just return PAM_USER_UNKNOWN. 6057c478bd9Sstevel@tonic-gate */ 6067c478bd9Sstevel@tonic-gate result = PAM_USER_UNKNOWN; 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate if (kmd->debug) 6093bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6103bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth:" 6117c478bd9Sstevel@tonic-gate " User is not part of the local Kerberos" 6127c478bd9Sstevel@tonic-gate " realm: %s", error_message(code)); 6137c478bd9Sstevel@tonic-gate break; 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_PREAUTH_FAILED: 6167c478bd9Sstevel@tonic-gate case KRB5KRB_AP_ERR_BAD_INTEGRITY: 6177c478bd9Sstevel@tonic-gate /* 6187c478bd9Sstevel@tonic-gate * We could be trying the password from a previous 6197c478bd9Sstevel@tonic-gate * pam authentication module, but we don't want to 6207c478bd9Sstevel@tonic-gate * generate an error if the unix password is different 6217c478bd9Sstevel@tonic-gate * than the Kerberos password... 6227c478bd9Sstevel@tonic-gate */ 6237c478bd9Sstevel@tonic-gate break; 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_KEY_EXP: 6267c478bd9Sstevel@tonic-gate if (!kmd->err_on_exp) { 6277c478bd9Sstevel@tonic-gate /* 6287c478bd9Sstevel@tonic-gate * Request a tik for changepw service 6297c478bd9Sstevel@tonic-gate * and it will tell us if pw is good or not. 6307c478bd9Sstevel@tonic-gate */ 6312278144aSsemery code = krb5_verifypw(kuser, *krb5_pass, kmd->debug); 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate if (kmd->debug) 6343bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6357c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: " 6362278144aSsemery "verifypw %d", code); 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate if (code == 0) { 6397c478bd9Sstevel@tonic-gate /* pw is good, set age status for acct_mgmt */ 6407c478bd9Sstevel@tonic-gate kmd->age_status = PAM_NEW_AUTHTOK_REQD; 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate break; 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate default: 6467c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 6477c478bd9Sstevel@tonic-gate if (kmd->debug) 6483bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6493bfb48feSsemery "PAM-KRB5 (auth): error %d - %s", 6507c478bd9Sstevel@tonic-gate code, error_message(code)); 6517c478bd9Sstevel@tonic-gate break; 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate if (code == 0) { 6557c478bd9Sstevel@tonic-gate /* 6567c478bd9Sstevel@tonic-gate * success for the entered pw 6577c478bd9Sstevel@tonic-gate * 6587c478bd9Sstevel@tonic-gate * we can't rely on the pw in PAM_AUTHTOK 6597c478bd9Sstevel@tonic-gate * to be the (correct) krb5 one so 6607c478bd9Sstevel@tonic-gate * store krb5 pw in module data for 6617c478bd9Sstevel@tonic-gate * use in acct_mgmt 6627c478bd9Sstevel@tonic-gate */ 6637c478bd9Sstevel@tonic-gate if (!(kmd->password = strdup(*krb5_pass))) { 6643bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, "Cannot strdup password"); 6657c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 6667c478bd9Sstevel@tonic-gate goto out_err; 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate result = PAM_SUCCESS; 6697c478bd9Sstevel@tonic-gate goto out; 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate out_err: 6737c478bd9Sstevel@tonic-gate /* jump (or reach) here if error and cred cache has been init */ 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate if (kmd->debug) 6763bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6777c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): clearing initcreds in " 6787c478bd9Sstevel@tonic-gate "pam_authenticate()"); 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 6817c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate out: 6847c478bd9Sstevel@tonic-gate if (server) 6857c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, server); 6867c478bd9Sstevel@tonic-gate if (me) 6877c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, me); 688*3125ebfcSsemery if (as_reply) 689*3125ebfcSsemery krb5_free_kdc_rep(kmd->kcontext, as_reply); 6907c478bd9Sstevel@tonic-gate if (kmd->kcontext) { 6917c478bd9Sstevel@tonic-gate krb5_free_context(kmd->kcontext); 6927c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate if (kmd->debug) 6963bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6977c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth returning %d", 6987c478bd9Sstevel@tonic-gate result); 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate return (kmd->auth_status = result); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7047c478bd9Sstevel@tonic-gate void 7057c478bd9Sstevel@tonic-gate krb5_cleanup(pam_handle_t *pamh, void *data, int pam_status) 7067c478bd9Sstevel@tonic-gate { 7077c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd = (krb5_module_data_t *)data; 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate if (kmd == NULL) 7107c478bd9Sstevel@tonic-gate return; 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate if (kmd->debug) { 7133bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 7143bfb48feSsemery "PAM-KRB5 (auth): krb5_cleanup auth_status = %d", 7157c478bd9Sstevel@tonic-gate kmd->auth_status); 7167c478bd9Sstevel@tonic-gate } 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate /* 7197c478bd9Sstevel@tonic-gate * if pam_status is PAM_SUCCESS, clean up based on value in 7207c478bd9Sstevel@tonic-gate * auth_status, otherwise just purge the context 7217c478bd9Sstevel@tonic-gate */ 7227c478bd9Sstevel@tonic-gate if ((pam_status == PAM_SUCCESS) && 7237c478bd9Sstevel@tonic-gate (kmd->auth_status == PAM_SUCCESS) && kmd->ccache) 7247c478bd9Sstevel@tonic-gate krb5_cc_close(kmd->kcontext, kmd->ccache); 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate if (kmd->password) { 7277c478bd9Sstevel@tonic-gate (void) memset(kmd->password, 0, strlen(kmd->password)); 7287c478bd9Sstevel@tonic-gate free(kmd->password); 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate 7313bfb48feSsemery if (kmd->user != NULL) 7323bfb48feSsemery free(kmd->user); 7333bfb48feSsemery 7347c478bd9Sstevel@tonic-gate if ((pam_status != PAM_SUCCESS) || 7357c478bd9Sstevel@tonic-gate (kmd->auth_status != PAM_SUCCESS)) { 7367c478bd9Sstevel@tonic-gate krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 7377c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 7387c478bd9Sstevel@tonic-gate } 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate free(kmd); 7417c478bd9Sstevel@tonic-gate } 742