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 */ 21*5ad42b1bSSurya Prakki 227c478bd9Sstevel@tonic-gate /* 238ce3ffdfSPeter Shoults * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 287c478bd9Sstevel@tonic-gate #include <security/pam_modules.h> 297c478bd9Sstevel@tonic-gate #include <security/pam_impl.h> 307c478bd9Sstevel@tonic-gate #include <string.h> 317c478bd9Sstevel@tonic-gate #include <stdio.h> 327c478bd9Sstevel@tonic-gate #include <stdlib.h> 337c478bd9Sstevel@tonic-gate #include <sys/types.h> 347c478bd9Sstevel@tonic-gate #include <sys/stat.h> 357c478bd9Sstevel@tonic-gate #include <pwd.h> 367c478bd9Sstevel@tonic-gate #include <syslog.h> 377c478bd9Sstevel@tonic-gate #include <libintl.h> 387c478bd9Sstevel@tonic-gate #include <k5-int.h> 397c478bd9Sstevel@tonic-gate #include "profile/prof_int.h" 407c478bd9Sstevel@tonic-gate #include <netdb.h> 417c478bd9Sstevel@tonic-gate #include <ctype.h> 427c478bd9Sstevel@tonic-gate #include "utils.h" 437c478bd9Sstevel@tonic-gate #include "krb5_repository.h" 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate #define KRB5_DEFAULT_OPTIONS 0 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate int forwardable_flag = 0; 487c478bd9Sstevel@tonic-gate int renewable_flag = 0; 497c478bd9Sstevel@tonic-gate int proxiable_flag = 0; 507c478bd9Sstevel@tonic-gate int no_address_flag = 0; 517c478bd9Sstevel@tonic-gate profile_options_boolean config_option[] = { 527c478bd9Sstevel@tonic-gate { "forwardable", &forwardable_flag, 0 }, 537c478bd9Sstevel@tonic-gate { "renewable", &renewable_flag, 0 }, 547c478bd9Sstevel@tonic-gate { "proxiable", &proxiable_flag, 0 }, 557c478bd9Sstevel@tonic-gate { "no_addresses", &no_address_flag, 0 }, 567c478bd9Sstevel@tonic-gate { NULL, NULL, 0 } 577c478bd9Sstevel@tonic-gate }; 587c478bd9Sstevel@tonic-gate char *renew_timeval; 597c478bd9Sstevel@tonic-gate char *life_timeval; 607c478bd9Sstevel@tonic-gate profile_option_strings config_times[] = { 617c478bd9Sstevel@tonic-gate { "max_life", &life_timeval, 0 }, 627c478bd9Sstevel@tonic-gate { "max_renewable_life", &renew_timeval, 0 }, 637c478bd9Sstevel@tonic-gate { NULL, NULL, 0 } 647c478bd9Sstevel@tonic-gate }; 657c478bd9Sstevel@tonic-gate char *realmdef[] = { "realms", NULL, NULL, NULL }; 667c478bd9Sstevel@tonic-gate char *appdef[] = { "appdefaults", "kinit", NULL }; 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate #define krb_realm (*(realmdef + 1)) 697c478bd9Sstevel@tonic-gate 702278144aSsemery int attempt_krb5_auth(krb5_module_data_t *, char *, char **, boolean_t); 717c478bd9Sstevel@tonic-gate void krb5_cleanup(pam_handle_t *, void *, int); 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate extern errcode_t profile_get_options_boolean(); 747c478bd9Sstevel@tonic-gate extern errcode_t profile_get_options_string(); 752278144aSsemery extern int krb5_verifypw(char *, char *, int); 767c478bd9Sstevel@tonic-gate extern krb5_error_code krb5_verify_init_creds(krb5_context, 777c478bd9Sstevel@tonic-gate krb5_creds *, krb5_principal, krb5_keytab, krb5_ccache *, 787c478bd9Sstevel@tonic-gate krb5_verify_init_creds_opt *); 793125ebfcSsemery extern krb5_error_code __krb5_get_init_creds_password(krb5_context, 803125ebfcSsemery krb5_creds *, krb5_principal, char *, krb5_prompter_fct, void *, 813125ebfcSsemery krb5_deltat, char *, krb5_get_init_creds_opt *, 823125ebfcSsemery krb5_kdc_rep **); 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * pam_sm_authenticate - Authenticate user 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate int 887c478bd9Sstevel@tonic-gate pam_sm_authenticate( 897c478bd9Sstevel@tonic-gate pam_handle_t *pamh, 907c478bd9Sstevel@tonic-gate int flags, 917c478bd9Sstevel@tonic-gate int argc, 927c478bd9Sstevel@tonic-gate const char **argv) 937c478bd9Sstevel@tonic-gate { 940be37caaSsemery char *user = NULL; 957c478bd9Sstevel@tonic-gate int err; 967c478bd9Sstevel@tonic-gate int result = PAM_AUTH_ERR; 977c478bd9Sstevel@tonic-gate /* pam.conf options */ 987c478bd9Sstevel@tonic-gate int debug = 0; 997c478bd9Sstevel@tonic-gate int warn = 1; 1007c478bd9Sstevel@tonic-gate /* return an error on password expire */ 1017c478bd9Sstevel@tonic-gate int err_on_exp = 0; 1027c478bd9Sstevel@tonic-gate int i; 1037c478bd9Sstevel@tonic-gate char *password = NULL; 1047c478bd9Sstevel@tonic-gate uid_t pw_uid; 1057c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd = NULL; 1067c478bd9Sstevel@tonic-gate krb5_repository_data_t *krb5_data = NULL; 1077c478bd9Sstevel@tonic-gate pam_repository_t *rep_data = NULL; 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 1107c478bd9Sstevel@tonic-gate if (strcmp(argv[i], "debug") == 0) { 1117c478bd9Sstevel@tonic-gate debug = 1; 1127c478bd9Sstevel@tonic-gate } else if (strcmp(argv[i], "nowarn") == 0) { 1137c478bd9Sstevel@tonic-gate warn = 0; 1147c478bd9Sstevel@tonic-gate } else if (strcmp(argv[i], "err_on_exp") == 0) { 1157c478bd9Sstevel@tonic-gate err_on_exp = 1; 1167c478bd9Sstevel@tonic-gate } else { 1173bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 1183bfb48feSsemery "PAM-KRB5 (auth) unrecognized option %s", 1197c478bd9Sstevel@tonic-gate argv[i]); 1207c478bd9Sstevel@tonic-gate } 1217c478bd9Sstevel@tonic-gate } 1227c478bd9Sstevel@tonic-gate if (flags & PAM_SILENT) warn = 0; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate if (debug) 1253bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 1267c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): pam_sm_authenticate flags=%d", 1277c478bd9Sstevel@tonic-gate flags); 1287c478bd9Sstevel@tonic-gate 1290be37caaSsemery (void) pam_get_item(pamh, PAM_USER, (void**) &user); 1307c478bd9Sstevel@tonic-gate 131a0e56b0eSsemery if (user == NULL || *user == '\0') { 1327c478bd9Sstevel@tonic-gate if (debug) 1333bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 1343bfb48feSsemery "PAM-KRB5 (auth): user empty or null"); 135a0e56b0eSsemery return (PAM_USER_UNKNOWN); 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* make sure a password entry exists for this user */ 1390be37caaSsemery if (!get_pw_uid(user, &pw_uid)) 1400be37caaSsemery return (PAM_USER_UNKNOWN); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * pam_get_data could fail if we are being called for the first time 1447c478bd9Sstevel@tonic-gate * or if the module is not found, PAM_NO_MODULE_DATA is not an error 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate err = pam_get_data(pamh, KRB5_DATA, (const void**)&kmd); 1477c478bd9Sstevel@tonic-gate if (!(err == PAM_SUCCESS || err == PAM_NO_MODULE_DATA)) 1483bfb48feSsemery return (PAM_SYSTEM_ERR); 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate if (kmd == NULL) { 1517c478bd9Sstevel@tonic-gate kmd = calloc(1, sizeof (krb5_module_data_t)); 1527c478bd9Sstevel@tonic-gate if (kmd == NULL) { 1537c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 1547c478bd9Sstevel@tonic-gate goto out; 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate err = pam_set_data(pamh, KRB5_DATA, kmd, &krb5_cleanup); 1587c478bd9Sstevel@tonic-gate if (err != PAM_SUCCESS) { 1597c478bd9Sstevel@tonic-gate free(kmd); 1607c478bd9Sstevel@tonic-gate result = err; 1617c478bd9Sstevel@tonic-gate goto out; 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate if (!kmd->env) { 1667c478bd9Sstevel@tonic-gate char buffer[512]; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate if (snprintf(buffer, sizeof (buffer), 1697c478bd9Sstevel@tonic-gate "%s=FILE:/tmp/krb5cc_%d", 1707c478bd9Sstevel@tonic-gate KRB5_ENV_CCNAME, (int)pw_uid) >= sizeof (buffer)) { 1717c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 1727c478bd9Sstevel@tonic-gate goto out; 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate /* we MUST copy this to the heap for the putenv to work! */ 1767c478bd9Sstevel@tonic-gate kmd->env = strdup(buffer); 1777c478bd9Sstevel@tonic-gate if (!kmd->env) { 1787c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 1797c478bd9Sstevel@tonic-gate goto out; 1807c478bd9Sstevel@tonic-gate } else { 1817c478bd9Sstevel@tonic-gate if (putenv(kmd->env)) { 1827c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 1837c478bd9Sstevel@tonic-gate goto out; 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 18867c90040Ssemery if (kmd->user != NULL) 18967c90040Ssemery free(kmd->user); 1903bfb48feSsemery if ((kmd->user = strdup(user)) == NULL) { 1913bfb48feSsemery result = PAM_BUF_ERR; 1923bfb48feSsemery goto out; 1933bfb48feSsemery } 1943bfb48feSsemery 1957c478bd9Sstevel@tonic-gate kmd->auth_status = PAM_AUTH_ERR; 1967c478bd9Sstevel@tonic-gate kmd->debug = debug; 1977c478bd9Sstevel@tonic-gate kmd->warn = warn; 1987c478bd9Sstevel@tonic-gate kmd->err_on_exp = err_on_exp; 1997c478bd9Sstevel@tonic-gate kmd->ccache = NULL; 2007c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 2017c478bd9Sstevel@tonic-gate kmd->password = NULL; 2027c478bd9Sstevel@tonic-gate kmd->age_status = PAM_SUCCESS; 2037c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* 2067c478bd9Sstevel@tonic-gate * For apps that already did krb5 auth exchange... 2077c478bd9Sstevel@tonic-gate * Now that we've created the kmd structure, we can 2087c478bd9Sstevel@tonic-gate * return SUCCESS. 'kmd' may be needed later by other 2097c478bd9Sstevel@tonic-gate * PAM functions, thats why we wait until this point to 2107c478bd9Sstevel@tonic-gate * return. 2117c478bd9Sstevel@tonic-gate */ 2120be37caaSsemery (void) pam_get_item(pamh, PAM_REPOSITORY, (void **)&rep_data); 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate if (rep_data != NULL) { 2157c478bd9Sstevel@tonic-gate if (strcmp(rep_data->type, KRB5_REPOSITORY_NAME) != 0) { 2167c478bd9Sstevel@tonic-gate if (debug) 2173bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2183bfb48feSsemery "PAM-KRB5 (auth): wrong" 2197c478bd9Sstevel@tonic-gate "repository found (%s), returning " 2207c478bd9Sstevel@tonic-gate "PAM_IGNORE", rep_data->type); 2217c478bd9Sstevel@tonic-gate return (PAM_IGNORE); 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate if (rep_data->scope_len == sizeof (krb5_repository_data_t)) { 2247c478bd9Sstevel@tonic-gate krb5_data = (krb5_repository_data_t *)rep_data->scope; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate if (krb5_data->flags == 2277c478bd9Sstevel@tonic-gate SUNW_PAM_KRB5_ALREADY_AUTHENTICATED && 2287c478bd9Sstevel@tonic-gate krb5_data->principal != NULL && 2297c478bd9Sstevel@tonic-gate strlen(krb5_data->principal)) { 2307c478bd9Sstevel@tonic-gate if (debug) 2313bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2327c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Principal " 2337c478bd9Sstevel@tonic-gate "%s already authenticated", 2347c478bd9Sstevel@tonic-gate krb5_data->principal); 2357c478bd9Sstevel@tonic-gate kmd->auth_status = PAM_SUCCESS; 2367c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * if root key exists in the keytab, it's a random key so no 2437c478bd9Sstevel@tonic-gate * need to prompt for pw and we just return IGNORE. 2447c478bd9Sstevel@tonic-gate * 2457c478bd9Sstevel@tonic-gate * note we don't need to force a prompt for pw as authtok_get 2467c478bd9Sstevel@tonic-gate * is required to be stacked above this module. 2477c478bd9Sstevel@tonic-gate */ 2487c478bd9Sstevel@tonic-gate if ((strcmp(user, ROOT_UNAME) == 0) && 2497c478bd9Sstevel@tonic-gate key_in_keytab(user, debug)) { 2507c478bd9Sstevel@tonic-gate if (debug) 2513bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2527c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): " 2537c478bd9Sstevel@tonic-gate "key for '%s' in keytab, returning IGNORE", user); 2547c478bd9Sstevel@tonic-gate result = PAM_IGNORE; 2557c478bd9Sstevel@tonic-gate goto out; 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2580be37caaSsemery (void) pam_get_item(pamh, PAM_AUTHTOK, (void **)&password); 2597c478bd9Sstevel@tonic-gate 2602278144aSsemery result = attempt_krb5_auth(kmd, user, &password, 1); 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate out: 2637c478bd9Sstevel@tonic-gate if (kmd) { 2647c478bd9Sstevel@tonic-gate if (debug) 2653bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2667c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): pam_sm_auth finalize" 2677c478bd9Sstevel@tonic-gate " ccname env, result =%d, env ='%s'," 2687c478bd9Sstevel@tonic-gate " age = %d, status = %d", 2697c478bd9Sstevel@tonic-gate result, kmd->env ? kmd->env : "<null>", 2707c478bd9Sstevel@tonic-gate kmd->age_status, kmd->auth_status); 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate if (kmd->env && 2737c478bd9Sstevel@tonic-gate !(kmd->age_status == PAM_NEW_AUTHTOK_REQD && 2747c478bd9Sstevel@tonic-gate kmd->auth_status == PAM_SUCCESS)) { 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate if (result == PAM_SUCCESS) { 2787c478bd9Sstevel@tonic-gate /* 2797c478bd9Sstevel@tonic-gate * Put ccname into the pamh so that login 2807c478bd9Sstevel@tonic-gate * apps can pick this up when they run 2817c478bd9Sstevel@tonic-gate * pam_getenvlist(). 2827c478bd9Sstevel@tonic-gate */ 2837c478bd9Sstevel@tonic-gate if ((result = pam_putenv(pamh, kmd->env)) 2847c478bd9Sstevel@tonic-gate != PAM_SUCCESS) { 2857c478bd9Sstevel@tonic-gate /* should not happen but... */ 2863bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 2877c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth):" 2883bfb48feSsemery " pam_putenv failed: result: %d", 2897c478bd9Sstevel@tonic-gate result); 2907c478bd9Sstevel@tonic-gate goto cleanupccname; 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate } else { 2937c478bd9Sstevel@tonic-gate cleanupccname: 2947c478bd9Sstevel@tonic-gate /* for lack of a Solaris unputenv() */ 2957c478bd9Sstevel@tonic-gate krb5_unsetenv(KRB5_ENV_CCNAME); 2967c478bd9Sstevel@tonic-gate free(kmd->env); 2977c478bd9Sstevel@tonic-gate kmd->env = NULL; 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate kmd->auth_status = result; 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate if (debug) 3043bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3057c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): end: %s", pam_strerror(pamh, result)); 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate return (result); 3087c478bd9Sstevel@tonic-gate } 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate int 3117c478bd9Sstevel@tonic-gate attempt_krb5_auth( 3127c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd, 3137c478bd9Sstevel@tonic-gate char *user, 3147c478bd9Sstevel@tonic-gate char **krb5_pass, 3150be37caaSsemery boolean_t verify_tik) 3167c478bd9Sstevel@tonic-gate { 31767c90040Ssemery krb5_principal me = NULL, clientp = NULL; 31867c90040Ssemery krb5_principal server = NULL, serverp = NULL; 3197c478bd9Sstevel@tonic-gate krb5_creds *my_creds; 3207c478bd9Sstevel@tonic-gate krb5_timestamp now; 3217c478bd9Sstevel@tonic-gate krb5_error_code code = 0; 3227c478bd9Sstevel@tonic-gate char kuser[2*MAXHOSTNAMELEN]; 3237c478bd9Sstevel@tonic-gate krb5_deltat lifetime; 3247c478bd9Sstevel@tonic-gate krb5_deltat rlife; 3257c478bd9Sstevel@tonic-gate krb5_deltat krb5_max_duration; 3267c478bd9Sstevel@tonic-gate int options = KRB5_DEFAULT_OPTIONS; 3277c478bd9Sstevel@tonic-gate krb5_data tgtname = { 3287c478bd9Sstevel@tonic-gate 0, 3297c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE, 3307c478bd9Sstevel@tonic-gate KRB5_TGS_NAME 3317c478bd9Sstevel@tonic-gate }; 3327c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt opts; 3333125ebfcSsemery krb5_kdc_rep *as_reply = NULL; 3347c478bd9Sstevel@tonic-gate /* 3357c478bd9Sstevel@tonic-gate * "result" should not be assigned PAM_SUCCESS unless 3367c478bd9Sstevel@tonic-gate * authentication has succeeded and there are no other errors. 3377c478bd9Sstevel@tonic-gate * 3387c478bd9Sstevel@tonic-gate * "code" is sometimes used for PAM codes, sometimes for krb5 3397c478bd9Sstevel@tonic-gate * codes. Be careful. 3407c478bd9Sstevel@tonic-gate */ 3417c478bd9Sstevel@tonic-gate int result = PAM_AUTH_ERR; 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate if (kmd->debug) 3443bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3457c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: start: user='%s'", 3467c478bd9Sstevel@tonic-gate user ? user : "<null>"); 3477c478bd9Sstevel@tonic-gate 3487c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_init(&opts); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate /* need to free context with krb5_free_context */ 3518ce3ffdfSPeter Shoults if (code = krb5_init_secure_context(&kmd->kcontext)) { 3523bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 3537c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Error initializing " 3543bfb48feSsemery "krb5: %s", 3557c478bd9Sstevel@tonic-gate error_message(code)); 3567c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 3577c478bd9Sstevel@tonic-gate } 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate if ((code = get_kmd_kuser(kmd->kcontext, (const char *)user, kuser, 3607c478bd9Sstevel@tonic-gate 2*MAXHOSTNAMELEN)) != 0) { 3617c478bd9Sstevel@tonic-gate /* get_kmd_kuser returns proper PAM error statuses */ 3627c478bd9Sstevel@tonic-gate return (code); 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate if ((code = krb5_parse_name(kmd->kcontext, kuser, &me)) != 0) { 3667c478bd9Sstevel@tonic-gate krb5_free_context(kmd->kcontext); 3677c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 3683bfb48feSsemery return (PAM_SYSTEM_ERR); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* call krb5_free_cred_contents() on error */ 3727c478bd9Sstevel@tonic-gate my_creds = &kmd->initcreds; 3737c478bd9Sstevel@tonic-gate 3743bfb48feSsemery if ((code = 3753bfb48feSsemery krb5_copy_principal(kmd->kcontext, me, &my_creds->client))) { 3763bfb48feSsemery result = PAM_SYSTEM_ERR; 3773bfb48feSsemery goto out_err; 3783bfb48feSsemery } 37967c90040Ssemery clientp = my_creds->client; 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate if (code = krb5_build_principal_ext(kmd->kcontext, &server, 3827c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 3837c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 3847c478bd9Sstevel@tonic-gate tgtname.length, tgtname.data, 3857c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 3867c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 0)) { 3873bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 3883bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth: " 3893bfb48feSsemery "krb5_build_princ_ext failed: %s", 3903bfb48feSsemery error_message(code)); 3913bfb48feSsemery result = PAM_SYSTEM_ERR; 3927c478bd9Sstevel@tonic-gate goto out; 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate if (code = krb5_copy_principal(kmd->kcontext, server, 3967c478bd9Sstevel@tonic-gate &my_creds->server)) { 3973bfb48feSsemery result = PAM_SYSTEM_ERR; 3987c478bd9Sstevel@tonic-gate goto out_err; 3997c478bd9Sstevel@tonic-gate } 40067c90040Ssemery serverp = my_creds->server; 4017c478bd9Sstevel@tonic-gate 4027c478bd9Sstevel@tonic-gate if (code = krb5_timeofday(kmd->kcontext, &now)) { 4033bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4043bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth: " 4053bfb48feSsemery "krb5_timeofday failed: %s", 4063bfb48feSsemery error_message(code)); 4073bfb48feSsemery result = PAM_SYSTEM_ERR; 4087c478bd9Sstevel@tonic-gate goto out; 4097c478bd9Sstevel@tonic-gate } 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate /* 4127c478bd9Sstevel@tonic-gate * set the values for lifetime and rlife to be the maximum 4137c478bd9Sstevel@tonic-gate * possible 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate krb5_max_duration = KRB5_KDB_EXPIRATION - now - 60*60; 4167c478bd9Sstevel@tonic-gate lifetime = krb5_max_duration; 4177c478bd9Sstevel@tonic-gate rlife = krb5_max_duration; 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* 4207c478bd9Sstevel@tonic-gate * Let us get the values for various options 4217c478bd9Sstevel@tonic-gate * from Kerberos configuration file 4227c478bd9Sstevel@tonic-gate */ 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate krb_realm = krb5_princ_realm(kmd->kcontext, me)->data; 4257c478bd9Sstevel@tonic-gate profile_get_options_boolean(kmd->kcontext->profile, 4267c478bd9Sstevel@tonic-gate realmdef, config_option); 4277c478bd9Sstevel@tonic-gate profile_get_options_boolean(kmd->kcontext->profile, 4287c478bd9Sstevel@tonic-gate appdef, config_option); 4297c478bd9Sstevel@tonic-gate profile_get_options_string(kmd->kcontext->profile, 4307c478bd9Sstevel@tonic-gate realmdef, config_times); 4317c478bd9Sstevel@tonic-gate profile_get_options_string(kmd->kcontext->profile, 4327c478bd9Sstevel@tonic-gate appdef, config_times); 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate if (renew_timeval) { 4357c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(renew_timeval, &rlife); 4367c478bd9Sstevel@tonic-gate if (code != 0 || rlife == 0 || rlife > krb5_max_duration) { 4373bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4387c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Bad max_renewable_life " 4393bfb48feSsemery " value '%s' in Kerberos config file", 4407c478bd9Sstevel@tonic-gate renew_timeval); 4417c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 4427c478bd9Sstevel@tonic-gate goto out; 4437c478bd9Sstevel@tonic-gate } 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate if (life_timeval) { 4467c478bd9Sstevel@tonic-gate code = krb5_string_to_deltat(life_timeval, &lifetime); 4477c478bd9Sstevel@tonic-gate if (code != 0 || lifetime == 0 || 4487c478bd9Sstevel@tonic-gate lifetime > krb5_max_duration) { 4493bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4503bfb48feSsemery "lifetime value '%s' in Kerberos config file", 4517c478bd9Sstevel@tonic-gate life_timeval); 4527c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 4537c478bd9Sstevel@tonic-gate goto out; 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate } 4567c478bd9Sstevel@tonic-gate /* start timer when request gets to KDC */ 4577c478bd9Sstevel@tonic-gate my_creds->times.starttime = 0; 4587c478bd9Sstevel@tonic-gate my_creds->times.endtime = now + lifetime; 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate if (options & KDC_OPT_RENEWABLE) { 4617c478bd9Sstevel@tonic-gate my_creds->times.renew_till = now + rlife; 4627c478bd9Sstevel@tonic-gate } else 4637c478bd9Sstevel@tonic-gate my_creds->times.renew_till = 0; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime); 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate if (proxiable_flag) { /* Set in config file */ 4687c478bd9Sstevel@tonic-gate if (kmd->debug) 4693bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4707c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Proxiable tickets " 4713bfb48feSsemery "requested"); 4727c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_proxiable(&opts, TRUE); 4737c478bd9Sstevel@tonic-gate } 4747c478bd9Sstevel@tonic-gate if (forwardable_flag) { 4757c478bd9Sstevel@tonic-gate if (kmd->debug) 4763bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4777c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Forwardable tickets " 4783bfb48feSsemery "requested"); 4797c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_forwardable(&opts, TRUE); 4807c478bd9Sstevel@tonic-gate } 4817c478bd9Sstevel@tonic-gate if (renewable_flag) { 4827c478bd9Sstevel@tonic-gate if (kmd->debug) 4833bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4847c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Renewable tickets " 4853bfb48feSsemery "requested"); 4867c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_renew_life(&opts, rlife); 4877c478bd9Sstevel@tonic-gate } 4887c478bd9Sstevel@tonic-gate if (no_address_flag) { 4897c478bd9Sstevel@tonic-gate if (kmd->debug) 4903bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4917c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): Addressless tickets " 4923bfb48feSsemery "requested"); 4937c478bd9Sstevel@tonic-gate krb5_get_init_creds_opt_set_address_list(&opts, NULL); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * mech_krb5 interprets empty passwords as NULL passwords 4987c478bd9Sstevel@tonic-gate * and tries to read a password from stdin. Since we are in 4997c478bd9Sstevel@tonic-gate * pam this is bad and should not be allowed. 5007c478bd9Sstevel@tonic-gate */ 5017c478bd9Sstevel@tonic-gate if (*krb5_pass == NULL || strlen(*krb5_pass) == 0) { 5027c478bd9Sstevel@tonic-gate code = KRB5KRB_AP_ERR_BAD_INTEGRITY; 5037c478bd9Sstevel@tonic-gate } else { 5043125ebfcSsemery 5053125ebfcSsemery /* 5063125ebfcSsemery * We call our own private version of gic_pwd, because we need 5073125ebfcSsemery * more information, such as password/account expiration, that 5083125ebfcSsemery * is found in the as_reply. The "prompter" interface is not 5093125ebfcSsemery * granular enough for PAM to make use of. 5103125ebfcSsemery */ 5113125ebfcSsemery code = __krb5_get_init_creds_password(kmd->kcontext, 5127c478bd9Sstevel@tonic-gate my_creds, 5137c478bd9Sstevel@tonic-gate me, 5147c478bd9Sstevel@tonic-gate *krb5_pass, /* clear text passwd */ 5157c478bd9Sstevel@tonic-gate NULL, /* prompter */ 5167c478bd9Sstevel@tonic-gate NULL, /* data */ 5177c478bd9Sstevel@tonic-gate 0, /* start time */ 5187c478bd9Sstevel@tonic-gate NULL, /* defaults to krbtgt@REALM */ 5193125ebfcSsemery &opts, 5203125ebfcSsemery &as_reply); 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate if (kmd->debug) 5243bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 5257c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: " 5267c478bd9Sstevel@tonic-gate "krb5_get_init_creds_password returns: %s", 5277c478bd9Sstevel@tonic-gate code == 0 ? "SUCCESS" : error_message(code)); 5287c478bd9Sstevel@tonic-gate 5297c478bd9Sstevel@tonic-gate switch (code) { 5307c478bd9Sstevel@tonic-gate case 0: 5317c478bd9Sstevel@tonic-gate /* got a tgt, let's verify it */ 5327c478bd9Sstevel@tonic-gate if (verify_tik) { 5337c478bd9Sstevel@tonic-gate krb5_verify_init_creds_opt vopts; 5347c478bd9Sstevel@tonic-gate 535a0709436Smp krb5_principal sp = NULL; 536a0709436Smp char kt_name[MAX_KEYTAB_NAME_LEN]; 537a0709436Smp char *fqdn; 538a0709436Smp 5397c478bd9Sstevel@tonic-gate krb5_verify_init_creds_opt_init(&vopts); 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate code = krb5_verify_init_creds(kmd->kcontext, 5427c478bd9Sstevel@tonic-gate my_creds, 5437c478bd9Sstevel@tonic-gate NULL, /* defaults to host/localhost@REALM */ 5447c478bd9Sstevel@tonic-gate NULL, 5457c478bd9Sstevel@tonic-gate NULL, 5467c478bd9Sstevel@tonic-gate &vopts); 5477c478bd9Sstevel@tonic-gate 5487c478bd9Sstevel@tonic-gate if (code) { 5497c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 5507c478bd9Sstevel@tonic-gate 5510be37caaSsemery /* 5520be37caaSsemery * Give a better error message when the 5530be37caaSsemery * keytable entry isn't found or the keytab 5540be37caaSsemery * file cannot be found. 5550be37caaSsemery */ 556a0709436Smp if (krb5_sname_to_principal(kmd->kcontext, NULL, 557a0709436Smp NULL, KRB5_NT_SRV_HST, &sp)) 558a0709436Smp fqdn = "<fqdn>"; 559a0709436Smp else 560a0709436Smp fqdn = sp->data[1].data; 561a0709436Smp 562a0709436Smp if (krb5_kt_default_name(kmd->kcontext, kt_name, 563a0709436Smp sizeof (kt_name))) 564a0709436Smp (void) strncpy(kt_name, 565a0709436Smp "default keytab", 566a0709436Smp sizeof (kt_name)); 567a0709436Smp 568a0709436Smp switch (code) { 569a0709436Smp case KRB5_KT_NOTFOUND: 5703bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 571a0709436Smp "PAM-KRB5 (auth): " 572a0709436Smp "krb5_verify_init_creds failed:" 573a0709436Smp " Key table entry \"host/%s\"" 5743bfb48feSsemery " not found in %s", 575a0709436Smp fqdn, kt_name); 576a0709436Smp break; 577a0709436Smp case ENOENT: 5783bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 579a0709436Smp "PAM-KRB5 (auth): " 580a0709436Smp "krb5_verify_init_creds failed:" 581a0709436Smp " Keytab file \"%s\"" 5823bfb48feSsemery " does not exist.\n", 583a0709436Smp kt_name); 584a0709436Smp break; 585a0709436Smp default: 5863bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 587a0709436Smp "PAM-KRB5 (auth): " 588a0709436Smp "krb5_verify_init_creds failed:" 5893bfb48feSsemery " %s", 590a0709436Smp error_message(code)); 591a0709436Smp break; 592a0709436Smp } 593a0709436Smp 594a0709436Smp if (sp) 595a0709436Smp krb5_free_principal(kmd->kcontext, sp); 5967c478bd9Sstevel@tonic-gate } 5977c478bd9Sstevel@tonic-gate } 5983125ebfcSsemery 5993125ebfcSsemery if (code == 0) 6003125ebfcSsemery kmd->expiration = as_reply->enc_part2->key_exp; 6013125ebfcSsemery 6027c478bd9Sstevel@tonic-gate break; 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN: 6057c478bd9Sstevel@tonic-gate /* 6067c478bd9Sstevel@tonic-gate * Since this principal is not part of the local 6077c478bd9Sstevel@tonic-gate * Kerberos realm, we just return PAM_USER_UNKNOWN. 6087c478bd9Sstevel@tonic-gate */ 6097c478bd9Sstevel@tonic-gate result = PAM_USER_UNKNOWN; 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate if (kmd->debug) 6123bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6133bfb48feSsemery "PAM-KRB5 (auth): attempt_krb5_auth:" 6147c478bd9Sstevel@tonic-gate " User is not part of the local Kerberos" 6157c478bd9Sstevel@tonic-gate " realm: %s", error_message(code)); 6167c478bd9Sstevel@tonic-gate break; 6177c478bd9Sstevel@tonic-gate 6187c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_PREAUTH_FAILED: 6197c478bd9Sstevel@tonic-gate case KRB5KRB_AP_ERR_BAD_INTEGRITY: 6207c478bd9Sstevel@tonic-gate /* 6217c478bd9Sstevel@tonic-gate * We could be trying the password from a previous 6227c478bd9Sstevel@tonic-gate * pam authentication module, but we don't want to 6237c478bd9Sstevel@tonic-gate * generate an error if the unix password is different 6247c478bd9Sstevel@tonic-gate * than the Kerberos password... 6257c478bd9Sstevel@tonic-gate */ 6267c478bd9Sstevel@tonic-gate break; 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate case KRB5KDC_ERR_KEY_EXP: 6297c478bd9Sstevel@tonic-gate if (!kmd->err_on_exp) { 6307c478bd9Sstevel@tonic-gate /* 6317c478bd9Sstevel@tonic-gate * Request a tik for changepw service 6327c478bd9Sstevel@tonic-gate * and it will tell us if pw is good or not. 6337c478bd9Sstevel@tonic-gate */ 6342278144aSsemery code = krb5_verifypw(kuser, *krb5_pass, kmd->debug); 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate if (kmd->debug) 6373bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6387c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth: " 6392278144aSsemery "verifypw %d", code); 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate if (code == 0) { 6427c478bd9Sstevel@tonic-gate /* pw is good, set age status for acct_mgmt */ 6437c478bd9Sstevel@tonic-gate kmd->age_status = PAM_NEW_AUTHTOK_REQD; 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate } 6467c478bd9Sstevel@tonic-gate break; 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate default: 6497c478bd9Sstevel@tonic-gate result = PAM_SYSTEM_ERR; 6507c478bd9Sstevel@tonic-gate if (kmd->debug) 6513bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6523bfb48feSsemery "PAM-KRB5 (auth): error %d - %s", 6537c478bd9Sstevel@tonic-gate code, error_message(code)); 6547c478bd9Sstevel@tonic-gate break; 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate if (code == 0) { 6587c478bd9Sstevel@tonic-gate /* 6597c478bd9Sstevel@tonic-gate * success for the entered pw 6607c478bd9Sstevel@tonic-gate * 6617c478bd9Sstevel@tonic-gate * we can't rely on the pw in PAM_AUTHTOK 6627c478bd9Sstevel@tonic-gate * to be the (correct) krb5 one so 6637c478bd9Sstevel@tonic-gate * store krb5 pw in module data for 6647c478bd9Sstevel@tonic-gate * use in acct_mgmt 6657c478bd9Sstevel@tonic-gate */ 6667c478bd9Sstevel@tonic-gate if (!(kmd->password = strdup(*krb5_pass))) { 6673bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, "Cannot strdup password"); 6687c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 6697c478bd9Sstevel@tonic-gate goto out_err; 6707c478bd9Sstevel@tonic-gate } 6717c478bd9Sstevel@tonic-gate result = PAM_SUCCESS; 6727c478bd9Sstevel@tonic-gate goto out; 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate out_err: 6767c478bd9Sstevel@tonic-gate /* jump (or reach) here if error and cred cache has been init */ 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate if (kmd->debug) 6793bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6807c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): clearing initcreds in " 6817c478bd9Sstevel@tonic-gate "pam_authenticate()"); 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 6847c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate out: 6877c478bd9Sstevel@tonic-gate if (server) 6887c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, server); 6897c478bd9Sstevel@tonic-gate if (me) 6907c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, me); 6913125ebfcSsemery if (as_reply) 6923125ebfcSsemery krb5_free_kdc_rep(kmd->kcontext, as_reply); 69367c90040Ssemery 69467c90040Ssemery /* 69567c90040Ssemery * clientp or serverp could be NULL in certain error cases in this 69667c90040Ssemery * function. mycreds->[client|server] could also be NULL in case 69767c90040Ssemery * of error in this function, see out_err above. The pointers clientp 69867c90040Ssemery * and serverp reference the input argument in my_creds for 69967c90040Ssemery * get_init_creds and must be freed if the input argument does not 70067c90040Ssemery * match the output argument, which occurs during a successful call 70167c90040Ssemery * to get_init_creds. 70267c90040Ssemery */ 70367c90040Ssemery if (clientp && my_creds->client && clientp != my_creds->client) 70467c90040Ssemery krb5_free_principal(kmd->kcontext, clientp); 70567c90040Ssemery if (serverp && my_creds->server && serverp != my_creds->server) 70667c90040Ssemery krb5_free_principal(kmd->kcontext, serverp); 70767c90040Ssemery 7087c478bd9Sstevel@tonic-gate if (kmd->kcontext) { 7097c478bd9Sstevel@tonic-gate krb5_free_context(kmd->kcontext); 7107c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate if (kmd->debug) 7143bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 7157c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): attempt_krb5_auth returning %d", 7167c478bd9Sstevel@tonic-gate result); 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate return (kmd->auth_status = result); 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 7227c478bd9Sstevel@tonic-gate void 7237c478bd9Sstevel@tonic-gate krb5_cleanup(pam_handle_t *pamh, void *data, int pam_status) 7247c478bd9Sstevel@tonic-gate { 7257c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd = (krb5_module_data_t *)data; 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate if (kmd == NULL) 7287c478bd9Sstevel@tonic-gate return; 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate if (kmd->debug) { 7313bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 7323bfb48feSsemery "PAM-KRB5 (auth): krb5_cleanup auth_status = %d", 7337c478bd9Sstevel@tonic-gate kmd->auth_status); 7347c478bd9Sstevel@tonic-gate } 7357c478bd9Sstevel@tonic-gate 7367c478bd9Sstevel@tonic-gate /* 73767c90040Ssemery * Apps could be calling pam_end here, so we should always clean 73867c90040Ssemery * up regardless of success or failure here. 7397c478bd9Sstevel@tonic-gate */ 74067c90040Ssemery if (kmd->ccache) 741*5ad42b1bSSurya Prakki (void) krb5_cc_close(kmd->kcontext, kmd->ccache); 7427c478bd9Sstevel@tonic-gate 7437c478bd9Sstevel@tonic-gate if (kmd->password) { 7447c478bd9Sstevel@tonic-gate (void) memset(kmd->password, 0, strlen(kmd->password)); 7457c478bd9Sstevel@tonic-gate free(kmd->password); 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate 74867c90040Ssemery if (kmd->user) 7493bfb48feSsemery free(kmd->user); 7503bfb48feSsemery 75167c90040Ssemery if (kmd->env) 75267c90040Ssemery free(kmd->env); 75367c90040Ssemery 75467c90040Ssemery krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 75567c90040Ssemery (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 7567c478bd9Sstevel@tonic-gate 7577c478bd9Sstevel@tonic-gate free(kmd); 7587c478bd9Sstevel@tonic-gate } 759