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 err = PAM_CRED_UNAVAIL; 142 goto out; 143 } 144 145 } else { /* pam_get_data success */ 146 if (kmd == NULL) { 147 if (debug) { 148 __pam_log(LOG_AUTH | LOG_DEBUG, 149 "PAM-KRB5 (setcred): kmd structure" 150 " gotten but is NULL for user %s", user); 151 } 152 err = PAM_CRED_UNAVAIL; 153 goto out; 154 } 155 156 if (debug) 157 __pam_log(LOG_AUTH | LOG_DEBUG, 158 "PAM-KRB5 (setcred): kmd auth_status: %s", 159 pam_strerror(pamh, kmd->auth_status)); 160 161 /* 162 * pam_auth has set status to ignore, so we also return ignore 163 */ 164 if (kmd->auth_status == PAM_IGNORE) { 165 err = PAM_IGNORE; 166 goto out; 167 } 168 } 169 170 kmd->debug = debug; 171 172 /* 173 * User must have passed pam_authenticate() 174 * in order to use PAM_ESTABLISH_CRED or PAM_REINITIALIZE_CRED 175 */ 176 if ((flags & (PAM_ESTABLISH_CRED|PAM_REINITIALIZE_CRED)) && 177 (kmd->auth_status != PAM_SUCCESS)) { 178 if (kmd->debug) 179 __pam_log(LOG_AUTH | LOG_DEBUG, 180 "PAM-KRB5 (setcred): unable to " 181 "setcreds, not authenticated!"); 182 return (PAM_CRED_UNAVAIL); 183 } 184 185 /* 186 * We cannot assume that kmd->kcontext being non-NULL 187 * means it is valid. Other pam_krb5 mods may have 188 * freed it but not reset it to NULL. 189 * Log a message when debugging to track down memory 190 * leaks. 191 */ 192 if (kmd->kcontext != NULL && kmd->debug) 193 __pam_log(LOG_AUTH | LOG_DEBUG, 194 "PAM-KRB5 (setcred): kcontext != NULL, " 195 "possible memory leak."); 196 197 /* 198 * Use the authenticated and validated user, if applicable. 199 */ 200 if (kmd->user != NULL) 201 user = kmd->user; 202 203 /* 204 * If auth was short-circuited we will not have anything to 205 * renew, so just return here. 206 */ 207 (void) pam_get_item(pamh, PAM_REPOSITORY, (void **)&rep_data); 208 209 if (rep_data != NULL) { 210 if (strcmp(rep_data->type, KRB5_REPOSITORY_NAME) != 0) { 211 if (debug) 212 __pam_log(LOG_AUTH | LOG_DEBUG, 213 "PAM-KRB5 (setcred): wrong" 214 "repository found (%s), returning " 215 "PAM_IGNORE", rep_data->type); 216 return (PAM_IGNORE); 217 } 218 if (rep_data->scope_len == sizeof (krb5_repository_data_t)) { 219 krb5_data = (krb5_repository_data_t *)rep_data->scope; 220 221 if (krb5_data->flags == 222 SUNW_PAM_KRB5_ALREADY_AUTHENTICATED && 223 krb5_data->principal != NULL && 224 strlen(krb5_data->principal)) { 225 if (debug) 226 __pam_log(LOG_AUTH | LOG_DEBUG, 227 "PAM-KRB5 (setcred): " 228 "Principal %s already " 229 "authenticated, " 230 "cannot setcred", 231 krb5_data->principal); 232 return (PAM_SUCCESS); 233 } 234 } 235 } 236 237 if (flags & PAM_REINITIALIZE_CRED) 238 err = attempt_refresh_cred(kmd, user, PAM_REINITIALIZE_CRED); 239 else if (flags & PAM_REFRESH_CRED) 240 err = attempt_refresh_cred(kmd, user, PAM_REFRESH_CRED); 241 else if (flags & PAM_DELETE_CRED) 242 err = attempt_delete_initcred(kmd); 243 else { 244 /* 245 * Default case: PAM_ESTABLISH_CRED 246 */ 247 err = attempt_refresh_cred(kmd, user, PAM_ESTABLISH_CRED); 248 } 249 250 if (err != PAM_SUCCESS) 251 __pam_log(LOG_AUTH | LOG_ERR, 252 "PAM-KRB5 (setcred): pam_setcred failed " 253 "for %s (%s).", user, pam_strerror(pamh, err)); 254 255 out: 256 if (kmd && kmd->kcontext) { 257 /* 258 * free 'kcontext' field if it is allocated, 259 * kcontext is local to the operation being performed 260 * not considered global to the entire pam module. 261 */ 262 krb5_free_context(kmd->kcontext); 263 kmd->kcontext = NULL; 264 } 265 266 /* 267 * 'kmd' is not freed here, it is handled in krb5_cleanup 268 */ 269 if (debug) 270 __pam_log(LOG_AUTH | LOG_DEBUG, 271 "PAM-KRB5 (setcred): end: %s", 272 pam_strerror(pamh, err)); 273 return (err); 274 } 275 276 static int 277 attempt_refresh_cred( 278 krb5_module_data_t *kmd, 279 char *user, 280 int flag) 281 { 282 krb5_principal me; 283 krb5_principal server; 284 krb5_error_code code; 285 char kuser[2*MAXHOSTNAMELEN]; 286 krb5_data tgtname = { 287 0, 288 KRB5_TGS_NAME_SIZE, 289 KRB5_TGS_NAME 290 }; 291 292 /* User must have passed pam_authenticate() */ 293 if (kmd->auth_status != PAM_SUCCESS) { 294 if (kmd->debug) 295 __pam_log(LOG_AUTH | LOG_DEBUG, 296 "PAM-KRB5 (setcred): unable to " 297 "setcreds, not authenticated!"); 298 return (PAM_CRED_UNAVAIL); 299 } 300 301 /* Create a new context here. */ 302 if (krb5_init_context(&kmd->kcontext) != 0) { 303 if (kmd->debug) 304 __pam_log(LOG_AUTH | LOG_DEBUG, 305 "PAM-KRB5 (setcred): unable to " 306 "initialize krb5 context"); 307 return (PAM_SYSTEM_ERR); 308 } 309 310 if (krb5_cc_default(kmd->kcontext, &kmd->ccache) != 0) { 311 return (PAM_SYSTEM_ERR); 312 } 313 314 if ((code = get_kmd_kuser(kmd->kcontext, (const char *)user, kuser, 315 2*MAXHOSTNAMELEN)) != 0) { 316 return (code); 317 } 318 319 if (krb5_parse_name(kmd->kcontext, kuser, &me) != 0) { 320 return (PAM_SYSTEM_ERR); 321 } 322 323 if (code = krb5_build_principal_ext(kmd->kcontext, &server, 324 krb5_princ_realm(kmd->kcontext, me)->length, 325 krb5_princ_realm(kmd->kcontext, me)->data, 326 tgtname.length, tgtname.data, 327 krb5_princ_realm(kmd->kcontext, me)->length, 328 krb5_princ_realm(kmd->kcontext, me)->data, 0)) { 329 krb5_free_principal(kmd->kcontext, me); 330 return (PAM_SYSTEM_ERR); 331 } 332 333 code = krb5_renew_tgt(kmd, me, server, flag); 334 335 krb5_free_principal(kmd->kcontext, server); 336 krb5_free_principal(kmd->kcontext, me); 337 338 if (code) { 339 if (kmd->debug) 340 __pam_log(LOG_AUTH | LOG_DEBUG, 341 "PAM-KRB5(setcred): krb5_renew_tgt() " 342 "failed: %s", error_message((errcode_t)code)); 343 return (PAM_CRED_ERR); 344 } else { 345 return (PAM_SUCCESS); 346 } 347 } 348 349 /* 350 * This code will update the credential matching "server" in the user's 351 * credential cache. The flag may be set to one of: 352 * PAM_ESTABLISH_CRED - Create a new cred cache if one doesnt exist, 353 * else refresh the existing one. 354 * PAM_REINITIALIZE_CRED - destroy current cred cache and create a new one 355 * PAM_REFRESH_CRED - update the existing cred cache (default action) 356 */ 357 static krb5_error_code 358 krb5_renew_tgt( 359 krb5_module_data_t *kmd, 360 krb5_principal me, 361 krb5_principal server, 362 int flag) 363 { 364 krb5_error_code retval; 365 krb5_creds creds; 366 krb5_creds *renewed_cred = NULL; 367 char *client_name = NULL; 368 typedef struct _cred_node { 369 krb5_creds *creds; 370 struct _cred_node *next; 371 } cred_node; 372 cred_node *cred_list_head = NULL; 373 cred_node *fetched = NULL; 374 375 #define my_creds (kmd->initcreds) 376 377 if ((flag != PAM_REFRESH_CRED) && 378 (flag != PAM_REINITIALIZE_CRED) && 379 (flag != PAM_ESTABLISH_CRED)) 380 return (KRB5KRB_ERR_GENERIC); 381 382 /* this is needed only for the ktkt_warnd */ 383 if ((retval = krb5_unparse_name(kmd->kcontext, me, &client_name)) != 0) 384 return (retval); 385 386 (void) memset(&creds, 0, sizeof (krb5_creds)); 387 if ((retval = krb5_copy_principal(kmd->kcontext, 388 server, &creds.server))) { 389 if (kmd->debug) 390 __pam_log(LOG_AUTH | LOG_DEBUG, 391 "PAM-KRB5 (setcred): krb5_copy_principal " 392 "failed: %s", 393 error_message((errcode_t)retval)); 394 goto cleanup_creds; 395 } 396 397 /* obtain ticket & session key */ 398 retval = krb5_cc_get_principal(kmd->kcontext, 399 kmd->ccache, &creds.client); 400 if (retval && (kmd->debug)) 401 __pam_log(LOG_AUTH | LOG_DEBUG, 402 "PAM-KRB5 (setcred): User not in cred " 403 "cache (%s)", error_message((errcode_t)retval)); 404 405 if ((retval == KRB5_FCC_NOFILE) && 406 (flag & (PAM_ESTABLISH_CRED|PAM_REINITIALIZE_CRED))) { 407 /* 408 * Create a fresh ccache, and store the credentials 409 * we got from pam_authenticate() 410 */ 411 if ((retval = krb5_cc_initialize(kmd->kcontext, 412 kmd->ccache, me)) != 0) { 413 __pam_log(LOG_AUTH | LOG_DEBUG, 414 "PAM-KRB5 (setcred): krb5_cc_initialize " 415 "failed: %s", 416 error_message((errcode_t)retval)); 417 goto cleanup_creds; 418 } else if ((retval = krb5_cc_store_cred(kmd->kcontext, 419 kmd->ccache, &my_creds)) != 0) { 420 __pam_log(LOG_AUTH | LOG_DEBUG, 421 "PAM-KRB5 (setcred): krb5_cc_store_cred " 422 "failed: %s", 423 error_message((errcode_t)retval)); 424 goto cleanup_creds; 425 } 426 } else if (retval) { 427 /* 428 * We failed to get the user's credentials. 429 * This might be due to permission error on the cache, 430 * or maybe we are looking in the wrong cache file! 431 */ 432 __pam_log(LOG_AUTH | LOG_ERR, 433 "PAM-KRB5 (setcred): Cannot find creds" 434 " for %s (%s)", 435 client_name ? client_name : "(unknown)", 436 error_message((errcode_t)retval)); 437 438 } else if (flag & PAM_REINITIALIZE_CRED) { 439 /* 440 * This destroys the credential cache, and stores a new 441 * krbtgt with updated startime, endtime and renewable 442 * lifetime. 443 */ 444 creds.times.starttime = my_creds.times.starttime; 445 creds.times.endtime = my_creds.times.endtime; 446 creds.times.renew_till = my_creds.times.renew_till; 447 if ((retval = krb5_get_credentials_renew(kmd->kcontext, 0, 448 kmd->ccache, &creds, &renewed_cred))) { 449 if (kmd->debug) 450 __pam_log(LOG_AUTH | LOG_DEBUG, 451 "PAM-KRB5 (setcred): krb5_get_credentials", 452 "_renew(reinitialize) failed: %s", 453 error_message((errcode_t)retval)); 454 /* perhaps the tgt lifetime has expired */ 455 if ((retval = krb5_cc_initialize(kmd->kcontext, 456 kmd->ccache, me)) != 0) { 457 goto cleanup_creds; 458 } else if ((retval = krb5_cc_store_cred(kmd->kcontext, 459 kmd->ccache, &my_creds)) != 0) { 460 goto cleanup_creds; 461 } 462 } 463 } else { 464 /* 465 * Creds already exist, update them if possible. 466 * We got here either with the ESTABLISH or REFRESH flag. 467 * 468 * The credential cache does exist, and we are going to 469 * read in each cred, looking for our own. When we find 470 * a matching credential, we will update it, and store it. 471 * Any nonmatching credentials are stored as is. 472 * 473 * Rules: 474 * TGT must exist in cache to get to this point. 475 * if flag == ESTABLISH 476 * refresh it if possible, else overwrite 477 * with new TGT, other tickets in cache remain 478 * unchanged. 479 * else if flag == REFRESH 480 * refresh it if possible, else return error. 481 * - Will not work if "R" flag is not set in 482 * original cred, we dont want to 2nd guess the 483 * intention of the person who created the 484 * existing TGT. 485 * 486 */ 487 krb5_cc_cursor cursor; 488 krb5_creds nextcred; 489 boolean_t found = 0; 490 491 if ((retval = krb5_cc_start_seq_get(kmd->kcontext, 492 kmd->ccache, &cursor)) != 0) 493 goto cleanup_creds; 494 495 while ((krb5_cc_next_cred(kmd->kcontext, kmd->ccache, 496 &cursor, &nextcred) == 0)) { 497 /* if two creds match, we just update the first */ 498 if ((!found) && (creds_match(kmd->kcontext, 499 &nextcred, &creds))) { 500 /* 501 * Mark it as found, don't store it 502 * in the list or else it will be 503 * stored twice later. 504 */ 505 found = 1; 506 } else { 507 /* 508 * Add a new node to the list 509 * of creds that must be replaced 510 * in the cache later. 511 */ 512 cred_node *newnode = (cred_node *)malloc( 513 sizeof (cred_node)); 514 if (newnode == NULL) { 515 retval = ENOMEM; 516 goto cleanup_creds; 517 } 518 newnode->creds = NULL; 519 newnode->next = NULL; 520 521 if (cred_list_head == NULL) { 522 cred_list_head = newnode; 523 fetched = cred_list_head; 524 } else { 525 fetched->next = newnode; 526 fetched = fetched->next; 527 } 528 retval = krb5_copy_creds(kmd->kcontext, 529 &nextcred, &fetched->creds); 530 if (retval) 531 goto cleanup_creds; 532 } 533 } 534 535 if ((retval = krb5_cc_end_seq_get(kmd->kcontext, 536 kmd->ccache, &cursor)) != 0) 537 goto cleanup_creds; 538 539 /* 540 * If we found a matching cred, renew it. 541 * This destroys the credential cache, if and only 542 * if it passes. 543 */ 544 if (found && 545 (retval = krb5_get_credentials_renew(kmd->kcontext, 546 0, kmd->ccache, &creds, &renewed_cred))) { 547 if (kmd->debug) 548 __pam_log(LOG_AUTH | LOG_DEBUG, 549 "PAM-KRB5 (setcred): krb5_get_credentials" 550 "_renew(update) failed: %s", 551 error_message((errcode_t)retval)); 552 /* 553 * If we only wanted to refresh the creds but failed 554 * due to expiration, lack of "R" flag, or other 555 * problems, return an error. If we were trying to 556 * establish new creds, add them to the cache. 557 */ 558 if ((retval = krb5_cc_initialize(kmd->kcontext, 559 kmd->ccache, me)) != 0) { 560 goto cleanup_creds; 561 } else if ((retval = krb5_cc_store_cred(kmd->kcontext, 562 kmd->ccache, &my_creds)) != 0) { 563 goto cleanup_creds; 564 } 565 } 566 /* 567 * If no matching creds were found, we must 568 * initialize the cache before we can store stuff 569 * in it. 570 */ 571 if (!found) { 572 if ((retval = krb5_cc_initialize(kmd->kcontext, 573 kmd->ccache, me)) != 0) { 574 goto cleanup_creds; 575 } 576 } 577 578 /* now store all the other tickets */ 579 fetched = cred_list_head; 580 while (fetched != NULL) { 581 retval = krb5_cc_store_cred(kmd->kcontext, 582 kmd->ccache, fetched->creds); 583 fetched = fetched->next; 584 if (retval) { 585 if (kmd->debug) 586 __pam_log(LOG_AUTH | LOG_DEBUG, 587 "PAM-KRB5(setcred): krb5_cc_store_cred() " 588 "failed: %s", 589 error_message((errcode_t)retval)); 590 goto cleanup_creds; 591 } 592 } 593 } 594 595 cleanup_creds: 596 /* Cleanup the list of creds read from the cache if necessary */ 597 fetched = cred_list_head; 598 while (fetched != NULL) { 599 cred_node *old = fetched; 600 /* Free the contents and the cred structure itself */ 601 krb5_free_creds(kmd->kcontext, fetched->creds); 602 fetched = fetched->next; 603 free(old); 604 } 605 606 if ((retval == 0) && (client_name != NULL)) { 607 /* 608 * Credential update was successful! 609 * 610 * We now chown the ccache to the appropriate uid/gid 611 * combination, if its a FILE based ccache. 612 */ 613 if (strstr(kmd->env, "FILE:")) { 614 uid_t uuid; 615 gid_t ugid; 616 char *username = NULL, *tmpname = NULL; 617 char *filepath = NULL; 618 619 username = strdup(client_name); 620 if ((tmpname = strchr(username, '@'))) 621 *tmpname = '\0'; 622 623 if (get_pw_uid(username, &uuid) == 0 || 624 get_pw_gid(username, &ugid) == 0) { 625 __pam_log(LOG_AUTH | LOG_ERR, 626 "PAM-KRB5 (setcred): Unable to " 627 "find matching uid/gid pair for user `%s'", 628 username); 629 retval = KRB5KRB_ERR_GENERIC; 630 goto error; 631 } 632 if (!(filepath = strchr(kmd->env, ':')) || 633 !(filepath+1)) { 634 __pam_log(LOG_AUTH | LOG_ERR, 635 "PAM-KRB5 (setcred): Invalid pathname " 636 "for credential cache of user `%s'", 637 username); 638 retval = KRB5KRB_ERR_GENERIC; 639 goto error; 640 } 641 if (chown(filepath+1, uuid, ugid)) { 642 if (kmd->debug) 643 __pam_log(LOG_AUTH | LOG_DEBUG, 644 "PAM-KRB5 (setcred): chown to user " 645 "`%s' failed for FILE=%s", 646 username, filepath); 647 } 648 649 free(username); 650 } 651 } 652 653 error: 654 if (retval == 0) { 655 krb5_timestamp endtime; 656 657 if (renewed_cred && renewed_cred->times.endtime != 0) 658 endtime = renewed_cred->times.endtime; 659 else 660 endtime = my_creds.times.endtime; 661 662 if (kmd->debug) 663 __pam_log(LOG_AUTH | LOG_DEBUG, 664 "PAM-KRB5 (setcred): delete/add warning"); 665 666 kwarn_del_warning(client_name); 667 if (kwarn_add_warning(client_name, endtime) != 0) { 668 __pam_log(LOG_AUTH | LOG_NOTICE, 669 "PAM-KRB5 (setcred): kwarn_add_warning" 670 " failed: ktkt_warnd(1M) down?"); 671 } 672 } 673 674 if (renewed_cred != NULL) 675 krb5_free_creds(kmd->kcontext, renewed_cred); 676 677 if (client_name != NULL) 678 free(client_name); 679 680 krb5_free_cred_contents(kmd->kcontext, &creds); 681 682 return (retval); 683 } 684 685 static krb5_boolean 686 creds_match(krb5_context ctx, const krb5_creds *mcreds, 687 const krb5_creds *creds) 688 { 689 char *s1, *s2, *c1, *c2; 690 krb5_unparse_name(ctx, mcreds->client, &c1); 691 krb5_unparse_name(ctx, mcreds->server, &s1); 692 krb5_unparse_name(ctx, creds->client, &c2); 693 krb5_unparse_name(ctx, creds->server, &s2); 694 695 return (krb5_principal_compare(ctx, mcreds->client, creds->client) && 696 krb5_principal_compare(ctx, mcreds->server, creds->server)); 697 } 698 699 /* 700 * Delete the user's credentials for this session 701 */ 702 static int 703 attempt_delete_initcred(krb5_module_data_t *kmd) 704 { 705 if (kmd == NULL) 706 return (PAM_SUCCESS); 707 708 if (kmd->debug) { 709 __pam_log(LOG_AUTH | LOG_DEBUG, 710 "PAM-KRB5 (setcred): deleting user's " 711 "credentials (initcreds)"); 712 } 713 krb5_free_cred_contents(kmd->kcontext, &kmd->initcreds); 714 (void) memset((char *)&kmd->initcreds, 0, sizeof (krb5_creds)); 715 kmd->auth_status = PAM_AUTHINFO_UNAVAIL; 716 return (PAM_SUCCESS); 717 } 718