From b5506d5ee38dabbb26dfc889a8a222e632ddf99b Mon Sep 17 00:00:00 2001 From: Joseph Sutton Date: Thu, 15 Jun 2023 10:46:55 +1200 Subject: [PATCH] s4:kdc: Add function to perform an authentication policy access check with a device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the ‘audit_info_out’ parameter is non-NULL, auditing information will be returned so that it might be logged. Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- source4/kdc/authn_policy_util.c | 173 ++++++++++++++++++++++++++++++++ source4/kdc/authn_policy_util.h | 12 +++ 2 files changed, 185 insertions(+) diff --git a/source4/kdc/authn_policy_util.c b/source4/kdc/authn_policy_util.c index fde127e9d17..bf14096e6c3 100644 --- a/source4/kdc/authn_policy_util.c +++ b/source4/kdc/authn_policy_util.c @@ -535,6 +535,146 @@ static NTSTATUS _authn_policy_audit_info(TALLOC_CTX *mem_ctx, __location__, \ audit_info_out) +/* + * Perform an access check against the security descriptor set in an + * authentication policy. ‘client_info’ must be talloc-allocated so that we can + * make a reference to it. + */ +static NTSTATUS _authn_policy_access_check(TALLOC_CTX *mem_ctx, + struct ldb_context *samdb, + struct loadparm_context* lp_ctx, + const struct auth_user_info_dc *client_info, + const struct authn_policy *policy, + const struct authn_int64_optional tgt_lifetime_raw, + const enum authn_audit_event restriction_event, + const DATA_BLOB *descriptor_blob, + const char *location, + struct authn_audit_info **audit_info_out) +{ + TALLOC_CTX *tmp_ctx = NULL; + NTSTATUS status = NT_STATUS_OK; + NTSTATUS status2; + enum ndr_err_code ndr_err; + struct security_descriptor *descriptor = NULL; + struct security_token *security_token = NULL; + uint32_t session_info_flags = + AUTH_SESSION_INFO_DEFAULT_GROUPS | + AUTH_SESSION_INFO_SIMPLE_PRIVILEGES; + const uint32_t access_desired = SEC_ADS_CONTROL_ACCESS; + uint32_t access_granted; + enum authn_audit_event event = restriction_event; + enum authn_audit_reason reason = AUTHN_AUDIT_REASON_NONE; + + if (audit_info_out != NULL) { + *audit_info_out = NULL; + } + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + + if (!(client_info->info->user_flags & NETLOGON_GUEST)) { + session_info_flags |= AUTH_SESSION_INFO_AUTHENTICATED; + } + + descriptor = talloc(tmp_ctx, struct security_descriptor); + if (descriptor == NULL) { + status = NT_STATUS_NO_MEMORY; + goto out; + } + + ndr_err = ndr_pull_struct_blob(descriptor_blob, + tmp_ctx, + descriptor, + (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + status = ndr_map_error2ntstatus(ndr_err); + DBG_ERR("Failed to unmarshall " + "security descriptor for authentication policy: %s\n", + nt_errstr(status)); + reason = AUTHN_AUDIT_REASON_DESCRIPTOR_INVALID; + goto out; + } + + /* Require that the security descriptor has an owner set. */ + if (descriptor->owner_sid == NULL) { + status = NT_STATUS_INVALID_PARAMETER; + reason = AUTHN_AUDIT_REASON_DESCRIPTOR_NO_OWNER; + goto out; + } + + status = auth_generate_security_token(tmp_ctx, + lp_ctx, + samdb, + client_info, + session_info_flags, + &security_token); + if (!NT_STATUS_IS_OK(status)) { + reason = AUTHN_AUDIT_REASON_SECURITY_TOKEN_FAILURE; + goto out; + } + + status = sec_access_check_ds(descriptor, security_token, + access_desired, &access_granted, + NULL, NULL); + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + status = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + reason = AUTHN_AUDIT_REASON_ACCESS_DENIED; + goto out; + } + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + + event = AUTHN_AUDIT_EVENT_OK; +out: + /* + * Create the structure with auditing information here while we have all + * the relevant information to hand. It will contain references to + * information regarding the client and the policy, to be consulted + * after the referents have possibly been freed. + */ + status2 = _authn_policy_audit_info(mem_ctx, + policy, + tgt_lifetime_raw, + client_info, + event, + reason, + status, + location, + audit_info_out); + if (!NT_STATUS_IS_OK(status2)) { + status = status2; + } else if (!authn_policy_is_enforced(policy)) { + status = NT_STATUS_OK; + } + + talloc_free(tmp_ctx); + return status; +} + +#define authn_policy_access_check(mem_ctx, \ + samdb, \ + lp_ctx, \ + client_info, \ + policy, \ + tgt_lifetime_raw, \ + restriction_event, \ + descriptor_blob, \ + audit_info_out) \ + _authn_policy_access_check(mem_ctx, \ + samdb, \ + lp_ctx, \ + client_info, \ + policy, \ + tgt_lifetime_raw, \ + restriction_event, \ + descriptor_blob, \ + __location__, \ + audit_info_out) + /* Return an authentication policy moved onto a talloc context. */ static struct authn_policy authn_policy_move(TALLOC_CTX *mem_ctx, struct authn_policy *policy) @@ -669,6 +809,39 @@ bool authn_policy_device_restrictions_present(const struct authn_kerberos_client return authn_policy_kerberos_device_restrictions(policy) != NULL; } +/* + * Perform an access check for the device with which the client is + * authenticating. ‘device_info’ must be talloc-allocated so that we can make a + * reference to it. + */ +NTSTATUS authn_policy_authenticate_from_device(TALLOC_CTX *mem_ctx, + struct ldb_context *samdb, + struct loadparm_context* lp_ctx, + const struct auth_user_info_dc *device_info, + const struct authn_kerberos_client_policy *client_policy, + struct authn_audit_info **client_audit_info_out) +{ + NTSTATUS status = NT_STATUS_OK; + const DATA_BLOB *restrictions = NULL; + + restrictions = authn_policy_kerberos_device_restrictions(client_policy); + if (restrictions == NULL) { + goto out; + } + + status = authn_policy_access_check(mem_ctx, + samdb, + lp_ctx, + device_info, + &client_policy->policy, + authn_int64_some(client_policy->tgt_lifetime_raw), + AUTHN_AUDIT_EVENT_KERBEROS_DEVICE_RESTRICTION, + restrictions, + client_audit_info_out); +out: + return status; +} + /* Authentication policies for NTLM clients. */ /* diff --git a/source4/kdc/authn_policy_util.h b/source4/kdc/authn_policy_util.h index 71f4e2a73b5..f768b5e5f8f 100644 --- a/source4/kdc/authn_policy_util.h +++ b/source4/kdc/authn_policy_util.h @@ -59,6 +59,18 @@ int authn_policy_kerberos_client(struct ldb_context *samdb, const struct ldb_message *msg, const struct authn_kerberos_client_policy **policy_out); +/* + * Perform an access check for the device with which the client is + * authenticating. ‘device_info’ must be talloc-allocated so that we can make a + * reference to it. + */ +NTSTATUS authn_policy_authenticate_from_device(TALLOC_CTX *mem_ctx, + struct ldb_context *samdb, + struct loadparm_context* lp_ctx, + const struct auth_user_info_dc *device_info, + const struct authn_kerberos_client_policy *client_policy, + struct authn_audit_info **client_audit_info_out); + /* Return whether an authentication policy enforces device restrictions. */ bool authn_policy_device_restrictions_present(const struct authn_kerberos_client_policy *policy);