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$"); 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, KRB5_ENCTYPE_DES_CBC_CRC); 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 krb5_free_keyblock(context, key_block); 493 return; 494 } 495 Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length); 496 } 497 if (krb5_unparse_name(context, ticket->client, &name)) 498 name = 0; 499 500 if(UserNameRequested && krb5_kuserok(context, 501 ticket->client, 502 UserNameRequested)) { 503 Data(ap, KRB_ACCEPT, name, name ? -1 : 0); 504 log_message("%s accepted as user %s from %s", 505 name ? name : "<unknown>", 506 UserNameRequested ? UserNameRequested : "<unknown>", 507 RemoteHostName ? RemoteHostName : "<unknown>"); 508 509 if(key_block->keytype == ETYPE_DES_CBC_MD5 || 510 key_block->keytype == ETYPE_DES_CBC_MD4 || 511 key_block->keytype == ETYPE_DES_CBC_CRC) { 512 Session_Key skey; 513 514 skey.type = SK_DES; 515 skey.length = 8; 516 skey.data = key_block->keyvalue.data; 517 encrypt_session_key(&skey, 0); 518 } 519 520 } else { 521 const char *msg2 = "user is not authorized to login"; 522 char *msg; 523 524 ret = asprintf (&msg, "user `%s' is not authorized to " 525 "login as `%s'", 526 name ? name : "<unknown>", 527 UserNameRequested ? UserNameRequested : "<nobody>"); 528 if (ret != -1) 529 msg2 = msg; 530 Data(ap, KRB_REJECT, (void *)msg2, -1); 531 if (ret != -1) 532 free(msg); 533 auth_finished (ap, AUTH_REJECT); 534 krb5_free_keyblock(context, key_block); 535 break; 536 } 537 auth_finished(ap, AUTH_USER); 538 krb5_free_keyblock(context, key_block); 539 540 break; 541 case KRB_FORWARD: { 542 struct passwd *pwd; 543 char ccname[1024]; /* XXX */ 544 krb5_data inbuf; 545 krb5_ccache ccache; 546 inbuf.data = (char *)data; 547 inbuf.length = cnt; 548 549 pwd = getpwnam (UserNameRequested); 550 if (pwd == NULL) 551 break; 552 553 snprintf (ccname, sizeof(ccname), 554 "FILE:/tmp/krb5cc_%lu", (unsigned long)pwd->pw_uid); 555 556 ret = krb5_cc_resolve (context, ccname, &ccache); 557 if (ret) { 558 log_message("Kerberos V5: could not get ccache: %s", 559 krb5_get_err_text(context, ret)); 560 break; 561 } 562 563 ret = krb5_cc_initialize (context, 564 ccache, 565 ticket->client); 566 if (ret) { 567 log_message("Kerberos V5: could not init ccache: %s", 568 krb5_get_err_text(context, ret)); 569 break; 570 } 571 572 #if defined(DCE) 573 esetenv("KRB5CCNAME", ccname, 1); 574 #endif 575 ret = krb5_rd_cred2 (context, 576 auth_context, 577 ccache, 578 &inbuf); 579 if(ret) { 580 const char *errbuf2 = "Read forwarded creds failed"; 581 char *errbuf; 582 int ret2; 583 584 ret2 = asprintf (&errbuf, 585 "Read forwarded creds failed: %s", 586 krb5_get_err_text (context, ret)); 587 if (ret2 != -1) 588 errbuf2 = errbuf; 589 Data(ap, KRB_FORWARD_REJECT, errbuf, -1); 590 log_message("Could not read forwarded credentials: %s", errbuf); 591 592 if (ret2 != -1) 593 free (errbuf); 594 } else { 595 Data(ap, KRB_FORWARD_ACCEPT, 0, 0); 596 #if defined(DCE) 597 dfsfwd = 1; 598 #endif 599 } 600 chown (ccname + 5, pwd->pw_uid, -1); 601 log_message("Forwarded credentials obtained"); 602 break; 603 } 604 default: 605 log_message("Unknown Kerberos option %d", data[-1]); 606 Data(ap, KRB_REJECT, 0, 0); 607 break; 608 } 609 } 610 611 void 612 kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt) 613 { 614 static int mutual_complete = 0; 615 616 if (cnt-- < 1) 617 return; 618 switch (*data++) { 619 case KRB_REJECT: 620 if (cnt > 0) { 621 printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n", 622 cnt, data); 623 } else 624 printf("[ Kerberos V5 refuses authentication ]\r\n"); 625 auth_send_retry(); 626 return; 627 case KRB_ACCEPT: { 628 krb5_error_code ret; 629 Session_Key skey; 630 krb5_keyblock *keyblock; 631 632 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && 633 !mutual_complete) { 634 printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n"); 635 auth_send_retry(); 636 return; 637 } 638 if (cnt) 639 printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data); 640 else 641 printf("[ Kerberos V5 accepts you ]\r\n"); 642 643 ret = krb5_auth_con_getlocalsubkey (context, 644 auth_context, 645 &keyblock); 646 if (ret) 647 ret = krb5_auth_con_getkey (context, 648 auth_context, 649 &keyblock); 650 if(ret) { 651 printf("[ krb5_auth_con_getkey: %s ]\r\n", 652 krb5_get_err_text(context, ret)); 653 auth_send_retry(); 654 return; 655 } 656 657 skey.type = SK_DES; 658 skey.length = 8; 659 skey.data = keyblock->keyvalue.data; 660 encrypt_session_key(&skey, 0); 661 krb5_free_keyblock (context, keyblock); 662 auth_finished(ap, AUTH_USER); 663 if (forward_flags & OPTS_FORWARD_CREDS) 664 kerberos5_forward(ap); 665 break; 666 } 667 case KRB_RESPONSE: 668 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 669 /* the rest of the reply should contain a krb_ap_rep */ 670 krb5_ap_rep_enc_part *reply; 671 krb5_data inbuf; 672 krb5_error_code ret; 673 674 inbuf.length = cnt; 675 inbuf.data = (char *)data; 676 677 ret = krb5_rd_rep(context, auth_context, &inbuf, &reply); 678 if (ret) { 679 printf("[ Mutual authentication failed: %s ]\r\n", 680 krb5_get_err_text (context, ret)); 681 auth_send_retry(); 682 return; 683 } 684 krb5_free_ap_rep_enc_part(context, reply); 685 mutual_complete = 1; 686 } 687 return; 688 case KRB_FORWARD_ACCEPT: 689 printf("[ Kerberos V5 accepted forwarded credentials ]\r\n"); 690 return; 691 case KRB_FORWARD_REJECT: 692 printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n", 693 cnt, data); 694 return; 695 default: 696 if (auth_debug_mode) 697 printf("Unknown Kerberos option %d\r\n", data[-1]); 698 return; 699 } 700 } 701 702 int 703 kerberos5_status(Authenticator *ap, char *name, size_t name_sz, int level) 704 { 705 if (level < AUTH_USER) 706 return(level); 707 708 if (UserNameRequested && 709 krb5_kuserok(context, 710 ticket->client, 711 UserNameRequested)) 712 { 713 strlcpy(name, UserNameRequested, name_sz); 714 #if defined(DCE) 715 dfsk5ok = 1; 716 #endif 717 return(AUTH_VALID); 718 } else 719 return(AUTH_USER); 720 } 721 722 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 723 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 724 725 void 726 kerberos5_printsub(unsigned char *data, size_t cnt, 727 unsigned char *buf, size_t buflen) 728 { 729 int i; 730 731 buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ 732 buflen -= 1; 733 734 switch(data[3]) { 735 case KRB_REJECT: /* Rejected (reason might follow) */ 736 strlcpy((char *)buf, " REJECT ", buflen); 737 goto common; 738 739 case KRB_ACCEPT: /* Accepted (name might follow) */ 740 strlcpy((char *)buf, " ACCEPT ", buflen); 741 common: 742 BUMP(buf, buflen); 743 if (cnt <= 4) 744 break; 745 ADDC(buf, buflen, '"'); 746 for (i = 4; i < cnt; i++) 747 ADDC(buf, buflen, data[i]); 748 ADDC(buf, buflen, '"'); 749 ADDC(buf, buflen, '\0'); 750 break; 751 752 753 case KRB_AUTH: /* Authentication data follows */ 754 strlcpy((char *)buf, " AUTH", buflen); 755 goto common2; 756 757 case KRB_RESPONSE: 758 strlcpy((char *)buf, " RESPONSE", buflen); 759 goto common2; 760 761 case KRB_FORWARD: /* Forwarded credentials follow */ 762 strlcpy((char *)buf, " FORWARD", buflen); 763 goto common2; 764 765 case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */ 766 strlcpy((char *)buf, " FORWARD_ACCEPT", buflen); 767 goto common2; 768 769 case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */ 770 /* (reason might follow) */ 771 strlcpy((char *)buf, " FORWARD_REJECT", buflen); 772 goto common2; 773 774 default: 775 snprintf((char*)buf, buflen, " %d (unknown)", data[3]); 776 common2: 777 BUMP(buf, buflen); 778 for (i = 4; i < cnt; i++) { 779 snprintf((char*)buf, buflen, " %d", data[i]); 780 BUMP(buf, buflen); 781 } 782 break; 783 } 784 } 785 786 void 787 kerberos5_forward(Authenticator *ap) 788 { 789 krb5_error_code ret; 790 krb5_ccache ccache; 791 krb5_creds creds; 792 KDCOptions flags; 793 krb5_data out_data; 794 krb5_principal principal; 795 796 ret = krb5_cc_default (context, &ccache); 797 if (ret) { 798 if (auth_debug_mode) 799 printf ("KerberosV5: could not get default ccache: %s\r\n", 800 krb5_get_err_text (context, ret)); 801 return; 802 } 803 804 ret = krb5_cc_get_principal (context, ccache, &principal); 805 if (ret) { 806 if (auth_debug_mode) 807 printf ("KerberosV5: could not get principal: %s\r\n", 808 krb5_get_err_text (context, ret)); 809 return; 810 } 811 812 memset (&creds, 0, sizeof(creds)); 813 814 creds.client = principal; 815 816 ret = krb5_make_principal(context, 817 &creds.server, 818 principal->realm, 819 "krbtgt", 820 principal->realm, 821 NULL); 822 823 if (ret) { 824 if (auth_debug_mode) 825 printf ("KerberosV5: could not get principal: %s\r\n", 826 krb5_get_err_text (context, ret)); 827 return; 828 } 829 830 creds.times.endtime = 0; 831 832 memset(&flags, 0, sizeof(flags)); 833 flags.forwarded = 1; 834 if (forward_flags & OPTS_FORWARDABLE_CREDS) 835 flags.forwardable = 1; 836 837 ret = krb5_get_forwarded_creds (context, 838 auth_context, 839 ccache, 840 KDCOptions2int(flags), 841 RemoteHostName, 842 &creds, 843 &out_data); 844 if (ret) { 845 if (auth_debug_mode) 846 printf ("Kerberos V5: error getting forwarded creds: %s\r\n", 847 krb5_get_err_text (context, ret)); 848 return; 849 } 850 851 if(!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) { 852 if (auth_debug_mode) 853 printf("Not enough room for authentication data\r\n"); 854 } else { 855 if (auth_debug_mode) 856 printf("Forwarded local Kerberos V5 credentials to server\r\n"); 857 } 858 } 859 860 #if defined(DCE) 861 /* if this was a K5 authentication try and join a PAG for the user. */ 862 void 863 kerberos5_dfspag(void) 864 { 865 if (dfsk5ok) { 866 dfspag = krb5_dfs_pag(context, dfsfwd, ticket->client, 867 UserNameRequested); 868 } 869 } 870 #endif 871 872 int 873 kerberos5_set_forward(int on) 874 { 875 if(on == 0) 876 forward_flags &= ~OPTS_FORWARD_CREDS; 877 if(on == 1) 878 forward_flags |= OPTS_FORWARD_CREDS; 879 if(on == -1) 880 forward_flags ^= OPTS_FORWARD_CREDS; 881 return 0; 882 } 883 884 int 885 kerberos5_set_forwardable(int on) 886 { 887 if(on == 0) 888 forward_flags &= ~OPTS_FORWARDABLE_CREDS; 889 if(on == 1) 890 forward_flags |= OPTS_FORWARDABLE_CREDS; 891 if(on == -1) 892 forward_flags ^= OPTS_FORWARDABLE_CREDS; 893 return 0; 894 } 895 896 #endif /* KRB5 */ 897