I'm very pleased to announce the release of our new website and documentation using the new toolchain with Hugo and AsciiDoctor. To get more information about the new toolchain please read the FreeBSD Documentation Project Primer[1], Hugo docs[2] and AsciiDoctor docs[3]. Acknowledgment: Benedict Reuschling <bcr@> Glen Barber <gjb@> Hiroki Sato <hrs@> Li-Wen Hsu <lwhsu@> Sean Chittenden <seanc@> The FreeBSD Foundation [1] https://docs.FreeBSD.org/en/books/fdp-primer/ [2] https://gohugo.io/documentation/ [3] https://docs.asciidoctor.org/home/ Approved by: doceng, core
558 lines
16 KiB
Diff
558 lines
16 KiB
Diff
diff -urN crypto/heimdal/kdc/config.c heimdal-0.5.3/kdc/config.c
|
|
--- crypto/heimdal/kdc/config.c 2003-03-17 07:46:55.000000000 +0100
|
|
+++ crypto/heimdal/kdc/config.c 2004-02-16 20:08:49.000000000 +0100
|
|
@@ -64,6 +64,8 @@
|
|
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;
|
|
@@ -292,9 +294,8 @@
|
|
|
|
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,
|
|
@@ -365,6 +366,23 @@
|
|
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 -urN crypto/heimdal/kdc/kdc.8 heimdal-0.5.3/kdc/kdc.8
|
|
--- crypto/heimdal/kdc/kdc.8 2003-03-17 07:47:03.000000000 +0100
|
|
+++ crypto/heimdal/kdc/kdc.8 2004-02-16 18:50:11.000000000 +0100
|
|
@@ -2,5 +2,5 @@
|
|
.\"
|
|
-.Dd August 22, 2002
|
|
+.Dd October 22, 2003
|
|
.Dt KDC 8
|
|
.Os HEIMDAL
|
|
.Sh NAME
|
|
@@ -145,6 +145,27 @@
|
|
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 -u crypto/heimdal/kdc/kdc_locl.h:1.1.1.6 crypto/heimdal/kdc/kdc_locl.h:1.1.1.7
|
|
--- crypto/heimdal/kdc/kdc_locl.h:1.1.1.6 Thu Oct 9 14:36:19 2003
|
|
+++ crypto/heimdal/kdc/kdc_locl.h Sat Apr 3 15:20:48 2004
|
|
@@ -62,6 +62,10 @@
|
|
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_524;
|
|
extern int enable_v4_cross_realm;
|
|
|
|
--- crypto/heimdal/kdc/kerberos5.c 9 Oct 2003 19:36:19 -0000 1.1.1.8
|
|
+++ crypto/heimdal/kdc/kerberos5.c 3 Apr 2004 21:20:51 -0000 1.1.1.9
|
|
@@ -496,8 +496,8 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
}
|
|
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
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 @@
|
|
}
|
|
|
|
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 @@
|
|
|
|
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);
|
|
@@ -1724,6 +1776,18 @@
|
|
goto out;
|
|
}
|
|
#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)
|
|
diff -urN crypto/heimdal/lib/krb5/krb5-protos.h heimdal-0.5.3/lib/krb5/krb5-protos.h
|
|
--- crypto/heimdal/lib/krb5/krb5-protos.h 2003-03-17 11:27:40.000000000 +0100
|
|
+++ crypto/heimdal/lib/krb5/krb5-protos.h 2004-04-01 16:16:33.000000000 +0200
|
|
@@ -521,6 +521,15 @@
|
|
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 -urN crypto/heimdal/lib/krb5/rd_req.c heimdal-0.5.3/lib/krb5/rd_req.c
|
|
--- crypto/heimdal/lib/krb5/rd_req.c 2001-06-18 04:48:18.000000000 +0200
|
|
+++ crypto/heimdal/lib/krb5/rd_req.c 2004-02-16 19:17:47.000000000 +0100
|
|
@@ -129,6 +129,32 @@
|
|
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_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 @@
|
|
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 -urN crypto/heimdal/lib/krb5/transited.c heimdal-0.5.3/lib/krb5/transited.c
|
|
--- crypto/heimdal/lib/krb5/transited.c 2002-09-09 16:03:03.000000000 +0200
|
|
+++ crypto/heimdal/lib/krb5/transited.c 2004-02-16 19:20:52.000000000 +0100
|
|
@@ -304,6 +304,12 @@
|
|
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 @@
|
|
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 @@
|
|
}
|
|
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_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,
|