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 *); 803125ebfcSsemery extern krb5_error_code __krb5_get_init_creds_password(krb5_context, 813125ebfcSsemery krb5_creds *, krb5_principal, char *, krb5_prompter_fct, void *, 823125ebfcSsemery krb5_deltat, char *, krb5_get_init_creds_opt *, 833125ebfcSsemery 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 189*67c90040Ssemery if (kmd->user != NULL) 190*67c90040Ssemery free(kmd->user); 1913bfb48feSsemery if ((kmd->user = strdup(user)) == NULL) { 1923bfb48feSsemery result = PAM_BUF_ERR; 1933bfb48feSsemery goto out; 1943bfb48feSsemery } 1953bfb48feSsemery 1967c478bd9Sstevel@tonic-gate kmd->auth_status = PAM_AUTH_ERR; 1977c478bd9Sstevel@tonic-gate kmd->debug = debug; 1987c478bd9Sstevel@tonic-gate kmd->warn = warn; 1997c478bd9Sstevel@tonic-gate kmd->err_on_exp = err_on_exp; 2007c478bd9Sstevel@tonic-gate kmd->ccache = NULL; 2017c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 2027c478bd9Sstevel@tonic-gate kmd->password = NULL; 2037c478bd9Sstevel@tonic-gate kmd->age_status = PAM_SUCCESS; 2047c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* 2077c478bd9Sstevel@tonic-gate * For apps that already did krb5 auth exchange... 2087c478bd9Sstevel@tonic-gate * Now that we've created the kmd structure, we can 2097c478bd9Sstevel@tonic-gate * return SUCCESS. 'kmd' may be needed later by other 2107c478bd9Sstevel@tonic-gate * PAM functions, thats why we wait until this point to 2117c478bd9Sstevel@tonic-gate * return. 2127c478bd9Sstevel@tonic-gate */ 2130be37caaSsemery (void) pam_get_item(pamh, PAM_REPOSITORY, (void **)&rep_data); 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate if (rep_data != NULL) { 2167c478bd9Sstevel@tonic-gate if (strcmp(rep_data->type, KRB5_REPOSITORY_NAME) != 0) { 2177c478bd9Sstevel@tonic-gate if (debug) 2183bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2193bfb48feSsemery "PAM-KRB5 (auth): wrong" 2207c478bd9Sstevel@tonic-gate "repository found (%s), returning " 2217c478bd9Sstevel@tonic-gate "PAM_IGNORE", rep_data->type); 2227c478bd9Sstevel@tonic-gate return (PAM_IGNORE); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate if (rep_data->scope_len == sizeof (krb5_repository_data_t)) { 2257c478bd9Sstevel@tonic-gate krb5_data = (krb5_repository_data_t *)rep_data->scope; 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate if (krb5_data->flags == 2287c478bd9Sstevel@tonic-gate SUNW_PAM_KRB5_ALREADY_AUTHENTICATED && 2297c478bd9Sstevel@tonic-gate krb5_data->principal != NULL && 2307c478bd9Sstevel@tonic-gate strlen(krb5_data->principal)) { 2317c478bd9Sstevel@tonic-gate if (debug) 2323bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2337c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Principal " 2347c478bd9Sstevel@tonic-gate "%s already authenticated", 2357c478bd9Sstevel@tonic-gate krb5_data->principal); 2367c478bd9Sstevel@tonic-gate kmd->auth_status = PAM_SUCCESS; 2377c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* 2437c478bd9Sstevel@tonic-gate * if root key exists in the keytab, it's a random key so no 2447c478bd9Sstevel@tonic-gate * need to prompt for pw and we just return IGNORE. 2457c478bd9Sstevel@tonic-gate * 2467c478bd9Sstevel@tonic-gate * note we don't need to force a prompt for pw as authtok_get 2477c478bd9Sstevel@tonic-gate * is required to be stacked above this module. 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate if ((strcmp(user, ROOT_UNAME) == 0) && 2507c478bd9Sstevel@tonic-gate key_in_keytab(user, debug)) { 2517c478bd9Sstevel@tonic-gate if (debug) 2523bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2537c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): " 2547c478bd9Sstevel@tonic-gate "key for '%s' in keytab, returning IGNORE", user); 2557c478bd9Sstevel@tonic-gate result = PAM_IGNORE; 2567c478bd9Sstevel@tonic-gate goto out; 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2590be37caaSsemery (void) pam_get_item(pamh, PAM_AUTHTOK, (void **)&password); 2607c478bd9Sstevel@tonic-gate 2612278144aSsemery result = attempt_krb5_auth(kmd, user, &password, 1); 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate out: 2647c478bd9Sstevel@tonic-gate if (kmd) { 2657c478bd9Sstevel@tonic-gate if (debug) 2663bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2677c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): pam_sm_auth finalize" 2687c478bd9Sstevel@tonic-gate " ccname env, result =%d, env ='%s'," 2697c478bd9Sstevel@tonic-gate " age = %d, status = %d", 2707c478bd9Sstevel@tonic-gate result, kmd->env ? kmd->env : "<null>", 2717c478bd9Sstevel@tonic-gate kmd->age_status, kmd->auth_status); 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate if (kmd->env && 2747c478bd9Sstevel@tonic-gate !(kmd->age_status == PAM_NEW_AUTHTOK_REQD && 2757c478bd9Sstevel@tonic-gate kmd->auth_status == PAM_SUCCESS)) { 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate 2787c478bd9Sstevel@tonic-gate if (result == PAM_SUCCESS) { 2797c478bd9Sstevel@tonic-gate /* 2807c478bd9Sstevel@tonic-gate * Put ccname into the pamh so that login 2817c478bd9Sstevel@tonic-gate * apps can pick this up when they run 2827c478bd9Sstevel@tonic-gate * pam_getenvlist(). 2837c478bd9Sstevel@tonic-gate */ 2847c478bd9Sstevel@tonic-gate if ((result = pam_putenv(pamh, kmd->env)) 2857c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 2867c478bd9Sstevel@tonic-gate /* should not happen but... */ 2873bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 2887c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth):" 2893bfb48feSsemery " pam_putenv failed: result: %d", 2907c478bd9Sstevel@tonic-gate result); 2917c478bd9Sstevel@tonic-gate goto cleanupccname; 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate } else { 2947c478bd9Sstevel@tonic-gate cleanupccname: 2957c478bd9Sstevel@tonic-gate /* for lack of a Solaris unputenv() */ 2967c478bd9Sstevel@tonic-gate krb5_unsetenv(KRB5_ENV_CCNAME); 2977c478bd9Sstevel@tonic-gate free(kmd->env); 2987c478bd9Sstevel@tonic-gate kmd->env = NULL; 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate kmd->auth_status = result; 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate if (debug) 3053bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3067c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): end: %s", pam_strerror(pamh, result)); 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate return (result); 3097c478bd9Sstevel@tonic-gate } 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate int 3127c478bd9Sstevel@tonic-gate attempt_krb5_auth( 3137c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd, 3147c478bd9Sstevel@tonic-gate char *user, 3157c478bd9Sstevel@tonic-gate char **krb5_pass, 3160be37caaSsemery boolean_t verify_tik) 3177c478bd9Sstevel@tonic-gate { 318*67c90040Ssemery krb5_principal me = NULL, clientp = NULL; 319*67c90040Ssemery krb5_principal server = NULL, serverp = NULL; 3207c478bd9Sstevel@tonic-gate krb5_creds *my_creds; 3217c478bd9Sstevel@tonic-gate krb5_timestamp now; 3227c478bd9Sstevel@tonic-gate krb5_error_code code = 0; 3237c478bd9Sstevel@tonic-gate char kuser[2*MAXHOSTNAMELEN]; 3247c478bd9Sstevel@tonic-gate krb5_deltat lifetime; 3257c478bd9Sstevel@tonic-gate krb5_deltat rlife; 3267c478bd9Sstevel@tonic-gate krb5_deltat krb5_max_duration; 3277c478bd9Sstevel@tonic-gate int options = KRB5_DEFAULT_OPTIONS; 3287c478bd9Sstevel@tonic-gate krb5_data tgtname = { 3297c478bd9Sstevel@tonic-gate 0, 3307c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE, 3317c478bd9Sstevel@tonic-gate KRB5_TGS_NAME 3327c478bd9Sstevel@tonic-gate }; 3337c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt opts; 3343125ebfcSsemery krb5_kdc_rep *as_reply = NULL; 3357c478bd9Sstevel@tonic-gate /* 3367c478bd9Sstevel@tonic-gate * "result" should not be assigned PAM_SUCCESS unless 3377c478bd9Sstevel@tonic-gate * authentication has succeeded and there are no other errors. 3387c478bd9Sstevel@tonic-gate * 3397c478bd9Sstevel@tonic-gate * "code" is sometimes used for PAM codes, sometimes for krb5 3407c478bd9Sstevel@tonic-gate * codes. Be careful. 3417c478bd9Sstevel@tonic-gate */ 3427c478bd9Sstevel@tonic-gate int result = PAM_AUTH_ERR; 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate if (kmd->debug) 3453bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3467c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: start: user='%s'", 3477c478bd9Sstevel@tonic-gate user ? user : "<null>"); 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_init(&opts); 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate /* need to free context with krb5_free_context */ 3527c478bd9Sstevel@tonic-gate if (code = krb5_init_context(&kmd->kcontext)) { 3533bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 3547c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Error initializing " 3553bfb48feSsemery "krb5: %s", 3567c478bd9Sstevel@tonic-gate error_message(code)); 3577c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate if ((code = get_kmd_kuser(kmd->kcontext, (const char *)user, kuser, 3617c478bd9Sstevel@tonic-gate 2*MAXHOSTNAMELEN)) != 0) { 3627c478bd9Sstevel@tonic-gate /* get_kmd_kuser returns proper PAM error statuses */ 3637c478bd9Sstevel@tonic-gate return (code); 3647c478bd9Sstevel@tonic-gate } 3657c478bd9Sstevel@tonic-gate 3667c478bd9Sstevel@tonic-gate if ((code = krb5_parse_name(kmd->kcontext, kuser, &me)) != 0) { 3677c478bd9Sstevel@tonic-gate krb5_free_context(kmd->kcontext); 3687c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 3693bfb48feSsemery return (PAM_SYSTEM_ERR); 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate /* call krb5_free_cred_contents() on error */ 3737c478bd9Sstevel@tonic-gate my_creds = &kmd->initcreds; 3747c478bd9Sstevel@tonic-gate 3753bfb48feSsemery if ((code = 3763bfb48feSsemery krb5_copy_principal(kmd->kcontext, me, &my_creds->client))) { 3773bfb48feSsemery result = PAM_SYSTEM_ERR; 3783bfb48feSsemery goto out_err; 3793bfb48feSsemery } 380*67c90040Ssemery clientp = my_creds->client; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate if (code = krb5_build_principal_ext(kmd->kcontext, &server, 3837c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 3847c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 3857c478bd9Sstevel@tonic-gate tgtname.length, tgtname.data, 3867c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 3877c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 0)) { 3883bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 3893bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth: " 3903bfb48feSsemery "krb5_build_princ_ext failed: %s", 3913bfb48feSsemery error_message(code)); 3923bfb48feSsemery result = PAM_SYSTEM_ERR; 3937c478bd9Sstevel@tonic-gate goto out; 3947c478bd9Sstevel@tonic-gate } 3957c478bd9Sstevel@tonic-gate 3967c478bd9Sstevel@tonic-gate if (code = krb5_copy_principal(kmd->kcontext, server, 3977c478bd9Sstevel@tonic-gate &my_creds->server)) { 3983bfb48feSsemery result = PAM_SYSTEM_ERR; 3997c478bd9Sstevel@tonic-gate goto out_err; 4007c478bd9Sstevel@tonic-gate } 401*67c90040Ssemery serverp = my_creds->server; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate if (code = krb5_timeofday(kmd->kcontext, &now)) { 4043bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4053bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth: " 4063bfb48feSsemery "krb5_timeofday failed: %s", 4073bfb48feSsemery error_message(code)); 4083bfb48feSsemery result = PAM_SYSTEM_ERR; 4097c478bd9Sstevel@tonic-gate goto out; 4107c478bd9Sstevel@tonic-gate } 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate /* 4137c478bd9Sstevel@tonic-gate * set the values for lifetime and rlife to be the maximum 4147c478bd9Sstevel@tonic-gate * possible 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate krb5_max_duration = KRB5_KDB_EXPIRATION - now - 60*60; 4177c478bd9Sstevel@tonic-gate lifetime = krb5_max_duration; 4187c478bd9Sstevel@tonic-gate rlife = krb5_max_duration; 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate /* 4217c478bd9Sstevel@tonic-gate * Let us get the values for various options 4227c478bd9Sstevel@tonic-gate * from Kerberos configuration file 4237c478bd9Sstevel@tonic-gate */ 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate krb_realm = krb5_princ_realm(kmd->kcontext, me)->data; 4267c478bd9Sstevel@tonic-gate profile_get_options_boolean(kmd->kcontext->profile, 4277c478bd9Sstevel@tonic-gate realmdef, config_option); 4287c478bd9Sstevel@tonic-gate profile_get_options_boolean(kmd->kcontext->profile, 4297c478bd9Sstevel@tonic-gate appdef, config_option); 4307c478bd9Sstevel@tonic-gate profile_get_options_string(kmd->kcontext->profile, 4317c478bd9Sstevel@tonic-gate realmdef, config_times); 4327c478bd9Sstevel@tonic-gate profile_get_options_string(kmd->kcontext->profile, 4337c478bd9Sstevel@tonic-gate appdef, config_times); 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate if (renew_timeval) { 4367c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(renew_timeval, &rlife); 4377c478bd9Sstevel@tonic-gate if (code != 0 || rlife == 0 || rlife > krb5_max_duration) { 4383bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4397c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Bad max_renewable_life " 4403bfb48feSsemery " value '%s' in Kerberos config file", 4417c478bd9Sstevel@tonic-gate renew_timeval); 4427c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 4437c478bd9Sstevel@tonic-gate goto out; 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate if (life_timeval) { 4477c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(life_timeval, &lifetime); 4487c478bd9Sstevel@tonic-gate if (code != 0 || lifetime == 0 || 4497c478bd9Sstevel@tonic-gate lifetime > krb5_max_duration) { 4503bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4513bfb48feSsemery "lifetime value '%s' in Kerberos config file", 4527c478bd9Sstevel@tonic-gate life_timeval); 4537c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 4547c478bd9Sstevel@tonic-gate goto out; 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate } 4577c478bd9Sstevel@tonic-gate /* start timer when request gets to KDC */ 4587c478bd9Sstevel@tonic-gate my_creds->times.starttime = 0; 4597c478bd9Sstevel@tonic-gate my_creds->times.endtime = now + lifetime; 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate if (options & KDC_OPT_RENEWABLE) { 4627c478bd9Sstevel@tonic-gate my_creds->times.renew_till = now + rlife; 4637c478bd9Sstevel@tonic-gate } else 4647c478bd9Sstevel@tonic-gate my_creds->times.renew_till = 0; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime); 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate if (proxiable_flag) { /* Set in config file */ 4697c478bd9Sstevel@tonic-gate if (kmd->debug) 4703bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4717c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Proxiable tickets " 4723bfb48feSsemery "requested"); 4737c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_proxiable(&opts, TRUE); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate if (forwardable_flag) { 4767c478bd9Sstevel@tonic-gate if (kmd->debug) 4773bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4787c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Forwardable tickets " 4793bfb48feSsemery "requested"); 4807c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_forwardable(&opts, TRUE); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate if (renewable_flag) { 4837c478bd9Sstevel@tonic-gate if (kmd->debug) 4843bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4857c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Renewable tickets " 4863bfb48feSsemery "requested"); 4877c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_renew_life(&opts, rlife); 4887c478bd9Sstevel@tonic-gate } 4897c478bd9Sstevel@tonic-gate if (no_address_flag) { 4907c478bd9Sstevel@tonic-gate if (kmd->debug) 4913bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4927c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Addressless tickets " 4933bfb48feSsemery "requested"); 4947c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_address_list(&opts, NULL); 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate /* 4987c478bd9Sstevel@tonic-gate * mech_krb5 interprets empty passwords as NULL passwords 4997c478bd9Sstevel@tonic-gate * and tries to read a password from stdin. Since we are in 5007c478bd9Sstevel@tonic-gate * pam this is bad and should not be allowed. 5017c478bd9Sstevel@tonic-gate */ 5027c478bd9Sstevel@tonic-gate if (*krb5_pass == NULL || strlen(*krb5_pass) == 0) { 5037c478bd9Sstevel@tonic-gate code = KRB5KRB_AP_ERR_BAD_INTEGRITY; 5047c478bd9Sstevel@tonic-gate } else { 5053125ebfcSsemery 5063125ebfcSsemery /* 5073125ebfcSsemery * We call our own private version of gic_pwd, because we need 5083125ebfcSsemery * more information, such as password/account expiration, that 5093125ebfcSsemery * is found in the as_reply. The "prompter" interface is not 5103125ebfcSsemery * granular enough for PAM to make use of. 5113125ebfcSsemery */ 5123125ebfcSsemery code = __krb5_get_init_creds_password(kmd->kcontext, 5137c478bd9Sstevel@tonic-gate my_creds, 5147c478bd9Sstevel@tonic-gate me, 5157c478bd9Sstevel@tonic-gate *krb5_pass, /* clear text passwd */ 5167c478bd9Sstevel@tonic-gate NULL, /* prompter */ 5177c478bd9Sstevel@tonic-gate NULL, /* data */ 5187c478bd9Sstevel@tonic-gate 0, /* start time */ 5197c478bd9Sstevel@tonic-gate NULL, /* defaults to krbtgt@REALM */ 5203125ebfcSsemery &opts, 5213125ebfcSsemery &as_reply); 5227c478bd9Sstevel@tonic-gate } 5237c478bd9Sstevel@tonic-gate 5247c478bd9Sstevel@tonic-gate if (kmd->debug) 5253bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 5267c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: " 5277c478bd9Sstevel@tonic-gate "krb5_get_init_creds_password returns: %s", 5287c478bd9Sstevel@tonic-gate code == 0 ? "SUCCESS" : error_message(code)); 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate switch (code) { 5317c478bd9Sstevel@tonic-gate case 0: 5327c478bd9Sstevel@tonic-gate /* got a tgt, let's verify it */ 5337c478bd9Sstevel@tonic-gate if (verify_tik) { 5347c478bd9Sstevel@tonic-gate krb5_verify_init_creds_opt vopts; 5357c478bd9Sstevel@tonic-gate 536a0709436Smp krb5_principal sp = NULL; 537a0709436Smp char kt_name[MAX_KEYTAB_NAME_LEN]; 538a0709436Smp char *fqdn; 539a0709436Smp 5407c478bd9Sstevel@tonic-gate krb5_verify_init_creds_opt_init(&vopts); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate code = krb5_verify_init_creds(kmd->kcontext, 5437c478bd9Sstevel@tonic-gate my_creds, 5447c478bd9Sstevel@tonic-gate NULL, /* defaults to host/localhost@REALM */ 5457c478bd9Sstevel@tonic-gate NULL, 5467c478bd9Sstevel@tonic-gate NULL, 5477c478bd9Sstevel@tonic-gate &vopts); 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate if (code) { 5507c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 5517c478bd9Sstevel@tonic-gate 5520be37caaSsemery /* 5530be37caaSsemery * Give a better error message when the 5540be37caaSsemery * keytable entry isn't found or the keytab 5550be37caaSsemery * file cannot be found. 5560be37caaSsemery */ 557a0709436Smp if (krb5_sname_to_principal(kmd->kcontext, NULL, 558a0709436Smp NULL, KRB5_NT_SRV_HST, &sp)) 559a0709436Smp fqdn = "<fqdn>"; 560a0709436Smp else 561a0709436Smp fqdn = sp->data[1].data; 562a0709436Smp 563a0709436Smp if (krb5_kt_default_name(kmd->kcontext, kt_name, 564a0709436Smp sizeof (kt_name))) 565a0709436Smp (void) strncpy(kt_name, 566a0709436Smp "default keytab", 567a0709436Smp sizeof (kt_name)); 568a0709436Smp 569a0709436Smp switch (code) { 570a0709436Smp case KRB5_KT_NOTFOUND: 5713bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 572a0709436Smp "PAM-KRB5 (auth): " 573a0709436Smp "krb5_verify_init_creds failed:" 574a0709436Smp " Key table entry \"host/%s\"" 5753bfb48feSsemery " not found in %s", 576a0709436Smp fqdn, kt_name); 577a0709436Smp break; 578a0709436Smp case ENOENT: 5793bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 580a0709436Smp "PAM-KRB5 (auth): " 581a0709436Smp "krb5_verify_init_creds failed:" 582a0709436Smp " Keytab file \"%s\"" 5833bfb48feSsemery " does not exist.\n", 584a0709436Smp kt_name); 585a0709436Smp break; 586a0709436Smp default: 5873bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 588a0709436Smp "PAM-KRB5 (auth): " 589a0709436Smp "krb5_verify_init_creds failed:" 5903bfb48feSsemery " %s", 591a0709436Smp error_message(code)); 592a0709436Smp break; 593a0709436Smp } 594a0709436Smp 595a0709436Smp if (sp) 596a0709436Smp krb5_free_principal(kmd->kcontext, sp); 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate } 5993125ebfcSsemery 6003125ebfcSsemery if (code == 0) 6013125ebfcSsemery kmd->expiration = as_reply->enc_part2->key_exp; 6023125ebfcSsemery 6037c478bd9Sstevel@tonic-gate break; 6047c478bd9Sstevel@tonic-gate 6057c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: 6067c478bd9Sstevel@tonic-gate /* 6077c478bd9Sstevel@tonic-gate * Since this principal is not part of the local 6087c478bd9Sstevel@tonic-gate * Kerberos realm, we just return PAM_USER_UNKNOWN. 6097c478bd9Sstevel@tonic-gate */ 6107c478bd9Sstevel@tonic-gate result = PAM_USER_UNKNOWN; 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate if (kmd->debug) 6133bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6143bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth:" 6157c478bd9Sstevel@tonic-gate " User is not part of the local Kerberos" 6167c478bd9Sstevel@tonic-gate " realm: %s", error_message(code)); 6177c478bd9Sstevel@tonic-gate break; 6187c478bd9Sstevel@tonic-gate 6197c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_PREAUTH_FAILED: 6207c478bd9Sstevel@tonic-gate case KRB5KRB_AP_ERR_BAD_INTEGRITY: 6217c478bd9Sstevel@tonic-gate /* 6227c478bd9Sstevel@tonic-gate * We could be trying the password from a previous 6237c478bd9Sstevel@tonic-gate * pam authentication module, but we don't want to 6247c478bd9Sstevel@tonic-gate * generate an error if the unix password is different 6257c478bd9Sstevel@tonic-gate * than the Kerberos password... 6267c478bd9Sstevel@tonic-gate */ 6277c478bd9Sstevel@tonic-gate break; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_KEY_EXP: 6307c478bd9Sstevel@tonic-gate if (!kmd->err_on_exp) { 6317c478bd9Sstevel@tonic-gate /* 6327c478bd9Sstevel@tonic-gate * Request a tik for changepw service 6337c478bd9Sstevel@tonic-gate * and it will tell us if pw is good or not. 6347c478bd9Sstevel@tonic-gate */ 6352278144aSsemery code = krb5_verifypw(kuser, *krb5_pass, kmd->debug); 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate if (kmd->debug) 6383bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6397c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: " 6402278144aSsemery "verifypw %d", code); 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate if (code == 0) { 6437c478bd9Sstevel@tonic-gate /* pw is good, set age status for acct_mgmt */ 6447c478bd9Sstevel@tonic-gate kmd->age_status = PAM_NEW_AUTHTOK_REQD; 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate break; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate default: 6507c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 6517c478bd9Sstevel@tonic-gate if (kmd->debug) 6523bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6533bfb48feSsemery "PAM-KRB5 (auth): error %d - %s", 6547c478bd9Sstevel@tonic-gate code, error_message(code)); 6557c478bd9Sstevel@tonic-gate break; 6567c478bd9Sstevel@tonic-gate } 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate if (code == 0) { 6597c478bd9Sstevel@tonic-gate /* 6607c478bd9Sstevel@tonic-gate * success for the entered pw 6617c478bd9Sstevel@tonic-gate * 6627c478bd9Sstevel@tonic-gate * we can't rely on the pw in PAM_AUTHTOK 6637c478bd9Sstevel@tonic-gate * to be the (correct) krb5 one so 6647c478bd9Sstevel@tonic-gate * store krb5 pw in module data for 6657c478bd9Sstevel@tonic-gate * use in acct_mgmt 6667c478bd9Sstevel@tonic-gate */ 6677c478bd9Sstevel@tonic-gate if (!(kmd->password = strdup(*krb5_pass))) { 6683bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, "Cannot strdup password"); 6697c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 6707c478bd9Sstevel@tonic-gate goto out_err; 6717c478bd9Sstevel@tonic-gate } 6727c478bd9Sstevel@tonic-gate result = PAM_SUCCESS; 6737c478bd9Sstevel@tonic-gate goto out; 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate 6767c478bd9Sstevel@tonic-gate out_err: 6777c478bd9Sstevel@tonic-gate /* jump (or reach) here if error and cred cache has been init */ 6787c478bd9Sstevel@tonic-gate 6797c478bd9Sstevel@tonic-gate if (kmd->debug) 6803bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6817c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): clearing initcreds in " 6827c478bd9Sstevel@tonic-gate "pam_authenticate()"); 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 6857c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 6867c478bd9Sstevel@tonic-gate 6877c478bd9Sstevel@tonic-gate out: 6887c478bd9Sstevel@tonic-gate if (server) 6897c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, server); 6907c478bd9Sstevel@tonic-gate if (me) 6917c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, me); 6923125ebfcSsemery if (as_reply) 6933125ebfcSsemery krb5_free_kdc_rep(kmd->kcontext, as_reply); 694*67c90040Ssemery 695*67c90040Ssemery /* 696*67c90040Ssemery * clientp or serverp could be NULL in certain error cases in this 697*67c90040Ssemery * function. mycreds->[client|server] could also be NULL in case 698*67c90040Ssemery * of error in this function, see out_err above. The pointers clientp 699*67c90040Ssemery * and serverp reference the input argument in my_creds for 700*67c90040Ssemery * get_init_creds and must be freed if the input argument does not 701*67c90040Ssemery * match the output argument, which occurs during a successful call 702*67c90040Ssemery * to get_init_creds. 703*67c90040Ssemery */ 704*67c90040Ssemery if (clientp && my_creds->client && clientp != my_creds->client) 705*67c90040Ssemery krb5_free_principal(kmd->kcontext, clientp); 706*67c90040Ssemery if (serverp && my_creds->server && serverp != my_creds->server) 707*67c90040Ssemery krb5_free_principal(kmd->kcontext, serverp); 708*67c90040Ssemery 7097c478bd9Sstevel@tonic-gate if (kmd->kcontext) { 7107c478bd9Sstevel@tonic-gate krb5_free_context(kmd->kcontext); 7117c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 7127c478bd9Sstevel@tonic-gate } 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate if (kmd->debug) 7153bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 7167c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth returning %d", 7177c478bd9Sstevel@tonic-gate result); 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate return (kmd->auth_status = result); 7207c478bd9Sstevel@tonic-gate } 7217c478bd9Sstevel@tonic-gate 7227c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7237c478bd9Sstevel@tonic-gate void 7247c478bd9Sstevel@tonic-gate krb5_cleanup(pam_handle_t *pamh, void *data, int pam_status) 7257c478bd9Sstevel@tonic-gate { 7267c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd = (krb5_module_data_t *)data; 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate if (kmd == NULL) 7297c478bd9Sstevel@tonic-gate return; 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate if (kmd->debug) { 7323bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 7333bfb48feSsemery "PAM-KRB5 (auth): krb5_cleanup auth_status = %d", 7347c478bd9Sstevel@tonic-gate kmd->auth_status); 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate /* 738*67c90040Ssemery * Apps could be calling pam_end here, so we should always clean 739*67c90040Ssemery * up regardless of success or failure here. 7407c478bd9Sstevel@tonic-gate */ 741*67c90040Ssemery if (kmd->ccache) 7427c478bd9Sstevel@tonic-gate krb5_cc_close(kmd->kcontext, kmd->ccache); 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate if (kmd->password) { 7457c478bd9Sstevel@tonic-gate (void) memset(kmd->password, 0, strlen(kmd->password)); 7467c478bd9Sstevel@tonic-gate free(kmd->password); 7477c478bd9Sstevel@tonic-gate } 7487c478bd9Sstevel@tonic-gate 749*67c90040Ssemery if (kmd->user) 7503bfb48feSsemery free(kmd->user); 7513bfb48feSsemery 752*67c90040Ssemery if (kmd->env) 753*67c90040Ssemery free(kmd->env); 754*67c90040Ssemery 755*67c90040Ssemery krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 756*67c90040Ssemery (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate free(kmd); 7597c478bd9Sstevel@tonic-gate } 760