10Sstevel@tonic-gate /*
2*4807Smp153739 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
30Sstevel@tonic-gate * Use is subject to license terms.
40Sstevel@tonic-gate */
50Sstevel@tonic-gate
60Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
70Sstevel@tonic-gate
80Sstevel@tonic-gate /*
90Sstevel@tonic-gate * usr/src/cmd/cmd-inet/usr.bin/telnet/kerberos5.c
100Sstevel@tonic-gate *
110Sstevel@tonic-gate * Copyright (c) 1991, 1993
120Sstevel@tonic-gate * The Regents of the University of California. All rights reserved.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without
150Sstevel@tonic-gate * modification, are permitted provided that the following conditions
160Sstevel@tonic-gate * are met:
170Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright
180Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer.
190Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright
200Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the
210Sstevel@tonic-gate * documentation and/or other materials provided with the distribution.
220Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software
230Sstevel@tonic-gate * must display the following acknowledgement:
240Sstevel@tonic-gate * This product includes software developed by the University of
250Sstevel@tonic-gate * California, Berkeley and its contributors.
260Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors
270Sstevel@tonic-gate * may be used to endorse or promote products derived from this software
280Sstevel@tonic-gate * without specific prior written permission.
290Sstevel@tonic-gate *
300Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
310Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
320Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
330Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
340Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
350Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
360Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
370Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
380Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
390Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
400Sstevel@tonic-gate * SUCH DAMAGE.
410Sstevel@tonic-gate */
420Sstevel@tonic-gate
430Sstevel@tonic-gate /* based on @(#)kerberos5.c 8.1 (Berkeley) 6/4/93 */
440Sstevel@tonic-gate
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate * Copyright (C) 1990 by the Massachusetts Institute of Technology
470Sstevel@tonic-gate *
480Sstevel@tonic-gate * Export of this software from the United States of America may
490Sstevel@tonic-gate * require a specific license from the United States Government.
500Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating
510Sstevel@tonic-gate * export to obtain such a license before exporting.
520Sstevel@tonic-gate *
530Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
540Sstevel@tonic-gate * distribute this software and its documentation for any purpose and
550Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright
560Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and
570Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that
580Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining
590Sstevel@tonic-gate * to distribution of the software without specific, written prior
600Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label
610Sstevel@tonic-gate * your software as modified software and not distribute it in such a
620Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software.
630Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of
640Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express
650Sstevel@tonic-gate * or implied warranty.
660Sstevel@tonic-gate */
670Sstevel@tonic-gate
680Sstevel@tonic-gate
690Sstevel@tonic-gate #include <arpa/telnet.h>
700Sstevel@tonic-gate #include <stdio.h>
710Sstevel@tonic-gate #include <ctype.h>
720Sstevel@tonic-gate #include <syslog.h>
730Sstevel@tonic-gate #include <stdlib.h>
740Sstevel@tonic-gate
750Sstevel@tonic-gate /* the following are from the kerberos tree */
760Sstevel@tonic-gate #include <k5-int.h>
770Sstevel@tonic-gate #include <com_err.h>
780Sstevel@tonic-gate #include <netdb.h>
790Sstevel@tonic-gate #include <profile/prof_int.h>
800Sstevel@tonic-gate #include <sys/param.h>
810Sstevel@tonic-gate #include "externs.h"
820Sstevel@tonic-gate
830Sstevel@tonic-gate extern char *RemoteHostName;
840Sstevel@tonic-gate extern boolean_t auth_debug_mode;
850Sstevel@tonic-gate extern int net;
860Sstevel@tonic-gate
871347Smp153739 #define ACCEPTED_ENCTYPE(a) \
881347Smp153739 (a == ENCTYPE_DES_CBC_CRC || a == ENCTYPE_DES_CBC_MD5)
890Sstevel@tonic-gate /* for comapatibility with non-Solaris KDC's, this has to be big enough */
900Sstevel@tonic-gate #define KERBEROS_BUFSIZ 8192
910Sstevel@tonic-gate
920Sstevel@tonic-gate int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */
930Sstevel@tonic-gate static void kerberos5_forward(Authenticator *);
940Sstevel@tonic-gate
950Sstevel@tonic-gate static unsigned char str_data[KERBEROS_BUFSIZ] = { IAC, SB,
960Sstevel@tonic-gate TELOPT_AUTHENTICATION, 0, AUTHTYPE_KERBEROS_V5, };
970Sstevel@tonic-gate static char *appdef[] = { "appdefaults", "telnet", NULL };
980Sstevel@tonic-gate static char *realmdef[] = { "realms", NULL, "telnet", NULL };
990Sstevel@tonic-gate
1000Sstevel@tonic-gate static krb5_auth_context auth_context = 0;
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate static krb5_data auth; /* telnetd gets session key from here */
1030Sstevel@tonic-gate static krb5_ticket *ticket = NULL;
1040Sstevel@tonic-gate /* telnet matches the AP_REQ and AP_REP with this */
1050Sstevel@tonic-gate
1060Sstevel@tonic-gate static krb5_keyblock *session_key = 0;
1070Sstevel@tonic-gate char *telnet_krb5_realm = NULL;
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate /*
1100Sstevel@tonic-gate * Change the kerberos realm
1110Sstevel@tonic-gate */
1120Sstevel@tonic-gate void
set_krb5_realm(char * name)1130Sstevel@tonic-gate set_krb5_realm(char *name)
1140Sstevel@tonic-gate {
1150Sstevel@tonic-gate if (name == NULL) {
1160Sstevel@tonic-gate (void) fprintf(stderr, gettext("Could not set Kerberos realm, "
1170Sstevel@tonic-gate "no realm provided.\n"));
1180Sstevel@tonic-gate return;
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate if (telnet_krb5_realm)
1220Sstevel@tonic-gate free(telnet_krb5_realm);
1230Sstevel@tonic-gate
1240Sstevel@tonic-gate telnet_krb5_realm = (char *)strdup(name);
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate if (telnet_krb5_realm == NULL)
1270Sstevel@tonic-gate (void) fprintf(stderr, gettext(
1280Sstevel@tonic-gate "Could not set Kerberos realm, malloc failed\n"));
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate #define RETURN_NOMEM { errno = ENOMEM; return (-1); }
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate static int
krb5_send_data(Authenticator * ap,int type,krb5_pointer d,int c)1340Sstevel@tonic-gate krb5_send_data(Authenticator *ap, int type, krb5_pointer d, int c)
1350Sstevel@tonic-gate {
1360Sstevel@tonic-gate /* the first 3 bytes are control chars */
1370Sstevel@tonic-gate unsigned char *p = str_data + 4;
1380Sstevel@tonic-gate unsigned char *cd = (unsigned char *)d;
1390Sstevel@tonic-gate /* spaceleft is incremented whenever p is decremented */
1400Sstevel@tonic-gate size_t spaceleft = sizeof (str_data) - 4;
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate if (c == -1)
1430Sstevel@tonic-gate c = strlen((char *)cd);
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate if (auth_debug_mode) {
1460Sstevel@tonic-gate (void) printf("%s:%d: [%d] (%d)",
1470Sstevel@tonic-gate str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
1480Sstevel@tonic-gate str_data[3], type, c);
1490Sstevel@tonic-gate printd(d, c);
1500Sstevel@tonic-gate (void) printf("\r\n");
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate if (spaceleft < 3)
1540Sstevel@tonic-gate RETURN_NOMEM;
1550Sstevel@tonic-gate *p++ = ap->type;
1560Sstevel@tonic-gate *p++ = ap->way;
1570Sstevel@tonic-gate *p++ = type;
1580Sstevel@tonic-gate spaceleft -= 3;
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate while (c-- > 0) {
1610Sstevel@tonic-gate if (spaceleft < 2)
1620Sstevel@tonic-gate RETURN_NOMEM;
1630Sstevel@tonic-gate if ((*p++ = *cd++) == IAC) {
1640Sstevel@tonic-gate *p++ = IAC;
1650Sstevel@tonic-gate spaceleft -= 2;
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate }
1680Sstevel@tonic-gate
1690Sstevel@tonic-gate if (spaceleft < 2)
1700Sstevel@tonic-gate RETURN_NOMEM;
1710Sstevel@tonic-gate *p++ = IAC;
1720Sstevel@tonic-gate *p++ = SE;
1730Sstevel@tonic-gate if (str_data[3] == TELQUAL_IS)
1740Sstevel@tonic-gate printsub('>', &str_data[2], p - &str_data[2]);
1750Sstevel@tonic-gate return (net_write(str_data, p - str_data));
1760Sstevel@tonic-gate }
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate krb5_context telnet_context = 0;
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate /* ARGSUSED */
1810Sstevel@tonic-gate int
kerberos5_init(Authenticator * ap)1820Sstevel@tonic-gate kerberos5_init(Authenticator *ap)
1830Sstevel@tonic-gate {
1840Sstevel@tonic-gate krb5_error_code retval;
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate str_data[3] = TELQUAL_IS;
1870Sstevel@tonic-gate if (krb5auth_flag && (telnet_context == 0)) {
1880Sstevel@tonic-gate retval = krb5_init_context(&telnet_context);
1890Sstevel@tonic-gate if (retval)
1900Sstevel@tonic-gate return (0);
1910Sstevel@tonic-gate }
1920Sstevel@tonic-gate return (1);
1930Sstevel@tonic-gate }
1940Sstevel@tonic-gate
1950Sstevel@tonic-gate int
kerberos5_send(Authenticator * ap)1960Sstevel@tonic-gate kerberos5_send(Authenticator *ap)
1970Sstevel@tonic-gate {
1980Sstevel@tonic-gate krb5_error_code retval;
1990Sstevel@tonic-gate krb5_ccache ccache;
2000Sstevel@tonic-gate krb5_creds creds; /* telnet gets session key from here */
2010Sstevel@tonic-gate krb5_creds *new_creds = 0;
2020Sstevel@tonic-gate int ap_opts;
2030Sstevel@tonic-gate char type_check[2];
2040Sstevel@tonic-gate krb5_data check_data;
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate krb5_keyblock *newkey = 0;
2070Sstevel@tonic-gate
2081347Smp153739 int i;
2091347Smp153739 krb5_enctype *ktypes;
2101347Smp153739
2110Sstevel@tonic-gate if (!UserNameRequested) {
2120Sstevel@tonic-gate if (auth_debug_mode)
2130Sstevel@tonic-gate (void) printf(gettext("telnet: Kerberos V5: "
2140Sstevel@tonic-gate "no user name supplied\r\n"));
2150Sstevel@tonic-gate return (0);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate if ((retval = krb5_cc_default(telnet_context, &ccache))) {
2190Sstevel@tonic-gate if (auth_debug_mode)
2200Sstevel@tonic-gate (void) printf(gettext("telnet: Kerberos V5: "
2210Sstevel@tonic-gate "could not get default ccache\r\n"));
2220Sstevel@tonic-gate return (0);
2230Sstevel@tonic-gate }
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate (void) memset((char *)&creds, 0, sizeof (creds));
226*4807Smp153739 if (auth_debug_mode)
227*4807Smp153739 printf("telnet: calling krb5_sname_to_principal\n");
2280Sstevel@tonic-gate if ((retval = krb5_sname_to_principal(telnet_context, RemoteHostName,
2290Sstevel@tonic-gate "host", KRB5_NT_SRV_HST, &creds.server))) {
2300Sstevel@tonic-gate if (auth_debug_mode)
2310Sstevel@tonic-gate (void) printf(gettext("telnet: Kerberos V5: error "
2320Sstevel@tonic-gate "while constructing service name: %s\r\n"),
2330Sstevel@tonic-gate error_message(retval));
2340Sstevel@tonic-gate return (0);
2350Sstevel@tonic-gate }
236*4807Smp153739 if (auth_debug_mode)
237*4807Smp153739 printf("telnet: done calling krb5_sname_to_principal\n");
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate if (telnet_krb5_realm != NULL) {
2400Sstevel@tonic-gate krb5_data rdata;
2410Sstevel@tonic-gate
242*4807Smp153739 rdata.magic = 0;
2430Sstevel@tonic-gate rdata.length = strlen(telnet_krb5_realm);
2440Sstevel@tonic-gate rdata.data = (char *)malloc(rdata.length + 1);
2450Sstevel@tonic-gate if (rdata.data == NULL) {
2460Sstevel@tonic-gate (void) fprintf(stderr, gettext("malloc failed\n"));
2470Sstevel@tonic-gate return (0);
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate (void) strcpy(rdata.data, telnet_krb5_realm);
2500Sstevel@tonic-gate krb5_princ_set_realm(telnet_context, creds.server, &rdata);
2510Sstevel@tonic-gate if (auth_debug_mode)
2520Sstevel@tonic-gate (void) printf(gettext(
2530Sstevel@tonic-gate "telnet: Kerberos V5: set kerberos realm to %s\r\n"),
2540Sstevel@tonic-gate telnet_krb5_realm);
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate if ((retval = krb5_cc_get_principal(telnet_context, ccache,
2580Sstevel@tonic-gate &creds.client)) != NULL) {
2590Sstevel@tonic-gate if (auth_debug_mode) {
2600Sstevel@tonic-gate (void) printf(gettext(
2610Sstevel@tonic-gate "telnet: Kerberos V5: failure on principal "
2620Sstevel@tonic-gate "(%s)\r\n"), error_message(retval));
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate krb5_free_cred_contents(telnet_context, &creds);
2650Sstevel@tonic-gate return (0);
2660Sstevel@tonic-gate }
2671347Smp153739 /*
2681347Smp153739 * Check to to confirm that at least one of the supported
2691347Smp153739 * encryption types (des-cbc-md5, des-cbc-crc is available. If
2701347Smp153739 * one is available then use it to obtain credentials.
2711347Smp153739 */
2720Sstevel@tonic-gate
2731347Smp153739 if ((retval = krb5_get_tgs_ktypes(telnet_context, creds.server,
2741347Smp153739 &ktypes))) {
2751347Smp153739 if (auth_debug_mode) {
2761347Smp153739 (void) printf(gettext(
2771347Smp153739 "telnet: Kerberos V5: could not determine "
2781347Smp153739 "TGS encryption types "
2791347Smp153739 "(see default_tgs_enctypes in krb5.conf) "
2801347Smp153739 "(%s)\r\n"), error_message(retval));
2811347Smp153739 }
2821347Smp153739 krb5_free_cred_contents(telnet_context, &creds);
2831347Smp153739 return (0);
2841347Smp153739 }
2851347Smp153739
2861347Smp153739 for (i = 0; ktypes[i]; i++) {
2871347Smp153739 if (ACCEPTED_ENCTYPE(ktypes[i]))
2881347Smp153739 break;
2891347Smp153739 }
2901347Smp153739
2911347Smp153739 if (ktypes[i] == 0) {
2921347Smp153739 if (auth_debug_mode) {
2931347Smp153739 (void) printf(gettext(
2941347Smp153739 "telnet: Kerberos V5: "
2951347Smp153739 "failure on encryption types. "
2961347Smp153739 "Cannot find des-cbc-md5 or des-cbc-crc "
2971347Smp153739 "in list of TGS encryption types "
2981347Smp153739 "(see default_tgs_enctypes in krb5.conf)\n"));
2991347Smp153739 }
3001347Smp153739 krb5_free_cred_contents(telnet_context, &creds);
3011347Smp153739 return (0);
3021347Smp153739 }
3031347Smp153739
3041347Smp153739 creds.keyblock.enctype = ktypes[i];
3050Sstevel@tonic-gate if ((retval = krb5_get_credentials(telnet_context, 0,
3060Sstevel@tonic-gate ccache, &creds, &new_creds))) {
3070Sstevel@tonic-gate if (auth_debug_mode) {
3080Sstevel@tonic-gate (void) printf(gettext(
3090Sstevel@tonic-gate "telnet: Kerberos V5: failure on credentials "
3100Sstevel@tonic-gate "(%s)\r\n"), error_message(retval));
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate krb5_free_cred_contents(telnet_context, &creds);
3130Sstevel@tonic-gate return (0);
3140Sstevel@tonic-gate }
3150Sstevel@tonic-gate
3160Sstevel@tonic-gate ap_opts = ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
3170Sstevel@tonic-gate AP_OPTS_MUTUAL_REQUIRED : 0;
3180Sstevel@tonic-gate
3190Sstevel@tonic-gate ap_opts |= AP_OPTS_USE_SUBKEY;
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate if (auth_context) {
3220Sstevel@tonic-gate krb5_auth_con_free(telnet_context, auth_context);
3230Sstevel@tonic-gate auth_context = 0;
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate if ((retval = krb5_auth_con_init(telnet_context, &auth_context))) {
3260Sstevel@tonic-gate if (auth_debug_mode) {
3270Sstevel@tonic-gate (void) printf(gettext(
3280Sstevel@tonic-gate "Kerberos V5: failed to init auth_context "
3290Sstevel@tonic-gate "(%s)\r\n"), error_message(retval));
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate return (0);
3320Sstevel@tonic-gate }
3330Sstevel@tonic-gate
3340Sstevel@tonic-gate krb5_auth_con_setflags(telnet_context, auth_context,
3350Sstevel@tonic-gate KRB5_AUTH_CONTEXT_RET_TIME);
3360Sstevel@tonic-gate
3370Sstevel@tonic-gate type_check[0] = ap->type;
3380Sstevel@tonic-gate type_check[1] = ap->way;
3390Sstevel@tonic-gate check_data.magic = KV5M_DATA;
3400Sstevel@tonic-gate check_data.length = 2;
3410Sstevel@tonic-gate check_data.data = (char *)&type_check;
3420Sstevel@tonic-gate
3430Sstevel@tonic-gate retval = krb5_mk_req_extended(telnet_context, &auth_context, ap_opts,
3440Sstevel@tonic-gate &check_data, new_creds, &auth);
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate krb5_auth_con_getlocalsubkey(telnet_context, auth_context, &newkey);
3470Sstevel@tonic-gate if (session_key) {
3480Sstevel@tonic-gate krb5_free_keyblock(telnet_context, session_key);
3490Sstevel@tonic-gate session_key = 0;
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate
3520Sstevel@tonic-gate if (newkey) {
3530Sstevel@tonic-gate /*
3540Sstevel@tonic-gate * keep the key in our private storage, but don't use it
3550Sstevel@tonic-gate * yet---see kerberos5_reply() below
3560Sstevel@tonic-gate */
3571347Smp153739 if (!(ACCEPTED_ENCTYPE(newkey->enctype))) {
3581347Smp153739 if (!(ACCEPTED_ENCTYPE(new_creds->keyblock.enctype)))
3590Sstevel@tonic-gate /* use the session key in credentials instead */
3600Sstevel@tonic-gate krb5_copy_keyblock(telnet_context,
3610Sstevel@tonic-gate &new_creds->keyblock, &session_key);
3620Sstevel@tonic-gate } else
3630Sstevel@tonic-gate krb5_copy_keyblock(telnet_context,
3640Sstevel@tonic-gate newkey, &session_key);
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate krb5_free_keyblock(telnet_context, newkey);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate krb5_free_cred_contents(telnet_context, &creds);
3700Sstevel@tonic-gate krb5_free_creds(telnet_context, new_creds);
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate if (retval) {
3730Sstevel@tonic-gate if (auth_debug_mode)
3740Sstevel@tonic-gate (void) printf(gettext(
3750Sstevel@tonic-gate "telnet: Kerberos V5: mk_req failed (%s)\r\n"),
3760Sstevel@tonic-gate error_message(retval));
3770Sstevel@tonic-gate return (0);
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate if ((auth_sendname((uchar_t *)UserNameRequested,
3810Sstevel@tonic-gate strlen(UserNameRequested))) == NULL) {
3820Sstevel@tonic-gate if (auth_debug_mode)
3830Sstevel@tonic-gate (void) printf(gettext(
3840Sstevel@tonic-gate "telnet: Not enough room for user name\r\n"));
3850Sstevel@tonic-gate return (0);
3860Sstevel@tonic-gate }
3870Sstevel@tonic-gate retval = krb5_send_data(ap, KRB_AUTH, auth.data, auth.length);
3880Sstevel@tonic-gate if (auth_debug_mode && retval) {
3890Sstevel@tonic-gate (void) printf(gettext(
3900Sstevel@tonic-gate "telnet: Sent Kerberos V5 credentials to server\r\n"));
3910Sstevel@tonic-gate } else if (auth_debug_mode) {
3920Sstevel@tonic-gate (void) printf(gettext(
3930Sstevel@tonic-gate "telnet: Not enough room for authentication data\r\n"));
3940Sstevel@tonic-gate return (0);
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate return (1);
3970Sstevel@tonic-gate }
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate void
kerberos5_reply(Authenticator * ap,unsigned char * data,int cnt)4000Sstevel@tonic-gate kerberos5_reply(Authenticator *ap, unsigned char *data, int cnt)
4010Sstevel@tonic-gate {
4020Sstevel@tonic-gate Session_Key skey;
4030Sstevel@tonic-gate static boolean_t mutual_complete = B_FALSE;
4040Sstevel@tonic-gate
4050Sstevel@tonic-gate if (cnt-- < 1)
4060Sstevel@tonic-gate return;
4070Sstevel@tonic-gate switch (*data++) {
4080Sstevel@tonic-gate case KRB_REJECT:
4090Sstevel@tonic-gate if (cnt > 0)
4100Sstevel@tonic-gate (void) printf(gettext(
4110Sstevel@tonic-gate "[ Kerberos V5 refuses authentication because "
4120Sstevel@tonic-gate "%.*s ]\r\n"), cnt, data);
4130Sstevel@tonic-gate else
4140Sstevel@tonic-gate (void) printf(gettext(
4150Sstevel@tonic-gate "[ Kerberos V5 refuses authentication ]\r\n"));
4160Sstevel@tonic-gate auth_send_retry();
4170Sstevel@tonic-gate return;
4180Sstevel@tonic-gate case KRB_ACCEPT:
4190Sstevel@tonic-gate if (!mutual_complete) {
4200Sstevel@tonic-gate if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
4210Sstevel@tonic-gate (void) printf(gettext(
4220Sstevel@tonic-gate "[ Kerberos V5 accepted you, but didn't "
4230Sstevel@tonic-gate "provide mutual authentication! ]\r\n"));
4240Sstevel@tonic-gate auth_send_retry();
4250Sstevel@tonic-gate return;
4260Sstevel@tonic-gate }
4270Sstevel@tonic-gate
4280Sstevel@tonic-gate if (session_key) {
4290Sstevel@tonic-gate skey.type = SK_DES;
4300Sstevel@tonic-gate skey.length = 8;
4310Sstevel@tonic-gate skey.data = session_key->contents;
4320Sstevel@tonic-gate encrypt_session_key(&skey);
4330Sstevel@tonic-gate }
4340Sstevel@tonic-gate }
4350Sstevel@tonic-gate if (cnt)
4360Sstevel@tonic-gate (void) printf(gettext(
4370Sstevel@tonic-gate "[ Kerberos V5 accepts you as ``%.*s'' ]\r\n"),
4380Sstevel@tonic-gate cnt, data);
4390Sstevel@tonic-gate else
4400Sstevel@tonic-gate (void) printf(gettext(
4410Sstevel@tonic-gate "[ Kerberos V5 accepts you ]\r\n"));
4420Sstevel@tonic-gate auth_finished(ap, AUTH_USER);
4430Sstevel@tonic-gate
4440Sstevel@tonic-gate if (forward_flags & OPTS_FORWARD_CREDS)
4450Sstevel@tonic-gate kerberos5_forward(ap);
4460Sstevel@tonic-gate
4470Sstevel@tonic-gate break;
4480Sstevel@tonic-gate case KRB_RESPONSE:
4490Sstevel@tonic-gate if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
4500Sstevel@tonic-gate /* the rest of the reply should contain a krb_ap_rep */
4510Sstevel@tonic-gate krb5_ap_rep_enc_part *reply;
4520Sstevel@tonic-gate krb5_data inbuf;
4530Sstevel@tonic-gate krb5_error_code retval;
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate inbuf.length = cnt;
4560Sstevel@tonic-gate inbuf.data = (char *)data;
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate retval = krb5_rd_rep(telnet_context, auth_context,
4590Sstevel@tonic-gate &inbuf, &reply);
4600Sstevel@tonic-gate if (retval) {
4610Sstevel@tonic-gate (void) printf(gettext(
4620Sstevel@tonic-gate "[ Mutual authentication failed: "
4630Sstevel@tonic-gate "%s ]\r\n"), error_message(retval));
4640Sstevel@tonic-gate auth_send_retry();
4650Sstevel@tonic-gate return;
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate krb5_free_ap_rep_enc_part(telnet_context, reply);
4680Sstevel@tonic-gate
4690Sstevel@tonic-gate if (session_key) {
4700Sstevel@tonic-gate skey.type = SK_DES;
4710Sstevel@tonic-gate skey.length = 8;
4720Sstevel@tonic-gate skey.data = session_key->contents;
4730Sstevel@tonic-gate encrypt_session_key(&skey);
4740Sstevel@tonic-gate }
4750Sstevel@tonic-gate mutual_complete = B_TRUE;
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate return;
4780Sstevel@tonic-gate case KRB_FORWARD_ACCEPT:
4790Sstevel@tonic-gate (void) printf(gettext(
4800Sstevel@tonic-gate "[ Kerberos V5 accepted forwarded credentials ]\r\n"));
4810Sstevel@tonic-gate return;
4820Sstevel@tonic-gate case KRB_FORWARD_REJECT:
4830Sstevel@tonic-gate (void) printf(gettext(
4840Sstevel@tonic-gate "[ Kerberos V5 refuses forwarded credentials because "
4850Sstevel@tonic-gate "%.*s ]\r\n"), cnt, data);
4860Sstevel@tonic-gate return;
4870Sstevel@tonic-gate default:
4880Sstevel@tonic-gate if (auth_debug_mode)
4890Sstevel@tonic-gate (void) printf(gettext(
4900Sstevel@tonic-gate "Unknown Kerberos option %d\r\n"), data[-1]);
4910Sstevel@tonic-gate return;
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate
4950Sstevel@tonic-gate /* ARGSUSED */
4960Sstevel@tonic-gate int
kerberos5_status(Authenticator * ap,char * name,int level)4970Sstevel@tonic-gate kerberos5_status(Authenticator *ap, char *name, int level)
4980Sstevel@tonic-gate {
4990Sstevel@tonic-gate if (level < AUTH_USER)
5000Sstevel@tonic-gate return (level);
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate if (UserNameRequested && krb5_kuserok(telnet_context,
5030Sstevel@tonic-gate ticket->enc_part2->client, UserNameRequested)) {
5040Sstevel@tonic-gate
5050Sstevel@tonic-gate /* the name buffer comes from telnetd/telnetd{-ktd}.c */
5060Sstevel@tonic-gate (void) strncpy(name, UserNameRequested, MAXNAMELEN);
5070Sstevel@tonic-gate name[MAXNAMELEN-1] = '\0';
5080Sstevel@tonic-gate return (AUTH_VALID);
5090Sstevel@tonic-gate } else
5100Sstevel@tonic-gate return (AUTH_USER);
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate
5130Sstevel@tonic-gate #define BUMP(buf, len) while (*(buf)) {++(buf), --(len); }
5140Sstevel@tonic-gate #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len); }
5150Sstevel@tonic-gate
5160Sstevel@tonic-gate /*
5170Sstevel@tonic-gate * Used with the set opt command to print suboptions
5180Sstevel@tonic-gate */
5190Sstevel@tonic-gate void
kerberos5_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen)5200Sstevel@tonic-gate kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
5210Sstevel@tonic-gate {
5220Sstevel@tonic-gate char lbuf[AUTH_LBUF_BUFSIZ];
5230Sstevel@tonic-gate register int i;
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate buf[buflen-1] = '\0'; /* make sure its NULL terminated */
5260Sstevel@tonic-gate buflen -= 1;
5270Sstevel@tonic-gate
5280Sstevel@tonic-gate switch (data[3]) {
5290Sstevel@tonic-gate case KRB_REJECT: /* Rejected (reason might follow) */
5300Sstevel@tonic-gate (void) strncpy((char *)buf, " REJECT ", buflen);
5310Sstevel@tonic-gate goto common;
5320Sstevel@tonic-gate
5330Sstevel@tonic-gate case KRB_ACCEPT: /* Accepted (name might follow) */
5340Sstevel@tonic-gate (void) strncpy((char *)buf, " ACCEPT ", buflen);
5350Sstevel@tonic-gate common:
5360Sstevel@tonic-gate BUMP(buf, buflen);
5370Sstevel@tonic-gate if (cnt <= 4)
5380Sstevel@tonic-gate break;
5390Sstevel@tonic-gate ADDC(buf, buflen, '"');
5400Sstevel@tonic-gate for (i = 4; i < cnt; i++)
5410Sstevel@tonic-gate ADDC(buf, buflen, data[i]);
5420Sstevel@tonic-gate ADDC(buf, buflen, '"');
5430Sstevel@tonic-gate ADDC(buf, buflen, '\0');
5440Sstevel@tonic-gate break;
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate case KRB_AUTH: /* Authentication data follows */
5470Sstevel@tonic-gate (void) strncpy((char *)buf, " AUTH", buflen);
5480Sstevel@tonic-gate goto common2;
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate case KRB_RESPONSE:
5510Sstevel@tonic-gate (void) strncpy((char *)buf, " RESPONSE", buflen);
5520Sstevel@tonic-gate goto common2;
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate case KRB_FORWARD: /* Forwarded credentials follow */
5550Sstevel@tonic-gate (void) strncpy((char *)buf, " FORWARD", buflen);
5560Sstevel@tonic-gate goto common2;
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */
5590Sstevel@tonic-gate (void) strncpy((char *)buf, " FORWARD_ACCEPT", buflen);
5600Sstevel@tonic-gate goto common2;
5610Sstevel@tonic-gate
5620Sstevel@tonic-gate case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */
5630Sstevel@tonic-gate /* (reason might follow) */
5640Sstevel@tonic-gate (void) strncpy((char *)buf, " FORWARD_REJECT", buflen);
5650Sstevel@tonic-gate goto common2;
5660Sstevel@tonic-gate
5670Sstevel@tonic-gate default:
5680Sstevel@tonic-gate (void) snprintf(lbuf, AUTH_LBUF_BUFSIZ,
5690Sstevel@tonic-gate gettext(" %d (unknown)"),
5700Sstevel@tonic-gate data[3]);
5710Sstevel@tonic-gate (void) strncpy((char *)buf, lbuf, buflen);
5720Sstevel@tonic-gate common2:
5730Sstevel@tonic-gate BUMP(buf, buflen);
5740Sstevel@tonic-gate for (i = 4; i < cnt; i++) {
5750Sstevel@tonic-gate (void) snprintf(lbuf, AUTH_LBUF_BUFSIZ, " %d", data[i]);
5760Sstevel@tonic-gate (void) strncpy((char *)buf, lbuf, buflen);
5770Sstevel@tonic-gate BUMP(buf, buflen);
5780Sstevel@tonic-gate }
5790Sstevel@tonic-gate break;
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate
5830Sstevel@tonic-gate void
krb5_profile_get_options(char * host,char * realm,profile_options_boolean * optionsp)5840Sstevel@tonic-gate krb5_profile_get_options(char *host, char *realm,
5850Sstevel@tonic-gate profile_options_boolean *optionsp)
5860Sstevel@tonic-gate {
5870Sstevel@tonic-gate char **realms = NULL;
5880Sstevel@tonic-gate krb5_error_code err = 0;
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate if (!telnet_context) {
5910Sstevel@tonic-gate err = krb5_init_context(&telnet_context);
5920Sstevel@tonic-gate if (err) {
5930Sstevel@tonic-gate (void) fprintf(stderr, gettext(
5940Sstevel@tonic-gate "Error initializing Kerberos 5 library: %s\n"),
5950Sstevel@tonic-gate error_message(err));
5960Sstevel@tonic-gate return;
5970Sstevel@tonic-gate }
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate
6000Sstevel@tonic-gate if ((realmdef[1] = realm) == NULL) {
6010Sstevel@tonic-gate err = krb5_get_host_realm(telnet_context, host, &realms);
6020Sstevel@tonic-gate if (err) {
6030Sstevel@tonic-gate (void) fprintf(stderr, gettext(
6040Sstevel@tonic-gate "Error getting Kerberos 5 realms for: %s (%s)\n"),
6050Sstevel@tonic-gate host, error_message(err));
6060Sstevel@tonic-gate return;
6070Sstevel@tonic-gate }
6080Sstevel@tonic-gate realmdef[1] = realms[0];
6090Sstevel@tonic-gate }
6100Sstevel@tonic-gate
6110Sstevel@tonic-gate profile_get_options_boolean(telnet_context->profile,
6120Sstevel@tonic-gate realmdef, optionsp);
6130Sstevel@tonic-gate profile_get_options_boolean(telnet_context->profile,
6140Sstevel@tonic-gate appdef, optionsp);
6150Sstevel@tonic-gate }
6160Sstevel@tonic-gate
6170Sstevel@tonic-gate static void
kerberos5_forward(Authenticator * ap)6180Sstevel@tonic-gate kerberos5_forward(Authenticator *ap)
6190Sstevel@tonic-gate {
6200Sstevel@tonic-gate krb5_error_code retval;
6210Sstevel@tonic-gate krb5_ccache ccache;
6220Sstevel@tonic-gate krb5_principal client = 0;
6230Sstevel@tonic-gate krb5_principal server = 0;
6240Sstevel@tonic-gate krb5_data forw_creds;
6250Sstevel@tonic-gate
6260Sstevel@tonic-gate forw_creds.data = 0;
6270Sstevel@tonic-gate
6280Sstevel@tonic-gate if ((retval = krb5_cc_default(telnet_context, &ccache))) {
6290Sstevel@tonic-gate if (auth_debug_mode)
6300Sstevel@tonic-gate (void) printf(gettext(
6310Sstevel@tonic-gate "Kerberos V5: could not get default ccache - %s\r\n"),
6320Sstevel@tonic-gate error_message(retval));
6330Sstevel@tonic-gate return;
6340Sstevel@tonic-gate }
6350Sstevel@tonic-gate
6360Sstevel@tonic-gate retval = krb5_cc_get_principal(telnet_context, ccache, &client);
6370Sstevel@tonic-gate if (retval) {
6380Sstevel@tonic-gate if (auth_debug_mode)
6390Sstevel@tonic-gate (void) printf(gettext(
6400Sstevel@tonic-gate "Kerberos V5: could not get default "
6410Sstevel@tonic-gate "principal - %s\r\n"), error_message(retval));
6420Sstevel@tonic-gate goto cleanup;
6430Sstevel@tonic-gate }
6440Sstevel@tonic-gate
6450Sstevel@tonic-gate retval = krb5_sname_to_principal(telnet_context, RemoteHostName,
6460Sstevel@tonic-gate "host", KRB5_NT_SRV_HST, &server);
6470Sstevel@tonic-gate if (retval) {
6480Sstevel@tonic-gate if (auth_debug_mode)
6490Sstevel@tonic-gate (void) printf(gettext(
6500Sstevel@tonic-gate "Kerberos V5: could not make server "
6510Sstevel@tonic-gate "principal - %s\r\n"), error_message(retval));
6520Sstevel@tonic-gate goto cleanup;
6530Sstevel@tonic-gate }
6540Sstevel@tonic-gate
6550Sstevel@tonic-gate retval = krb5_auth_con_genaddrs(telnet_context, auth_context, net,
6560Sstevel@tonic-gate KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
6570Sstevel@tonic-gate if (retval) {
6580Sstevel@tonic-gate if (auth_debug_mode)
6590Sstevel@tonic-gate (void) printf(gettext(
6600Sstevel@tonic-gate "Kerberos V5: could not gen local full "
6610Sstevel@tonic-gate "address - %s\r\n"), error_message(retval));
6620Sstevel@tonic-gate goto cleanup;
6630Sstevel@tonic-gate }
6640Sstevel@tonic-gate
6650Sstevel@tonic-gate retval = krb5_fwd_tgt_creds(telnet_context, auth_context, 0, client,
6660Sstevel@tonic-gate server, ccache, forward_flags & OPTS_FORWARDABLE_CREDS,
6670Sstevel@tonic-gate &forw_creds);
6680Sstevel@tonic-gate if (retval) {
6690Sstevel@tonic-gate if (auth_debug_mode)
6700Sstevel@tonic-gate (void) printf(gettext(
6710Sstevel@tonic-gate "Kerberos V5: error getting forwarded "
6720Sstevel@tonic-gate "creds - %s\r\n"), error_message(retval));
6730Sstevel@tonic-gate goto cleanup;
6740Sstevel@tonic-gate }
6750Sstevel@tonic-gate
6760Sstevel@tonic-gate /* Send forwarded credentials */
6770Sstevel@tonic-gate if (!krb5_send_data(ap, KRB_FORWARD, forw_creds.data,
6780Sstevel@tonic-gate forw_creds.length)) {
6790Sstevel@tonic-gate if (auth_debug_mode)
6800Sstevel@tonic-gate (void) printf(gettext(
6810Sstevel@tonic-gate "Not enough room for authentication data\r\n"));
6820Sstevel@tonic-gate } else if (auth_debug_mode)
6830Sstevel@tonic-gate (void) printf(gettext(
6840Sstevel@tonic-gate "Forwarded local Kerberos V5 credentials to server\r\n"));
6850Sstevel@tonic-gate cleanup:
6860Sstevel@tonic-gate if (client)
6870Sstevel@tonic-gate krb5_free_principal(telnet_context, client);
6880Sstevel@tonic-gate if (server)
6890Sstevel@tonic-gate krb5_free_principal(telnet_context, server);
6900Sstevel@tonic-gate if (forw_creds.data)
6910Sstevel@tonic-gate free(forw_creds.data);
6920Sstevel@tonic-gate /* LINTED */
6930Sstevel@tonic-gate krb5_cc_close(telnet_context, ccache);
6940Sstevel@tonic-gate }
695