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