17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 53bfb48feSsemery * Common Development and Distribution License (the "License"). 63bfb48feSsemery * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 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 <libintl.h> 297c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 307c478bd9Sstevel@tonic-gate #include <security/pam_modules.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 <pwd.h> 367c478bd9Sstevel@tonic-gate #include <syslog.h> 377c478bd9Sstevel@tonic-gate #include <libintl.h> 387c478bd9Sstevel@tonic-gate #include <krb5.h> 397c478bd9Sstevel@tonic-gate #include <netdb.h> 407c478bd9Sstevel@tonic-gate #include <unistd.h> 417c478bd9Sstevel@tonic-gate #include <sys/stat.h> 427c478bd9Sstevel@tonic-gate #include <fcntl.h> 43505d05c7Sgtb #include <errno.h> 447c478bd9Sstevel@tonic-gate #include <com_err.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #include "utils.h" 477c478bd9Sstevel@tonic-gate #include "krb5_repository.h" 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #define PAMTXD "SUNW_OST_SYSOSPAM" 507c478bd9Sstevel@tonic-gate #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */ 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate extern void krb5_cleanup(pam_handle_t *, void *, int); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate static int attempt_refresh_cred(krb5_module_data_t *, char *, int); 557c478bd9Sstevel@tonic-gate static int attempt_delete_initcred(krb5_module_data_t *); 567c478bd9Sstevel@tonic-gate static krb5_error_code krb5_renew_tgt(krb5_module_data_t *, krb5_principal, 577c478bd9Sstevel@tonic-gate krb5_principal, int); 587c478bd9Sstevel@tonic-gate static krb5_boolean creds_match(krb5_context, const krb5_creds *, 597c478bd9Sstevel@tonic-gate const krb5_creds *); 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate extern uint_t kwarn_add_warning(char *, int); 627c478bd9Sstevel@tonic-gate extern uint_t kwarn_del_warning(char *); 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /* 657c478bd9Sstevel@tonic-gate * pam_sm_setcred 667c478bd9Sstevel@tonic-gate */ 677c478bd9Sstevel@tonic-gate int 687c478bd9Sstevel@tonic-gate pam_sm_setcred( 697c478bd9Sstevel@tonic-gate pam_handle_t *pamh, 707c478bd9Sstevel@tonic-gate int flags, 717c478bd9Sstevel@tonic-gate int argc, 727c478bd9Sstevel@tonic-gate const char **argv) 737c478bd9Sstevel@tonic-gate { 747c478bd9Sstevel@tonic-gate int i; 757c478bd9Sstevel@tonic-gate int err = 0; 767c478bd9Sstevel@tonic-gate int debug = 0; 777c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd = NULL; 783bfb48feSsemery char *user = NULL; 797c478bd9Sstevel@tonic-gate int result; 807c478bd9Sstevel@tonic-gate krb5_repository_data_t *krb5_data = NULL; 817c478bd9Sstevel@tonic-gate pam_repository_t *rep_data = NULL; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 847c478bd9Sstevel@tonic-gate if (strcasecmp(argv[i], "debug") == 0) 857c478bd9Sstevel@tonic-gate debug = 1; 867c478bd9Sstevel@tonic-gate else if (strcasecmp(argv[i], "nowarn") == 0) 877c478bd9Sstevel@tonic-gate flags = flags | PAM_SILENT; 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate if (debug) 913bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 927c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): start: nowarn = %d, flags = 0x%x", 937c478bd9Sstevel@tonic-gate flags & PAM_SILENT ? 1 : 0, flags); 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /* make sure flags are valid */ 967c478bd9Sstevel@tonic-gate if (flags && 977c478bd9Sstevel@tonic-gate !(flags & PAM_ESTABLISH_CRED) && 987c478bd9Sstevel@tonic-gate !(flags & PAM_REINITIALIZE_CRED) && 997c478bd9Sstevel@tonic-gate !(flags & PAM_REFRESH_CRED) && 1007c478bd9Sstevel@tonic-gate !(flags & PAM_DELETE_CRED) && 1017c478bd9Sstevel@tonic-gate !(flags & PAM_SILENT)) { 1023bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 1033bfb48feSsemery "PAM-KRB5 (setcred): illegal flag %d", flags); 1047c478bd9Sstevel@tonic-gate err = PAM_SYSTEM_ERR; 1057c478bd9Sstevel@tonic-gate goto out; 1067c478bd9Sstevel@tonic-gate } 1077c478bd9Sstevel@tonic-gate 1083bfb48feSsemery (void) pam_get_item(pamh, PAM_USER, (void**) &user); 1097c478bd9Sstevel@tonic-gate 1103bfb48feSsemery if (user == NULL || *user == '\0') 1113bfb48feSsemery return (PAM_USER_UNKNOWN); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate if (pam_get_data(pamh, KRB5_DATA, (const void**)&kmd) != PAM_SUCCESS) { 1147c478bd9Sstevel@tonic-gate if (debug) { 1153bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 1167c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): kmd get failed, kmd=0x%p", 1177c478bd9Sstevel@tonic-gate kmd); 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate /* 1217c478bd9Sstevel@tonic-gate * User doesn't need to authenticate for PAM_REFRESH_CRED 1227c478bd9Sstevel@tonic-gate * or for PAM_DELETE_CRED 1237c478bd9Sstevel@tonic-gate */ 1247c478bd9Sstevel@tonic-gate if (flags & (PAM_REFRESH_CRED|PAM_DELETE_CRED)) { 1253bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 1267c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): inst kmd structure"); 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate kmd = calloc(1, sizeof (krb5_module_data_t)); 1297c478bd9Sstevel@tonic-gate 1307c478bd9Sstevel@tonic-gate if (kmd == NULL) { 1317c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 1327c478bd9Sstevel@tonic-gate return (result); 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate if ((err = pam_set_data(pamh, KRB5_DATA, 1367c478bd9Sstevel@tonic-gate kmd, &krb5_cleanup)) != PAM_SUCCESS) { 1377c478bd9Sstevel@tonic-gate free(kmd); 1387c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate } else { 141*3441f6a1Ssemery /* 142*3441f6a1Ssemery * This could mean that we are not the account authority 143*3441f6a1Ssemery * for the authenticated user. Therefore we should 144*3441f6a1Ssemery * return PAM_IGNORE in order to not affect the 145*3441f6a1Ssemery * login process of said user. 146*3441f6a1Ssemery */ 147*3441f6a1Ssemery err = PAM_IGNORE; 148*3441f6a1Ssemery goto out; 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate } else { /* pam_get_data success */ 1527c478bd9Sstevel@tonic-gate if (kmd == NULL) { 1537c478bd9Sstevel@tonic-gate if (debug) { 1543bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 1557c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): kmd structure" 1567c478bd9Sstevel@tonic-gate " gotten but is NULL for user %s", user); 1577c478bd9Sstevel@tonic-gate } 1587c478bd9Sstevel@tonic-gate err = PAM_CRED_UNAVAIL; 1597c478bd9Sstevel@tonic-gate goto out; 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate if (debug) 1633bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 1647c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): kmd auth_status: %s", 1657c478bd9Sstevel@tonic-gate pam_strerror(pamh, kmd->auth_status)); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * pam_auth has set status to ignore, so we also return ignore 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate if (kmd->auth_status == PAM_IGNORE) { 1717c478bd9Sstevel@tonic-gate err = PAM_IGNORE; 1727c478bd9Sstevel@tonic-gate goto out; 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate 1767c478bd9Sstevel@tonic-gate kmd->debug = debug; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* 1797c478bd9Sstevel@tonic-gate * User must have passed pam_authenticate() 1807c478bd9Sstevel@tonic-gate * in order to use PAM_ESTABLISH_CRED or PAM_REINITIALIZE_CRED 1817c478bd9Sstevel@tonic-gate */ 1827c478bd9Sstevel@tonic-gate if ((flags & (PAM_ESTABLISH_CRED|PAM_REINITIALIZE_CRED)) && 1837c478bd9Sstevel@tonic-gate (kmd->auth_status != PAM_SUCCESS)) { 1847c478bd9Sstevel@tonic-gate if (kmd->debug) 1853bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 1867c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): unable to " 1877c478bd9Sstevel@tonic-gate "setcreds, not authenticated!"); 1887c478bd9Sstevel@tonic-gate return (PAM_CRED_UNAVAIL); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * We cannot assume that kmd->kcontext being non-NULL 1937c478bd9Sstevel@tonic-gate * means it is valid. Other pam_krb5 mods may have 1947c478bd9Sstevel@tonic-gate * freed it but not reset it to NULL. 1957c478bd9Sstevel@tonic-gate * Log a message when debugging to track down memory 1967c478bd9Sstevel@tonic-gate * leaks. 1977c478bd9Sstevel@tonic-gate */ 1987c478bd9Sstevel@tonic-gate if (kmd->kcontext != NULL && kmd->debug) 1993bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2007c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): kcontext != NULL, " 2017c478bd9Sstevel@tonic-gate "possible memory leak."); 2027c478bd9Sstevel@tonic-gate 2033bfb48feSsemery /* 2043bfb48feSsemery * Use the authenticated and validated user, if applicable. 2053bfb48feSsemery */ 2063bfb48feSsemery if (kmd->user != NULL) 2073bfb48feSsemery user = kmd->user; 2083bfb48feSsemery 2097c478bd9Sstevel@tonic-gate /* 2107c478bd9Sstevel@tonic-gate * If auth was short-circuited we will not have anything to 2117c478bd9Sstevel@tonic-gate * renew, so just return here. 2127c478bd9Sstevel@tonic-gate */ 2133bfb48feSsemery (void) pam_get_item(pamh, PAM_REPOSITORY, (void **)&rep_data); 2143bfb48feSsemery 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 (setcred): 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 (setcred): " 2347c478bd9Sstevel@tonic-gate "Principal %s already " 2357c478bd9Sstevel@tonic-gate "authenticated, " 2367c478bd9Sstevel@tonic-gate "cannot setcred", 2377c478bd9Sstevel@tonic-gate krb5_data->principal); 2387c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate if (flags & PAM_REINITIALIZE_CRED) 2447c478bd9Sstevel@tonic-gate err = attempt_refresh_cred(kmd, user, PAM_REINITIALIZE_CRED); 2457c478bd9Sstevel@tonic-gate else if (flags & PAM_REFRESH_CRED) 2467c478bd9Sstevel@tonic-gate err = attempt_refresh_cred(kmd, user, PAM_REFRESH_CRED); 2477c478bd9Sstevel@tonic-gate else if (flags & PAM_DELETE_CRED) 2487c478bd9Sstevel@tonic-gate err = attempt_delete_initcred(kmd); 2497c478bd9Sstevel@tonic-gate else { 2507c478bd9Sstevel@tonic-gate /* 2517c478bd9Sstevel@tonic-gate * Default case: PAM_ESTABLISH_CRED 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate err = attempt_refresh_cred(kmd, user, PAM_ESTABLISH_CRED); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2563bfb48feSsemery if (err != PAM_SUCCESS) 2573bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 2587c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): pam_setcred failed " 2597c478bd9Sstevel@tonic-gate "for %s (%s).", user, pam_strerror(pamh, err)); 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate out: 2627c478bd9Sstevel@tonic-gate if (kmd && kmd->kcontext) { 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * free 'kcontext' field if it is allocated, 2657c478bd9Sstevel@tonic-gate * kcontext is local to the operation being performed 2667c478bd9Sstevel@tonic-gate * not considered global to the entire pam module. 2677c478bd9Sstevel@tonic-gate */ 2687c478bd9Sstevel@tonic-gate krb5_free_context(kmd->kcontext); 2697c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 2707c478bd9Sstevel@tonic-gate } 2717c478bd9Sstevel@tonic-gate 2727c478bd9Sstevel@tonic-gate /* 2737c478bd9Sstevel@tonic-gate * 'kmd' is not freed here, it is handled in krb5_cleanup 2747c478bd9Sstevel@tonic-gate */ 2757c478bd9Sstevel@tonic-gate if (debug) 2763bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 2777c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): end: %s", 2787c478bd9Sstevel@tonic-gate pam_strerror(pamh, err)); 2797c478bd9Sstevel@tonic-gate return (err); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate static int 2837c478bd9Sstevel@tonic-gate attempt_refresh_cred( 2847c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd, 2857c478bd9Sstevel@tonic-gate char *user, 2867c478bd9Sstevel@tonic-gate int flag) 2877c478bd9Sstevel@tonic-gate { 2887c478bd9Sstevel@tonic-gate krb5_principal me; 2897c478bd9Sstevel@tonic-gate krb5_principal server; 2907c478bd9Sstevel@tonic-gate krb5_error_code code; 2917c478bd9Sstevel@tonic-gate char kuser[2*MAXHOSTNAMELEN]; 2927c478bd9Sstevel@tonic-gate krb5_data tgtname = { 2937c478bd9Sstevel@tonic-gate 0, 2947c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE, 2957c478bd9Sstevel@tonic-gate KRB5_TGS_NAME 2967c478bd9Sstevel@tonic-gate }; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate /* User must have passed pam_authenticate() */ 2997c478bd9Sstevel@tonic-gate if (kmd->auth_status != PAM_SUCCESS) { 3007c478bd9Sstevel@tonic-gate if (kmd->debug) 3013bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3027c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): unable to " 3037c478bd9Sstevel@tonic-gate "setcreds, not authenticated!"); 3047c478bd9Sstevel@tonic-gate return (PAM_CRED_UNAVAIL); 3057c478bd9Sstevel@tonic-gate } 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gate /* Create a new context here. */ 3087c478bd9Sstevel@tonic-gate if (krb5_init_context(&kmd->kcontext) != 0) { 3097c478bd9Sstevel@tonic-gate if (kmd->debug) 3103bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3117c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): unable to " 3127c478bd9Sstevel@tonic-gate "initialize krb5 context"); 3137c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate if (krb5_cc_default(kmd->kcontext, &kmd->ccache) != 0) { 3173bfb48feSsemery return (PAM_SYSTEM_ERR); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate if ((code = get_kmd_kuser(kmd->kcontext, (const char *)user, kuser, 3217c478bd9Sstevel@tonic-gate 2*MAXHOSTNAMELEN)) != 0) { 3227c478bd9Sstevel@tonic-gate return (code); 3237c478bd9Sstevel@tonic-gate } 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate if (krb5_parse_name(kmd->kcontext, kuser, &me) != 0) { 3263bfb48feSsemery return (PAM_SYSTEM_ERR); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate 3297c478bd9Sstevel@tonic-gate if (code = krb5_build_principal_ext(kmd->kcontext, &server, 3307c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 3317c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 3327c478bd9Sstevel@tonic-gate tgtname.length, tgtname.data, 3337c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 3347c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 0)) { 3353bfb48feSsemery krb5_free_principal(kmd->kcontext, me); 3363bfb48feSsemery return (PAM_SYSTEM_ERR); 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate 3397c478bd9Sstevel@tonic-gate code = krb5_renew_tgt(kmd, me, server, flag); 3407c478bd9Sstevel@tonic-gate 3413bfb48feSsemery krb5_free_principal(kmd->kcontext, server); 3423bfb48feSsemery krb5_free_principal(kmd->kcontext, me); 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate if (code) { 3453bfb48feSsemery if (kmd->debug) 3463bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3473bfb48feSsemery "PAM-KRB5(setcred): krb5_renew_tgt() " 3483bfb48feSsemery "failed: %s", error_message((errcode_t)code)); 3497c478bd9Sstevel@tonic-gate return (PAM_CRED_ERR); 3507c478bd9Sstevel@tonic-gate } else { 3517c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate } 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate /* 3567c478bd9Sstevel@tonic-gate * This code will update the credential matching "server" in the user's 3577c478bd9Sstevel@tonic-gate * credential cache. The flag may be set to one of: 3587c478bd9Sstevel@tonic-gate * PAM_ESTABLISH_CRED - Create a new cred cache if one doesnt exist, 3597c478bd9Sstevel@tonic-gate * else refresh the existing one. 3607c478bd9Sstevel@tonic-gate * PAM_REINITIALIZE_CRED - destroy current cred cache and create a new one 3617c478bd9Sstevel@tonic-gate * PAM_REFRESH_CRED - update the existing cred cache (default action) 3627c478bd9Sstevel@tonic-gate */ 3637c478bd9Sstevel@tonic-gate static krb5_error_code 3647c478bd9Sstevel@tonic-gate krb5_renew_tgt( 3657c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd, 3667c478bd9Sstevel@tonic-gate krb5_principal me, 3677c478bd9Sstevel@tonic-gate krb5_principal server, 3687c478bd9Sstevel@tonic-gate int flag) 3697c478bd9Sstevel@tonic-gate { 3707c478bd9Sstevel@tonic-gate krb5_error_code retval; 3717c478bd9Sstevel@tonic-gate krb5_creds creds; 3721dac1dbeSgtb krb5_creds *renewed_cred = NULL; 3737c478bd9Sstevel@tonic-gate char *client_name = NULL; 3747c478bd9Sstevel@tonic-gate typedef struct _cred_node { 3757c478bd9Sstevel@tonic-gate krb5_creds *creds; 3767c478bd9Sstevel@tonic-gate struct _cred_node *next; 3777c478bd9Sstevel@tonic-gate } cred_node; 3787c478bd9Sstevel@tonic-gate cred_node *cred_list_head = NULL; 3797c478bd9Sstevel@tonic-gate cred_node *fetched = NULL; 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gate #define my_creds (kmd->initcreds) 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate if ((flag != PAM_REFRESH_CRED) && 3847c478bd9Sstevel@tonic-gate (flag != PAM_REINITIALIZE_CRED) && 3857c478bd9Sstevel@tonic-gate (flag != PAM_ESTABLISH_CRED)) 3863bfb48feSsemery return (KRB5KRB_ERR_GENERIC); 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* this is needed only for the ktkt_warnd */ 3893bfb48feSsemery if ((retval = krb5_unparse_name(kmd->kcontext, me, &client_name)) != 0) 3903bfb48feSsemery return (retval); 3917c478bd9Sstevel@tonic-gate 3921dac1dbeSgtb (void) memset(&creds, 0, sizeof (krb5_creds)); 3937c478bd9Sstevel@tonic-gate if ((retval = krb5_copy_principal(kmd->kcontext, 3941dac1dbeSgtb server, &creds.server))) { 3957c478bd9Sstevel@tonic-gate if (kmd->debug) 3963bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 3977c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): krb5_copy_principal " 3987c478bd9Sstevel@tonic-gate "failed: %s", 3997c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 4007c478bd9Sstevel@tonic-gate goto cleanup_creds; 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate /* obtain ticket & session key */ 4047c478bd9Sstevel@tonic-gate retval = krb5_cc_get_principal(kmd->kcontext, 4051dac1dbeSgtb kmd->ccache, &creds.client); 4067c478bd9Sstevel@tonic-gate if (retval && (kmd->debug)) 4073bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4087c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): User not in cred " 4093bfb48feSsemery "cache (%s)", error_message((errcode_t)retval)); 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate if ((retval == KRB5_FCC_NOFILE) && 4127c478bd9Sstevel@tonic-gate (flag & (PAM_ESTABLISH_CRED|PAM_REINITIALIZE_CRED))) { 4137c478bd9Sstevel@tonic-gate /* 4147c478bd9Sstevel@tonic-gate * Create a fresh ccache, and store the credentials 4157c478bd9Sstevel@tonic-gate * we got from pam_authenticate() 4167c478bd9Sstevel@tonic-gate */ 4177c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_initialize(kmd->kcontext, 4187c478bd9Sstevel@tonic-gate kmd->ccache, me)) != 0) { 4193bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4207c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): krb5_cc_initialize " 4217c478bd9Sstevel@tonic-gate "failed: %s", 4227c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 4237c478bd9Sstevel@tonic-gate goto cleanup_creds; 4247c478bd9Sstevel@tonic-gate } else if ((retval = krb5_cc_store_cred(kmd->kcontext, 4257c478bd9Sstevel@tonic-gate kmd->ccache, &my_creds)) != 0) { 4263bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4277c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): krb5_cc_store_cred " 4287c478bd9Sstevel@tonic-gate "failed: %s", 4297c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 4307c478bd9Sstevel@tonic-gate goto cleanup_creds; 4317c478bd9Sstevel@tonic-gate } 4327c478bd9Sstevel@tonic-gate } else if (retval) { 4337c478bd9Sstevel@tonic-gate /* 4347c478bd9Sstevel@tonic-gate * We failed to get the user's credentials. 4357c478bd9Sstevel@tonic-gate * This might be due to permission error on the cache, 4367c478bd9Sstevel@tonic-gate * or maybe we are looking in the wrong cache file! 4377c478bd9Sstevel@tonic-gate */ 4383bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 4397c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): Cannot find creds" 4403bfb48feSsemery " for %s (%s)", 4417c478bd9Sstevel@tonic-gate client_name ? client_name : "(unknown)", 4427c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 4437c478bd9Sstevel@tonic-gate 4447c478bd9Sstevel@tonic-gate } else if (flag & PAM_REINITIALIZE_CRED) { 4457c478bd9Sstevel@tonic-gate /* 4467c478bd9Sstevel@tonic-gate * This destroys the credential cache, and stores a new 4477c478bd9Sstevel@tonic-gate * krbtgt with updated startime, endtime and renewable 4487c478bd9Sstevel@tonic-gate * lifetime. 4497c478bd9Sstevel@tonic-gate */ 4507c478bd9Sstevel@tonic-gate creds.times.starttime = my_creds.times.starttime; 4517c478bd9Sstevel@tonic-gate creds.times.endtime = my_creds.times.endtime; 4527c478bd9Sstevel@tonic-gate creds.times.renew_till = my_creds.times.renew_till; 4537c478bd9Sstevel@tonic-gate if ((retval = krb5_get_credentials_renew(kmd->kcontext, 0, 4541dac1dbeSgtb kmd->ccache, &creds, &renewed_cred))) { 4557c478bd9Sstevel@tonic-gate if (kmd->debug) 4563bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 4577c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): krb5_get_credentials", 4587c478bd9Sstevel@tonic-gate "_renew(reinitialize) failed: %s", 4597c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 4607c478bd9Sstevel@tonic-gate /* perhaps the tgt lifetime has expired */ 4617c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_initialize(kmd->kcontext, 4627c478bd9Sstevel@tonic-gate kmd->ccache, me)) != 0) { 4637c478bd9Sstevel@tonic-gate goto cleanup_creds; 4647c478bd9Sstevel@tonic-gate } else if ((retval = krb5_cc_store_cred(kmd->kcontext, 4657c478bd9Sstevel@tonic-gate kmd->ccache, &my_creds)) != 0) { 4667c478bd9Sstevel@tonic-gate goto cleanup_creds; 4677c478bd9Sstevel@tonic-gate } 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate } else { 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * Creds already exist, update them if possible. 4727c478bd9Sstevel@tonic-gate * We got here either with the ESTABLISH or REFRESH flag. 4737c478bd9Sstevel@tonic-gate * 4747c478bd9Sstevel@tonic-gate * The credential cache does exist, and we are going to 4757c478bd9Sstevel@tonic-gate * read in each cred, looking for our own. When we find 4767c478bd9Sstevel@tonic-gate * a matching credential, we will update it, and store it. 4777c478bd9Sstevel@tonic-gate * Any nonmatching credentials are stored as is. 4787c478bd9Sstevel@tonic-gate * 4797c478bd9Sstevel@tonic-gate * Rules: 4807c478bd9Sstevel@tonic-gate * TGT must exist in cache to get to this point. 4817c478bd9Sstevel@tonic-gate * if flag == ESTABLISH 4827c478bd9Sstevel@tonic-gate * refresh it if possible, else overwrite 4837c478bd9Sstevel@tonic-gate * with new TGT, other tickets in cache remain 4847c478bd9Sstevel@tonic-gate * unchanged. 4857c478bd9Sstevel@tonic-gate * else if flag == REFRESH 4867c478bd9Sstevel@tonic-gate * refresh it if possible, else return error. 4877c478bd9Sstevel@tonic-gate * - Will not work if "R" flag is not set in 4887c478bd9Sstevel@tonic-gate * original cred, we dont want to 2nd guess the 4897c478bd9Sstevel@tonic-gate * intention of the person who created the 4907c478bd9Sstevel@tonic-gate * existing TGT. 4917c478bd9Sstevel@tonic-gate * 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate krb5_cc_cursor cursor; 4947c478bd9Sstevel@tonic-gate krb5_creds nextcred; 4957c478bd9Sstevel@tonic-gate boolean_t found = 0; 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_start_seq_get(kmd->kcontext, 4987c478bd9Sstevel@tonic-gate kmd->ccache, &cursor)) != 0) 4997c478bd9Sstevel@tonic-gate goto cleanup_creds; 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate while ((krb5_cc_next_cred(kmd->kcontext, kmd->ccache, 5027c478bd9Sstevel@tonic-gate &cursor, &nextcred) == 0)) { 5037c478bd9Sstevel@tonic-gate /* if two creds match, we just update the first */ 5047c478bd9Sstevel@tonic-gate if ((!found) && (creds_match(kmd->kcontext, 5057c478bd9Sstevel@tonic-gate &nextcred, &creds))) { 5067c478bd9Sstevel@tonic-gate /* 5077c478bd9Sstevel@tonic-gate * Mark it as found, don't store it 5087c478bd9Sstevel@tonic-gate * in the list or else it will be 5097c478bd9Sstevel@tonic-gate * stored twice later. 5107c478bd9Sstevel@tonic-gate */ 5117c478bd9Sstevel@tonic-gate found = 1; 5127c478bd9Sstevel@tonic-gate } else { 5137c478bd9Sstevel@tonic-gate /* 5147c478bd9Sstevel@tonic-gate * Add a new node to the list 5157c478bd9Sstevel@tonic-gate * of creds that must be replaced 5167c478bd9Sstevel@tonic-gate * in the cache later. 5177c478bd9Sstevel@tonic-gate */ 5187c478bd9Sstevel@tonic-gate cred_node *newnode = (cred_node *)malloc( 5197c478bd9Sstevel@tonic-gate sizeof (cred_node)); 5207c478bd9Sstevel@tonic-gate if (newnode == NULL) { 5217c478bd9Sstevel@tonic-gate retval = ENOMEM; 5227c478bd9Sstevel@tonic-gate goto cleanup_creds; 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate newnode->creds = NULL; 5257c478bd9Sstevel@tonic-gate newnode->next = NULL; 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate if (cred_list_head == NULL) { 5287c478bd9Sstevel@tonic-gate cred_list_head = newnode; 5297c478bd9Sstevel@tonic-gate fetched = cred_list_head; 5307c478bd9Sstevel@tonic-gate } else { 5317c478bd9Sstevel@tonic-gate fetched->next = newnode; 5327c478bd9Sstevel@tonic-gate fetched = fetched->next; 5337c478bd9Sstevel@tonic-gate } 5347c478bd9Sstevel@tonic-gate retval = krb5_copy_creds(kmd->kcontext, 5357c478bd9Sstevel@tonic-gate &nextcred, &fetched->creds); 5367c478bd9Sstevel@tonic-gate if (retval) 5377c478bd9Sstevel@tonic-gate goto cleanup_creds; 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate } 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_end_seq_get(kmd->kcontext, 5427c478bd9Sstevel@tonic-gate kmd->ccache, &cursor)) != 0) 5437c478bd9Sstevel@tonic-gate goto cleanup_creds; 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate /* 5467c478bd9Sstevel@tonic-gate * If we found a matching cred, renew it. 5477c478bd9Sstevel@tonic-gate * This destroys the credential cache, if and only 5487c478bd9Sstevel@tonic-gate * if it passes. 5497c478bd9Sstevel@tonic-gate */ 5507c478bd9Sstevel@tonic-gate if (found && 5517c478bd9Sstevel@tonic-gate (retval = krb5_get_credentials_renew(kmd->kcontext, 5521dac1dbeSgtb 0, kmd->ccache, &creds, &renewed_cred))) { 5537c478bd9Sstevel@tonic-gate if (kmd->debug) 5543bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 5557c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): krb5_get_credentials" 5567c478bd9Sstevel@tonic-gate "_renew(update) failed: %s", 5577c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 5587c478bd9Sstevel@tonic-gate /* 5597c478bd9Sstevel@tonic-gate * If we only wanted to refresh the creds but failed 5607c478bd9Sstevel@tonic-gate * due to expiration, lack of "R" flag, or other 5617c478bd9Sstevel@tonic-gate * problems, return an error. If we were trying to 5627c478bd9Sstevel@tonic-gate * establish new creds, add them to the cache. 5637c478bd9Sstevel@tonic-gate */ 5647c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_initialize(kmd->kcontext, 5657c478bd9Sstevel@tonic-gate kmd->ccache, me)) != 0) { 5667c478bd9Sstevel@tonic-gate goto cleanup_creds; 5677c478bd9Sstevel@tonic-gate } else if ((retval = krb5_cc_store_cred(kmd->kcontext, 5687c478bd9Sstevel@tonic-gate kmd->ccache, &my_creds)) != 0) { 5697c478bd9Sstevel@tonic-gate goto cleanup_creds; 5707c478bd9Sstevel@tonic-gate } 5717c478bd9Sstevel@tonic-gate } 5727c478bd9Sstevel@tonic-gate /* 5737c478bd9Sstevel@tonic-gate * If no matching creds were found, we must 5747c478bd9Sstevel@tonic-gate * initialize the cache before we can store stuff 5757c478bd9Sstevel@tonic-gate * in it. 5767c478bd9Sstevel@tonic-gate */ 5777c478bd9Sstevel@tonic-gate if (!found) { 5787c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_initialize(kmd->kcontext, 5797c478bd9Sstevel@tonic-gate kmd->ccache, me)) != 0) { 5807c478bd9Sstevel@tonic-gate goto cleanup_creds; 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate /* now store all the other tickets */ 5857c478bd9Sstevel@tonic-gate fetched = cred_list_head; 5867c478bd9Sstevel@tonic-gate while (fetched != NULL) { 5877c478bd9Sstevel@tonic-gate retval = krb5_cc_store_cred(kmd->kcontext, 5887c478bd9Sstevel@tonic-gate kmd->ccache, fetched->creds); 5897c478bd9Sstevel@tonic-gate fetched = fetched->next; 5907c478bd9Sstevel@tonic-gate if (retval) { 5917c478bd9Sstevel@tonic-gate if (kmd->debug) 5923bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 5937c478bd9Sstevel@tonic-gate "PAM-KRB5(setcred): krb5_cc_store_cred() " 5947c478bd9Sstevel@tonic-gate "failed: %s", 5957c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 5967c478bd9Sstevel@tonic-gate goto cleanup_creds; 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate cleanup_creds: 6027c478bd9Sstevel@tonic-gate /* Cleanup the list of creds read from the cache if necessary */ 6037c478bd9Sstevel@tonic-gate fetched = cred_list_head; 6047c478bd9Sstevel@tonic-gate while (fetched != NULL) { 6057c478bd9Sstevel@tonic-gate cred_node *old = fetched; 6067c478bd9Sstevel@tonic-gate /* Free the contents and the cred structure itself */ 6077c478bd9Sstevel@tonic-gate krb5_free_creds(kmd->kcontext, fetched->creds); 6087c478bd9Sstevel@tonic-gate fetched = fetched->next; 6097c478bd9Sstevel@tonic-gate free(old); 6107c478bd9Sstevel@tonic-gate } 6117c478bd9Sstevel@tonic-gate 6127c478bd9Sstevel@tonic-gate if ((retval == 0) && (client_name != NULL)) { 6137c478bd9Sstevel@tonic-gate /* 6147c478bd9Sstevel@tonic-gate * Credential update was successful! 6157c478bd9Sstevel@tonic-gate * 6167c478bd9Sstevel@tonic-gate * We now chown the ccache to the appropriate uid/gid 6177c478bd9Sstevel@tonic-gate * combination, if its a FILE based ccache. 6187c478bd9Sstevel@tonic-gate */ 6197c478bd9Sstevel@tonic-gate if (strstr(kmd->env, "FILE:")) { 6207c478bd9Sstevel@tonic-gate uid_t uuid; 6217c478bd9Sstevel@tonic-gate gid_t ugid; 6227c478bd9Sstevel@tonic-gate char *username = NULL, *tmpname = NULL; 6237c478bd9Sstevel@tonic-gate char *filepath = NULL; 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate username = strdup(client_name); 6267c478bd9Sstevel@tonic-gate if ((tmpname = strchr(username, '@'))) 6277c478bd9Sstevel@tonic-gate *tmpname = '\0'; 6287c478bd9Sstevel@tonic-gate 6297c478bd9Sstevel@tonic-gate if (get_pw_uid(username, &uuid) == 0 || 6307c478bd9Sstevel@tonic-gate get_pw_gid(username, &ugid) == 0) { 6313bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 6323bfb48feSsemery "PAM-KRB5 (setcred): Unable to " 6337c478bd9Sstevel@tonic-gate "find matching uid/gid pair for user `%s'", 6347c478bd9Sstevel@tonic-gate username); 6351dac1dbeSgtb retval = KRB5KRB_ERR_GENERIC; 6361dac1dbeSgtb goto error; 6377c478bd9Sstevel@tonic-gate } 6387c478bd9Sstevel@tonic-gate if (!(filepath = strchr(kmd->env, ':')) || 6397c478bd9Sstevel@tonic-gate !(filepath+1)) { 6403bfb48feSsemery __pam_log(LOG_AUTH | LOG_ERR, 6417c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): Invalid pathname " 6427c478bd9Sstevel@tonic-gate "for credential cache of user `%s'", 6437c478bd9Sstevel@tonic-gate username); 6441dac1dbeSgtb retval = KRB5KRB_ERR_GENERIC; 6451dac1dbeSgtb goto error; 6467c478bd9Sstevel@tonic-gate } 6477c478bd9Sstevel@tonic-gate if (chown(filepath+1, uuid, ugid)) { 6487c478bd9Sstevel@tonic-gate if (kmd->debug) 6493bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 6507c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): chown to user " 6517c478bd9Sstevel@tonic-gate "`%s' failed for FILE=%s", 6527c478bd9Sstevel@tonic-gate username, filepath); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate 6557c478bd9Sstevel@tonic-gate free(username); 6567c478bd9Sstevel@tonic-gate } 6571dac1dbeSgtb } 6587c478bd9Sstevel@tonic-gate 6591dac1dbeSgtb error: 6601dac1dbeSgtb if (retval == 0) { 6611dac1dbeSgtb krb5_timestamp endtime; 6621dac1dbeSgtb 6631dac1dbeSgtb if (renewed_cred && renewed_cred->times.endtime != 0) 6641dac1dbeSgtb endtime = renewed_cred->times.endtime; 6651dac1dbeSgtb else 6661dac1dbeSgtb endtime = my_creds.times.endtime; 6671dac1dbeSgtb 6681dac1dbeSgtb if (kmd->debug) 6691dac1dbeSgtb __pam_log(LOG_AUTH | LOG_DEBUG, 6701dac1dbeSgtb "PAM-KRB5 (setcred): delete/add warning"); 6711dac1dbeSgtb 6721dac1dbeSgtb kwarn_del_warning(client_name); 6731dac1dbeSgtb if (kwarn_add_warning(client_name, endtime) != 0) { 6741dac1dbeSgtb __pam_log(LOG_AUTH | LOG_NOTICE, 6751dac1dbeSgtb "PAM-KRB5 (setcred): kwarn_add_warning" 6761dac1dbeSgtb " failed: ktkt_warnd(1M) down?"); 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate } 6791dac1dbeSgtb 6801dac1dbeSgtb if (renewed_cred != NULL) 6811dac1dbeSgtb krb5_free_creds(kmd->kcontext, renewed_cred); 6821dac1dbeSgtb 6837c478bd9Sstevel@tonic-gate if (client_name != NULL) 6847c478bd9Sstevel@tonic-gate free(client_name); 6857c478bd9Sstevel@tonic-gate 6867c478bd9Sstevel@tonic-gate krb5_free_cred_contents(kmd->kcontext, &creds); 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate return (retval); 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate static krb5_boolean 6927c478bd9Sstevel@tonic-gate creds_match(krb5_context ctx, const krb5_creds *mcreds, 6937c478bd9Sstevel@tonic-gate const krb5_creds *creds) 6947c478bd9Sstevel@tonic-gate { 6957c478bd9Sstevel@tonic-gate char *s1, *s2, *c1, *c2; 6967c478bd9Sstevel@tonic-gate krb5_unparse_name(ctx, mcreds->client, &c1); 6977c478bd9Sstevel@tonic-gate krb5_unparse_name(ctx, mcreds->server, &s1); 6987c478bd9Sstevel@tonic-gate krb5_unparse_name(ctx, creds->client, &c2); 6997c478bd9Sstevel@tonic-gate krb5_unparse_name(ctx, creds->server, &s2); 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate return (krb5_principal_compare(ctx, mcreds->client, creds->client) && 7027c478bd9Sstevel@tonic-gate krb5_principal_compare(ctx, mcreds->server, creds->server)); 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate /* 7067c478bd9Sstevel@tonic-gate * Delete the user's credentials for this session 7077c478bd9Sstevel@tonic-gate */ 7087c478bd9Sstevel@tonic-gate static int 7097c478bd9Sstevel@tonic-gate attempt_delete_initcred(krb5_module_data_t *kmd) 7107c478bd9Sstevel@tonic-gate { 7117c478bd9Sstevel@tonic-gate if (kmd == NULL) 7123bfb48feSsemery return (PAM_SUCCESS); 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate if (kmd->debug) { 7153bfb48feSsemery __pam_log(LOG_AUTH | LOG_DEBUG, 7167c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): deleting user's " 7177c478bd9Sstevel@tonic-gate "credentials (initcreds)"); 7187c478bd9Sstevel@tonic-gate } 7197c478bd9Sstevel@tonic-gate krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 7207c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 7217c478bd9Sstevel@tonic-gate kmd->auth_status = PAM_AUTHINFO_UNAVAIL; 7223bfb48feSsemery return (PAM_SUCCESS); 7237c478bd9Sstevel@tonic-gate } 724