From 426c08476704f8ac574a18562719517c6084ed3f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 28 May 2024 18:49:41 +0200 Subject: [PATCH] gensec: Refactor gensec_security_mechs() The decision whether to offer a mechanism was split between gensec_security_mechs() and gensec_use_kerberos_mechs() with two booleans passed down. Consolidate that decision into one gensec_offer_mech() function that queries all information on its own. Signed-off-by: Volker Lendecke Reviewed-by: Andrew Bartlett --- auth/gensec/gensec_start.c | 145 ++++++++++++++++++------------------- 1 file changed, 69 insertions(+), 76 deletions(-) diff --git a/auth/gensec/gensec_start.c b/auth/gensec/gensec_start.c index e4b9ddb93c6..c4c5f04029b 100644 --- a/auth/gensec/gensec_start.c +++ b/auth/gensec/gensec_start.c @@ -79,72 +79,62 @@ bool gensec_security_ops_enabled(const struct gensec_security_ops *ops, struct g * more complex. */ -static const struct gensec_security_ops **gensec_use_kerberos_mechs( - TALLOC_CTX *mem_ctx, - const struct gensec_security_ops * const *old_gensec_list, - enum credentials_use_kerberos use_kerberos, - bool keep_schannel) +static bool gensec_offer_mech(struct gensec_security *gensec_security, + const struct gensec_security_ops *mech) { - const struct gensec_security_ops **new_gensec_list; - int i, j, num_mechs_in; + struct cli_credentials *creds = NULL; + enum credentials_use_kerberos use_kerberos; + bool offer; - for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) { - /* noop */ - } + /* + * We want to always offer SPNEGO and other backends + */ + offer = mech->glue; - new_gensec_list = talloc_array(mem_ctx, - const struct gensec_security_ops *, - num_mechs_in + 1); - if (!new_gensec_list) { - return NULL; + if (gensec_security != NULL) { + creds = gensec_get_credentials(gensec_security); } - j = 0; - for (i=0; old_gensec_list && old_gensec_list[i]; i++) { - bool keep = false; - + if ((mech->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) && (creds != NULL)) + { + if (cli_credentials_get_netlogon_creds(creds) != NULL) { + offer = true; + } /* - * We want to keep SPNEGO and other backends + * Even if Kerberos is set to REQUIRED, offer the + * schannel auth mechanism so that machine accounts are + * able to authenticate via netlogon. */ - keep = old_gensec_list[i]->glue; - - if (old_gensec_list[i]->auth_type == DCERPC_AUTH_TYPE_SCHANNEL) { - keep = keep_schannel; + if (gensec_security->gensec_role == GENSEC_SERVER) { + offer = true; } + } - switch (use_kerberos) { - case CRED_USE_KERBEROS_DESIRED: - keep = true; - break; - - case CRED_USE_KERBEROS_DISABLED: - if (old_gensec_list[i]->kerberos == false) { - keep = true; - } - - break; - - case CRED_USE_KERBEROS_REQUIRED: - if (old_gensec_list[i]->kerberos == true) { - keep = true; - } + use_kerberos = CRED_USE_KERBEROS_DESIRED; + if (creds != NULL) { + use_kerberos = cli_credentials_get_kerberos_state(creds); + } - break; - default: - /* Can't happen or invalid parameter */ - return NULL; + switch (use_kerberos) { + case CRED_USE_KERBEROS_DESIRED: + offer = true; + break; + case CRED_USE_KERBEROS_DISABLED: + if (!mech->kerberos) { + offer = true; } - - if (!keep) { - continue; + break; + case CRED_USE_KERBEROS_REQUIRED: + if (mech->kerberos) { + offer = true; } - - new_gensec_list[j] = old_gensec_list[i]; - j++; + break; + default: + /* Can't happen or invalid parameter */ + offer = false; } - new_gensec_list[j] = NULL; - return new_gensec_list; + return offer; } _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs( @@ -153,37 +143,40 @@ _PUBLIC_ const struct gensec_security_ops **gensec_security_mechs( { const struct gensec_security_ops * const *backends = generic_security_ops; - enum credentials_use_kerberos use_kerberos = CRED_USE_KERBEROS_DESIRED; - bool keep_schannel = false; + const struct gensec_security_ops **result = NULL; + size_t i, j, num_backends; - if (gensec_security != NULL) { - struct cli_credentials *creds = NULL; + if ((gensec_security != NULL) && + (gensec_security->settings->backends != NULL)) { + backends = gensec_security->settings->backends; + } - creds = gensec_get_credentials(gensec_security); - if (creds != NULL) { - use_kerberos = cli_credentials_get_kerberos_state(creds); - if (cli_credentials_get_netlogon_creds(creds) != NULL) { - keep_schannel = true; - } + if (backends == NULL) { + /* Just return the NULL terminator */ + return talloc_zero(mem_ctx, + const struct gensec_security_ops *); + } - /* - * Even if Kerberos is set to REQUIRED, keep the - * schannel auth mechanism so that machine accounts are - * able to authenticate via netlogon. - */ - if (gensec_security->gensec_role == GENSEC_SERVER) { - keep_schannel = true; - } - } + for (num_backends = 0; backends[num_backends]; num_backends++) { + /* noop */ + } - if (gensec_security->settings->backends) { - backends = gensec_security->settings->backends; - } + result = talloc_array( + mem_ctx, const struct gensec_security_ops *, num_backends + 1); + if (result == NULL) { + return NULL; } - return gensec_use_kerberos_mechs(mem_ctx, backends, - use_kerberos, keep_schannel); + j = 0; + for (i = 0; backends[i]; i++) { + bool offer = gensec_offer_mech(gensec_security, backends[i]); + if (offer) { + result[j++] = backends[i]; + } + } + result[j] = NULL; + return result; } static const struct gensec_security_ops *gensec_security_by_fn( -- 2.47.3