2
* Copyright (c) 1991, 1993
3
* The Regents of the University of California. All rights reserved.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. All advertising materials mentioning features or use of this software
14
* must display the following acknowledgement:
15
* This product includes software developed by the University of
16
* California, Berkeley and its contributors.
17
* 4. Neither the name of the University nor the names of its contributors
18
* may be used to endorse or promote products derived from this software
19
* without specific prior written permission.
21
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
/* based on @(#)kerberos.c 8.1 (Berkeley) 6/4/93 */
37
* Copyright (C) 1990 by the Massachusetts Institute of Technology
39
* Export of this software from the United States of America may
40
* require a specific license from the United States Government.
41
* It is the responsibility of any person or organization contemplating
42
* export to obtain such a license before exporting.
44
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
45
* distribute this software and its documentation for any purpose and
46
* without fee is hereby granted, provided that the above copyright
47
* notice appear in all copies and that both that copyright notice and
48
* this permission notice appear in supporting documentation, and that
49
* the name of M.I.T. not be used in advertising or publicity pertaining
50
* to distribution of the software without specific, written prior
51
* permission. Furthermore if you modify this software you must label
52
* your software as modified software and not distribute it in such a
53
* fashion that it might be confused with the original M.I.T. software.
54
* M.I.T. makes no representations about the suitability of
55
* this software for any purpose. It is provided "as is" without express
56
* or implied warranty.
60
* Copyright (C) 1998 by the FundsXpress, INC.
62
* All rights reserved.
64
* Export of this software from the United States of America may require
65
* a specific license from the United States Government. It is the
66
* responsibility of any person or organization contemplating export to
67
* obtain such a license before exporting.
69
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
70
* distribute this software and its documentation for any purpose and
71
* without fee is hereby granted, provided that the above copyright
72
* notice appear in all copies and that both that copyright notice and
73
* this permission notice appear in supporting documentation, and that
74
* the name of FundsXpress. not be used in advertising or publicity pertaining
75
* to distribution of the software without specific, written prior
76
* permission. FundsXpress makes no representations about the suitability of
77
* this software for any purpose. It is provided "as is" without express
78
* or implied warranty.
80
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
81
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
82
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
86
/* this code must be compiled in the krb5 tree. disgustingly, there
87
is code in here which declares structures which happen to mirror
88
the krb4 des structures. I didn't want to rototill this *completely*
89
so this is how it's going to work. --marc */
91
#include <sys/types.h>
93
#include <arpa/telnet.h>
95
#include <des.h> /* BSD wont include this in krb.h, so we do it here */
110
extern int auth_debug_mode;
111
extern krb5_context telnet_context;
113
int kerberos4_cksum (unsigned char *, int);
115
static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
116
AUTHTYPE_KERBEROS_V4, };
118
static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
122
#define KRB_AUTH 0 /* Authentication data follows */
123
#define KRB_REJECT 1 /* Rejected (reason might follow) */
124
#define KRB_ACCEPT 2 /* Accepted */
125
#define KRB_CHALLENGE 3 /* Challenge for mutual auth. */
126
#define KRB_RESPONSE 4 /* Response for mutual auth. */
128
#define KRB_SERVICE_NAME "rcmd"
130
static KTEXT_ST auth;
131
static char name[ANAME_SZ];
132
static AUTH_DAT adat = { 0 };
134
static Block session_key = { 0 };
135
static krb5_keyblock krbkey;
136
static Block challenge = { 0 };
137
#endif /* ENCRYPTION */
146
unsigned char *p = str_data + 4;
147
const unsigned char *cd = (const unsigned char *)d;
148
size_t spaceleft = sizeof(str_data) - 4;
150
c = strlen((const char *)cd);
152
if (auth_debug_mode) {
153
printf("%s:%d: [%d] (%d)",
154
str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
165
if ((*p++ = *cd++) == IAC) {
169
if ((--spaceleft < 4) && c) {
176
if (str_data[3] == TELQUAL_IS)
177
printsub('>', &str_data[2], p - (&str_data[2]));
178
return(net_write(str_data, p - str_data));
182
kerberos4_init(ap, server)
189
str_data[3] = TELQUAL_REPLY;
190
if ((fp = fopen(KEYFILE, "r")) == NULL)
194
str_data[3] = TELQUAL_IS;
197
kerberos5_init(NULL, server);
202
char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
203
unsigned int dst_realm_sz = REALM_SZ;
210
char instance[INST_SZ];
212
char *krb_realmofhost();
213
char *krb_get_phost();
218
krb5_enc_data encdata;
219
krb5_error_code code;
220
krb5_keyblock rand_key;
223
printf("[ Trying KERBEROS4 ... ]\r\n");
224
if (!UserNameRequested) {
225
if (auth_debug_mode) {
226
printf("Kerberos V4: no user name supplied\r\n");
231
memset(instance, 0, sizeof(instance));
233
if ((realm = krb_get_phost(RemoteHostName)))
234
strncpy(instance, realm, sizeof(instance));
236
instance[sizeof(instance)-1] = '\0';
238
realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);
241
printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
244
if ((r = krb_mk_req(&kauth, KRB_SERVICE_NAME, instance, realm, 0))) {
245
printf("mk_req failed: %s\r\n", krb_get_err_text(r));
248
if ((r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred))) {
249
printf("get_cred failed: %s\r\n", krb_get_err_text(r));
252
if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
254
printf("Not enough room for user name\r\n");
258
printf("Sent %d bytes of authentication data\r\n", kauth.length);
259
if (!Data(ap, KRB_AUTH, (void *)kauth.dat, kauth.length)) {
261
printf("Not enough room for authentication data\r\n");
266
* If we are doing mutual authentication, get set up to send
267
* the challenge, and verify it when the response comes back.
269
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
272
data.data = cred.session;
273
data.length = 8; /* sizeof(cred.session) */;
275
if ((code = krb5_c_random_seed(telnet_context, &data))) {
276
com_err("libtelnet", code,
277
"while seeding random number generator");
281
if ((code = krb5_c_make_random_key(telnet_context,
284
com_err("libtelnet", code,
285
"while creating random session key");
289
/* the krb4 code uses ecb mode, but on a single block
290
with a zero ivec, ecb and cbc are the same */
291
krbkey.enctype = ENCTYPE_DES_CBC_RAW;
293
krbkey.contents = cred.session;
295
encdata.ciphertext.data = rand_key.contents;
296
encdata.ciphertext.length = rand_key.length;
297
encdata.enctype = ENCTYPE_UNKNOWN;
299
data.data = session_key;
302
code = krb5_c_decrypt(telnet_context, &krbkey, 0, 0,
305
krb5_free_keyblock_contents(telnet_context, &rand_key);
308
com_err("libtelnet", code, "while encrypting random key");
312
encdata.ciphertext.data = session_key;
313
encdata.ciphertext.length = 8;
314
encdata.enctype = ENCTYPE_UNKNOWN;
316
data.data = challenge;
319
code = krb5_c_decrypt(telnet_context, &krbkey, 0, 0,
323
* Increment the challenge by 1, and encrypt it for
326
for (i = 7; i >= 0; --i) {
328
x = (unsigned int)challenge[i] + 1;
329
challenge[i] = x; /* ignore overflow */
330
if (x < 256) /* if no overflow, all done */
334
data.data = challenge;
337
encdata.ciphertext.data = challenge;
338
encdata.ciphertext.length = 8;
339
encdata.enctype = ENCTYPE_UNKNOWN;
341
if ((code = krb5_c_encrypt(telnet_context, &krbkey, 0, 0,
343
com_err("libtelnet", code, "while encrypting random key");
347
#endif /* ENCRYPTION */
349
if (auth_debug_mode) {
350
printf("CK: %d:", kerberos4_cksum(kauth.dat, kauth.length));
351
printd(kauth.dat, kauth.length);
353
printf("Sent Kerberos V4 credentials to server\r\n");
359
kerberos4_is(ap, data, cnt)
366
Block datablock, tmpkey;
368
krb5_enc_data encdata;
369
krb5_error_code code;
370
#endif /* ENCRYPTION */
371
char realm[REALM_SZ];
372
char instance[INST_SZ];
379
if (krb_get_lrealm(realm, 1) != KSUCCESS) {
380
Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1);
381
auth_finished(ap, AUTH_REJECT);
383
printf("No local realm\r\n");
386
memcpy((void *)auth.dat, (void *)data, auth.length = cnt);
387
if (auth_debug_mode) {
388
printf("Got %d bytes of authentication data\r\n", cnt);
389
printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
390
printd(auth.dat, auth.length);
393
instance[0] = '*'; instance[1] = 0;
394
if ((r = krb_rd_req(&auth, KRB_SERVICE_NAME,
395
instance, 0, &adat, ""))) {
397
printf("Kerberos failed him as %s\r\n", name);
398
Data(ap, KRB_REJECT, (const void *)krb_get_err_text(r), -1);
399
auth_finished(ap, AUTH_REJECT);
403
memcpy((void *)session_key, (void *)adat.session, sizeof(Block));
404
#endif /* ENCRYPTION */
405
krb_kntoln(&adat, name);
407
if (UserNameRequested && !kuserok(&adat, UserNameRequested))
408
Data(ap, KRB_ACCEPT, (void *)0, 0);
411
(void *)"user is not authorized", -1);
412
auth_finished(ap, AUTH_USER);
417
Data(ap, KRB_RESPONSE, (void *)0, 0);
418
#else /* ENCRYPTION */
419
if (!VALIDKEY(session_key)) {
421
* We don't have a valid session key, so just
422
* send back a response with an empty session
425
Data(ap, KRB_RESPONSE, (void *)0, 0);
430
* Initialize the random number generator since it's
431
* used later on by the encryption routine.
434
kdata.data = session_key;
437
if ((code = krb5_c_random_seed(telnet_context, &kdata))) {
438
com_err("libtelnet", code,
439
"while seeding random number generator");
443
memcpy((void *)datablock, (void *)data, sizeof(Block));
445
* Take the received encrypted challenge, and encrypt
446
* it again to get a unique session_key for the
449
krbkey.enctype = ENCTYPE_DES_CBC_RAW;
451
krbkey.contents = session_key;
453
kdata.data = datablock;
456
encdata.ciphertext.data = tmpkey;
457
encdata.ciphertext.length = 8;
458
encdata.enctype = ENCTYPE_UNKNOWN;
460
if ((code = krb5_c_encrypt(telnet_context, &krbkey, 0, 0,
461
&kdata, &encdata))) {
462
com_err("libtelnet", code, "while encrypting random key");
469
encrypt_session_key(&skey, 1);
471
* Now decrypt the received encrypted challenge,
472
* increment by one, re-encrypt it and send it back.
474
encdata.ciphertext.data = datablock;
475
encdata.ciphertext.length = 8;
476
encdata.enctype = ENCTYPE_UNKNOWN;
478
kdata.data = challenge;
481
if ((code = krb5_c_decrypt(telnet_context, &krbkey, 0, 0,
482
&encdata, &kdata))) {
483
com_err("libtelnet", code, "while decrypting challenge");
487
for (r = 7; r >= 0; r--) {
489
t = (unsigned int)challenge[r] + 1;
490
challenge[r] = t; /* ignore overflow */
491
if (t < 256) /* if no overflow, all done */
495
kdata.data = challenge;
498
encdata.ciphertext.data = challenge;
499
encdata.ciphertext.length = 8;
500
encdata.enctype = ENCTYPE_UNKNOWN;
502
if ((code = krb5_c_encrypt(telnet_context, &krbkey, 0, 0,
503
&kdata, &encdata))) {
504
com_err("libtelnet", code, "while decrypting challenge");
508
Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge));
509
#endif /* ENCRYPTION */
514
printf("Unknown Kerberos option %d\r\n", data[-1]);
515
Data(ap, KRB_REJECT, 0, 0);
521
kerberos4_reply(ap, data, cnt)
529
krb5_enc_data encdata;
530
krb5_error_code code;
532
#endif /* ENCRYPTION */
539
printf("[ Kerberos V4 refuses authentication because %.*s ]\r\n",
542
printf("[ Kerberos V4 refuses authentication ]\r\n");
546
printf("[ Kerberos V4 accepts you ]\r\n");
547
if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
549
* Send over the encrypted challenge.
552
Data(ap, KRB_CHALLENGE, (void *)0, 0);
553
#else /* ENCRYPTION */
554
Data(ap, KRB_CHALLENGE, (void *)session_key,
555
sizeof(session_key));
557
kdata.data = session_key;
560
encdata.ciphertext.data = session_key;
561
encdata.ciphertext.length = 8;
562
encdata.enctype = ENCTYPE_UNKNOWN;
564
if ((code = krb5_c_encrypt(telnet_context, &krbkey,
565
0, 0, &kdata, &encdata))) {
566
com_err("libtelnet", code,
567
"while encrypting session_key");
573
skey.data = session_key;
574
encrypt_session_key(&skey, 0);
575
#endif /* ENCRYPTION */
578
auth_finished(ap, AUTH_USER);
583
* Verify that the response to the challenge is correct.
585
if ((cnt != sizeof(Block)) ||
586
(0 != memcmp((void *)data, (void *)challenge,
589
#endif /* ENCRYPTION */
590
printf("[ Kerberos V4 challenge failed!!! ]\r\n");
595
printf("[ Kerberos V4 challenge successful ]\r\n");
596
auth_finished(ap, AUTH_USER);
597
#endif /* ENCRYPTION */
601
printf("Unknown Kerberos option %d\r\n", data[-1]);
607
kerberos4_status(ap, kname, level)
612
if (level < AUTH_USER)
616
* Always copy in UserNameRequested if the authentication
617
* is valid, because the higher level routines need it.
619
if (UserNameRequested) {
620
/* the name buffer comes from telnetd/telnetd{-ktd}.c */
621
strncpy(kname, UserNameRequested, 255);
625
if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
631
#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
632
#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
635
kerberos4_printsub(data, cnt, buf, buflen)
636
unsigned char *data, *buf;
643
buf[buflen-1] = '\0'; /* make sure its NULL terminated */
647
case KRB_REJECT: /* Rejected (reason might follow) */
648
strncpy((char *)buf, " REJECT ", buflen);
651
case KRB_ACCEPT: /* Accepted (name might follow) */
652
strncpy((char *)buf, " ACCEPT ", buflen);
657
ADDC(buf, buflen, '"');
658
for (i = 4; i < cnt; i++)
659
ADDC(buf, buflen, data[i]);
660
ADDC(buf, buflen, '"');
661
ADDC(buf, buflen, '\0');
664
case KRB_AUTH: /* Authentication data follows */
665
strncpy((char *)buf, " AUTH", buflen);
669
strncpy((char *)buf, " CHALLENGE", buflen);
673
strncpy((char *)buf, " RESPONSE", buflen);
677
sprintf(lbuf, " %d (unknown)", data[3]);
678
strncpy((char *)buf, lbuf, buflen);
681
for (i = 4; i < cnt; i++) {
682
sprintf(lbuf, " %d", data[i]);
683
strncpy((char *)buf, lbuf, buflen);
691
kerberos4_cksum(d, n)
698
* A comment is probably needed here for those not
699
* well versed in the "C" language. Yes, this is
700
* supposed to be a "switch" with the body of the
701
* "switch" being a "while" statement. The whole
702
* purpose of the switch is to allow us to jump into
703
* the middle of the while() loop, and then not have
704
* to do any more switch()s.
706
* Some compilers will spit out a warning message
707
* about the loop not being entered at the top.
712
ck ^= (int)*d++ << 24;
715
ck ^= (int)*d++ << 16;
718
ck ^= (int)*d++ << 8;
740
for (i = 0; i < 8; i++)
741
printf(" %3d", key[i]);