Deleted Added
full compact
kerberos5.c (29089) kerberos5.c (81965)
1/*
2 * $Source: /mit/krb5/.cvsroot/src/appl/telnet/libtelnet/kerberos5.c,v $
3 * $Author: tytso $
4 * $Id: kerberos5.c,v 1.1 1997/09/04 06:11:15 markm Exp $
5 */
6
7#if !defined(lint) && !defined(SABER)
8static
9#ifdef __STDC__
10const
11#endif
1/*
2 * $Source: /mit/krb5/.cvsroot/src/appl/telnet/libtelnet/kerberos5.c,v $
3 * $Author: tytso $
4 * $Id: kerberos5.c,v 1.1 1997/09/04 06:11:15 markm Exp $
5 */
6
7#if !defined(lint) && !defined(SABER)
8static
9#ifdef __STDC__
10const
11#endif
12char rcsid_kerberos5_c[] = "$Id: kerberos5.c,v 1.1 1997/09/04 06:11:15 markm Exp $";
12char rcsid_kerberos5_c[] = "$FreeBSD: head/contrib/telnet/libtelnet/kerberos5.c 81965 2001-08-20 12:28:40Z markm $";
13#endif /* lint */
14
15/*-
16 * Copyright (c) 1991, 1993
17 * The Regents of the University of California. All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * 3. All advertising materials mentioning features or use of this software
28 * must display the following acknowledgement:
29 * This product includes software developed by the University of
30 * California, Berkeley and its contributors.
31 * 4. Neither the name of the University nor the names of its contributors
32 * may be used to endorse or promote products derived from this software
33 * without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48#ifndef lint
13#endif /* lint */
14
15/*-
16 * Copyright (c) 1991, 1993
17 * The Regents of the University of California. All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * 3. All advertising materials mentioning features or use of this software
28 * must display the following acknowledgement:
29 * This product includes software developed by the University of
30 * California, Berkeley and its contributors.
31 * 4. Neither the name of the University nor the names of its contributors
32 * may be used to endorse or promote products derived from this software
33 * without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 */
47
48#ifndef lint
49static char sccsid[] = "@(#)kerberos5.c 8.3 (Berkeley) 5/30/95";
49static const char sccsid[] = "@(#)kerberos5.c 8.3 (Berkeley) 5/30/95";
50#endif /* not lint */
51
52/*
53 * Copyright (C) 1990 by the Massachusetts Institute of Technology
54 *
55 * Export of this software from the United States of America may
56 * require a specific license from the United States Government.
57 * It is the responsibility of any person or organization contemplating
58 * export to obtain such a license before exporting.
59 *
60 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
61 * distribute this software and its documentation for any purpose and
62 * without fee is hereby granted, provided that the above copyright
63 * notice appear in all copies and that both that copyright notice and
64 * this permission notice appear in supporting documentation, and that
65 * the name of M.I.T. not be used in advertising or publicity pertaining
66 * to distribution of the software without specific, written prior
67 * permission. M.I.T. makes no representations about the suitability of
68 * this software for any purpose. It is provided "as is" without express
69 * or implied warranty.
70 */
71
72
73#ifdef KRB5
74#include <arpa/telnet.h>
50#endif /* not lint */
51
52/*
53 * Copyright (C) 1990 by the Massachusetts Institute of Technology
54 *
55 * Export of this software from the United States of America may
56 * require a specific license from the United States Government.
57 * It is the responsibility of any person or organization contemplating
58 * export to obtain such a license before exporting.
59 *
60 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
61 * distribute this software and its documentation for any purpose and
62 * without fee is hereby granted, provided that the above copyright
63 * notice appear in all copies and that both that copyright notice and
64 * this permission notice appear in supporting documentation, and that
65 * the name of M.I.T. not be used in advertising or publicity pertaining
66 * to distribution of the software without specific, written prior
67 * permission. M.I.T. makes no representations about the suitability of
68 * this software for any purpose. It is provided "as is" without express
69 * or implied warranty.
70 */
71
72
73#ifdef KRB5
74#include <arpa/telnet.h>
75#include <stdio.h>
76#include <krb5/krb5.h>
77#include <krb5/asn1.h>
78#include <krb5/crc-32.h>
79#include <krb5/los-proto.h>
80#include <krb5/ext-proto.h>
81#include <com_err.h>
75#include <com_err.h>
82#include <netdb.h>
83#include <ctype.h>
76#include <ctype.h>
77#include <krb5.h>
78#include <krb5_asn1.h>
79#include <netdb.h>
80#include <stdio.h>
81#include <stdlib.h>
82#include <string.h>
84
85/* kerberos 5 include files (ext-proto.h) will get an appropriate stdlib.h
86 and string.h/strings.h */
87
88#include "encrypt.h"
89#include "auth.h"
90#include "misc.h"
91
83
84/* kerberos 5 include files (ext-proto.h) will get an appropriate stdlib.h
85 and string.h/strings.h */
86
87#include "encrypt.h"
88#include "auth.h"
89#include "misc.h"
90
92extern auth_debug_mode;
91extern int auth_debug_mode;
93
94#ifdef FORWARD
95int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */
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
102void kerberos5_forward();
103
104#endif /* FORWARD */
105
106static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
107 AUTHTYPE_KERBEROS_V5, };
108/*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
109 TELQUAL_NAME, };*/
110
111#define KRB_AUTH 0 /* Authentication data follows */
112#define KRB_REJECT 1 /* Rejected (reason might follow) */
113#define KRB_ACCEPT 2 /* Accepted */
114#define KRB_RESPONSE 3 /* Response for mutual auth. */
115
116#ifdef FORWARD
117#define KRB_FORWARD 4 /* Forwarded credentials follow */
118#define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */
119#define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */
120#endif /* FORWARD */
121
122static krb5_data auth;
123 /* telnetd gets session key from here */
124static krb5_tkt_authent *authdat = NULL;
125/* telnet matches the AP_REQ and AP_REP with this */
126static krb5_authenticator authenticator;
127
128/* some compilers can't hack void *, so we use the Kerberos krb5_pointer,
129 which is either void * or char *, depending on the compiler. */
130
131#define Voidptr krb5_pointer
132
133Block session_key;
134
135 static int
136Data(ap, type, d, c)
137 Authenticator *ap;
138 int type;
139 Voidptr d;
140 int c;
141{
142 unsigned char *p = str_data + 4;
143 unsigned char *cd = (unsigned char *)d;
144
145 if (c == -1)
146 c = strlen((char *)cd);
147
148 if (auth_debug_mode) {
149 printf("%s:%d: [%d] (%d)",
150 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
151 str_data[3],
152 type, c);
153 printd(d, c);
154 printf("\r\n");
155 }
156 *p++ = ap->type;
157 *p++ = ap->way;
158 *p++ = type;
159 while (c-- > 0) {
160 if ((*p++ = *cd++) == IAC)
161 *p++ = IAC;
162 }
163 *p++ = IAC;
164 *p++ = SE;
165 if (str_data[3] == TELQUAL_IS)
166 printsub('>', &str_data[2], p - &str_data[2]);
167 return(net_write(str_data, p - str_data));
168}
169
170 int
171kerberos5_init(ap, server)
172 Authenticator *ap;
173 int server;
174{
175 if (server)
176 str_data[3] = TELQUAL_REPLY;
177 else
178 str_data[3] = TELQUAL_IS;
179 krb5_init_ets();
180 return(1);
181}
182
183 int
184kerberos5_send(ap)
185 Authenticator *ap;
186{
187 char **realms;
188 char *name;
189 char *p1, *p2;
190 krb5_checksum ksum;
191 krb5_octet sum[CRC32_CKSUM_LENGTH];
192 krb5_principal server;
193 krb5_error_code r;
194 krb5_ccache ccache;
195 krb5_creds creds; /* telnet gets session key from here */
196 extern krb5_flags krb5_kdc_default_options;
197 int ap_opts;
198
199#ifdef ENCRYPTION
200 krb5_keyblock *newkey = 0;
201#endif /* ENCRYPTION */
202
203 ksum.checksum_type = CKSUMTYPE_CRC32;
204 ksum.contents = sum;
205 ksum.length = sizeof(sum);
206 memset((Voidptr )sum, 0, sizeof(sum));
207
208 if (!UserNameRequested) {
209 if (auth_debug_mode) {
210 printf("Kerberos V5: no user name supplied\r\n");
211 }
212 return(0);
213 }
214
215 if (r = krb5_cc_default(&ccache)) {
216 if (auth_debug_mode) {
217 printf("Kerberos V5: could not get default ccache\r\n");
218 }
219 return(0);
220 }
221
222 if ((name = malloc(strlen(RemoteHostName)+1)) == NULL) {
223 if (auth_debug_mode)
224 printf("Out of memory for hostname in Kerberos V5\r\n");
225 return(0);
226 }
227
228 if (r = krb5_get_host_realm(RemoteHostName, &realms)) {
229 if (auth_debug_mode)
230 printf("Kerberos V5: no realm for %s\r\n", RemoteHostName);
231 free(name);
232 return(0);
233 }
234
235 p1 = RemoteHostName;
236 p2 = name;
237
238 while (*p2 = *p1++) {
239 if (isupper(*p2))
240 *p2 |= 040;
241 ++p2;
242 }
243
244 if (r = krb5_build_principal_ext(&server,
245 strlen(realms[0]), realms[0],
246 4, "host",
247 p2 - name, name,
248 0)) {
249 if (auth_debug_mode) {
250 printf("Kerberos V5: failure setting up principal (%s)\r\n",
251 error_message(r));
252 }
253 free(name);
254 krb5_free_host_realm(realms);
255 return(0);
256 }
257
258
259 memset((char *)&creds, 0, sizeof(creds));
260 creds.server = server;
261
262 if (r = krb5_cc_get_principal(ccache, &creds.client)) {
263 if (auth_debug_mode) {
264 printf("Kerberos V5: failure on principal (%s)\r\n",
265 error_message(r));
266 }
267 free(name);
268 krb5_free_principal(server);
269 krb5_free_host_realm(realms);
270 return(0);
271 }
272
273 if (r = krb5_get_credentials(krb5_kdc_default_options, ccache, &creds)) {
274 if (auth_debug_mode) {
275 printf("Kerberos V5: failure on credentials(%d)\r\n",r);
276 }
277 free(name);
278 krb5_free_host_realm(realms);
279 krb5_free_principal(server);
280 return(0);
281 }
282
283 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
284 ap_opts = AP_OPTS_MUTUAL_REQUIRED;
285 else
286 ap_opts = 0;
287
288 r = krb5_mk_req_extended(ap_opts, &ksum, krb5_kdc_default_options, 0,
289#ifdef ENCRYPTION
290 &newkey,
291#else /* ENCRYPTION */
292 0,
293#endif /* ENCRYPTION */
294 ccache, &creds, &authenticator, &auth);
295 /* don't let the key get freed if we clean up the authenticator */
296 authenticator.subkey = 0;
297
298 free(name);
299 krb5_free_host_realm(realms);
300 krb5_free_principal(server);
301#ifdef ENCRYPTION
302 if (newkey) {
303 /* keep the key in our private storage, but don't use it
304 yet---see kerberos5_reply() below */
305 if (newkey->keytype != KEYTYPE_DES) {
306 if (creds.keyblock.keytype == KEYTYPE_DES)
307 /* use the session key in credentials instead */
308 memmove((char *)session_key,
309 (char *)creds.keyblock.contents, sizeof(Block));
310 else
311 /* XXX ? */;
312 } else {
313 memmove((char *)session_key, (char *)newkey->contents,
314 sizeof(Block));
315 }
316 krb5_free_keyblock(newkey);
317 }
318#endif /* ENCRYPTION */
319 if (r) {
320 if (auth_debug_mode) {
321 printf("Kerberos V5: mk_req failed (%s)\r\n",
322 error_message(r));
323 }
324 return(0);
325 }
326
327 if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
328 if (auth_debug_mode)
329 printf("Not enough room for user name\r\n");
330 return(0);
331 }
332 if (!Data(ap, KRB_AUTH, auth.data, auth.length)) {
333 if (auth_debug_mode)
334 printf("Not enough room for authentication data\r\n");
335 return(0);
336 }
337 if (auth_debug_mode) {
338 printf("Sent Kerberos V5 credentials to server\r\n");
339 }
340 return(1);
341}
342
343 void
344kerberos5_is(ap, data, cnt)
345 Authenticator *ap;
346 unsigned char *data;
347 int cnt;
348{
349 int r;
350 struct hostent *hp;
351 char *p1, *p2;
352 static char *realm = NULL;
353 krb5_principal server;
354 krb5_ap_rep_enc_part reply;
355 krb5_data outbuf;
356#ifdef ENCRYPTION
357 Session_Key skey;
358#endif /* ENCRYPTION */
359 char *name;
360 char *getenv();
361 krb5_data inbuf;
362
363 if (cnt-- < 1)
364 return;
365 switch (*data++) {
366 case KRB_AUTH:
367 auth.data = (char *)data;
368 auth.length = cnt;
369
370 if (!(hp = gethostbyname(LocalHostName))) {
371 if (auth_debug_mode)
372 printf("Cannot resolve local host name\r\n");
373 Data(ap, KRB_REJECT, "Unknown local hostname.", -1);
374 auth_finished(ap, AUTH_REJECT);
375 return;
376 }
377
378 if (!realm && (krb5_get_default_realm(&realm))) {
379 if (auth_debug_mode)
380 printf("Could not get default realm\r\n");
381 Data(ap, KRB_REJECT, "Could not get default realm.", -1);
382 auth_finished(ap, AUTH_REJECT);
383 return;
384 }
385
386 if ((name = malloc(strlen(hp->h_name)+1)) == NULL) {
387 if (auth_debug_mode)
388 printf("Out of memory for hostname in Kerberos V5\r\n");
389 Data(ap, KRB_REJECT, "Out of memory.", -1);
390 auth_finished(ap, AUTH_REJECT);
391 return;
392 }
393
394 p1 = hp->h_name;
395 p2 = name;
396
397 while (*p2 = *p1++) {
398 if (isupper(*p2))
399 *p2 |= 040;
400 ++p2;
401 }
402
403 if (authdat)
404 krb5_free_tkt_authent(authdat);
405
406 r = krb5_build_principal_ext(&server,
407 strlen(realm), realm,
408 4, "host",
409 p2 - name, name,
410 0);
411 if (!r) {
412 r = krb5_rd_req_simple(&auth, server, 0, &authdat);
413 krb5_free_principal(server);
414 }
415 if (r) {
416 char errbuf[128];
417
418 errout:
419 authdat = 0;
420 (void) strcpy(errbuf, "Read req failed: ");
421 (void) strcat(errbuf, error_message(r));
422 Data(ap, KRB_REJECT, errbuf, -1);
423 if (auth_debug_mode)
424 printf("%s\r\n", errbuf);
425 return;
426 }
427 free(name);
428 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
429 /* do ap_rep stuff here */
430 reply.ctime = authdat->authenticator->ctime;
431 reply.cusec = authdat->authenticator->cusec;
432 reply.subkey = 0; /* use the one he gave us, so don't
433 need to return one here */
434 reply.seq_number = 0; /* we don't do seq #'s. */
435
436 if (r = krb5_mk_rep(&reply,
437 authdat->authenticator->subkey ?
438 authdat->authenticator->subkey :
439 authdat->ticket->enc_part2->session,
440 &outbuf)) {
441 goto errout;
442 }
443 Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
444 }
445 if (krb5_unparse_name(authdat->ticket->enc_part2 ->client,
446 &name))
447 name = 0;
448 Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
449 if (auth_debug_mode) {
450 printf("Kerberos5 identifies him as ``%s''\r\n",
451 name ? name : "");
452 }
453 auth_finished(ap, AUTH_USER);
454
455 free(name);
456 if (authdat->authenticator->subkey &&
457 authdat->authenticator->subkey->keytype == KEYTYPE_DES) {
458 memmove((Voidptr )session_key,
459 (Voidptr )authdat->authenticator->subkey->contents,
460 sizeof(Block));
461 } else if (authdat->ticket->enc_part2->session->keytype ==
462 KEYTYPE_DES) {
463 memmove((Voidptr )session_key,
464 (Voidptr )authdat->ticket->enc_part2->session->contents,
465 sizeof(Block));
466 } else
467 break;
468
469#ifdef ENCRYPTION
470 skey.type = SK_DES;
471 skey.length = 8;
472 skey.data = session_key;
473 encrypt_session_key(&skey, 1);
474#endif /* ENCRYPTION */
475 break;
476#ifdef FORWARD
477 case KRB_FORWARD:
478 inbuf.data = (char *)data;
479 inbuf.length = cnt;
480 if (r = rd_and_store_for_creds(&inbuf, authdat->ticket,
481 UserNameRequested)) {
482 char errbuf[128];
483
484 (void) strcpy(errbuf, "Read forwarded creds failed: ");
485 (void) strcat(errbuf, error_message(r));
486 Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
487 if (auth_debug_mode)
488 printf("Could not read forwarded credentials\r\n");
489 }
490 else
491 Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
492 if (auth_debug_mode)
493 printf("Forwarded credentials obtained\r\n");
494 break;
495#endif /* FORWARD */
496 default:
497 if (auth_debug_mode)
498 printf("Unknown Kerberos option %d\r\n", data[-1]);
499 Data(ap, KRB_REJECT, 0, 0);
500 break;
501 }
502}
503
504 void
505kerberos5_reply(ap, data, cnt)
506 Authenticator *ap;
507 unsigned char *data;
508 int cnt;
509{
510 Session_Key skey;
511 static int mutual_complete = 0;
512
513 if (cnt-- < 1)
514 return;
515 switch (*data++) {
516 case KRB_REJECT:
517 if (cnt > 0) {
518 printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n",
519 cnt, data);
520 } else
521 printf("[ Kerberos V5 refuses authentication ]\r\n");
522 auth_send_retry();
523 return;
524 case KRB_ACCEPT:
525 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
526 !mutual_complete) {
527 printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\n");
528 auth_send_retry();
529 return;
530 }
531 if (cnt)
532 printf("[ Kerberos V5 accepts you as ``%.*s'' ]\n", cnt, data);
533 else
534 printf("[ Kerberos V5 accepts you ]\n");
535 auth_finished(ap, AUTH_USER);
536#ifdef FORWARD
537 if (forward_flags & OPTS_FORWARD_CREDS)
538 kerberos5_forward(ap);
539#endif /* FORWARD */
540 break;
541 case KRB_RESPONSE:
542 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
543 /* the rest of the reply should contain a krb_ap_rep */
544 krb5_ap_rep_enc_part *reply;
545 krb5_data inbuf;
546 krb5_error_code r;
547 krb5_keyblock tmpkey;
548
549 inbuf.length = cnt;
550 inbuf.data = (char *)data;
551
552 tmpkey.keytype = KEYTYPE_DES;
553 tmpkey.contents = session_key;
554 tmpkey.length = sizeof(Block);
555
556 if (r = krb5_rd_rep(&inbuf, &tmpkey, &reply)) {
557 printf("[ Mutual authentication failed: %s ]\n",
558 error_message(r));
559 auth_send_retry();
560 return;
561 }
562 if (reply->ctime != authenticator.ctime ||
563 reply->cusec != authenticator.cusec) {
564 printf("[ Mutual authentication failed (mismatched KRB_AP_REP) ]\n");
565 auth_send_retry();
566 return;
567 }
568 krb5_free_ap_rep_enc_part(reply);
569#ifdef ENCRYPTION
570 skey.type = SK_DES;
571 skey.length = 8;
572 skey.data = session_key;
573 encrypt_session_key(&skey, 0);
574#endif /* ENCRYPTION */
575 mutual_complete = 1;
576 }
577 return;
578#ifdef FORWARD
579 case KRB_FORWARD_ACCEPT:
580 printf("[ Kerberos V5 accepted forwarded credentials ]\n");
581 return;
582 case KRB_FORWARD_REJECT:
583 printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n",
584 cnt, data);
585 return;
586#endif /* FORWARD */
587 default:
588 if (auth_debug_mode)
589 printf("Unknown Kerberos option %d\r\n", data[-1]);
590 return;
591 }
592}
593
594 int
595kerberos5_status(ap, name, level)
596 Authenticator *ap;
597 char *name;
598 int level;
599{
600 if (level < AUTH_USER)
601 return(level);
602
603 if (UserNameRequested &&
604 krb5_kuserok(authdat->ticket->enc_part2->client, UserNameRequested))
605 {
606 strcpy(name, UserNameRequested);
607 return(AUTH_VALID);
608 } else
609 return(AUTH_USER);
610}
611
612#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
613#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
614
615 void
616kerberos5_printsub(data, cnt, buf, buflen)
617 unsigned char *data, *buf;
618 int cnt, buflen;
619{
620 char lbuf[32];
621 register int i;
622
623 buf[buflen-1] = '\0'; /* make sure its NULL terminated */
624 buflen -= 1;
625
626 switch(data[3]) {
627 case KRB_REJECT: /* Rejected (reason might follow) */
628 strncpy((char *)buf, " REJECT ", buflen);
629 goto common;
630
631 case KRB_ACCEPT: /* Accepted (name might follow) */
632 strncpy((char *)buf, " ACCEPT ", buflen);
633 common:
634 BUMP(buf, buflen);
635 if (cnt <= 4)
636 break;
637 ADDC(buf, buflen, '"');
638 for (i = 4; i < cnt; i++)
639 ADDC(buf, buflen, data[i]);
640 ADDC(buf, buflen, '"');
641 ADDC(buf, buflen, '\0');
642 break;
643
644
645 case KRB_AUTH: /* Authentication data follows */
646 strncpy((char *)buf, " AUTH", buflen);
647 goto common2;
648
649 case KRB_RESPONSE:
650 strncpy((char *)buf, " RESPONSE", buflen);
651 goto common2;
652
653#ifdef FORWARD
654 case KRB_FORWARD: /* Forwarded credentials follow */
655 strncpy((char *)buf, " FORWARD", buflen);
656 goto common2;
657
658 case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */
659 strncpy((char *)buf, " FORWARD_ACCEPT", buflen);
660 goto common2;
661
662 case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */
663 /* (reason might follow) */
664 strncpy((char *)buf, " FORWARD_REJECT", buflen);
665 goto common2;
666#endif /* FORWARD */
667
668 default:
669 sprintf(lbuf, " %d (unknown)", data[3]);
670 strncpy((char *)buf, lbuf, buflen);
671 common2:
672 BUMP(buf, buflen);
673 for (i = 4; i < cnt; i++) {
674 sprintf(lbuf, " %d", data[i]);
675 strncpy((char *)buf, lbuf, buflen);
676 BUMP(buf, buflen);
677 }
678 break;
679 }
680}
681
682#ifdef FORWARD
683 void
684kerberos5_forward(ap)
685 Authenticator *ap;
686{
687 struct hostent *hp;
688 krb5_creds *local_creds;
689 krb5_error_code r;
690 krb5_data forw_creds;
691 extern krb5_cksumtype krb5_kdc_req_sumtype;
692 krb5_ccache ccache;
693 int i;
694
695 if (!(local_creds = (krb5_creds *)
696 calloc(1, sizeof(*local_creds)))) {
697 if (auth_debug_mode)
698 printf("Kerberos V5: could not allocate memory for credentials\r\n");
699 return;
700 }
701
702 if (r = krb5_sname_to_principal(RemoteHostName, "host", 1,
703 &local_creds->server)) {
704 if (auth_debug_mode)
705 printf("Kerberos V5: could not build server name - %s\r\n",
706 error_message(r));
707 krb5_free_creds(local_creds);
708 return;
709 }
710
711 if (r = krb5_cc_default(&ccache)) {
712 if (auth_debug_mode)
713 printf("Kerberos V5: could not get default ccache - %s\r\n",
714 error_message(r));
715 krb5_free_creds(local_creds);
716 return;
717 }
718
719 if (r = krb5_cc_get_principal(ccache, &local_creds->client)) {
720 if (auth_debug_mode)
721 printf("Kerberos V5: could not get default principal - %s\r\n",
722 error_message(r));
723 krb5_free_creds(local_creds);
724 return;
725 }
726
727 /* Get ticket from credentials cache */
728 if (r = krb5_get_credentials(KRB5_GC_CACHED, ccache, local_creds)) {
729 if (auth_debug_mode)
730 printf("Kerberos V5: could not obtain credentials - %s\r\n",
731 error_message(r));
732 krb5_free_creds(local_creds);
733 return;
734 }
735
736 if (r = get_for_creds(ETYPE_DES_CBC_CRC,
737 krb5_kdc_req_sumtype,
738 RemoteHostName,
739 local_creds->client,
740 &local_creds->keyblock,
741 forward_flags & OPTS_FORWARDABLE_CREDS,
742 &forw_creds)) {
743 if (auth_debug_mode)
744 printf("Kerberos V5: error getting forwarded creds - %s\r\n",
745 error_message(r));
746 krb5_free_creds(local_creds);
747 return;
748 }
749
750 /* Send forwarded credentials */
751 if (!Data(ap, KRB_FORWARD, forw_creds.data, forw_creds.length)) {
752 if (auth_debug_mode)
753 printf("Not enough room for authentication data\r\n");
754 }
755 else {
756 if (auth_debug_mode)
757 printf("Forwarded local Kerberos V5 credentials to server\r\n");
758 }
759
760 krb5_free_creds(local_creds);
761}
762#endif /* FORWARD */
763
764#endif /* KRB5 */
92
93#ifdef FORWARD
94int forward_flags = 0; /* Flags get set in telnet/main.c on -f and -F */
95
96/* These values need to be the same as those defined in telnet/main.c. */
97/* Either define them in both places, or put in some common header file. */
98#define OPTS_FORWARD_CREDS 0x00000002
99#define OPTS_FORWARDABLE_CREDS 0x00000001
100
101void kerberos5_forward();
102
103#endif /* FORWARD */
104
105static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
106 AUTHTYPE_KERBEROS_V5, };
107/*static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
108 TELQUAL_NAME, };*/
109
110#define KRB_AUTH 0 /* Authentication data follows */
111#define KRB_REJECT 1 /* Rejected (reason might follow) */
112#define KRB_ACCEPT 2 /* Accepted */
113#define KRB_RESPONSE 3 /* Response for mutual auth. */
114
115#ifdef FORWARD
116#define KRB_FORWARD 4 /* Forwarded credentials follow */
117#define KRB_FORWARD_ACCEPT 5 /* Forwarded credentials accepted */
118#define KRB_FORWARD_REJECT 6 /* Forwarded credentials rejected */
119#endif /* FORWARD */
120
121static krb5_data auth;
122 /* telnetd gets session key from here */
123static krb5_tkt_authent *authdat = NULL;
124/* telnet matches the AP_REQ and AP_REP with this */
125static krb5_authenticator authenticator;
126
127/* some compilers can't hack void *, so we use the Kerberos krb5_pointer,
128 which is either void * or char *, depending on the compiler. */
129
130#define Voidptr krb5_pointer
131
132Block session_key;
133
134 static int
135Data(ap, type, d, c)
136 Authenticator *ap;
137 int type;
138 Voidptr d;
139 int c;
140{
141 unsigned char *p = str_data + 4;
142 unsigned char *cd = (unsigned char *)d;
143
144 if (c == -1)
145 c = strlen((char *)cd);
146
147 if (auth_debug_mode) {
148 printf("%s:%d: [%d] (%d)",
149 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
150 str_data[3],
151 type, c);
152 printd(d, c);
153 printf("\r\n");
154 }
155 *p++ = ap->type;
156 *p++ = ap->way;
157 *p++ = type;
158 while (c-- > 0) {
159 if ((*p++ = *cd++) == IAC)
160 *p++ = IAC;
161 }
162 *p++ = IAC;
163 *p++ = SE;
164 if (str_data[3] == TELQUAL_IS)
165 printsub('>', &str_data[2], p - &str_data[2]);
166 return(net_write(str_data, p - str_data));
167}
168
169 int
170kerberos5_init(ap, server)
171 Authenticator *ap;
172 int server;
173{
174 if (server)
175 str_data[3] = TELQUAL_REPLY;
176 else
177 str_data[3] = TELQUAL_IS;
178 krb5_init_ets();
179 return(1);
180}
181
182 int
183kerberos5_send(ap)
184 Authenticator *ap;
185{
186 char **realms;
187 char *name;
188 char *p1, *p2;
189 krb5_checksum ksum;
190 krb5_octet sum[CRC32_CKSUM_LENGTH];
191 krb5_principal server;
192 krb5_error_code r;
193 krb5_ccache ccache;
194 krb5_creds creds; /* telnet gets session key from here */
195 extern krb5_flags krb5_kdc_default_options;
196 int ap_opts;
197
198#ifdef ENCRYPTION
199 krb5_keyblock *newkey = 0;
200#endif /* ENCRYPTION */
201
202 ksum.checksum_type = CKSUMTYPE_CRC32;
203 ksum.contents = sum;
204 ksum.length = sizeof(sum);
205 memset((Voidptr )sum, 0, sizeof(sum));
206
207 if (!UserNameRequested) {
208 if (auth_debug_mode) {
209 printf("Kerberos V5: no user name supplied\r\n");
210 }
211 return(0);
212 }
213
214 if (r = krb5_cc_default(&ccache)) {
215 if (auth_debug_mode) {
216 printf("Kerberos V5: could not get default ccache\r\n");
217 }
218 return(0);
219 }
220
221 if ((name = malloc(strlen(RemoteHostName)+1)) == NULL) {
222 if (auth_debug_mode)
223 printf("Out of memory for hostname in Kerberos V5\r\n");
224 return(0);
225 }
226
227 if (r = krb5_get_host_realm(RemoteHostName, &realms)) {
228 if (auth_debug_mode)
229 printf("Kerberos V5: no realm for %s\r\n", RemoteHostName);
230 free(name);
231 return(0);
232 }
233
234 p1 = RemoteHostName;
235 p2 = name;
236
237 while (*p2 = *p1++) {
238 if (isupper(*p2))
239 *p2 |= 040;
240 ++p2;
241 }
242
243 if (r = krb5_build_principal_ext(&server,
244 strlen(realms[0]), realms[0],
245 4, "host",
246 p2 - name, name,
247 0)) {
248 if (auth_debug_mode) {
249 printf("Kerberos V5: failure setting up principal (%s)\r\n",
250 error_message(r));
251 }
252 free(name);
253 krb5_free_host_realm(realms);
254 return(0);
255 }
256
257
258 memset((char *)&creds, 0, sizeof(creds));
259 creds.server = server;
260
261 if (r = krb5_cc_get_principal(ccache, &creds.client)) {
262 if (auth_debug_mode) {
263 printf("Kerberos V5: failure on principal (%s)\r\n",
264 error_message(r));
265 }
266 free(name);
267 krb5_free_principal(server);
268 krb5_free_host_realm(realms);
269 return(0);
270 }
271
272 if (r = krb5_get_credentials(krb5_kdc_default_options, ccache, &creds)) {
273 if (auth_debug_mode) {
274 printf("Kerberos V5: failure on credentials(%d)\r\n",r);
275 }
276 free(name);
277 krb5_free_host_realm(realms);
278 krb5_free_principal(server);
279 return(0);
280 }
281
282 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
283 ap_opts = AP_OPTS_MUTUAL_REQUIRED;
284 else
285 ap_opts = 0;
286
287 r = krb5_mk_req_extended(ap_opts, &ksum, krb5_kdc_default_options, 0,
288#ifdef ENCRYPTION
289 &newkey,
290#else /* ENCRYPTION */
291 0,
292#endif /* ENCRYPTION */
293 ccache, &creds, &authenticator, &auth);
294 /* don't let the key get freed if we clean up the authenticator */
295 authenticator.subkey = 0;
296
297 free(name);
298 krb5_free_host_realm(realms);
299 krb5_free_principal(server);
300#ifdef ENCRYPTION
301 if (newkey) {
302 /* keep the key in our private storage, but don't use it
303 yet---see kerberos5_reply() below */
304 if (newkey->keytype != KEYTYPE_DES) {
305 if (creds.keyblock.keytype == KEYTYPE_DES)
306 /* use the session key in credentials instead */
307 memmove((char *)session_key,
308 (char *)creds.keyblock.contents, sizeof(Block));
309 else
310 /* XXX ? */;
311 } else {
312 memmove((char *)session_key, (char *)newkey->contents,
313 sizeof(Block));
314 }
315 krb5_free_keyblock(newkey);
316 }
317#endif /* ENCRYPTION */
318 if (r) {
319 if (auth_debug_mode) {
320 printf("Kerberos V5: mk_req failed (%s)\r\n",
321 error_message(r));
322 }
323 return(0);
324 }
325
326 if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
327 if (auth_debug_mode)
328 printf("Not enough room for user name\r\n");
329 return(0);
330 }
331 if (!Data(ap, KRB_AUTH, auth.data, auth.length)) {
332 if (auth_debug_mode)
333 printf("Not enough room for authentication data\r\n");
334 return(0);
335 }
336 if (auth_debug_mode) {
337 printf("Sent Kerberos V5 credentials to server\r\n");
338 }
339 return(1);
340}
341
342 void
343kerberos5_is(ap, data, cnt)
344 Authenticator *ap;
345 unsigned char *data;
346 int cnt;
347{
348 int r;
349 struct hostent *hp;
350 char *p1, *p2;
351 static char *realm = NULL;
352 krb5_principal server;
353 krb5_ap_rep_enc_part reply;
354 krb5_data outbuf;
355#ifdef ENCRYPTION
356 Session_Key skey;
357#endif /* ENCRYPTION */
358 char *name;
359 char *getenv();
360 krb5_data inbuf;
361
362 if (cnt-- < 1)
363 return;
364 switch (*data++) {
365 case KRB_AUTH:
366 auth.data = (char *)data;
367 auth.length = cnt;
368
369 if (!(hp = gethostbyname(LocalHostName))) {
370 if (auth_debug_mode)
371 printf("Cannot resolve local host name\r\n");
372 Data(ap, KRB_REJECT, "Unknown local hostname.", -1);
373 auth_finished(ap, AUTH_REJECT);
374 return;
375 }
376
377 if (!realm && (krb5_get_default_realm(&realm))) {
378 if (auth_debug_mode)
379 printf("Could not get default realm\r\n");
380 Data(ap, KRB_REJECT, "Could not get default realm.", -1);
381 auth_finished(ap, AUTH_REJECT);
382 return;
383 }
384
385 if ((name = malloc(strlen(hp->h_name)+1)) == NULL) {
386 if (auth_debug_mode)
387 printf("Out of memory for hostname in Kerberos V5\r\n");
388 Data(ap, KRB_REJECT, "Out of memory.", -1);
389 auth_finished(ap, AUTH_REJECT);
390 return;
391 }
392
393 p1 = hp->h_name;
394 p2 = name;
395
396 while (*p2 = *p1++) {
397 if (isupper(*p2))
398 *p2 |= 040;
399 ++p2;
400 }
401
402 if (authdat)
403 krb5_free_tkt_authent(authdat);
404
405 r = krb5_build_principal_ext(&server,
406 strlen(realm), realm,
407 4, "host",
408 p2 - name, name,
409 0);
410 if (!r) {
411 r = krb5_rd_req_simple(&auth, server, 0, &authdat);
412 krb5_free_principal(server);
413 }
414 if (r) {
415 char errbuf[128];
416
417 errout:
418 authdat = 0;
419 (void) strcpy(errbuf, "Read req failed: ");
420 (void) strcat(errbuf, error_message(r));
421 Data(ap, KRB_REJECT, errbuf, -1);
422 if (auth_debug_mode)
423 printf("%s\r\n", errbuf);
424 return;
425 }
426 free(name);
427 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
428 /* do ap_rep stuff here */
429 reply.ctime = authdat->authenticator->ctime;
430 reply.cusec = authdat->authenticator->cusec;
431 reply.subkey = 0; /* use the one he gave us, so don't
432 need to return one here */
433 reply.seq_number = 0; /* we don't do seq #'s. */
434
435 if (r = krb5_mk_rep(&reply,
436 authdat->authenticator->subkey ?
437 authdat->authenticator->subkey :
438 authdat->ticket->enc_part2->session,
439 &outbuf)) {
440 goto errout;
441 }
442 Data(ap, KRB_RESPONSE, outbuf.data, outbuf.length);
443 }
444 if (krb5_unparse_name(authdat->ticket->enc_part2 ->client,
445 &name))
446 name = 0;
447 Data(ap, KRB_ACCEPT, name, name ? -1 : 0);
448 if (auth_debug_mode) {
449 printf("Kerberos5 identifies him as ``%s''\r\n",
450 name ? name : "");
451 }
452 auth_finished(ap, AUTH_USER);
453
454 free(name);
455 if (authdat->authenticator->subkey &&
456 authdat->authenticator->subkey->keytype == KEYTYPE_DES) {
457 memmove((Voidptr )session_key,
458 (Voidptr )authdat->authenticator->subkey->contents,
459 sizeof(Block));
460 } else if (authdat->ticket->enc_part2->session->keytype ==
461 KEYTYPE_DES) {
462 memmove((Voidptr )session_key,
463 (Voidptr )authdat->ticket->enc_part2->session->contents,
464 sizeof(Block));
465 } else
466 break;
467
468#ifdef ENCRYPTION
469 skey.type = SK_DES;
470 skey.length = 8;
471 skey.data = session_key;
472 encrypt_session_key(&skey, 1);
473#endif /* ENCRYPTION */
474 break;
475#ifdef FORWARD
476 case KRB_FORWARD:
477 inbuf.data = (char *)data;
478 inbuf.length = cnt;
479 if (r = rd_and_store_for_creds(&inbuf, authdat->ticket,
480 UserNameRequested)) {
481 char errbuf[128];
482
483 (void) strcpy(errbuf, "Read forwarded creds failed: ");
484 (void) strcat(errbuf, error_message(r));
485 Data(ap, KRB_FORWARD_REJECT, errbuf, -1);
486 if (auth_debug_mode)
487 printf("Could not read forwarded credentials\r\n");
488 }
489 else
490 Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
491 if (auth_debug_mode)
492 printf("Forwarded credentials obtained\r\n");
493 break;
494#endif /* FORWARD */
495 default:
496 if (auth_debug_mode)
497 printf("Unknown Kerberos option %d\r\n", data[-1]);
498 Data(ap, KRB_REJECT, 0, 0);
499 break;
500 }
501}
502
503 void
504kerberos5_reply(ap, data, cnt)
505 Authenticator *ap;
506 unsigned char *data;
507 int cnt;
508{
509 Session_Key skey;
510 static int mutual_complete = 0;
511
512 if (cnt-- < 1)
513 return;
514 switch (*data++) {
515 case KRB_REJECT:
516 if (cnt > 0) {
517 printf("[ Kerberos V5 refuses authentication because %.*s ]\r\n",
518 cnt, data);
519 } else
520 printf("[ Kerberos V5 refuses authentication ]\r\n");
521 auth_send_retry();
522 return;
523 case KRB_ACCEPT:
524 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
525 !mutual_complete) {
526 printf("[ Kerberos V5 accepted you, but didn't provide mutual authentication! ]\n");
527 auth_send_retry();
528 return;
529 }
530 if (cnt)
531 printf("[ Kerberos V5 accepts you as ``%.*s'' ]\n", cnt, data);
532 else
533 printf("[ Kerberos V5 accepts you ]\n");
534 auth_finished(ap, AUTH_USER);
535#ifdef FORWARD
536 if (forward_flags & OPTS_FORWARD_CREDS)
537 kerberos5_forward(ap);
538#endif /* FORWARD */
539 break;
540 case KRB_RESPONSE:
541 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
542 /* the rest of the reply should contain a krb_ap_rep */
543 krb5_ap_rep_enc_part *reply;
544 krb5_data inbuf;
545 krb5_error_code r;
546 krb5_keyblock tmpkey;
547
548 inbuf.length = cnt;
549 inbuf.data = (char *)data;
550
551 tmpkey.keytype = KEYTYPE_DES;
552 tmpkey.contents = session_key;
553 tmpkey.length = sizeof(Block);
554
555 if (r = krb5_rd_rep(&inbuf, &tmpkey, &reply)) {
556 printf("[ Mutual authentication failed: %s ]\n",
557 error_message(r));
558 auth_send_retry();
559 return;
560 }
561 if (reply->ctime != authenticator.ctime ||
562 reply->cusec != authenticator.cusec) {
563 printf("[ Mutual authentication failed (mismatched KRB_AP_REP) ]\n");
564 auth_send_retry();
565 return;
566 }
567 krb5_free_ap_rep_enc_part(reply);
568#ifdef ENCRYPTION
569 skey.type = SK_DES;
570 skey.length = 8;
571 skey.data = session_key;
572 encrypt_session_key(&skey, 0);
573#endif /* ENCRYPTION */
574 mutual_complete = 1;
575 }
576 return;
577#ifdef FORWARD
578 case KRB_FORWARD_ACCEPT:
579 printf("[ Kerberos V5 accepted forwarded credentials ]\n");
580 return;
581 case KRB_FORWARD_REJECT:
582 printf("[ Kerberos V5 refuses forwarded credentials because %.*s ]\r\n",
583 cnt, data);
584 return;
585#endif /* FORWARD */
586 default:
587 if (auth_debug_mode)
588 printf("Unknown Kerberos option %d\r\n", data[-1]);
589 return;
590 }
591}
592
593 int
594kerberos5_status(ap, name, level)
595 Authenticator *ap;
596 char *name;
597 int level;
598{
599 if (level < AUTH_USER)
600 return(level);
601
602 if (UserNameRequested &&
603 krb5_kuserok(authdat->ticket->enc_part2->client, UserNameRequested))
604 {
605 strcpy(name, UserNameRequested);
606 return(AUTH_VALID);
607 } else
608 return(AUTH_USER);
609}
610
611#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
612#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
613
614 void
615kerberos5_printsub(data, cnt, buf, buflen)
616 unsigned char *data, *buf;
617 int cnt, buflen;
618{
619 char lbuf[32];
620 register int i;
621
622 buf[buflen-1] = '\0'; /* make sure its NULL terminated */
623 buflen -= 1;
624
625 switch(data[3]) {
626 case KRB_REJECT: /* Rejected (reason might follow) */
627 strncpy((char *)buf, " REJECT ", buflen);
628 goto common;
629
630 case KRB_ACCEPT: /* Accepted (name might follow) */
631 strncpy((char *)buf, " ACCEPT ", buflen);
632 common:
633 BUMP(buf, buflen);
634 if (cnt <= 4)
635 break;
636 ADDC(buf, buflen, '"');
637 for (i = 4; i < cnt; i++)
638 ADDC(buf, buflen, data[i]);
639 ADDC(buf, buflen, '"');
640 ADDC(buf, buflen, '\0');
641 break;
642
643
644 case KRB_AUTH: /* Authentication data follows */
645 strncpy((char *)buf, " AUTH", buflen);
646 goto common2;
647
648 case KRB_RESPONSE:
649 strncpy((char *)buf, " RESPONSE", buflen);
650 goto common2;
651
652#ifdef FORWARD
653 case KRB_FORWARD: /* Forwarded credentials follow */
654 strncpy((char *)buf, " FORWARD", buflen);
655 goto common2;
656
657 case KRB_FORWARD_ACCEPT: /* Forwarded credentials accepted */
658 strncpy((char *)buf, " FORWARD_ACCEPT", buflen);
659 goto common2;
660
661 case KRB_FORWARD_REJECT: /* Forwarded credentials rejected */
662 /* (reason might follow) */
663 strncpy((char *)buf, " FORWARD_REJECT", buflen);
664 goto common2;
665#endif /* FORWARD */
666
667 default:
668 sprintf(lbuf, " %d (unknown)", data[3]);
669 strncpy((char *)buf, lbuf, buflen);
670 common2:
671 BUMP(buf, buflen);
672 for (i = 4; i < cnt; i++) {
673 sprintf(lbuf, " %d", data[i]);
674 strncpy((char *)buf, lbuf, buflen);
675 BUMP(buf, buflen);
676 }
677 break;
678 }
679}
680
681#ifdef FORWARD
682 void
683kerberos5_forward(ap)
684 Authenticator *ap;
685{
686 struct hostent *hp;
687 krb5_creds *local_creds;
688 krb5_error_code r;
689 krb5_data forw_creds;
690 extern krb5_cksumtype krb5_kdc_req_sumtype;
691 krb5_ccache ccache;
692 int i;
693
694 if (!(local_creds = (krb5_creds *)
695 calloc(1, sizeof(*local_creds)))) {
696 if (auth_debug_mode)
697 printf("Kerberos V5: could not allocate memory for credentials\r\n");
698 return;
699 }
700
701 if (r = krb5_sname_to_principal(RemoteHostName, "host", 1,
702 &local_creds->server)) {
703 if (auth_debug_mode)
704 printf("Kerberos V5: could not build server name - %s\r\n",
705 error_message(r));
706 krb5_free_creds(local_creds);
707 return;
708 }
709
710 if (r = krb5_cc_default(&ccache)) {
711 if (auth_debug_mode)
712 printf("Kerberos V5: could not get default ccache - %s\r\n",
713 error_message(r));
714 krb5_free_creds(local_creds);
715 return;
716 }
717
718 if (r = krb5_cc_get_principal(ccache, &local_creds->client)) {
719 if (auth_debug_mode)
720 printf("Kerberos V5: could not get default principal - %s\r\n",
721 error_message(r));
722 krb5_free_creds(local_creds);
723 return;
724 }
725
726 /* Get ticket from credentials cache */
727 if (r = krb5_get_credentials(KRB5_GC_CACHED, ccache, local_creds)) {
728 if (auth_debug_mode)
729 printf("Kerberos V5: could not obtain credentials - %s\r\n",
730 error_message(r));
731 krb5_free_creds(local_creds);
732 return;
733 }
734
735 if (r = get_for_creds(ETYPE_DES_CBC_CRC,
736 krb5_kdc_req_sumtype,
737 RemoteHostName,
738 local_creds->client,
739 &local_creds->keyblock,
740 forward_flags & OPTS_FORWARDABLE_CREDS,
741 &forw_creds)) {
742 if (auth_debug_mode)
743 printf("Kerberos V5: error getting forwarded creds - %s\r\n",
744 error_message(r));
745 krb5_free_creds(local_creds);
746 return;
747 }
748
749 /* Send forwarded credentials */
750 if (!Data(ap, KRB_FORWARD, forw_creds.data, forw_creds.length)) {
751 if (auth_debug_mode)
752 printf("Not enough room for authentication data\r\n");
753 }
754 else {
755 if (auth_debug_mode)
756 printf("Forwarded local Kerberos V5 credentials to server\r\n");
757 }
758
759 krb5_free_creds(local_creds);
760}
761#endif /* FORWARD */
762
763#endif /* KRB5 */