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