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 22071 2007-11-14 20:04:50Z lha $"); 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 int forward(int); 90 int forwardable(int); 91 92 /* These values need to be the same as those defined in telnet/main.c. */ 93 /* Either define them in both places, or put in some common header file. */ 94 #define OPTS_FORWARD_CREDS 0x00000002 95 #define OPTS_FORWARDABLE_CREDS 0x00000001 96 97 98 void kerberos5_forward (Authenticator *); 99 100 static unsigned char str_data[4] = { IAC, SB, TELOPT_AUTHENTICATION, 0 }; 101 102 #define KRB_AUTH 0 /* Authentication data follows */ 103 #define KRB_REJECT 1 /* Rejected (reason might follow) */ 104 #define KRB_ACCEPT 2 /* Accepted */ 105 #define KRB_RESPONSE 3 /* Response for mutual auth. */ 106 107 #define KRB_FORWARD 4 /* Forwarded credentials follow */ 108 #define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */ 109 #define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */ 110 111 static krb5_data auth; 112 static krb5_ticket *ticket; 113 114 static krb5_context context; 115 static krb5_auth_context auth_context; 116 117 static int 118 Data(Authenticator *ap, int type, const void *d, int c) 119 { 120 const unsigned char *cp, *cd = d; 121 unsigned char *p0, *p; 122 size_t len = sizeof(str_data) + 3 + 2; 123 int ret; 124 125 if (c == -1) 126 c = strlen((const char*)cd); 127 128 for (cp = cd; cp - cd < c; cp++, len++) 129 if (*cp == IAC) 130 len++; 131 132 p0 = malloc(len); 133 if (p0 == NULL) 134 return 0; 135 136 memcpy(p0, str_data, sizeof(str_data)); 137 p = p0 + sizeof(str_data); 138 139 if (auth_debug_mode) { 140 printf("%s:%d: [%d] (%d)", 141 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", 142 str_data[3], 143 type, c); 144 printd(d, c); 145 printf("\r\n"); 146 } 147 *p++ = ap->type; 148 *p++ = ap->way; 149 *p++ = type; 150 while (c-- > 0) { 151 if ((*p++ = *cd++) == IAC) 152 *p++ = IAC; 153 } 154 *p++ = IAC; 155 *p++ = SE; 156 if (str_data[3] == TELQUAL_IS) 157 printsub('>', &p0[2], len - 2); 158 ret = telnet_net_write(p0, len); 159 free(p0); 160 return ret; 161 } 162 163 int 164 kerberos5_init(Authenticator *ap, int server) 165 { 166 krb5_error_code ret; 167 168 ret = krb5_init_context(&context); 169 if (ret) 170 return 0; 171 if (server) { 172 krb5_keytab kt; 173 krb5_kt_cursor cursor; 174 175 ret = krb5_kt_default(context, &kt); 176 if (ret) 177 return 0; 178 179 ret = krb5_kt_start_seq_get (context, kt, &cursor); 180 if (ret) { 181 krb5_kt_close (context, kt); 182 return 0; 183 } 184 krb5_kt_end_seq_get (context, kt, &cursor); 185 krb5_kt_close (context, kt); 186 187 str_data[3] = TELQUAL_REPLY; 188 } else 189 str_data[3] = TELQUAL_IS; 190 return(1); 191 } 192 193 extern int net; 194 static int 195 kerberos5_send(char *name, Authenticator *ap) 196 { 197 krb5_error_code ret; 198 krb5_ccache ccache; 199 int ap_opts; 200 krb5_data cksum_data; 201 char ap_msg[2]; 202 203 if (!UserNameRequested) { 204 if (auth_debug_mode) { 205 printf("Kerberos V5: no user name supplied\r\n"); 206 } 207 return(0); 208 } 209 210 ret = krb5_cc_default(context, &ccache); 211 if (ret) { 212 if (auth_debug_mode) { 213 printf("Kerberos V5: could not get default ccache: %s\r\n", 214 krb5_get_err_text (context, ret)); 215 } 216 return 0; 217 } 218 219 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) 220 ap_opts = AP_OPTS_MUTUAL_REQUIRED; 221 else 222 ap_opts = 0; 223 224 ap_opts |= AP_OPTS_USE_SUBKEY; 225 226 ret = krb5_auth_con_init (context, &auth_context); 227 if (ret) { 228 if (auth_debug_mode) { 229 printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n", 230 krb5_get_err_text(context, ret)); 231 } 232 return(0); 233 } 234 235 ret = krb5_auth_con_setaddrs_from_fd (context, 236 auth_context, 237 &net); 238 if (ret) { 239 if (auth_debug_mode) { 240 printf ("Kerberos V5:" 241 " krb5_auth_con_setaddrs_from_fd failed (%s)\r\n", 242 krb5_get_err_text(context, ret)); 243 } 244 return(0); 245 } 246 247 krb5_auth_con_setkeytype (context, auth_context, KEYTYPE_DES); 248 249 ap_msg[0] = ap->type; 250 ap_msg[1] = ap->way; 251 252 cksum_data.length = sizeof(ap_msg); 253 cksum_data.data = ap_msg; 254 255 256 { 257 krb5_principal service; 258 char sname[128]; 259 260 261 ret = krb5_sname_to_principal (context, 262 RemoteHostName, 263 NULL, 264 KRB5_NT_SRV_HST, 265 &service); 266 if(ret) { 267 if (auth_debug_mode) { 268 printf ("Kerberos V5:" 269 " krb5_sname_to_principal(%s) failed (%s)\r\n", 270 RemoteHostName, krb5_get_err_text(context, ret)); 271 } 272 return 0; 273 } 274 ret = krb5_unparse_name_fixed(context, service, sname, sizeof(sname)); 275 if(ret) { 276 if (auth_debug_mode) { 277 printf ("Kerberos V5:" 278 " krb5_unparse_name_fixed failed (%s)\r\n", 279 krb5_get_err_text(context, ret)); 280 } 281 return 0; 282 } 283 printf("[ Trying %s (%s)... ]\r\n", name, sname); 284 ret = krb5_mk_req_exact(context, &auth_context, ap_opts, 285 service, 286 &cksum_data, ccache, &auth); 287 krb5_free_principal (context, service); 288 289 } 290 if (ret) { 291 if (1 || auth_debug_mode) { 292 printf("Kerberos V5: mk_req failed (%s)\r\n", 293 krb5_get_err_text(context, ret)); 294 } 295 return(0); 296 } 297 298 if (!auth_sendname((unsigned char *)UserNameRequested, 299 strlen(UserNameRequested))) { 300 if (auth_debug_mode) 301 printf("Not enough room for user name\r\n"); 302 return(0); 303 } 304 if (!Data(ap, KRB_AUTH, auth.data, auth.length)) { 305 if (auth_debug_mode) 306 printf("Not enough room for authentication data\r\n"); 307 return(0); 308 } 309 if (auth_debug_mode) { 310 printf("Sent Kerberos V5 credentials to server\r\n"); 311 } 312 return(1); 313 } 314 315 int 316 kerberos5_send_mutual(Authenticator *ap) 317 { 318 return kerberos5_send("mutual KERBEROS5", ap); 319 } 320 321 int 322 kerberos5_send_oneway(Authenticator *ap) 323 { 324 return kerberos5_send("KERBEROS5", ap); 325 } 326 327 static void log_message(const char *fmt, ...) 328 { 329 va_list ap; 330 va_start(ap, fmt); 331 if (auth_debug_mode) { 332 va_start(ap, fmt); 333 vfprintf(stdout, fmt, ap); 334 va_end(ap); 335 fprintf(stdout, "\r\n"); 336 } 337 va_start(ap, fmt); 338 vsyslog(LOG_NOTICE, fmt, ap); 339 va_end(ap); 340 } 341 342 void 343 kerberos5_is(Authenticator *ap, unsigned char *data, int cnt) 344 { 345 krb5_error_code ret; 346 krb5_data outbuf; 347 krb5_keyblock *key_block; 348 char *name; 349 krb5_principal server; 350 int zero = 0; 351 352 if (cnt-- < 1) 353 return; 354 switch (*data++) { 355 case KRB_AUTH: 356 auth.data = (char *)data; 357 auth.length = cnt; 358 359 auth_context = NULL; 360 361 ret = krb5_auth_con_init (context, &auth_context); 362 if (ret) { 363 Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1); 364 auth_finished(ap, AUTH_REJECT); 365 log_message("Kerberos V5: krb5_auth_con_init failed (%s)", 366 krb5_get_err_text(context, ret)); 367 return; 368 } 369 370 ret = krb5_auth_con_setaddrs_from_fd (context, 371 auth_context, 372 &zero); 373 if (ret) { 374 Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1); 375 auth_finished(ap, AUTH_REJECT); 376 log_message("Kerberos V5: " 377 "krb5_auth_con_setaddrs_from_fd failed (%s)", 378 krb5_get_err_text(context, ret)); 379 return; 380 } 381 382 ret = krb5_sock_to_principal (context, 383 0, 384 "host", 385 KRB5_NT_SRV_HST, 386 &server); 387 if (ret) { 388 Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1); 389 auth_finished(ap, AUTH_REJECT); 390 log_message("Kerberos V5: " 391 "krb5_sock_to_principal failed (%s)", 392 krb5_get_err_text(context, ret)); 393 return; 394 } 395 396 ret = krb5_rd_req(context, 397 &auth_context, 398 &auth, 399 server, 400 NULL, 401 NULL, 402 &ticket); 403 404 krb5_free_principal (context, server); 405 if (ret) { 406 const char *errbuf2 = "Read req failed"; 407 char *errbuf; 408 int ret2; 409 410 ret2 = asprintf(&errbuf, 411 "Read req failed: %s", 412 krb5_get_err_text(context, ret)); 413 if (ret2 != -1) 414 errbuf2 = errbuf; 415 Data(ap, KRB_REJECT, errbuf2, -1); 416 log_message("%s", errbuf2); 417 if (ret2 != -1) 418 free (errbuf); 419 return; 420 } 421 422 { 423 char ap_msg[2]; 424 425 ap_msg[0] = ap->type; 426 ap_msg[1] = ap->way; 427 428 ret = krb5_verify_authenticator_checksum(context, 429 auth_context, 430 ap_msg, 431 sizeof(ap_msg)); 432 433 if (ret) { 434 const char *errbuf2 = "Bad checksum"; 435 char *errbuf; 436 int ret2; 437 438 ret2 = asprintf(&errbuf, "Bad checksum: %s", 439 krb5_get_err_text(context, ret)); 440 if (ret2 != -1) 441 errbuf2 = errbuf; 442 Data(ap, KRB_REJECT, errbuf2, -1); 443 log_message("%s", errbuf2); 444 if (ret2 != -1) 445 free(errbuf); 446 return; 447 } 448 } 449 ret = krb5_auth_con_getremotesubkey (context, 450 auth_context, 451 &key_block); 452 453 if (ret) { 454 Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1); 455 auth_finished(ap, AUTH_REJECT); 456 log_message("Kerberos V5: " 457 "krb5_auth_con_getremotesubkey failed (%s)", 458 krb5_get_err_text(context, ret)); 459 return; 460 } 461 462 if (key_block == NULL) { 463 ret = krb5_auth_con_getkey(context, 464 auth_context, 465 &key_block); 466 } 467 if (ret) { 468 Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1); 469 auth_finished(ap, AUTH_REJECT); 470 log_message("Kerberos V5: " 471 "krb5_auth_con_getkey failed (%s)", 472 krb5_get_err_text(context, ret)); 473 return; 474 } 475 if (key_block == NULL) { 476 Data(ap, KRB_REJECT, "no subkey received", -1); 477 auth_finished(ap, AUTH_REJECT); 478 log_message("Kerberos V5: " 479 "krb5_auth_con_getremotesubkey returned NULL key"); 480 return; 481 } 482 483 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 484 ret = krb5_mk_rep(context, auth_context, &outbuf); 485 if (ret) { 486 Data(ap, KRB_REJECT, 487 "krb5_mk_rep failed", -1); 488 auth_finished(ap, AUTH_REJECT); 489 log_message("Kerberos V5: " 490 "krb5_mk_rep failed (%s)", 491 krb5_get_err_text(context, ret)); 492 return; 493 } 494 Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); 495 } 496 if (krb5_unparse_name(context, ticket->client, &name)) 497 name = 0; 498 499 if(UserNameRequested && krb5_kuserok(context, 500 ticket->client, 501 UserNameRequested)) { 502 Data(ap, KRB_ACCEPT, name, name ? -1 : 0); 503 log_message("%s accepted as user %s from %s", 504 name ? name : "<unknown>", 505 UserNameRequested ? UserNameRequested : "<unknown>", 506 RemoteHostName ? RemoteHostName : "<unknown>"); 507 508 if(key_block->keytype == ETYPE_DES_CBC_MD5 || 509 key_block->keytype == ETYPE_DES_CBC_MD4 || 510 key_block->keytype == ETYPE_DES_CBC_CRC) { 511 Session_Key skey; 512 513 skey.type = SK_DES; 514 skey.length = 8; 515 skey.data = key_block->keyvalue.data; 516 encrypt_session_key(&skey, 0); 517 } 518 519 } else { 520 const char *msg2 = "user is not authorized to login"; 521 char *msg; 522 523 ret = asprintf (&msg, "user `%s' is not authorized to " 524 "login as `%s'", 525 name ? name : "<unknown>", 526 UserNameRequested ? UserNameRequested : "<nobody>"); 527 if (ret != -1) 528 msg2 = msg; 529 Data(ap, KRB_REJECT, (void *)msg2, -1); 530 if (ret != -1) 531 free(msg); 532 auth_finished (ap, AUTH_REJECT); 533 krb5_free_keyblock_contents(context, key_block); 534 break; 535 } 536 auth_finished(ap, AUTH_USER); 537 krb5_free_keyblock_contents(context, key_block); 538 539 break; 540 case KRB_FORWARD: { 541 struct passwd *pwd; 542 char ccname[1024]; /* XXX */ 543 krb5_data inbuf; 544 krb5_ccache ccache; 545 inbuf.data = (char *)data; 546 inbuf.length = cnt; 547 548 pwd = getpwnam (UserNameRequested); 549 if (pwd == NULL) 550 break; 551 552 snprintf (ccname, sizeof(ccname), 553 "FILE:/tmp/krb5cc_%lu", (unsigned long)pwd->pw_uid); 554 555 ret = krb5_cc_resolve (context, ccname, &ccache); 556 if (ret) { 557 log_message("Kerberos V5: could not get ccache: %s", 558 krb5_get_err_text(context, ret)); 559 break; 560 } 561 562 ret = krb5_cc_initialize (context, 563 ccache, 564 ticket->client); 565 if (ret) { 566 log_message("Kerberos V5: could not init ccache: %s", 567 krb5_get_err_text(context, ret)); 568 break; 569 } 570 571 #if defined(DCE) 572 esetenv("KRB5CCNAME", ccname, 1); 573 #endif 574 ret = krb5_rd_cred2 (context, 575 auth_context, 576 ccache, 577 &inbuf); 578 if(ret) { 579 const char *errbuf2 = "Read forwarded creds failed"; 580 char *errbuf; 581 int ret2; 582 583 ret2 = asprintf (&errbuf, 584 "Read forwarded creds failed: %s", 585 krb5_get_err_text (context, ret)); 586 if (ret2 != -1) 587 errbuf2 = errbuf; 588 Data(ap, KRB_FORWARD_REJECT, errbuf, -1); 589 log_message("Could not read forwarded credentials: %s", errbuf); 590 591 if (ret2 != -1) 592 free (errbuf); 593 } else { 594 Data(ap, KRB_FORWARD_ACCEPT, 0, 0); 595 #if defined(DCE) 596 dfsfwd = 1; 597 #endif 598 } 599 chown (ccname + 5, pwd->pw_uid, -1); 600 log_message("Forwarded credentials obtained"); 601 break; 602 } 603 default: 604 log_message("Unknown Kerberos option %d", data[-1]); 605 Data(ap, KRB_REJECT, 0, 0); 606 break; 607 } 608 } 609 610 void 611 kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt) 612 { 613 static int mutual_complete = 0; 614 615 if (cnt-- < 1) 616 return; 617 switch (*data++) { 618 case KRB_REJECT: 619 if (cnt > 0) { 620 printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", 621 cnt, data); 622 } else 623 printf("[ Kerberos V5 refuses authentication ]\r\n"); 624 auth_send_retry(); 625 return; 626 case KRB_ACCEPT: { 627 krb5_error_code ret; 628 Session_Key skey; 629 krb5_keyblock *keyblock; 630 631 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && 632 !mutual_complete) { 633 printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n"); 634 auth_send_retry(); 635 return; 636 } 637 if (cnt) 638 printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data); 639 else 640 printf("[ Kerberos V5 accepts you ]\r\n"); 641 642 ret = krb5_auth_con_getlocalsubkey (context, 643 auth_context, 644 &keyblock); 645 if (ret) 646 ret = krb5_auth_con_getkey (context, 647 auth_context, 648 &keyblock); 649 if(ret) { 650 printf("[ krb5_auth_con_getkey: %s ]\r\n", 651 krb5_get_err_text(context, ret)); 652 auth_send_retry(); 653 return; 654 } 655 656 skey.type = SK_DES; 657 skey.length = 8; 658 skey.data = keyblock->keyvalue.data; 659 encrypt_session_key(&skey, 0); 660 krb5_free_keyblock_contents (context, keyblock); 661 auth_finished(ap, AUTH_USER); 662 if (forward_flags & OPTS_FORWARD_CREDS) 663 kerberos5_forward(ap); 664 break; 665 } 666 case KRB_RESPONSE: 667 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 668 /* the rest of the reply should contain a krb_ap_rep */ 669 krb5_ap_rep_enc_part *reply; 670 krb5_data inbuf; 671 krb5_error_code ret; 672 673 inbuf.length = cnt; 674 inbuf.data = (char *)data; 675 676 ret = krb5_rd_rep(context, auth_context, &inbuf, &reply); 677 if (ret) { 678 printf("[ Mutual authentication failed: %s ]\r\n", 679 krb5_get_err_text (context, ret)); 680 auth_send_retry(); 681 return; 682 } 683 krb5_free_ap_rep_enc_part(context, reply); 684 mutual_complete = 1; 685 } 686 return; 687 case KRB_FORWARD_ACCEPT: 688 printf("[ Kerberos V5 accepted forwarded credentials ]\r\n"); 689 return; 690 case KRB_FORWARD_REJECT: 691 printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", 692 cnt, data); 693 return; 694 default: 695 if (auth_debug_mode) 696 printf("Unknown Kerberos option %d\r\n", data[-1]); 697 return; 698 } 699 } 700 701 int 702 kerberos5_status(Authenticator *ap, char *name, size_t name_sz, int level) 703 { 704 if (level < AUTH_USER) 705 return(level); 706 707 if (UserNameRequested && 708 krb5_kuserok(context, 709 ticket->client, 710 UserNameRequested)) 711 { 712 strlcpy(name, UserNameRequested, name_sz); 713 #if defined(DCE) 714 dfsk5ok = 1; 715 #endif 716 return(AUTH_VALID); 717 } else 718 return(AUTH_USER); 719 } 720 721 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 722 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 723 724 void 725 kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen) 726 { 727 int i; 728 729 buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ 730 buflen -= 1; 731 732 switch(data[3]) { 733 case KRB_REJECT: /* Rejected (reason might follow) */ 734 strlcpy((char *)buf, " REJECT ", buflen); 735 goto common; 736 737 case KRB_ACCEPT: /* Accepted (name might follow) */ 738 strlcpy((char *)buf, " ACCEPT ", buflen); 739 common: 740 BUMP(buf, buflen); 741 if (cnt <= 4) 742 break; 743 ADDC(buf, buflen, '"'); 744 for (i = 4; i < cnt; i++) 745 ADDC(buf, buflen, data[i]); 746 ADDC(buf, buflen, '"'); 747 ADDC(buf, buflen, '\0'); 748 break; 749 750 751 case KRB_AUTH: /* Authentication data follows */ 752 strlcpy((char *)buf, " AUTH", buflen); 753 goto common2; 754 755 case KRB_RESPONSE: 756 strlcpy((char *)buf, " RESPONSE", buflen); 757 goto common2; 758 759 case KRB_FORWARD: /* Forwarded credentials follow */ 760 strlcpy((char *)buf, " FORWARD", buflen); 761 goto common2; 762 763 case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ 764 strlcpy((char *)buf, " FORWARD_ACCEPT", buflen); 765 goto common2; 766 767 case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ 768 /* (reason might follow) */ 769 strlcpy((char *)buf, " FORWARD_REJECT", buflen); 770 goto common2; 771 772 default: 773 snprintf((char*)buf, buflen, " %d (unknown)", data[3]); 774 common2: 775 BUMP(buf, buflen); 776 for (i = 4; i < cnt; i++) { 777 snprintf((char*)buf, buflen, " %d", data[i]); 778 BUMP(buf, buflen); 779 } 780 break; 781 } 782 } 783 784 void 785 kerberos5_forward(Authenticator *ap) 786 { 787 krb5_error_code ret; 788 krb5_ccache ccache; 789 krb5_creds creds; 790 KDCOptions flags; 791 krb5_data out_data; 792 krb5_principal principal; 793 794 ret = krb5_cc_default (context, &ccache); 795 if (ret) { 796 if (auth_debug_mode) 797 printf ("KerberosV5: could not get default ccache: %s\r\n", 798 krb5_get_err_text (context, ret)); 799 return; 800 } 801 802 ret = krb5_cc_get_principal (context, ccache, &principal); 803 if (ret) { 804 if (auth_debug_mode) 805 printf ("KerberosV5: could not get principal: %s\r\n", 806 krb5_get_err_text (context, ret)); 807 return; 808 } 809 810 memset (&creds, 0, sizeof(creds)); 811 812 creds.client = principal; 813 814 ret = krb5_build_principal (context, 815 &creds.server, 816 strlen(principal->realm), 817 principal->realm, 818 "krbtgt", 819 principal->realm, 820 NULL); 821 822 if (ret) { 823 if (auth_debug_mode) 824 printf ("KerberosV5: could not get principal: %s\r\n", 825 krb5_get_err_text (context, ret)); 826 return; 827 } 828 829 creds.times.endtime = 0; 830 831 memset(&flags, 0, sizeof(flags)); 832 flags.forwarded = 1; 833 if (forward_flags & OPTS_FORWARDABLE_CREDS) 834 flags.forwardable = 1; 835 836 ret = krb5_get_forwarded_creds (context, 837 auth_context, 838 ccache, 839 KDCOptions2int(flags), 840 RemoteHostName, 841 &creds, 842 &out_data); 843 if (ret) { 844 if (auth_debug_mode) 845 printf ("Kerberos V5: error getting forwarded creds: %s\r\n", 846 krb5_get_err_text (context, ret)); 847 return; 848 } 849 850 if(!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) { 851 if (auth_debug_mode) 852 printf("Not enough room for authentication data\r\n"); 853 } else { 854 if (auth_debug_mode) 855 printf("Forwarded local Kerberos V5 credentials to server\r\n"); 856 } 857 } 858 859 #if defined(DCE) 860 /* if this was a K5 authentication try and join a PAG for the user. */ 861 void 862 kerberos5_dfspag(void) 863 { 864 if (dfsk5ok) { 865 dfspag = krb5_dfs_pag(context, dfsfwd, ticket->client, 866 UserNameRequested); 867 } 868 } 869 #endif 870 871 int 872 kerberos5_set_forward(int on) 873 { 874 if(on == 0) 875 forward_flags &= ~OPTS_FORWARD_CREDS; 876 if(on == 1) 877 forward_flags |= OPTS_FORWARD_CREDS; 878 if(on == -1) 879 forward_flags ^= OPTS_FORWARD_CREDS; 880 return 0; 881 } 882 883 int 884 kerberos5_set_forwardable(int on) 885 { 886 if(on == 0) 887 forward_flags &= ~OPTS_FORWARDABLE_CREDS; 888 if(on == 1) 889 forward_flags |= OPTS_FORWARDABLE_CREDS; 890 if(on == -1) 891 forward_flags ^= OPTS_FORWARDABLE_CREDS; 892 return 0; 893 } 894 895 #endif /* KRB5 */ 896