2020-11-18 22:34:00 +00:00
|
|
|
From e0fc680b2fb51513993c4cdaa2c25b292f57a073 Mon Sep 17 00:00:00 2001
|
2020-10-27 20:13:14 +00:00
|
|
|
From: Greg Hudson <ghudson@mit.edu>
|
|
|
|
Date: Wed, 30 Sep 2020 02:12:00 -0400
|
|
|
|
Subject: [PATCH] Avoid passing DB entry structures in KDC
|
|
|
|
|
|
|
|
When validating AS or TGS requests, pass pointers to DB entry
|
|
|
|
structures, not the structures themselves.
|
|
|
|
|
|
|
|
(cherry picked from commit 7ccc08a889b40693b2ce7f108f2cdda51bc04bff)
|
|
|
|
---
|
|
|
|
src/kdc/do_as_req.c | 4 ++--
|
|
|
|
src/kdc/do_tgs_req.c | 2 +-
|
|
|
|
src/kdc/kdc_util.c | 34 +++++++++++++++++-----------------
|
|
|
|
src/kdc/kdc_util.h | 6 +++---
|
|
|
|
src/kdc/tgs_policy.c | 35 ++++++++++++++++++-----------------
|
|
|
|
5 files changed, 41 insertions(+), 40 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
|
|
|
|
index 9ae7b0a5e..c2dfea9b8 100644
|
|
|
|
--- a/src/kdc/do_as_req.c
|
|
|
|
+++ b/src/kdc/do_as_req.c
|
|
|
|
@@ -663,8 +663,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
|
|
|
|
au_state->stage = VALIDATE_POL;
|
|
|
|
|
|
|
|
if ((errcode = validate_as_request(kdc_active_realm,
|
|
|
|
- state->request, *state->client,
|
|
|
|
- *state->server, state->kdc_time,
|
|
|
|
+ state->request, state->client,
|
|
|
|
+ state->server, state->kdc_time,
|
|
|
|
&state->status, &state->e_data))) {
|
|
|
|
errcode += ERROR_TABLE_BASE_krb5;
|
|
|
|
goto errout;
|
|
|
|
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
|
|
|
|
index 74cd19e96..d345797c4 100644
|
|
|
|
--- a/src/kdc/do_tgs_req.c
|
|
|
|
+++ b/src/kdc/do_tgs_req.c
|
|
|
|
@@ -260,7 +260,7 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if ((retval = validate_tgs_request(kdc_active_realm,
|
|
|
|
- request, *server, header_ticket,
|
|
|
|
+ request, server, header_ticket,
|
|
|
|
kdc_time, &status, &e_data))) {
|
|
|
|
if (retval == KDC_ERR_POLICY || retval == KDC_ERR_BADOPTION)
|
|
|
|
au_state->violation = PROT_CONSTRAINT;
|
|
|
|
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
|
|
|
index a4a05b9fa..b2042862a 100644
|
|
|
|
--- a/src/kdc/kdc_util.c
|
|
|
|
+++ b/src/kdc/kdc_util.c
|
|
|
|
@@ -612,8 +612,8 @@ check_anon(kdc_realm_t *kdc_active_realm,
|
|
|
|
KDC_OPT_ENC_TKT_IN_SKEY | KDC_OPT_CNAME_IN_ADDL_TKT)
|
|
|
|
int
|
|
|
|
validate_as_request(kdc_realm_t *kdc_active_realm,
|
|
|
|
- krb5_kdc_req *request, krb5_db_entry client,
|
|
|
|
- krb5_db_entry server, krb5_timestamp kdc_time,
|
|
|
|
+ krb5_kdc_req *request, krb5_db_entry *client,
|
|
|
|
+ krb5_db_entry *server, krb5_timestamp kdc_time,
|
|
|
|
const char **status, krb5_pa_data ***e_data)
|
|
|
|
{
|
|
|
|
krb5_error_code ret;
|
|
|
|
@@ -627,7 +627,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The client must not be expired */
|
|
|
|
- if (client.expiration && ts_after(kdc_time, client.expiration)) {
|
|
|
|
+ if (client->expiration && ts_after(kdc_time, client->expiration)) {
|
|
|
|
*status = "CLIENT EXPIRED";
|
|
|
|
if (vague_errors)
|
|
|
|
return(KRB_ERR_GENERIC);
|
|
|
|
@@ -637,8 +637,8 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
|
|
|
|
|
|
|
|
/* The client's password must not be expired, unless the server is
|
|
|
|
a KRB5_KDC_PWCHANGE_SERVICE. */
|
|
|
|
- if (client.pw_expiration && ts_after(kdc_time, client.pw_expiration) &&
|
|
|
|
- !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
|
|
|
|
+ if (client->pw_expiration && ts_after(kdc_time, client->pw_expiration) &&
|
|
|
|
+ !isflagset(server->attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
|
|
|
|
*status = "CLIENT KEY EXPIRED";
|
|
|
|
if (vague_errors)
|
|
|
|
return(KRB_ERR_GENERIC);
|
|
|
|
@@ -647,7 +647,7 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The server must not be expired */
|
|
|
|
- if (server.expiration && ts_after(kdc_time, server.expiration)) {
|
|
|
|
+ if (server->expiration && ts_after(kdc_time, server->expiration)) {
|
|
|
|
*status = "SERVICE EXPIRED";
|
|
|
|
return(KDC_ERR_SERVICE_EXP);
|
|
|
|
}
|
|
|
|
@@ -656,8 +656,8 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
|
|
|
|
* If the client requires password changing, then only allow the
|
|
|
|
* pwchange service.
|
|
|
|
*/
|
|
|
|
- if (isflagset(client.attributes, KRB5_KDB_REQUIRES_PWCHANGE) &&
|
|
|
|
- !isflagset(server.attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
|
|
|
|
+ if (isflagset(client->attributes, KRB5_KDB_REQUIRES_PWCHANGE) &&
|
|
|
|
+ !isflagset(server->attributes, KRB5_KDB_PWCHANGE_SERVICE)) {
|
|
|
|
*status = "REQUIRED PWCHANGE";
|
|
|
|
return(KDC_ERR_KEY_EXP);
|
|
|
|
}
|
|
|
|
@@ -665,37 +665,37 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
|
|
|
|
/* Client and server must allow postdating tickets */
|
|
|
|
if ((isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE) ||
|
|
|
|
isflagset(request->kdc_options, KDC_OPT_POSTDATED)) &&
|
|
|
|
- (isflagset(client.attributes, KRB5_KDB_DISALLOW_POSTDATED) ||
|
|
|
|
- isflagset(server.attributes, KRB5_KDB_DISALLOW_POSTDATED))) {
|
|
|
|
+ (isflagset(client->attributes, KRB5_KDB_DISALLOW_POSTDATED) ||
|
|
|
|
+ isflagset(server->attributes, KRB5_KDB_DISALLOW_POSTDATED))) {
|
|
|
|
*status = "POSTDATE NOT ALLOWED";
|
|
|
|
return(KDC_ERR_CANNOT_POSTDATE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check to see if client is locked out */
|
|
|
|
- if (isflagset(client.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
|
|
|
|
+ if (isflagset(client->attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
|
|
|
|
*status = "CLIENT LOCKED OUT";
|
|
|
|
return(KDC_ERR_CLIENT_REVOKED);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check to see if server is locked out */
|
|
|
|
- if (isflagset(server.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
|
|
|
|
+ if (isflagset(server->attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
|
|
|
|
*status = "SERVICE LOCKED OUT";
|
|
|
|
return(KDC_ERR_S_PRINCIPAL_UNKNOWN);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check to see if server is allowed to be a service */
|
|
|
|
- if (isflagset(server.attributes, KRB5_KDB_DISALLOW_SVR)) {
|
|
|
|
+ if (isflagset(server->attributes, KRB5_KDB_DISALLOW_SVR)) {
|
|
|
|
*status = "SERVICE NOT ALLOWED";
|
|
|
|
return(KDC_ERR_MUST_USE_USER2USER);
|
|
|
|
}
|
|
|
|
|
|
|
|
- if (check_anon(kdc_active_realm, client.princ, request->server) != 0) {
|
|
|
|
+ if (check_anon(kdc_active_realm, client->princ, request->server) != 0) {
|
|
|
|
*status = "ANONYMOUS NOT ALLOWED";
|
|
|
|
return(KDC_ERR_POLICY);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Perform KDB module policy checks. */
|
|
|
|
- ret = krb5_db_check_policy_as(kdc_context, request, &client, &server,
|
|
|
|
+ ret = krb5_db_check_policy_as(kdc_context, request, client, server,
|
|
|
|
kdc_time, status, e_data);
|
|
|
|
if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP)
|
|
|
|
return errcode_to_protocol(ret);
|
|
|
|
@@ -1568,8 +1568,8 @@ kdc_process_s4u2self_req(kdc_realm_t *kdc_active_realm,
|
|
|
|
princ->pw_expiration = 0;
|
|
|
|
clear(princ->attributes, KRB5_KDB_REQUIRES_PWCHANGE);
|
|
|
|
|
|
|
|
- code = validate_as_request(kdc_active_realm, request, *princ,
|
|
|
|
- no_server, kdc_time, status, &e_data);
|
|
|
|
+ code = validate_as_request(kdc_active_realm, request, princ,
|
|
|
|
+ &no_server, kdc_time, status, &e_data);
|
|
|
|
if (code) {
|
|
|
|
krb5_db_free_principal(kdc_context, princ);
|
|
|
|
krb5_free_pa_data(kdc_context, e_data);
|
|
|
|
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
|
|
|
|
index 42b7ee208..04007a8f5 100644
|
|
|
|
--- a/src/kdc/kdc_util.h
|
|
|
|
+++ b/src/kdc/kdc_util.h
|
|
|
|
@@ -76,12 +76,12 @@ get_local_tgt(krb5_context context, const krb5_data *realm,
|
|
|
|
krb5_db_entry **storage_out, krb5_keyblock *kb_out);
|
|
|
|
|
|
|
|
int
|
|
|
|
-validate_as_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry,
|
|
|
|
- krb5_db_entry, krb5_timestamp,
|
|
|
|
+validate_as_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry *,
|
|
|
|
+ krb5_db_entry *, krb5_timestamp,
|
|
|
|
const char **, krb5_pa_data ***);
|
|
|
|
|
|
|
|
int
|
|
|
|
-validate_tgs_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry,
|
|
|
|
+validate_tgs_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry *,
|
|
|
|
krb5_ticket *, krb5_timestamp,
|
|
|
|
const char **, krb5_pa_data ***);
|
|
|
|
|
|
|
|
diff --git a/src/kdc/tgs_policy.c b/src/kdc/tgs_policy.c
|
|
|
|
index 554345ba5..3f4fa8499 100644
|
|
|
|
--- a/src/kdc/tgs_policy.c
|
|
|
|
+++ b/src/kdc/tgs_policy.c
|
|
|
|
@@ -48,7 +48,7 @@ struct tgsflagrule {
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Service principal TGS policy checking functions */
|
|
|
|
-typedef int (check_tgs_svc_pol_fn)(krb5_kdc_req *, krb5_db_entry,
|
|
|
|
+typedef int (check_tgs_svc_pol_fn)(krb5_kdc_req *, krb5_db_entry *,
|
|
|
|
krb5_ticket *, krb5_timestamp,
|
|
|
|
const char **);
|
|
|
|
|
|
|
|
@@ -110,7 +110,7 @@ static const struct tgsflagrule svcdenyrules[] = {
|
|
|
|
* A service principal can forbid some TGS-REQ options.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
-check_tgs_svc_deny_opts(krb5_kdc_req *req, krb5_db_entry server,
|
|
|
|
+check_tgs_svc_deny_opts(krb5_kdc_req *req, krb5_db_entry *server,
|
|
|
|
krb5_ticket *tkt, krb5_timestamp kdc_time,
|
|
|
|
const char **status)
|
|
|
|
{
|
|
|
|
@@ -122,7 +122,7 @@ check_tgs_svc_deny_opts(krb5_kdc_req *req, krb5_db_entry server,
|
|
|
|
r = &svcdenyrules[i];
|
|
|
|
if (!(r->reqflags & req->kdc_options))
|
|
|
|
continue;
|
|
|
|
- if (r->checkflag & server.attributes) {
|
|
|
|
+ if (r->checkflag & server->attributes) {
|
|
|
|
*status = r->status;
|
|
|
|
return r->err;
|
|
|
|
}
|
|
|
|
@@ -134,20 +134,20 @@ check_tgs_svc_deny_opts(krb5_kdc_req *req, krb5_db_entry server,
|
|
|
|
* A service principal can deny all TGS-REQs for it.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
-check_tgs_svc_deny_all(krb5_kdc_req *req, krb5_db_entry server,
|
|
|
|
+check_tgs_svc_deny_all(krb5_kdc_req *req, krb5_db_entry *server,
|
|
|
|
krb5_ticket *tkt, krb5_timestamp kdc_time,
|
|
|
|
const char **status)
|
|
|
|
{
|
|
|
|
- if (server.attributes & KRB5_KDB_DISALLOW_ALL_TIX) {
|
|
|
|
+ if (server->attributes & KRB5_KDB_DISALLOW_ALL_TIX) {
|
|
|
|
*status = "SERVER LOCKED OUT";
|
|
|
|
return KDC_ERR_S_PRINCIPAL_UNKNOWN;
|
|
|
|
}
|
|
|
|
- if ((server.attributes & KRB5_KDB_DISALLOW_SVR) &&
|
|
|
|
+ if ((server->attributes & KRB5_KDB_DISALLOW_SVR) &&
|
|
|
|
!(req->kdc_options & KDC_OPT_ENC_TKT_IN_SKEY)) {
|
|
|
|
*status = "SERVER NOT ALLOWED";
|
|
|
|
return KDC_ERR_MUST_USE_USER2USER;
|
|
|
|
}
|
|
|
|
- if (server.attributes & KRB5_KDB_DISALLOW_TGT_BASED) {
|
|
|
|
+ if (server->attributes & KRB5_KDB_DISALLOW_TGT_BASED) {
|
|
|
|
if (krb5_is_tgs_principal(tkt->server)) {
|
|
|
|
*status = "TGT BASED NOT ALLOWED";
|
|
|
|
return KDC_ERR_POLICY;
|
|
|
|
@@ -160,17 +160,17 @@ check_tgs_svc_deny_all(krb5_kdc_req *req, krb5_db_entry server,
|
|
|
|
* A service principal can require certain TGT flags.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
-check_tgs_svc_reqd_flags(krb5_kdc_req *req, krb5_db_entry server,
|
|
|
|
+check_tgs_svc_reqd_flags(krb5_kdc_req *req, krb5_db_entry *server,
|
|
|
|
krb5_ticket *tkt,
|
|
|
|
krb5_timestamp kdc_time, const char **status)
|
|
|
|
{
|
|
|
|
- if (server.attributes & KRB5_KDB_REQUIRES_HW_AUTH) {
|
|
|
|
+ if (server->attributes & KRB5_KDB_REQUIRES_HW_AUTH) {
|
|
|
|
if (!(tkt->enc_part2->flags & TKT_FLG_HW_AUTH)) {
|
|
|
|
*status = "NO HW PREAUTH";
|
|
|
|
return KRB_ERR_GENERIC;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
- if (server.attributes & KRB5_KDB_REQUIRES_PRE_AUTH) {
|
|
|
|
+ if (server->attributes & KRB5_KDB_REQUIRES_PRE_AUTH) {
|
|
|
|
if (!(tkt->enc_part2->flags & TKT_FLG_PRE_AUTH)) {
|
|
|
|
*status = "NO PREAUTH";
|
|
|
|
return KRB_ERR_GENERIC;
|
|
|
|
@@ -180,10 +180,10 @@ check_tgs_svc_reqd_flags(krb5_kdc_req *req, krb5_db_entry server,
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
-check_tgs_svc_time(krb5_kdc_req *req, krb5_db_entry server, krb5_ticket *tkt,
|
|
|
|
+check_tgs_svc_time(krb5_kdc_req *req, krb5_db_entry *server, krb5_ticket *tkt,
|
|
|
|
krb5_timestamp kdc_time, const char **status)
|
|
|
|
{
|
|
|
|
- if (server.expiration && ts_after(kdc_time, server.expiration)) {
|
|
|
|
+ if (server->expiration && ts_after(kdc_time, server->expiration)) {
|
|
|
|
*status = "SERVICE EXPIRED";
|
|
|
|
return KDC_ERR_SERVICE_EXP;
|
|
|
|
}
|
|
|
|
@@ -191,8 +191,9 @@ check_tgs_svc_time(krb5_kdc_req *req, krb5_db_entry server, krb5_ticket *tkt,
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
-check_tgs_svc_policy(krb5_kdc_req *req, krb5_db_entry server, krb5_ticket *tkt,
|
|
|
|
- krb5_timestamp kdc_time, const char **status)
|
|
|
|
+check_tgs_svc_policy(krb5_kdc_req *req, krb5_db_entry *server,
|
|
|
|
+ krb5_ticket *tkt, krb5_timestamp kdc_time,
|
|
|
|
+ const char **status)
|
|
|
|
{
|
|
|
|
int errcode;
|
|
|
|
size_t i;
|
|
|
|
@@ -317,7 +318,7 @@ check_tgs_tgt(kdc_realm_t *kdc_active_realm, krb5_kdc_req *req,
|
|
|
|
|
|
|
|
int
|
|
|
|
validate_tgs_request(kdc_realm_t *kdc_active_realm,
|
|
|
|
- krb5_kdc_req *request, krb5_db_entry server,
|
|
|
|
+ krb5_kdc_req *request, krb5_db_entry *server,
|
|
|
|
krb5_ticket *ticket, krb5_timestamp kdc_time,
|
|
|
|
const char **status, krb5_pa_data ***e_data)
|
|
|
|
{
|
|
|
|
@@ -367,8 +368,8 @@ validate_tgs_request(kdc_realm_t *kdc_active_realm,
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Perform KDB module policy checks. */
|
|
|
|
- ret = krb5_db_check_policy_tgs(kdc_context, request, &server,
|
|
|
|
- ticket, status, e_data);
|
|
|
|
+ ret = krb5_db_check_policy_tgs(kdc_context, request, server, ticket,
|
|
|
|
+ status, e_data);
|
|
|
|
if (ret && ret != KRB5_PLUGIN_OP_NOTSUPP)
|
|
|
|
return errcode_to_protocol(ret);
|
|
|
|
|