2 * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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
36 __RCSID("$Heimdal: kaserver.c 21654 2007-07-21 17:30:18Z lha $"
39 #include <krb5-v4compat.h>
42 #define KA_AUTHENTICATION_SERVICE 731
43 #define KA_TICKET_GRANTING_SERVICE 732
44 #define KA_MAINTENANCE_SERVICE 733
46 #define AUTHENTICATE_OLD 1
47 #define CHANGEPASSWORD 2
48 #define GETTICKET_OLD 3
57 #define GETPASSWORD 12
58 #define GETRANDOMKEY 13
59 #define AUTHENTICATE 21
60 #define AUTHENTICATE_V2 22
63 /* XXX - Where do we get these? */
65 #define RXGEN_OPCODE (-455)
67 #define KADATABASEINCONSISTENT (180480L)
68 #define KAEXIST (180481L)
69 #define KAIO (180482L)
70 #define KACREATEFAIL (180483L)
71 #define KANOENT (180484L)
72 #define KAEMPTY (180485L)
73 #define KABADNAME (180486L)
74 #define KABADINDEX (180487L)
75 #define KANOAUTH (180488L)
76 #define KAANSWERTOOLONG (180489L)
77 #define KABADREQUEST (180490L)
78 #define KAOLDINTERFACE (180491L)
79 #define KABADARGUMENT (180492L)
80 #define KABADCMD (180493L)
81 #define KANOKEYS (180494L)
82 #define KAREADPW (180495L)
83 #define KABADKEY (180496L)
84 #define KAUBIKINIT (180497L)
85 #define KAUBIKCALL (180498L)
86 #define KABADPROTOCOL (180499L)
87 #define KANOCELLS (180500L)
88 #define KANOCELL (180501L)
89 #define KATOOMANYUBIKS (180502L)
90 #define KATOOMANYKEYS (180503L)
91 #define KABADTICKET (180504L)
92 #define KAUNKNOWNKEY (180505L)
93 #define KAKEYCACHEINVALID (180506L)
94 #define KABADSERVER (180507L)
95 #define KABADUSER (180508L)
96 #define KABADCPW (180509L)
97 #define KABADCREATE (180510L)
98 #define KANOTICKET (180511L)
99 #define KAASSOCUSER (180512L)
100 #define KANOTSPECIAL (180513L)
101 #define KACLOCKSKEW (180514L)
102 #define KANORECURSE (180515L)
103 #define KARXFAIL (180516L)
104 #define KANULLPASSWORD (180517L)
105 #define KAINTERNALERROR (180518L)
106 #define KAPWEXPIRED (180519L)
107 #define KAREUSED (180520L)
108 #define KATOOSOON (180521L)
109 #define KALOCKED (180522L)
112 static krb5_error_code
113 decode_rx_header (krb5_storage
*sp
,
118 ret
= krb5_ret_uint32(sp
, &h
->epoch
);
120 ret
= krb5_ret_uint32(sp
, &h
->connid
);
122 ret
= krb5_ret_uint32(sp
, &h
->callid
);
124 ret
= krb5_ret_uint32(sp
, &h
->seqno
);
126 ret
= krb5_ret_uint32(sp
, &h
->serialno
);
128 ret
= krb5_ret_uint8(sp
, &h
->type
);
130 ret
= krb5_ret_uint8(sp
, &h
->flags
);
132 ret
= krb5_ret_uint8(sp
, &h
->status
);
134 ret
= krb5_ret_uint8(sp
, &h
->secindex
);
136 ret
= krb5_ret_uint16(sp
, &h
->reserved
);
138 ret
= krb5_ret_uint16(sp
, &h
->serviceid
);
144 static krb5_error_code
145 encode_rx_header (struct rx_header
*h
,
150 ret
= krb5_store_uint32(sp
, h
->epoch
);
152 ret
= krb5_store_uint32(sp
, h
->connid
);
154 ret
= krb5_store_uint32(sp
, h
->callid
);
156 ret
= krb5_store_uint32(sp
, h
->seqno
);
158 ret
= krb5_store_uint32(sp
, h
->serialno
);
160 ret
= krb5_store_uint8(sp
, h
->type
);
162 ret
= krb5_store_uint8(sp
, h
->flags
);
164 ret
= krb5_store_uint8(sp
, h
->status
);
166 ret
= krb5_store_uint8(sp
, h
->secindex
);
168 ret
= krb5_store_uint16(sp
, h
->reserved
);
170 ret
= krb5_store_uint16(sp
, h
->serviceid
);
177 init_reply_header (struct rx_header
*hdr
,
178 struct rx_header
*reply_hdr
,
182 reply_hdr
->epoch
= hdr
->epoch
;
183 reply_hdr
->connid
= hdr
->connid
;
184 reply_hdr
->callid
= hdr
->callid
;
185 reply_hdr
->seqno
= 1;
186 reply_hdr
->serialno
= 1;
187 reply_hdr
->type
= type
;
188 reply_hdr
->flags
= flags
;
189 reply_hdr
->status
= 0;
190 reply_hdr
->secindex
= 0;
191 reply_hdr
->reserved
= 0;
192 reply_hdr
->serviceid
= hdr
->serviceid
;
196 * Create an error `reply´ using for the packet `hdr' with the error
200 make_error_reply (struct rx_header
*hdr
,
205 struct rx_header reply_hdr
;
209 init_reply_header (hdr
, &reply_hdr
, HT_ABORT
, HF_LAST
);
210 sp
= krb5_storage_emem();
213 ret
= encode_rx_header (&reply_hdr
, sp
);
216 krb5_store_int32(sp
, error
);
217 krb5_storage_to_data (sp
, reply
);
218 krb5_storage_free (sp
);
221 static krb5_error_code
222 krb5_ret_xdr_data(krb5_storage
*sp
,
227 ret
= krb5_ret_int32(sp
, &size
);
235 size_t pad
= (4 - size
% 4) % 4;
237 data
->data
= malloc(size
);
238 if (data
->data
== NULL
)
240 ret
= krb5_storage_read(sp
, data
->data
, size
);
242 return (ret
< 0)? errno
: KRB5_CC_END
;
244 ret
= krb5_storage_read(sp
, foo
, pad
);
246 return (ret
< 0)? errno
: KRB5_CC_END
;
253 static krb5_error_code
254 krb5_store_xdr_data(krb5_storage
*sp
,
257 u_char zero
[4] = {0, 0, 0, 0};
261 ret
= krb5_store_int32(sp
, data
.length
);
264 ret
= krb5_storage_write(sp
, data
.data
, data
.length
);
265 if(ret
!= data
.length
){
270 pad
= (4 - data
.length
% 4) % 4;
272 ret
= krb5_storage_write(sp
, zero
, pad
);
283 static krb5_error_code
284 create_reply_ticket (krb5_context context
,
285 struct rx_header
*hdr
,
287 char *name
, char *instance
, char *realm
,
288 struct sockaddr_in
*addr
,
292 const char *sname
, const char *sinstance
,
300 krb5_keyblock session
;
303 struct rx_header reply_hdr
;
306 unsigned fyrtiosjuelva
;
308 /* create the ticket */
310 krb5_generate_random_keyblock(context
, ETYPE_DES_PCBC_NONE
, &session
);
312 _krb5_krb_create_ticket(context
,
317 addr
->sin_addr
.s_addr
,
326 /* create the encrypted part of the reply */
327 sp
= krb5_storage_emem ();
328 krb5_generate_random_block(&fyrtiosjuelva
, sizeof(fyrtiosjuelva
));
329 fyrtiosjuelva
&= 0xffffffff;
330 krb5_store_int32 (sp
, fyrtiosjuelva
);
331 krb5_store_int32 (sp
, challenge
);
332 krb5_storage_write (sp
, session
.keyvalue
.data
, 8);
333 krb5_free_keyblock_contents(context
, &session
);
334 krb5_store_int32 (sp
, kdc_time
);
335 krb5_store_int32 (sp
, kdc_time
+ _krb5_krb_life_to_time (0, life
));
336 krb5_store_int32 (sp
, kvno
);
337 krb5_store_int32 (sp
, ticket
.length
);
338 krb5_store_stringz (sp
, name
);
339 krb5_store_stringz (sp
, instance
);
340 #if 1 /* XXX - Why shouldn't the realm go here? */
341 krb5_store_stringz (sp
, "");
343 krb5_store_stringz (sp
, realm
);
345 krb5_store_stringz (sp
, sname
);
346 krb5_store_stringz (sp
, sinstance
);
347 krb5_storage_write (sp
, ticket
.data
, ticket
.length
);
348 krb5_storage_write (sp
, label
, strlen(label
));
350 /* pad to DES block */
351 memset (zero
, 0, sizeof(zero
));
352 pad
= (8 - krb5_storage_seek (sp
, 0, SEEK_CUR
) % 8) % 8;
353 krb5_storage_write (sp
, zero
, pad
);
355 krb5_storage_to_data (sp
, &enc_data
);
356 krb5_storage_free (sp
);
358 if (enc_data
.length
> max_seq_len
) {
359 krb5_data_free (&enc_data
);
360 make_error_reply (hdr
, KAANSWERTOOLONG
, reply
);
366 DES_key_schedule schedule
;
369 memcpy (&deskey
, key
->keyvalue
.data
, sizeof(deskey
));
370 DES_set_key (&deskey
, &schedule
);
371 DES_pcbc_encrypt (enc_data
.data
,
377 memset (&schedule
, 0, sizeof(schedule
));
378 memset (&deskey
, 0, sizeof(deskey
));
381 /* create the reply packet */
382 init_reply_header (hdr
, &reply_hdr
, HT_DATA
, HF_LAST
);
383 sp
= krb5_storage_emem ();
384 ret
= encode_rx_header (&reply_hdr
, sp
);
385 krb5_store_int32 (sp
, max_seq_len
);
386 krb5_store_xdr_data (sp
, enc_data
);
387 krb5_data_free (&enc_data
);
388 krb5_storage_to_data (sp
, reply
);
389 krb5_storage_free (sp
);
393 static krb5_error_code
394 unparse_auth_args (krb5_storage
*sp
,
400 int32_t *max_seq_len
)
405 krb5_ret_xdr_data (sp
, &data
);
406 *name
= malloc(data
.length
+ 1);
409 memcpy (*name
, data
.data
, data
.length
);
410 (*name
)[data
.length
] = '\0';
411 krb5_data_free (&data
);
413 krb5_ret_xdr_data (sp
, &data
);
414 *instance
= malloc(data
.length
+ 1);
415 if (*instance
== NULL
) {
419 memcpy (*instance
, data
.data
, data
.length
);
420 (*instance
)[data
.length
] = '\0';
421 krb5_data_free (&data
);
423 krb5_ret_int32 (sp
, &tmp
);
425 krb5_ret_int32 (sp
, &tmp
);
427 krb5_ret_xdr_data (sp
, request
);
428 krb5_ret_int32 (sp
, max_seq_len
);
429 /* ignore the rest */
434 do_authenticate (krb5_context context
,
435 krb5_kdc_configuration
*config
,
436 struct rx_header
*hdr
,
438 struct sockaddr_in
*addr
,
444 char *instance
= NULL
;
449 hdb_entry_ex
*client_entry
= NULL
;
450 hdb_entry_ex
*server_entry
= NULL
;
453 krb5_storage
*reply_sp
;
457 char client_name
[256];
458 char server_name
[256];
460 krb5_data_zero (&request
);
462 ret
= unparse_auth_args (sp
, &name
, &instance
, &start_time
, &end_time
,
463 &request
, &max_seq_len
);
464 if (ret
!= 0 || request
.length
< 8) {
465 make_error_reply (hdr
, KABADREQUEST
, reply
);
469 snprintf (client_name
, sizeof(client_name
), "%s.%s@%s",
470 name
, instance
, config
->v4_realm
);
471 snprintf (server_name
, sizeof(server_name
), "%s.%s@%s",
472 "krbtgt", config
->v4_realm
, config
->v4_realm
);
474 kdc_log(context
, config
, 0, "AS-REQ (kaserver) %s from %s for %s",
475 client_name
, from
, server_name
);
477 ret
= _kdc_db_fetch4 (context
, config
, name
, instance
,
478 config
->v4_realm
, HDB_F_GET_CLIENT
,
481 kdc_log(context
, config
, 0, "Client not found in database: %s: %s",
482 client_name
, krb5_get_err_text(context
, ret
));
483 make_error_reply (hdr
, KANOENT
, reply
);
487 ret
= _kdc_db_fetch4 (context
, config
, "krbtgt",
488 config
->v4_realm
, config
->v4_realm
,
489 HDB_F_GET_KRBTGT
, &server_entry
);
491 kdc_log(context
, config
, 0, "Server not found in database: %s: %s",
492 server_name
, krb5_get_err_text(context
, ret
));
493 make_error_reply (hdr
, KANOENT
, reply
);
497 ret
= _kdc_check_flags (context
, config
,
498 client_entry
, client_name
,
499 server_entry
, server_name
,
502 make_error_reply (hdr
, KAPWEXPIRED
, reply
);
507 ret
= _kdc_get_des_key(context
, client_entry
, FALSE
, TRUE
, &ckey
);
509 kdc_log(context
, config
, 0, "no suitable DES key for client");
510 make_error_reply (hdr
, KANOKEYS
, reply
);
515 ret
= _kdc_get_des_key(context
, server_entry
, TRUE
, TRUE
, &skey
);
517 kdc_log(context
, config
, 0, "no suitable DES key for server");
518 make_error_reply (hdr
, KANOKEYS
, reply
);
524 DES_key_schedule schedule
;
526 /* try to decode the `request' */
527 memcpy (&key
, ckey
->key
.keyvalue
.data
, sizeof(key
));
528 DES_set_key (&key
, &schedule
);
529 DES_pcbc_encrypt (request
.data
,
535 memset (&schedule
, 0, sizeof(schedule
));
536 memset (&key
, 0, sizeof(key
));
539 /* check for the magic label */
540 if (memcmp ((char *)request
.data
+ 4, "gTGS", 4) != 0) {
541 kdc_log(context
, config
, 0, "preauth failed for %s", client_name
);
542 make_error_reply (hdr
, KABADREQUEST
, reply
);
546 reply_sp
= krb5_storage_from_mem (request
.data
, 4);
547 krb5_ret_int32 (reply_sp
, &chal
);
548 krb5_storage_free (reply_sp
);
550 if (abs(chal
- kdc_time
) > context
->max_skew
) {
551 make_error_reply (hdr
, KACLOCKSKEW
, reply
);
556 max_life
= end_time
- kdc_time
;
557 /* end_time - kdc_time can sometimes be non-positive due to slight
558 time skew between client and server. Let's make sure it is postive */
561 if (client_entry
->entry
.max_life
)
562 max_life
= min(max_life
, *client_entry
->entry
.max_life
);
563 if (server_entry
->entry
.max_life
)
564 max_life
= min(max_life
, *server_entry
->entry
.max_life
);
566 life
= krb_time_to_life(kdc_time
, kdc_time
+ max_life
);
568 create_reply_ticket (context
,
570 name
, instance
, config
->v4_realm
,
571 addr
, life
, server_entry
->entry
.kvno
,
573 "krbtgt", config
->v4_realm
,
578 if (request
.length
) {
579 memset (request
.data
, 0, request
.length
);
580 krb5_data_free (&request
);
587 _kdc_free_ent (context
, client_entry
);
589 _kdc_free_ent (context
, server_entry
);
592 static krb5_error_code
593 unparse_getticket_args (krb5_storage
*sp
,
600 int32_t *max_seq_len
)
605 krb5_ret_int32 (sp
, &tmp
);
608 krb5_ret_xdr_data (sp
, &data
);
609 *auth_domain
= malloc(data
.length
+ 1);
610 if (*auth_domain
== NULL
)
612 memcpy (*auth_domain
, data
.data
, data
.length
);
613 (*auth_domain
)[data
.length
] = '\0';
614 krb5_data_free (&data
);
616 krb5_ret_xdr_data (sp
, ticket
);
618 krb5_ret_xdr_data (sp
, &data
);
619 *name
= malloc(data
.length
+ 1);
624 memcpy (*name
, data
.data
, data
.length
);
625 (*name
)[data
.length
] = '\0';
626 krb5_data_free (&data
);
628 krb5_ret_xdr_data (sp
, &data
);
629 *instance
= malloc(data
.length
+ 1);
630 if (*instance
== NULL
) {
635 memcpy (*instance
, data
.data
, data
.length
);
636 (*instance
)[data
.length
] = '\0';
637 krb5_data_free (&data
);
639 krb5_ret_xdr_data (sp
, times
);
641 krb5_ret_int32 (sp
, max_seq_len
);
642 /* ignore the rest */
647 do_getticket (krb5_context context
,
648 krb5_kdc_configuration
*config
,
649 struct rx_header
*hdr
,
651 struct sockaddr_in
*addr
,
657 char *auth_domain
= NULL
;
660 char *instance
= NULL
;
663 hdb_entry_ex
*server_entry
= NULL
;
664 hdb_entry_ex
*client_entry
= NULL
;
665 hdb_entry_ex
*krbtgt_entry
= NULL
;
669 DES_key_schedule schedule
;
673 time_t start_time
, end_time
;
674 char server_name
[256];
675 char client_name
[256];
676 struct _krb5_krb_auth_data ad
;
678 krb5_data_zero (&aticket
);
679 krb5_data_zero (×
);
681 memset(&ad
, 0, sizeof(ad
));
683 unparse_getticket_args (sp
, &kvno
, &auth_domain
, &aticket
,
684 &name
, &instance
, ×
, &max_seq_len
);
685 if (times
.length
< 8) {
686 make_error_reply (hdr
, KABADREQUEST
, reply
);
691 snprintf (server_name
, sizeof(server_name
),
692 "%s.%s@%s", name
, instance
, config
->v4_realm
);
694 ret
= _kdc_db_fetch4 (context
, config
, name
, instance
,
695 config
->v4_realm
, HDB_F_GET_SERVER
, &server_entry
);
697 kdc_log(context
, config
, 0, "Server not found in database: %s: %s",
698 server_name
, krb5_get_err_text(context
, ret
));
699 make_error_reply (hdr
, KANOENT
, reply
);
703 ret
= _kdc_db_fetch4 (context
, config
, "krbtgt",
704 config
->v4_realm
, config
->v4_realm
, HDB_F_GET_KRBTGT
, &krbtgt_entry
);
706 kdc_log(context
, config
, 0,
707 "Server not found in database: %s.%s@%s: %s",
708 "krbtgt", config
->v4_realm
, config
->v4_realm
,
709 krb5_get_err_text(context
, ret
));
710 make_error_reply (hdr
, KANOENT
, reply
);
715 ret
= _kdc_get_des_key(context
, krbtgt_entry
, TRUE
, TRUE
, &kkey
);
717 kdc_log(context
, config
, 0, "no suitable DES key for krbtgt");
718 make_error_reply (hdr
, KANOKEYS
, reply
);
723 ret
= _kdc_get_des_key(context
, server_entry
, TRUE
, TRUE
, &skey
);
725 kdc_log(context
, config
, 0, "no suitable DES key for server");
726 make_error_reply (hdr
, KANOKEYS
, reply
);
730 /* decrypt the incoming ticket */
731 memcpy (&key
, kkey
->key
.keyvalue
.data
, sizeof(key
));
733 /* unpack the ticket */
736 char *sinstance
= NULL
;
738 ret
= _krb5_krb_decomp_ticket(context
, &aticket
, &kkey
->key
,
739 config
->v4_realm
, &sname
,
742 kdc_log(context
, config
, 0,
743 "kaserver: decomp failed for %s.%s with %d",
744 sname
, sinstance
, ret
);
745 make_error_reply (hdr
, KABADTICKET
, reply
);
749 if (strcmp (sname
, "krbtgt") != 0
750 || strcmp (sinstance
, config
->v4_realm
) != 0) {
751 kdc_log(context
, config
, 0, "no TGT: %s.%s for %s.%s@%s",
753 ad
.pname
, ad
.pinst
, ad
.prealm
);
754 make_error_reply (hdr
, KABADTICKET
, reply
);
762 if (kdc_time
> _krb5_krb_life_to_time(ad
.time_sec
, ad
.life
)) {
763 kdc_log(context
, config
, 0, "TGT expired: %s.%s@%s",
764 ad
.pname
, ad
.pinst
, ad
.prealm
);
765 make_error_reply (hdr
, KABADTICKET
, reply
);
770 snprintf (client_name
, sizeof(client_name
),
771 "%s.%s@%s", ad
.pname
, ad
.pinst
, ad
.prealm
);
773 kdc_log(context
, config
, 0, "TGS-REQ (kaserver) %s from %s for %s",
774 client_name
, from
, server_name
);
776 ret
= _kdc_db_fetch4 (context
, config
,
777 ad
.pname
, ad
.pinst
, ad
.prealm
, HDB_F_GET_CLIENT
,
779 if(ret
&& ret
!= HDB_ERR_NOENTRY
) {
780 kdc_log(context
, config
, 0,
781 "Client not found in database: (krb4) %s: %s",
782 client_name
, krb5_get_err_text(context
, ret
));
783 make_error_reply (hdr
, KANOENT
, reply
);
786 if (client_entry
== NULL
&& strcmp(ad
.prealm
, config
->v4_realm
) == 0) {
787 kdc_log(context
, config
, 0,
788 "Local client not found in database: (krb4) "
790 make_error_reply (hdr
, KANOENT
, reply
);
794 ret
= _kdc_check_flags (context
, config
,
795 client_entry
, client_name
,
796 server_entry
, server_name
,
799 make_error_reply (hdr
, KAPWEXPIRED
, reply
);
803 /* decrypt the times */
804 memcpy(&session
, ad
.session
.keyvalue
.data
, sizeof(session
));
805 DES_set_key (&session
, &schedule
);
806 DES_ecb_encrypt (times
.data
,
810 memset (&schedule
, 0, sizeof(schedule
));
811 memset (&session
, 0, sizeof(session
));
813 /* and extract them */
818 tsp
= krb5_storage_from_mem (times
.data
, times
.length
);
819 krb5_ret_int32 (tsp
, &tmp
);
821 krb5_ret_int32 (tsp
, &tmp
);
823 krb5_storage_free (tsp
);
827 max_life
= end_time
- kdc_time
;
828 /* end_time - kdc_time can sometimes be non-positive due to slight
829 time skew between client and server. Let's make sure it is postive */
832 if (krbtgt_entry
->entry
.max_life
)
833 max_life
= min(max_life
, *krbtgt_entry
->entry
.max_life
);
834 if (server_entry
->entry
.max_life
)
835 max_life
= min(max_life
, *server_entry
->entry
.max_life
);
836 /* if this is a cross realm request, the client_entry will likely
838 if (client_entry
&& client_entry
->entry
.max_life
)
839 max_life
= min(max_life
, *client_entry
->entry
.max_life
);
841 life
= _krb5_krb_time_to_life(kdc_time
, kdc_time
+ max_life
);
843 create_reply_ticket (context
,
845 ad
.pname
, ad
.pinst
, ad
.prealm
,
846 addr
, life
, server_entry
->entry
.kvno
,
853 _krb5_krb_free_auth_data(context
, &ad
);
854 if (aticket
.length
) {
855 memset (aticket
.data
, 0, aticket
.length
);
856 krb5_data_free (&aticket
);
859 memset (times
.data
, 0, times
.length
);
860 krb5_data_free (×
);
869 _kdc_free_ent (context
, krbtgt_entry
);
871 _kdc_free_ent (context
, server_entry
);
875 _kdc_do_kaserver(krb5_context context
,
876 krb5_kdc_configuration
*config
,
881 struct sockaddr_in
*addr
)
883 krb5_error_code ret
= 0;
884 struct rx_header hdr
;
888 if (len
< RX_HEADER_SIZE
)
890 sp
= krb5_storage_from_mem (buf
, len
);
892 ret
= decode_rx_header (sp
, &hdr
);
895 buf
+= RX_HEADER_SIZE
;
896 len
-= RX_HEADER_SIZE
;
914 if (hdr
.serviceid
!= KA_AUTHENTICATION_SERVICE
915 && hdr
.serviceid
!= KA_TICKET_GRANTING_SERVICE
) {
920 ret
= krb5_ret_uint32(sp
, &op
);
925 case AUTHENTICATE_V2
:
926 do_authenticate (context
, config
, &hdr
, sp
, addr
, from
, reply
);
929 do_getticket (context
, config
, &hdr
, sp
, addr
, from
, reply
);
931 case AUTHENTICATE_OLD
:
932 case CHANGEPASSWORD
:
945 make_error_reply (&hdr
, RXGEN_OPCODE
, reply
);
950 krb5_storage_free (sp
);