summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Sutton <josephsutton@catalyst.net.nz>2023-05-09 11:57:09 +1200
committerAndrew Bartlett <abartlet@samba.org>2023-05-18 01:03:37 +0000
commitbbdb3bf8a634c32f9d2c93d6b1c77eff194dabe6 (patch)
treea6e37545dafe044dfe97c01b7c4cc5efc8c2977f
parent9a78a8b3f21c934f736870b25065278545359d21 (diff)
downloadsamba-bbdb3bf8a634c32f9d2c93d6b1c77eff194dabe6.tar.gz
s4:kdc: Factor out PAC blob functions into new source file
pac-glue.c has become rather large, and can do without these PAC blob–handling functions. Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
-rw-r--r--source4/kdc/pac-blobs.c250
-rw-r--r--source4/kdc/pac-blobs.h89
-rw-r--r--source4/kdc/pac-glue.c252
-rw-r--r--source4/kdc/wscript_build2
4 files changed, 341 insertions, 252 deletions
diff --git a/source4/kdc/pac-blobs.c b/source4/kdc/pac-blobs.c
new file mode 100644
index 00000000000..2c0bce6f7c6
--- /dev/null
+++ b/source4/kdc/pac-blobs.c
@@ -0,0 +1,250 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ PAC Glue between Samba and the KDC
+
+ Copyright (C) Catalyst.Net Ltd 2023
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "source4/kdc/pac-blobs.h"
+
+#include "lib/util/debug.h"
+#include "lib/util/samba_util.h"
+
+void pac_blobs_init(struct pac_blobs *pac_blobs)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(pac_blobs->type_index); ++i) {
+ pac_blobs->type_index[i] = SIZE_MAX;
+ }
+
+ pac_blobs->type_blobs = NULL;
+ pac_blobs->num_types = 0;
+}
+
+void pac_blobs_destroy(struct pac_blobs *pac_blobs)
+{
+ TALLOC_FREE(pac_blobs->type_blobs);
+}
+
+static inline size_t *pac_blobs_get_index(struct pac_blobs *pac_blobs, size_t type)
+{
+ /* Ensure the type is valid. */
+ SMB_ASSERT(type >= PAC_TYPE_BEGIN);
+ SMB_ASSERT(type < PAC_TYPE_END);
+
+ return &pac_blobs->type_index[type - PAC_TYPE_BEGIN];
+}
+
+static inline struct type_data *pac_blobs_get(struct pac_blobs *pac_blobs, size_t type)
+{
+ size_t index = *pac_blobs_get_index(pac_blobs, type);
+ SMB_ASSERT(index < pac_blobs->num_types);
+
+ return &pac_blobs->type_blobs[index];
+}
+
+krb5_error_code pac_blobs_from_krb5_pac(struct pac_blobs *pac_blobs,
+ TALLOC_CTX *mem_ctx,
+ krb5_context context,
+ const krb5_const_pac pac)
+{
+ krb5_error_code code;
+ uint32_t *types = NULL;
+ size_t i;
+
+ code = krb5_pac_get_types(context, pac, &pac_blobs->num_types, &types);
+ if (code != 0) {
+ DBG_ERR("krb5_pac_get_types failed\n");
+ return code;
+ }
+
+ pac_blobs->type_blobs = talloc_array(mem_ctx, struct type_data, pac_blobs->num_types);
+ if (pac_blobs->type_blobs == NULL) {
+ DBG_ERR("Out of memory\n");
+ SAFE_FREE(types);
+ return ENOMEM;
+ }
+
+ for (i = 0; i < pac_blobs->num_types; ++i) {
+ uint32_t type = types[i];
+ size_t *type_index = NULL;
+
+ pac_blobs->type_blobs[i] = (struct type_data) {
+ .type = type,
+ .data = NULL,
+ };
+
+ switch (type) {
+ /* PAC buffer types that we support. */
+ case PAC_TYPE_LOGON_INFO:
+ case PAC_TYPE_CREDENTIAL_INFO:
+ case PAC_TYPE_SRV_CHECKSUM:
+ case PAC_TYPE_KDC_CHECKSUM:
+ case PAC_TYPE_LOGON_NAME:
+ case PAC_TYPE_CONSTRAINED_DELEGATION:
+ case PAC_TYPE_UPN_DNS_INFO:
+ case PAC_TYPE_CLIENT_CLAIMS_INFO:
+ case PAC_TYPE_DEVICE_INFO:
+ case PAC_TYPE_DEVICE_CLAIMS_INFO:
+ case PAC_TYPE_TICKET_CHECKSUM:
+ case PAC_TYPE_ATTRIBUTES_INFO:
+ case PAC_TYPE_REQUESTER_SID:
+ case PAC_TYPE_FULL_CHECKSUM:
+ type_index = pac_blobs_get_index(pac_blobs, type);
+ if (*type_index != SIZE_MAX) {
+ DBG_WARNING("PAC buffer type[%"PRIu32"] twice\n", type);
+ pac_blobs_destroy(pac_blobs);
+ SAFE_FREE(types);
+ return EINVAL;
+ }
+ *type_index = i;
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ SAFE_FREE(types);
+ return 0;
+}
+
+krb5_error_code _pac_blobs_ensure_exists(struct pac_blobs *pac_blobs,
+ const uint32_t type,
+ const char *name,
+ const char *location,
+ const char *function)
+{
+ if (*pac_blobs_get_index(pac_blobs, type) == SIZE_MAX) {
+ DEBUGLF(DBGLVL_ERR, ("%s: %s missing\n", function, name), location, function);
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+krb5_error_code _pac_blobs_replace_existing(struct pac_blobs *pac_blobs,
+ const uint32_t type,
+ const char *name,
+ const DATA_BLOB *blob,
+ const char *location,
+ const char *function)
+{
+ krb5_error_code code;
+
+ code = _pac_blobs_ensure_exists(pac_blobs,
+ type,
+ name,
+ location,
+ function);
+ if (code != 0) {
+ return code;
+ }
+
+ pac_blobs_get(pac_blobs, type)->data = blob;
+
+ return 0;
+}
+
+krb5_error_code pac_blobs_add_blob(struct pac_blobs *pac_blobs,
+ TALLOC_CTX *mem_ctx,
+ const uint32_t type,
+ const DATA_BLOB *blob)
+{
+ size_t *index = NULL;
+
+ if (blob == NULL) {
+ return 0;
+ }
+
+ index = pac_blobs_get_index(pac_blobs, type);
+ if (*index == SIZE_MAX) {
+ pac_blobs->type_blobs = talloc_realloc(mem_ctx,
+ pac_blobs->type_blobs,
+ struct type_data,
+ pac_blobs->num_types + 1);
+ if (pac_blobs->type_blobs == NULL) {
+ DBG_ERR("Out of memory\n");
+ return ENOMEM;
+ }
+
+ *index = pac_blobs->num_types++;
+ }
+
+ *pac_blobs_get(pac_blobs, type) = (struct type_data) {
+ .type = type,
+ .data = blob,
+ };
+
+ return 0;
+}
+
+krb5_error_code pac_blobs_remove_blob(struct pac_blobs *pac_blobs,
+ TALLOC_CTX *mem_ctx,
+ const uint32_t type)
+{
+ size_t found_index;
+ size_t i;
+
+ /* Get the index of this PAC buffer type. */
+ found_index = *pac_blobs_get_index(pac_blobs, type);
+ if (found_index == SIZE_MAX) {
+ /* We don't have a PAC buffer of this type, so we're done. */
+ return 0;
+ }
+
+ /* Since the PAC buffer is present, there will be at least one type in the array. */
+ SMB_ASSERT(pac_blobs->num_types > 0);
+
+ /* The index should be valid. */
+ SMB_ASSERT(found_index < pac_blobs->num_types);
+
+ /*
+ * Even though a consistent ordering of PAC buffers is not to be relied
+ * upon, we must still maintain the ordering we are given.
+ */
+ for (i = found_index; i < pac_blobs->num_types - 1; ++i) {
+ size_t moved_type;
+
+ /* Shift each following element backwards by one. */
+ pac_blobs->type_blobs[i] = pac_blobs->type_blobs[i + 1];
+
+ /* Mark the new position of the moved element in the index. */
+ moved_type = pac_blobs->type_blobs[i].type;
+ if (moved_type >= PAC_TYPE_BEGIN && moved_type < PAC_TYPE_END) {
+ *pac_blobs_get_index(pac_blobs, moved_type) = i;
+ }
+ }
+
+ /* Mark the removed element as no longer present. */
+ *pac_blobs_get_index(pac_blobs, type) = SIZE_MAX;
+
+ /* We do not free the removed data blob, as it may be statically allocated (e.g., a null blob). */
+
+ /* Remove the last element from the array. */
+ pac_blobs->type_blobs = talloc_realloc(mem_ctx,
+ pac_blobs->type_blobs,
+ struct type_data,
+ --pac_blobs->num_types);
+ if (pac_blobs->type_blobs == NULL) {
+ DBG_ERR("Out of memory\n");
+ return ENOMEM;
+ }
+
+ return 0;
+}
diff --git a/source4/kdc/pac-blobs.h b/source4/kdc/pac-blobs.h
new file mode 100644
index 00000000000..769684927f3
--- /dev/null
+++ b/source4/kdc/pac-blobs.h
@@ -0,0 +1,89 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ PAC Glue between Samba and the KDC
+
+ Copyright (C) Catalyst.Net Ltd 2023
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "lib/replace/replace.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "system/kerberos.h"
+#include "auth/kerberos/kerberos.h"
+#include <krb5/krb5.h>
+
+#include "lib/util/data_blob.h"
+#include "librpc/gen_ndr/ndr_krb5pac.h"
+
+struct type_data {
+ uint32_t type;
+ const DATA_BLOB *data;
+};
+
+struct pac_blobs {
+ size_t type_index[PAC_TYPE_COUNT];
+ struct type_data *type_blobs;
+ size_t num_types;
+};
+
+void pac_blobs_init(struct pac_blobs *pac_blobs);
+
+void pac_blobs_destroy(struct pac_blobs *pac_blobs);
+
+krb5_error_code pac_blobs_from_krb5_pac(struct pac_blobs *pac_blobs,
+ TALLOC_CTX *mem_ctx,
+ krb5_context context,
+ const krb5_const_pac pac);
+
+#define pac_blobs_ensure_exists(pac_blobs, type) \
+ _pac_blobs_ensure_exists(pac_blobs, \
+ type, \
+ #type, \
+ __location__, \
+ __func__)
+
+krb5_error_code _pac_blobs_ensure_exists(struct pac_blobs *pac_blobs,
+ const uint32_t type,
+ const char *name,
+ const char *location,
+ const char *function);
+
+#define pac_blobs_replace_existing(pac_blobs, type, blob) \
+ _pac_blobs_replace_existing(pac_blobs, \
+ type, \
+ #type, \
+ blob, \
+ __location__, \
+ __func__)
+
+krb5_error_code _pac_blobs_replace_existing(struct pac_blobs *pac_blobs,
+ const uint32_t type,
+ const char *name,
+ const DATA_BLOB *blob,
+ const char *location,
+ const char *function);
+
+krb5_error_code pac_blobs_add_blob(struct pac_blobs *pac_blobs,
+ TALLOC_CTX *mem_ctx,
+ const uint32_t type,
+ const DATA_BLOB *blob);
+
+krb5_error_code pac_blobs_remove_blob(struct pac_blobs *pac_blobs,
+ TALLOC_CTX *mem_ctx,
+ const uint32_t type);
diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c
index 1f94391af78..e09271bdb43 100644
--- a/source4/kdc/pac-glue.c
+++ b/source4/kdc/pac-glue.c
@@ -41,263 +41,13 @@
#include "source4/kdc/samba_kdc.h"
#include "source4/kdc/pac-glue.h"
#include "source4/kdc/ad_claims.h"
+#include "source4/kdc/pac-blobs.h"
#include <ldb.h>
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_KERBEROS
-struct type_data {
- uint32_t type;
- const DATA_BLOB *data;
-};
-
-struct pac_blobs {
- size_t type_index[PAC_TYPE_COUNT];
- struct type_data *type_blobs;
- size_t num_types;
-};
-
-static void pac_blobs_init(struct pac_blobs *pac_blobs)
-{
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(pac_blobs->type_index); ++i) {
- pac_blobs->type_index[i] = SIZE_MAX;
- }
-
- pac_blobs->type_blobs = NULL;
- pac_blobs->num_types = 0;
-}
-
-static void pac_blobs_destroy(struct pac_blobs *pac_blobs)
-{
- TALLOC_FREE(pac_blobs->type_blobs);
-}
-
-static inline size_t *pac_blobs_get_index(struct pac_blobs *pac_blobs, size_t type)
-{
- /* Ensure the type is valid. */
- SMB_ASSERT(type >= PAC_TYPE_BEGIN);
- SMB_ASSERT(type < PAC_TYPE_END);
-
- return &pac_blobs->type_index[type - PAC_TYPE_BEGIN];
-}
-
-static inline struct type_data *pac_blobs_get(struct pac_blobs *pac_blobs, size_t type)
-{
- size_t index = *pac_blobs_get_index(pac_blobs, type);
- SMB_ASSERT(index < pac_blobs->num_types);
-
- return &pac_blobs->type_blobs[index];
-}
-
-static krb5_error_code pac_blobs_from_krb5_pac(struct pac_blobs *pac_blobs,
- TALLOC_CTX *mem_ctx,
- krb5_context context,
- const krb5_const_pac pac)
-{
- krb5_error_code code;
- uint32_t *types = NULL;
- size_t i;
-
- code = krb5_pac_get_types(context, pac, &pac_blobs->num_types, &types);
- if (code != 0) {
- DBG_ERR("krb5_pac_get_types failed\n");
- return code;
- }
-
- pac_blobs->type_blobs = talloc_array(mem_ctx, struct type_data, pac_blobs->num_types);
- if (pac_blobs->type_blobs == NULL) {
- DBG_ERR("Out of memory\n");
- SAFE_FREE(types);
- return ENOMEM;
- }
-
- for (i = 0; i < pac_blobs->num_types; ++i) {
- uint32_t type = types[i];
- size_t *type_index = NULL;
-
- pac_blobs->type_blobs[i] = (struct type_data) {
- .type = type,
- .data = NULL,
- };
-
- switch (type) {
- /* PAC buffer types that we support. */
- case PAC_TYPE_LOGON_INFO:
- case PAC_TYPE_CREDENTIAL_INFO:
- case PAC_TYPE_SRV_CHECKSUM:
- case PAC_TYPE_KDC_CHECKSUM:
- case PAC_TYPE_LOGON_NAME:
- case PAC_TYPE_CONSTRAINED_DELEGATION:
- case PAC_TYPE_UPN_DNS_INFO:
- case PAC_TYPE_CLIENT_CLAIMS_INFO:
- case PAC_TYPE_DEVICE_INFO:
- case PAC_TYPE_DEVICE_CLAIMS_INFO:
- case PAC_TYPE_TICKET_CHECKSUM:
- case PAC_TYPE_ATTRIBUTES_INFO:
- case PAC_TYPE_REQUESTER_SID:
- case PAC_TYPE_FULL_CHECKSUM:
- type_index = pac_blobs_get_index(pac_blobs, type);
- if (*type_index != SIZE_MAX) {
- DBG_WARNING("PAC buffer type[%"PRIu32"] twice\n", type);
- pac_blobs_destroy(pac_blobs);
- SAFE_FREE(types);
- return EINVAL;
- }
- *type_index = i;
-
- break;
- default:
- break;
- }
- }
-
- SAFE_FREE(types);
- return 0;
-}
-
-#define pac_blobs_ensure_exists(pac_blobs, type) \
- _pac_blobs_ensure_exists(pac_blobs, \
- type, \
- #type, \
- __location__, \
- __func__)
-
-static inline krb5_error_code _pac_blobs_ensure_exists(struct pac_blobs *pac_blobs,
- const uint32_t type,
- const char *name,
- const char *location,
- const char *function)
-{
- if (*pac_blobs_get_index(pac_blobs, type) == SIZE_MAX) {
- DEBUGLF(DBGLVL_ERR, ("%s: %s missing\n", function, name), location, function);
- return EINVAL;
- }
-
- return 0;
-}
-
-#define pac_blobs_replace_existing(pac_blobs, type, blob) \
- _pac_blobs_replace_existing(pac_blobs, \
- type, \
- #type, \
- blob, \
- __location__, \
- __func__)
-
-static krb5_error_code _pac_blobs_replace_existing(struct pac_blobs *pac_blobs,
- const uint32_t type,
- const char *name,
- const DATA_BLOB *blob,
- const char *location,
- const char *function)
-{
- krb5_error_code code;
-
- code = _pac_blobs_ensure_exists(pac_blobs,
- type,
- name,
- location,
- function);
- if (code != 0) {
- return code;
- }
-
- pac_blobs_get(pac_blobs, type)->data = blob;
-
- return 0;
-}
-
-static krb5_error_code pac_blobs_add_blob(struct pac_blobs *pac_blobs,
- TALLOC_CTX *mem_ctx,
- const uint32_t type,
- const DATA_BLOB *blob)
-{
- size_t *index = NULL;
-
- if (blob == NULL) {
- return 0;
- }
-
- index = pac_blobs_get_index(pac_blobs, type);
- if (*index == SIZE_MAX) {
- pac_blobs->type_blobs = talloc_realloc(mem_ctx,
- pac_blobs->type_blobs,
- struct type_data,
- pac_blobs->num_types + 1);
- if (pac_blobs->type_blobs == NULL) {
- DBG_ERR("Out of memory\n");
- return ENOMEM;
- }
-
- *index = pac_blobs->num_types++;
- }
-
- *pac_blobs_get(pac_blobs, type) = (struct type_data) {
- .type = type,
- .data = blob,
- };
-
- return 0;
-}
-
-static krb5_error_code pac_blobs_remove_blob(struct pac_blobs *pac_blobs,
- TALLOC_CTX *mem_ctx,
- const uint32_t type)
-{
- size_t found_index;
- size_t i;
-
- /* Get the index of this PAC buffer type. */
- found_index = *pac_blobs_get_index(pac_blobs, type);
- if (found_index == SIZE_MAX) {
- /* We don't have a PAC buffer of this type, so we're done. */
- return 0;
- }
-
- /* Since the PAC buffer is present, there will be at least one type in the array. */
- SMB_ASSERT(pac_blobs->num_types > 0);
-
- /* The index should be valid. */
- SMB_ASSERT(found_index < pac_blobs->num_types);
-
- /*
- * Even though a consistent ordering of PAC buffers is not to be relied
- * upon, we must still maintain the ordering we are given.
- */
- for (i = found_index; i < pac_blobs->num_types - 1; ++i) {
- size_t moved_type;
-
- /* Shift each following element backwards by one. */
- pac_blobs->type_blobs[i] = pac_blobs->type_blobs[i + 1];
-
- /* Mark the new position of the moved element in the index. */
- moved_type = pac_blobs->type_blobs[i].type;
- if (moved_type >= PAC_TYPE_BEGIN && moved_type < PAC_TYPE_END) {
- *pac_blobs_get_index(pac_blobs, moved_type) = i;
- }
- }
-
- /* Mark the removed element as no longer present. */
- *pac_blobs_get_index(pac_blobs, type) = SIZE_MAX;
-
- /* We do not free the removed data blob, as it may be statically allocated (e.g., a null blob). */
-
- /* Remove the last element from the array. */
- pac_blobs->type_blobs = talloc_realloc(mem_ctx,
- pac_blobs->type_blobs,
- struct type_data,
- --pac_blobs->num_types);
- if (pac_blobs->type_blobs == NULL) {
- DBG_ERR("Out of memory\n");
- return ENOMEM;
- }
-
- return 0;
-}
-
static
NTSTATUS samba_get_logon_info_pac_blob(TALLOC_CTX *mem_ctx,
const struct auth_user_info_dc *info,
diff --git a/source4/kdc/wscript_build b/source4/kdc/wscript_build
index c6c00c4c369..807fd10791c 100644
--- a/source4/kdc/wscript_build
+++ b/source4/kdc/wscript_build
@@ -122,7 +122,7 @@ bld.SAMBA_SUBSYSTEM('sdb_kdb',
)
bld.SAMBA_SUBSYSTEM('PAC_GLUE',
- source='pac-glue.c',
+ source='pac-glue.c pac-blobs.c',
deps='ldb auth4_sam common_auth samba-credentials samba-hostconfig com_err ad_claims'
)