2 * Copyright (c) 1997 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. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 #define MAX_TIME ((time_t)((1U << 31) - 1))
52 if(**t
== 0) **t
= MAX_TIME
; /* fix for old clients */
60 KDC_REQ_BODY
*b
= &req
->req_body
;
62 KDCOptions f
= b
->kdc_options
;
63 hdb_entry
*client
= NULL
, *server
= NULL
;
67 krb5_principal client_princ
, server_princ
;
68 char *client_name
, *server_name
;
69 krb5_error_code ret
= 0;
70 const char *e_text
= NULL
;
73 Key
*ckey
, *skey
, *ekey
;
76 server_name
= "<unknown server>";
77 ret
= KRB5KRB_ERR_GENERIC
;
78 e_text
= "No server in request";
80 principalname2krb5_principal (&server_princ
, *(b
->sname
), b
->realm
);
81 krb5_unparse_name(context
, server_princ
, &server_name
);
85 client_name
= "<unknown client>";
86 ret
= KRB5KRB_ERR_GENERIC
;
87 e_text
= "No client in request";
89 principalname2krb5_principal (&client_princ
, *(b
->cname
), b
->realm
);
90 krb5_unparse_name(context
, client_princ
, &client_name
);
92 kdc_log(0, "AS-REQ %s from %s for %s",
93 client_name
, from
, server_name
);
98 client
= db_fetch(client_princ
);
100 kdc_log(0, "UNKNOWN -- %s", client_name
);
101 ret
= KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
;
105 if (client
->valid_start
&& *client
->valid_start
> kdc_time
) {
106 kdc_log(0, "Client not yet valid -- %s", client_name
);
107 ret
= KRB5KDC_ERR_CLIENT_NOTYET
;
111 if (client
->valid_end
&& *client
->valid_end
< kdc_time
) {
112 kdc_log(0, "Client expired -- %s", client_name
);
113 ret
= KRB5KDC_ERR_NAME_EXP
;
117 server
= db_fetch(server_princ
);
120 kdc_log(0, "UNKNOWN -- %s", server_name
);
121 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
125 if (server
->valid_start
&& *server
->valid_start
> kdc_time
) {
126 kdc_log(0, "Server not yet valid -- %s", server_name
);
127 ret
= KRB5KDC_ERR_SERVICE_NOTYET
;
131 if (server
->valid_end
&& *server
->valid_end
< kdc_time
) {
132 kdc_log(0, "Server expired -- %s", server_name
);
133 ret
= KRB5KDC_ERR_SERVICE_EXP
;
137 if(!client
->flags
.client
){
138 ret
= KRB5KDC_ERR_POLICY
;
139 kdc_log(0, "Principal may not act as client -- %s",
143 if(!server
->flags
.server
){
144 ret
= KRB5KDC_ERR_POLICY
;
145 kdc_log(0, "Principal (%s) may not act as server -- %s",
146 server_name
, client_name
);
150 if (client
->pw_end
&& *client
->pw_end
< kdc_time
151 && !server
->flags
.change_pw
) {
152 ret
= KRB5KDC_ERR_KEY_EXPIRED
;
153 kdc_log(0, "Client (%s)'s key has expired", client_name
);
157 /* Find appropriate key */
158 for(i
= 0; i
< b
->etype
.len
; i
++){
159 ret
= hdb_etype2key(context
, client
, b
->etype
.val
[i
], &ckey
);
162 ret
= hdb_etype2key(context
, server
, b
->etype
.val
[i
], &skey
);
169 ret
= KRB5KDC_ERR_ETYPE_NOSUPP
;
170 kdc_log(0, "No support for etypes -- %s", client_name
);
174 etype
= b
->etype
.val
[i
];
176 memset(&et
, 0, sizeof(et
));
177 memset(&ek
, 0, sizeof(ek
));
183 kdc_log(5, "Looking for pa-data -- %s", client_name
);
184 for(i
= 0; i
< req
->padata
->len
; i
++){
185 PA_DATA
*pa
= &req
->padata
->val
[i
];
186 if(pa
->padata_type
== pa_enc_timestamp
){
191 EncryptedData enc_data
;
193 kdc_log(5, "Found pa-enc-timestamp -- %s",
197 ret
= decode_EncryptedData(pa
->padata_value
.data
,
198 pa
->padata_value
.length
,
202 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
203 kdc_log(5, "Failed to decode PA-DATA -- %s",
208 ekey
= unseal_key(ckey
);
210 ret
= krb5_decrypt (context
,
211 enc_data
.cipher
.data
,
212 enc_data
.cipher
.length
,
217 free_EncryptedData(&enc_data
);
219 e_text
= "Failed to decrypt PA-DATA";
220 kdc_log (5, "Failed to decrypt PA-DATA -- %s",
222 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
225 ret
= decode_PA_ENC_TS_ENC(ts_data
.data
,
229 krb5_data_free(&ts_data
);
231 e_text
= "Failed to decode PA-ENC-TS-ENC";
232 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
233 kdc_log (5, "Failed to decode PA-ENC-TS_ENC -- %s",
237 patime
= p
.patimestamp
;
238 free_PA_ENC_TS_ENC(&p
);
239 if (abs(kdc_time
- p
.patimestamp
) > context
->max_skew
) {
240 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
241 krb5_mk_error (context
,
243 "Too large time skew",
249 kdc_log(0, "Too large time skew -- %s",
253 et
.flags
.pre_authent
= 1;
254 kdc_log(2, "Pre-authentication succeded -- %s",
258 kdc_log(5, "Found pa-data of type %d -- %s",
259 pa
->padata_type
, client_name
);
263 if(found_pa
== 0 && require_preauth
)
265 /* We come here if we found a pa-enc-timestamp, but if there
266 was some problem with it, other than too large skew */
267 if(et
.flags
.pre_authent
== 0){
268 kdc_log(0, "%s -- %s", e_text
, client_name
);
272 }else if (require_preauth
273 || client
->flags
.require_preauth
) {
274 METHOD_DATA method_data
;
282 method_data
.val
= &pa_data
;
284 pa_data
.padata_type
= pa_enc_timestamp
;
285 pa_data
.padata_value
.length
= 0;
286 pa_data
.padata_value
.data
= NULL
;
288 encode_METHOD_DATA(buf
+ sizeof(buf
) - 1,
292 foo_data
.length
= len
;
293 foo_data
.data
= buf
+ sizeof(buf
) - len
;
295 ret
= KRB5KDC_ERR_PREAUTH_REQUIRED
;
296 krb5_mk_error(context
,
298 "Need to use PA-ENC-TIMESTAMP",
305 kdc_log(0, "No PA-ENC-TIMESTAMP -- %s", client_name
);
309 kdc_log(2, "Using etype %d -- %s", etype
, client_name
);
311 memset(&rep
, 0, sizeof(rep
));
313 rep
.msg_type
= krb_as_rep
;
314 copy_Realm(&b
->realm
, &rep
.crealm
);
315 copy_PrincipalName(b
->cname
, &rep
.cname
);
316 rep
.ticket
.tkt_vno
= 5;
317 copy_Realm(&b
->realm
, &rep
.ticket
.realm
);
318 copy_PrincipalName(b
->sname
, &rep
.ticket
.sname
);
320 if(f
.renew
|| f
.validate
|| f
.proxy
|| f
.forwarded
|| f
.enc_tkt_in_skey
){
321 ret
= KRB5KDC_ERR_BADOPTION
;
322 kdc_log(0, "Bad KDC options -- %s", client_name
);
326 et
.flags
.initial
= 1;
327 if(client
->flags
.forwardable
&& server
->flags
.forwardable
)
328 et
.flags
.forwardable
= f
.forwardable
;
329 else if (f
.forwardable
) {
330 ret
= KRB5KDC_ERR_POLICY
;
331 kdc_log(0, "Ticket may not be forwardable -- %s", client_name
);
334 if(client
->flags
.proxiable
&& server
->flags
.proxiable
)
335 et
.flags
.proxiable
= f
.proxiable
;
336 else if (f
.proxiable
) {
337 ret
= KRB5KDC_ERR_POLICY
;
338 kdc_log(0, "Ticket may not be proxiable -- %s", client_name
);
341 if(client
->flags
.postdate
&& server
->flags
.postdate
)
342 et
.flags
.may_postdate
= f
.allow_postdate
;
343 else if (f
.allow_postdate
){
344 ret
= KRB5KDC_ERR_POLICY
;
345 kdc_log(0, "Ticket may not be postdatable -- %s", client_name
);
349 krb5_generate_random_keyblock(context
, ckey
->key
.keytype
, &et
.key
);
350 copy_PrincipalName(b
->cname
, &et
.cname
);
351 copy_Realm(&b
->realm
, &et
.crealm
);
357 start
= et
.authtime
= kdc_time
;
359 if(f
.postdated
&& req
->req_body
.from
){
361 start
= *et
.starttime
= *req
->req_body
.from
;
362 et
.flags
.invalid
= 1;
363 et
.flags
.postdated
= 1; /* XXX ??? */
364 kdc_log(2, "Postdated ticket requested -- %s",
370 t
= min(t
, start
+ *client
->max_life
);
372 t
= min(t
, start
+ *server
->max_life
);
374 t
= min(t
, start
+ realm
->max_life
);
377 if(f
.renewable_ok
&& et
.endtime
< *b
->till
){
379 if(b
->rtime
== NULL
){
383 if(*b
->rtime
< *b
->till
)
384 *b
->rtime
= *b
->till
;
386 if(f
.renewable
&& b
->rtime
){
390 if(client
->max_renew
)
391 t
= min(t
, start
+ *client
->max_renew
);
392 if(server
->max_renew
)
393 t
= min(t
, start
+ *server
->max_renew
);
395 t
= min(t
, start
+ realm
->max_renew
);
397 ALLOC(et
.renew_till
);
399 et
.flags
.renewable
= 1;
405 copy_HostAddresses(b
->addresses
, et
.caddr
);
408 copy_EncryptionKey(&et
.key
, &ek
.key
);
410 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
411 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
412 * incapable to correctly decode vectors of zero length.
414 * To fix this, always send at least one no-op last_req
416 * If there's a pw_end or valid_end we will use that,
417 * otherwise just a dummy lr.
419 ek
.last_req
.val
= malloc(2 * sizeof(*ek
.last_req
.val
));
422 && (kdc_warn_pwexpire
== 0
423 || kdc_time
+ kdc_warn_pwexpire
<= *client
->pw_end
)) {
424 ek
.last_req
.val
[ek
.last_req
.len
].lr_type
= 6;
425 ek
.last_req
.val
[ek
.last_req
.len
].lr_value
= *client
->pw_end
;
428 if (client
->valid_end
) {
429 ek
.last_req
.val
[ek
.last_req
.len
].lr_type
= 7;
430 ek
.last_req
.val
[ek
.last_req
.len
].lr_value
= *client
->valid_end
;
433 if (ek
.last_req
.len
== 0) {
434 ek
.last_req
.val
[ek
.last_req
.len
].lr_type
= 0;
435 ek
.last_req
.val
[ek
.last_req
.len
].lr_value
= 0;
439 if (client
->valid_end
|| client
->pw_end
) {
440 ALLOC(ek
.key_expiration
);
441 if (client
->valid_end
)
443 *ek
.key_expiration
= min(*client
->valid_end
, *client
->pw_end
);
445 *ek
.key_expiration
= *client
->valid_end
;
447 *ek
.key_expiration
= *client
->pw_end
;
449 ek
.key_expiration
= NULL
;
451 ek
.authtime
= et
.authtime
;
454 *ek
.starttime
= *et
.starttime
;
456 ek
.starttime
= et
.starttime
;
457 ek
.endtime
= et
.endtime
;
459 ALLOC(ek
.renew_till
);
460 *ek
.renew_till
= *et
.renew_till
;
462 ek
.renew_till
= et
.renew_till
;
463 copy_Realm(&rep
.ticket
.realm
, &ek
.srealm
);
464 copy_PrincipalName(&rep
.ticket
.sname
, &ek
.sname
);
467 copy_HostAddresses(et
.caddr
, ek
.caddr
);
471 unsigned char buf
[1024]; /* XXX The data could be indefinite */
474 ret
= encode_EncTicketPart(buf
+ sizeof(buf
) - 1, sizeof(buf
),
476 free_EncTicketPart(&et
);
478 kdc_log(0, "Failed to encode ticket -- %s", client
);
482 ekey
= unseal_key(skey
);
483 krb5_encrypt_EncryptedData(context
,
484 buf
+ sizeof(buf
) - len
,
489 &rep
.ticket
.enc_part
);
492 ret
= encode_EncASRepPart(buf
+ sizeof(buf
) - 1, sizeof(buf
),
494 free_EncKDCRepPart(&ek
);
496 kdc_log(0, "Failed to encode KDC-REP -- %s", client_name
);
499 ekey
= unseal_key(ckey
);
500 krb5_encrypt_EncryptedData(context
,
501 buf
+ sizeof(buf
) - len
,
511 rep
.padata
->val
= calloc(1, sizeof(*rep
.padata
->val
));
512 rep
.padata
->val
->padata_type
= pa_pw_salt
;
513 copy_octet_string(ckey
->salt
, &rep
.padata
->val
->padata_value
);
516 ret
= encode_AS_REP(buf
+ sizeof(buf
) - 1, sizeof(buf
), &rep
, &len
);
519 kdc_log(0, "Failed to encode AS-REP -- %s", client_name
);
523 krb5_data_copy(reply
, buf
+ sizeof(buf
) - len
, len
);
527 krb5_mk_error(context
,
537 krb5_free_principal(context
, client_princ
);
539 krb5_free_principal(context
, server_princ
);
542 hdb_free_entry(context
, client
);
546 hdb_free_entry(context
, server
);
554 static krb5_error_code
555 check_tgs_flags(KDC_REQ_BODY
*b
, EncTicketPart
*tgt
, EncTicketPart
*et
)
557 KDCOptions f
= b
->kdc_options
;
560 if(!tgt
->flags
.invalid
|| tgt
->starttime
== NULL
){
561 kdc_log(0, "Bad request to validate ticket");
562 return KRB5KDC_ERR_BADOPTION
;
564 if(*tgt
->starttime
< kdc_time
){
565 kdc_log(0, "Early request to validate ticket");
566 return KRB5KRB_AP_ERR_TKT_NYV
;
569 et
->flags
.invalid
= 0;
570 }else if(tgt
->flags
.invalid
){
571 kdc_log(0, "Ticket-granting ticket has INVALID flag set");
572 return KRB5KRB_AP_ERR_TKT_INVALID
;
576 if(!tgt
->flags
.forwardable
){
577 kdc_log(0, "Bad request for forwardable ticket");
578 return KRB5KDC_ERR_BADOPTION
;
580 et
->flags
.forwardable
= 1;
583 if(!tgt
->flags
.forwardable
){
584 kdc_log(0, "Request to forward non-forwardable ticket");
585 return KRB5KDC_ERR_BADOPTION
;
587 et
->flags
.forwarded
= 1;
588 et
->caddr
= b
->addresses
;
590 if(tgt
->flags
.forwarded
)
591 et
->flags
.forwarded
= 1;
594 if(!tgt
->flags
.proxiable
){
595 kdc_log(0, "Bad request for proxiable ticket");
596 return KRB5KDC_ERR_BADOPTION
;
598 et
->flags
.proxiable
= 1;
601 if(!tgt
->flags
.proxiable
){
602 kdc_log(0, "Request to proxy non-proxiable ticket");
603 return KRB5KDC_ERR_BADOPTION
;
606 et
->caddr
= b
->addresses
;
611 if(f
.allow_postdate
){
612 if(!tgt
->flags
.may_postdate
){
613 kdc_log(0, "Bad request for post-datable ticket");
614 return KRB5KDC_ERR_BADOPTION
;
616 et
->flags
.may_postdate
= 1;
619 if(!tgt
->flags
.may_postdate
){
620 kdc_log(0, "Bad request for postdated ticket");
621 return KRB5KDC_ERR_BADOPTION
;
624 *et
->starttime
= *b
->from
;
625 et
->flags
.postdated
= 1;
626 et
->flags
.invalid
= 1;
627 }else if(b
->from
&& *b
->from
> kdc_time
+ context
->max_skew
){
628 kdc_log(0, "Ticket cannot be postdated");
629 return KRB5KDC_ERR_CANNOT_POSTDATE
;
633 if(!tgt
->flags
.renewable
){
634 kdc_log(0, "Bad request for renewable ticket");
635 return KRB5KDC_ERR_BADOPTION
;
637 et
->flags
.renewable
= 1;
638 ALLOC(et
->renew_till
);
639 *et
->renew_till
= *b
->rtime
;
643 if(!tgt
->flags
.renewable
|| tgt
->renew_till
== NULL
){
644 kdc_log(0, "Request to renew non-renewable ticket");
645 return KRB5KDC_ERR_BADOPTION
;
647 old_life
= tgt
->endtime
;
649 old_life
-= *tgt
->starttime
;
651 old_life
-= tgt
->authtime
;
652 et
->endtime
= *et
->starttime
+ old_life
;
655 /* check for excess flags */
659 static krb5_error_code
660 tgs_make_reply(KDC_REQ_BODY
*b
, EncTicketPart
*tgt
,
661 hdb_entry
*server
, hdb_entry
*client
, krb5_data
*reply
)
666 KDCOptions f
= b
->kdc_options
;
672 /* Find appropriate key */
673 for(i
= 0; i
< b
->etype
.len
; i
++){
674 ret
= hdb_etype2key(context
, server
, b
->etype
.val
[i
], &skey
);
680 kdc_log(0, "Failed to find requested etype");
681 return KRB5KDC_ERR_ETYPE_NOSUPP
;
684 etype
= b
->etype
.val
[i
];
686 memset(&rep
, 0, sizeof(rep
));
687 memset(&et
, 0, sizeof(et
));
688 memset(&ek
, 0, sizeof(ek
));
691 rep
.msg_type
= krb_tgs_rep
;
693 et
.authtime
= tgt
->authtime
;
695 et
.endtime
= min(tgt
->endtime
, *b
->till
);
697 *et
.starttime
= kdc_time
;
699 ret
= check_tgs_flags(b
, tgt
, &et
);
703 copy_Realm(krb5_princ_realm(context
, server
->principal
),
705 krb5_principal2principalname(&rep
.ticket
.sname
, server
->principal
);
706 copy_Realm(&tgt
->crealm
, &rep
.crealm
);
707 copy_PrincipalName(&tgt
->cname
, &rep
.cname
);
708 rep
.ticket
.tkt_vno
= 5;
712 et
.caddr
= tgt
->caddr
;
716 life
= et
.endtime
- *et
.starttime
;
718 life
= min(life
, *client
->max_life
);
720 life
= min(life
, *server
->max_life
);
721 et
.endtime
= *et
.starttime
+ life
;
723 if(f
.renewable_ok
&& tgt
->flags
.renewable
&&
724 et
.renew_till
== NULL
&& et
.endtime
< *b
->till
){
725 et
.flags
.renewable
= 1;
726 ALLOC(et
.renew_till
);
727 *et
.renew_till
= *b
->till
;
731 renew
= *et
.renew_till
- et
.authtime
;
732 if(client
->max_renew
)
733 renew
= min(renew
, *client
->max_renew
);
734 if(server
->max_renew
)
735 renew
= min(renew
, *server
->max_renew
);
736 *et
.renew_till
= et
.authtime
+ renew
;
740 *et
.renew_till
= min(*et
.renew_till
, *tgt
->renew_till
);
741 *et
.starttime
= min(*et
.starttime
, *et
.renew_till
);
742 et
.endtime
= min(et
.endtime
, *et
.renew_till
);
745 *et
.starttime
= min(*et
.starttime
, et
.endtime
);
747 if(*et
.starttime
== et
.endtime
){
748 ret
= KRB5KDC_ERR_NEVER_VALID
;
751 if(et
.renew_till
&& et
.endtime
== *et
.renew_till
){
753 et
.renew_till
= NULL
;
754 et
.flags
.renewable
= 0;
757 et
.flags
.pre_authent
= tgt
->flags
.pre_authent
;
758 et
.flags
.hw_authent
= tgt
->flags
.hw_authent
;
760 /* XXX Check enc-authorization-data */
762 krb5_generate_random_keyblock(context
,
765 et
.crealm
= tgt
->crealm
;
766 et
.cname
= tgt
->cname
;
767 /* do cross realm stuff */
768 et
.transited
= tgt
->transited
;
772 /* MIT must have at least one last_req */
774 ek
.last_req
.val
= calloc(1, sizeof(*ek
.last_req
.val
));
777 ek
.authtime
= et
.authtime
;
778 ek
.starttime
= et
.starttime
;
779 ek
.endtime
= et
.endtime
;
780 ek
.renew_till
= et
.renew_till
;
781 ek
.srealm
= rep
.ticket
.realm
;
782 ek
.sname
= rep
.ticket
.sname
;
785 unsigned char buf
[1024]; /* XXX The data could be indefinite */
787 ret
= encode_EncTicketPart(buf
+ sizeof(buf
) - 1,
788 sizeof(buf
), &et
, &len
);
790 kdc_log(0, "Failed to encode EncTicketPart: %s",
791 krb5_get_err_text(context
, ret
));
794 ekey
= unseal_key(skey
);
795 krb5_encrypt_EncryptedData(context
, buf
+ sizeof(buf
) - len
, len
,
799 &rep
.ticket
.enc_part
);
802 ret
= encode_EncTGSRepPart(buf
+ sizeof(buf
) - 1,
803 sizeof(buf
), &ek
, &len
);
805 kdc_log(0, "Failed to encode EncTicketPart: %s",
806 krb5_get_err_text(context
, ret
));
810 /* It is somewhat unclear where the etype in the following
811 encryption should come from. What we have is a session
812 key in the passed tgt, and a list of preferred etypes
813 *for the new ticket*. Should we pick the best possible
814 etype, given the keytype in the tgt, or should we look
815 at the etype list here as well? What if the tgt
816 session key is DES3 and we want a ticket with a (say)
817 CAST session key. Should the DES3 etype be added to the
818 etype list, even if we don't want a session key with
822 krb5_encrypt_EncryptedData(context
,
823 buf
+ sizeof(buf
) - len
, len
,
829 ret
= encode_TGS_REP(buf
+ sizeof(buf
) - 1, sizeof(buf
), &rep
, &len
);
831 kdc_log(0, "Failed to encode TGS-REP: %s",
832 krb5_get_err_text(context
, ret
));
835 krb5_data_copy(reply
, buf
+ sizeof(buf
) - len
, len
);
842 free_LastReq(&ek
.last_req
);
843 memset(et
.key
.keyvalue
.data
, 0, et
.key
.keyvalue
.length
);
844 free_EncryptionKey(&et
.key
);
849 static krb5_error_code
850 tgs_check_authenticator(krb5_auth_context ac
,
851 KDC_REQ_BODY
*b
, krb5_keyblock
*key
)
853 krb5_authenticator auth
;
855 unsigned char buf
[1024];
858 krb5_auth_getauthenticator(context
, ac
, &auth
);
859 if(auth
->cksum
== NULL
){
860 kdc_log(0, "No authenticator in request");
861 ret
= KRB5KRB_AP_ERR_INAPP_CKSUM
;
865 if (auth
->cksum
->cksumtype
!= CKSUMTYPE_RSA_MD4
&&
866 auth
->cksum
->cksumtype
!= CKSUMTYPE_RSA_MD5
&&
867 auth
->cksum
->cksumtype
!= CKSUMTYPE_RSA_MD5_DES
){
868 kdc_log(0, "Bad checksum type in authenticator: %d",
869 auth
->cksum
->cksumtype
);
870 ret
= KRB5KRB_AP_ERR_INAPP_CKSUM
;
875 ret
= encode_KDC_REQ_BODY(buf
+ sizeof(buf
) - 1, sizeof(buf
),
878 kdc_log(0, "Failed to encode KDC-REQ-BODY: %s",
879 krb5_get_err_text(context
, ret
));
882 ret
= krb5_verify_checksum(context
, buf
+ sizeof(buf
) - len
, len
,
886 kdc_log(0, "Failed to verify checksum: %s",
887 krb5_get_err_text(context
, ret
));
890 free_Authenticator(auth
);
897 static krb5_error_code
898 tgs_rep2(KDC_REQ_BODY
*b
,
907 krb5_principal princ
;
908 krb5_auth_context ac
= NULL
;
909 krb5_ticket
*ticket
= NULL
;
910 krb5_flags ap_req_options
;
911 const char *e_text
= NULL
;
916 krb5_principal cp
= NULL
;
918 memset(&ap_req
, 0, sizeof(ap_req
));
919 ret
= krb5_decode_ap_req(context
, &pa_data
->padata_value
, &ap_req
);
921 kdc_log(0, "Failed to decode AP-REQ: %s",
922 krb5_get_err_text(context
, ret
));
926 if(ap_req
.ticket
.sname
.name_string
.len
!= 2 ||
927 strcmp(ap_req
.ticket
.sname
.name_string
.val
[0], "krbtgt")){
928 kdc_log(0, "PA-DATA is not a ticket-granting ticket");
929 ret
= KRB5KDC_ERR_POLICY
; /* ? */
933 principalname2krb5_principal(&princ
,
935 ap_req
.ticket
.realm
);
937 krbtgt
= db_fetch(princ
);
941 krb5_unparse_name(context
, princ
, &p
);
942 kdc_log(0, "Ticket-granting ticket not found in database: %s", p
);
944 ret
= KRB5KRB_AP_ERR_NOT_US
;
948 ekey
= unseal_key(&krbtgt
->keys
.val
[0]); /* XXX */
949 ret
= krb5_verify_ap_req(context
,
958 krb5_free_principal(context
, princ
);
960 kdc_log(0, "Failed to verify AP-REQ: %s",
961 krb5_get_err_text(context
, ret
));
965 tgt
= &ticket
->ticket
;
967 ret
= tgs_check_authenticator(ac
, b
, &tgt
->key
);
969 krb5_auth_con_free(context
, ac
);
972 kdc_log(0, "Failed to verify authenticator: %s",
973 krb5_get_err_text(context
, ret
));
980 char *spn
= NULL
, *cpn
= NULL
;
981 hdb_entry
*server
= NULL
, *client
= NULL
;
986 if(b
->kdc_options
.enc_tkt_in_skey
&&
987 b
->additional_tickets
&&
988 b
->additional_tickets
->len
>= 1){
991 principalname2krb5_principal(&p
,
992 b
->additional_tickets
->val
[0].sname
,
993 b
->additional_tickets
->val
[0].realm
);
995 krb5_free_principal(context
, p
);
997 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
1002 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
1007 principalname2krb5_principal(&sp
, *s
, r
);
1009 krb5_unparse_name(context
, sp
, &spn
);
1010 server
= db_fetch(sp
);
1012 principalname2krb5_principal(&cp
, tgt
->cname
, tgt
->crealm
);
1013 krb5_unparse_name(context
, cp
, &cpn
);
1014 client
= db_fetch(cp
);
1016 kdc_log(0, "TGS-REQ %s from %s for %s", cpn
, from
, spn
);
1019 kdc_log(0, "Server not found in database: %s", spn
);
1020 /* do foreign realm stuff */
1021 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
1026 kdc_log(0, "Client not found in database: %s", cpn
);
1027 ret
= KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
;
1031 if((b
->kdc_options
.validate
|| b
->kdc_options
.renew
) &&
1032 !krb5_principal_compare(context
,
1034 server
->principal
)){
1035 kdc_log(0, "Inconsistent request.");
1036 ret
= KRB5KDC_ERR_SERVER_NOMATCH
;
1040 ret
= tgs_make_reply(b
, tgt
, server
, client
, reply
);
1047 hdb_free_entry(context
, server
);
1051 hdb_free_entry(context
, client
);
1058 krb5_mk_error(context
,
1066 krb5_free_principal(context
, cp
);
1068 krb5_free_ticket(context
, ticket
);
1071 free_AP_REQ(&ap_req
);
1074 hdb_free_entry(context
, krbtgt
);
1080 static krb5_error_code
1081 request_server(KDC_REQ
*req
, krb5_principal
*server
)
1083 PrincipalName
*s
= NULL
;
1085 s
= req
->req_body
.sname
;
1086 r
= req
->req_body
.realm
;
1088 req
->req_body
.additional_tickets
&&
1089 req
->req_body
.additional_tickets
->len
){
1090 s
= &req
->req_body
.additional_tickets
->val
[0].sname
;
1091 r
= req
->req_body
.additional_tickets
->val
[0].realm
;
1094 principalname2krb5_principal(server
, *s
, r
);
1096 krb5_build_principal(context
, server
, strlen(r
), r
, "anonymous", NULL
);
1102 tgs_rep(KDC_REQ
*req
,
1106 krb5_error_code ret
;
1108 PA_DATA
*pa_data
= NULL
;
1109 krb5_principal server
;
1111 request_server(req
, &server
);
1113 if(req
->padata
== NULL
){
1114 ret
= KRB5KDC_ERR_PREAUTH_REQUIRED
; /* XXX ??? */
1115 kdc_log(0, "TGS-REQ from %s without PA-DATA", from
);
1119 for(i
= 0; i
< req
->padata
->len
; i
++)
1120 if(req
->padata
->val
[i
].padata_type
== pa_tgs_req
){
1121 pa_data
= &req
->padata
->val
[i
];
1124 if(pa_data
== NULL
){
1125 ret
= KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
1127 kdc_log(0, "TGS-REQ from %s without PA-TGS-REQ", from
);
1130 ret
= tgs_rep2(&req
->req_body
, server
, pa_data
, data
, from
);
1132 if(ret
&& data
->data
== NULL
)
1133 krb5_mk_error(context
,
1141 krb5_free_principal(context
, server
);