1 /* $NetBSD: kerberos5.c,v 1.8 2001/09/17 12:34:43 assar Exp $ */ 2 3 /*- 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 /* 37 * Copyright (C) 1990 by the Massachusetts Institute of Technology 38 * 39 * Export of this software from the United States of America may 40 * require a specific license from the United States Government. 41 * It is the responsibility of any person or organization contemplating 42 * export to obtain such a license before exporting. 43 * 44 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 45 * distribute this software and its documentation for any purpose and 46 * without fee is hereby granted, provided that the above copyright 47 * notice appear in all copies and that both that copyright notice and 48 * this permission notice appear in supporting documentation, and that 49 * the name of M.I.T. not be used in advertising or publicity pertaining 50 * to distribution of the software without specific, written prior 51 * permission. M.I.T. makes no representations about the suitability of 52 * this software for any purpose. It is provided "as is" without express 53 * or implied warranty. 54 */ 55 56 #ifdef KRB5 57 #include <arpa/telnet.h> 58 #include <stdio.h> 59 #include <stdlib.h> 60 #include <string.h> 61 #include <unistd.h> 62 #include <netdb.h> 63 #include <ctype.h> 64 #include <pwd.h> 65 #define Authenticator k5_Authenticator 66 #include <krb5.h> 67 #undef Authenticator 68 /* #include <roken.h> */ 69 70 #include "encrypt.h" 71 #include "auth.h" 72 #include "misc.h" 73 74 extern int net; 75 76 int forward_flags; /* Flags get set in telnet/main.c on -f and -F */ 77 int got_forwarded_creds;/* Tell telnetd to pass -F or -f to login. */ 78 79 int require_hwpreauth; 80 81 void kerberos5_forward(Authenticator *); 82 83 static unsigned char str_data[1024] = {IAC, SB, TELOPT_AUTHENTICATION, 0, 84 AUTHTYPE_KERBEROS_V5,}; 85 86 #define KRB_AUTH 0 /* Authentication data follows */ 87 #define KRB_REJECT 1 /* Rejected (reason might follow) */ 88 #define KRB_ACCEPT 2 /* Accepted */ 89 #define KRB_RESPONSE 3 /* Response for mutual auth. */ 90 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 95 static krb5_data auth; 96 static krb5_ticket *ticket; 97 98 krb5_context telnet_context; 99 static krb5_auth_context auth_context; 100 101 static int 102 Data(Authenticator *ap, int type, void *d, int c) 103 { 104 unsigned char *p = str_data + 4; 105 unsigned char *cd = (unsigned char *) d; 106 107 if (c == -1) 108 c = strlen(cd); 109 110 if (auth_debug_mode) { 111 printf("%s:%d: [%d] (%d)", 112 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", 113 str_data[3], 114 type, c); 115 printd(d, c); 116 printf("\r\n"); 117 } 118 *p++ = ap->type; 119 *p++ = ap->way; 120 *p++ = type; 121 while (c-- > 0) { 122 if ((*p++ = *cd++) == IAC) 123 *p++ = IAC; 124 } 125 *p++ = IAC; 126 *p++ = SE; 127 if (str_data[3] == TELQUAL_IS) 128 printsub('>', &str_data[2], p - &str_data[2]); 129 return (telnet_net_write(str_data, p - str_data)); 130 } 131 132 int 133 kerberos5_init(Authenticator *ap, int server) 134 { 135 krb5_error_code ret; 136 137 if (telnet_context == 0) { 138 ret = krb5_init_context(&telnet_context); 139 if (ret) 140 return 0; 141 } 142 143 if (server) { 144 krb5_keytab kt; 145 krb5_kt_cursor cursor; 146 147 ret = krb5_kt_default(telnet_context, &kt); 148 if (ret) 149 return 0; 150 151 ret = krb5_kt_start_seq_get(telnet_context, kt, &cursor); 152 if (ret) { 153 krb5_kt_close(telnet_context, kt); 154 return 0; 155 } 156 krb5_kt_end_seq_get(telnet_context, kt, &cursor); 157 krb5_kt_close(telnet_context, kt); 158 159 str_data[3] = TELQUAL_REPLY; 160 } else 161 str_data[3] = TELQUAL_IS; 162 return (1); 163 } 164 165 int 166 kerberos5_send(Authenticator *ap) 167 { 168 krb5_error_code ret; 169 krb5_ccache ccache; 170 int ap_opts; 171 krb5_data cksum_data; 172 char foo[2]; 173 174 printf("[ Trying KERBEROS5 ... ]\r\n"); 175 176 if (!UserNameRequested) { 177 if (auth_debug_mode) { 178 printf("Kerberos V5: no user name supplied\r\n"); 179 } 180 return (0); 181 } 182 ret = krb5_cc_default(telnet_context, &ccache); 183 if (ret) { 184 if (auth_debug_mode) { 185 printf( 186 "Kerberos V5: could not get default ccache: %s\r\n", 187 krb5_get_err_text(telnet_context, ret)); 188 } 189 return (0); 190 } 191 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) 192 ap_opts = AP_OPTS_MUTUAL_REQUIRED; 193 else 194 ap_opts = 0; 195 196 ret = krb5_auth_con_init(telnet_context, &auth_context); 197 if (ret) { 198 if (auth_debug_mode) { 199 printf( 200 "Kerberos V5: krb5_auth_con_init failed: %s\r\n", 201 krb5_get_err_text(telnet_context, ret)); 202 } 203 return (0); 204 } 205 ret = krb5_auth_con_setaddrs_from_fd(telnet_context, 206 auth_context, &net); 207 if (ret) { 208 if (auth_debug_mode) { 209 printf("Kerberos V5: " 210 "krb5_auth_con_setaddrs_from_fd failed: %s\r\n", 211 krb5_get_err_text(telnet_context, ret)); 212 } 213 return (0); 214 } 215 krb5_auth_con_setkeytype(telnet_context, auth_context, KEYTYPE_DES); 216 217 foo[0] = ap->type; 218 foo[1] = ap->way; 219 220 cksum_data.length = sizeof(foo); 221 cksum_data.data = foo; 222 ret = krb5_mk_req(telnet_context, &auth_context, ap_opts, "host", 223 RemoteHostName, &cksum_data, ccache, &auth); 224 if (ret) { 225 if (1 || auth_debug_mode) { 226 printf("Kerberos V5: mk_req failed (%s)\r\n", 227 krb5_get_err_text(telnet_context, ret)); 228 } 229 return (0); 230 } 231 232 if (!auth_sendname((unsigned char *) UserNameRequested, 233 strlen(UserNameRequested))) { 234 if (auth_debug_mode) 235 printf("Not enough room for user name\r\n"); 236 return (0); 237 } 238 if (!Data(ap, KRB_AUTH, auth.data, auth.length)) { 239 if (auth_debug_mode) 240 printf("Not enough room for authentication data\r\n"); 241 return (0); 242 } 243 if (auth_debug_mode) { 244 printf("Sent Kerberos V5 credentials to server\r\n"); 245 } 246 return (1); 247 } 248 249 void 250 kerberos5_is(Authenticator * ap, unsigned char *data, int cnt) 251 { 252 krb5_error_code ret; 253 krb5_data outbuf; 254 krb5_keyblock *key_block; 255 char *name; 256 krb5_principal server; 257 int zero = 0; 258 259 if (cnt-- < 1) 260 return; 261 switch (*data++) { 262 case KRB_AUTH: 263 auth.data = (char *) data; 264 auth.length = cnt; 265 266 auth_context = NULL; 267 268 ret = krb5_auth_con_init(telnet_context, &auth_context); 269 if (ret) { 270 Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1); 271 auth_finished(ap, AUTH_REJECT); 272 if (auth_debug_mode) 273 printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", 274 krb5_get_err_text(telnet_context, ret)); 275 return; 276 } 277 ret = krb5_auth_con_setaddrs_from_fd(telnet_context, 278 auth_context, &zero); 279 if (ret) { 280 Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1); 281 auth_finished(ap, AUTH_REJECT); 282 if (auth_debug_mode) 283 printf("Kerberos V5: " 284 "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", 285 krb5_get_err_text(telnet_context, ret)); 286 return; 287 } 288 ret = krb5_sock_to_principal(telnet_context, 0, "host", 289 KRB5_NT_SRV_HST, &server); 290 if (ret) { 291 Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1); 292 auth_finished(ap, AUTH_REJECT); 293 if (auth_debug_mode) 294 printf("Kerberos V5: " 295 "krb5_sock_to_principal failed (%s)\r\n", 296 krb5_get_err_text(telnet_context, ret)); 297 return; 298 } 299 ret = krb5_rd_req(telnet_context, &auth_context, &auth, 300 server, NULL, NULL, &ticket); 301 krb5_free_principal(telnet_context, server); 302 303 if (ret) { 304 char *errbuf; 305 306 asprintf(&errbuf, 307 "Read req failed: %s", 308 krb5_get_err_text(telnet_context, ret)); 309 Data(ap, KRB_REJECT, errbuf, -1); 310 if (auth_debug_mode) 311 printf("%s\r\n", errbuf); 312 free(errbuf); 313 return; 314 } { 315 char foo[2]; 316 317 foo[0] = ap->type; 318 foo[1] = ap->way; 319 320 ret = krb5_verify_authenticator_checksum(telnet_context, 321 auth_context, foo, sizeof(foo)); 322 323 if (ret) { 324 char *errbuf; 325 asprintf(&errbuf, "Bad checksum: %s", 326 krb5_get_err_text(telnet_context, ret)); 327 Data(ap, KRB_REJECT, errbuf, -1); 328 if (auth_debug_mode) 329 printf("%s\r\n", errbuf); 330 free(errbuf); 331 return; 332 } 333 } 334 ret = krb5_auth_con_getremotesubkey(telnet_context, 335 auth_context, &key_block); 336 337 if (ret) { 338 Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1); 339 auth_finished(ap, AUTH_REJECT); 340 if (auth_debug_mode) 341 printf("Kerberos V5: " 342 "krb5_auth_con_getremotesubkey failed (%s)\r\n", 343 krb5_get_err_text(telnet_context, ret)); 344 return; 345 } 346 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 347 ret = krb5_mk_rep(telnet_context, 348 auth_context, &outbuf); 349 if (ret) { 350 Data(ap, KRB_REJECT, 351 "krb5_mk_rep failed", -1); 352 auth_finished(ap, AUTH_REJECT); 353 if (auth_debug_mode) 354 printf("Kerberos V5: " 355 "krb5_mk_rep failed (%s)\r\n", 356 krb5_get_err_text(telnet_context, 357 ret)); 358 return; 359 } 360 Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); 361 } 362 if (krb5_unparse_name(telnet_context, ticket->client, &name)) 363 name = 0; 364 365 if (UserNameRequested && krb5_kuserok(telnet_context, 366 ticket->client, UserNameRequested)) { 367 Data(ap, KRB_ACCEPT, name, name ? -1 : 0); 368 if (auth_debug_mode) { 369 printf("Kerberos5 identifies him as ``%s''\r\n", 370 name ? name : ""); 371 } 372 if (key_block->keytype == ETYPE_DES_CBC_MD5 || 373 key_block->keytype == ETYPE_DES_CBC_MD4 || 374 key_block->keytype == ETYPE_DES_CBC_CRC) { 375 Session_Key skey; 376 377 skey.type = SK_DES; 378 skey.length = 8; 379 skey.data = key_block->keyvalue.data; 380 encrypt_session_key(&skey, 0); 381 } 382 } else { 383 char *msg; 384 385 asprintf(&msg, "user `%s' is not authorized to " 386 "login as `%s'", 387 name ? name : "<unknown>", 388 UserNameRequested ? UserNameRequested : "<nobody>"); 389 if (msg == NULL) 390 Data(ap, KRB_REJECT, NULL, 0); 391 else { 392 Data(ap, KRB_REJECT, (void *) msg, -1); 393 free(msg); 394 } 395 auth_finished(ap, AUTH_REJECT); 396 krb5_free_keyblock_contents(telnet_context, key_block); 397 break; 398 } 399 auth_finished(ap, AUTH_USER); 400 krb5_free_keyblock_contents(telnet_context, key_block); 401 402 break; 403 case KRB_FORWARD:{ 404 struct passwd *pwd; 405 char ccname[1024]; /* XXX */ 406 krb5_data inbuf; 407 krb5_ccache ccache; 408 inbuf.data = (char *) data; 409 inbuf.length = cnt; 410 411 pwd = getpwnam(UserNameRequested); 412 if (pwd == NULL) 413 break; 414 415 snprintf(ccname, sizeof(ccname), 416 "FILE:/tmp/krb5cc_%u", pwd->pw_uid); 417 418 ret = krb5_cc_resolve(telnet_context, ccname, &ccache); 419 if (ret) { 420 if (auth_debug_mode) 421 printf("Kerberos V5: could not get ccache: %s\r\n", 422 krb5_get_err_text(telnet_context, 423 ret)); 424 break; 425 } 426 ret = krb5_cc_initialize(telnet_context, ccache, 427 ticket->client); 428 if (ret) { 429 if (auth_debug_mode) 430 printf("Kerberos V5: could not init ccache: %s\r\n", 431 krb5_get_err_text(telnet_context, 432 ret)); 433 break; 434 } 435 ret = krb5_rd_cred2(telnet_context, auth_context, 436 ccache, &inbuf); 437 if (ret) { 438 char *errbuf; 439 440 asprintf(&errbuf, 441 "Read forwarded creds failed: %s", 442 krb5_get_err_text(telnet_context, ret)); 443 if (errbuf == NULL) 444 Data(ap, KRB_FORWARD_REJECT, NULL, 0); 445 else 446 Data(ap, KRB_FORWARD_REJECT, errbuf, -1); 447 if (auth_debug_mode) 448 printf("Could not read forwarded credentials: %s\r\n", 449 errbuf); 450 free(errbuf); 451 } else 452 Data(ap, KRB_FORWARD_ACCEPT, 0, 0); 453 chown(ccname + 5, pwd->pw_uid, -1); 454 if (auth_debug_mode) 455 printf("Forwarded credentials obtained\r\n"); 456 break; 457 } 458 default: 459 if (auth_debug_mode) 460 printf("Unknown Kerberos option %d\r\n", data[-1]); 461 Data(ap, KRB_REJECT, 0, 0); 462 break; 463 } 464 } 465 466 void 467 kerberos5_reply(Authenticator * ap, unsigned char *data, int cnt) 468 { 469 static int mutual_complete = 0; 470 471 if (cnt-- < 1) 472 return; 473 switch (*data++) { 474 case KRB_REJECT: 475 if (cnt > 0) { 476 printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", 477 cnt, data); 478 } else 479 printf("[ Kerberos V5 refuses authentication ]\r\n"); 480 auth_send_retry(); 481 return; 482 case KRB_ACCEPT:{ 483 krb5_error_code ret; 484 Session_Key skey; 485 krb5_keyblock *keyblock; 486 487 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && 488 !mutual_complete) { 489 printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n"); 490 auth_send_retry(); 491 return; 492 } 493 if (cnt) 494 printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data); 495 else 496 printf("[ Kerberos V5 accepts you ]\r\n"); 497 498 ret = krb5_auth_con_getlocalsubkey(telnet_context, 499 auth_context, &keyblock); 500 if (ret) 501 ret = krb5_auth_con_getkey(telnet_context, 502 auth_context, &keyblock); 503 if (ret) { 504 printf("[ krb5_auth_con_getkey: %s ]\r\n", 505 krb5_get_err_text(telnet_context, ret)); 506 auth_send_retry(); 507 return; 508 } 509 skey.type = SK_DES; 510 skey.length = 8; 511 skey.data = keyblock->keyvalue.data; 512 encrypt_session_key(&skey, 0); 513 krb5_free_keyblock_contents(telnet_context, keyblock); 514 auth_finished(ap, AUTH_USER); 515 if (forward_flags & OPTS_FORWARD_CREDS) 516 kerberos5_forward(ap); 517 break; 518 } 519 case KRB_RESPONSE: 520 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 521 /* the rest of the reply should contain a krb_ap_rep */ 522 krb5_ap_rep_enc_part *reply; 523 krb5_data inbuf; 524 krb5_error_code ret; 525 526 inbuf.length = cnt; 527 inbuf.data = (char *) data; 528 529 ret = krb5_rd_rep(telnet_context, 530 auth_context, &inbuf, &reply); 531 if (ret) { 532 printf("[ Mutual authentication failed: %s ]\r\n", 533 krb5_get_err_text(telnet_context, ret)); 534 auth_send_retry(); 535 return; 536 } 537 krb5_free_ap_rep_enc_part(telnet_context, reply); 538 mutual_complete = 1; 539 } 540 return; 541 case KRB_FORWARD_ACCEPT: 542 printf("[ Kerberos V5 accepted forwarded credentials ]\r\n"); 543 return; 544 case KRB_FORWARD_REJECT: 545 printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", 546 cnt, data); 547 return; 548 default: 549 if (auth_debug_mode) 550 printf("Unknown Kerberos option %d\r\n", data[-1]); 551 return; 552 } 553 } 554 555 int 556 kerberos5_status(Authenticator *ap, char *name, int level) 557 { 558 if (level < AUTH_USER) 559 return (level); 560 561 if (UserNameRequested && 562 krb5_kuserok(telnet_context, ticket->client, UserNameRequested)) { 563 strcpy(name, UserNameRequested); 564 return (AUTH_VALID); 565 } else 566 return (AUTH_USER); 567 } 568 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 569 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 570 571 void 572 kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) 573 { 574 int i; 575 576 buf[buflen - 1] = '\0'; /* make sure its NULL terminated */ 577 buflen -= 1; 578 579 switch (data[3]) { 580 case KRB_REJECT: /* Rejected (reason might follow) */ 581 strlcpy((char *) buf, " REJECT ", buflen); 582 goto common; 583 584 case KRB_ACCEPT: /* Accepted (name might follow) */ 585 strlcpy((char *) buf, " ACCEPT ", buflen); 586 common: 587 BUMP(buf, buflen); 588 if (cnt <= 4) 589 break; 590 ADDC(buf, buflen, '"'); 591 for (i = 4; i < cnt; i++) 592 ADDC(buf, buflen, data[i]); 593 ADDC(buf, buflen, '"'); 594 ADDC(buf, buflen, '\0'); 595 break; 596 597 598 case KRB_AUTH: /* Authentication data follows */ 599 strlcpy((char *) buf, " AUTH", buflen); 600 goto common2; 601 602 case KRB_RESPONSE: 603 strlcpy((char *) buf, " RESPONSE", buflen); 604 goto common2; 605 606 case KRB_FORWARD: /* Forwarded credentials follow */ 607 strlcpy((char *) buf, " FORWARD", buflen); 608 goto common2; 609 610 case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ 611 strlcpy((char *) buf, " FORWARD_ACCEPT", buflen); 612 goto common2; 613 614 case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ 615 /* (reason might follow) */ 616 strlcpy((char *) buf, " FORWARD_REJECT", buflen); 617 goto common2; 618 619 default: 620 snprintf(buf, buflen, " %d (unknown)", data[3]); 621 common2: 622 BUMP(buf, buflen); 623 for (i = 4; i < cnt; i++) { 624 snprintf(buf, buflen, " %d", data[i]); 625 BUMP(buf, buflen); 626 } 627 break; 628 } 629 } 630 631 void 632 kerberos5_forward(Authenticator * ap) 633 { 634 krb5_error_code ret; 635 krb5_ccache ccache; 636 krb5_creds creds; 637 krb5_kdc_flags flags; 638 krb5_data out_data; 639 krb5_principal principal; 640 641 ret = krb5_cc_default(telnet_context, &ccache); 642 if (ret) { 643 if (auth_debug_mode) 644 printf("KerberosV5: could not get default ccache: %s\r\n", 645 krb5_get_err_text(telnet_context, ret)); 646 return; 647 } 648 ret = krb5_cc_get_principal(telnet_context, ccache, &principal); 649 if (ret) { 650 if (auth_debug_mode) 651 printf("KerberosV5: could not get principal: %s\r\n", 652 krb5_get_err_text(telnet_context, ret)); 653 return; 654 } 655 memset(&creds, 0, sizeof(creds)); 656 657 creds.client = principal; 658 659 ret = krb5_build_principal(telnet_context, &creds.server, 660 strlen(principal->realm), principal->realm, "krbtgt", 661 principal->realm, NULL); 662 663 if (ret) { 664 if (auth_debug_mode) 665 printf("KerberosV5: could not get principal: %s\r\n", 666 krb5_get_err_text(telnet_context, ret)); 667 return; 668 } 669 creds.times.endtime = 0; 670 671 flags.i = 0; 672 flags.b.forwarded = 1; 673 if (forward_flags & OPTS_FORWARDABLE_CREDS) 674 flags.b.forwardable = 1; 675 676 ret = krb5_get_forwarded_creds(telnet_context, auth_context, 677 ccache, flags.i, RemoteHostName, &creds, &out_data); 678 if (ret) { 679 if (auth_debug_mode) 680 printf("Kerberos V5: error getting forwarded creds: %s\r\n", 681 krb5_get_err_text(telnet_context, ret)); 682 return; 683 } 684 if (!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) { 685 if (auth_debug_mode) 686 printf("Not enough room for authentication data\r\n"); 687 } else { 688 if (auth_debug_mode) 689 printf("Forwarded local Kerberos V5 credentials to server\r\n"); 690 } 691 } 692 #endif /* KRB5 */ 693