2
* Copyright (c) 1997-2008 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
39
* return the realm of a krbtgt-ticket or NULL
43
get_krbtgt_realm(const PrincipalName *p)
45
if(p->name_string.len == 2
46
&& strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
47
return p->name_string.val[1];
53
* The KDC might add a signed path to the ticket authorization data
54
* field. This is to avoid server impersonating clients and the
55
* request constrained delegation.
57
* This is done by storing a KRB5_AUTHDATA_IF_RELEVANT with a single
58
* entry of type KRB5SignedPath.
61
static krb5_error_code
62
find_KRB5SignedPath(krb5_context context,
63
const AuthorizationData *ad,
66
AuthorizationData child;
70
if (ad == NULL || ad->len == 0)
71
return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
75
if (ad->val[pos].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
76
return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
78
ret = decode_AuthorizationData(ad->val[pos].ad_data.data,
79
ad->val[pos].ad_data.length,
83
krb5_set_error_message(context, ret, "Failed to decode "
84
"IF_RELEVANT with %d", ret);
89
free_AuthorizationData(&child);
90
return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
93
if (child.val[0].ad_type != KRB5_AUTHDATA_SIGNTICKET) {
94
free_AuthorizationData(&child);
95
return KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
99
ret = der_copy_octet_string(&child.val[0].ad_data, data);
100
free_AuthorizationData(&child);
105
_kdc_add_KRB5SignedPath(krb5_context context,
106
krb5_kdc_configuration *config,
107
hdb_entry_ex *krbtgt,
108
krb5_enctype enctype,
109
krb5_const_principal server,
110
KRB5SignedPathPrincipals *principals,
116
krb5_crypto crypto = NULL;
119
if (server && principals) {
120
ret = add_KRB5SignedPathPrincipals(principals, server);
126
KRB5SignedPathData spd;
128
spd.encticket = *tkt;
129
spd.delegated = principals;
131
ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
135
if (data.length != size)
136
krb5_abortx(context, "internal asn.1 encoder error");
141
ret = hdb_enctype2key(context, &krbtgt->entry, enctype, &key);
143
ret = krb5_crypto_init(context, &key->key, 0, &crypto);
151
* Fill in KRB5SignedPath
155
sp.delegated = principals;
157
ret = krb5_create_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 0,
158
data.data, data.length, &sp.cksum);
159
krb5_crypto_destroy(context, crypto);
164
ASN1_MALLOC_ENCODE(KRB5SignedPath, data.data, data.length, &sp, &size, ret);
165
free_Checksum(&sp.cksum);
168
if (data.length != size)
169
krb5_abortx(context, "internal asn.1 encoder error");
173
* Add IF-RELEVANT(KRB5SignedPath) to the last slot in
174
* authorization data field.
177
ret = _kdc_tkt_add_if_relevant_ad(context, tkt,
178
KRB5_AUTHDATA_SIGNTICKET, &data);
179
krb5_data_free(&data);
184
static krb5_error_code
185
check_KRB5SignedPath(krb5_context context,
186
krb5_kdc_configuration *config,
187
hdb_entry_ex *krbtgt,
189
KRB5SignedPathPrincipals **delegated,
194
krb5_crypto crypto = NULL;
199
ret = find_KRB5SignedPath(context, tkt->authorization_data, &data);
201
KRB5SignedPathData spd;
203
AuthorizationData *ad;
206
ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL);
207
krb5_data_free(&data);
211
spd.encticket = *tkt;
212
/* the KRB5SignedPath is the last entry */
213
ad = spd.encticket.authorization_data;
215
spd.encticket.authorization_data = NULL;
216
spd.delegated = sp.delegated;
218
ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length,
221
spd.encticket.authorization_data = ad;
223
free_KRB5SignedPath(&sp);
226
if (data.length != size)
227
krb5_abortx(context, "internal asn.1 encoder error");
231
ret = hdb_enctype2key(context, &krbtgt->entry, sp.etype, &key);
233
ret = krb5_crypto_init(context, &key->key, 0, &crypto);
236
free_KRB5SignedPath(&sp);
240
ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH,
241
data.data, data.length,
243
krb5_crypto_destroy(context, crypto);
246
free_KRB5SignedPath(&sp);
250
if (delegated && sp.delegated) {
252
*delegated = malloc(sizeof(*sp.delegated));
253
if (*delegated == NULL) {
254
free_KRB5SignedPath(&sp);
258
ret = copy_KRB5SignedPathPrincipals(*delegated, sp.delegated);
260
free_KRB5SignedPath(&sp);
266
free_KRB5SignedPath(&sp);
278
static krb5_error_code
279
check_PAC(krb5_context context,
280
krb5_kdc_configuration *config,
281
const krb5_principal client_principal,
282
hdb_entry_ex *client,
283
hdb_entry_ex *server,
284
const EncryptionKey *server_key,
285
const EncryptionKey *krbtgt_key,
290
AuthorizationData *ad = tkt->authorization_data;
294
if (ad == NULL || ad->len == 0)
297
for (i = 0; i < ad->len; i++) {
298
AuthorizationData child;
300
if (ad->val[i].ad_type != KRB5_AUTHDATA_IF_RELEVANT)
303
ret = decode_AuthorizationData(ad->val[i].ad_data.data,
304
ad->val[i].ad_data.length,
308
krb5_set_error_message(context, ret, "Failed to decode "
309
"IF_RELEVANT with %d", ret);
312
for (j = 0; j < child.len; j++) {
314
if (child.val[j].ad_type == KRB5_AUTHDATA_WIN2K_PAC) {
318
ret = krb5_pac_parse(context,
319
child.val[j].ad_data.data,
320
child.val[j].ad_data.length,
322
free_AuthorizationData(&child);
326
ret = krb5_pac_verify(context, pac, tkt->authtime,
330
krb5_pac_free(context, pac);
334
ret = _kdc_pac_verify(context, client_principal,
335
client, server, &pac);
337
krb5_pac_free(context, pac);
342
ret = _krb5_pac_sign(context, pac, tkt->authtime,
344
server_key, krbtgt_key, rspac);
346
krb5_pac_free(context, pac);
351
free_AuthorizationData(&child);
360
static krb5_error_code
361
check_tgs_flags(krb5_context context,
362
krb5_kdc_configuration *config,
363
KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et)
365
KDCOptions f = b->kdc_options;
368
if(!tgt->flags.invalid || tgt->starttime == NULL){
369
kdc_log(context, config, 0,
370
"Bad request to validate ticket");
371
return KRB5KDC_ERR_BADOPTION;
373
if(*tgt->starttime > kdc_time){
374
kdc_log(context, config, 0,
375
"Early request to validate ticket");
376
return KRB5KRB_AP_ERR_TKT_NYV;
379
et->flags.invalid = 0;
380
}else if(tgt->flags.invalid){
381
kdc_log(context, config, 0,
382
"Ticket-granting ticket has INVALID flag set");
383
return KRB5KRB_AP_ERR_TKT_INVALID;
387
if(!tgt->flags.forwardable){
388
kdc_log(context, config, 0,
389
"Bad request for forwardable ticket");
390
return KRB5KDC_ERR_BADOPTION;
392
et->flags.forwardable = 1;
395
if(!tgt->flags.forwardable){
396
kdc_log(context, config, 0,
397
"Request to forward non-forwardable ticket");
398
return KRB5KDC_ERR_BADOPTION;
400
et->flags.forwarded = 1;
401
et->caddr = b->addresses;
403
if(tgt->flags.forwarded)
404
et->flags.forwarded = 1;
407
if(!tgt->flags.proxiable){
408
kdc_log(context, config, 0,
409
"Bad request for proxiable ticket");
410
return KRB5KDC_ERR_BADOPTION;
412
et->flags.proxiable = 1;
415
if(!tgt->flags.proxiable){
416
kdc_log(context, config, 0,
417
"Request to proxy non-proxiable ticket");
418
return KRB5KDC_ERR_BADOPTION;
421
et->caddr = b->addresses;
426
if(f.allow_postdate){
427
if(!tgt->flags.may_postdate){
428
kdc_log(context, config, 0,
429
"Bad request for post-datable ticket");
430
return KRB5KDC_ERR_BADOPTION;
432
et->flags.may_postdate = 1;
435
if(!tgt->flags.may_postdate){
436
kdc_log(context, config, 0,
437
"Bad request for postdated ticket");
438
return KRB5KDC_ERR_BADOPTION;
441
*et->starttime = *b->from;
442
et->flags.postdated = 1;
443
et->flags.invalid = 1;
444
}else if(b->from && *b->from > kdc_time + context->max_skew){
445
kdc_log(context, config, 0, "Ticket cannot be postdated");
446
return KRB5KDC_ERR_CANNOT_POSTDATE;
450
if(!tgt->flags.renewable){
451
kdc_log(context, config, 0,
452
"Bad request for renewable ticket");
453
return KRB5KDC_ERR_BADOPTION;
455
et->flags.renewable = 1;
456
ALLOC(et->renew_till);
457
_kdc_fix_time(&b->rtime);
458
*et->renew_till = *b->rtime;
462
if(!tgt->flags.renewable || tgt->renew_till == NULL){
463
kdc_log(context, config, 0,
464
"Request to renew non-renewable ticket");
465
return KRB5KDC_ERR_BADOPTION;
467
old_life = tgt->endtime;
469
old_life -= *tgt->starttime;
471
old_life -= tgt->authtime;
472
et->endtime = *et->starttime + old_life;
473
if (et->renew_till != NULL)
474
et->endtime = min(*et->renew_till, et->endtime);
478
/* checks for excess flags */
479
if(f.request_anonymous && !config->allow_anonymous){
480
kdc_log(context, config, 0,
481
"Request for anonymous ticket");
482
return KRB5KDC_ERR_BADOPTION;
492
static krb5_error_code
493
check_constrained_delegation(krb5_context context,
494
krb5_kdc_configuration *config,
495
hdb_entry_ex *client,
496
krb5_const_principal server)
498
const HDB_Ext_Constrained_delegation_acl *acl;
502
ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);
504
krb5_clear_error_message(context);
509
for (i = 0; i < acl->len; i++) {
510
if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE)
514
kdc_log(context, config, 0,
515
"Bad request for constrained delegation");
516
return KRB5KDC_ERR_BADOPTION;
523
static krb5_error_code
524
verify_flags (krb5_context context,
525
krb5_kdc_configuration *config,
526
const EncTicketPart *et,
529
if(et->endtime < kdc_time){
530
kdc_log(context, config, 0, "Ticket expired (%s)", pstr);
531
return KRB5KRB_AP_ERR_TKT_EXPIRED;
533
if(et->flags.invalid){
534
kdc_log(context, config, 0, "Ticket not valid (%s)", pstr);
535
return KRB5KRB_AP_ERR_TKT_NYV;
544
static krb5_error_code
545
fix_transited_encoding(krb5_context context,
546
krb5_kdc_configuration *config,
547
krb5_boolean check_policy,
548
const TransitedEncoding *tr,
550
const char *client_realm,
551
const char *server_realm,
552
const char *tgt_realm)
554
krb5_error_code ret = 0;
555
char **realms, **tmp;
556
unsigned int num_realms;
559
switch (tr->tr_type) {
560
case DOMAIN_X500_COMPRESS:
564
* Allow empty content of type 0 because that is was Microsoft
565
* generates in their TGT.
567
if (tr->contents.length == 0)
569
kdc_log(context, config, 0,
570
"Transited type 0 with non empty content");
571
return KRB5KDC_ERR_TRTYPE_NOSUPP;
573
kdc_log(context, config, 0,
574
"Unknown transited type: %u", tr->tr_type);
575
return KRB5KDC_ERR_TRTYPE_NOSUPP;
578
ret = krb5_domain_x500_decode(context,
585
krb5_warn(context, ret,
586
"Decoding transited encoding");
589
if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
590
/* not us, so add the previous realm to transited set */
591
if (num_realms + 1 > UINT_MAX/sizeof(*realms)) {
595
tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
601
realms[num_realms] = strdup(tgt_realm);
602
if(realms[num_realms] == NULL){
608
if(num_realms == 0) {
609
if(strcmp(client_realm, server_realm))
610
kdc_log(context, config, 0,
611
"cross-realm %s -> %s", client_realm, server_realm);
615
for(i = 0; i < num_realms; i++)
616
l += strlen(realms[i]) + 2;
620
for(i = 0; i < num_realms; i++) {
622
strlcat(rs, ", ", l);
623
strlcat(rs, realms[i], l);
625
kdc_log(context, config, 0,
626
"cross-realm %s -> %s via [%s]",
627
client_realm, server_realm, rs);
632
ret = krb5_check_transited(context, client_realm,
634
realms, num_realms, NULL);
636
krb5_warn(context, ret, "cross-realm %s -> %s",
637
client_realm, server_realm);
640
et->flags.transited_policy_checked = 1;
642
et->transited.tr_type = DOMAIN_X500_COMPRESS;
643
ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
645
krb5_warn(context, ret, "Encoding transited encoding");
647
for(i = 0; i < num_realms; i++)
654
static krb5_error_code
655
tgs_make_reply(krb5_context context,
656
krb5_kdc_configuration *config,
658
krb5_const_principal tgt_name,
659
const EncTicketPart *tgt,
660
const EncryptionKey *serverkey,
661
const krb5_keyblock *sessionkey,
663
AuthorizationData *auth_data,
664
hdb_entry_ex *server,
665
krb5_principal server_principal,
666
const char *server_name,
667
hdb_entry_ex *client,
668
krb5_principal client_principal,
669
hdb_entry_ex *krbtgt,
670
krb5_enctype krbtgt_etype,
671
KRB5SignedPathPrincipals *spp,
672
const krb5_data *rspac,
673
const METHOD_DATA *enc_pa_data,
680
KDCOptions f = b->kdc_options;
684
memset(&rep, 0, sizeof(rep));
685
memset(&et, 0, sizeof(et));
686
memset(&ek, 0, sizeof(ek));
689
rep.msg_type = krb_tgs_rep;
691
et.authtime = tgt->authtime;
692
_kdc_fix_time(&b->till);
693
et.endtime = min(tgt->endtime, *b->till);
695
*et.starttime = kdc_time;
697
ret = check_tgs_flags(context, config, b, tgt, &et);
701
/* We should check the transited encoding if:
702
1) the request doesn't ask not to be checked
703
2) globally enforcing a check
704
3) principal requires checking
705
4) we allow non-check per-principal, but principal isn't marked as allowing this
706
5) we don't globally allow this
709
#define GLOBAL_FORCE_TRANSITED_CHECK \
710
(config->trpolicy == TRPOLICY_ALWAYS_CHECK)
711
#define GLOBAL_ALLOW_PER_PRINCIPAL \
712
(config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
713
#define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \
714
(config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
716
/* these will consult the database in future release */
717
#define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0
718
#define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0
720
ret = fix_transited_encoding(context, config,
721
!f.disable_transited_check ||
722
GLOBAL_FORCE_TRANSITED_CHECK ||
723
PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
724
!((GLOBAL_ALLOW_PER_PRINCIPAL &&
725
PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
726
GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
727
&tgt->transited, &et,
728
*krb5_princ_realm(context, client_principal),
729
*krb5_princ_realm(context, server->entry.principal),
730
*krb5_princ_realm(context, krbtgt->entry.principal));
734
copy_Realm(krb5_princ_realm(context, server_principal),
736
_krb5_principal2principalname(&rep.ticket.sname, server_principal);
737
copy_Realm(&tgt_name->realm, &rep.crealm);
739
if (f.request_anonymous)
740
_kdc_make_anonymous_principalname (&rep.cname);
743
copy_PrincipalName(&tgt_name->name, &rep.cname);
744
rep.ticket.tkt_vno = 5;
748
et.caddr = tgt->caddr;
752
life = et.endtime - *et.starttime;
753
if(client && client->entry.max_life)
754
life = min(life, *client->entry.max_life);
755
if(server->entry.max_life)
756
life = min(life, *server->entry.max_life);
757
et.endtime = *et.starttime + life;
759
if(f.renewable_ok && tgt->flags.renewable &&
760
et.renew_till == NULL && et.endtime < *b->till){
761
et.flags.renewable = 1;
762
ALLOC(et.renew_till);
763
*et.renew_till = *b->till;
767
renew = *et.renew_till - et.authtime;
768
if(client && client->entry.max_renew)
769
renew = min(renew, *client->entry.max_renew);
770
if(server->entry.max_renew)
771
renew = min(renew, *server->entry.max_renew);
772
*et.renew_till = et.authtime + renew;
776
*et.renew_till = min(*et.renew_till, *tgt->renew_till);
777
*et.starttime = min(*et.starttime, *et.renew_till);
778
et.endtime = min(et.endtime, *et.renew_till);
781
*et.starttime = min(*et.starttime, et.endtime);
783
if(*et.starttime == et.endtime){
784
ret = KRB5KDC_ERR_NEVER_VALID;
787
if(et.renew_till && et.endtime == *et.renew_till){
789
et.renew_till = NULL;
790
et.flags.renewable = 0;
793
et.flags.pre_authent = tgt->flags.pre_authent;
794
et.flags.hw_authent = tgt->flags.hw_authent;
795
et.flags.anonymous = tgt->flags.anonymous;
796
et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate;
799
/* XXX Check enc-authorization-data */
800
et.authorization_data = calloc(1, sizeof(*et.authorization_data));
801
if (et.authorization_data == NULL) {
805
ret = copy_AuthorizationData(auth_data, et.authorization_data);
809
/* Filter out type KRB5SignedPath */
810
ret = find_KRB5SignedPath(context, et.authorization_data, NULL);
812
if (et.authorization_data->len == 1) {
813
free_AuthorizationData(et.authorization_data);
814
free(et.authorization_data);
815
et.authorization_data = NULL;
817
AuthorizationData *ad = et.authorization_data;
818
free_AuthorizationDataElement(&ad->val[ad->len - 1]);
826
* No not need to filter out the any PAC from the
827
* auth_data since it's signed by the KDC.
829
ret = _kdc_tkt_add_if_relevant_ad(context, &et,
830
KRB5_AUTHDATA_WIN2K_PAC,
836
ret = krb5_copy_keyblock_contents(context, sessionkey, &et.key);
839
et.crealm = tgt->crealm;
840
et.cname = tgt_name->name;
843
/* MIT must have at least one last_req */
845
ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
846
if (ek.last_req.val == NULL) {
852
ek.authtime = et.authtime;
853
ek.starttime = et.starttime;
854
ek.endtime = et.endtime;
855
ek.renew_till = et.renew_till;
856
ek.srealm = rep.ticket.realm;
857
ek.sname = rep.ticket.sname;
859
_kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime,
860
et.endtime, et.renew_till);
862
/* Don't sign cross realm tickets, they can't be checked anyway */
864
char *r = get_krbtgt_realm(&ek.sname);
866
if (r == NULL || strcmp(r, ek.srealm) == 0) {
867
ret = _kdc_add_KRB5SignedPath(context,
879
if (enc_pa_data->len) {
880
rep.padata = calloc(1, sizeof(*rep.padata));
881
if (rep.padata == NULL) {
885
ret = copy_METHOD_DATA(enc_pa_data, rep.padata);
890
if (krb5_enctype_valid(context, et.key.keytype) != 0
891
&& _kdc_is_weak_expection(server->entry.principal, et.key.keytype))
893
krb5_enctype_enable(context, et.key.keytype);
898
/* It is somewhat unclear where the etype in the following
899
encryption should come from. What we have is a session
900
key in the passed tgt, and a list of preferred etypes
901
*for the new ticket*. Should we pick the best possible
902
etype, given the keytype in the tgt, or should we look
903
at the etype list here as well? What if the tgt
904
session key is DES3 and we want a ticket with a (say)
905
CAST session key. Should the DES3 etype be added to the
906
etype list, even if we don't want a session key with
908
ret = _kdc_encode_reply(context, config,
909
&rep, &et, &ek, et.key.keytype,
911
serverkey, 0, &tgt->key, e_text, reply);
913
krb5_enctype_disable(context, et.key.keytype);
917
free_TransitedEncoding(&et.transited);
922
if(et.authorization_data) {
923
free_AuthorizationData(et.authorization_data);
924
free(et.authorization_data);
926
free_LastReq(&ek.last_req);
927
memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
928
free_EncryptionKey(&et.key);
932
static krb5_error_code
933
tgs_check_authenticator(krb5_context context,
934
krb5_kdc_configuration *config,
935
krb5_auth_context ac,
940
krb5_authenticator auth;
947
krb5_auth_con_getauthenticator(context, ac, &auth);
948
if(auth->cksum == NULL){
949
kdc_log(context, config, 0, "No authenticator in request");
950
ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
954
* according to RFC1510 it doesn't need to be keyed,
955
* but according to the latest draft it needs to.
959
!krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
962
!krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
963
kdc_log(context, config, 0, "Bad checksum type in authenticator: %d",
964
auth->cksum->cksumtype);
965
ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
969
/* XXX should not re-encode this */
970
ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
972
kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s",
973
krb5_get_err_text(context, ret));
976
if(buf_size != len) {
978
kdc_log(context, config, 0, "Internal error in ASN.1 encoder");
979
*e_text = "KDC internal error";
980
ret = KRB5KRB_ERR_GENERIC;
983
ret = krb5_crypto_init(context, key, 0, &crypto);
986
kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
987
krb5_get_err_text(context, ret));
990
ret = krb5_verify_checksum(context,
992
KRB5_KU_TGS_REQ_AUTH_CKSUM,
997
krb5_crypto_destroy(context, crypto);
999
kdc_log(context, config, 0,
1000
"Failed to verify authenticator checksum: %s",
1001
krb5_get_err_text(context, ret));
1004
free_Authenticator(auth);
1014
find_rpath(krb5_context context, Realm crealm, Realm srealm)
1016
const char *new_realm = krb5_config_get_string(context,
1027
need_referral(krb5_context context, krb5_kdc_configuration *config,
1028
const KDCOptions * const options, krb5_principal server,
1029
krb5_realm **realms)
1033
if(!options->canonicalize && server->name.name_type != KRB5_NT_SRV_INST)
1036
if (server->name.name_string.len == 1)
1037
name = server->name.name_string.val[0];
1038
if (server->name.name_string.len > 1)
1039
name = server->name.name_string.val[1];
1043
kdc_log(context, config, 0, "Searching referral for %s", name);
1045
return _krb5_get_host_realm_int(context, name, FALSE, realms) == 0;
1048
static krb5_error_code
1049
tgs_parse_request(krb5_context context,
1050
krb5_kdc_configuration *config,
1052
const PA_DATA *tgs_req,
1053
hdb_entry_ex **krbtgt,
1054
krb5_enctype *krbtgt_etype,
1055
krb5_ticket **ticket,
1056
const char **e_text,
1058
const struct sockaddr *from_addr,
1061
AuthorizationData **auth_data)
1064
krb5_error_code ret;
1065
krb5_principal princ;
1066
krb5_auth_context ac = NULL;
1067
krb5_flags ap_req_options;
1068
krb5_flags verify_ap_req_flags;
1076
memset(&ap_req, 0, sizeof(ap_req));
1077
ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
1079
kdc_log(context, config, 0, "Failed to decode AP-REQ: %s",
1080
krb5_get_err_text(context, ret));
1084
if(!get_krbtgt_realm(&ap_req.ticket.sname)){
1085
/* XXX check for ticket.sname == req.sname */
1086
kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket");
1087
ret = KRB5KDC_ERR_POLICY; /* ? */
1091
_krb5_principalname2krb5_principal(context,
1093
ap_req.ticket.sname,
1094
ap_req.ticket.realm);
1096
ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt);
1100
ret = krb5_unparse_name(context, princ, &p);
1102
p = "<unparse_name failed>";
1103
krb5_free_principal(context, princ);
1104
kdc_log(context, config, 0,
1105
"Ticket-granting ticket not found in database: %s: %s",
1106
p, krb5_get_err_text(context, ret));
1109
ret = KRB5KRB_AP_ERR_NOT_US;
1113
if(ap_req.ticket.enc_part.kvno &&
1114
*ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){
1117
ret = krb5_unparse_name (context, princ, &p);
1118
krb5_free_principal(context, princ);
1120
p = "<unparse_name failed>";
1121
kdc_log(context, config, 0,
1122
"Ticket kvno = %d, DB kvno = %d (%s)",
1123
*ap_req.ticket.enc_part.kvno,
1124
(*krbtgt)->entry.kvno,
1128
ret = KRB5KRB_AP_ERR_BADKEYVER;
1132
*krbtgt_etype = ap_req.ticket.enc_part.etype;
1134
ret = hdb_enctype2key(context, &(*krbtgt)->entry,
1135
ap_req.ticket.enc_part.etype, &tkey);
1137
char *str = NULL, *p = NULL;
1139
krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
1140
krb5_unparse_name(context, princ, &p);
1141
kdc_log(context, config, 0,
1142
"No server key with enctype %s found for %s",
1143
str ? str : "<unknown enctype>",
1144
p ? p : "<unparse_name failed>");
1147
ret = KRB5KRB_AP_ERR_BADKEYVER;
1151
if (b->kdc_options.validate)
1152
verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
1154
verify_ap_req_flags = 0;
1156
ret = krb5_verify_ap_req2(context,
1161
verify_ap_req_flags,
1164
KRB5_KU_TGS_REQ_AUTH);
1166
krb5_free_principal(context, princ);
1168
kdc_log(context, config, 0, "Failed to verify AP-REQ: %s",
1169
krb5_get_err_text(context, ret));
1174
krb5_authenticator auth;
1176
ret = krb5_auth_con_getauthenticator(context, ac, &auth);
1178
*csec = malloc(sizeof(**csec));
1179
if (*csec == NULL) {
1180
krb5_free_authenticator(context, &auth);
1181
kdc_log(context, config, 0, "malloc failed");
1184
**csec = auth->ctime;
1185
*cusec = malloc(sizeof(**cusec));
1186
if (*cusec == NULL) {
1187
krb5_free_authenticator(context, &auth);
1188
kdc_log(context, config, 0, "malloc failed");
1191
**cusec = auth->cusec;
1192
krb5_free_authenticator(context, &auth);
1196
ret = tgs_check_authenticator(context, config,
1197
ac, b, e_text, &(*ticket)->ticket.key);
1199
krb5_auth_con_free(context, ac);
1203
if (b->enc_authorization_data) {
1204
unsigned usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
1205
krb5_keyblock *subkey;
1208
ret = krb5_auth_con_getremotesubkey(context,
1212
krb5_auth_con_free(context, ac);
1213
kdc_log(context, config, 0, "Failed to get remote subkey: %s",
1214
krb5_get_err_text(context, ret));
1218
usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
1219
ret = krb5_auth_con_getkey(context, ac, &subkey);
1221
krb5_auth_con_free(context, ac);
1222
kdc_log(context, config, 0, "Failed to get session key: %s",
1223
krb5_get_err_text(context, ret));
1228
krb5_auth_con_free(context, ac);
1229
kdc_log(context, config, 0,
1230
"Failed to get key for enc-authorization-data");
1231
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1234
ret = krb5_crypto_init(context, subkey, 0, &crypto);
1236
krb5_auth_con_free(context, ac);
1237
kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1238
krb5_get_err_text(context, ret));
1241
ret = krb5_decrypt_EncryptedData (context,
1244
b->enc_authorization_data,
1246
krb5_crypto_destroy(context, crypto);
1248
krb5_auth_con_free(context, ac);
1249
kdc_log(context, config, 0,
1250
"Failed to decrypt enc-authorization-data");
1251
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1254
krb5_free_keyblock(context, subkey);
1256
if (*auth_data == NULL) {
1257
krb5_auth_con_free(context, ac);
1258
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1261
ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL);
1263
krb5_auth_con_free(context, ac);
1266
kdc_log(context, config, 0, "Failed to decode authorization data");
1267
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
1272
krb5_auth_con_free(context, ac);
1275
free_AP_REQ(&ap_req);
1280
static krb5_error_code
1281
build_server_referral(krb5_context context,
1282
krb5_kdc_configuration *config,
1283
krb5_crypto session,
1284
krb5_const_realm referred_realm,
1285
const PrincipalName *true_principal_name,
1286
const PrincipalName *requested_principal,
1289
PA_ServerReferralData ref;
1290
krb5_error_code ret;
1295
memset(&ref, 0, sizeof(ref));
1297
if (referred_realm) {
1298
ALLOC(ref.referred_realm);
1299
if (ref.referred_realm == NULL)
1301
*ref.referred_realm = strdup(referred_realm);
1302
if (*ref.referred_realm == NULL)
1305
if (true_principal_name) {
1306
ALLOC(ref.true_principal_name);
1307
if (ref.true_principal_name == NULL)
1309
ret = copy_PrincipalName(true_principal_name, ref.true_principal_name);
1313
if (requested_principal) {
1314
ALLOC(ref.requested_principal_name);
1315
if (ref.requested_principal_name == NULL)
1317
ret = copy_PrincipalName(requested_principal,
1318
ref.requested_principal_name);
1323
ASN1_MALLOC_ENCODE(PA_ServerReferralData,
1324
data.data, data.length,
1326
free_PA_ServerReferralData(&ref);
1329
if (data.length != size)
1330
krb5_abortx(context, "internal asn.1 encoder error");
1332
ret = krb5_encrypt_EncryptedData(context, session,
1333
KRB5_KU_PA_SERVER_REFERRAL,
1334
data.data, data.length,
1340
ASN1_MALLOC_ENCODE(EncryptedData,
1341
outdata->data, outdata->length,
1343
free_EncryptedData(&ed);
1346
if (outdata->length != size)
1347
krb5_abortx(context, "internal asn.1 encoder error");
1351
free_PA_ServerReferralData(&ref);
1352
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
1356
static krb5_error_code
1357
tgs_build_reply(krb5_context context,
1358
krb5_kdc_configuration *config,
1361
hdb_entry_ex *krbtgt,
1362
krb5_enctype krbtgt_etype,
1363
krb5_ticket *ticket,
1366
const char **e_text,
1367
AuthorizationData **auth_data,
1368
const struct sockaddr *from_addr,
1371
krb5_error_code ret;
1372
krb5_principal cp = NULL, sp = NULL;
1373
krb5_principal client_principal = NULL;
1374
char *spn = NULL, *cpn = NULL;
1375
hdb_entry_ex *server = NULL, *client = NULL;
1376
krb5_realm ref_realm = NULL;
1377
EncTicketPart *tgt = &ticket->ticket;
1378
KRB5SignedPathPrincipals *spp = NULL;
1380
const EncryptionKey *ekey;
1381
krb5_keyblock sessionkey;
1384
int cross_realm = 0;
1386
METHOD_DATA enc_pa_data;
1391
EncTicketPart adtkt;
1395
memset(&sessionkey, 0, sizeof(sessionkey));
1396
memset(&adtkt, 0, sizeof(adtkt));
1397
krb5_data_zero(&rspac);
1398
memset(&enc_pa_data, 0, sizeof(enc_pa_data));
1403
if(b->kdc_options.enc_tkt_in_skey){
1409
if(b->additional_tickets == NULL ||
1410
b->additional_tickets->len == 0){
1411
ret = KRB5KDC_ERR_BADOPTION; /* ? */
1412
kdc_log(context, config, 0,
1413
"No second ticket present in request");
1416
t = &b->additional_tickets->val[0];
1417
if(!get_krbtgt_realm(&t->sname)){
1418
kdc_log(context, config, 0,
1419
"Additional ticket is not a ticket-granting ticket");
1420
ret = KRB5KDC_ERR_POLICY;
1423
_krb5_principalname2krb5_principal(context, &p, t->sname, t->realm);
1424
ret = _kdc_db_fetch(context, config, p,
1425
HDB_F_GET_CLIENT|HDB_F_GET_SERVER,
1427
krb5_free_principal(context, p);
1429
if (ret == HDB_ERR_NOENTRY)
1430
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1433
ret = hdb_enctype2key(context, &uu->entry,
1434
t->enc_part.etype, &uukey);
1436
_kdc_free_ent(context, uu);
1437
ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1440
ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0);
1441
_kdc_free_ent(context, uu);
1445
ret = verify_flags(context, config, &adtkt, spn);
1453
_krb5_principalname2krb5_principal(context, &sp, *s, r);
1454
ret = krb5_unparse_name(context, sp, &spn);
1457
_krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm);
1458
ret = krb5_unparse_name(context, cp, &cpn);
1461
unparse_flags (KDCOptions2int(b->kdc_options),
1462
asn1_KDCOptions_units(),
1463
opt_str, sizeof(opt_str));
1465
kdc_log(context, config, 0,
1466
"TGS-REQ %s from %s for %s [%s]",
1467
cpn, from, spn, opt_str);
1469
kdc_log(context, config, 0,
1470
"TGS-REQ %s from %s for %s", cpn, from, spn);
1477
ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER | HDB_F_CANON,
1481
const char *new_rlm;
1485
if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
1487
new_rlm = find_rpath(context, tgt->crealm, req_rlm);
1489
kdc_log(context, config, 5, "krbtgt for realm %s "
1490
"not found, trying %s",
1492
krb5_free_principal(context, sp);
1494
krb5_make_principal(context, &sp, r,
1495
KRB5_TGS_NAME, new_rlm, NULL);
1496
ret = krb5_unparse_name(context, sp, &spn);
1502
ref_realm = strdup(new_rlm);
1506
} else if(need_referral(context, config, &b->kdc_options, sp, &realms)) {
1507
if (strcmp(realms[0], sp->realm) != 0) {
1508
kdc_log(context, config, 5,
1509
"Returning a referral to realm %s for "
1510
"server %s that was not found",
1512
krb5_free_principal(context, sp);
1514
krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
1516
ret = krb5_unparse_name(context, sp, &spn);
1522
ref_realm = strdup(realms[0]);
1524
krb5_free_host_realm(context, realms);
1527
krb5_free_host_realm(context, realms);
1529
kdc_log(context, config, 0,
1530
"Server not found in database: %s: %s", spn,
1531
krb5_get_err_text(context, ret));
1532
if (ret == HDB_ERR_NOENTRY)
1533
ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
1537
ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
1540
const char *krbtgt_realm;
1543
* If the client belongs to the same realm as our krbtgt, it
1544
* should exist in the local database.
1549
krb5_principal_get_comp_string(context,
1550
krbtgt->entry.principal, 1);
1552
if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) {
1553
if (ret == HDB_ERR_NOENTRY)
1554
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
1555
kdc_log(context, config, 1, "Client no longer in database: %s",
1560
kdc_log(context, config, 1, "Client not found in database: %s: %s",
1561
cpn, krb5_get_err_text(context, ret));
1567
* Select enctype, return key and kvno.
1573
if(b->kdc_options.enc_tkt_in_skey) {
1576
for(i = 0; i < b->etype.len; i++)
1577
if (b->etype.val[i] == adtkt.key.keytype)
1579
if(i == b->etype.len) {
1580
kdc_log(context, config, 0,
1581
"Addition ticket have not matching etypes", spp);
1582
krb5_clear_error_message(context);
1583
return KRB5KDC_ERR_ETYPE_NOSUPP;
1585
etype = b->etype.val[i];
1590
ret = _kdc_find_etype(context, server, b->etype.val, b->etype.len,
1593
kdc_log(context, config, 0,
1594
"Server (%s) has no support for etypes", spn);
1598
kvno = server->entry.kvno;
1601
ret = krb5_generate_random_keyblock(context, etype, &sessionkey);
1607
* Validate authoriation data
1611
* Check that service is in the same realm as the krbtgt. If it's
1612
* not the same, it's someone that is using a uni-directional trust
1616
if (strcmp(krb5_principal_get_realm(context, sp),
1617
krb5_principal_get_comp_string(context,
1618
krbtgt->entry.principal,
1621
ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn);
1622
kdc_log(context, config, 0,
1623
"Request with wrong krbtgt: %s",
1624
(ret == 0) ? tpn : "<unknown>");
1627
ret = KRB5KRB_AP_ERR_NOT_US;
1631
/* check PAC if there is one */
1633
ret = hdb_enctype2key(context, &krbtgt->entry,
1634
krbtgt_etype, &tkey);
1636
kdc_log(context, config, 0,
1637
"Failed to find key for krbtgt PAC check");
1641
ret = check_PAC(context, config, cp,
1642
client, server, ekey, &tkey->key,
1643
tgt, &rspac, &signedpath);
1645
kdc_log(context, config, 0,
1646
"Verify PAC failed for %s (%s) from %s with %s",
1647
spn, cpn, from, krb5_get_err_text(context, ret));
1651
/* also check the krbtgt for signature */
1652
ret = check_KRB5SignedPath(context,
1659
kdc_log(context, config, 0,
1660
"KRB5SignedPath check failed for %s (%s) from %s with %s",
1661
spn, cpn, from, krb5_get_err_text(context, ret));
1669
client_principal = cp;
1672
const PA_DATA *sdata;
1675
sdata = _kdc_find_padata(req, &i, KRB5_PADATA_S4U2SELF);
1680
char *selfcpn = NULL;
1683
ret = decode_PA_S4U2Self(sdata->padata_value.data,
1684
sdata->padata_value.length,
1687
kdc_log(context, config, 0, "Failed to decode PA-S4U2Self");
1691
ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack);
1695
ret = krb5_crypto_init(context, &tgt->key, 0, &crypto);
1697
free_PA_S4U2Self(&self);
1698
krb5_data_free(&datack);
1699
kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
1700
krb5_get_err_text(context, ret));
1704
ret = krb5_verify_checksum(context,
1706
KRB5_KU_OTHER_CKSUM,
1710
krb5_data_free(&datack);
1711
krb5_crypto_destroy(context, crypto);
1713
free_PA_S4U2Self(&self);
1714
kdc_log(context, config, 0,
1715
"krb5_verify_checksum failed for S4U2Self: %s",
1716
krb5_get_err_text(context, ret));
1720
ret = _krb5_principalname2krb5_principal(context,
1724
free_PA_S4U2Self(&self);
1728
ret = krb5_unparse_name(context, client_principal, &selfcpn);
1733
* Check that service doing the impersonating is
1734
* requesting a ticket to it-self.
1736
if (krb5_principal_compare(context, cp, sp) != TRUE) {
1737
kdc_log(context, config, 0, "S4U2Self: %s is not allowed "
1738
"to impersonate some other user "
1739
"(tried for user %s to service %s)",
1742
ret = KRB5KDC_ERR_BADOPTION; /* ? */
1747
* If the service isn't trusted for authentication to
1748
* delegation, remove the forward flag.
1751
if (client->entry.flags.trusted_for_delegation) {
1752
str = "[forwardable]";
1754
b->kdc_options.forwardable = 0;
1757
kdc_log(context, config, 0, "s4u2self %s impersonating %s to "
1758
"service %s %s", cpn, selfcpn, spn, str);
1764
* Constrained delegation
1768
&& b->additional_tickets != NULL
1769
&& b->additional_tickets->len != 0
1770
&& b->kdc_options.enc_tkt_in_skey == 0)
1772
int ad_signedpath = 0;
1778
* Require that the KDC have issued the service's krbtgt (not
1779
* self-issued ticket with kimpersonate(1).
1782
ret = KRB5KDC_ERR_BADOPTION;
1783
kdc_log(context, config, 0,
1784
"Constrained delegation done on service ticket %s/%s",
1789
t = &b->additional_tickets->val[0];
1791
ret = hdb_enctype2key(context, &client->entry,
1792
t->enc_part.etype, &clientkey);
1794
ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
1798
ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0);
1800
kdc_log(context, config, 0,
1801
"failed to decrypt ticket for "
1802
"constrained delegation from %s to %s ", spn, cpn);
1806
/* check that ticket is valid */
1807
if (adtkt.flags.forwardable == 0) {
1808
kdc_log(context, config, 0,
1809
"Missing forwardable flag on ticket for "
1810
"constrained delegation from %s to %s ", spn, cpn);
1811
ret = KRB5KDC_ERR_BADOPTION;
1815
ret = check_constrained_delegation(context, config, client, sp);
1817
kdc_log(context, config, 0,
1818
"constrained delegation from %s to %s not allowed",
1823
ret = _krb5_principalname2krb5_principal(context,
1830
ret = krb5_unparse_name(context, client_principal, &str);
1834
ret = verify_flags(context, config, &adtkt, str);
1841
* Check that the KDC issued the user's ticket.
1843
ret = check_KRB5SignedPath(context,
1849
if (ret == 0 && !ad_signedpath)
1850
ret = KRB5KDC_ERR_BADOPTION;
1852
kdc_log(context, config, 0,
1853
"KRB5SignedPath check from service %s failed "
1854
"for delegation to %s for client %s "
1855
"from %s failed with %s",
1856
spn, str, cpn, from, krb5_get_err_text(context, ret));
1861
kdc_log(context, config, 0, "constrained delegation for %s "
1862
"from %s to %s", str, cpn, spn);
1870
ret = _kdc_check_flags(context, config,
1877
if((b->kdc_options.validate || b->kdc_options.renew) &&
1878
!krb5_principal_compare(context,
1879
krbtgt->entry.principal,
1880
server->entry.principal)){
1881
kdc_log(context, config, 0, "Inconsistent request.");
1882
ret = KRB5KDC_ERR_SERVER_NOMATCH;
1886
/* check for valid set of addresses */
1887
if(!_kdc_check_addresses(context, config, tgt->caddr, from_addr)) {
1888
ret = KRB5KRB_AP_ERR_BADADDR;
1889
kdc_log(context, config, 0, "Request from wrong address");
1894
* If this is an referral, add server referral data to the
1901
kdc_log(context, config, 0,
1902
"Adding server referral to %s", ref_realm);
1904
ret = krb5_crypto_init(context, &sessionkey, 0, &crypto);
1908
ret = build_server_referral(context, config, crypto, ref_realm,
1909
NULL, s, &pa.padata_value);
1910
krb5_crypto_destroy(context, crypto);
1912
kdc_log(context, config, 0,
1913
"Failed building server referral");
1916
pa.padata_type = KRB5_PADATA_SERVER_REFERRAL;
1918
ret = add_METHOD_DATA(&enc_pa_data, &pa);
1919
krb5_data_free(&pa.padata_value);
1921
kdc_log(context, config, 0,
1922
"Add server referral METHOD-DATA failed");
1931
ret = tgs_make_reply(context,
1957
krb5_data_free(&rspac);
1958
krb5_free_keyblock_contents(context, &sessionkey);
1960
_kdc_free_ent(context, server);
1962
_kdc_free_ent(context, client);
1964
if (client_principal && client_principal != cp)
1965
krb5_free_principal(context, client_principal);
1967
krb5_free_principal(context, cp);
1969
krb5_free_principal(context, sp);
1972
free_METHOD_DATA(&enc_pa_data);
1974
free_EncTicketPart(&adtkt);
1984
_kdc_tgs_rep(krb5_context context,
1985
krb5_kdc_configuration *config,
1989
struct sockaddr *from_addr,
1992
AuthorizationData *auth_data = NULL;
1993
krb5_error_code ret;
1995
const PA_DATA *tgs_req;
1997
hdb_entry_ex *krbtgt = NULL;
1998
krb5_ticket *ticket = NULL;
1999
const char *e_text = NULL;
2000
krb5_enctype krbtgt_etype = ETYPE_NULL;
2002
time_t *csec = NULL;
2005
if(req->padata == NULL){
2006
ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
2007
kdc_log(context, config, 0,
2008
"TGS-REQ from %s without PA-DATA", from);
2012
tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ);
2014
if(tgs_req == NULL){
2015
ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
2017
kdc_log(context, config, 0,
2018
"TGS-REQ from %s without PA-TGS-REQ", from);
2021
ret = tgs_parse_request(context, config,
2022
&req->req_body, tgs_req,
2031
kdc_log(context, config, 0,
2032
"Failed parsing TGS-REQ from %s", from);
2036
ret = tgs_build_reply(context,
2050
kdc_log(context, config, 0,
2051
"Failed building TGS-REP to %s", from);
2056
if (datagram_reply && data->length > config->max_datagram_reply_length) {
2057
krb5_data_free(data);
2058
ret = KRB5KRB_ERR_RESPONSE_TOO_BIG;
2059
e_text = "Reply packet too large";
2063
if(ret && data->data == NULL){
2064
krb5_mk_error(context,
2077
krb5_free_ticket(context, ticket);
2079
_kdc_free_ent(context, krbtgt);
2082
free_AuthorizationData(auth_data);