]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s4:kdc: Cache user info and resource groups from PACs
authorJoseph Sutton <josephsutton@catalyst.net.nz>
Wed, 4 Oct 2023 04:19:31 +0000 (17:19 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 12 Oct 2023 23:13:32 +0000 (23:13 +0000)
When authentication policies are implemented, we shall need to fetch
SIDs (and claims) from the PACs of users and devices repeatedly — not
just when first looking up a user, but every time a policy needs to be
evaluated.

This will likely be more efficient if we can cache this information,
removing the need to derive it more than once.

View with ‘git show -b’.

Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/kdc/pac-glue.c
source4/kdc/samba_kdc.h

index e1ee8a6e2dd81053dec3bee6f74c1763b5f3d0cb..f48d0b139be9c847871289aeccaf7bb05843e993 100644 (file)
@@ -1203,44 +1203,62 @@ static krb5_error_code samba_kdc_get_user_info_from_pac(TALLOC_CTX *mem_ctx,
                *resource_groups_out = NULL;
        }
 
-       frame = talloc_stackframe();
+       if (entry.entry == NULL || entry.entry->info_from_pac == NULL) {
+               frame = talloc_stackframe();
+
+               ret = kerberos_pac_to_user_info_dc(frame,
+                                                  entry.pac,
+                                                  context,
+                                                  &info,
+                                                  AUTH_EXCLUDE_RESOURCE_GROUPS,
+                                                  NULL,
+                                                  NULL,
+                                                  &resource_groups);
+               if (ret) {
+                       const char *krb5err = krb5_get_error_message(context, ret);
+                       DBG_ERR("kerberos_pac_to_user_info_dc failed: %s\n",
+                               krb5err != NULL ? krb5err : "?");
+                       krb5_free_error_message(context, krb5err);
 
-       ret = kerberos_pac_to_user_info_dc(frame,
-                                          entry.pac,
-                                          context,
-                                          &info,
-                                          AUTH_EXCLUDE_RESOURCE_GROUPS,
-                                          NULL,
-                                          NULL,
-                                          &resource_groups);
-       if (ret) {
-               const char *krb5err = krb5_get_error_message(context, ret);
-               DBG_ERR("kerberos_pac_to_user_info_dc failed: %s\n",
-                       krb5err != NULL ? krb5err : "?");
-               krb5_free_error_message(context, krb5err);
+                       goto out;
+               }
 
-               goto out;
-       }
+               /*
+                * We need to expand group memberships within our local domain,
+                * as the token might be generated by a trusted domain.
+                */
+               nt_status = authsam_update_user_info_dc(frame,
+                                                       samdb,
+                                                       info);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       DBG_ERR("authsam_update_user_info_dc failed: %s\n",
+                               nt_errstr(nt_status));
 
-       /*
-        * We need to expand group memberships within our local domain,
-        * as the token might be generated by a trusted domain.
-        */
-       nt_status = authsam_update_user_info_dc(frame,
-                                               samdb,
-                                               info);
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               DBG_ERR("authsam_update_user_info_dc failed: %s\n",
-                       nt_errstr(nt_status));
+                       ret = map_errno_from_nt_status(nt_status);
+                       goto out;
+               }
 
-               ret = map_errno_from_nt_status(nt_status);
-               goto out;
+               if (entry.entry != NULL) {
+                       entry.entry->info_from_pac = talloc_steal(entry.entry, info);
+                       entry.entry->resource_groups_from_pac = talloc_steal(entry.entry, resource_groups);
+               }
        }
 
-       *info_out = talloc_steal(mem_ctx, info);
 
-       if (resource_groups_out != NULL) {
-               *resource_groups_out = talloc_steal(mem_ctx, resource_groups);
+       if (entry.entry != NULL) {
+               /* Note: the caller does not own this! */
+               *info_out = entry.entry->info_from_pac;
+
+               if (resource_groups_out != NULL) {
+                       /* Note: the caller does not own this! */
+                       *resource_groups_out = entry.entry->resource_groups_from_pac;
+               }
+       } else {
+               *info_out = talloc_steal(mem_ctx, info);
+
+               if (resource_groups_out != NULL) {
+                       *resource_groups_out = talloc_steal(mem_ctx, resource_groups);
+               }
        }
 
 out:
index 3b8c20fc28ff8540304767d76bfb6b0071acb786..59c146b0d818f0e60053f10eccf6eb0748143ecb 100644 (file)
@@ -60,6 +60,8 @@ struct samba_kdc_entry {
        const void *kdc_entry; /* this is a reference to hdb_entry/krb5_db_entry */
        struct ldb_message *msg;
        struct ldb_dn *realm_dn;
+       struct auth_user_info_dc *info_from_pac;
+       struct PAC_DOMAIN_GROUP_MEMBERSHIP *resource_groups_from_pac;
        struct auth_user_info_dc *info_from_db;
        const struct authn_kerberos_client_policy *client_policy;
        const struct authn_server_policy *server_policy;