1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <libintl.h> 30*7c478bd9Sstevel@tonic-gate #include <security/pam_appl.h> 31*7c478bd9Sstevel@tonic-gate #include <security/pam_modules.h> 32*7c478bd9Sstevel@tonic-gate #include <string.h> 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 36*7c478bd9Sstevel@tonic-gate #include <pwd.h> 37*7c478bd9Sstevel@tonic-gate #include <syslog.h> 38*7c478bd9Sstevel@tonic-gate #include <libintl.h> 39*7c478bd9Sstevel@tonic-gate #include <krb5.h> 40*7c478bd9Sstevel@tonic-gate #include <netdb.h> 41*7c478bd9Sstevel@tonic-gate #include <unistd.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 43*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 44*7c478bd9Sstevel@tonic-gate #include <com_err.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #include "utils.h" 47*7c478bd9Sstevel@tonic-gate #include "krb5_repository.h" 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #define PAMTXD "SUNW_OST_SYSOSPAM" 50*7c478bd9Sstevel@tonic-gate #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */ 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate extern void krb5_cleanup(pam_handle_t *, void *, int); 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate static int attempt_refresh_cred(krb5_module_data_t *, char *, int); 55*7c478bd9Sstevel@tonic-gate static int attempt_delete_initcred(krb5_module_data_t *); 56*7c478bd9Sstevel@tonic-gate static krb5_error_code krb5_renew_tgt(krb5_module_data_t *, krb5_principal, 57*7c478bd9Sstevel@tonic-gate krb5_principal, int); 58*7c478bd9Sstevel@tonic-gate static krb5_boolean creds_match(krb5_context, const krb5_creds *, 59*7c478bd9Sstevel@tonic-gate const krb5_creds *); 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate extern uint_t kwarn_add_warning(char *, int); 62*7c478bd9Sstevel@tonic-gate extern uint_t kwarn_del_warning(char *); 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate /* 65*7c478bd9Sstevel@tonic-gate * pam_sm_setcred 66*7c478bd9Sstevel@tonic-gate */ 67*7c478bd9Sstevel@tonic-gate int 68*7c478bd9Sstevel@tonic-gate pam_sm_setcred( 69*7c478bd9Sstevel@tonic-gate pam_handle_t *pamh, 70*7c478bd9Sstevel@tonic-gate int flags, 71*7c478bd9Sstevel@tonic-gate int argc, 72*7c478bd9Sstevel@tonic-gate const char **argv) 73*7c478bd9Sstevel@tonic-gate { 74*7c478bd9Sstevel@tonic-gate int i; 75*7c478bd9Sstevel@tonic-gate int err = 0; 76*7c478bd9Sstevel@tonic-gate int debug = 0; 77*7c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd = NULL; 78*7c478bd9Sstevel@tonic-gate char *user; 79*7c478bd9Sstevel@tonic-gate int result; 80*7c478bd9Sstevel@tonic-gate krb5_repository_data_t *krb5_data = NULL; 81*7c478bd9Sstevel@tonic-gate pam_repository_t *rep_data = NULL; 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate for (i = 0; i < argc; i++) { 84*7c478bd9Sstevel@tonic-gate if (strcasecmp(argv[i], "debug") == 0) 85*7c478bd9Sstevel@tonic-gate debug = 1; 86*7c478bd9Sstevel@tonic-gate else if (strcasecmp(argv[i], "nowarn") == 0) 87*7c478bd9Sstevel@tonic-gate flags = flags | PAM_SILENT; 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate if (debug) 91*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 92*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): start: nowarn = %d, flags = 0x%x", 93*7c478bd9Sstevel@tonic-gate flags & PAM_SILENT ? 1 : 0, flags); 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate /* make sure flags are valid */ 96*7c478bd9Sstevel@tonic-gate if (flags && 97*7c478bd9Sstevel@tonic-gate !(flags & PAM_ESTABLISH_CRED) && 98*7c478bd9Sstevel@tonic-gate !(flags & PAM_REINITIALIZE_CRED) && 99*7c478bd9Sstevel@tonic-gate !(flags & PAM_REFRESH_CRED) && 100*7c478bd9Sstevel@tonic-gate !(flags & PAM_DELETE_CRED) && 101*7c478bd9Sstevel@tonic-gate !(flags & PAM_SILENT)) { 102*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 103*7c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, 104*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): illegal flag %d"), flags); 105*7c478bd9Sstevel@tonic-gate err = PAM_SYSTEM_ERR; 106*7c478bd9Sstevel@tonic-gate goto out; 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate err = pam_get_item(pamh, PAM_USER, (void**) &user); 110*7c478bd9Sstevel@tonic-gate if (err != PAM_SUCCESS) 111*7c478bd9Sstevel@tonic-gate return (err); 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate if (user == NULL || !user[0]) 114*7c478bd9Sstevel@tonic-gate return (PAM_AUTH_ERR); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate if (pam_get_data(pamh, KRB5_DATA, (const void**)&kmd) != PAM_SUCCESS) { 117*7c478bd9Sstevel@tonic-gate if (debug) { 118*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 119*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): kmd get failed, kmd=0x%p", 120*7c478bd9Sstevel@tonic-gate kmd); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate /* 124*7c478bd9Sstevel@tonic-gate * User doesn't need to authenticate for PAM_REFRESH_CRED 125*7c478bd9Sstevel@tonic-gate * or for PAM_DELETE_CRED 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate if (flags & (PAM_REFRESH_CRED|PAM_DELETE_CRED)) { 128*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 129*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): inst kmd structure"); 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate kmd = calloc(1, sizeof (krb5_module_data_t)); 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate if (kmd == NULL) { 134*7c478bd9Sstevel@tonic-gate result = PAM_BUF_ERR; 135*7c478bd9Sstevel@tonic-gate return (result); 136*7c478bd9Sstevel@tonic-gate } 137*7c478bd9Sstevel@tonic-gate 138*7c478bd9Sstevel@tonic-gate if ((err = pam_set_data(pamh, KRB5_DATA, 139*7c478bd9Sstevel@tonic-gate kmd, &krb5_cleanup)) != PAM_SUCCESS) { 140*7c478bd9Sstevel@tonic-gate free(kmd); 141*7c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate } else { 144*7c478bd9Sstevel@tonic-gate err = PAM_CRED_UNAVAIL; 145*7c478bd9Sstevel@tonic-gate goto out; 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate 148*7c478bd9Sstevel@tonic-gate } else { /* pam_get_data success */ 149*7c478bd9Sstevel@tonic-gate if (kmd == NULL) { 150*7c478bd9Sstevel@tonic-gate if (debug) { 151*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 152*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): kmd structure" 153*7c478bd9Sstevel@tonic-gate " gotten but is NULL for user %s", user); 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate err = PAM_CRED_UNAVAIL; 156*7c478bd9Sstevel@tonic-gate goto out; 157*7c478bd9Sstevel@tonic-gate } 158*7c478bd9Sstevel@tonic-gate 159*7c478bd9Sstevel@tonic-gate if (debug) 160*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 161*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): kmd auth_status: %s", 162*7c478bd9Sstevel@tonic-gate pam_strerror(pamh, kmd->auth_status)); 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate /* 165*7c478bd9Sstevel@tonic-gate * pam_auth has set status to ignore, so we also return ignore 166*7c478bd9Sstevel@tonic-gate */ 167*7c478bd9Sstevel@tonic-gate if (kmd->auth_status == PAM_IGNORE) { 168*7c478bd9Sstevel@tonic-gate err = PAM_IGNORE; 169*7c478bd9Sstevel@tonic-gate goto out; 170*7c478bd9Sstevel@tonic-gate } 171*7c478bd9Sstevel@tonic-gate } 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate kmd->debug = debug; 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * User must have passed pam_authenticate() 178*7c478bd9Sstevel@tonic-gate * in order to use PAM_ESTABLISH_CRED or PAM_REINITIALIZE_CRED 179*7c478bd9Sstevel@tonic-gate */ 180*7c478bd9Sstevel@tonic-gate if ((flags & (PAM_ESTABLISH_CRED|PAM_REINITIALIZE_CRED)) && 181*7c478bd9Sstevel@tonic-gate (kmd->auth_status != PAM_SUCCESS)) { 182*7c478bd9Sstevel@tonic-gate if (kmd->debug) 183*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 184*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): unable to " 185*7c478bd9Sstevel@tonic-gate "setcreds, not authenticated!"); 186*7c478bd9Sstevel@tonic-gate return (PAM_CRED_UNAVAIL); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate /* 190*7c478bd9Sstevel@tonic-gate * We cannot assume that kmd->kcontext being non-NULL 191*7c478bd9Sstevel@tonic-gate * means it is valid. Other pam_krb5 mods may have 192*7c478bd9Sstevel@tonic-gate * freed it but not reset it to NULL. 193*7c478bd9Sstevel@tonic-gate * Log a message when debugging to track down memory 194*7c478bd9Sstevel@tonic-gate * leaks. 195*7c478bd9Sstevel@tonic-gate */ 196*7c478bd9Sstevel@tonic-gate if (kmd->kcontext != NULL && kmd->debug) 197*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 198*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): kcontext != NULL, " 199*7c478bd9Sstevel@tonic-gate "possible memory leak."); 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate /* 202*7c478bd9Sstevel@tonic-gate * If auth was short-circuited we will not have anything to 203*7c478bd9Sstevel@tonic-gate * renew, so just return here. 204*7c478bd9Sstevel@tonic-gate */ 205*7c478bd9Sstevel@tonic-gate err = pam_get_item(pamh, PAM_REPOSITORY, (void **)&rep_data); 206*7c478bd9Sstevel@tonic-gate if (rep_data != NULL) { 207*7c478bd9Sstevel@tonic-gate if (strcmp(rep_data->type, KRB5_REPOSITORY_NAME) != 0) { 208*7c478bd9Sstevel@tonic-gate if (debug) 209*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, "PAM-KRB5 (setcred): wrong" 210*7c478bd9Sstevel@tonic-gate "repository found (%s), returning " 211*7c478bd9Sstevel@tonic-gate "PAM_IGNORE", rep_data->type); 212*7c478bd9Sstevel@tonic-gate return (PAM_IGNORE); 213*7c478bd9Sstevel@tonic-gate } 214*7c478bd9Sstevel@tonic-gate if (rep_data->scope_len == sizeof (krb5_repository_data_t)) { 215*7c478bd9Sstevel@tonic-gate krb5_data = (krb5_repository_data_t *)rep_data->scope; 216*7c478bd9Sstevel@tonic-gate 217*7c478bd9Sstevel@tonic-gate if (krb5_data->flags == 218*7c478bd9Sstevel@tonic-gate SUNW_PAM_KRB5_ALREADY_AUTHENTICATED && 219*7c478bd9Sstevel@tonic-gate krb5_data->principal != NULL && 220*7c478bd9Sstevel@tonic-gate strlen(krb5_data->principal)) { 221*7c478bd9Sstevel@tonic-gate if (debug) 222*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 223*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): " 224*7c478bd9Sstevel@tonic-gate "Principal %s already " 225*7c478bd9Sstevel@tonic-gate "authenticated, " 226*7c478bd9Sstevel@tonic-gate "cannot setcred", 227*7c478bd9Sstevel@tonic-gate krb5_data->principal); 228*7c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate } 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate if (flags & PAM_REINITIALIZE_CRED) 234*7c478bd9Sstevel@tonic-gate err = attempt_refresh_cred(kmd, user, PAM_REINITIALIZE_CRED); 235*7c478bd9Sstevel@tonic-gate else if (flags & PAM_REFRESH_CRED) 236*7c478bd9Sstevel@tonic-gate err = attempt_refresh_cred(kmd, user, PAM_REFRESH_CRED); 237*7c478bd9Sstevel@tonic-gate else if (flags & PAM_DELETE_CRED) 238*7c478bd9Sstevel@tonic-gate err = attempt_delete_initcred(kmd); 239*7c478bd9Sstevel@tonic-gate else { 240*7c478bd9Sstevel@tonic-gate /* 241*7c478bd9Sstevel@tonic-gate * Default case: PAM_ESTABLISH_CRED 242*7c478bd9Sstevel@tonic-gate */ 243*7c478bd9Sstevel@tonic-gate err = attempt_refresh_cred(kmd, user, PAM_ESTABLISH_CRED); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate if (err) 247*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 248*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): pam_setcred failed " 249*7c478bd9Sstevel@tonic-gate "for %s (%s).", user, pam_strerror(pamh, err)); 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate out: 252*7c478bd9Sstevel@tonic-gate if (kmd && kmd->kcontext) { 253*7c478bd9Sstevel@tonic-gate /* 254*7c478bd9Sstevel@tonic-gate * free 'kcontext' field if it is allocated, 255*7c478bd9Sstevel@tonic-gate * kcontext is local to the operation being performed 256*7c478bd9Sstevel@tonic-gate * not considered global to the entire pam module. 257*7c478bd9Sstevel@tonic-gate */ 258*7c478bd9Sstevel@tonic-gate krb5_free_context(kmd->kcontext); 259*7c478bd9Sstevel@tonic-gate kmd->kcontext = NULL; 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate * 'kmd' is not freed here, it is handled in krb5_cleanup 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate if (debug) 268*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 269*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): end: %s", 270*7c478bd9Sstevel@tonic-gate pam_strerror(pamh, err)); 271*7c478bd9Sstevel@tonic-gate return (err); 272*7c478bd9Sstevel@tonic-gate } 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate static int 275*7c478bd9Sstevel@tonic-gate attempt_refresh_cred( 276*7c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd, 277*7c478bd9Sstevel@tonic-gate char *user, 278*7c478bd9Sstevel@tonic-gate int flag) 279*7c478bd9Sstevel@tonic-gate { 280*7c478bd9Sstevel@tonic-gate krb5_principal me; 281*7c478bd9Sstevel@tonic-gate krb5_principal server; 282*7c478bd9Sstevel@tonic-gate krb5_error_code code; 283*7c478bd9Sstevel@tonic-gate char kuser[2*MAXHOSTNAMELEN]; 284*7c478bd9Sstevel@tonic-gate krb5_data tgtname = { 285*7c478bd9Sstevel@tonic-gate 0, 286*7c478bd9Sstevel@tonic-gate KRB5_TGS_NAME_SIZE, 287*7c478bd9Sstevel@tonic-gate KRB5_TGS_NAME 288*7c478bd9Sstevel@tonic-gate }; 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate /* User must have passed pam_authenticate() */ 291*7c478bd9Sstevel@tonic-gate if (kmd->auth_status != PAM_SUCCESS) { 292*7c478bd9Sstevel@tonic-gate if (kmd->debug) 293*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 294*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): unable to " 295*7c478bd9Sstevel@tonic-gate "setcreds, not authenticated!"); 296*7c478bd9Sstevel@tonic-gate return (PAM_CRED_UNAVAIL); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate /* Create a new context here. */ 300*7c478bd9Sstevel@tonic-gate if (krb5_init_context(&kmd->kcontext) != 0) { 301*7c478bd9Sstevel@tonic-gate if (kmd->debug) 302*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 303*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): unable to " 304*7c478bd9Sstevel@tonic-gate "initialize krb5 context"); 305*7c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate if (krb5_cc_default(kmd->kcontext, &kmd->ccache) != 0) { 309*7c478bd9Sstevel@tonic-gate return (PAM_CRED_ERR); 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate 312*7c478bd9Sstevel@tonic-gate if ((code = get_kmd_kuser(kmd->kcontext, (const char *)user, kuser, 313*7c478bd9Sstevel@tonic-gate 2*MAXHOSTNAMELEN)) != 0) { 314*7c478bd9Sstevel@tonic-gate return (code); 315*7c478bd9Sstevel@tonic-gate } 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate if (krb5_parse_name(kmd->kcontext, kuser, &me) != 0) { 318*7c478bd9Sstevel@tonic-gate return (PAM_CRED_ERR); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate if (code = krb5_build_principal_ext(kmd->kcontext, &server, 322*7c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 323*7c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 324*7c478bd9Sstevel@tonic-gate tgtname.length, tgtname.data, 325*7c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->length, 326*7c478bd9Sstevel@tonic-gate krb5_princ_realm(kmd->kcontext, me)->data, 0)) { 327*7c478bd9Sstevel@tonic-gate code = PAM_CRED_ERR; 328*7c478bd9Sstevel@tonic-gate goto out; 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate code = krb5_renew_tgt(kmd, me, server, flag); 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate out: 334*7c478bd9Sstevel@tonic-gate if (server) 335*7c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, server); 336*7c478bd9Sstevel@tonic-gate if (me) 337*7c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, me); 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate if (code) { 340*7c478bd9Sstevel@tonic-gate return (PAM_CRED_ERR); 341*7c478bd9Sstevel@tonic-gate } else { 342*7c478bd9Sstevel@tonic-gate return (PAM_SUCCESS); 343*7c478bd9Sstevel@tonic-gate } 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate /* 347*7c478bd9Sstevel@tonic-gate * This code will update the credential matching "server" in the user's 348*7c478bd9Sstevel@tonic-gate * credential cache. The flag may be set to one of: 349*7c478bd9Sstevel@tonic-gate * PAM_ESTABLISH_CRED - Create a new cred cache if one doesnt exist, 350*7c478bd9Sstevel@tonic-gate * else refresh the existing one. 351*7c478bd9Sstevel@tonic-gate * PAM_REINITIALIZE_CRED - destroy current cred cache and create a new one 352*7c478bd9Sstevel@tonic-gate * PAM_REFRESH_CRED - update the existing cred cache (default action) 353*7c478bd9Sstevel@tonic-gate */ 354*7c478bd9Sstevel@tonic-gate static krb5_error_code 355*7c478bd9Sstevel@tonic-gate krb5_renew_tgt( 356*7c478bd9Sstevel@tonic-gate krb5_module_data_t *kmd, 357*7c478bd9Sstevel@tonic-gate krb5_principal me, 358*7c478bd9Sstevel@tonic-gate krb5_principal server, 359*7c478bd9Sstevel@tonic-gate int flag) 360*7c478bd9Sstevel@tonic-gate { 361*7c478bd9Sstevel@tonic-gate krb5_error_code retval; 362*7c478bd9Sstevel@tonic-gate krb5_creds creds; 363*7c478bd9Sstevel@tonic-gate krb5_creds *credsp = &creds; 364*7c478bd9Sstevel@tonic-gate char *client_name = NULL; 365*7c478bd9Sstevel@tonic-gate typedef struct _cred_node { 366*7c478bd9Sstevel@tonic-gate krb5_creds *creds; 367*7c478bd9Sstevel@tonic-gate struct _cred_node *next; 368*7c478bd9Sstevel@tonic-gate } cred_node; 369*7c478bd9Sstevel@tonic-gate cred_node *cred_list_head = NULL; 370*7c478bd9Sstevel@tonic-gate cred_node *fetched = NULL; 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate #define my_creds (kmd->initcreds) 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate if ((flag != PAM_REFRESH_CRED) && 375*7c478bd9Sstevel@tonic-gate (flag != PAM_REINITIALIZE_CRED) && 376*7c478bd9Sstevel@tonic-gate (flag != PAM_ESTABLISH_CRED)) 377*7c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate /* this is needed only for the ktkt_warnd */ 380*7c478bd9Sstevel@tonic-gate if (krb5_unparse_name(kmd->kcontext, me, &client_name) != 0) { 381*7c478bd9Sstevel@tonic-gate krb5_free_principal(kmd->kcontext, me); 382*7c478bd9Sstevel@tonic-gate return (PAM_CRED_ERR); 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate (void) memset((char *)credsp, 0, sizeof (krb5_creds)); 386*7c478bd9Sstevel@tonic-gate if ((retval = krb5_copy_principal(kmd->kcontext, 387*7c478bd9Sstevel@tonic-gate server, &credsp->server))) { 388*7c478bd9Sstevel@tonic-gate if (kmd->debug) 389*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 390*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): krb5_copy_principal " 391*7c478bd9Sstevel@tonic-gate "failed: %s", 392*7c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 393*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 394*7c478bd9Sstevel@tonic-gate } 395*7c478bd9Sstevel@tonic-gate 396*7c478bd9Sstevel@tonic-gate /* obtain ticket & session key */ 397*7c478bd9Sstevel@tonic-gate retval = krb5_cc_get_principal(kmd->kcontext, 398*7c478bd9Sstevel@tonic-gate kmd->ccache, &credsp->client); 399*7c478bd9Sstevel@tonic-gate if (retval && (kmd->debug)) 400*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 401*7c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, 402*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): User not in cred " 403*7c478bd9Sstevel@tonic-gate "cache (%s)"), error_message((errcode_t)retval)); 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate if ((retval == KRB5_FCC_NOFILE) && 406*7c478bd9Sstevel@tonic-gate (flag & (PAM_ESTABLISH_CRED|PAM_REINITIALIZE_CRED))) { 407*7c478bd9Sstevel@tonic-gate /* 408*7c478bd9Sstevel@tonic-gate * Create a fresh ccache, and store the credentials 409*7c478bd9Sstevel@tonic-gate * we got from pam_authenticate() 410*7c478bd9Sstevel@tonic-gate */ 411*7c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_initialize(kmd->kcontext, 412*7c478bd9Sstevel@tonic-gate kmd->ccache, me)) != 0) { 413*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 414*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): krb5_cc_initialize " 415*7c478bd9Sstevel@tonic-gate "failed: %s", 416*7c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 417*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 418*7c478bd9Sstevel@tonic-gate } else if ((retval = krb5_cc_store_cred(kmd->kcontext, 419*7c478bd9Sstevel@tonic-gate kmd->ccache, &my_creds)) != 0) { 420*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 421*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): krb5_cc_store_cred " 422*7c478bd9Sstevel@tonic-gate "failed: %s", 423*7c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 424*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 425*7c478bd9Sstevel@tonic-gate } 426*7c478bd9Sstevel@tonic-gate } else if (retval) { 427*7c478bd9Sstevel@tonic-gate /* 428*7c478bd9Sstevel@tonic-gate * We failed to get the user's credentials. 429*7c478bd9Sstevel@tonic-gate * This might be due to permission error on the cache, 430*7c478bd9Sstevel@tonic-gate * or maybe we are looking in the wrong cache file! 431*7c478bd9Sstevel@tonic-gate */ 432*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 433*7c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, 434*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): Cannot find creds" 435*7c478bd9Sstevel@tonic-gate " for %s (%s)"), 436*7c478bd9Sstevel@tonic-gate client_name ? client_name : "(unknown)", 437*7c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 438*7c478bd9Sstevel@tonic-gate 439*7c478bd9Sstevel@tonic-gate } else if (flag & PAM_REINITIALIZE_CRED) { 440*7c478bd9Sstevel@tonic-gate /* 441*7c478bd9Sstevel@tonic-gate * This destroys the credential cache, and stores a new 442*7c478bd9Sstevel@tonic-gate * krbtgt with updated startime, endtime and renewable 443*7c478bd9Sstevel@tonic-gate * lifetime. 444*7c478bd9Sstevel@tonic-gate */ 445*7c478bd9Sstevel@tonic-gate creds.times.starttime = my_creds.times.starttime; 446*7c478bd9Sstevel@tonic-gate creds.times.endtime = my_creds.times.endtime; 447*7c478bd9Sstevel@tonic-gate creds.times.renew_till = my_creds.times.renew_till; 448*7c478bd9Sstevel@tonic-gate if ((retval = krb5_get_credentials_renew(kmd->kcontext, 0, 449*7c478bd9Sstevel@tonic-gate kmd->ccache, &creds, &credsp))) { 450*7c478bd9Sstevel@tonic-gate if (kmd->debug) 451*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 452*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): krb5_get_credentials", 453*7c478bd9Sstevel@tonic-gate "_renew(reinitialize) failed: %s", 454*7c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 455*7c478bd9Sstevel@tonic-gate /* perhaps the tgt lifetime has expired */ 456*7c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_initialize(kmd->kcontext, 457*7c478bd9Sstevel@tonic-gate kmd->ccache, me)) != 0) { 458*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 459*7c478bd9Sstevel@tonic-gate } else if ((retval = krb5_cc_store_cred(kmd->kcontext, 460*7c478bd9Sstevel@tonic-gate kmd->ccache, &my_creds)) != 0) { 461*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate } else { 465*7c478bd9Sstevel@tonic-gate /* 466*7c478bd9Sstevel@tonic-gate * Creds already exist, update them if possible. 467*7c478bd9Sstevel@tonic-gate * We got here either with the ESTABLISH or REFRESH flag. 468*7c478bd9Sstevel@tonic-gate * 469*7c478bd9Sstevel@tonic-gate * The credential cache does exist, and we are going to 470*7c478bd9Sstevel@tonic-gate * read in each cred, looking for our own. When we find 471*7c478bd9Sstevel@tonic-gate * a matching credential, we will update it, and store it. 472*7c478bd9Sstevel@tonic-gate * Any nonmatching credentials are stored as is. 473*7c478bd9Sstevel@tonic-gate * 474*7c478bd9Sstevel@tonic-gate * Rules: 475*7c478bd9Sstevel@tonic-gate * TGT must exist in cache to get to this point. 476*7c478bd9Sstevel@tonic-gate * if flag == ESTABLISH 477*7c478bd9Sstevel@tonic-gate * refresh it if possible, else overwrite 478*7c478bd9Sstevel@tonic-gate * with new TGT, other tickets in cache remain 479*7c478bd9Sstevel@tonic-gate * unchanged. 480*7c478bd9Sstevel@tonic-gate * else if flag == REFRESH 481*7c478bd9Sstevel@tonic-gate * refresh it if possible, else return error. 482*7c478bd9Sstevel@tonic-gate * - Will not work if "R" flag is not set in 483*7c478bd9Sstevel@tonic-gate * original cred, we dont want to 2nd guess the 484*7c478bd9Sstevel@tonic-gate * intention of the person who created the 485*7c478bd9Sstevel@tonic-gate * existing TGT. 486*7c478bd9Sstevel@tonic-gate * 487*7c478bd9Sstevel@tonic-gate */ 488*7c478bd9Sstevel@tonic-gate krb5_cc_cursor cursor; 489*7c478bd9Sstevel@tonic-gate krb5_creds nextcred; 490*7c478bd9Sstevel@tonic-gate boolean_t found = 0; 491*7c478bd9Sstevel@tonic-gate 492*7c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_start_seq_get(kmd->kcontext, 493*7c478bd9Sstevel@tonic-gate kmd->ccache, &cursor)) != 0) 494*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate while ((krb5_cc_next_cred(kmd->kcontext, kmd->ccache, 497*7c478bd9Sstevel@tonic-gate &cursor, &nextcred) == 0)) { 498*7c478bd9Sstevel@tonic-gate /* if two creds match, we just update the first */ 499*7c478bd9Sstevel@tonic-gate if ((!found) && (creds_match(kmd->kcontext, 500*7c478bd9Sstevel@tonic-gate &nextcred, &creds))) { 501*7c478bd9Sstevel@tonic-gate /* 502*7c478bd9Sstevel@tonic-gate * Mark it as found, don't store it 503*7c478bd9Sstevel@tonic-gate * in the list or else it will be 504*7c478bd9Sstevel@tonic-gate * stored twice later. 505*7c478bd9Sstevel@tonic-gate */ 506*7c478bd9Sstevel@tonic-gate found = 1; 507*7c478bd9Sstevel@tonic-gate } else { 508*7c478bd9Sstevel@tonic-gate /* 509*7c478bd9Sstevel@tonic-gate * Add a new node to the list 510*7c478bd9Sstevel@tonic-gate * of creds that must be replaced 511*7c478bd9Sstevel@tonic-gate * in the cache later. 512*7c478bd9Sstevel@tonic-gate */ 513*7c478bd9Sstevel@tonic-gate cred_node *newnode = (cred_node *)malloc( 514*7c478bd9Sstevel@tonic-gate sizeof (cred_node)); 515*7c478bd9Sstevel@tonic-gate if (newnode == NULL) { 516*7c478bd9Sstevel@tonic-gate retval = ENOMEM; 517*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 518*7c478bd9Sstevel@tonic-gate } 519*7c478bd9Sstevel@tonic-gate newnode->creds = NULL; 520*7c478bd9Sstevel@tonic-gate newnode->next = NULL; 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate if (cred_list_head == NULL) { 523*7c478bd9Sstevel@tonic-gate cred_list_head = newnode; 524*7c478bd9Sstevel@tonic-gate fetched = cred_list_head; 525*7c478bd9Sstevel@tonic-gate } else { 526*7c478bd9Sstevel@tonic-gate fetched->next = newnode; 527*7c478bd9Sstevel@tonic-gate fetched = fetched->next; 528*7c478bd9Sstevel@tonic-gate } 529*7c478bd9Sstevel@tonic-gate retval = krb5_copy_creds(kmd->kcontext, 530*7c478bd9Sstevel@tonic-gate &nextcred, &fetched->creds); 531*7c478bd9Sstevel@tonic-gate if (retval) 532*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 533*7c478bd9Sstevel@tonic-gate } 534*7c478bd9Sstevel@tonic-gate } 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_end_seq_get(kmd->kcontext, 537*7c478bd9Sstevel@tonic-gate kmd->ccache, &cursor)) != 0) 538*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 539*7c478bd9Sstevel@tonic-gate 540*7c478bd9Sstevel@tonic-gate /* 541*7c478bd9Sstevel@tonic-gate * If we found a matching cred, renew it. 542*7c478bd9Sstevel@tonic-gate * This destroys the credential cache, if and only 543*7c478bd9Sstevel@tonic-gate * if it passes. 544*7c478bd9Sstevel@tonic-gate */ 545*7c478bd9Sstevel@tonic-gate if (found && 546*7c478bd9Sstevel@tonic-gate (retval = krb5_get_credentials_renew(kmd->kcontext, 547*7c478bd9Sstevel@tonic-gate 0, kmd->ccache, &creds, &credsp))) { 548*7c478bd9Sstevel@tonic-gate if (kmd->debug) 549*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 550*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): krb5_get_credentials" 551*7c478bd9Sstevel@tonic-gate "_renew(update) failed: %s", 552*7c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 553*7c478bd9Sstevel@tonic-gate /* 554*7c478bd9Sstevel@tonic-gate * If we only wanted to refresh the creds but failed 555*7c478bd9Sstevel@tonic-gate * due to expiration, lack of "R" flag, or other 556*7c478bd9Sstevel@tonic-gate * problems, return an error. If we were trying to 557*7c478bd9Sstevel@tonic-gate * establish new creds, add them to the cache. 558*7c478bd9Sstevel@tonic-gate */ 559*7c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_initialize(kmd->kcontext, 560*7c478bd9Sstevel@tonic-gate kmd->ccache, me)) != 0) { 561*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 562*7c478bd9Sstevel@tonic-gate } else if ((retval = krb5_cc_store_cred(kmd->kcontext, 563*7c478bd9Sstevel@tonic-gate kmd->ccache, &my_creds)) != 0) { 564*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 565*7c478bd9Sstevel@tonic-gate } 566*7c478bd9Sstevel@tonic-gate } 567*7c478bd9Sstevel@tonic-gate /* 568*7c478bd9Sstevel@tonic-gate * If no matching creds were found, we must 569*7c478bd9Sstevel@tonic-gate * initialize the cache before we can store stuff 570*7c478bd9Sstevel@tonic-gate * in it. 571*7c478bd9Sstevel@tonic-gate */ 572*7c478bd9Sstevel@tonic-gate if (!found) { 573*7c478bd9Sstevel@tonic-gate if ((retval = krb5_cc_initialize(kmd->kcontext, 574*7c478bd9Sstevel@tonic-gate kmd->ccache, me)) != 0) { 575*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 576*7c478bd9Sstevel@tonic-gate } 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate /* now store all the other tickets */ 580*7c478bd9Sstevel@tonic-gate fetched = cred_list_head; 581*7c478bd9Sstevel@tonic-gate while (fetched != NULL) { 582*7c478bd9Sstevel@tonic-gate retval = krb5_cc_store_cred(kmd->kcontext, 583*7c478bd9Sstevel@tonic-gate kmd->ccache, fetched->creds); 584*7c478bd9Sstevel@tonic-gate fetched = fetched->next; 585*7c478bd9Sstevel@tonic-gate if (retval) { 586*7c478bd9Sstevel@tonic-gate if (kmd->debug) 587*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 588*7c478bd9Sstevel@tonic-gate "PAM-KRB5(setcred): krb5_cc_store_cred() " 589*7c478bd9Sstevel@tonic-gate "failed: %s", 590*7c478bd9Sstevel@tonic-gate error_message((errcode_t)retval)); 591*7c478bd9Sstevel@tonic-gate goto cleanup_creds; 592*7c478bd9Sstevel@tonic-gate } 593*7c478bd9Sstevel@tonic-gate } 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate 596*7c478bd9Sstevel@tonic-gate cleanup_creds: 597*7c478bd9Sstevel@tonic-gate /* Cleanup the list of creds read from the cache if necessary */ 598*7c478bd9Sstevel@tonic-gate fetched = cred_list_head; 599*7c478bd9Sstevel@tonic-gate while (fetched != NULL) { 600*7c478bd9Sstevel@tonic-gate cred_node *old = fetched; 601*7c478bd9Sstevel@tonic-gate /* Free the contents and the cred structure itself */ 602*7c478bd9Sstevel@tonic-gate krb5_free_creds(kmd->kcontext, fetched->creds); 603*7c478bd9Sstevel@tonic-gate fetched = fetched->next; 604*7c478bd9Sstevel@tonic-gate free(old); 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate if ((retval == 0) && (client_name != NULL)) { 608*7c478bd9Sstevel@tonic-gate /* 609*7c478bd9Sstevel@tonic-gate * Credential update was successful! 610*7c478bd9Sstevel@tonic-gate * 611*7c478bd9Sstevel@tonic-gate * We now chown the ccache to the appropriate uid/gid 612*7c478bd9Sstevel@tonic-gate * combination, if its a FILE based ccache. 613*7c478bd9Sstevel@tonic-gate */ 614*7c478bd9Sstevel@tonic-gate if (strstr(kmd->env, "FILE:")) { 615*7c478bd9Sstevel@tonic-gate uid_t uuid; 616*7c478bd9Sstevel@tonic-gate gid_t ugid; 617*7c478bd9Sstevel@tonic-gate char *username = NULL, *tmpname = NULL; 618*7c478bd9Sstevel@tonic-gate char *filepath = NULL; 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate username = strdup(client_name); 621*7c478bd9Sstevel@tonic-gate if ((tmpname = strchr(username, '@'))) 622*7c478bd9Sstevel@tonic-gate *tmpname = '\0'; 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate if (get_pw_uid(username, &uuid) == 0 || 625*7c478bd9Sstevel@tonic-gate get_pw_gid(username, &ugid) == 0) { 626*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "PAM-KRB5 (setcred): Unable to " 627*7c478bd9Sstevel@tonic-gate "find matching uid/gid pair for user `%s'", 628*7c478bd9Sstevel@tonic-gate username); 629*7c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate if (!(filepath = strchr(kmd->env, ':')) || 632*7c478bd9Sstevel@tonic-gate !(filepath+1)) { 633*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 634*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): Invalid pathname " 635*7c478bd9Sstevel@tonic-gate "for credential cache of user `%s'", 636*7c478bd9Sstevel@tonic-gate username); 637*7c478bd9Sstevel@tonic-gate return (PAM_SYSTEM_ERR); 638*7c478bd9Sstevel@tonic-gate } 639*7c478bd9Sstevel@tonic-gate if (chown(filepath+1, uuid, ugid)) { 640*7c478bd9Sstevel@tonic-gate if (kmd->debug) 641*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 642*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): chown to user " 643*7c478bd9Sstevel@tonic-gate "`%s' failed for FILE=%s", 644*7c478bd9Sstevel@tonic-gate username, filepath); 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate 647*7c478bd9Sstevel@tonic-gate free(username); 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate if (creds.times.endtime != 0) { 651*7c478bd9Sstevel@tonic-gate kwarn_del_warning(client_name); 652*7c478bd9Sstevel@tonic-gate if (kwarn_add_warning(client_name, 653*7c478bd9Sstevel@tonic-gate creds.times.endtime) != 0) { 654*7c478bd9Sstevel@tonic-gate syslog(LOG_NOTICE, dgettext(TEXT_DOMAIN, 655*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (auth): kwarn_add_warning" 656*7c478bd9Sstevel@tonic-gate " failed: ktkt_warnd(1M) down?")); 657*7c478bd9Sstevel@tonic-gate } 658*7c478bd9Sstevel@tonic-gate } 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate if (client_name != NULL) 661*7c478bd9Sstevel@tonic-gate free(client_name); 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(kmd->kcontext, &creds); 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate return (retval); 666*7c478bd9Sstevel@tonic-gate } 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate static krb5_boolean 669*7c478bd9Sstevel@tonic-gate creds_match(krb5_context ctx, const krb5_creds *mcreds, 670*7c478bd9Sstevel@tonic-gate const krb5_creds *creds) 671*7c478bd9Sstevel@tonic-gate { 672*7c478bd9Sstevel@tonic-gate char *s1, *s2, *c1, *c2; 673*7c478bd9Sstevel@tonic-gate krb5_unparse_name(ctx, mcreds->client, &c1); 674*7c478bd9Sstevel@tonic-gate krb5_unparse_name(ctx, mcreds->server, &s1); 675*7c478bd9Sstevel@tonic-gate krb5_unparse_name(ctx, creds->client, &c2); 676*7c478bd9Sstevel@tonic-gate krb5_unparse_name(ctx, creds->server, &s2); 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate return (krb5_principal_compare(ctx, mcreds->client, creds->client) && 679*7c478bd9Sstevel@tonic-gate krb5_principal_compare(ctx, mcreds->server, creds->server)); 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate /* 683*7c478bd9Sstevel@tonic-gate * Delete the user's credentials for this session 684*7c478bd9Sstevel@tonic-gate */ 685*7c478bd9Sstevel@tonic-gate static int 686*7c478bd9Sstevel@tonic-gate attempt_delete_initcred(krb5_module_data_t *kmd) 687*7c478bd9Sstevel@tonic-gate { 688*7c478bd9Sstevel@tonic-gate if (kmd == NULL) 689*7c478bd9Sstevel@tonic-gate return (0); 690*7c478bd9Sstevel@tonic-gate 691*7c478bd9Sstevel@tonic-gate if (kmd->debug) { 692*7c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 693*7c478bd9Sstevel@tonic-gate "PAM-KRB5 (setcred): deleting user's " 694*7c478bd9Sstevel@tonic-gate "credentials (initcreds)"); 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 697*7c478bd9Sstevel@tonic-gate (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 698*7c478bd9Sstevel@tonic-gate kmd->auth_status = PAM_AUTHINFO_UNAVAIL; 699*7c478bd9Sstevel@tonic-gate return (0); 700*7c478bd9Sstevel@tonic-gate } 701