kdc: use attribute dictionary in altsec authorizer plugin

This commit is contained in:
Luke Howard
2021-12-30 21:49:53 +11:00
parent a8ff420b16
commit b0f0ed74e8
3 changed files with 55 additions and 59 deletions

View File

@@ -272,7 +272,7 @@ ad_lookup(krb5_context context,
gss_const_name_t initiator_name, gss_const_name_t initiator_name,
gss_const_OID mech_type, gss_const_OID mech_type,
krb5_principal *canon_principal, krb5_principal *canon_principal,
krb5_data *requestor_sid) heim_data_t *requestor_sid)
{ {
krb5_error_code ret; krb5_error_code ret;
OM_uint32 minor; OM_uint32 minor;
@@ -286,7 +286,8 @@ ad_lookup(krb5_context context,
struct berval **values = NULL; struct berval **values = NULL;
*canon_principal = NULL; *canon_principal = NULL;
krb5_data_zero(requestor_sid); if (requestor_sid)
*requestor_sid = NULL;
mech_type_str = gss_oid_to_name(mech_type); mech_type_str = gss_oid_to_name(mech_type);
if (mech_type_str == NULL) { if (mech_type_str == NULL) {
@@ -335,18 +336,6 @@ ad_lookup(krb5_context context,
if (m0 == NULL) if (m0 == NULL)
goto out; goto out;
if (requestor_sid) {
values = ldap_get_values_len(server->ld, m0, "objectSid");
if (values == NULL ||
ldap_count_values_len(values) == 0)
goto out;
if (krb5_data_copy(requestor_sid, values[0]->bv_val, values[0]->bv_len) != 0)
goto enomem;
ldap_value_free_len(values);
}
values = ldap_get_values_len(server->ld, m0, "sAMAccountName"); values = ldap_get_values_len(server->ld, m0, "sAMAccountName");
if (values == NULL || if (values == NULL ||
ldap_count_values_len(values) == 0) ldap_count_values_len(values) == 0)
@@ -354,6 +343,22 @@ ad_lookup(krb5_context context,
ret = krb5_make_principal(context, canon_principal, realm, ret = krb5_make_principal(context, canon_principal, realm,
values[0]->bv_val, NULL); values[0]->bv_val, NULL);
if (ret)
goto out;
if (requestor_sid) {
ldap_value_free_len(values);
values = ldap_get_values_len(server->ld, m0, "objectSid");
if (values == NULL ||
ldap_count_values_len(values) == 0)
goto out;
*requestor_sid = heim_data_create(values[0]->bv_val, values[0]->bv_len);
if (*requestor_sid == NULL)
goto enomem;
}
goto out; goto out;
enomem: enomem:
@@ -361,6 +366,16 @@ enomem:
goto out; goto out;
out: out:
if (ret) {
krb5_free_principal(context, *canon_principal);
*canon_principal = NULL;
if (requestor_sid) {
heim_release(*requestor_sid);
*requestor_sid = NULL;
}
}
ldap_value_free_len(values); ldap_value_free_len(values);
ldap_msgfree(m); ldap_msgfree(m);
ldap_memfree(basedn); ldap_memfree(basedn);
@@ -377,8 +392,7 @@ authorize(void *ctx,
gss_const_OID mech_type, gss_const_OID mech_type,
OM_uint32 ret_flags, OM_uint32 ret_flags,
krb5_boolean *authorized, krb5_boolean *authorized,
krb5_principal *mapped_name, krb5_principal *mapped_name)
krb5_data *requestor_sid)
{ {
struct altsecid_gss_preauth_authorizer_context *c = ctx; struct altsecid_gss_preauth_authorizer_context *c = ctx;
struct ad_server_tuple *server = NULL; struct ad_server_tuple *server = NULL;
@@ -386,10 +400,10 @@ authorize(void *ctx,
krb5_const_realm realm = krb5_principal_get_realm(r->context, r->client->entry.principal); krb5_const_realm realm = krb5_principal_get_realm(r->context, r->client->entry.principal);
krb5_boolean reconnect_p = FALSE; krb5_boolean reconnect_p = FALSE;
krb5_boolean is_tgs; krb5_boolean is_tgs;
heim_data_t requestor_sid = NULL;
*authorized = FALSE; *authorized = FALSE;
*mapped_name = NULL; *mapped_name = NULL;
krb5_data_zero(requestor_sid);
if (!krb5_principal_is_federated(r->context, r->client->entry.principal) || if (!krb5_principal_is_federated(r->context, r->client->entry.principal) ||
(ret_flags & GSS_C_ANON_FLAG)) (ret_flags & GSS_C_ANON_FLAG))
@@ -425,7 +439,7 @@ authorize(void *ctx,
ret = ad_lookup(r->context, realm, server, ret = ad_lookup(r->context, realm, server,
initiator_name, mech_type, initiator_name, mech_type,
mapped_name, is_tgs ? requestor_sid : NULL); mapped_name, is_tgs ? &requestor_sid : NULL);
if (ret == KRB5KDC_ERR_SVC_UNAVAILABLE) { if (ret == KRB5KDC_ERR_SVC_UNAVAILABLE) {
ldap_unbind_ext_s(server->ld, NULL, NULL); ldap_unbind_ext_s(server->ld, NULL, NULL);
server->ld = NULL; server->ld = NULL;
@@ -437,17 +451,27 @@ authorize(void *ctx,
*authorized = (ret == 0); *authorized = (ret == 0);
} while (reconnect_p); } while (reconnect_p);
if (requestor_sid) {
krb5_kdc_request_set_attribute((kdc_request_t)r,
HSTR("org.h5l.pac-requestor-sid"), requestor_sid);
heim_release(requestor_sid);
}
return ret; return ret;
} }
static KRB5_LIB_CALL krb5_error_code static KRB5_LIB_CALL krb5_error_code
finalize_pac(void *ctx, astgs_request_t r, krb5_data *requestor_sid) finalize_pac(void *ctx, astgs_request_t r)
{ {
if (requestor_sid->length == 0) heim_data_t requestor_sid;
requestor_sid = krb5_kdc_request_get_attribute((kdc_request_t)r,
HSTR("org.h5l.pac-requestor-sid"));
if (requestor_sid == NULL)
return 0; return 0;
return krb5_pac_add_buffer(r->context, r->pac, return krb5_pac_add_buffer(r->context, r->pac, PAC_REQUESTOR_SID,
PAC_REQUESTOR_SID, requestor_sid); heim_data_get_data(requestor_sid));
} }
static KRB5_LIB_CALL krb5_error_code static KRB5_LIB_CALL krb5_error_code

View File

@@ -51,7 +51,6 @@ struct gss_client_params {
OM_uint32 flags; OM_uint32 flags;
OM_uint32 lifetime; OM_uint32 lifetime;
krb5_checksum req_body_checksum; krb5_checksum req_body_checksum;
krb5_data pac_data;
}; };
static void static void
@@ -501,7 +500,6 @@ struct pa_gss_authorize_plugin_ctx {
struct gss_client_params *gcp; struct gss_client_params *gcp;
krb5_boolean authorized; krb5_boolean authorized;
krb5_principal initiator_princ; krb5_principal initiator_princ;
krb5_data pac_data;
}; };
static krb5_error_code KRB5_LIB_CALL static krb5_error_code KRB5_LIB_CALL
@@ -519,8 +517,7 @@ pa_gss_authorize_cb(krb5_context context,
pa_gss_authorize_plugin_ctx->gcp->mech_type, pa_gss_authorize_plugin_ctx->gcp->mech_type,
pa_gss_authorize_plugin_ctx->gcp->flags, pa_gss_authorize_plugin_ctx->gcp->flags,
&pa_gss_authorize_plugin_ctx->authorized, &pa_gss_authorize_plugin_ctx->authorized,
&pa_gss_authorize_plugin_ctx->initiator_princ, &pa_gss_authorize_plugin_ctx->initiator_princ);
&pa_gss_authorize_plugin_ctx->pac_data);
} }
static const char *plugin_deps[] = { static const char *plugin_deps[] = {
@@ -545,8 +542,7 @@ pa_gss_authorize_plugin(astgs_request_t r,
struct gss_client_params *gcp, struct gss_client_params *gcp,
gss_const_buffer_t display_name, gss_const_buffer_t display_name,
krb5_boolean *authorized, krb5_boolean *authorized,
krb5_principal *initiator_princ, krb5_principal *initiator_princ)
krb5_data *pac_data)
{ {
krb5_error_code ret; krb5_error_code ret;
struct pa_gss_authorize_plugin_ctx ctx; struct pa_gss_authorize_plugin_ctx ctx;
@@ -555,7 +551,6 @@ pa_gss_authorize_plugin(astgs_request_t r,
ctx.gcp = gcp; ctx.gcp = gcp;
ctx.authorized = 0; ctx.authorized = 0;
ctx.initiator_princ = NULL; ctx.initiator_princ = NULL;
krb5_data_zero(&ctx.pac_data);
krb5_clear_error_message(r->context); krb5_clear_error_message(r->context);
ret = _krb5_plugin_run_f(r->context, &gss_preauth_authorizer_data, ret = _krb5_plugin_run_f(r->context, &gss_preauth_authorizer_data,
@@ -576,7 +571,6 @@ pa_gss_authorize_plugin(astgs_request_t r,
*authorized = ctx.authorized; *authorized = ctx.authorized;
*initiator_princ = ctx.initiator_princ; *initiator_princ = ctx.initiator_princ;
*pac_data = ctx.pac_data;
return ret; return ret;
} }
@@ -586,8 +580,7 @@ pa_gss_authorize_default(astgs_request_t r,
struct gss_client_params *gcp, struct gss_client_params *gcp,
gss_const_buffer_t display_name, gss_const_buffer_t display_name,
krb5_boolean *authorized, krb5_boolean *authorized,
krb5_principal *initiator_princ, krb5_principal *initiator_princ)
krb5_data *pac_data)
{ {
krb5_error_code ret; krb5_error_code ret;
krb5_principal principal; krb5_principal principal;
@@ -689,14 +682,12 @@ _kdc_gss_check_client(astgs_request_t r,
krb5_principal initiator_princ = NULL; krb5_principal initiator_princ = NULL;
hdb_entry_ex *initiator = NULL; hdb_entry_ex *initiator = NULL;
krb5_boolean authorized = FALSE; krb5_boolean authorized = FALSE;
krb5_data pac_data;
OM_uint32 minor; OM_uint32 minor;
gss_buffer_desc display_name = GSS_C_EMPTY_BUFFER; gss_buffer_desc display_name = GSS_C_EMPTY_BUFFER;
gss_const_buffer_t display_name_p; gss_const_buffer_t display_name_p;
*client_name = NULL; *client_name = NULL;
krb5_data_zero(&pac_data);
pa_gss_display_name(gcp->initiator_name, &display_name, &display_name_p); pa_gss_display_name(gcp->initiator_name, &display_name, &display_name_p);
@@ -705,10 +696,10 @@ _kdc_gss_check_client(astgs_request_t r,
* are authorized as the directly corresponding Kerberos principal. * are authorized as the directly corresponding Kerberos principal.
*/ */
ret = pa_gss_authorize_plugin(r, gcp, display_name_p, ret = pa_gss_authorize_plugin(r, gcp, display_name_p,
&authorized, &initiator_princ, &pac_data); &authorized, &initiator_princ);
if (ret == KRB5_PLUGIN_NO_HANDLE) if (ret == KRB5_PLUGIN_NO_HANDLE)
ret = pa_gss_authorize_default(r, gcp, display_name_p, ret = pa_gss_authorize_default(r, gcp, display_name_p,
&authorized, &initiator_princ, &pac_data); &authorized, &initiator_princ);
if (ret == 0 && !authorized) if (ret == 0 && !authorized)
ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
if (ret) if (ret)
@@ -766,14 +757,10 @@ _kdc_gss_check_client(astgs_request_t r,
goto out; goto out;
} }
gcp->pac_data = pac_data;
krb5_data_zero(&pac_data);
out: out:
krb5_free_principal(r->context, initiator_princ); krb5_free_principal(r->context, initiator_princ);
if (initiator) if (initiator)
_kdc_free_ent(r->context, initiator); _kdc_free_ent(r->context, initiator);
krb5_data_free(&pac_data);
gss_release_buffer(&minor, &display_name); gss_release_buffer(&minor, &display_name);
return ret; return ret;
@@ -880,7 +867,6 @@ pa_gss_dealloc_client_params(void *ptr)
gss_release_name(&minor, &gcp->initiator_name); gss_release_name(&minor, &gcp->initiator_name);
gss_release_buffer(&minor, &gcp->output_token); gss_release_buffer(&minor, &gcp->output_token);
free_Checksum(&gcp->req_body_checksum); free_Checksum(&gcp->req_body_checksum);
krb5_data_free(&gcp->pac_data);
memset(gcp, 0, sizeof(*gcp)); memset(gcp, 0, sizeof(*gcp));
} }
@@ -1015,11 +1001,6 @@ pa_gss_display_name(gss_name_t name,
*namebuf_p = namebuf; *namebuf_p = namebuf;
} }
struct pa_gss_finalize_pac_plugin_ctx {
astgs_request_t r;
krb5_data *pac_data;
};
static krb5_error_code KRB5_LIB_CALL static krb5_error_code KRB5_LIB_CALL
pa_gss_finalize_pac_cb(krb5_context context, pa_gss_finalize_pac_cb(krb5_context context,
const void *plug, const void *plug,
@@ -1027,11 +1008,8 @@ pa_gss_finalize_pac_cb(krb5_context context,
void *userctx) void *userctx)
{ {
const krb5plugin_gss_preauth_authorizer_ftable *authorizer = plug; const krb5plugin_gss_preauth_authorizer_ftable *authorizer = plug;
struct pa_gss_finalize_pac_plugin_ctx *pa_gss_finalize_pac_ctx = userctx;
return authorizer->finalize_pac(plugctx, return authorizer->finalize_pac(plugctx, userctx);
pa_gss_finalize_pac_ctx->r,
pa_gss_finalize_pac_ctx->pac_data);
} }
@@ -1040,14 +1018,10 @@ _kdc_gss_finalize_pac(astgs_request_t r,
gss_client_params *gcp) gss_client_params *gcp)
{ {
krb5_error_code ret; krb5_error_code ret;
struct pa_gss_finalize_pac_plugin_ctx ctx;
ctx.r = r;
ctx.pac_data = &gcp->pac_data;
krb5_clear_error_message(r->context); krb5_clear_error_message(r->context);
ret = _krb5_plugin_run_f(r->context, &gss_preauth_authorizer_data, ret = _krb5_plugin_run_f(r->context, &gss_preauth_authorizer_data,
0, &ctx, pa_gss_finalize_pac_cb); 0, r, pa_gss_finalize_pac_cb);
if (ret == KRB5_PLUGIN_NO_HANDLE) if (ret == KRB5_PLUGIN_NO_HANDLE)
ret = 0; ret = 0;

View File

@@ -69,11 +69,9 @@ typedef struct krb5plugin_gss_preauth_authorizer_ftable_desc {
gss_const_OID, /*mech_type*/ gss_const_OID, /*mech_type*/
OM_uint32, /*ret_flags*/ OM_uint32, /*ret_flags*/
krb5_boolean *, /*authorized*/ krb5_boolean *, /*authorized*/
krb5_principal *, /*mapped_name*/ krb5_principal *); /*mapped_name*/
krb5_data *); /*pac_data*/
krb5_error_code (KRB5_LIB_CALL *finalize_pac)(void *, /*plug_ctx*/ krb5_error_code (KRB5_LIB_CALL *finalize_pac)(void *, /*plug_ctx*/
astgs_request_t, /*r*/ astgs_request_t); /*r*/
krb5_data *); /*pac_data*/
} krb5plugin_gss_preauth_authorizer_ftable; } krb5plugin_gss_preauth_authorizer_ftable;
#endif /* HEIMDAL_KDC_GSS_PREAUTH_AUTHORIZER_PLUGIN_H */ #endif /* HEIMDAL_KDC_GSS_PREAUTH_AUTHORIZER_PLUGIN_H */