aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacques Vidrine <nectar@FreeBSD.org>2004-05-05 20:01:06 +0000
committerJacques Vidrine <nectar@FreeBSD.org>2004-05-05 20:01:06 +0000
commit18bab81cc1b09b9d60a0d1dae0da4cf13421dada (patch)
tree4b0f5f95587fe836834224665f398ba38dbbb11a
parent4a3041fa055ee510f52d7216aa90a8e1f020d824 (diff)
downloadsrc-18bab81cc1b09b9d60a0d1dae0da4cf13421dada.tar.gz
src-18bab81cc1b09b9d60a0d1dae0da4cf13421dada.zip
Merge from 4-STABLE 1.1.1.2.2.4 config.c, 1.1.1.2.2.5 kdc.8,
1.1.1.2.2.4 kdc_locl.h, 1.1.1.2.2.5 kerberos5.c, 1.1.1.3.2.5 krb5-protos.h, 1.1.1.3.2.3 rd_req.c, 1.1.1.3.2.3 transited.c: Correctly validate the transited field in Kerberos tickets. Approved by: so
Notes
Notes: svn path=/releng/4.9/; revision=128977
-rw-r--r--UPDATING3
-rw-r--r--crypto/heimdal/kdc/config.c22
-rw-r--r--crypto/heimdal/kdc/kdc.823
-rw-r--r--crypto/heimdal/kdc/kdc_locl.h5
-rw-r--r--crypto/heimdal/kdc/kerberos5.c236
-rw-r--r--crypto/heimdal/lib/krb5/krb5-protos.h9
-rw-r--r--crypto/heimdal/lib/krb5/rd_req.c57
-rw-r--r--crypto/heimdal/lib/krb5/transited.c49
-rw-r--r--sys/conf/newvers.sh2
9 files changed, 301 insertions, 105 deletions
diff --git a/UPDATING b/UPDATING
index ddab9811a8b7..460745737383 100644
--- a/UPDATING
+++ b/UPDATING
@@ -17,6 +17,9 @@ minimal number of processes, if possible, for that patch. For those
updates that don't have an advisory, or to be safe, you can do a full
build and install as described in the COMMON ITEMS section.
+20040505: p6 FreeBSD-SA-04:08.heimdal
+ Correctly validate the transited field in Kerberos tickets.
+
20040415: p5 FreeBSD-SA-04:07.cvs
Correct some path validation errors in CVS.
diff --git a/crypto/heimdal/kdc/config.c b/crypto/heimdal/kdc/config.c
index 165e309e0c9e..00d924cb5467 100644
--- a/crypto/heimdal/kdc/config.c
+++ b/crypto/heimdal/kdc/config.c
@@ -64,6 +64,8 @@ krb5_boolean encode_as_rep_as_tgs_rep; /* bug compatibility */
krb5_boolean check_ticket_addresses;
krb5_boolean allow_null_ticket_addresses;
krb5_boolean allow_anonymous;
+int trpolicy;
+static const char *trpolicy_str;
static struct getarg_strings addresses_str; /* addresses to listen on */
krb5_addresses explicit_addresses;
@@ -287,9 +289,8 @@ configure(int argc, char **argv)
get_dbinfo();
- if(max_request_str){
+ if(max_request_str)
max_request = parse_bytes(max_request_str, NULL);
- }
if(max_request == 0){
p = krb5_config_get_string (context,
@@ -352,6 +353,23 @@ configure(int argc, char **argv)
allow_anonymous =
krb5_config_get_bool(context, NULL, "kdc",
"allow-anonymous", NULL);
+ trpolicy_str =
+ krb5_config_get_string_default(context, NULL, "always-check", "kdc",
+ "transited-policy", NULL);
+ if(strcasecmp(trpolicy_str, "always-check") == 0)
+ trpolicy = TRPOLICY_ALWAYS_CHECK;
+ else if(strcasecmp(trpolicy_str, "allow-per-principal") == 0)
+ trpolicy = TRPOLICY_ALLOW_PER_PRINCIPAL;
+ else if(strcasecmp(trpolicy_str, "always-honour-request") == 0)
+ trpolicy = TRPOLICY_ALWAYS_HONOUR_REQUEST;
+ else {
+ kdc_log(0, "unknown transited-policy: %s, reverting to always-check",
+ trpolicy_str);
+ trpolicy = TRPOLICY_ALWAYS_CHECK;
+ }
+
+ krb5_config_get_bool_default(context, NULL, TRUE, "kdc",
+ "enforce-transited-policy", NULL);
#ifdef KRB4
if(v4_realm == NULL){
p = krb5_config_get_string (context, NULL,
diff --git a/crypto/heimdal/kdc/kdc.8 b/crypto/heimdal/kdc/kdc.8
index 20c180a4d7d3..33859212261f 100644
--- a/crypto/heimdal/kdc/kdc.8
+++ b/crypto/heimdal/kdc/kdc.8
@@ -1,6 +1,6 @@
.\" $Id: kdc.8,v 1.17 2002/08/28 21:09:05 joda Exp $
.\"
-.Dd August 22, 2002
+.Dd October 22, 2003
.Dt KDC 8
.Os HEIMDAL
.Sh NAME
@@ -128,6 +128,27 @@ Permit tickets with no addresses. This option is only relevant when
check-ticket-addresses is TRUE.
.It Li allow-anonymous = Va boolean
Permit anonymous tickets with no addresses.
+.It Li transited-policy = Xo
+.Li always-check \*(Ba
+.Li allow-per-principal |
+.Li always-honour-request
+.Xc
+This controls how KDC requests with the
+.Li disable-transited-check
+flag are handled. It can be one of:
+.Bl -tag -width "xxx" -offset indent
+.It Li always-check
+Always check transited encoding, this is the default.
+.It Li allow-per-principal
+Currently this is identical to
+.Li always-check .
+In a future release, it will be possible to mark a principal as able
+to handle unchecked requests.
+.It Li always-honour-request
+Always do what the client asked.
+In a future release, it will be possible to force a check per
+principal.
+.El
.It encode_as_rep_as_tgs_rep = Va boolean
Encode AS-Rep as TGS-Rep to be bug-compatible with old DCE code. The
Heimdal clients allow both.
diff --git a/crypto/heimdal/kdc/kdc_locl.h b/crypto/heimdal/kdc/kdc_locl.h
index 6ab28d0dccc6..9b0c2cda0513 100644
--- a/crypto/heimdal/kdc/kdc_locl.h
+++ b/crypto/heimdal/kdc/kdc_locl.h
@@ -62,6 +62,11 @@ extern krb5_boolean encode_as_rep_as_tgs_rep;
extern krb5_boolean check_ticket_addresses;
extern krb5_boolean allow_null_ticket_addresses;
extern krb5_boolean allow_anonymous;
+enum { TRPOLICY_ALWAYS_CHECK,
+ TRPOLICY_ALLOW_PER_PRINCIPAL,
+ TRPOLICY_ALWAYS_HONOUR_REQUEST };
+extern int trpolicy;
+extern int enable_v4_cross_realm;
#ifdef KRB4
extern char *v4_realm;
diff --git a/crypto/heimdal/kdc/kerberos5.c b/crypto/heimdal/kdc/kerberos5.c
index 7ba968083ee5..35949babd854 100644
--- a/crypto/heimdal/kdc/kerberos5.c
+++ b/crypto/heimdal/kdc/kerberos5.c
@@ -355,10 +355,13 @@ get_pa_etype_info(METHOD_DATA *md, hdb_entry *client,
if(n != pa.len) {
char *name;
- krb5_unparse_name(context, client->principal, &name);
+ ret = krb5_unparse_name(context, client->principal, &name);
+ if (ret)
+ name = "<unparse_name failed>";
kdc_log(0, "internal error in get_pa_etype_info(%s): %d != %d",
name, n, pa.len);
- free(name);
+ if (ret == 0)
+ free(name);
pa.len = n;
}
@@ -496,8 +499,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,28 +509,32 @@ 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);
+ ret = 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);
+ ret = krb5_unparse_name(context, client_princ, &client_name);
}
+ 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);
- if(ret)
- goto out;
-
ret = db_fetch(client_princ, &client);
if(ret){
kdc_log(0, "UNKNOWN -- %s: %s", client_name,
@@ -559,7 +566,6 @@ as_rep(KDC_REQ *req,
while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
krb5_data ts_data;
PA_ENC_TS_ENC p;
- time_t patime;
size_t len;
EncryptedData enc_data;
Key *pa_key;
@@ -635,7 +641,6 @@ as_rep(KDC_REQ *req,
client_name);
continue;
}
- patime = p.patimestamp;
free_PA_ENC_TS_ENC(&p);
if (abs(kdc_time - p.patimestamp) > context->max_skew) {
ret = KRB5KDC_ERR_PREAUTH_FAILED;
@@ -716,9 +721,10 @@ as_rep(KDC_REQ *req,
if (ret == 0) {
kdc_log(5, "Using %s/%s", cet, set);
free(set);
- } else
- free(cet);
- } else
+ }
+ free(cet);
+ }
+ if (ret != 0)
kdc_log(5, "Using e-types %d/%d", cetype, setype);
}
@@ -841,13 +847,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);
@@ -914,8 +915,8 @@ as_rep(KDC_REQ *req,
client->kvno, &ckey->key, &e_text, reply);
free_EncTicketPart(&et);
free_EncKDCRepPart(&ek);
- free_AS_REP(&rep);
out:
+ free_AS_REP(&rep);
if(ret){
krb5_mk_error(context,
ret,
@@ -929,9 +930,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);
@@ -1054,33 +1057,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;
@@ -1097,16 +1102,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;
}
@@ -1172,18 +1207,35 @@ tgs_make_reply(KDC_REQ_BODY *b,
ret = check_tgs_flags(b, tgt, &et);
if(ret)
- return 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));
- if(ret){
- free_TransitedEncoding(&et.transited);
- return ret;
- }
-
+ if(ret)
+ goto out;
copy_Realm(krb5_princ_realm(context, server->principal),
&rep.ticket.realm);
@@ -1278,7 +1330,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)
@@ -1380,13 +1432,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;
}
@@ -1456,10 +1508,14 @@ tgs_rep2(KDC_REQ_BODY *b,
if(ret) {
char *p;
- krb5_unparse_name(context, princ, &p);
+ ret = krb5_unparse_name(context, princ, &p);
+ if (ret != 0)
+ p = "<unparse_name failed>";
+ krb5_free_principal(context, princ);
kdc_log(0, "Ticket-granting ticket not found in database: %s: %s",
p, krb5_get_err_text(context, ret));
- free(p);
+ if (ret == 0)
+ free(p);
ret = KRB5KRB_AP_ERR_NOT_US;
goto out2;
}
@@ -1468,12 +1524,16 @@ tgs_rep2(KDC_REQ_BODY *b,
*ap_req.ticket.enc_part.kvno != krbtgt->kvno){
char *p;
- krb5_unparse_name (context, princ, &p);
+ ret = krb5_unparse_name (context, princ, &p);
+ krb5_free_principal(context, princ);
+ if (ret != 0)
+ p = "<unparse_name failed>";
kdc_log(0, "Ticket kvno = %d, DB kvno = %d (%s)",
*ap_req.ticket.enc_part.kvno,
krbtgt->kvno,
p);
- free (p);
+ if (ret == 0)
+ free (p);
ret = KRB5KRB_AP_ERR_BADKEYVER;
goto out2;
}
@@ -1657,9 +1717,13 @@ tgs_rep2(KDC_REQ_BODY *b,
}
principalname2krb5_principal(&sp, *s, r);
- krb5_unparse_name(context, sp, &spn);
+ ret = krb5_unparse_name(context, sp, &spn);
+ if (ret)
+ goto out;
principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
- krb5_unparse_name(context, cp, &cpn);
+ ret = krb5_unparse_name(context, cp, &cpn);
+ if (ret)
+ goto out;
unparse_flags (KDCOptions2int(b->kdc_options), KDCOptions_units,
opt_str, sizeof(opt_str));
if(*opt_str)
@@ -1676,7 +1740,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);
@@ -1684,7 +1748,9 @@ tgs_rep2(KDC_REQ_BODY *b,
free(spn);
krb5_make_principal(context, &sp, r,
KRB5_TGS_NAME, new_rlm, NULL);
- krb5_unparse_name(context, sp, &spn);
+ ret = krb5_unparse_name(context, sp, &spn);
+ if (ret)
+ goto out;
goto server_lookup;
}
}
@@ -1697,7 +1763,9 @@ tgs_rep2(KDC_REQ_BODY *b,
free(spn);
krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
realms[0], NULL);
- krb5_unparse_name(context, sp, &spn);
+ ret = krb5_unparse_name(context, sp, &spn);
+ if (ret)
+ goto out;
krb5_free_host_realm(context, realms);
goto server_lookup;
}
@@ -1725,6 +1793,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;
diff --git a/crypto/heimdal/lib/krb5/krb5-protos.h b/crypto/heimdal/lib/krb5/krb5-protos.h
index 91a28f1f8e35..bce4cc23e0fc 100644
--- a/crypto/heimdal/lib/krb5/krb5-protos.h
+++ b/crypto/heimdal/lib/krb5/krb5-protos.h
@@ -521,6 +521,15 @@ krb5_change_password (
krb5_data */*result_string*/);
krb5_error_code
+krb5_check_transited (
+ krb5_context /*context*/,
+ krb5_const_realm /*client_realm*/,
+ krb5_const_realm /*server_realm*/,
+ krb5_realm */*realms*/,
+ int /*num_realms*/,
+ int */*bad_realm*/);
+
+krb5_error_code
krb5_check_transited_realms (
krb5_context /*context*/,
const char *const */*realms*/,
diff --git a/crypto/heimdal/lib/krb5/rd_req.c b/crypto/heimdal/lib/krb5/rd_req.c
index 69fb059e4e63..cc68bcfa0dc0 100644
--- a/crypto/heimdal/lib/krb5/rd_req.c
+++ b/crypto/heimdal/lib/krb5/rd_req.c
@@ -129,6 +129,32 @@ krb5_decode_ap_req(krb5_context context,
return 0;
}
+static krb5_error_code
+check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc)
+{
+ char **realms;
+ int num_realms;
+ krb5_error_code ret;
+
+ if(enc->transited.tr_type != DOMAIN_X500_COMPRESS)
+ return KRB5KDC_ERR_TRTYPE_NOSUPP;
+
+ if(enc->transited.contents.length == 0)
+ return 0;
+
+ ret = krb5_domain_x500_decode(context, enc->transited.contents,
+ &realms, &num_realms,
+ enc->crealm,
+ ticket->realm);
+ if(ret)
+ return ret;
+ ret = krb5_check_transited(context, enc->crealm,
+ ticket->realm,
+ realms, num_realms, NULL);
+ free(realms);
+ return ret;
+}
+
krb5_error_code
krb5_decrypt_ticket(krb5_context context,
Ticket *ticket,
@@ -161,6 +187,14 @@ krb5_decrypt_ticket(krb5_context context,
krb5_clear_error_string (context);
return KRB5KRB_AP_ERR_TKT_EXPIRED;
}
+
+ if(!t.flags.transited_policy_checked) {
+ ret = check_transited(context, ticket, &t);
+ if(ret) {
+ free_EncTicketPart(&t);
+ return ret;
+ }
+ }
}
if(out)
@@ -209,29 +243,6 @@ out:
return ret;
}
-#if 0
-static krb5_error_code
-check_transited(krb5_context context,
- krb5_ticket *ticket)
-{
- char **realms;
- int num_realms;
- krb5_error_code ret;
-
- if(ticket->ticket.transited.tr_type != DOMAIN_X500_COMPRESS)
- return KRB5KDC_ERR_TRTYPE_NOSUPP;
-
- ret = krb5_domain_x500_decode(ticket->ticket.transited.contents,
- &realms, &num_realms,
- ticket->client->realm,
- ticket->server->realm);
- if(ret)
- return ret;
- ret = krb5_check_transited_realms(context, realms, num_realms, NULL);
- free(realms);
- return ret;
-}
-#endif
krb5_error_code
krb5_verify_ap_req(krb5_context context,
diff --git a/crypto/heimdal/lib/krb5/transited.c b/crypto/heimdal/lib/krb5/transited.c
index b587c63bb6f8..33da76d39385 100644
--- a/crypto/heimdal/lib/krb5/transited.c
+++ b/crypto/heimdal/lib/krb5/transited.c
@@ -304,6 +304,12 @@ krb5_domain_x500_decode(krb5_context context,
struct tr_realm *p, **q;
int ret;
+ if(tr.length == 0) {
+ *realms = NULL;
+ *num_realms = 0;
+ return 0;
+ }
+
/* split string in components */
ret = decode_realms(context, tr.data, tr.length, &r);
if(ret)
@@ -358,6 +364,9 @@ krb5_domain_x500_encode(char **realms, int num_realms, krb5_data *encoding)
char *s = NULL;
int len = 0;
int i;
+ krb5_data_zero(encoding);
+ if (num_realms == 0)
+ return 0;
for(i = 0; i < num_realms; i++){
len += strlen(realms[i]);
if(realms[i][0] == '/')
@@ -365,6 +374,8 @@ krb5_domain_x500_encode(char **realms, int num_realms, krb5_data *encoding)
}
len += num_realms - 1;
s = malloc(len + 1);
+ if (s == NULL)
+ return ENOMEM;
*s = '\0';
for(i = 0; i < num_realms; i++){
if(i && i < num_realms - 1)
@@ -379,6 +390,44 @@ krb5_domain_x500_encode(char **realms, int num_realms, krb5_data *encoding)
}
krb5_error_code
+krb5_check_transited(krb5_context context,
+ krb5_const_realm client_realm,
+ krb5_const_realm server_realm,
+ krb5_realm *realms,
+ int num_realms,
+ int *bad_realm)
+{
+ char **tr_realms;
+ char **p;
+ int i;
+
+ if(num_realms == 0)
+ return 0;
+
+ tr_realms = krb5_config_get_strings(context, NULL,
+ "capaths",
+ client_realm,
+ server_realm,
+ NULL);
+ for(i = 0; i < num_realms; i++) {
+ for(p = tr_realms; p && *p; p++) {
+ if(strcmp(*p, realms[i]) == 0)
+ break;
+ }
+ if(p == NULL || *p == NULL) {
+ krb5_config_free_strings(tr_realms);
+ krb5_set_error_string (context, "no transit through realm %s",
+ realms[i]);
+ if(bad_realm)
+ *bad_realm = i;
+ return KRB5KRB_AP_ERR_ILL_CR_TKT;
+ }
+ }
+ krb5_config_free_strings(tr_realms);
+ return 0;
+}
+
+krb5_error_code
krb5_check_transited_realms(krb5_context context,
const char *const *realms,
int num_realms,
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index a870fa0a9346..8d6bdd1a7a69 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -36,7 +36,7 @@
TYPE="FreeBSD"
REVISION="4.9"
-BRANCH="RELEASE-p5"
+BRANCH="RELEASE-p6"
RELEASE="${REVISION}-${BRANCH}"
VERSION="${TYPE} ${RELEASE}"