1*7348b5c5SDavid van Moolenbroek /* $NetBSD: kerberos5.c,v 1.20 2014/04/26 22:10:40 joerg Exp $ */
2*7348b5c5SDavid van Moolenbroek
3*7348b5c5SDavid van Moolenbroek /*-
4*7348b5c5SDavid van Moolenbroek * Copyright (c) 1991, 1993
5*7348b5c5SDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
6*7348b5c5SDavid van Moolenbroek *
7*7348b5c5SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
8*7348b5c5SDavid van Moolenbroek * modification, are permitted provided that the following conditions
9*7348b5c5SDavid van Moolenbroek * are met:
10*7348b5c5SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
11*7348b5c5SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
12*7348b5c5SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
13*7348b5c5SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
14*7348b5c5SDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
15*7348b5c5SDavid van Moolenbroek * 3. Neither the name of the University nor the names of its contributors
16*7348b5c5SDavid van Moolenbroek * may be used to endorse or promote products derived from this software
17*7348b5c5SDavid van Moolenbroek * without specific prior written permission.
18*7348b5c5SDavid van Moolenbroek *
19*7348b5c5SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*7348b5c5SDavid van Moolenbroek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*7348b5c5SDavid van Moolenbroek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*7348b5c5SDavid van Moolenbroek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*7348b5c5SDavid van Moolenbroek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*7348b5c5SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*7348b5c5SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*7348b5c5SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*7348b5c5SDavid van Moolenbroek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*7348b5c5SDavid van Moolenbroek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*7348b5c5SDavid van Moolenbroek * SUCH DAMAGE.
30*7348b5c5SDavid van Moolenbroek */
31*7348b5c5SDavid van Moolenbroek
32*7348b5c5SDavid van Moolenbroek /*
33*7348b5c5SDavid van Moolenbroek * Copyright (C) 1990 by the Massachusetts Institute of Technology
34*7348b5c5SDavid van Moolenbroek *
35*7348b5c5SDavid van Moolenbroek * Export of this software from the United States of America may
36*7348b5c5SDavid van Moolenbroek * require a specific license from the United States Government.
37*7348b5c5SDavid van Moolenbroek * It is the responsibility of any person or organization contemplating
38*7348b5c5SDavid van Moolenbroek * export to obtain such a license before exporting.
39*7348b5c5SDavid van Moolenbroek *
40*7348b5c5SDavid van Moolenbroek * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
41*7348b5c5SDavid van Moolenbroek * distribute this software and its documentation for any purpose and
42*7348b5c5SDavid van Moolenbroek * without fee is hereby granted, provided that the above copyright
43*7348b5c5SDavid van Moolenbroek * notice appear in all copies and that both that copyright notice and
44*7348b5c5SDavid van Moolenbroek * this permission notice appear in supporting documentation, and that
45*7348b5c5SDavid van Moolenbroek * the name of M.I.T. not be used in advertising or publicity pertaining
46*7348b5c5SDavid van Moolenbroek * to distribution of the software without specific, written prior
47*7348b5c5SDavid van Moolenbroek * permission. M.I.T. makes no representations about the suitability of
48*7348b5c5SDavid van Moolenbroek * this software for any purpose. It is provided "as is" without express
49*7348b5c5SDavid van Moolenbroek * or implied warranty.
50*7348b5c5SDavid van Moolenbroek */
51*7348b5c5SDavid van Moolenbroek
52*7348b5c5SDavid van Moolenbroek #ifdef KRB5
53*7348b5c5SDavid van Moolenbroek #include <arpa/telnet.h>
54*7348b5c5SDavid van Moolenbroek #include <stdio.h>
55*7348b5c5SDavid van Moolenbroek #include <stdlib.h>
56*7348b5c5SDavid van Moolenbroek #include <string.h>
57*7348b5c5SDavid van Moolenbroek #include <unistd.h>
58*7348b5c5SDavid van Moolenbroek #include <netdb.h>
59*7348b5c5SDavid van Moolenbroek #include <ctype.h>
60*7348b5c5SDavid van Moolenbroek #include <pwd.h>
61*7348b5c5SDavid van Moolenbroek #define Authenticator k5_Authenticator
62*7348b5c5SDavid van Moolenbroek #include <krb5.h>
63*7348b5c5SDavid van Moolenbroek #undef Authenticator
64*7348b5c5SDavid van Moolenbroek /* #include <roken.h> */
65*7348b5c5SDavid van Moolenbroek
66*7348b5c5SDavid van Moolenbroek #include "encrypt.h"
67*7348b5c5SDavid van Moolenbroek #include "auth.h"
68*7348b5c5SDavid van Moolenbroek #include "misc.h"
69*7348b5c5SDavid van Moolenbroek
70*7348b5c5SDavid van Moolenbroek extern int net;
71*7348b5c5SDavid van Moolenbroek
72*7348b5c5SDavid van Moolenbroek int forward_flags; /* Flags get set in telnet/main.c on -f and -F */
73*7348b5c5SDavid van Moolenbroek int got_forwarded_creds;/* Tell telnetd to pass -F or -f to login. */
74*7348b5c5SDavid van Moolenbroek
75*7348b5c5SDavid van Moolenbroek int require_hwpreauth;
76*7348b5c5SDavid van Moolenbroek
77*7348b5c5SDavid van Moolenbroek const char *get_krb5_err_text(krb5_context, krb5_error_code);
78*7348b5c5SDavid van Moolenbroek void kerberos5_forward(Authenticator *);
79*7348b5c5SDavid van Moolenbroek
80*7348b5c5SDavid van Moolenbroek static unsigned char str_data[1024] = {IAC, SB, TELOPT_AUTHENTICATION, 0,
81*7348b5c5SDavid van Moolenbroek AUTHTYPE_KERBEROS_V5,};
82*7348b5c5SDavid van Moolenbroek
83*7348b5c5SDavid van Moolenbroek #define KRB_AUTH 0 /* Authentication data follows */
84*7348b5c5SDavid van Moolenbroek #define KRB_REJECT 1 /* Rejected (reason might follow) */
85*7348b5c5SDavid van Moolenbroek #define KRB_ACCEPT 2 /* Accepted */
86*7348b5c5SDavid van Moolenbroek #define KRB_RESPONSE 3 /* Response for mutual auth. */
87*7348b5c5SDavid van Moolenbroek
88*7348b5c5SDavid van Moolenbroek #define KRB_FORWARD 4 /* Forwarded credentials follow */
89*7348b5c5SDavid van Moolenbroek #define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */
90*7348b5c5SDavid van Moolenbroek #define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */
91*7348b5c5SDavid van Moolenbroek
92*7348b5c5SDavid van Moolenbroek static krb5_data auth;
93*7348b5c5SDavid van Moolenbroek static krb5_ticket *ticket;
94*7348b5c5SDavid van Moolenbroek
95*7348b5c5SDavid van Moolenbroek krb5_context telnet_context;
96*7348b5c5SDavid van Moolenbroek static krb5_auth_context auth_context;
97*7348b5c5SDavid van Moolenbroek
98*7348b5c5SDavid van Moolenbroek static int
Data(Authenticator * ap,int type,const void * d,int c)99*7348b5c5SDavid van Moolenbroek Data(Authenticator *ap, int type, const void *d, int c)
100*7348b5c5SDavid van Moolenbroek {
101*7348b5c5SDavid van Moolenbroek unsigned char *p = str_data + 4;
102*7348b5c5SDavid van Moolenbroek const unsigned char *cd = (const unsigned char *) d;
103*7348b5c5SDavid van Moolenbroek
104*7348b5c5SDavid van Moolenbroek if (c == -1)
105*7348b5c5SDavid van Moolenbroek c = strlen(cd);
106*7348b5c5SDavid van Moolenbroek
107*7348b5c5SDavid van Moolenbroek if (auth_debug_mode) {
108*7348b5c5SDavid van Moolenbroek printf("%s:%d: [%d] (%d)",
109*7348b5c5SDavid van Moolenbroek str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
110*7348b5c5SDavid van Moolenbroek str_data[3],
111*7348b5c5SDavid van Moolenbroek type, c);
112*7348b5c5SDavid van Moolenbroek printd(d, c);
113*7348b5c5SDavid van Moolenbroek printf("\r\n");
114*7348b5c5SDavid van Moolenbroek }
115*7348b5c5SDavid van Moolenbroek *p++ = ap->type;
116*7348b5c5SDavid van Moolenbroek *p++ = ap->way;
117*7348b5c5SDavid van Moolenbroek *p++ = type;
118*7348b5c5SDavid van Moolenbroek while (c-- > 0) {
119*7348b5c5SDavid van Moolenbroek if ((*p++ = *cd++) == IAC)
120*7348b5c5SDavid van Moolenbroek *p++ = IAC;
121*7348b5c5SDavid van Moolenbroek }
122*7348b5c5SDavid van Moolenbroek *p++ = IAC;
123*7348b5c5SDavid van Moolenbroek *p++ = SE;
124*7348b5c5SDavid van Moolenbroek if (str_data[3] == TELQUAL_IS)
125*7348b5c5SDavid van Moolenbroek printsub('>', &str_data[2], p - &str_data[2]);
126*7348b5c5SDavid van Moolenbroek return (telnet_net_write(str_data, p - str_data));
127*7348b5c5SDavid van Moolenbroek }
128*7348b5c5SDavid van Moolenbroek
129*7348b5c5SDavid van Moolenbroek const char *
get_krb5_err_text(krb5_context ctx,krb5_error_code ret)130*7348b5c5SDavid van Moolenbroek get_krb5_err_text(krb5_context ctx, krb5_error_code ret)
131*7348b5c5SDavid van Moolenbroek {
132*7348b5c5SDavid van Moolenbroek static const char *str = NULL;
133*7348b5c5SDavid van Moolenbroek
134*7348b5c5SDavid van Moolenbroek if (str)
135*7348b5c5SDavid van Moolenbroek krb5_free_error_message(ctx, str);
136*7348b5c5SDavid van Moolenbroek
137*7348b5c5SDavid van Moolenbroek str = krb5_get_error_message(ctx, ret);
138*7348b5c5SDavid van Moolenbroek
139*7348b5c5SDavid van Moolenbroek if (str != NULL)
140*7348b5c5SDavid van Moolenbroek return str;
141*7348b5c5SDavid van Moolenbroek
142*7348b5c5SDavid van Moolenbroek return "unknown";
143*7348b5c5SDavid van Moolenbroek }
144*7348b5c5SDavid van Moolenbroek
145*7348b5c5SDavid van Moolenbroek int
kerberos5_init(Authenticator * ap,int server)146*7348b5c5SDavid van Moolenbroek kerberos5_init(Authenticator *ap, int server)
147*7348b5c5SDavid van Moolenbroek {
148*7348b5c5SDavid van Moolenbroek krb5_error_code ret;
149*7348b5c5SDavid van Moolenbroek
150*7348b5c5SDavid van Moolenbroek if (telnet_context == 0) {
151*7348b5c5SDavid van Moolenbroek ret = krb5_init_context(&telnet_context);
152*7348b5c5SDavid van Moolenbroek if (ret)
153*7348b5c5SDavid van Moolenbroek return 0;
154*7348b5c5SDavid van Moolenbroek }
155*7348b5c5SDavid van Moolenbroek
156*7348b5c5SDavid van Moolenbroek if (server) {
157*7348b5c5SDavid van Moolenbroek krb5_keytab kt;
158*7348b5c5SDavid van Moolenbroek krb5_kt_cursor cursor;
159*7348b5c5SDavid van Moolenbroek
160*7348b5c5SDavid van Moolenbroek ret = krb5_kt_default(telnet_context, &kt);
161*7348b5c5SDavid van Moolenbroek if (ret)
162*7348b5c5SDavid van Moolenbroek return 0;
163*7348b5c5SDavid van Moolenbroek
164*7348b5c5SDavid van Moolenbroek ret = krb5_kt_start_seq_get(telnet_context, kt, &cursor);
165*7348b5c5SDavid van Moolenbroek if (ret) {
166*7348b5c5SDavid van Moolenbroek krb5_kt_close(telnet_context, kt);
167*7348b5c5SDavid van Moolenbroek return 0;
168*7348b5c5SDavid van Moolenbroek }
169*7348b5c5SDavid van Moolenbroek krb5_kt_end_seq_get(telnet_context, kt, &cursor);
170*7348b5c5SDavid van Moolenbroek krb5_kt_close(telnet_context, kt);
171*7348b5c5SDavid van Moolenbroek
172*7348b5c5SDavid van Moolenbroek str_data[3] = TELQUAL_REPLY;
173*7348b5c5SDavid van Moolenbroek } else
174*7348b5c5SDavid van Moolenbroek str_data[3] = TELQUAL_IS;
175*7348b5c5SDavid van Moolenbroek return (1);
176*7348b5c5SDavid van Moolenbroek }
177*7348b5c5SDavid van Moolenbroek
178*7348b5c5SDavid van Moolenbroek int
kerberos5_send(Authenticator * ap)179*7348b5c5SDavid van Moolenbroek kerberos5_send(Authenticator *ap)
180*7348b5c5SDavid van Moolenbroek {
181*7348b5c5SDavid van Moolenbroek krb5_error_code ret;
182*7348b5c5SDavid van Moolenbroek krb5_ccache ccache;
183*7348b5c5SDavid van Moolenbroek int ap_opts;
184*7348b5c5SDavid van Moolenbroek krb5_data cksum_data;
185*7348b5c5SDavid van Moolenbroek char foo[2];
186*7348b5c5SDavid van Moolenbroek
187*7348b5c5SDavid van Moolenbroek printf("[ Trying KERBEROS5 ... ]\r\n");
188*7348b5c5SDavid van Moolenbroek
189*7348b5c5SDavid van Moolenbroek if (!UserNameRequested) {
190*7348b5c5SDavid van Moolenbroek if (auth_debug_mode) {
191*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: no user name supplied\r\n");
192*7348b5c5SDavid van Moolenbroek }
193*7348b5c5SDavid van Moolenbroek return (0);
194*7348b5c5SDavid van Moolenbroek }
195*7348b5c5SDavid van Moolenbroek ret = krb5_cc_default(telnet_context, &ccache);
196*7348b5c5SDavid van Moolenbroek if (ret) {
197*7348b5c5SDavid van Moolenbroek if (auth_debug_mode) {
198*7348b5c5SDavid van Moolenbroek printf(
199*7348b5c5SDavid van Moolenbroek "Kerberos V5: could not get default ccache: %s\r\n",
200*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
201*7348b5c5SDavid van Moolenbroek }
202*7348b5c5SDavid van Moolenbroek return (0);
203*7348b5c5SDavid van Moolenbroek }
204*7348b5c5SDavid van Moolenbroek if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
205*7348b5c5SDavid van Moolenbroek ap_opts = AP_OPTS_MUTUAL_REQUIRED;
206*7348b5c5SDavid van Moolenbroek else
207*7348b5c5SDavid van Moolenbroek ap_opts = 0;
208*7348b5c5SDavid van Moolenbroek
209*7348b5c5SDavid van Moolenbroek ap_opts |= AP_OPTS_USE_SUBKEY;
210*7348b5c5SDavid van Moolenbroek
211*7348b5c5SDavid van Moolenbroek ret = krb5_auth_con_init(telnet_context, &auth_context);
212*7348b5c5SDavid van Moolenbroek if (ret) {
213*7348b5c5SDavid van Moolenbroek if (auth_debug_mode) {
214*7348b5c5SDavid van Moolenbroek printf(
215*7348b5c5SDavid van Moolenbroek "Kerberos V5: krb5_auth_con_init failed: %s\r\n",
216*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
217*7348b5c5SDavid van Moolenbroek }
218*7348b5c5SDavid van Moolenbroek return (0);
219*7348b5c5SDavid van Moolenbroek }
220*7348b5c5SDavid van Moolenbroek ret = krb5_auth_con_setaddrs_from_fd(telnet_context,
221*7348b5c5SDavid van Moolenbroek auth_context, &net);
222*7348b5c5SDavid van Moolenbroek if (ret) {
223*7348b5c5SDavid van Moolenbroek if (auth_debug_mode) {
224*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: "
225*7348b5c5SDavid van Moolenbroek "krb5_auth_con_setaddrs_from_fd failed: %s\r\n",
226*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
227*7348b5c5SDavid van Moolenbroek }
228*7348b5c5SDavid van Moolenbroek return (0);
229*7348b5c5SDavid van Moolenbroek }
230*7348b5c5SDavid van Moolenbroek krb5_auth_con_setkeytype(telnet_context, auth_context,
231*7348b5c5SDavid van Moolenbroek ETYPE_DES_CBC_CRC);
232*7348b5c5SDavid van Moolenbroek
233*7348b5c5SDavid van Moolenbroek foo[0] = ap->type;
234*7348b5c5SDavid van Moolenbroek foo[1] = ap->way;
235*7348b5c5SDavid van Moolenbroek
236*7348b5c5SDavid van Moolenbroek cksum_data.length = sizeof(foo);
237*7348b5c5SDavid van Moolenbroek cksum_data.data = foo;
238*7348b5c5SDavid van Moolenbroek ret = krb5_mk_req(telnet_context, &auth_context, ap_opts, "host",
239*7348b5c5SDavid van Moolenbroek RemoteHostName, &cksum_data, ccache, &auth);
240*7348b5c5SDavid van Moolenbroek if (ret) {
241*7348b5c5SDavid van Moolenbroek if (1 || auth_debug_mode) {
242*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: mk_req failed (%s)\r\n",
243*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
244*7348b5c5SDavid van Moolenbroek }
245*7348b5c5SDavid van Moolenbroek return (0);
246*7348b5c5SDavid van Moolenbroek }
247*7348b5c5SDavid van Moolenbroek
248*7348b5c5SDavid van Moolenbroek if (!auth_sendname((unsigned char *) UserNameRequested,
249*7348b5c5SDavid van Moolenbroek strlen(UserNameRequested))) {
250*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
251*7348b5c5SDavid van Moolenbroek printf("Not enough room for user name\r\n");
252*7348b5c5SDavid van Moolenbroek return (0);
253*7348b5c5SDavid van Moolenbroek }
254*7348b5c5SDavid van Moolenbroek if (!Data(ap, KRB_AUTH, auth.data, auth.length)) {
255*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
256*7348b5c5SDavid van Moolenbroek printf("Not enough room for authentication data\r\n");
257*7348b5c5SDavid van Moolenbroek return (0);
258*7348b5c5SDavid van Moolenbroek }
259*7348b5c5SDavid van Moolenbroek if (auth_debug_mode) {
260*7348b5c5SDavid van Moolenbroek printf("Sent Kerberos V5 credentials to server\r\n");
261*7348b5c5SDavid van Moolenbroek }
262*7348b5c5SDavid van Moolenbroek return (1);
263*7348b5c5SDavid van Moolenbroek }
264*7348b5c5SDavid van Moolenbroek
265*7348b5c5SDavid van Moolenbroek void
kerberos5_is(Authenticator * ap,unsigned char * data,int cnt)266*7348b5c5SDavid van Moolenbroek kerberos5_is(Authenticator * ap, unsigned char *data, int cnt)
267*7348b5c5SDavid van Moolenbroek {
268*7348b5c5SDavid van Moolenbroek krb5_error_code ret;
269*7348b5c5SDavid van Moolenbroek krb5_data outbuf;
270*7348b5c5SDavid van Moolenbroek krb5_keyblock *key_block;
271*7348b5c5SDavid van Moolenbroek char *name;
272*7348b5c5SDavid van Moolenbroek krb5_principal server;
273*7348b5c5SDavid van Moolenbroek int zero = 0;
274*7348b5c5SDavid van Moolenbroek
275*7348b5c5SDavid van Moolenbroek if (cnt-- < 1)
276*7348b5c5SDavid van Moolenbroek return;
277*7348b5c5SDavid van Moolenbroek switch (*data++) {
278*7348b5c5SDavid van Moolenbroek case KRB_AUTH:
279*7348b5c5SDavid van Moolenbroek auth.data = (char *) data;
280*7348b5c5SDavid van Moolenbroek auth.length = cnt;
281*7348b5c5SDavid van Moolenbroek
282*7348b5c5SDavid van Moolenbroek auth_context = NULL;
283*7348b5c5SDavid van Moolenbroek
284*7348b5c5SDavid van Moolenbroek ret = krb5_auth_con_init(telnet_context, &auth_context);
285*7348b5c5SDavid van Moolenbroek if (ret) {
286*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, "krb5_auth_con_init failed", -1);
287*7348b5c5SDavid van Moolenbroek auth_finished(ap, AUTH_REJECT);
288*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
289*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: krb5_auth_con_init failed (%s)\r\n",
290*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
291*7348b5c5SDavid van Moolenbroek return;
292*7348b5c5SDavid van Moolenbroek }
293*7348b5c5SDavid van Moolenbroek ret = krb5_auth_con_setaddrs_from_fd(telnet_context,
294*7348b5c5SDavid van Moolenbroek auth_context, &zero);
295*7348b5c5SDavid van Moolenbroek if (ret) {
296*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, "krb5_auth_con_setaddrs_from_fd failed", -1);
297*7348b5c5SDavid van Moolenbroek auth_finished(ap, AUTH_REJECT);
298*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
299*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: "
300*7348b5c5SDavid van Moolenbroek "krb5_auth_con_setaddrs_from_fd failed (%s)\r\n",
301*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
302*7348b5c5SDavid van Moolenbroek return;
303*7348b5c5SDavid van Moolenbroek }
304*7348b5c5SDavid van Moolenbroek ret = krb5_sock_to_principal(telnet_context, 0, "host",
305*7348b5c5SDavid van Moolenbroek KRB5_NT_SRV_HST, &server);
306*7348b5c5SDavid van Moolenbroek if (ret) {
307*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, "krb5_sock_to_principal failed", -1);
308*7348b5c5SDavid van Moolenbroek auth_finished(ap, AUTH_REJECT);
309*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
310*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: "
311*7348b5c5SDavid van Moolenbroek "krb5_sock_to_principal failed (%s)\r\n",
312*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
313*7348b5c5SDavid van Moolenbroek return;
314*7348b5c5SDavid van Moolenbroek }
315*7348b5c5SDavid van Moolenbroek ret = krb5_rd_req(telnet_context, &auth_context, &auth,
316*7348b5c5SDavid van Moolenbroek server, NULL, NULL, &ticket);
317*7348b5c5SDavid van Moolenbroek krb5_free_principal(telnet_context, server);
318*7348b5c5SDavid van Moolenbroek
319*7348b5c5SDavid van Moolenbroek if (ret) {
320*7348b5c5SDavid van Moolenbroek char *errbuf;
321*7348b5c5SDavid van Moolenbroek
322*7348b5c5SDavid van Moolenbroek asprintf(&errbuf,
323*7348b5c5SDavid van Moolenbroek "Read req failed: %s",
324*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
325*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, errbuf, -1);
326*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
327*7348b5c5SDavid van Moolenbroek printf("%s\r\n", errbuf);
328*7348b5c5SDavid van Moolenbroek free(errbuf);
329*7348b5c5SDavid van Moolenbroek return;
330*7348b5c5SDavid van Moolenbroek } {
331*7348b5c5SDavid van Moolenbroek char foo[2];
332*7348b5c5SDavid van Moolenbroek
333*7348b5c5SDavid van Moolenbroek foo[0] = ap->type;
334*7348b5c5SDavid van Moolenbroek foo[1] = ap->way;
335*7348b5c5SDavid van Moolenbroek
336*7348b5c5SDavid van Moolenbroek ret = krb5_verify_authenticator_checksum(telnet_context,
337*7348b5c5SDavid van Moolenbroek auth_context, foo, sizeof(foo));
338*7348b5c5SDavid van Moolenbroek
339*7348b5c5SDavid van Moolenbroek if (ret) {
340*7348b5c5SDavid van Moolenbroek char *errbuf;
341*7348b5c5SDavid van Moolenbroek asprintf(&errbuf, "Bad checksum: %s",
342*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
343*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, errbuf, -1);
344*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
345*7348b5c5SDavid van Moolenbroek printf("%s\r\n", errbuf);
346*7348b5c5SDavid van Moolenbroek free(errbuf);
347*7348b5c5SDavid van Moolenbroek return;
348*7348b5c5SDavid van Moolenbroek }
349*7348b5c5SDavid van Moolenbroek }
350*7348b5c5SDavid van Moolenbroek ret = krb5_auth_con_getremotesubkey(telnet_context,
351*7348b5c5SDavid van Moolenbroek auth_context, &key_block);
352*7348b5c5SDavid van Moolenbroek
353*7348b5c5SDavid van Moolenbroek if (ret) {
354*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, "krb5_auth_con_getremotesubkey failed", -1);
355*7348b5c5SDavid van Moolenbroek auth_finished(ap, AUTH_REJECT);
356*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
357*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: "
358*7348b5c5SDavid van Moolenbroek "krb5_auth_con_getremotesubkey failed (%s)\r\n",
359*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
360*7348b5c5SDavid van Moolenbroek return;
361*7348b5c5SDavid van Moolenbroek }
362*7348b5c5SDavid van Moolenbroek if (key_block == NULL) {
363*7348b5c5SDavid van Moolenbroek ret = krb5_auth_con_getkey(telnet_context,
364*7348b5c5SDavid van Moolenbroek auth_context,
365*7348b5c5SDavid van Moolenbroek &key_block);
366*7348b5c5SDavid van Moolenbroek }
367*7348b5c5SDavid van Moolenbroek if (ret) {
368*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, "krb5_auth_con_getkey failed", -1);
369*7348b5c5SDavid van Moolenbroek auth_finished(ap, AUTH_REJECT);
370*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
371*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: "
372*7348b5c5SDavid van Moolenbroek "krb5_auth_con_getkey failed (%s)\r\n",
373*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
374*7348b5c5SDavid van Moolenbroek return;
375*7348b5c5SDavid van Moolenbroek }
376*7348b5c5SDavid van Moolenbroek if (key_block == NULL) {
377*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, "no subkey received", -1);
378*7348b5c5SDavid van Moolenbroek auth_finished(ap, AUTH_REJECT);
379*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
380*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: "
381*7348b5c5SDavid van Moolenbroek "krb5_auth_con_getremotesubkey returned NULL key\r\n");
382*7348b5c5SDavid van Moolenbroek return;
383*7348b5c5SDavid van Moolenbroek }
384*7348b5c5SDavid van Moolenbroek if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
385*7348b5c5SDavid van Moolenbroek ret = krb5_mk_rep(telnet_context,
386*7348b5c5SDavid van Moolenbroek auth_context, &outbuf);
387*7348b5c5SDavid van Moolenbroek if (ret) {
388*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT,
389*7348b5c5SDavid van Moolenbroek "krb5_mk_rep failed", -1);
390*7348b5c5SDavid van Moolenbroek auth_finished(ap, AUTH_REJECT);
391*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
392*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: "
393*7348b5c5SDavid van Moolenbroek "krb5_mk_rep failed (%s)\r\n",
394*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context,
395*7348b5c5SDavid van Moolenbroek ret));
396*7348b5c5SDavid van Moolenbroek krb5_free_keyblock(telnet_context, key_block);
397*7348b5c5SDavid van Moolenbroek return;
398*7348b5c5SDavid van Moolenbroek }
399*7348b5c5SDavid van Moolenbroek Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
400*7348b5c5SDavid van Moolenbroek }
401*7348b5c5SDavid van Moolenbroek if (krb5_unparse_name(telnet_context, ticket->client, &name))
402*7348b5c5SDavid van Moolenbroek name = 0;
403*7348b5c5SDavid van Moolenbroek
404*7348b5c5SDavid van Moolenbroek if (UserNameRequested && krb5_kuserok(telnet_context,
405*7348b5c5SDavid van Moolenbroek ticket->client, UserNameRequested)) {
406*7348b5c5SDavid van Moolenbroek Data(ap, KRB_ACCEPT, name ? name : "", name ? -1 : 0);
407*7348b5c5SDavid van Moolenbroek if (auth_debug_mode) {
408*7348b5c5SDavid van Moolenbroek printf("Kerberos5 identifies him as ``%s''\r\n",
409*7348b5c5SDavid van Moolenbroek name ? name : "");
410*7348b5c5SDavid van Moolenbroek }
411*7348b5c5SDavid van Moolenbroek if (key_block->keytype == ETYPE_DES_CBC_MD5 ||
412*7348b5c5SDavid van Moolenbroek key_block->keytype == ETYPE_DES_CBC_MD4 ||
413*7348b5c5SDavid van Moolenbroek key_block->keytype == ETYPE_DES_CBC_CRC) {
414*7348b5c5SDavid van Moolenbroek Session_Key skey;
415*7348b5c5SDavid van Moolenbroek
416*7348b5c5SDavid van Moolenbroek skey.type = SK_DES;
417*7348b5c5SDavid van Moolenbroek skey.length = 8;
418*7348b5c5SDavid van Moolenbroek skey.data = key_block->keyvalue.data;
419*7348b5c5SDavid van Moolenbroek encrypt_session_key(&skey, 0);
420*7348b5c5SDavid van Moolenbroek }
421*7348b5c5SDavid van Moolenbroek } else {
422*7348b5c5SDavid van Moolenbroek char *msg;
423*7348b5c5SDavid van Moolenbroek
424*7348b5c5SDavid van Moolenbroek asprintf(&msg, "user `%s' is not authorized to "
425*7348b5c5SDavid van Moolenbroek "login as `%s'",
426*7348b5c5SDavid van Moolenbroek name ? name : "<unknown>",
427*7348b5c5SDavid van Moolenbroek UserNameRequested ? UserNameRequested : "<nobody>");
428*7348b5c5SDavid van Moolenbroek if (msg == NULL)
429*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, NULL, 0);
430*7348b5c5SDavid van Moolenbroek else {
431*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, (void *) msg, -1);
432*7348b5c5SDavid van Moolenbroek free(msg);
433*7348b5c5SDavid van Moolenbroek }
434*7348b5c5SDavid van Moolenbroek auth_finished(ap, AUTH_REJECT);
435*7348b5c5SDavid van Moolenbroek krb5_free_keyblock(telnet_context, key_block);
436*7348b5c5SDavid van Moolenbroek break;
437*7348b5c5SDavid van Moolenbroek }
438*7348b5c5SDavid van Moolenbroek auth_finished(ap, AUTH_USER);
439*7348b5c5SDavid van Moolenbroek krb5_free_keyblock(telnet_context, key_block);
440*7348b5c5SDavid van Moolenbroek break;
441*7348b5c5SDavid van Moolenbroek case KRB_FORWARD:{
442*7348b5c5SDavid van Moolenbroek struct passwd pws, *pwd;
443*7348b5c5SDavid van Moolenbroek char pwbuf[1024];
444*7348b5c5SDavid van Moolenbroek char ccname[1024]; /* XXX */
445*7348b5c5SDavid van Moolenbroek krb5_data inbuf;
446*7348b5c5SDavid van Moolenbroek krb5_ccache ccache;
447*7348b5c5SDavid van Moolenbroek inbuf.data = (char *) data;
448*7348b5c5SDavid van Moolenbroek inbuf.length = cnt;
449*7348b5c5SDavid van Moolenbroek
450*7348b5c5SDavid van Moolenbroek if (getpwnam_r(UserNameRequested, &pws, pwbuf,
451*7348b5c5SDavid van Moolenbroek sizeof(pwbuf), &pwd) != 0 || pwd == NULL)
452*7348b5c5SDavid van Moolenbroek break;
453*7348b5c5SDavid van Moolenbroek
454*7348b5c5SDavid van Moolenbroek snprintf(ccname, sizeof(ccname),
455*7348b5c5SDavid van Moolenbroek "FILE:/tmp/krb5cc_%u", pwd->pw_uid);
456*7348b5c5SDavid van Moolenbroek
457*7348b5c5SDavid van Moolenbroek ret = krb5_cc_resolve(telnet_context, ccname, &ccache);
458*7348b5c5SDavid van Moolenbroek if (ret) {
459*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
460*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: could not get ccache: %s\r\n",
461*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context,
462*7348b5c5SDavid van Moolenbroek ret));
463*7348b5c5SDavid van Moolenbroek break;
464*7348b5c5SDavid van Moolenbroek }
465*7348b5c5SDavid van Moolenbroek ret = krb5_cc_initialize(telnet_context, ccache,
466*7348b5c5SDavid van Moolenbroek ticket->client);
467*7348b5c5SDavid van Moolenbroek if (ret) {
468*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
469*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: could not init ccache: %s\r\n",
470*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context,
471*7348b5c5SDavid van Moolenbroek ret));
472*7348b5c5SDavid van Moolenbroek break;
473*7348b5c5SDavid van Moolenbroek }
474*7348b5c5SDavid van Moolenbroek ret = krb5_rd_cred2(telnet_context, auth_context,
475*7348b5c5SDavid van Moolenbroek ccache, &inbuf);
476*7348b5c5SDavid van Moolenbroek if (ret) {
477*7348b5c5SDavid van Moolenbroek char *errbuf;
478*7348b5c5SDavid van Moolenbroek
479*7348b5c5SDavid van Moolenbroek asprintf(&errbuf,
480*7348b5c5SDavid van Moolenbroek "Read forwarded creds failed: %s",
481*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
482*7348b5c5SDavid van Moolenbroek if (errbuf == NULL)
483*7348b5c5SDavid van Moolenbroek Data(ap, KRB_FORWARD_REJECT, NULL, 0);
484*7348b5c5SDavid van Moolenbroek else
485*7348b5c5SDavid van Moolenbroek Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
486*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
487*7348b5c5SDavid van Moolenbroek printf("Could not read forwarded credentials: %s\r\n",
488*7348b5c5SDavid van Moolenbroek errbuf);
489*7348b5c5SDavid van Moolenbroek free(errbuf);
490*7348b5c5SDavid van Moolenbroek } else
491*7348b5c5SDavid van Moolenbroek Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
492*7348b5c5SDavid van Moolenbroek chown(ccname + 5, pwd->pw_uid, -1);
493*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
494*7348b5c5SDavid van Moolenbroek printf("Forwarded credentials obtained\r\n");
495*7348b5c5SDavid van Moolenbroek break;
496*7348b5c5SDavid van Moolenbroek }
497*7348b5c5SDavid van Moolenbroek default:
498*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
499*7348b5c5SDavid van Moolenbroek printf("Unknown Kerberos option %d\r\n", data[-1]);
500*7348b5c5SDavid van Moolenbroek Data(ap, KRB_REJECT, 0, 0);
501*7348b5c5SDavid van Moolenbroek break;
502*7348b5c5SDavid van Moolenbroek }
503*7348b5c5SDavid van Moolenbroek }
504*7348b5c5SDavid van Moolenbroek
505*7348b5c5SDavid van Moolenbroek void
kerberos5_reply(Authenticator * ap,unsigned char * data,int cnt)506*7348b5c5SDavid van Moolenbroek kerberos5_reply(Authenticator * ap, unsigned char *data, int cnt)
507*7348b5c5SDavid van Moolenbroek {
508*7348b5c5SDavid van Moolenbroek static int mutual_complete = 0;
509*7348b5c5SDavid van Moolenbroek
510*7348b5c5SDavid van Moolenbroek if (cnt-- < 1)
511*7348b5c5SDavid van Moolenbroek return;
512*7348b5c5SDavid van Moolenbroek switch (*data++) {
513*7348b5c5SDavid van Moolenbroek case KRB_REJECT:
514*7348b5c5SDavid van Moolenbroek if (cnt > 0) {
515*7348b5c5SDavid van Moolenbroek printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n",
516*7348b5c5SDavid van Moolenbroek cnt, data);
517*7348b5c5SDavid van Moolenbroek } else
518*7348b5c5SDavid van Moolenbroek printf("[ Kerberos V5 refuses authentication ]\r\n");
519*7348b5c5SDavid van Moolenbroek auth_send_retry();
520*7348b5c5SDavid van Moolenbroek return;
521*7348b5c5SDavid van Moolenbroek case KRB_ACCEPT:{
522*7348b5c5SDavid van Moolenbroek krb5_error_code ret;
523*7348b5c5SDavid van Moolenbroek Session_Key skey;
524*7348b5c5SDavid van Moolenbroek krb5_keyblock *keyblock;
525*7348b5c5SDavid van Moolenbroek
526*7348b5c5SDavid van Moolenbroek if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
527*7348b5c5SDavid van Moolenbroek !mutual_complete) {
528*7348b5c5SDavid van Moolenbroek printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\r\n");
529*7348b5c5SDavid van Moolenbroek auth_send_retry();
530*7348b5c5SDavid van Moolenbroek return;
531*7348b5c5SDavid van Moolenbroek }
532*7348b5c5SDavid van Moolenbroek if (cnt)
533*7348b5c5SDavid van Moolenbroek printf("[ Kerberos V5 accepts you as ``%.*s'' ]\r\n", cnt, data);
534*7348b5c5SDavid van Moolenbroek else
535*7348b5c5SDavid van Moolenbroek printf("[ Kerberos V5 accepts you ]\r\n");
536*7348b5c5SDavid van Moolenbroek
537*7348b5c5SDavid van Moolenbroek ret = krb5_auth_con_getlocalsubkey(telnet_context,
538*7348b5c5SDavid van Moolenbroek auth_context, &keyblock);
539*7348b5c5SDavid van Moolenbroek if (ret)
540*7348b5c5SDavid van Moolenbroek ret = krb5_auth_con_getkey(telnet_context,
541*7348b5c5SDavid van Moolenbroek auth_context, &keyblock);
542*7348b5c5SDavid van Moolenbroek if (ret) {
543*7348b5c5SDavid van Moolenbroek printf("[ krb5_auth_con_getkey: %s ]\r\n",
544*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
545*7348b5c5SDavid van Moolenbroek auth_send_retry();
546*7348b5c5SDavid van Moolenbroek return;
547*7348b5c5SDavid van Moolenbroek }
548*7348b5c5SDavid van Moolenbroek skey.type = SK_DES;
549*7348b5c5SDavid van Moolenbroek skey.length = 8;
550*7348b5c5SDavid van Moolenbroek skey.data = keyblock->keyvalue.data;
551*7348b5c5SDavid van Moolenbroek encrypt_session_key(&skey, 0);
552*7348b5c5SDavid van Moolenbroek krb5_free_keyblock(telnet_context, keyblock);
553*7348b5c5SDavid van Moolenbroek auth_finished(ap, AUTH_USER);
554*7348b5c5SDavid van Moolenbroek if (forward_flags & OPTS_FORWARD_CREDS)
555*7348b5c5SDavid van Moolenbroek kerberos5_forward(ap);
556*7348b5c5SDavid van Moolenbroek break;
557*7348b5c5SDavid van Moolenbroek }
558*7348b5c5SDavid van Moolenbroek case KRB_RESPONSE:
559*7348b5c5SDavid van Moolenbroek if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
560*7348b5c5SDavid van Moolenbroek /* the rest of the reply should contain a krb_ap_rep */
561*7348b5c5SDavid van Moolenbroek krb5_ap_rep_enc_part *reply;
562*7348b5c5SDavid van Moolenbroek krb5_data inbuf;
563*7348b5c5SDavid van Moolenbroek krb5_error_code ret;
564*7348b5c5SDavid van Moolenbroek
565*7348b5c5SDavid van Moolenbroek inbuf.length = cnt;
566*7348b5c5SDavid van Moolenbroek inbuf.data = (char *) data;
567*7348b5c5SDavid van Moolenbroek
568*7348b5c5SDavid van Moolenbroek ret = krb5_rd_rep(telnet_context,
569*7348b5c5SDavid van Moolenbroek auth_context, &inbuf, &reply);
570*7348b5c5SDavid van Moolenbroek if (ret) {
571*7348b5c5SDavid van Moolenbroek printf("[ Mutual authentication failed: %s ]\r\n",
572*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
573*7348b5c5SDavid van Moolenbroek auth_send_retry();
574*7348b5c5SDavid van Moolenbroek return;
575*7348b5c5SDavid van Moolenbroek }
576*7348b5c5SDavid van Moolenbroek krb5_free_ap_rep_enc_part(telnet_context, reply);
577*7348b5c5SDavid van Moolenbroek mutual_complete = 1;
578*7348b5c5SDavid van Moolenbroek }
579*7348b5c5SDavid van Moolenbroek return;
580*7348b5c5SDavid van Moolenbroek case KRB_FORWARD_ACCEPT:
581*7348b5c5SDavid van Moolenbroek printf("[ Kerberos V5 accepted forwarded credentials ]\r\n");
582*7348b5c5SDavid van Moolenbroek return;
583*7348b5c5SDavid van Moolenbroek case KRB_FORWARD_REJECT:
584*7348b5c5SDavid van Moolenbroek printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n",
585*7348b5c5SDavid van Moolenbroek cnt, data);
586*7348b5c5SDavid van Moolenbroek return;
587*7348b5c5SDavid van Moolenbroek default:
588*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
589*7348b5c5SDavid van Moolenbroek printf("Unknown Kerberos option %d\r\n", data[-1]);
590*7348b5c5SDavid van Moolenbroek return;
591*7348b5c5SDavid van Moolenbroek }
592*7348b5c5SDavid van Moolenbroek }
593*7348b5c5SDavid van Moolenbroek
594*7348b5c5SDavid van Moolenbroek int
kerberos5_status(Authenticator * ap,char * name,size_t l,int level)595*7348b5c5SDavid van Moolenbroek kerberos5_status(Authenticator *ap, char *name, size_t l, int level)
596*7348b5c5SDavid van Moolenbroek {
597*7348b5c5SDavid van Moolenbroek if (level < AUTH_USER)
598*7348b5c5SDavid van Moolenbroek return (level);
599*7348b5c5SDavid van Moolenbroek
600*7348b5c5SDavid van Moolenbroek if (UserNameRequested &&
601*7348b5c5SDavid van Moolenbroek krb5_kuserok(telnet_context, ticket->client, UserNameRequested)) {
602*7348b5c5SDavid van Moolenbroek strlcpy(name, UserNameRequested, l);
603*7348b5c5SDavid van Moolenbroek return (AUTH_VALID);
604*7348b5c5SDavid van Moolenbroek } else
605*7348b5c5SDavid van Moolenbroek return (AUTH_USER);
606*7348b5c5SDavid van Moolenbroek }
607*7348b5c5SDavid van Moolenbroek #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
608*7348b5c5SDavid van Moolenbroek #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
609*7348b5c5SDavid van Moolenbroek
610*7348b5c5SDavid van Moolenbroek void
kerberos5_printsub(unsigned char * data,int cnt,unsigned char * buf,int buflen)611*7348b5c5SDavid van Moolenbroek kerberos5_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
612*7348b5c5SDavid van Moolenbroek {
613*7348b5c5SDavid van Moolenbroek int i;
614*7348b5c5SDavid van Moolenbroek
615*7348b5c5SDavid van Moolenbroek buf[buflen - 1] = '\0'; /* make sure its NULL terminated */
616*7348b5c5SDavid van Moolenbroek buflen -= 1;
617*7348b5c5SDavid van Moolenbroek
618*7348b5c5SDavid van Moolenbroek switch (data[3]) {
619*7348b5c5SDavid van Moolenbroek case KRB_REJECT: /* Rejected (reason might follow) */
620*7348b5c5SDavid van Moolenbroek strlcpy((char *) buf, " REJECT ", buflen);
621*7348b5c5SDavid van Moolenbroek goto common;
622*7348b5c5SDavid van Moolenbroek
623*7348b5c5SDavid van Moolenbroek case KRB_ACCEPT: /* Accepted (name might follow) */
624*7348b5c5SDavid van Moolenbroek strlcpy((char *) buf, " ACCEPT ", buflen);
625*7348b5c5SDavid van Moolenbroek common:
626*7348b5c5SDavid van Moolenbroek BUMP(buf, buflen);
627*7348b5c5SDavid van Moolenbroek if (cnt <= 4)
628*7348b5c5SDavid van Moolenbroek break;
629*7348b5c5SDavid van Moolenbroek ADDC(buf, buflen, '"');
630*7348b5c5SDavid van Moolenbroek for (i = 4; i < cnt; i++)
631*7348b5c5SDavid van Moolenbroek ADDC(buf, buflen, data[i]);
632*7348b5c5SDavid van Moolenbroek ADDC(buf, buflen, '"');
633*7348b5c5SDavid van Moolenbroek ADDC(buf, buflen, '\0');
634*7348b5c5SDavid van Moolenbroek break;
635*7348b5c5SDavid van Moolenbroek
636*7348b5c5SDavid van Moolenbroek
637*7348b5c5SDavid van Moolenbroek case KRB_AUTH: /* Authentication data follows */
638*7348b5c5SDavid van Moolenbroek strlcpy((char *) buf, " AUTH", buflen);
639*7348b5c5SDavid van Moolenbroek goto common2;
640*7348b5c5SDavid van Moolenbroek
641*7348b5c5SDavid van Moolenbroek case KRB_RESPONSE:
642*7348b5c5SDavid van Moolenbroek strlcpy((char *) buf, " RESPONSE", buflen);
643*7348b5c5SDavid van Moolenbroek goto common2;
644*7348b5c5SDavid van Moolenbroek
645*7348b5c5SDavid van Moolenbroek case KRB_FORWARD: /* Forwarded credentials follow */
646*7348b5c5SDavid van Moolenbroek strlcpy((char *) buf, " FORWARD", buflen);
647*7348b5c5SDavid van Moolenbroek goto common2;
648*7348b5c5SDavid van Moolenbroek
649*7348b5c5SDavid van Moolenbroek case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */
650*7348b5c5SDavid van Moolenbroek strlcpy((char *) buf, " FORWARD_ACCEPT", buflen);
651*7348b5c5SDavid van Moolenbroek goto common2;
652*7348b5c5SDavid van Moolenbroek
653*7348b5c5SDavid van Moolenbroek case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */
654*7348b5c5SDavid van Moolenbroek /* (reason might follow) */
655*7348b5c5SDavid van Moolenbroek strlcpy((char *) buf, " FORWARD_REJECT", buflen);
656*7348b5c5SDavid van Moolenbroek goto common2;
657*7348b5c5SDavid van Moolenbroek
658*7348b5c5SDavid van Moolenbroek default:
659*7348b5c5SDavid van Moolenbroek snprintf(buf, buflen, " %d (unknown)", data[3]);
660*7348b5c5SDavid van Moolenbroek common2:
661*7348b5c5SDavid van Moolenbroek BUMP(buf, buflen);
662*7348b5c5SDavid van Moolenbroek for (i = 4; i < cnt; i++) {
663*7348b5c5SDavid van Moolenbroek snprintf(buf, buflen, " %d", data[i]);
664*7348b5c5SDavid van Moolenbroek BUMP(buf, buflen);
665*7348b5c5SDavid van Moolenbroek }
666*7348b5c5SDavid van Moolenbroek break;
667*7348b5c5SDavid van Moolenbroek }
668*7348b5c5SDavid van Moolenbroek }
669*7348b5c5SDavid van Moolenbroek
670*7348b5c5SDavid van Moolenbroek void
kerberos5_forward(Authenticator * ap)671*7348b5c5SDavid van Moolenbroek kerberos5_forward(Authenticator * ap)
672*7348b5c5SDavid van Moolenbroek {
673*7348b5c5SDavid van Moolenbroek krb5_error_code ret;
674*7348b5c5SDavid van Moolenbroek krb5_ccache ccache;
675*7348b5c5SDavid van Moolenbroek krb5_creds creds;
676*7348b5c5SDavid van Moolenbroek krb5_kdc_flags flags;
677*7348b5c5SDavid van Moolenbroek krb5_data out_data;
678*7348b5c5SDavid van Moolenbroek krb5_principal principal;
679*7348b5c5SDavid van Moolenbroek
680*7348b5c5SDavid van Moolenbroek ret = krb5_cc_default(telnet_context, &ccache);
681*7348b5c5SDavid van Moolenbroek if (ret) {
682*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
683*7348b5c5SDavid van Moolenbroek printf("KerberosV5: could not get default ccache: %s\r\n",
684*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
685*7348b5c5SDavid van Moolenbroek return;
686*7348b5c5SDavid van Moolenbroek }
687*7348b5c5SDavid van Moolenbroek ret = krb5_cc_get_principal(telnet_context, ccache, &principal);
688*7348b5c5SDavid van Moolenbroek if (ret) {
689*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
690*7348b5c5SDavid van Moolenbroek printf("KerberosV5: could not get principal: %s\r\n",
691*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
692*7348b5c5SDavid van Moolenbroek return;
693*7348b5c5SDavid van Moolenbroek }
694*7348b5c5SDavid van Moolenbroek memset(&creds, 0, sizeof(creds));
695*7348b5c5SDavid van Moolenbroek
696*7348b5c5SDavid van Moolenbroek creds.client = principal;
697*7348b5c5SDavid van Moolenbroek
698*7348b5c5SDavid van Moolenbroek ret = krb5_build_principal(telnet_context, &creds.server,
699*7348b5c5SDavid van Moolenbroek strlen(principal->realm), principal->realm, "krbtgt",
700*7348b5c5SDavid van Moolenbroek principal->realm, NULL);
701*7348b5c5SDavid van Moolenbroek
702*7348b5c5SDavid van Moolenbroek if (ret) {
703*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
704*7348b5c5SDavid van Moolenbroek printf("KerberosV5: could not get principal: %s\r\n",
705*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
706*7348b5c5SDavid van Moolenbroek return;
707*7348b5c5SDavid van Moolenbroek }
708*7348b5c5SDavid van Moolenbroek creds.times.endtime = 0;
709*7348b5c5SDavid van Moolenbroek
710*7348b5c5SDavid van Moolenbroek flags.i = 0;
711*7348b5c5SDavid van Moolenbroek flags.b.forwarded = 1;
712*7348b5c5SDavid van Moolenbroek if (forward_flags & OPTS_FORWARDABLE_CREDS)
713*7348b5c5SDavid van Moolenbroek flags.b.forwardable = 1;
714*7348b5c5SDavid van Moolenbroek
715*7348b5c5SDavid van Moolenbroek ret = krb5_get_forwarded_creds(telnet_context, auth_context,
716*7348b5c5SDavid van Moolenbroek ccache, flags.i, RemoteHostName, &creds, &out_data);
717*7348b5c5SDavid van Moolenbroek if (ret) {
718*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
719*7348b5c5SDavid van Moolenbroek printf("Kerberos V5: error getting forwarded creds: %s\r\n",
720*7348b5c5SDavid van Moolenbroek get_krb5_err_text(telnet_context, ret));
721*7348b5c5SDavid van Moolenbroek return;
722*7348b5c5SDavid van Moolenbroek }
723*7348b5c5SDavid van Moolenbroek if (!Data(ap, KRB_FORWARD, out_data.data, out_data.length)) {
724*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
725*7348b5c5SDavid van Moolenbroek printf("Not enough room for authentication data\r\n");
726*7348b5c5SDavid van Moolenbroek } else {
727*7348b5c5SDavid van Moolenbroek if (auth_debug_mode)
728*7348b5c5SDavid van Moolenbroek printf("Forwarded local Kerberos V5 credentials to server\r\n");
729*7348b5c5SDavid van Moolenbroek }
730*7348b5c5SDavid van Moolenbroek }
731*7348b5c5SDavid van Moolenbroek #endif /* KRB5 */
732