]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
gensec: Refactor gensec_security_mechs()
authorVolker Lendecke <vl@samba.org>
Tue, 28 May 2024 16:49:41 +0000 (18:49 +0200)
committerVolker Lendecke <vl@samba.org>
Tue, 4 Jun 2024 07:11:35 +0000 (07:11 +0000)
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 <vl@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
auth/gensec/gensec_start.c

index e4b9ddb93c62d75237c85948bf78382f8f43beed..c4c5f04029bdf1b601d7854916192654aff6c591 100644 (file)
@@ -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(