The branch, v3-5-test has been updated
       via  a5b388f s3-winbindd: let winbind try to use samlogon validation 
level 6. (bug #7945)
      from  f0e3978 s3: Prune the printername cache when a printer is deleted.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-5-test


- Log -----------------------------------------------------------------
commit a5b388fc5ea81868f09590e8b7674826315c348c
Author: Günther Deschner <g...@samba.org>
Date:   Fri Jan 7 17:28:29 2011 +0100

    s3-winbindd: let winbind try to use samlogon validation level 6. (bug #7945)
    
    The benefit of this that it makes us more robust to secure channel resets
    triggered from tools outside the winbind process. Long term we need to have 
a
    shared tdb secure channel store though as well.
    
    Guenther
    
    Signed-off-by: Stefan Metzmacher <me...@samba.org>
    
    (similar to commit f60398d7b20869d7b09d81854f3727fdcd897430)
    (similar to commit 7add712498fe93603b1bffff2c633e097ce8fbdf)

-----------------------------------------------------------------------

Summary of changes:
 source3/auth/auth_domain.c        |    1 +
 source3/auth/auth_netlogond.c     |    1 +
 source3/include/proto.h           |    2 +
 source3/rpc_client/cli_netlogon.c |  100 +++++++++++++++++++++++++++++++++++--
 source3/winbindd/winbindd.h       |    1 +
 source3/winbindd/winbindd_cm.c    |    1 +
 source3/winbindd/winbindd_pam.c   |   97 +++++++++++++++++++++++++++++++++++-
 7 files changed, 198 insertions(+), 5 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index c527360..9677ce7 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -310,6 +310,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
                                                      user_info->client_domain, 
  /* domain name */
                                                      user_info->wksta_name,    
  /* workstation name */
                                                      chal,                     
  /* 8 byte challenge. */
+                                                     3,                        
  /* validation level */
                                                      user_info->lm_resp,       
  /* lanman 24 byte response */
                                                      user_info->nt_resp,       
  /* nt 24 byte response */
                                                      &info3);                  
  /* info3 out */
diff --git a/source3/auth/auth_netlogond.c b/source3/auth/auth_netlogond.c
index ebfed83..2347dae 100644
--- a/source3/auth/auth_netlogond.c
+++ b/source3/auth/auth_netlogond.c
@@ -85,6 +85,7 @@ static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx,
                user_info->client_domain,   /* domain name */
                user_info->wksta_name,      /* workstation name */
                (uchar *)auth_context->challenge.data, /* 8 byte challenge. */
+               3,                          /* validation level */
                user_info->lm_resp,         /* lanman 24 byte response */
                user_info->nt_resp,         /* nt 24 byte response */
                &info3);                    /* info3 out */
diff --git a/source3/include/proto.h b/source3/include/proto.h
index bfcd012..ce33b70 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -5260,6 +5260,7 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct 
rpc_pipe_client *cli,
                                           const char *domain,
                                           const char *workstation,
                                           const uint8 chal[8],
+                                          uint16_t validation_level,
                                           DATA_BLOB lm_response,
                                           DATA_BLOB nt_response,
                                           struct netr_SamInfo3 **info3);
@@ -5271,6 +5272,7 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct 
rpc_pipe_client *cli,
                                              const char *domain,
                                              const char *workstation,
                                              const uint8 chal[8],
+                                             uint16_t validation_level,
                                              DATA_BLOB lm_response,
                                              DATA_BLOB nt_response,
                                              struct netr_SamInfo3 **info3);
diff --git a/source3/rpc_client/cli_netlogon.c 
b/source3/rpc_client/cli_netlogon.c
index 9cb0bc6..ca66faa 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -283,6 +283,92 @@ NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client 
*cli,
        return result;
 }
 
+#define COPY_LSA_STRING(mem_ctx, in, out, name) do { \
+       if (in->name.string) { \
+               out->name.string = talloc_strdup(mem_ctx, in->name.string); \
+               NT_STATUS_HAVE_NO_MEMORY(out->name.string); \
+       } \
+} while (0)
+
+static NTSTATUS copy_netr_SamBaseInfo(TALLOC_CTX *mem_ctx,
+                                     const struct netr_SamBaseInfo *in,
+                                     struct netr_SamBaseInfo *out)
+{
+       /* first copy all, then realloc pointers */
+       *out = *in;
+
+       COPY_LSA_STRING(mem_ctx, in, out, account_name);
+       COPY_LSA_STRING(mem_ctx, in, out, full_name);
+       COPY_LSA_STRING(mem_ctx, in, out, logon_script);
+       COPY_LSA_STRING(mem_ctx, in, out, profile_path);
+       COPY_LSA_STRING(mem_ctx, in, out, home_directory);
+       COPY_LSA_STRING(mem_ctx, in, out, home_drive);
+
+       if (in->groups.count) {
+               out->groups.rids = (struct samr_RidWithAttribute *)
+                       talloc_memdup(mem_ctx, in->groups.rids,
+                               (sizeof(struct samr_RidWithAttribute) *
+                                       in->groups.count));
+               NT_STATUS_HAVE_NO_MEMORY(out->groups.rids);
+       }
+
+       COPY_LSA_STRING(mem_ctx, in, out, logon_server);
+       COPY_LSA_STRING(mem_ctx, in, out, domain);
+
+       if (in->domain_sid) {
+               out->domain_sid = sid_dup_talloc(mem_ctx, in->domain_sid);
+               NT_STATUS_HAVE_NO_MEMORY(out->domain_sid);
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS map_validation_to_info3(TALLOC_CTX *mem_ctx,
+                                       uint16_t validation_level,
+                                       union netr_Validation *validation,
+                                       struct netr_SamInfo3 **info3_p)
+{
+       struct netr_SamInfo3 *info3;
+       NTSTATUS status;
+
+       if (validation == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       switch (validation_level) {
+       case 3:
+               if (validation->sam3 == NULL) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               info3 = talloc_move(mem_ctx, &validation->sam3);
+               break;
+       case 6:
+               if (validation->sam6 == NULL) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
+
+               info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
+               if (info3 == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               status = copy_netr_SamBaseInfo(info3, &validation->sam6->base, 
&info3->base);
+               if (!NT_STATUS_IS_OK(status)) {
+                       TALLOC_FREE(info3);
+                       return status;
+               }
+
+               info3->sidcount = validation->sam6->sidcount;
+               info3->sids = talloc_move(info3, &validation->sam6->sids);
+               break;
+       default:
+               return NT_STATUS_BAD_VALIDATION_CLASS;
+       }
+
+       *info3_p = info3;
+
+       return NT_STATUS_OK;
+}
 
 /**
  * Logon domain user with an 'network' SAM logon
@@ -298,12 +384,12 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct 
rpc_pipe_client *cli,
                                           const char *domain,
                                           const char *workstation,
                                           const uint8 chal[8],
+                                          uint16_t validation_level,
                                           DATA_BLOB lm_response,
                                           DATA_BLOB nt_response,
                                           struct netr_SamInfo3 **info3)
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       int validation_level = 3;
        const char *workstation_name_slash;
        const char *server_name_slash;
        uint8 zeros[16];
@@ -397,7 +483,10 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct 
rpc_pipe_client *cli,
 
        netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
 
-       *info3 = validation.sam3;
+       result = map_validation_to_info3(mem_ctx, validation_level, 
&validation, info3);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
 
        return result;
 }
@@ -410,12 +499,12 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct 
rpc_pipe_client *cli,
                                              const char *domain,
                                              const char *workstation,
                                              const uint8 chal[8],
+                                             uint16_t validation_level,
                                              DATA_BLOB lm_response,
                                              DATA_BLOB nt_response,
                                              struct netr_SamInfo3 **info3)
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       int validation_level = 3;
        const char *workstation_name_slash;
        const char *server_name_slash;
        uint8 zeros[16];
@@ -498,7 +587,10 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct 
rpc_pipe_client *cli,
 
        netlogon_creds_decrypt_samlogon(cli->dc, validation_level, &validation);
 
-       *info3 = validation.sam3;
+       result = map_validation_to_info3(mem_ctx, validation_level, 
&validation, info3);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
 
        return result;
 }
diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h
index f1815ac..56b0ad9 100644
--- a/source3/winbindd/winbindd.h
+++ b/source3/winbindd/winbindd.h
@@ -167,6 +167,7 @@ struct winbindd_domain {
                                  * we don't have to try _ex every time. */
 
        bool can_do_ncacn_ip_tcp;
+       bool can_do_validation6;
 
        /* Lookup methods for this domain (LDAP or RPC) */
        struct winbindd_methods *methods;
diff --git a/source3/winbindd/winbindd_cm.c b/source3/winbindd/winbindd_cm.c
index 77e5003..cc3e3ed 100644
--- a/source3/winbindd/winbindd_cm.c
+++ b/source3/winbindd/winbindd_cm.c
@@ -1945,6 +1945,7 @@ done:
                  domain->name, domain->active_directory ? "" : "NOT "));
 
        domain->can_do_ncacn_ip_tcp = domain->active_directory;
+       domain->can_do_validation6 = domain->active_directory;
 
        TALLOC_FREE(cli);
 
diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c
index e958a7e..aab3b72 100644
--- a/source3/winbindd/winbindd_pam.c
+++ b/source3/winbindd/winbindd_pam.c
@@ -1185,6 +1185,7 @@ typedef   NTSTATUS (*netlogon_fn_t)(struct 
rpc_pipe_client *cli,
                                  const char *domain,
                                  const char *workstation,
                                  const uint8 chal[8],
+                                 uint16_t validation_level,
                                  DATA_BLOB lm_response,
                                  DATA_BLOB nt_response,
                                  struct netr_SamInfo3 **info3);
@@ -1296,6 +1297,8 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(struct 
winbindd_domain *domain,
 
        do {
                netlogon_fn_t logon_fn;
+               const struct cli_pipe_auth_data *auth;
+               uint32_t neg_flags = 0;
 
                ZERO_STRUCTP(my_info3);
                retry = false;
@@ -1306,6 +1309,10 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(struct 
winbindd_domain *domain,
                        DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
                        goto done;
                }
+               auth = netlogon_pipe->auth;
+               if (netlogon_pipe->dc) {
+                       neg_flags = netlogon_pipe->dc->negotiate_flags;
+               }
 
                /* It is really important to try SamLogonEx here,
                 * because in a clustered environment, we want to use
@@ -1326,8 +1333,35 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(struct 
winbindd_domain *domain,
                 * wrapping SamLogon context.
                 *
                 *  -- abartlet 21 April 2008
+                *
+                * It's also important to use NetlogonValidationSamInfo4 (6),
+                * because it relies on the rpc transport encryption
+                * and avoids using the global netlogon schannel
+                * session key to en/decrypt secret information
+                * like the user_session_key for network logons.
+                *
+                * [MS-APDS] 3.1.5.2 NTLM Network Logon
+                * says NETLOGON_NEG_CROSS_FOREST_TRUSTS and
+                * NETLOGON_NEG_AUTHENTICATED_RPC set together
+                * are the indication that the server supports
+                * NetlogonValidationSamInfo4 (6). And must only
+                * be used if "SealSecureChannel" is used.
+                *
+                * -- metze 4 February 2011
                 */
 
+               if (auth == NULL) {
+                       domain->can_do_validation6 = false;
+               } else if (auth->auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
+                       domain->can_do_validation6 = false;
+               } else if (auth->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
+                       domain->can_do_validation6 = false;
+               } else if (!(neg_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
+                       domain->can_do_validation6 = false;
+               } else if (!(neg_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
+                       domain->can_do_validation6 = false;
+               }
+
                logon_fn = contact_domain->can_do_samlogon_ex
                        ? rpccli_netlogon_sam_network_logon_ex
                        : rpccli_netlogon_sam_network_logon;
@@ -1340,20 +1374,42 @@ static NTSTATUS winbindd_dual_pam_auth_samlogon(struct 
winbindd_domain *domain,
                                  name_domain,            /* target domain */
                                  global_myname(),        /* workstation */
                                  chal,
+                                 domain->can_do_validation6 ? 6 : 3,
                                  lm_resp,
                                  nt_resp,
                                  &my_info3);
-               attempts += 1;
 
                if ((NT_STATUS_V(result) == DCERPC_FAULT_OP_RNG_ERROR)
                    && contact_domain->can_do_samlogon_ex) {
                        DEBUG(3, ("Got a DC that can not do NetSamLogonEx, "
                                  "retrying with NetSamLogon\n"));
                        contact_domain->can_do_samlogon_ex = false;
+                       /*
+                        * It's likely that the server also does not support
+                        * validation level 6
+                        */
+                       domain->can_do_validation6 = false;
+                       retry = true;
+                       continue;
+               }
+
+               if (domain->can_do_validation6 &&
+                   (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) ||
+                    NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) ||
+                    NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL))) {
+                       DEBUG(3,("Got a DC that can not do validation level 6, "
+                                 "retrying with level 3\n"));
+                       domain->can_do_validation6 = false;
                        retry = true;
                        continue;
                }
 
+               /*
+                * we increment this after the "feature negotiation"
+                * for can_do_samlogon_ex and can_do_validation6
+                */
+               attempts += 1;
+
                /* We have to try a second time as cm_connect_netlogon
                   might not yet have noticed that the DC has killed
                   our connection. */
@@ -1889,6 +1945,8 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct 
winbindd_domain *domain,
 
        do {
                netlogon_fn_t logon_fn;
+               const struct cli_pipe_auth_data *auth;
+               uint32_t neg_flags = 0;
 
                retry = false;
 
@@ -1900,6 +1958,22 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct 
winbindd_domain *domain,
                                  nt_errstr(result)));
                        goto done;
                }
+               auth = netlogon_pipe->auth;
+               if (netlogon_pipe->dc) {
+                       neg_flags = netlogon_pipe->dc->negotiate_flags;
+               }
+
+               if (auth == NULL) {
+                       domain->can_do_validation6 = false;
+               } else if (auth->auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
+                       domain->can_do_validation6 = false;
+               } else if (auth->auth_level != DCERPC_AUTH_LEVEL_PRIVACY) {
+                       domain->can_do_validation6 = false;
+               } else if (!(neg_flags & NETLOGON_NEG_CROSS_FOREST_TRUSTS)) {
+                       domain->can_do_validation6 = false;
+               } else if (!(neg_flags & NETLOGON_NEG_AUTHENTICATED_RPC)) {
+                       domain->can_do_validation6 = false;
+               }
 
                logon_fn = contact_domain->can_do_samlogon_ex
                        ? rpccli_netlogon_sam_network_logon_ex
@@ -1914,6 +1988,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct 
winbindd_domain *domain,
                                  /* Bug #3248 - found by Stefan Burkei. */
                                  workstation, /* We carefully set this above 
so use it... */
                                  state->request->data.auth_crap.chal,
+                                 domain->can_do_validation6 ? 6 : 3,
                                  lm_resp,
                                  nt_resp,
                                  &info3);
@@ -1923,10 +1998,30 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct 
winbindd_domain *domain,
                        DEBUG(3, ("Got a DC that can not do NetSamLogonEx, "
                                  "retrying with NetSamLogon\n"));
                        contact_domain->can_do_samlogon_ex = false;
+                       /*
+                        * It's likely that the server also does not support
+                        * validation level 6
+                        */
+                       domain->can_do_validation6 = false;
                        retry = true;
                        continue;
                }
 
+               if (domain->can_do_validation6 &&
+                   (NT_STATUS_EQUAL(result, NT_STATUS_INVALID_INFO_CLASS) ||
+                    NT_STATUS_EQUAL(result, NT_STATUS_INVALID_PARAMETER) ||
+                    NT_STATUS_EQUAL(result, NT_STATUS_BUFFER_TOO_SMALL))) {
+                       DEBUG(3,("Got a DC that can not do validation level 6, "
+                                 "retrying with level 3\n"));
+                       domain->can_do_validation6 = false;
+                       retry = true;
+                       continue;
+               }
+
+               /*
+                * we increment this after the "feature negotiation"
+                * for can_do_samlogon_ex and can_do_validation6
+                */
                attempts += 1;
 
                /* We have to try a second time as cm_connect_netlogon


-- 
Samba Shared Repository

Reply via email to