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
38 #include <krb5-v4compat.h>
41 #define KA_AUTHENTICATION_SERVICE 731
42 #define KA_TICKET_GRANTING_SERVICE 732
43 #define KA_MAINTENANCE_SERVICE 733
45 #define AUTHENTICATE_OLD 1
46 #define CHANGEPASSWORD 2
47 #define GETTICKET_OLD 3
56 #define GETPASSWORD 12
57 #define GETRANDOMKEY 13
58 #define AUTHENTICATE 21
59 #define AUTHENTICATE_V2 22
62 /* XXX - Where do we get these? */
64 #define RXGEN_OPCODE (-455)
66 #define KADATABASEINCONSISTENT (180480L)
67 #define KAEXIST (180481L)
68 #define KAIO (180482L)
69 #define KACREATEFAIL (180483L)
70 #define KANOENT (180484L)
71 #define KAEMPTY (180485L)
72 #define KABADNAME (180486L)
73 #define KABADINDEX (180487L)
74 #define KANOAUTH (180488L)
75 #define KAANSWERTOOLONG (180489L)
76 #define KABADREQUEST (180490L)
77 #define KAOLDINTERFACE (180491L)
78 #define KABADARGUMENT (180492L)
79 #define KABADCMD (180493L)
80 #define KANOKEYS (180494L)
81 #define KAREADPW (180495L)
82 #define KABADKEY (180496L)
83 #define KAUBIKINIT (180497L)
84 #define KAUBIKCALL (180498L)
85 #define KABADPROTOCOL (180499L)
86 #define KANOCELLS (180500L)
87 #define KANOCELL (180501L)
88 #define KATOOMANYUBIKS (180502L)
89 #define KATOOMANYKEYS (180503L)
90 #define KABADTICKET (180504L)
91 #define KAUNKNOWNKEY (180505L)
92 #define KAKEYCACHEINVALID (180506L)
93 #define KABADSERVER (180507L)
94 #define KABADUSER (180508L)
95 #define KABADCPW (180509L)
96 #define KABADCREATE (180510L)
97 #define KANOTICKET (180511L)
98 #define KAASSOCUSER (180512L)
99 #define KANOTSPECIAL (180513L)
100 #define KACLOCKSKEW (180514L)
101 #define KANORECURSE (180515L)
102 #define KARXFAIL (180516L)
103 #define KANULLPASSWORD (180517L)
104 #define KAINTERNALERROR (180518L)
105 #define KAPWEXPIRED (180519L)
106 #define KAREUSED (180520L)
107 #define KATOOSOON (180521L)
108 #define KALOCKED (180522L)
111 static krb5_error_code
112 decode_rx_header (krb5_storage
*sp
,
117 ret
= krb5_ret_uint32(sp
, &h
->epoch
);
119 ret
= krb5_ret_uint32(sp
, &h
->connid
);
121 ret
= krb5_ret_uint32(sp
, &h
->callid
);
123 ret
= krb5_ret_uint32(sp
, &h
->seqno
);
125 ret
= krb5_ret_uint32(sp
, &h
->serialno
);
127 ret
= krb5_ret_uint8(sp
, &h
->type
);
129 ret
= krb5_ret_uint8(sp
, &h
->flags
);
131 ret
= krb5_ret_uint8(sp
, &h
->status
);
133 ret
= krb5_ret_uint8(sp
, &h
->secindex
);
135 ret
= krb5_ret_uint16(sp
, &h
->reserved
);
137 ret
= krb5_ret_uint16(sp
, &h
->serviceid
);
143 static krb5_error_code
144 encode_rx_header (struct rx_header
*h
,
149 ret
= krb5_store_uint32(sp
, h
->epoch
);
151 ret
= krb5_store_uint32(sp
, h
->connid
);
153 ret
= krb5_store_uint32(sp
, h
->callid
);
155 ret
= krb5_store_uint32(sp
, h
->seqno
);
157 ret
= krb5_store_uint32(sp
, h
->serialno
);
159 ret
= krb5_store_uint8(sp
, h
->type
);
161 ret
= krb5_store_uint8(sp
, h
->flags
);
163 ret
= krb5_store_uint8(sp
, h
->status
);
165 ret
= krb5_store_uint8(sp
, h
->secindex
);
167 ret
= krb5_store_uint16(sp
, h
->reserved
);
169 ret
= krb5_store_uint16(sp
, h
->serviceid
);
176 init_reply_header (struct rx_header
*hdr
,
177 struct rx_header
*reply_hdr
,
181 reply_hdr
->epoch
= hdr
->epoch
;
182 reply_hdr
->connid
= hdr
->connid
;
183 reply_hdr
->callid
= hdr
->callid
;
184 reply_hdr
->seqno
= 1;
185 reply_hdr
->serialno
= 1;
186 reply_hdr
->type
= type
;
187 reply_hdr
->flags
= flags
;
188 reply_hdr
->status
= 0;
189 reply_hdr
->secindex
= 0;
190 reply_hdr
->reserved
= 0;
191 reply_hdr
->serviceid
= hdr
->serviceid
;
195 * Create an error `reply´ using for the packet `hdr' with the error
199 make_error_reply (struct rx_header
*hdr
,
204 struct rx_header reply_hdr
;
208 init_reply_header (hdr
, &reply_hdr
, HT_ABORT
, HF_LAST
);
209 sp
= krb5_storage_emem();
212 ret
= encode_rx_header (&reply_hdr
, sp
);
215 krb5_store_int32(sp
, error
);
216 krb5_storage_to_data (sp
, reply
);
217 krb5_storage_free (sp
);
220 static krb5_error_code
221 krb5_ret_xdr_data(krb5_storage
*sp
,
226 ret
= krb5_ret_int32(sp
, &size
);
234 size_t pad
= (4 - size
% 4) % 4;
236 data
->data
= malloc(size
);
237 if (data
->data
== NULL
)
239 ret
= krb5_storage_read(sp
, data
->data
, size
);
241 return (ret
< 0)? errno
: KRB5_CC_END
;
243 ret
= krb5_storage_read(sp
, foo
, pad
);
245 return (ret
< 0)? errno
: KRB5_CC_END
;
252 static krb5_error_code
253 krb5_store_xdr_data(krb5_storage
*sp
,
256 u_char zero
[4] = {0, 0, 0, 0};
260 ret
= krb5_store_int32(sp
, data
.length
);
263 ret
= krb5_storage_write(sp
, data
.data
, data
.length
);
264 if(ret
!= data
.length
){
269 pad
= (4 - data
.length
% 4) % 4;
271 ret
= krb5_storage_write(sp
, zero
, pad
);
282 static krb5_error_code
283 create_reply_ticket (krb5_context context
,
284 struct rx_header
*hdr
,
286 char *name
, char *instance
, char *realm
,
287 struct sockaddr_in
*addr
,
291 const char *sname
, const char *sinstance
,
299 krb5_keyblock session
;
302 struct rx_header reply_hdr
;
305 unsigned fyrtiosjuelva
;
307 /* create the ticket */
309 krb5_generate_random_keyblock(context
, ETYPE_DES_PCBC_NONE
, &session
);
311 _krb5_krb_create_ticket(context
,
316 addr
->sin_addr
.s_addr
,
325 /* create the encrypted part of the reply */
326 sp
= krb5_storage_emem ();
327 krb5_generate_random_block(&fyrtiosjuelva
, sizeof(fyrtiosjuelva
));
328 fyrtiosjuelva
&= 0xffffffff;
329 krb5_store_int32 (sp
, fyrtiosjuelva
);
330 krb5_store_int32 (sp
, challenge
);
331 krb5_storage_write (sp
, session
.keyvalue
.data
, 8);
332 krb5_free_keyblock_contents(context
, &session
);
333 krb5_store_int32 (sp
, kdc_time
);
334 krb5_store_int32 (sp
, kdc_time
+ _krb5_krb_life_to_time (0, life
));
335 krb5_store_int32 (sp
, kvno
);
336 krb5_store_int32 (sp
, ticket
.length
);
337 krb5_store_stringz (sp
, name
);
338 krb5_store_stringz (sp
, instance
);
339 #if 1 /* XXX - Why shouldn't the realm go here? */
340 krb5_store_stringz (sp
, "");
342 krb5_store_stringz (sp
, realm
);
344 krb5_store_stringz (sp
, sname
);
345 krb5_store_stringz (sp
, sinstance
);
346 krb5_storage_write (sp
, ticket
.data
, ticket
.length
);
347 krb5_storage_write (sp
, label
, strlen(label
));
349 /* pad to DES block */
350 memset (zero
, 0, sizeof(zero
));
351 pad
= (8 - krb5_storage_seek (sp
, 0, SEEK_CUR
) % 8) % 8;
352 krb5_storage_write (sp
, zero
, pad
);
354 krb5_storage_to_data (sp
, &enc_data
);
355 krb5_storage_free (sp
);
357 if (enc_data
.length
> max_seq_len
) {
358 krb5_data_free (&enc_data
);
359 make_error_reply (hdr
, KAANSWERTOOLONG
, reply
);
365 DES_key_schedule schedule
;
368 memcpy (&deskey
, key
->keyvalue
.data
, sizeof(deskey
));
369 DES_set_key_unchecked (&deskey
, &schedule
);
370 DES_pcbc_encrypt (enc_data
.data
,
376 memset (&schedule
, 0, sizeof(schedule
));
377 memset (&deskey
, 0, sizeof(deskey
));
380 /* create the reply packet */
381 init_reply_header (hdr
, &reply_hdr
, HT_DATA
, HF_LAST
);
382 sp
= krb5_storage_emem ();
383 ret
= encode_rx_header (&reply_hdr
, sp
);
384 krb5_store_int32 (sp
, max_seq_len
);
385 krb5_store_xdr_data (sp
, enc_data
);
386 krb5_data_free (&enc_data
);
387 krb5_storage_to_data (sp
, reply
);
388 krb5_storage_free (sp
);
392 static krb5_error_code
393 unparse_auth_args (krb5_storage
*sp
,
399 int32_t *max_seq_len
)
404 krb5_ret_xdr_data (sp
, &data
);
405 *name
= malloc(data
.length
+ 1);
408 memcpy (*name
, data
.data
, data
.length
);
409 (*name
)[data
.length
] = '\0';
410 krb5_data_free (&data
);
412 krb5_ret_xdr_data (sp
, &data
);
413 *instance
= malloc(data
.length
+ 1);
414 if (*instance
== NULL
) {
418 memcpy (*instance
, data
.data
, data
.length
);
419 (*instance
)[data
.length
] = '\0';
420 krb5_data_free (&data
);
422 krb5_ret_int32 (sp
, &tmp
);
424 krb5_ret_int32 (sp
, &tmp
);
426 krb5_ret_xdr_data (sp
, request
);
427 krb5_ret_int32 (sp
, max_seq_len
);
428 /* ignore the rest */
433 do_authenticate (krb5_context context
,
434 krb5_kdc_configuration
*config
,
435 struct rx_header
*hdr
,
437 struct sockaddr_in
*addr
,
443 char *instance
= NULL
;
448 hdb_entry_ex
*client_entry
= NULL
;
449 hdb_entry_ex
*server_entry
= NULL
;
452 krb5_storage
*reply_sp
;
456 char client_name
[256];
457 char server_name
[256];
459 krb5_data_zero (&request
);
461 ret
= unparse_auth_args (sp
, &name
, &instance
, &start_time
, &end_time
,
462 &request
, &max_seq_len
);
463 if (ret
!= 0 || request
.length
< 8) {
464 make_error_reply (hdr
, KABADREQUEST
, reply
);
468 snprintf (client_name
, sizeof(client_name
), "%s.%s@%s",
469 name
, instance
, config
->v4_realm
);
470 snprintf (server_name
, sizeof(server_name
), "%s.%s@%s",
471 "krbtgt", config
->v4_realm
, config
->v4_realm
);
473 kdc_log(context
, config
, 0, "AS-REQ (kaserver) %s from %s for %s",
474 client_name
, from
, server_name
);
476 ret
= _kdc_db_fetch4 (context
, config
, name
, instance
,
477 config
->v4_realm
, HDB_F_GET_CLIENT
,
480 kdc_log(context
, config
, 0, "Client not found in database: %s: %s",
481 client_name
, krb5_get_err_text(context
, ret
));
482 make_error_reply (hdr
, KANOENT
, reply
);
486 ret
= _kdc_db_fetch4 (context
, config
, "krbtgt",
487 config
->v4_realm
, config
->v4_realm
,
488 HDB_F_GET_KRBTGT
, &server_entry
);
490 kdc_log(context
, config
, 0, "Server not found in database: %s: %s",
491 server_name
, krb5_get_err_text(context
, ret
));
492 make_error_reply (hdr
, KANOENT
, reply
);
496 ret
= kdc_check_flags (context
, config
,
497 client_entry
, client_name
,
498 server_entry
, server_name
,
501 make_error_reply (hdr
, KAPWEXPIRED
, reply
);
506 ret
= _kdc_get_des_key(context
, client_entry
, FALSE
, TRUE
, &ckey
);
508 kdc_log(context
, config
, 0, "no suitable DES key for client");
509 make_error_reply (hdr
, KANOKEYS
, reply
);
514 ret
= _kdc_get_des_key(context
, server_entry
, TRUE
, TRUE
, &skey
);
516 kdc_log(context
, config
, 0, "no suitable DES key for server");
517 make_error_reply (hdr
, KANOKEYS
, reply
);
523 DES_key_schedule schedule
;
525 /* try to decode the `request' */
526 memcpy (&key
, ckey
->key
.keyvalue
.data
, sizeof(key
));
527 DES_set_key_unchecked (&key
, &schedule
);
528 DES_pcbc_encrypt (request
.data
,
534 memset (&schedule
, 0, sizeof(schedule
));
535 memset (&key
, 0, sizeof(key
));
538 /* check for the magic label */
539 if (memcmp ((char *)request
.data
+ 4, "gTGS", 4) != 0) {
540 kdc_log(context
, config
, 0, "preauth failed for %s", client_name
);
541 make_error_reply (hdr
, KABADREQUEST
, reply
);
545 reply_sp
= krb5_storage_from_mem (request
.data
, 4);
546 krb5_ret_int32 (reply_sp
, &chal
);
547 krb5_storage_free (reply_sp
);
549 if (abs(chal
- kdc_time
) > context
->max_skew
) {
550 make_error_reply (hdr
, KACLOCKSKEW
, reply
);
555 max_life
= end_time
- kdc_time
;
556 /* end_time - kdc_time can sometimes be non-positive due to slight
557 time skew between client and server. Let's make sure it is postive */
560 if (client_entry
->entry
.max_life
)
561 max_life
= min(max_life
, *client_entry
->entry
.max_life
);
562 if (server_entry
->entry
.max_life
)
563 max_life
= min(max_life
, *server_entry
->entry
.max_life
);
565 life
= krb_time_to_life(kdc_time
, kdc_time
+ max_life
);
567 create_reply_ticket (context
,
569 name
, instance
, config
->v4_realm
,
570 addr
, life
, server_entry
->entry
.kvno
,
572 "krbtgt", config
->v4_realm
,
577 if (request
.length
) {
578 memset (request
.data
, 0, request
.length
);
579 krb5_data_free (&request
);
586 _kdc_free_ent (context
, client_entry
);
588 _kdc_free_ent (context
, server_entry
);
591 static krb5_error_code
592 unparse_getticket_args (krb5_storage
*sp
,
599 int32_t *max_seq_len
)
604 krb5_ret_int32 (sp
, &tmp
);
607 krb5_ret_xdr_data (sp
, &data
);
608 *auth_domain
= malloc(data
.length
+ 1);
609 if (*auth_domain
== NULL
)
611 memcpy (*auth_domain
, data
.data
, data
.length
);
612 (*auth_domain
)[data
.length
] = '\0';
613 krb5_data_free (&data
);
615 krb5_ret_xdr_data (sp
, ticket
);
617 krb5_ret_xdr_data (sp
, &data
);
618 *name
= malloc(data
.length
+ 1);
623 memcpy (*name
, data
.data
, data
.length
);
624 (*name
)[data
.length
] = '\0';
625 krb5_data_free (&data
);
627 krb5_ret_xdr_data (sp
, &data
);
628 *instance
= malloc(data
.length
+ 1);
629 if (*instance
== NULL
) {
634 memcpy (*instance
, data
.data
, data
.length
);
635 (*instance
)[data
.length
] = '\0';
636 krb5_data_free (&data
);
638 krb5_ret_xdr_data (sp
, times
);
640 krb5_ret_int32 (sp
, max_seq_len
);
641 /* ignore the rest */
646 do_getticket (krb5_context context
,
647 krb5_kdc_configuration
*config
,
648 struct rx_header
*hdr
,
650 struct sockaddr_in
*addr
,
656 char *auth_domain
= NULL
;
659 char *instance
= NULL
;
662 hdb_entry_ex
*server_entry
= NULL
;
663 hdb_entry_ex
*client_entry
= NULL
;
664 hdb_entry_ex
*krbtgt_entry
= NULL
;
668 DES_key_schedule schedule
;
672 time_t start_time
, end_time
;
673 char server_name
[256];
674 char client_name
[256];
675 struct _krb5_krb_auth_data ad
;
677 krb5_data_zero (&aticket
);
678 krb5_data_zero (×
);
680 memset(&ad
, 0, sizeof(ad
));
682 unparse_getticket_args (sp
, &kvno
, &auth_domain
, &aticket
,
683 &name
, &instance
, ×
, &max_seq_len
);
684 if (times
.length
< 8) {
685 make_error_reply (hdr
, KABADREQUEST
, reply
);
690 snprintf (server_name
, sizeof(server_name
),
691 "%s.%s@%s", name
, instance
, config
->v4_realm
);
693 ret
= _kdc_db_fetch4 (context
, config
, name
, instance
,
694 config
->v4_realm
, HDB_F_GET_SERVER
, &server_entry
);
696 kdc_log(context
, config
, 0, "Server not found in database: %s: %s",
697 server_name
, krb5_get_err_text(context
, ret
));
698 make_error_reply (hdr
, KANOENT
, reply
);
702 ret
= _kdc_db_fetch4 (context
, config
, "krbtgt",
703 config
->v4_realm
, config
->v4_realm
, HDB_F_GET_KRBTGT
, &krbtgt_entry
);
705 kdc_log(context
, config
, 0,
706 "Server not found in database: %s.%s@%s: %s",
707 "krbtgt", config
->v4_realm
, config
->v4_realm
,
708 krb5_get_err_text(context
, ret
));
709 make_error_reply (hdr
, KANOENT
, reply
);
714 ret
= _kdc_get_des_key(context
, krbtgt_entry
, TRUE
, TRUE
, &kkey
);
716 kdc_log(context
, config
, 0, "no suitable DES key for krbtgt");
717 make_error_reply (hdr
, KANOKEYS
, reply
);
722 ret
= _kdc_get_des_key(context
, server_entry
, TRUE
, TRUE
, &skey
);
724 kdc_log(context
, config
, 0, "no suitable DES key for server");
725 make_error_reply (hdr
, KANOKEYS
, reply
);
729 /* decrypt the incoming ticket */
730 memcpy (&key
, kkey
->key
.keyvalue
.data
, sizeof(key
));
732 /* unpack the ticket */
735 char *sinstance
= NULL
;
737 ret
= _krb5_krb_decomp_ticket(context
, &aticket
, &kkey
->key
,
738 config
->v4_realm
, &sname
,
741 kdc_log(context
, config
, 0,
742 "kaserver: decomp failed for %s.%s with %d",
743 sname
, sinstance
, ret
);
744 make_error_reply (hdr
, KABADTICKET
, reply
);
748 if (strcmp (sname
, "krbtgt") != 0
749 || strcmp (sinstance
, config
->v4_realm
) != 0) {
750 kdc_log(context
, config
, 0, "no TGT: %s.%s for %s.%s@%s",
752 ad
.pname
, ad
.pinst
, ad
.prealm
);
753 make_error_reply (hdr
, KABADTICKET
, reply
);
761 if (kdc_time
> _krb5_krb_life_to_time(ad
.time_sec
, ad
.life
)) {
762 kdc_log(context
, config
, 0, "TGT expired: %s.%s@%s",
763 ad
.pname
, ad
.pinst
, ad
.prealm
);
764 make_error_reply (hdr
, KABADTICKET
, reply
);
769 snprintf (client_name
, sizeof(client_name
),
770 "%s.%s@%s", ad
.pname
, ad
.pinst
, ad
.prealm
);
772 kdc_log(context
, config
, 0, "TGS-REQ (kaserver) %s from %s for %s",
773 client_name
, from
, server_name
);
775 ret
= _kdc_db_fetch4 (context
, config
,
776 ad
.pname
, ad
.pinst
, ad
.prealm
, HDB_F_GET_CLIENT
,
778 if(ret
&& ret
!= HDB_ERR_NOENTRY
) {
779 kdc_log(context
, config
, 0,
780 "Client not found in database: (krb4) %s: %s",
781 client_name
, krb5_get_err_text(context
, ret
));
782 make_error_reply (hdr
, KANOENT
, reply
);
785 if (client_entry
== NULL
&& strcmp(ad
.prealm
, config
->v4_realm
) == 0) {
786 kdc_log(context
, config
, 0,
787 "Local client not found in database: (krb4) "
789 make_error_reply (hdr
, KANOENT
, reply
);
793 ret
= kdc_check_flags (context
, config
,
794 client_entry
, client_name
,
795 server_entry
, server_name
,
798 make_error_reply (hdr
, KAPWEXPIRED
, reply
);
802 /* decrypt the times */
803 memcpy(&session
, ad
.session
.keyvalue
.data
, sizeof(session
));
804 DES_set_key_unchecked (&session
, &schedule
);
805 DES_ecb_encrypt (times
.data
,
809 memset (&schedule
, 0, sizeof(schedule
));
810 memset (&session
, 0, sizeof(session
));
812 /* and extract them */
817 tsp
= krb5_storage_from_mem (times
.data
, times
.length
);
818 krb5_ret_int32 (tsp
, &tmp
);
820 krb5_ret_int32 (tsp
, &tmp
);
822 krb5_storage_free (tsp
);
826 max_life
= end_time
- kdc_time
;
827 /* end_time - kdc_time can sometimes be non-positive due to slight
828 time skew between client and server. Let's make sure it is postive */
831 if (krbtgt_entry
->entry
.max_life
)
832 max_life
= min(max_life
, *krbtgt_entry
->entry
.max_life
);
833 if (server_entry
->entry
.max_life
)
834 max_life
= min(max_life
, *server_entry
->entry
.max_life
);
835 /* if this is a cross realm request, the client_entry will likely
837 if (client_entry
&& client_entry
->entry
.max_life
)
838 max_life
= min(max_life
, *client_entry
->entry
.max_life
);
840 life
= _krb5_krb_time_to_life(kdc_time
, kdc_time
+ max_life
);
842 create_reply_ticket (context
,
844 ad
.pname
, ad
.pinst
, ad
.prealm
,
845 addr
, life
, server_entry
->entry
.kvno
,
852 _krb5_krb_free_auth_data(context
, &ad
);
853 if (aticket
.length
) {
854 memset (aticket
.data
, 0, aticket
.length
);
855 krb5_data_free (&aticket
);
858 memset (times
.data
, 0, times
.length
);
859 krb5_data_free (×
);
868 _kdc_free_ent (context
, krbtgt_entry
);
870 _kdc_free_ent (context
, server_entry
);
874 _kdc_do_kaserver(krb5_context context
,
875 krb5_kdc_configuration
*config
,
880 struct sockaddr_in
*addr
)
882 krb5_error_code ret
= 0;
883 struct rx_header hdr
;
887 if (len
< RX_HEADER_SIZE
)
889 sp
= krb5_storage_from_mem (buf
, len
);
891 ret
= decode_rx_header (sp
, &hdr
);
894 buf
+= RX_HEADER_SIZE
;
895 len
-= RX_HEADER_SIZE
;
913 if (hdr
.serviceid
!= KA_AUTHENTICATION_SERVICE
914 && hdr
.serviceid
!= KA_TICKET_GRANTING_SERVICE
) {
919 ret
= krb5_ret_uint32(sp
, &op
);
924 case AUTHENTICATE_V2
:
925 do_authenticate (context
, config
, &hdr
, sp
, addr
, from
, reply
);
928 do_getticket (context
, config
, &hdr
, sp
, addr
, from
, reply
);
930 case AUTHENTICATE_OLD
:
931 case CHANGEPASSWORD
:
944 make_error_reply (&hdr
, RXGEN_OPCODE
, reply
);
949 krb5_storage_free (sp
);