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.2 (Berkeley) 12/15/93"; 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 bzero((Voidptr )sum, 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 bzero((char *)&creds, 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 memcpy((char *)session_key, 283 (char *)creds.keyblock.contents, sizeof(Block)); 284 else 285 /* XXX ? */; 286 } else { 287 memcpy((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 bcopy((Voidptr )authdat->authenticator->subkey->contents, 433 (Voidptr )session_key, sizeof(Block)); 434 } else if (authdat->ticket->enc_part2->session->keytype == 435 KEYTYPE_DES) { 436 bcopy((Voidptr )authdat->ticket->enc_part2->session->contents, 437 (Voidptr )session_key, sizeof(Block)); 438 } else 439 break; 440 441 #ifdef ENCRYPTION 442 skey.type = SK_DES; 443 skey.length = 8; 444 skey.data = session_key; 445 encrypt_session_key(&skey, 1); 446 #endif /* ENCRYPTION */ 447 break; 448 #ifdef FORWARD 449 case KRB_FORWARD: 450 inbuf.data = (char *)data; 451 inbuf.length = cnt; 452 if (r = rd_and_store_for_creds(&inbuf, authdat->ticket, 453 UserNameRequested)) { 454 char errbuf[128]; 455 456 (void) strcpy(errbuf, "Read forwarded creds failed: "); 457 (void) strcat(errbuf, error_message(r)); 458 Data(ap, KRB_FORWARD_REJECT, errbuf, -1); 459 if (auth_debug_mode) 460 printf("Could not read forwarded credentials\r\n"); 461 } 462 else 463 Data(ap, KRB_FORWARD_ACCEPT, 0, 0); 464 if (auth_debug_mode) 465 printf("Forwarded credentials obtained\r\n"); 466 break; 467 #endif /* FORWARD */ 468 default: 469 if (auth_debug_mode) 470 printf("Unknown Kerberos option %d\r\n", data[-1]); 471 Data(ap, KRB_REJECT, 0, 0); 472 break; 473 } 474 } 475 476 void 477 kerberos5_reply(ap, data, cnt) 478 Authenticator *ap; 479 unsigned char *data; 480 int cnt; 481 { 482 Session_Key skey; 483 static int mutual_complete = 0; 484 485 if (cnt-- < 1) 486 return; 487 switch (*data++) { 488 case KRB_REJECT: 489 if (cnt > 0) { 490 printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", 491 cnt, data); 492 } else 493 printf("[ Kerberos V5 refuses authentication ]\r\n"); 494 auth_send_retry(); 495 return; 496 case KRB_ACCEPT: 497 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && 498 !mutual_complete) { 499 printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\n"); 500 auth_send_retry(); 501 return; 502 } 503 if (cnt) 504 printf("[ Kerberos V5 accepts you as ``%.*s'' ]\n", cnt, data); 505 else 506 printf("[ Kerberos V5 accepts you ]\n"); 507 auth_finished(ap, AUTH_USER); 508 #ifdef FORWARD 509 if (forward_flags & OPTS_FORWARD_CREDS) 510 kerberos5_forward(ap); 511 #endif /* FORWARD */ 512 break; 513 case KRB_RESPONSE: 514 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 515 /* the rest of the reply should contain a krb_ap_rep */ 516 krb5_ap_rep_enc_part *reply; 517 krb5_data inbuf; 518 krb5_error_code r; 519 krb5_keyblock tmpkey; 520 521 inbuf.length = cnt; 522 inbuf.data = (char *)data; 523 524 tmpkey.keytype = KEYTYPE_DES; 525 tmpkey.contents = session_key; 526 tmpkey.length = sizeof(Block); 527 528 if (r = krb5_rd_rep(&inbuf, &tmpkey, &reply)) { 529 printf("[ Mutual authentication failed: %s ]\n", 530 error_message(r)); 531 auth_send_retry(); 532 return; 533 } 534 if (reply->ctime != authenticator.ctime || 535 reply->cusec != authenticator.cusec) { 536 printf("[ Mutual authentication failed (mismatched KRB_AP_REP) ]\n"); 537 auth_send_retry(); 538 return; 539 } 540 krb5_free_ap_rep_enc_part(reply); 541 #ifdef ENCRYPTION 542 skey.type = SK_DES; 543 skey.length = 8; 544 skey.data = session_key; 545 encrypt_session_key(&skey, 0); 546 #endif /* ENCRYPTION */ 547 mutual_complete = 1; 548 } 549 return; 550 #ifdef FORWARD 551 case KRB_FORWARD_ACCEPT: 552 printf("[ Kerberos V5 accepted forwarded credentials ]\n"); 553 return; 554 case KRB_FORWARD_REJECT: 555 printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", 556 cnt, data); 557 return; 558 #endif /* FORWARD */ 559 default: 560 if (auth_debug_mode) 561 printf("Unknown Kerberos option %d\r\n", data[-1]); 562 return; 563 } 564 } 565 566 int 567 kerberos5_status(ap, name, level) 568 Authenticator *ap; 569 char *name; 570 int level; 571 { 572 if (level < AUTH_USER) 573 return(level); 574 575 if (UserNameRequested && 576 krb5_kuserok(authdat->ticket->enc_part2->client, UserNameRequested)) 577 { 578 strcpy(name, UserNameRequested); 579 return(AUTH_VALID); 580 } else 581 return(AUTH_USER); 582 } 583 584 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 585 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 586 587 void 588 kerberos5_printsub(data, cnt, buf, buflen) 589 unsigned char *data, *buf; 590 int cnt, buflen; 591 { 592 char lbuf[32]; 593 register int i; 594 595 buf[buflen-1] = '\0'; /* make sure its NULL terminated */ 596 buflen -= 1; 597 598 switch(data[3]) { 599 case KRB_REJECT: /* Rejected (reason might follow) */ 600 strncpy((char *)buf, " REJECT ", buflen); 601 goto common; 602 603 case KRB_ACCEPT: /* Accepted (name might follow) */ 604 strncpy((char *)buf, " ACCEPT ", buflen); 605 common: 606 BUMP(buf, buflen); 607 if (cnt <= 4) 608 break; 609 ADDC(buf, buflen, '"'); 610 for (i = 4; i < cnt; i++) 611 ADDC(buf, buflen, data[i]); 612 ADDC(buf, buflen, '"'); 613 ADDC(buf, buflen, '\0'); 614 break; 615 616 617 case KRB_AUTH: /* Authentication data follows */ 618 strncpy((char *)buf, " AUTH", buflen); 619 goto common2; 620 621 case KRB_RESPONSE: 622 strncpy((char *)buf, " RESPONSE", buflen); 623 goto common2; 624 625 #ifdef FORWARD 626 case KRB_FORWARD: /* Forwarded credentials follow */ 627 strncpy((char *)buf, " FORWARD", buflen); 628 goto common2; 629 630 case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ 631 strncpy((char *)buf, " FORWARD_ACCEPT", buflen); 632 goto common2; 633 634 case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ 635 /* (reason might follow) */ 636 strncpy((char *)buf, " FORWARD_REJECT", buflen); 637 goto common2; 638 #endif /* FORWARD */ 639 640 default: 641 sprintf(lbuf, " %d (unknown)", data[3]); 642 strncpy((char *)buf, lbuf, buflen); 643 common2: 644 BUMP(buf, buflen); 645 for (i = 4; i < cnt; i++) { 646 sprintf(lbuf, " %d", data[i]); 647 strncpy((char *)buf, lbuf, buflen); 648 BUMP(buf, buflen); 649 } 650 break; 651 } 652 } 653 654 #ifdef FORWARD 655 void 656 kerberos5_forward(ap) 657 Authenticator *ap; 658 { 659 struct hostent *hp; 660 krb5_creds *local_creds; 661 krb5_error_code r; 662 krb5_data forw_creds; 663 extern krb5_cksumtype krb5_kdc_req_sumtype; 664 krb5_ccache ccache; 665 int i; 666 667 if (!(local_creds = (krb5_creds *) 668 calloc(1, sizeof(*local_creds)))) { 669 if (auth_debug_mode) 670 printf("Kerberos V5: could not allocate memory for credentials\r\n"); 671 return; 672 } 673 674 if (r = krb5_sname_to_principal(RemoteHostName, "host", 1, 675 &local_creds->server)) { 676 if (auth_debug_mode) 677 printf("Kerberos V5: could not build server name - %s\r\n", 678 error_message(r)); 679 krb5_free_creds(local_creds); 680 return; 681 } 682 683 if (r = krb5_cc_default(&ccache)) { 684 if (auth_debug_mode) 685 printf("Kerberos V5: could not get default ccache - %s\r\n", 686 error_message(r)); 687 krb5_free_creds(local_creds); 688 return; 689 } 690 691 if (r = krb5_cc_get_principal(ccache, &local_creds->client)) { 692 if (auth_debug_mode) 693 printf("Kerberos V5: could not get default principal - %s\r\n", 694 error_message(r)); 695 krb5_free_creds(local_creds); 696 return; 697 } 698 699 /* Get ticket from credentials cache */ 700 if (r = krb5_get_credentials(KRB5_GC_CACHED, ccache, local_creds)) { 701 if (auth_debug_mode) 702 printf("Kerberos V5: could not obtain credentials - %s\r\n", 703 error_message(r)); 704 krb5_free_creds(local_creds); 705 return; 706 } 707 708 if (r = get_for_creds(ETYPE_DES_CBC_CRC, 709 krb5_kdc_req_sumtype, 710 RemoteHostName, 711 local_creds->client, 712 &local_creds->keyblock, 713 forward_flags & OPTS_FORWARDABLE_CREDS, 714 &forw_creds)) { 715 if (auth_debug_mode) 716 printf("Kerberos V5: error getting forwarded creds - %s\r\n", 717 error_message(r)); 718 krb5_free_creds(local_creds); 719 return; 720 } 721 722 /* Send forwarded credentials */ 723 if (!Data(ap, KRB_FORWARD, forw_creds.data, forw_creds.length)) { 724 if (auth_debug_mode) 725 printf("Not enough room for authentication data\r\n"); 726 } 727 else { 728 if (auth_debug_mode) 729 printf("Forwarded local Kerberos V5 credentials to server\r\n"); 730 } 731 732 krb5_free_creds(local_creds); 733 } 734 #endif /* FORWARD */ 735 736 #endif /* KRB5 */ 737