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