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