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