]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:kdc: Add function to perform an authentication policy access check with a device
authorJoseph Sutton <josephsutton@catalyst.net.nz>
Wed, 14 Jun 2023 22:46:55 +0000 (10:46 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 15 Jun 2023 05:29:28 +0000 (05:29 +0000)
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/kdc/authn_policy_util.c
source4/kdc/authn_policy_util.h

index fde127e9d178bf8f15465db1f081626c8bd65781..bf14096e6c30b8ecdaa349c841d06a4500c449dc 100644 (file)
@@ -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. */
 
 /*
index 71f4e2a73b53907ba4567589951af42a8cda0e57..f768b5e5f8fc67724f3a1f7171a360a7f3ac116a 100644 (file)
@@ -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);