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 */
56 set_salt_padata (METHOD_DATA
**m
, Salt
*salt
)
62 (*m
)->val
->padata_type
= salt
->type
;
63 copy_octet_string(&salt
->salt
,
64 &(*m
)->val
->padata_value
);
73 KDC_REQ_BODY
*b
= &req
->req_body
;
75 KDCOptions f
= b
->kdc_options
;
76 hdb_entry
*client
= NULL
, *server
= NULL
;
80 krb5_principal client_princ
, server_princ
;
81 char *client_name
, *server_name
;
82 krb5_error_code ret
= 0;
83 const char *e_text
= NULL
;
86 Key
*ckey
, *skey
, *ekey
;
89 server_name
= "<unknown server>";
90 ret
= KRB5KRB_ERR_GENERIC
;
91 e_text
= "No server in request";
93 principalname2krb5_principal (&server_princ
, *(b
->sname
), b
->realm
);
94 krb5_unparse_name(context
, server_princ
, &server_name
);
98 client_name
= "<unknown client>";
99 ret
= KRB5KRB_ERR_GENERIC
;
100 e_text
= "No client in request";
102 principalname2krb5_principal (&client_princ
, *(b
->cname
), b
->realm
);
103 krb5_unparse_name(context
, client_princ
, &client_name
);
105 kdc_log(0, "AS-REQ %s from %s for %s",
106 client_name
, from
, server_name
);
111 client
= db_fetch(client_princ
);
113 kdc_log(0, "UNKNOWN -- %s", client_name
);
114 ret
= KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
;
118 if (client
->valid_start
&& *client
->valid_start
> kdc_time
) {
119 kdc_log(0, "Client not yet valid -- %s", client_name
);
120 ret
= KRB5KDC_ERR_CLIENT_NOTYET
;
124 if (client
->valid_end
&& *client
->valid_end
< kdc_time
) {
125 kdc_log(0, "Client expired -- %s", client_name
);
126 ret
= KRB5KDC_ERR_NAME_EXP
;
130 server
= db_fetch(server_princ
);
133 kdc_log(0, "UNKNOWN -- %s", server_name
);
134 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
138 if (server
->valid_start
&& *server
->valid_start
> kdc_time
) {
139 kdc_log(0, "Server not yet valid -- %s", server_name
);
140 ret
= KRB5KDC_ERR_SERVICE_NOTYET
;
144 if (server
->valid_end
&& *server
->valid_end
< kdc_time
) {
145 kdc_log(0, "Server expired -- %s", server_name
);
146 ret
= KRB5KDC_ERR_SERVICE_EXP
;
150 if(!client
->flags
.client
){
151 ret
= KRB5KDC_ERR_POLICY
;
152 kdc_log(0, "Principal may not act as client -- %s",
156 if(!server
->flags
.server
){
157 ret
= KRB5KDC_ERR_POLICY
;
158 kdc_log(0, "Principal (%s) may not act as server -- %s",
159 server_name
, client_name
);
163 if (client
->flags
.invalid
) {
164 ret
= KRB5KDC_ERR_POLICY
;
165 kdc_log(0, "Client (%s) has invalid bit set", client_name
);
169 if (server
->flags
.invalid
) {
170 ret
= KRB5KDC_ERR_POLICY
;
171 kdc_log(0, "Server (%s) has invalid bit set", server_name
);
175 if (client
->pw_end
&& *client
->pw_end
< kdc_time
176 && !server
->flags
.change_pw
) {
177 ret
= KRB5KDC_ERR_KEY_EXPIRED
;
178 kdc_log(0, "Client (%s)'s key has expired", client_name
);
182 /* Find appropriate key */
183 for(i
= 0; i
< b
->etype
.len
; i
++){
184 ret
= hdb_etype2key(context
, client
, b
->etype
.val
[i
], &ckey
);
187 ret
= hdb_etype2key(context
, server
, b
->etype
.val
[i
], &skey
);
194 ret
= KRB5KDC_ERR_ETYPE_NOSUPP
;
195 kdc_log(0, "No support for etypes -- %s", client_name
);
199 etype
= b
->etype
.val
[i
];
201 memset(&et
, 0, sizeof(et
));
202 memset(&ek
, 0, sizeof(ek
));
208 kdc_log(5, "Looking for pa-data -- %s", client_name
);
209 for(i
= 0; i
< req
->padata
->len
; i
++){
210 PA_DATA
*pa
= &req
->padata
->val
[i
];
211 if(pa
->padata_type
== pa_enc_timestamp
){
216 EncryptedData enc_data
;
218 kdc_log(5, "Found pa-enc-timestamp -- %s",
222 ret
= decode_EncryptedData(pa
->padata_value
.data
,
223 pa
->padata_value
.length
,
227 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
228 kdc_log(5, "Failed to decode PA-DATA -- %s",
233 ekey
= unseal_key(ckey
);
235 ret
= krb5_decrypt (context
,
236 enc_data
.cipher
.data
,
237 enc_data
.cipher
.length
,
242 free_EncryptedData(&enc_data
);
244 e_text
= "Failed to decrypt PA-DATA";
245 kdc_log (5, "Failed to decrypt PA-DATA -- %s",
247 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
250 ret
= decode_PA_ENC_TS_ENC(ts_data
.data
,
254 krb5_data_free(&ts_data
);
256 e_text
= "Failed to decode PA-ENC-TS-ENC";
257 ret
= KRB5KRB_AP_ERR_BAD_INTEGRITY
;
258 kdc_log (5, "Failed to decode PA-ENC-TS_ENC -- %s",
262 patime
= p
.patimestamp
;
263 free_PA_ENC_TS_ENC(&p
);
264 if (abs(kdc_time
- p
.patimestamp
) > context
->max_skew
) {
265 ret
= KRB5KDC_ERR_PREAUTH_FAILED
;
266 krb5_mk_error (context
,
268 "Too large time skew",
274 kdc_log(0, "Too large time skew -- %s",
278 et
.flags
.pre_authent
= 1;
279 kdc_log(2, "Pre-authentication succeded -- %s",
283 kdc_log(5, "Found pa-data of type %d -- %s",
284 pa
->padata_type
, client_name
);
288 if(found_pa
== 0 && require_preauth
)
290 /* We come here if we found a pa-enc-timestamp, but if there
291 was some problem with it, other than too large skew */
292 if(et
.flags
.pre_authent
== 0){
293 kdc_log(0, "%s -- %s", e_text
, client_name
);
297 }else if (require_preauth
298 || client
->flags
.require_preauth
) {
299 METHOD_DATA method_data
;
307 method_data
.val
= &pa_data
;
309 pa_data
.padata_type
= pa_enc_timestamp
;
310 pa_data
.padata_value
.length
= 0;
311 pa_data
.padata_value
.data
= NULL
;
313 encode_METHOD_DATA(buf
+ sizeof(buf
) - 1,
317 foo_data
.length
= len
;
318 foo_data
.data
= buf
+ sizeof(buf
) - len
;
320 ret
= KRB5KDC_ERR_PREAUTH_REQUIRED
;
321 krb5_mk_error(context
,
323 "Need to use PA-ENC-TIMESTAMP",
330 kdc_log(0, "No PA-ENC-TIMESTAMP -- %s", client_name
);
334 kdc_log(2, "Using etype %d -- %s", etype
, client_name
);
336 memset(&rep
, 0, sizeof(rep
));
338 rep
.msg_type
= krb_as_rep
;
339 copy_Realm(&b
->realm
, &rep
.crealm
);
340 copy_PrincipalName(b
->cname
, &rep
.cname
);
341 rep
.ticket
.tkt_vno
= 5;
342 copy_Realm(&b
->realm
, &rep
.ticket
.realm
);
343 copy_PrincipalName(b
->sname
, &rep
.ticket
.sname
);
345 if(f
.renew
|| f
.validate
|| f
.proxy
|| f
.forwarded
|| f
.enc_tkt_in_skey
){
346 ret
= KRB5KDC_ERR_BADOPTION
;
347 kdc_log(0, "Bad KDC options -- %s", client_name
);
351 et
.flags
.initial
= 1;
352 if(client
->flags
.forwardable
&& server
->flags
.forwardable
)
353 et
.flags
.forwardable
= f
.forwardable
;
354 else if (f
.forwardable
) {
355 ret
= KRB5KDC_ERR_POLICY
;
356 kdc_log(0, "Ticket may not be forwardable -- %s", client_name
);
359 if(client
->flags
.proxiable
&& server
->flags
.proxiable
)
360 et
.flags
.proxiable
= f
.proxiable
;
361 else if (f
.proxiable
) {
362 ret
= KRB5KDC_ERR_POLICY
;
363 kdc_log(0, "Ticket may not be proxiable -- %s", client_name
);
366 if(client
->flags
.postdate
&& server
->flags
.postdate
)
367 et
.flags
.may_postdate
= f
.allow_postdate
;
368 else if (f
.allow_postdate
){
369 ret
= KRB5KDC_ERR_POLICY
;
370 kdc_log(0, "Ticket may not be postdatable -- %s", client_name
);
374 krb5_generate_random_keyblock(context
, ckey
->key
.keytype
, &et
.key
);
375 copy_PrincipalName(b
->cname
, &et
.cname
);
376 copy_Realm(&b
->realm
, &et
.crealm
);
382 start
= et
.authtime
= kdc_time
;
384 if(f
.postdated
&& req
->req_body
.from
){
386 start
= *et
.starttime
= *req
->req_body
.from
;
387 et
.flags
.invalid
= 1;
388 et
.flags
.postdated
= 1; /* XXX ??? */
389 kdc_log(2, "Postdated ticket requested -- %s",
395 t
= min(t
, start
+ *client
->max_life
);
397 t
= min(t
, start
+ *server
->max_life
);
399 t
= min(t
, start
+ realm
->max_life
);
402 if(f
.renewable_ok
&& et
.endtime
< *b
->till
){
404 if(b
->rtime
== NULL
){
408 if(*b
->rtime
< *b
->till
)
409 *b
->rtime
= *b
->till
;
411 if(f
.renewable
&& b
->rtime
){
415 if(client
->max_renew
)
416 t
= min(t
, start
+ *client
->max_renew
);
417 if(server
->max_renew
)
418 t
= min(t
, start
+ *server
->max_renew
);
420 t
= min(t
, start
+ realm
->max_renew
);
422 ALLOC(et
.renew_till
);
424 et
.flags
.renewable
= 1;
430 copy_HostAddresses(b
->addresses
, et
.caddr
);
433 copy_EncryptionKey(&et
.key
, &ek
.key
);
435 /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
436 * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
437 * incapable to correctly decode vectors of zero length.
439 * To fix this, always send at least one no-op last_req
441 * If there's a pw_end or valid_end we will use that,
442 * otherwise just a dummy lr.
444 ek
.last_req
.val
= malloc(2 * sizeof(*ek
.last_req
.val
));
447 && (kdc_warn_pwexpire
== 0
448 || kdc_time
+ kdc_warn_pwexpire
<= *client
->pw_end
)) {
449 ek
.last_req
.val
[ek
.last_req
.len
].lr_type
= 6;
450 ek
.last_req
.val
[ek
.last_req
.len
].lr_value
= *client
->pw_end
;
453 if (client
->valid_end
) {
454 ek
.last_req
.val
[ek
.last_req
.len
].lr_type
= 7;
455 ek
.last_req
.val
[ek
.last_req
.len
].lr_value
= *client
->valid_end
;
458 if (ek
.last_req
.len
== 0) {
459 ek
.last_req
.val
[ek
.last_req
.len
].lr_type
= 0;
460 ek
.last_req
.val
[ek
.last_req
.len
].lr_value
= 0;
464 if (client
->valid_end
|| client
->pw_end
) {
465 ALLOC(ek
.key_expiration
);
466 if (client
->valid_end
)
468 *ek
.key_expiration
= min(*client
->valid_end
, *client
->pw_end
);
470 *ek
.key_expiration
= *client
->valid_end
;
472 *ek
.key_expiration
= *client
->pw_end
;
474 ek
.key_expiration
= NULL
;
476 ek
.authtime
= et
.authtime
;
479 *ek
.starttime
= *et
.starttime
;
481 ek
.starttime
= et
.starttime
;
482 ek
.endtime
= et
.endtime
;
484 ALLOC(ek
.renew_till
);
485 *ek
.renew_till
= *et
.renew_till
;
487 ek
.renew_till
= et
.renew_till
;
488 copy_Realm(&rep
.ticket
.realm
, &ek
.srealm
);
489 copy_PrincipalName(&rep
.ticket
.sname
, &ek
.sname
);
492 copy_HostAddresses(et
.caddr
, ek
.caddr
);
496 unsigned char buf
[8192]; /* XXX The data could be indefinite */
499 ret
= encode_EncTicketPart(buf
+ sizeof(buf
) - 1, sizeof(buf
),
501 free_EncTicketPart(&et
);
503 kdc_log(0, "Failed to encode ticket -- %s", client
);
507 ekey
= unseal_key(skey
);
508 krb5_encrypt_EncryptedData(context
,
509 buf
+ sizeof(buf
) - len
,
514 &rep
.ticket
.enc_part
);
517 ret
= encode_EncASRepPart(buf
+ sizeof(buf
) - 1, sizeof(buf
),
519 free_EncKDCRepPart(&ek
);
521 kdc_log(0, "Failed to encode KDC-REP -- %s", client_name
);
524 ekey
= unseal_key(ckey
);
525 krb5_encrypt_EncryptedData(context
,
526 buf
+ sizeof(buf
) - len
,
533 set_salt_padata (&rep
.padata
, ckey
->salt
);
535 ret
= encode_AS_REP(buf
+ sizeof(buf
) - 1, sizeof(buf
), &rep
, &len
);
538 kdc_log(0, "Failed to encode AS-REP -- %s", client_name
);
542 krb5_data_copy(reply
, buf
+ sizeof(buf
) - len
, len
);
546 krb5_mk_error(context
,
556 krb5_free_principal(context
, client_princ
);
558 krb5_free_principal(context
, server_princ
);
561 hdb_free_entry(context
, client
);
565 hdb_free_entry(context
, server
);
573 static krb5_error_code
574 check_tgs_flags(KDC_REQ_BODY
*b
, EncTicketPart
*tgt
, EncTicketPart
*et
)
576 KDCOptions f
= b
->kdc_options
;
579 if(!tgt
->flags
.invalid
|| tgt
->starttime
== NULL
){
580 kdc_log(0, "Bad request to validate ticket");
581 return KRB5KDC_ERR_BADOPTION
;
583 if(*tgt
->starttime
< kdc_time
){
584 kdc_log(0, "Early request to validate ticket");
585 return KRB5KRB_AP_ERR_TKT_NYV
;
588 et
->flags
.invalid
= 0;
589 }else if(tgt
->flags
.invalid
){
590 kdc_log(0, "Ticket-granting ticket has INVALID flag set");
591 return KRB5KRB_AP_ERR_TKT_INVALID
;
595 if(!tgt
->flags
.forwardable
){
596 kdc_log(0, "Bad request for forwardable ticket");
597 return KRB5KDC_ERR_BADOPTION
;
599 et
->flags
.forwardable
= 1;
602 if(!tgt
->flags
.forwardable
){
603 kdc_log(0, "Request to forward non-forwardable ticket");
604 return KRB5KDC_ERR_BADOPTION
;
606 et
->flags
.forwarded
= 1;
607 et
->caddr
= b
->addresses
;
609 if(tgt
->flags
.forwarded
)
610 et
->flags
.forwarded
= 1;
613 if(!tgt
->flags
.proxiable
){
614 kdc_log(0, "Bad request for proxiable ticket");
615 return KRB5KDC_ERR_BADOPTION
;
617 et
->flags
.proxiable
= 1;
620 if(!tgt
->flags
.proxiable
){
621 kdc_log(0, "Request to proxy non-proxiable ticket");
622 return KRB5KDC_ERR_BADOPTION
;
625 et
->caddr
= b
->addresses
;
630 if(f
.allow_postdate
){
631 if(!tgt
->flags
.may_postdate
){
632 kdc_log(0, "Bad request for post-datable ticket");
633 return KRB5KDC_ERR_BADOPTION
;
635 et
->flags
.may_postdate
= 1;
638 if(!tgt
->flags
.may_postdate
){
639 kdc_log(0, "Bad request for postdated ticket");
640 return KRB5KDC_ERR_BADOPTION
;
643 *et
->starttime
= *b
->from
;
644 et
->flags
.postdated
= 1;
645 et
->flags
.invalid
= 1;
646 }else if(b
->from
&& *b
->from
> kdc_time
+ context
->max_skew
){
647 kdc_log(0, "Ticket cannot be postdated");
648 return KRB5KDC_ERR_CANNOT_POSTDATE
;
652 if(!tgt
->flags
.renewable
){
653 kdc_log(0, "Bad request for renewable ticket");
654 return KRB5KDC_ERR_BADOPTION
;
656 et
->flags
.renewable
= 1;
657 ALLOC(et
->renew_till
);
658 *et
->renew_till
= *b
->rtime
;
662 if(!tgt
->flags
.renewable
|| tgt
->renew_till
== NULL
){
663 kdc_log(0, "Request to renew non-renewable ticket");
664 return KRB5KDC_ERR_BADOPTION
;
666 old_life
= tgt
->endtime
;
668 old_life
-= *tgt
->starttime
;
670 old_life
-= tgt
->authtime
;
671 et
->endtime
= *et
->starttime
+ old_life
;
674 /* check for excess flags */
678 static krb5_error_code
679 fix_transited_encoding(TransitedEncoding
*tr
,
680 const char *client_realm
,
681 const char *server_realm
,
682 const char *tgt_realm
)
684 krb5_error_code ret
= 0;
685 if(strcmp(client_realm
, tgt_realm
) && strcmp(server_realm
, tgt_realm
)){
686 char **realms
= NULL
, **tmp
;
690 if(tr
->tr_type
!= DOMAIN_X500_COMPRESS
){
691 kdc_log(0, "Unknown transited type: %u",
693 return KRB5KDC_ERR_TRTYPE_NOSUPP
;
695 ret
= krb5_domain_x500_decode(tr
->contents
,
701 krb5_warn(context
, ret
, "Decoding transited encoding");
705 tmp
= realloc(realms
, (num_realms
+ 1) * sizeof(*realms
));
711 realms
[num_realms
] = strdup(tgt_realm
);
712 if(realms
[num_realms
] == NULL
){
717 free_TransitedEncoding(tr
);
718 tr
->tr_type
= DOMAIN_X500_COMPRESS
;
719 ret
= krb5_domain_x500_encode(realms
, num_realms
, &tr
->contents
);
721 krb5_warn(context
, ret
, "Encoding transited encoding");
723 for(i
= 0; i
< num_realms
; i
++)
731 static krb5_error_code
732 tgs_make_reply(KDC_REQ_BODY
*b
, EncTicketPart
*tgt
,
733 hdb_entry
*server
, hdb_entry
*client
,
734 krb5_principal client_principal
,
741 KDCOptions f
= b
->kdc_options
;
747 /* Find appropriate key */
748 for(i
= 0; i
< b
->etype
.len
; i
++){
749 ret
= hdb_etype2key(context
, server
, b
->etype
.val
[i
], &skey
);
755 kdc_log(0, "Failed to find requested etype");
756 return KRB5KDC_ERR_ETYPE_NOSUPP
;
759 etype
= b
->etype
.val
[i
];
761 memset(&rep
, 0, sizeof(rep
));
762 memset(&et
, 0, sizeof(et
));
763 memset(&ek
, 0, sizeof(ek
));
766 rep
.msg_type
= krb_tgs_rep
;
768 et
.authtime
= tgt
->authtime
;
770 et
.endtime
= min(tgt
->endtime
, *b
->till
);
772 *et
.starttime
= kdc_time
;
774 ret
= check_tgs_flags(b
, tgt
, &et
);
778 copy_TransitedEncoding(&tgt
->transited
, &et
.transited
);
779 ret
= fix_transited_encoding(&et
.transited
,
780 *krb5_princ_realm(context
, client_principal
),
781 *krb5_princ_realm(context
, server
->principal
),
782 *krb5_princ_realm(context
, krbtgt
->principal
));
784 free_TransitedEncoding(&et
.transited
);
789 copy_Realm(krb5_princ_realm(context
, server
->principal
),
791 krb5_principal2principalname(&rep
.ticket
.sname
, server
->principal
);
792 copy_Realm(&tgt
->crealm
, &rep
.crealm
);
793 copy_PrincipalName(&tgt
->cname
, &rep
.cname
);
794 rep
.ticket
.tkt_vno
= 5;
798 et
.caddr
= tgt
->caddr
;
802 life
= et
.endtime
- *et
.starttime
;
803 if(client
&& client
->max_life
)
804 life
= min(life
, *client
->max_life
);
806 life
= min(life
, *server
->max_life
);
807 et
.endtime
= *et
.starttime
+ life
;
809 if(f
.renewable_ok
&& tgt
->flags
.renewable
&&
810 et
.renew_till
== NULL
&& et
.endtime
< *b
->till
){
811 et
.flags
.renewable
= 1;
812 ALLOC(et
.renew_till
);
813 *et
.renew_till
= *b
->till
;
817 renew
= *et
.renew_till
- et
.authtime
;
818 if(client
&& client
->max_renew
)
819 renew
= min(renew
, *client
->max_renew
);
820 if(server
->max_renew
)
821 renew
= min(renew
, *server
->max_renew
);
822 *et
.renew_till
= et
.authtime
+ renew
;
826 *et
.renew_till
= min(*et
.renew_till
, *tgt
->renew_till
);
827 *et
.starttime
= min(*et
.starttime
, *et
.renew_till
);
828 et
.endtime
= min(et
.endtime
, *et
.renew_till
);
831 *et
.starttime
= min(*et
.starttime
, et
.endtime
);
833 if(*et
.starttime
== et
.endtime
){
834 ret
= KRB5KDC_ERR_NEVER_VALID
;
837 if(et
.renew_till
&& et
.endtime
== *et
.renew_till
){
839 et
.renew_till
= NULL
;
840 et
.flags
.renewable
= 0;
843 et
.flags
.pre_authent
= tgt
->flags
.pre_authent
;
844 et
.flags
.hw_authent
= tgt
->flags
.hw_authent
;
846 /* XXX Check enc-authorization-data */
848 krb5_generate_random_keyblock(context
,
851 et
.crealm
= tgt
->crealm
;
852 et
.cname
= tgt
->cname
;
855 /* MIT must have at least one last_req */
857 ek
.last_req
.val
= calloc(1, sizeof(*ek
.last_req
.val
));
860 ek
.authtime
= et
.authtime
;
861 ek
.starttime
= et
.starttime
;
862 ek
.endtime
= et
.endtime
;
863 ek
.renew_till
= et
.renew_till
;
864 ek
.srealm
= rep
.ticket
.realm
;
865 ek
.sname
= rep
.ticket
.sname
;
869 unsigned char buf
[8192]; /* XXX The data could be indefinite */
871 ret
= encode_EncTicketPart(buf
+ sizeof(buf
) - 1,
872 sizeof(buf
), &et
, &len
);
874 kdc_log(0, "Failed to encode EncTicketPart: %s",
875 krb5_get_err_text(context
, ret
));
878 ekey
= unseal_key(skey
);
879 krb5_encrypt_EncryptedData(context
, buf
+ sizeof(buf
) - len
, len
,
883 &rep
.ticket
.enc_part
);
886 ret
= encode_EncTGSRepPart(buf
+ sizeof(buf
) - 1,
887 sizeof(buf
), &ek
, &len
);
889 kdc_log(0, "Failed to encode EncTicketPart: %s",
890 krb5_get_err_text(context
, ret
));
894 /* It is somewhat unclear where the etype in the following
895 encryption should come from. What we have is a session
896 key in the passed tgt, and a list of preferred etypes
897 *for the new ticket*. Should we pick the best possible
898 etype, given the keytype in the tgt, or should we look
899 at the etype list here as well? What if the tgt
900 session key is DES3 and we want a ticket with a (say)
901 CAST session key. Should the DES3 etype be added to the
902 etype list, even if we don't want a session key with
906 krb5_encrypt_EncryptedData(context
,
907 buf
+ sizeof(buf
) - len
, len
,
913 ret
= encode_TGS_REP(buf
+ sizeof(buf
) - 1, sizeof(buf
), &rep
, &len
);
915 kdc_log(0, "Failed to encode TGS-REP: %s",
916 krb5_get_err_text(context
, ret
));
919 krb5_data_copy(reply
, buf
+ sizeof(buf
) - len
, len
);
922 free_TransitedEncoding(&et
.transited
);
927 free_LastReq(&ek
.last_req
);
928 memset(et
.key
.keyvalue
.data
, 0, et
.key
.keyvalue
.length
);
929 free_EncryptionKey(&et
.key
);
934 static krb5_error_code
935 tgs_check_authenticator(krb5_auth_context ac
,
936 KDC_REQ_BODY
*b
, krb5_keyblock
*key
)
938 krb5_authenticator auth
;
940 unsigned char buf
[8192];
943 krb5_auth_getauthenticator(context
, ac
, &auth
);
944 if(auth
->cksum
== NULL
){
945 kdc_log(0, "No authenticator in request");
946 ret
= KRB5KRB_AP_ERR_INAPP_CKSUM
;
950 if (auth
->cksum
->cksumtype
!= CKSUMTYPE_RSA_MD4
&&
951 auth
->cksum
->cksumtype
!= CKSUMTYPE_RSA_MD5
&&
952 auth
->cksum
->cksumtype
!= CKSUMTYPE_RSA_MD5_DES
){
953 kdc_log(0, "Bad checksum type in authenticator: %d",
954 auth
->cksum
->cksumtype
);
955 ret
= KRB5KRB_AP_ERR_INAPP_CKSUM
;
960 ret
= encode_KDC_REQ_BODY(buf
+ sizeof(buf
) - 1, sizeof(buf
),
963 kdc_log(0, "Failed to encode KDC-REQ-BODY: %s",
964 krb5_get_err_text(context
, ret
));
967 ret
= krb5_verify_checksum(context
, buf
+ sizeof(buf
) - len
, len
,
971 kdc_log(0, "Failed to verify checksum: %s",
972 krb5_get_err_text(context
, ret
));
975 free_Authenticator(auth
);
981 is_krbtgt(PrincipalName
*p
)
983 if(p
->name_string
.len
== 2 && strcmp(p
->name_string
.val
[0], "krbtgt") == 0)
984 return p
->name_string
.val
[1];
992 const char *new_realm
= krb5_config_get_string(context
->cf
,
997 return (Realm
)new_realm
;
1001 static krb5_error_code
1002 tgs_rep2(KDC_REQ_BODY
*b
,
1009 krb5_error_code ret
;
1010 krb5_principal princ
;
1011 krb5_auth_context ac
= NULL
;
1012 krb5_ticket
*ticket
= NULL
;
1013 krb5_flags ap_req_options
;
1014 const char *e_text
= NULL
;
1019 krb5_principal cp
= NULL
;
1020 krb5_principal sp
= NULL
;
1022 memset(&ap_req
, 0, sizeof(ap_req
));
1023 ret
= krb5_decode_ap_req(context
, &pa_data
->padata_value
, &ap_req
);
1025 kdc_log(0, "Failed to decode AP-REQ: %s",
1026 krb5_get_err_text(context
, ret
));
1030 if(!is_krbtgt(&ap_req
.ticket
.sname
)){
1031 kdc_log(0, "PA-DATA is not a ticket-granting ticket");
1032 ret
= KRB5KDC_ERR_POLICY
; /* ? */
1036 principalname2krb5_principal(&princ
,
1037 ap_req
.ticket
.sname
,
1038 ap_req
.ticket
.realm
);
1040 krbtgt
= db_fetch(princ
);
1042 if(krbtgt
== NULL
) {
1044 krb5_unparse_name(context
, princ
, &p
);
1045 kdc_log(0, "Ticket-granting ticket not found in database: %s", p
);
1047 ret
= KRB5KRB_AP_ERR_NOT_US
;
1051 ekey
= unseal_key(&krbtgt
->keys
.val
[0]); /* XXX */
1052 ret
= krb5_verify_ap_req(context
,
1061 krb5_free_principal(context
, princ
);
1063 kdc_log(0, "Failed to verify AP-REQ: %s",
1064 krb5_get_err_text(context
, ret
));
1068 tgt
= &ticket
->ticket
;
1070 ret
= tgs_check_authenticator(ac
, b
, &tgt
->key
);
1072 krb5_auth_con_free(context
, ac
);
1075 kdc_log(0, "Failed to verify authenticator: %s",
1076 krb5_get_err_text(context
, ret
));
1083 char *spn
= NULL
, *cpn
= NULL
;
1084 hdb_entry
*server
= NULL
, *client
= NULL
;
1085 TransitedEncoding tr
;
1092 if(b
->kdc_options
.enc_tkt_in_skey
&&
1093 b
->additional_tickets
&&
1094 b
->additional_tickets
->len
>= 1){
1097 principalname2krb5_principal(&p
,
1098 b
->additional_tickets
->val
[0].sname
,
1099 b
->additional_tickets
->val
[0].realm
);
1101 krb5_free_principal(context
, p
);
1103 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
1108 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
1112 principalname2krb5_principal(&sp
, *s
, r
);
1113 krb5_unparse_name(context
, sp
, &spn
);
1114 principalname2krb5_principal(&cp
, tgt
->cname
, tgt
->crealm
);
1115 krb5_unparse_name(context
, cp
, &cpn
);
1116 kdc_log(0, "TGS-REQ %s from %s for %s", cpn
, from
, spn
);
1118 server
= db_fetch(sp
);
1122 Realm req_rlm
, new_rlm
;
1123 if(loop
++ < 2 && (req_rlm
= is_krbtgt(&sp
->name
))){
1124 new_rlm
= find_rpath(req_rlm
);
1126 kdc_log(5, "krbtgt for realm %s not found, trying %s",
1128 krb5_free_principal(context
, sp
);
1130 krb5_make_principal(context
, &sp
, r
,
1131 "krbtgt", new_rlm
, NULL
);
1132 krb5_unparse_name(context
, sp
, &spn
);
1136 kdc_log(0, "Server not found in database: %s", spn
);
1137 ret
= KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN
;
1141 client
= db_fetch(cp
);
1143 kdc_log(1, "Client not found in database: %s", cpn
);
1145 /* XXX check client only if same realm as krbtgt-instance */
1147 kdc_log(0, "Client not found in database: %s", cpn
);
1148 ret
= KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN
;
1154 if((b
->kdc_options
.validate
|| b
->kdc_options
.renew
) &&
1155 !krb5_principal_compare(context
,
1157 server
->principal
)){
1158 kdc_log(0, "Inconsistent request.");
1159 ret
= KRB5KDC_ERR_SERVER_NOMATCH
;
1163 ret
= tgs_make_reply(b
, tgt
, server
, client
, cp
, krbtgt
, reply
);
1170 hdb_free_entry(context
, server
);
1174 hdb_free_entry(context
, client
);
1181 krb5_mk_error(context
,
1189 krb5_free_principal(context
, cp
);
1190 krb5_free_principal(context
, sp
);
1192 krb5_free_ticket(context
, ticket
);
1195 free_AP_REQ(&ap_req
);
1198 hdb_free_entry(context
, krbtgt
);
1205 tgs_rep(KDC_REQ
*req
,
1209 krb5_error_code ret
;
1211 PA_DATA
*pa_data
= NULL
;
1213 if(req
->padata
== NULL
){
1214 ret
= KRB5KDC_ERR_PREAUTH_REQUIRED
; /* XXX ??? */
1215 kdc_log(0, "TGS-REQ from %s without PA-DATA", from
);
1219 for(i
= 0; i
< req
->padata
->len
; i
++)
1220 if(req
->padata
->val
[i
].padata_type
== pa_tgs_req
){
1221 pa_data
= &req
->padata
->val
[i
];
1224 if(pa_data
== NULL
){
1225 ret
= KRB5KDC_ERR_PADATA_TYPE_NOSUPP
;
1227 kdc_log(0, "TGS-REQ from %s without PA-TGS-REQ", from
);
1230 ret
= tgs_rep2(&req
->req_body
, pa_data
, data
, from
);
1232 if(ret
&& data
->data
== NULL
)
1233 krb5_mk_error(context
,