]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
s3:libads: split out ads_legacy_creds()
authorStefan Metzmacher <metze@samba.org>
Mon, 25 Apr 2022 16:08:33 +0000 (18:08 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 14 May 2024 10:18:31 +0000 (10:18 +0000)
This is just a temporary change until the highlevel caller
will pass in a cli_credentials structure and we'll get rid of
ads->auth.{user_name,realm,password}.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
source3/libads/ads_proto.h
source3/libads/ldap.c
source3/libads/sasl.c

index 2fb915996a6edc769e847080268a3449234b9f51..93fe2a2082fb3839640d51268a8560931d9cbe34 100644 (file)
@@ -32,6 +32,8 @@
 #ifndef _LIBADS_ADS_PROTO_H_
 #define _LIBADS_ADS_PROTO_H_
 
+struct cli_credentials;
+
 enum ads_sasl_state_e {
        ADS_SASL_PLAIN = 0,
        ADS_SASL_SIGN,
@@ -201,6 +203,9 @@ ADS_STATUS ads_ranged_search(ADS_STRUCT *ads,
 
 /* The following definitions come from libads/sasl.c  */
 
+NTSTATUS ads_legacy_creds(ADS_STRUCT *ads,
+                         TALLOC_CTX *mem_ctx,
+                         struct cli_credentials **_creds);
 ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads);
 
 /* The following definitions come from libads/sasl_wrapping.c  */
index e597f78597f007b08309b69348ad36ed989653ce..b5bf5634086e71b7f9a858c1391c61a4c7ba9dc6 100644 (file)
@@ -933,27 +933,6 @@ got_connection:
        print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
        DEBUG(3,("Successfully contacted LDAP server %s\n", addr));
 
-       if (!ads->auth.user_name) {
-               /* Must use the userPrincipalName value here or sAMAccountName
-                  and not servicePrincipalName; found by Guenther Deschner */
-               ads->auth.user_name = talloc_asprintf(ads,
-                                                     "%s$",
-                                                     lp_netbios_name());
-               if (ads->auth.user_name == NULL) {
-                       DBG_ERR("talloc_asprintf failed\n");
-                       status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
-                       goto out;
-               }
-       }
-
-       if (ads->auth.realm == NULL) {
-               ads->auth.realm = talloc_strdup(ads, ads->config.realm);
-               if (ads->auth.realm == NULL) {
-                       status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
-                       goto out;
-               }
-       }
-
        if (!ads->auth.kdc_server) {
                print_sockaddr(addr, sizeof(addr), &ads->ldap.ss);
                ads->auth.kdc_server = talloc_strdup(ads, addr);
index 32331d9ff6bd1575348b021ee60165e8b2d19d0a..61127d05556b2dce2bb175cca69552a9be28ecc1 100644 (file)
@@ -24,7 +24,7 @@
 #include "ads.h"
 #include "smb_krb5.h"
 #include "system/gssapi.h"
-#include "lib/param/loadparm.h"
+#include "lib/param/param.h"
 #include "krb5_env.h"
 #include "lib/util/asn1.h"
 
@@ -117,12 +117,157 @@ static const struct ads_saslwrap_ops ads_sasl_gensec_ops = {
        .disconnect     = ads_sasl_gensec_disconnect
 };
 
+NTSTATUS ads_legacy_creds(ADS_STRUCT *ads,
+                         TALLOC_CTX *mem_ctx,
+                         struct cli_credentials **_creds)
+{
+       TALLOC_CTX *frame = talloc_stackframe();
+       struct cli_credentials *creds = NULL;
+       struct loadparm_context *lp_ctx = NULL;
+       const char *account_name = NULL;
+       fstring acct_name;
+       enum credentials_use_kerberos krb5_state;
+       uint32_t gensec_features;
+       bool ok;
+
+       if (ads->auth.flags & (ADS_AUTH_NO_BIND|ADS_AUTH_ANON_BIND)) {
+               SMB_ASSERT(!(ads->auth.flags & ADS_AUTH_USER_CREDS));
+
+               creds = cli_credentials_init_anon(mem_ctx);
+               if (creds == NULL) {
+                       TALLOC_FREE(frame);
+                       return NT_STATUS_NO_MEMORY;
+               }
+               talloc_steal(frame, creds);
+               goto done;
+       }
+
+       if (ads->auth.user_name == NULL) {
+               /*
+                * Must use the userPrincipalName value here or sAMAccountName
+                * and not servicePrincipalName; found by Guenther Deschner
+                */
+               ads->auth.user_name = talloc_asprintf(ads,
+                                                     "%s$",
+                                                     lp_netbios_name());
+               if (ads->auth.user_name == NULL) {
+                       TALLOC_FREE(frame);
+                       return NT_STATUS_NO_MEMORY;
+               }
+       }
+
+       if (ads->auth.realm == NULL) {
+               if (ads->server.realm != NULL) {
+                       ads->auth.realm = talloc_strdup(ads, ads->server.realm);
+                       if (ads->auth.realm == NULL) {
+                               TALLOC_FREE(frame);
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               } else {
+                       ads->auth.realm = talloc_strdup(ads, lp_realm());
+                       if (ads->auth.realm == NULL) {
+                               TALLOC_FREE(frame);
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               }
+       }
+
+       lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
+       if (lp_ctx == NULL) {
+               DBG_ERR("loadparm_init_s3 failed\n");
+               TALLOC_FREE(frame);
+               return NT_STATUS_INVALID_SERVER_STATE;
+       }
+
+       creds = cli_credentials_init(mem_ctx);
+       if (creds == NULL) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+       talloc_steal(frame, creds);
+
+       ok = cli_credentials_guess(creds, lp_ctx);
+       if (!ok) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       /*
+        * This logic was taken from ads_kinit_password()
+        */
+       if (ads->auth.flags & ADS_AUTH_USER_CREDS) {
+               account_name = ads->auth.user_name;
+       } else if (IS_DC) {
+               /* this will end up getting a ticket for DOMAIN@RUSTED.REA.LM */
+               account_name = lp_workgroup();
+       } else if (lp_security() == SEC_DOMAIN ) {
+               fstr_sprintf( acct_name, "%s$", lp_netbios_name() );
+               account_name = acct_name;
+       } else {
+               /* This looks like host/lp_netbios_name()@REA.LM */
+               account_name = ads->auth.user_name;
+       }
+
+       ok = cli_credentials_set_username(creds,
+                                         account_name,
+                                         CRED_SPECIFIED);
+       if (!ok) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+       ok = cli_credentials_set_domain(creds,
+                                       ads->auth.realm,
+                                       CRED_SPECIFIED);
+       if (!ok) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+       ok = cli_credentials_set_password(creds,
+                                         ads->auth.password,
+                                         CRED_SPECIFIED);
+       if (!ok) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+#define __ADS_AUTH_BOTH (ADS_AUTH_ALLOW_NTLMSSP|ADS_AUTH_DISABLE_KERBEROS)
+       if ((ads->auth.flags & __ADS_AUTH_BOTH) == __ADS_AUTH_BOTH) {
+               krb5_state = CRED_USE_KERBEROS_DISABLED;
+       } else if (ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP) {
+               krb5_state = CRED_USE_KERBEROS_DESIRED;
+       } else if (ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) {
+               TALLOC_FREE(frame);
+               return NT_STATUS_INCOMPATIBLE_DRIVER_BLOCKED;
+       } else {
+               krb5_state = CRED_USE_KERBEROS_REQUIRED;
+       }
+       cli_credentials_set_kerberos_state(creds, krb5_state, CRED_SPECIFIED);
+
+       gensec_features = cli_credentials_get_gensec_features(creds);
+       if (ads->auth.flags & ADS_AUTH_SASL_LDAPS) {
+               gensec_features &= ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL);
+       } else if (ads->auth.flags & ADS_AUTH_SASL_STARTTLS) {
+               gensec_features &= ~(GENSEC_FEATURE_SIGN|GENSEC_FEATURE_SEAL);
+       } else if (ads->auth.flags & ADS_AUTH_SASL_SEAL) {
+               gensec_features |= GENSEC_FEATURE_SIGN;
+               gensec_features |= GENSEC_FEATURE_SEAL;
+       } else if (ads->auth.flags & ADS_AUTH_SASL_SIGN) {
+               gensec_features |= GENSEC_FEATURE_SIGN;
+       }
+       cli_credentials_set_gensec_features(creds, gensec_features, CRED_SPECIFIED);
+
+done:
+       *_creds = talloc_move(mem_ctx, &creds);
+       TALLOC_FREE(frame);
+       return NT_STATUS_OK;
+}
+
 /*
    perform a LDAP/SASL/SPNEGO/{NTLMSSP,KRB5} bind (just how many layers can
    we fit on one socket??)
 */
 static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
-                               enum credentials_use_kerberos krb5_state,
+                               struct cli_credentials *creds,
                                const char *target_service,
                                const char *target_hostname)
 {
@@ -143,20 +288,10 @@ static ADS_STATUS ads_sasl_spnego_gensec_bind(ADS_STRUCT *ads,
                return ADS_ERROR_NT(nt_status);
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_username(auth_generic_state, ads->auth.user_name))) {
-               return ADS_ERROR_NT(nt_status);
-       }
-       if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_domain(auth_generic_state, ads->auth.realm))) {
-               return ADS_ERROR_NT(nt_status);
-       }
-       if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_password(auth_generic_state, ads->auth.password))) {
+       if (!NT_STATUS_IS_OK(nt_status = auth_generic_set_creds(auth_generic_state, creds))) {
                return ADS_ERROR_NT(nt_status);
        }
 
-       cli_credentials_set_kerberos_state(auth_generic_state->credentials,
-                                          krb5_state,
-                                          CRED_SPECIFIED);
-
        if (target_service != NULL) {
                nt_status = gensec_set_target_service(
                                        auth_generic_state->gensec_security,
@@ -503,6 +638,8 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 {
        TALLOC_CTX *frame = talloc_stackframe();
        struct ads_service_principal p = {0};
+       struct cli_credentials *creds = NULL;
+       NTSTATUS nt_status;
        ADS_STATUS status;
        const char *mech = NULL;
 
@@ -511,18 +648,28 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
                goto done;
        }
 
+       nt_status = ads_legacy_creds(ads, frame, &creds);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               status = ADS_ERROR_NT(nt_status);
+               goto done;
+       }
+
 #ifdef HAVE_KRB5
        if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
            !is_ipaddress(p.hostname))
        {
                mech = "KRB5";
 
+               cli_credentials_set_kerberos_state(creds,
+                                                  CRED_USE_KERBEROS_REQUIRED,
+                                                  CRED_SPECIFIED);
+
                if (ads->auth.password == NULL ||
                    ads->auth.password[0] == '\0')
                {
 
                        status = ads_sasl_spnego_gensec_bind(ads,
-                                                            CRED_USE_KERBEROS_REQUIRED,
+                                                            creds,
                                                             p.service, p.hostname);
                        if (ADS_ERR_OK(status)) {
                                ads_free_service_principal(&p);
@@ -537,7 +684,7 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 
                if (ADS_ERR_OK(status)) {
                        status = ads_sasl_spnego_gensec_bind(ads,
-                                                       CRED_USE_KERBEROS_REQUIRED,
+                                                       creds,
                                                        p.service, p.hostname);
                        if (!ADS_ERR_OK(status)) {
                                DBG_ERR("kinit succeeded but "
@@ -584,8 +731,12 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
                goto done;
        }
 
+       cli_credentials_set_kerberos_state(creds,
+                                          CRED_USE_KERBEROS_DISABLED,
+                                          CRED_SPECIFIED);
+
        status = ads_sasl_spnego_gensec_bind(ads,
-                                            CRED_USE_KERBEROS_DISABLED,
+                                            creds,
                                             p.service, p.hostname);
 done:
        if (!ADS_ERR_OK(status)) {