diff options
Diffstat (limited to 'crypto/heimdal/kdc/kerberos5.c')
-rw-r--r-- | crypto/heimdal/kdc/kerberos5.c | 178 |
1 files changed, 121 insertions, 57 deletions
diff --git a/crypto/heimdal/kdc/kerberos5.c b/crypto/heimdal/kdc/kerberos5.c index 232c3ad..9dc3673 100644 --- a/crypto/heimdal/kdc/kerberos5.c +++ b/crypto/heimdal/kdc/kerberos5.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: kerberos5.c,v 1.145 2003/04/15 11:07:39 lha Exp $"); +RCSID("$Id: kerberos5.c,v 1.145.2.3 2003/12/14 19:43:04 lha Exp $"); #define MAX_TIME ((time_t)((1U << 31) - 1)) @@ -496,8 +496,8 @@ as_rep(KDC_REQ *req, krb5_enctype cetype, setype; EncTicketPart et; EncKDCRepPart ek; - krb5_principal client_princ, server_princ; - char *client_name, *server_name; + krb5_principal client_princ = NULL, server_princ = NULL; + char *client_name = NULL, *server_name = NULL; krb5_error_code ret = 0; const char *e_text = NULL; krb5_crypto crypto; @@ -506,27 +506,30 @@ as_rep(KDC_REQ *req, memset(&rep, 0, sizeof(rep)); if(b->sname == NULL){ - server_name = "<unknown server>"; ret = KRB5KRB_ERR_GENERIC; e_text = "No server in request"; } else{ principalname2krb5_principal (&server_princ, *(b->sname), b->realm); krb5_unparse_name(context, server_princ, &server_name); } + if (ret) { + kdc_log(0, "AS-REQ malformed server name from %s", from); + goto out; + } if(b->cname == NULL){ - client_name = "<unknown client>"; ret = KRB5KRB_ERR_GENERIC; e_text = "No client in request"; } else { principalname2krb5_principal (&client_princ, *(b->cname), b->realm); krb5_unparse_name(context, client_princ, &client_name); } - kdc_log(0, "AS-REQ %s from %s for %s", - client_name, from, server_name); - - if(ret) + if (ret) { + kdc_log(0, "AS-REQ malformed client name from %s", from); goto out; + } + + kdc_log(0, "AS-REQ %s from %s for %s", client_name, from, server_name); ret = db_fetch(client_princ, &client); if(ret){ @@ -842,13 +845,8 @@ as_rep(KDC_REQ *req, copy_HostAddresses(b->addresses, et.caddr); } - { - krb5_data empty_string; - - krb5_data_zero(&empty_string); - et.transited.tr_type = DOMAIN_X500_COMPRESS; - et.transited.contents = empty_string; - } + et.transited.tr_type = DOMAIN_X500_COMPRESS; + krb5_data_zero(&et.transited.contents); copy_EncryptionKey(&et.key, &ek.key); @@ -930,9 +928,11 @@ as_rep(KDC_REQ *req, ret = 0; } out2: - krb5_free_principal(context, client_princ); + if (client_princ) + krb5_free_principal(context, client_princ); free(client_name); - krb5_free_principal(context, server_princ); + if (server_princ) + krb5_free_principal(context, server_princ); free(server_name); if(client) free_ent(client); @@ -1055,33 +1055,35 @@ check_tgs_flags(KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et) } static krb5_error_code -fix_transited_encoding(TransitedEncoding *tr, +fix_transited_encoding(krb5_boolean check_policy, + TransitedEncoding *tr, + EncTicketPart *et, const char *client_realm, const char *server_realm, const char *tgt_realm) { krb5_error_code ret = 0; - if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)){ - char **realms = NULL, **tmp; - int num_realms = 0; - int i; - if(tr->tr_type && tr->contents.length != 0) { - if(tr->tr_type != DOMAIN_X500_COMPRESS){ - kdc_log(0, "Unknown transited type: %u", - tr->tr_type); - return KRB5KDC_ERR_TRTYPE_NOSUPP; - } - ret = krb5_domain_x500_decode(context, - tr->contents, - &realms, - &num_realms, - client_realm, - server_realm); - if(ret){ - krb5_warn(context, ret, "Decoding transited encoding"); - return ret; - } - } + char **realms, **tmp; + int num_realms; + int i; + + if(tr->tr_type != DOMAIN_X500_COMPRESS) { + kdc_log(0, "Unknown transited type: %u", tr->tr_type); + return KRB5KDC_ERR_TRTYPE_NOSUPP; + } + + ret = krb5_domain_x500_decode(context, + tr->contents, + &realms, + &num_realms, + client_realm, + server_realm); + if(ret){ + krb5_warn(context, ret, "Decoding transited encoding"); + return ret; + } + if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) { + /* not us, so add the previous realm to transited set */ if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) { ret = ERANGE; goto free_realms; @@ -1098,16 +1100,46 @@ fix_transited_encoding(TransitedEncoding *tr, goto free_realms; } num_realms++; - free_TransitedEncoding(tr); - tr->tr_type = DOMAIN_X500_COMPRESS; - ret = krb5_domain_x500_encode(realms, num_realms, &tr->contents); - if(ret) - krb5_warn(context, ret, "Encoding transited encoding"); - free_realms: + } + if(num_realms == 0) { + if(strcmp(client_realm, server_realm)) + kdc_log(0, "cross-realm %s -> %s", client_realm, server_realm); + } else { + size_t l = 0; + char *rs; for(i = 0; i < num_realms; i++) - free(realms[i]); - free(realms); + l += strlen(realms[i]) + 2; + rs = malloc(l); + if(rs != NULL) { + *rs = '\0'; + for(i = 0; i < num_realms; i++) { + if(i > 0) + strlcat(rs, ", ", l); + strlcat(rs, realms[i], l); + } + kdc_log(0, "cross-realm %s -> %s via [%s]", client_realm, server_realm, rs); + free(rs); + } } + if(check_policy) { + ret = krb5_check_transited(context, client_realm, + server_realm, + realms, num_realms, NULL); + if(ret) { + krb5_warn(context, ret, "cross-realm %s -> %s", + client_realm, server_realm); + goto free_realms; + } + et->flags.transited_policy_checked = 1; + } + et->transited.tr_type = DOMAIN_X500_COMPRESS; + ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents); + if(ret) + krb5_warn(context, ret, "Encoding transited encoding"); + free_realms: + for(i = 0; i < num_realms; i++) + free(realms[i]); + free(realms); return ret; } @@ -1175,8 +1207,28 @@ tgs_make_reply(KDC_REQ_BODY *b, if(ret) goto out; - copy_TransitedEncoding(&tgt->transited, &et.transited); - ret = fix_transited_encoding(&et.transited, + /* We should check the transited encoding if: + 1) the request doesn't ask not to be checked + 2) globally enforcing a check + 3) principal requires checking + 4) we allow non-check per-principal, but principal isn't marked as allowing this + 5) we don't globally allow this + */ + +#define GLOBAL_FORCE_TRANSITED_CHECK (trpolicy == TRPOLICY_ALWAYS_CHECK) +#define GLOBAL_ALLOW_PER_PRINCIPAL (trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL) +#define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK (trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST) +/* these will consult the database in future release */ +#define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0 +#define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0 + + ret = fix_transited_encoding(!f.disable_transited_check || + GLOBAL_FORCE_TRANSITED_CHECK || + PRINCIPAL_FORCE_TRANSITED_CHECK(server) || + !((GLOBAL_ALLOW_PER_PRINCIPAL && + PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) || + GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK), + &tgt->transited, &et, *krb5_princ_realm(context, client_principal), *krb5_princ_realm(context, server->principal), *krb5_princ_realm(context, krbtgt->principal)); @@ -1276,7 +1328,7 @@ tgs_make_reply(KDC_REQ_BODY *b, DES3? */ ret = encode_reply(&rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey, 0, &tgt->key, e_text, reply); -out: + out: free_TGS_REP(&rep); free_TransitedEncoding(&et.transited); if(et.starttime) @@ -1378,13 +1430,13 @@ get_krbtgt_realm(const PrincipalName *p) } static Realm -find_rpath(Realm r) +find_rpath(Realm crealm, Realm srealm) { const char *new_realm = krb5_config_get_string(context, NULL, - "libdefaults", - "capath", - r, + "capaths", + crealm, + srealm, NULL); return (Realm)new_realm; } @@ -1676,7 +1728,7 @@ tgs_rep2(KDC_REQ_BODY *b, if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) { if(loop++ < 2) { - new_rlm = find_rpath(req_rlm); + new_rlm = find_rpath(tgt->crealm, req_rlm); if(new_rlm) { kdc_log(5, "krbtgt for realm %s not found, trying %s", req_rlm, new_rlm); @@ -1725,6 +1777,18 @@ tgs_rep2(KDC_REQ_BODY *b, } #endif + if(strcmp(krb5_principal_get_realm(context, sp), + krb5_principal_get_comp_string(context, krbtgt->principal, 1)) != 0) { + char *tpn; + ret = krb5_unparse_name(context, krbtgt->principal, &tpn); + kdc_log(0, "Request with wrong krbtgt: %s", (ret == 0) ? tpn : "<unknown>"); + if(ret == 0) + free(tpn); + ret = KRB5KRB_AP_ERR_NOT_US; + goto out; + + } + ret = check_flags(client, cpn, server, spn, FALSE); if(ret) goto out; |