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