1 /* 2 * $Source: /mit/krb5/.cvsroot/src/appl/telnet/libtelnet/kerberos5.c,v $ 3 * $Author: tytso $ 4 * $Id: kerberos5.c,v 5.3 1993/09/01 03:00:12 tytso Exp $ 5 */ 6 7 #if !defined(lint) && !defined(SABER) 8 static 9 #ifdef __STDC__ 10 const 11 #endif 12 char rcsid_kerberos5_c[] = "$Id: kerberos5.c,v 5.3 1993/09/01 03:00:12 tytso Exp $"; 13 #endif /* lint */ 14 15 /*- 16 * Copyright (c) 1991, 1993 17 * The Regents of the University of California. All rights reserved. 18 * 19 * %sccs.include.redist.c% 20 */ 21 22 #ifndef lint 23 static char sccsid[] = "@(#)kerberos5.c 8.3 (Berkeley) 05/30/95"; 24 #endif /* not lint */ 25 26 /* 27 * Copyright (C) 1990 by the Massachusetts Institute of Technology 28 * 29 * Export of this software from the United States of America may 30 * require a specific license from the United States Government. 31 * It is the responsibility of any person or organization contemplating 32 * export to obtain such a license before exporting. 33 * 34 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 35 * distribute this software and its documentation for any purpose and 36 * without fee is hereby granted, provided that the above copyright 37 * notice appear in all copies and that both that copyright notice and 38 * this permission notice appear in supporting documentation, and that 39 * the name of M.I.T. not be used in advertising or publicity pertaining 40 * to distribution of the software without specific, written prior 41 * permission. M.I.T. makes no representations about the suitability of 42 * this software for any purpose. It is provided "as is" without express 43 * or implied warranty. 44 */ 45 46 47 #ifdef KRB5 48 #include <arpa/telnet.h> 49 #include <stdio.h> 50 #include <krb5/krb5.h> 51 #include <krb5/asn1.h> 52 #include <krb5/crc-32.h> 53 #include <krb5/los-proto.h> 54 #include <krb5/ext-proto.h> 55 #include <com_err.h> 56 #include <netdb.h> 57 #include <ctype.h> 58 59 /* kerberos 5 include files (ext-proto.h) will get an appropriate stdlib.h 60 and string.h/strings.h */ 61 62 #include "encrypt.h" 63 #include "auth.h" 64 #include "misc.h" 65 66 extern auth_debug_mode; 67 68 #ifdef FORWARD 69 int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */ 70 71 /* These values need to be the same as those defined in telnet/main.c. */ 72 /* Either define them in both places, or put in some common header file. */ 73 #define OPTS_FORWARD_CREDS 0x00000002 74 #define OPTS_FORWARDABLE_CREDS 0x00000001 75 76 void kerberos5_forward(); 77 78 #endif /* FORWARD */ 79 80 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, 81 AUTHTYPE_KERBEROS_V5, }; 82 /*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 83 TELQUAL_NAME, };*/ 84 85 #define KRB_AUTH 0 /* Authentication data follows */ 86 #define KRB_REJECT 1 /* Rejected (reason might follow) */ 87 #define KRB_ACCEPT 2 /* Accepted */ 88 #define KRB_RESPONSE 3 /* Response for mutual auth. */ 89 90 #ifdef FORWARD 91 #define KRB_FORWARD 4 /* Forwarded credentials follow */ 92 #define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */ 93 #define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */ 94 #endif /* FORWARD */ 95 96 static krb5_data auth; 97 /* telnetd gets session key from here */ 98 static krb5_tkt_authent *authdat = NULL; 99 /* telnet matches the AP_REQ and AP_REP with this */ 100 static krb5_authenticator authenticator; 101 102 /* some compilers can't hack void *, so we use the Kerberos krb5_pointer, 103 which is either void * or char *, depending on the compiler. */ 104 105 #define Voidptr krb5_pointer 106 107 Block session_key; 108 109 static int 110 Data(ap, type, d, c) 111 Authenticator *ap; 112 int type; 113 Voidptr d; 114 int c; 115 { 116 unsigned char *p = str_data + 4; 117 unsigned char *cd = (unsigned char *)d; 118 119 if (c == -1) 120 c = strlen((char *)cd); 121 122 if (auth_debug_mode) { 123 printf("%s:%d: [%d] (%d)", 124 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", 125 str_data[3], 126 type, c); 127 printd(d, c); 128 printf("\r\n"); 129 } 130 *p++ = ap->type; 131 *p++ = ap->way; 132 *p++ = type; 133 while (c-- > 0) { 134 if ((*p++ = *cd++) == IAC) 135 *p++ = IAC; 136 } 137 *p++ = IAC; 138 *p++ = SE; 139 if (str_data[3] == TELQUAL_IS) 140 printsub('>', &str_data[2], p - &str_data[2]); 141 return(net_write(str_data, p - str_data)); 142 } 143 144 int 145 kerberos5_init(ap, server) 146 Authenticator *ap; 147 int server; 148 { 149 if (server) 150 str_data[3] = TELQUAL_REPLY; 151 else 152 str_data[3] = TELQUAL_IS; 153 krb5_init_ets(); 154 return(1); 155 } 156 157 int 158 kerberos5_send(ap) 159 Authenticator *ap; 160 { 161 char **realms; 162 char *name; 163 char *p1, *p2; 164 krb5_checksum ksum; 165 krb5_octet sum[CRC32_CKSUM_LENGTH]; 166 krb5_principal server; 167 krb5_error_code r; 168 krb5_ccache ccache; 169 krb5_creds creds; /* telnet gets session key from here */ 170 extern krb5_flags krb5_kdc_default_options; 171 int ap_opts; 172 173 #ifdef ENCRYPTION 174 krb5_keyblock *newkey = 0; 175 #endif /* ENCRYPTION */ 176 177 ksum.checksum_type = CKSUMTYPE_CRC32; 178 ksum.contents = sum; 179 ksum.length = sizeof(sum); 180 memset((Voidptr )sum, 0, sizeof(sum)); 181 182 if (!UserNameRequested) { 183 if (auth_debug_mode) { 184 printf("Kerberos V5: no user name supplied\r\n"); 185 } 186 return(0); 187 } 188 189 if (r = krb5_cc_default(&ccache)) { 190 if (auth_debug_mode) { 191 printf("Kerberos V5: could not get default ccache\r\n"); 192 } 193 return(0); 194 } 195 196 if ((name = malloc(strlen(RemoteHostName)+1)) == NULL) { 197 if (auth_debug_mode) 198 printf("Out of memory for hostname in Kerberos V5\r\n"); 199 return(0); 200 } 201 202 if (r = krb5_get_host_realm(RemoteHostName, &realms)) { 203 if (auth_debug_mode) 204 printf("Kerberos V5: no realm for %s\r\n", RemoteHostName); 205 free(name); 206 return(0); 207 } 208 209 p1 = RemoteHostName; 210 p2 = name; 211 212 while (*p2 = *p1++) { 213 if (isupper(*p2)) 214 *p2 |= 040; 215 ++p2; 216 } 217 218 if (r = krb5_build_principal_ext(&server, 219 strlen(realms[0]), realms[0], 220 4, "host", 221 p2 - name, name, 222 0)) { 223 if (auth_debug_mode) { 224 printf("Kerberos V5: failure setting up principal (%s)\r\n", 225 error_message(r)); 226 } 227 free(name); 228 krb5_free_host_realm(realms); 229 return(0); 230 } 231 232 233 memset((char *)&creds, 0, sizeof(creds)); 234 creds.server = server; 235 236 if (r = krb5_cc_get_principal(ccache, &creds.client)) { 237 if (auth_debug_mode) { 238 printf("Kerberos V5: failure on principal (%s)\r\n", 239 error_message(r)); 240 } 241 free(name); 242 krb5_free_principal(server); 243 krb5_free_host_realm(realms); 244 return(0); 245 } 246 247 if (r = krb5_get_credentials(krb5_kdc_default_options, ccache, &creds)) { 248 if (auth_debug_mode) { 249 printf("Kerberos V5: failure on credentials(%d)\r\n",r); 250 } 251 free(name); 252 krb5_free_host_realm(realms); 253 krb5_free_principal(server); 254 return(0); 255 } 256 257 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) 258 ap_opts = AP_OPTS_MUTUAL_REQUIRED; 259 else 260 ap_opts = 0; 261 262 r = krb5_mk_req_extended(ap_opts, &ksum, krb5_kdc_default_options, 0, 263 #ifdef ENCRYPTION 264 &newkey, 265 #else /* ENCRYPTION */ 266 0, 267 #endif /* ENCRYPTION */ 268 ccache, &creds, &authenticator, &auth); 269 /* don't let the key get freed if we clean up the authenticator */ 270 authenticator.subkey = 0; 271 272 free(name); 273 krb5_free_host_realm(realms); 274 krb5_free_principal(server); 275 #ifdef ENCRYPTION 276 if (newkey) { 277 /* keep the key in our private storage, but don't use it 278 yet---see kerberos5_reply() below */ 279 if (newkey->keytype != KEYTYPE_DES) { 280 if (creds.keyblock.keytype == KEYTYPE_DES) 281 /* use the session key in credentials instead */ 282 memmove((char *)session_key, 283 (char *)creds.keyblock.contents, sizeof(Block)); 284 else 285 /* XXX ? */; 286 } else { 287 memmove((char *)session_key, (char *)newkey->contents, 288 sizeof(Block)); 289 } 290 krb5_free_keyblock(newkey); 291 } 292 #endif /* ENCRYPTION */ 293 if (r) { 294 if (auth_debug_mode) { 295 printf("Kerberos V5: mk_req failed (%s)\r\n", 296 error_message(r)); 297 } 298 return(0); 299 } 300 301 if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { 302 if (auth_debug_mode) 303 printf("Not enough room for user name\r\n"); 304 return(0); 305 } 306 if (!Data(ap, KRB_AUTH, auth.data, auth.length)) { 307 if (auth_debug_mode) 308 printf("Not enough room for authentication data\r\n"); 309 return(0); 310 } 311 if (auth_debug_mode) { 312 printf("Sent Kerberos V5 credentials to server\r\n"); 313 } 314 return(1); 315 } 316 317 void 318 kerberos5_is(ap, data, cnt) 319 Authenticator *ap; 320 unsigned char *data; 321 int cnt; 322 { 323 int r; 324 struct hostent *hp; 325 char *p1, *p2; 326 static char *realm = NULL; 327 krb5_principal server; 328 krb5_ap_rep_enc_part reply; 329 krb5_data outbuf; 330 #ifdef ENCRYPTION 331 Session_Key skey; 332 #endif /* ENCRYPTION */ 333 char *name; 334 char *getenv(); 335 krb5_data inbuf; 336 337 if (cnt-- < 1) 338 return; 339 switch (*data++) { 340 case KRB_AUTH: 341 auth.data = (char *)data; 342 auth.length = cnt; 343 344 if (!(hp = gethostbyname(LocalHostName))) { 345 if (auth_debug_mode) 346 printf("Cannot resolve local host name\r\n"); 347 Data(ap, KRB_REJECT, "Unknown local hostname.", -1); 348 auth_finished(ap, AUTH_REJECT); 349 return; 350 } 351 352 if (!realm && (krb5_get_default_realm(&realm))) { 353 if (auth_debug_mode) 354 printf("Could not get default realm\r\n"); 355 Data(ap, KRB_REJECT, "Could not get default realm.", -1); 356 auth_finished(ap, AUTH_REJECT); 357 return; 358 } 359 360 if ((name = malloc(strlen(hp->h_name)+1)) == NULL) { 361 if (auth_debug_mode) 362 printf("Out of memory for hostname in Kerberos V5\r\n"); 363 Data(ap, KRB_REJECT, "Out of memory.", -1); 364 auth_finished(ap, AUTH_REJECT); 365 return; 366 } 367 368 p1 = hp->h_name; 369 p2 = name; 370 371 while (*p2 = *p1++) { 372 if (isupper(*p2)) 373 *p2 |= 040; 374 ++p2; 375 } 376 377 if (authdat) 378 krb5_free_tkt_authent(authdat); 379 380 r = krb5_build_principal_ext(&server, 381 strlen(realm), realm, 382 4, "host", 383 p2 - name, name, 384 0); 385 if (!r) { 386 r = krb5_rd_req_simple(&auth, server, 0, &authdat); 387 krb5_free_principal(server); 388 } 389 if (r) { 390 char errbuf[128]; 391 392 errout: 393 authdat = 0; 394 (void) strcpy(errbuf, "Read req failed: "); 395 (void) strcat(errbuf, error_message(r)); 396 Data(ap, KRB_REJECT, errbuf, -1); 397 if (auth_debug_mode) 398 printf("%s\r\n", errbuf); 399 return; 400 } 401 free(name); 402 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 403 /* do ap_rep stuff here */ 404 reply.ctime = authdat->authenticator->ctime; 405 reply.cusec = authdat->authenticator->cusec; 406 reply.subkey = 0; /* use the one he gave us, so don't 407 need to return one here */ 408 reply.seq_number = 0; /* we don't do seq #'s. */ 409 410 if (r = krb5_mk_rep(&reply, 411 authdat->authenticator->subkey ? 412 authdat->authenticator->subkey : 413 authdat->ticket->enc_part2->session, 414 &outbuf)) { 415 goto errout; 416 } 417 Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); 418 } 419 if (krb5_unparse_name(authdat->ticket->enc_part2 ->client, 420 &name)) 421 name = 0; 422 Data(ap, KRB_ACCEPT, name, name ? -1 : 0); 423 if (auth_debug_mode) { 424 printf("Kerberos5 identifies him as ``%s''\r\n", 425 name ? name : ""); 426 } 427 auth_finished(ap, AUTH_USER); 428 429 free(name); 430 if (authdat->authenticator->subkey && 431 authdat->authenticator->subkey->keytype == KEYTYPE_DES) { 432 memmove((Voidptr )session_key, 433 (Voidptr )authdat->authenticator->subkey->contents, 434 sizeof(Block)); 435 } else if (authdat->ticket->enc_part2->session->keytype == 436 KEYTYPE_DES) { 437 memmove((Voidptr )session_key, 438 (Voidptr )authdat->ticket->enc_part2->session->contents, 439 sizeof(Block)); 440 } else 441 break; 442 443 #ifdef ENCRYPTION 444 skey.type = SK_DES; 445 skey.length = 8; 446 skey.data = session_key; 447 encrypt_session_key(&skey, 1); 448 #endif /* ENCRYPTION */ 449 break; 450 #ifdef FORWARD 451 case KRB_FORWARD: 452 inbuf.data = (char *)data; 453 inbuf.length = cnt; 454 if (r = rd_and_store_for_creds(&inbuf, authdat->ticket, 455 UserNameRequested)) { 456 char errbuf[128]; 457 458 (void) strcpy(errbuf, "Read forwarded creds failed: "); 459 (void) strcat(errbuf, error_message(r)); 460 Data(ap, KRB_FORWARD_REJECT, errbuf, -1); 461 if (auth_debug_mode) 462 printf("Could not read forwarded credentials\r\n"); 463 } 464 else 465 Data(ap, KRB_FORWARD_ACCEPT, 0, 0); 466 if (auth_debug_mode) 467 printf("Forwarded credentials obtained\r\n"); 468 break; 469 #endif /* FORWARD */ 470 default: 471 if (auth_debug_mode) 472 printf("Unknown Kerberos option %d\r\n", data[-1]); 473 Data(ap, KRB_REJECT, 0, 0); 474 break; 475 } 476 } 477 478 void 479 kerberos5_reply(ap, data, cnt) 480 Authenticator *ap; 481 unsigned char *data; 482 int cnt; 483 { 484 Session_Key skey; 485 static int mutual_complete = 0; 486 487 if (cnt-- < 1) 488 return; 489 switch (*data++) { 490 case KRB_REJECT: 491 if (cnt > 0) { 492 printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", 493 cnt, data); 494 } else 495 printf("[ Kerberos V5 refuses authentication ]\r\n"); 496 auth_send_retry(); 497 return; 498 case KRB_ACCEPT: 499 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && 500 !mutual_complete) { 501 printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\n"); 502 auth_send_retry(); 503 return; 504 } 505 if (cnt) 506 printf("[ Kerberos V5 accepts you as ``%.*s'' ]\n", cnt, data); 507 else 508 printf("[ Kerberos V5 accepts you ]\n"); 509 auth_finished(ap, AUTH_USER); 510 #ifdef FORWARD 511 if (forward_flags & OPTS_FORWARD_CREDS) 512 kerberos5_forward(ap); 513 #endif /* FORWARD */ 514 break; 515 case KRB_RESPONSE: 516 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 517 /* the rest of the reply should contain a krb_ap_rep */ 518 krb5_ap_rep_enc_part *reply; 519 krb5_data inbuf; 520 krb5_error_code r; 521 krb5_keyblock tmpkey; 522 523 inbuf.length = cnt; 524 inbuf.data = (char *)data; 525 526 tmpkey.keytype = KEYTYPE_DES; 527 tmpkey.contents = session_key; 528 tmpkey.length = sizeof(Block); 529 530 if (r = krb5_rd_rep(&inbuf, &tmpkey, &reply)) { 531 printf("[ Mutual authentication failed: %s ]\n", 532 error_message(r)); 533 auth_send_retry(); 534 return; 535 } 536 if (reply->ctime != authenticator.ctime || 537 reply->cusec != authenticator.cusec) { 538 printf("[ Mutual authentication failed (mismatched KRB_AP_REP) ]\n"); 539 auth_send_retry(); 540 return; 541 } 542 krb5_free_ap_rep_enc_part(reply); 543 #ifdef ENCRYPTION 544 skey.type = SK_DES; 545 skey.length = 8; 546 skey.data = session_key; 547 encrypt_session_key(&skey, 0); 548 #endif /* ENCRYPTION */ 549 mutual_complete = 1; 550 } 551 return; 552 #ifdef FORWARD 553 case KRB_FORWARD_ACCEPT: 554 printf("[ Kerberos V5 accepted forwarded credentials ]\n"); 555 return; 556 case KRB_FORWARD_REJECT: 557 printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", 558 cnt, data); 559 return; 560 #endif /* FORWARD */ 561 default: 562 if (auth_debug_mode) 563 printf("Unknown Kerberos option %d\r\n", data[-1]); 564 return; 565 } 566 } 567 568 int 569 kerberos5_status(ap, name, level) 570 Authenticator *ap; 571 char *name; 572 int level; 573 { 574 if (level < AUTH_USER) 575 return(level); 576 577 if (UserNameRequested && 578 krb5_kuserok(authdat->ticket->enc_part2->client, UserNameRequested)) 579 { 580 strcpy(name, UserNameRequested); 581 return(AUTH_VALID); 582 } else 583 return(AUTH_USER); 584 } 585 586 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 587 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 588 589 void 590 kerberos5_printsub(data, cnt, buf, buflen) 591 unsigned char *data, *buf; 592 int cnt, buflen; 593 { 594 char lbuf[32]; 595 register int i; 596 597 buf[buflen-1] = '\0'; /* make sure its NULL terminated */ 598 buflen -= 1; 599 600 switch(data[3]) { 601 case KRB_REJECT: /* Rejected (reason might follow) */ 602 strncpy((char *)buf, " REJECT ", buflen); 603 goto common; 604 605 case KRB_ACCEPT: /* Accepted (name might follow) */ 606 strncpy((char *)buf, " ACCEPT ", buflen); 607 common: 608 BUMP(buf, buflen); 609 if (cnt <= 4) 610 break; 611 ADDC(buf, buflen, '"'); 612 for (i = 4; i < cnt; i++) 613 ADDC(buf, buflen, data[i]); 614 ADDC(buf, buflen, '"'); 615 ADDC(buf, buflen, '\0'); 616 break; 617 618 619 case KRB_AUTH: /* Authentication data follows */ 620 strncpy((char *)buf, " AUTH", buflen); 621 goto common2; 622 623 case KRB_RESPONSE: 624 strncpy((char *)buf, " RESPONSE", buflen); 625 goto common2; 626 627 #ifdef FORWARD 628 case KRB_FORWARD: /* Forwarded credentials follow */ 629 strncpy((char *)buf, " FORWARD", buflen); 630 goto common2; 631 632 case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ 633 strncpy((char *)buf, " FORWARD_ACCEPT", buflen); 634 goto common2; 635 636 case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ 637 /* (reason might follow) */ 638 strncpy((char *)buf, " FORWARD_REJECT", buflen); 639 goto common2; 640 #endif /* FORWARD */ 641 642 default: 643 sprintf(lbuf, " %d (unknown)", data[3]); 644 strncpy((char *)buf, lbuf, buflen); 645 common2: 646 BUMP(buf, buflen); 647 for (i = 4; i < cnt; i++) { 648 sprintf(lbuf, " %d", data[i]); 649 strncpy((char *)buf, lbuf, buflen); 650 BUMP(buf, buflen); 651 } 652 break; 653 } 654 } 655 656 #ifdef FORWARD 657 void 658 kerberos5_forward(ap) 659 Authenticator *ap; 660 { 661 struct hostent *hp; 662 krb5_creds *local_creds; 663 krb5_error_code r; 664 krb5_data forw_creds; 665 extern krb5_cksumtype krb5_kdc_req_sumtype; 666 krb5_ccache ccache; 667 int i; 668 669 if (!(local_creds = (krb5_creds *) 670 calloc(1, sizeof(*local_creds)))) { 671 if (auth_debug_mode) 672 printf("Kerberos V5: could not allocate memory for credentials\r\n"); 673 return; 674 } 675 676 if (r = krb5_sname_to_principal(RemoteHostName, "host", 1, 677 &local_creds->server)) { 678 if (auth_debug_mode) 679 printf("Kerberos V5: could not build server name - %s\r\n", 680 error_message(r)); 681 krb5_free_creds(local_creds); 682 return; 683 } 684 685 if (r = krb5_cc_default(&ccache)) { 686 if (auth_debug_mode) 687 printf("Kerberos V5: could not get default ccache - %s\r\n", 688 error_message(r)); 689 krb5_free_creds(local_creds); 690 return; 691 } 692 693 if (r = krb5_cc_get_principal(ccache, &local_creds->client)) { 694 if (auth_debug_mode) 695 printf("Kerberos V5: could not get default principal - %s\r\n", 696 error_message(r)); 697 krb5_free_creds(local_creds); 698 return; 699 } 700 701 /* Get ticket from credentials cache */ 702 if (r = krb5_get_credentials(KRB5_GC_CACHED, ccache, local_creds)) { 703 if (auth_debug_mode) 704 printf("Kerberos V5: could not obtain credentials - %s\r\n", 705 error_message(r)); 706 krb5_free_creds(local_creds); 707 return; 708 } 709 710 if (r = get_for_creds(ETYPE_DES_CBC_CRC, 711 krb5_kdc_req_sumtype, 712 RemoteHostName, 713 local_creds->client, 714 &local_creds->keyblock, 715 forward_flags & OPTS_FORWARDABLE_CREDS, 716 &forw_creds)) { 717 if (auth_debug_mode) 718 printf("Kerberos V5: error getting forwarded creds - %s\r\n", 719 error_message(r)); 720 krb5_free_creds(local_creds); 721 return; 722 } 723 724 /* Send forwarded credentials */ 725 if (!Data(ap, KRB_FORWARD, forw_creds.data, forw_creds.length)) { 726 if (auth_debug_mode) 727 printf("Not enough room for authentication data\r\n"); 728 } 729 else { 730 if (auth_debug_mode) 731 printf("Forwarded local Kerberos V5 credentials to server\r\n"); 732 } 733 734 krb5_free_creds(local_creds); 735 } 736 #endif /* FORWARD */ 737 738 #endif /* KRB5 */ 739