Change our Domain controller lookup routines to more carefully seperate
authorAndrew Bartlett <abartlet@samba.org>
Mon, 5 Jan 2004 04:10:28 +0000 (04:10 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Mon, 5 Jan 2004 04:10:28 +0000 (04:10 +0000)
DNS names (realms) from NetBIOS domain names.

Until now, we would experience delays as we broadcast lookups for DNS names
onto the local network segments.

Now if DNS comes back negative, we fall straight back to looking up the
short name.

Andrew Bartlett
(This used to be commit 32397c8b01f1dec7b05140d210bb32f836a80ca6)

source3/auth/auth_domain.c
source3/libsmb/namequery_dc.c
source3/libsmb/trusts_util.c
source3/nsswitch/winbindd_ads.c
source3/nsswitch/winbindd_cm.c
source3/nsswitch/winbindd_misc.c
source3/nsswitch/winbindd_pam.c
source3/nsswitch/winbindd_rpc.c
source3/nsswitch/winbindd_util.c

index 43e7597cd9626356243688eaa8da2b8c33259606..0f34bcc0e2a20062c56b95ba4afb5491351ac444 100644 (file)
@@ -165,6 +165,9 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
 
        if ( !NT_STATUS_IS_OK(nt_status) ) {
                DEBUG(0,("domain_client_validate: Domain password server not available.\n"));
+               if (NT_STATUS_EQUAL(nt_status, NT_STATUS_ACCESS_DENIED)) {
+                       return NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE;
+               }
                return nt_status;
        }
 
@@ -290,7 +293,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
 
        /* we need our DC to send the net_sam_logon() request to */
 
-       if ( !get_dc_name(domain, dc_name, &dc_ip) ) {
+       if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
                DEBUG(5,("check_trustdomain_security: unable to locate a DC for domain %s\n",
                        user_info->domain.str));
                return NT_STATUS_NO_LOGON_SERVERS;
@@ -385,7 +388,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
        /* use get_dc_name() for consistency even through we know that it will be 
           a netbios name */
           
-       if ( !get_dc_name(user_info->domain.str, dc_name, &dc_ip) ) {
+       if ( !get_dc_name(user_info->domain.str, NULL, dc_name, &dc_ip) ) {
                DEBUG(5,("check_trustdomain_security: unable to locate a DC for domain %s\n",
                        user_info->domain.str));
                return NT_STATUS_NO_LOGON_SERVERS;
index df7f856cd7b1837ee06d8bf7c955cc228dd1147d..31d759e0d2cde636b52501ee99fd819738cfd569 100644 (file)
  Find the name and IP address for a server in he realm/domain
  *************************************************************************/
  
-static BOOL ads_dc_name(const char *domain, struct in_addr *dc_ip, fstring srv_name)
+static BOOL ads_dc_name(const char *domain, const char *realm, struct in_addr *dc_ip, fstring srv_name)
 {
        ADS_STRUCT *ads;
-       const char *realm = domain;
 
-       if (strequal(realm, lp_workgroup()))
+       if (!realm && strequal(domain, lp_workgroup()))
                realm = lp_realm();
 
        ads = ads_init(realm, domain, NULL);
        if (!ads)
                return False;
 
-       /* we don't need to bind, just connect */
-       ads->auth.flags |= ADS_AUTH_NO_BIND;
-
        DEBUG(4,("ads_dc_name: domain=%s\n", domain));
 
 #ifdef HAVE_ADS
-       /* a full ads_connect() is actually overkill, as we don't srictly need
-          to do the SASL auth in order to get the info we need, but libads
-          doesn't offer a better way right now */
+       /* we don't need to bind, just connect */
+       ads->auth.flags |= ADS_AUTH_NO_BIND;
+
        ads_connect(ads);
 #endif
 
@@ -157,7 +153,7 @@ static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip
  wrapper around ads and rpc methods of finds DC's
 **********************************************************************/
 
-BOOL get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
+BOOL get_dc_name(const char *domain, const char *realm, fstring srv_name, struct in_addr *ip_out)
 {
        struct in_addr dc_ip;
        BOOL ret;
@@ -167,15 +163,14 @@ BOOL get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out)
 
        ret = False;
        
-       if ( strequal(lp_workgroup(), domain) || strequal(lp_realm(), domain) )
+       if ( strequal(lp_workgroup(), domain) || strequal(lp_realm(), realm) )
                our_domain = True;
        
-       /* always try to obey what the admin specified in smb.conf.
-          If it is not our domain, assume that domain names with periods 
-          in them are realm names */
+       /* always try to obey what the admin specified in smb.conf 
+          (for the local domain) */
        
-       if ( (our_domain && lp_security()==SEC_ADS) || strchr_m(domain, '.') ) {
-               ret = ads_dc_name(domain, &dc_ip, srv_name);
+       if ( (our_domain && lp_security()==SEC_ADS) || realm ) {
+               ret = ads_dc_name(domain, realm, &dc_ip, srv_name);
        }
        
        if (!ret) {
index 7c1000b9a59c051735d775aab325b1c57fbb84b7..b420e4fa08168b77d4586ea65baa1817659c1787 100644 (file)
@@ -144,7 +144,7 @@ BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
 
        /* lookup a DC first */
 
-       if ( !get_dc_name(domain, dc_name, &dc_ip) ) {
+       if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
                DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n",
                        domain));
                return False;
index 3a70c1a01e2b182aeeb62a044d32bf9b405a562d..5e12b0fbb531ae46c59bea23bd622ffb2fef64f3 100644 (file)
@@ -842,7 +842,6 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        struct cli_state        *cli = NULL;
                                /* i think we only need our forest and downlevel trusted domains */
        uint32                  flags = DS_DOMAIN_IN_FOREST | DS_DOMAIN_DIRECT_OUTBOUND;
-       char                    *contact_domain_name;
 
        DEBUG(3,("ads: trusted_domains\n"));
 
@@ -851,8 +850,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        *names       = NULL;
        *dom_sids    = NULL;
                
-       contact_domain_name = *domain->alt_name ? domain->alt_name : domain->name;
-       if ( !NT_STATUS_IS_OK(result = cm_fresh_connection(contact_domain_name, PI_NETLOGON, &cli)) ) {
+       if ( !NT_STATUS_IS_OK(result = cm_fresh_connection(domain, PI_NETLOGON, &cli)) ) {
                DEBUG(5, ("trusted_domains: Could not open a connection to %s for PIPE_NETLOGON (%s)\n", 
                          domain->name, nt_errstr(result)));
                return NT_STATUS_UNSUCCESSFUL;
index 73c8a6b783491a594989e3d584ee68722a4cdb71..bdbf80eb2f062ea9e35662785934c29b14b3d78c 100644 (file)
@@ -113,8 +113,8 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password)
 
 /* Open a connction to the remote server, cache failures for 30 seconds */
 
-static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
-                              struct winbindd_cm_conn *new_conn)
+static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const int pipe_index,
+                                  struct winbindd_cm_conn *new_conn)
 {
        NTSTATUS result;
        char *machine_password; 
@@ -125,21 +125,22 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
 
        ZERO_STRUCT(dc_ip);
 
-       fstrcpy(new_conn->domain, domain);
-       fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
+       fstrcpy(new_conn->domain, domain->name);
        
        /* connection failure cache has been moved inside of get_dc_name
           so we can deal with half dead DC's   --jerry */
 
-       if (!get_dc_name(domain, new_conn->controller, &dc_ip)) {
+       if (!get_dc_name(domain->name, domain->alt_name[0] ? domain->alt_name : NULL, 
+                        new_conn->controller, &dc_ip)) {
                result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
-               add_failed_connection_entry(domain, "", result);
+               add_failed_connection_entry(domain->name, "", result);
                return result;
        }
                
        /* Initialise SMB connection */
+       fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index));
 
-       /* grab stored passwords */
+/* grab stored passwords */
        machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL);
        
        if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), lp_realm()) == -1) {
@@ -181,7 +182,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
 
                                if (!NT_STATUS_IS_OK(result = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, 
                                                              machine_password, 
-                                                             domain))) {
+                                                             domain->name))) {
                                        DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result)));
                                }
                        }
@@ -201,7 +202,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
                                if (!cli_session_setup(new_conn->cli, ipc_username, 
                                                       ipc_password, strlen(ipc_password)+1, 
                                                       ipc_password, strlen(ipc_password)+1, 
-                                                      domain)) {
+                                                      domain->name)) {
                                        result = cli_nt_error(new_conn->cli);
                                        DEBUG(4,("failed authenticated session setup with %s\n", nt_errstr(result)));
                                        if (NT_STATUS_IS_OK(result)) 
@@ -258,13 +259,13 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
        SAFE_FREE(machine_password);
 
        if (!NT_STATUS_IS_OK(result)) {
-               add_failed_connection_entry(domain, new_conn->controller, result);
+               add_failed_connection_entry(domain->name, new_conn->controller, result);
                return result;
        }
        
        /* set the domain if empty; needed for schannel connections */
        if ( !*new_conn->cli->domain )
-               fstrcpy( new_conn->cli->domain, domain );
+               fstrcpy( new_conn->cli->domain, domain->name );
                
        
        if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) {
@@ -278,7 +279,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
                 * specific UUID right now, i'm not going to bother.  --jerry
                 */
                if ( !is_win2k_pipe(pipe_index) )
-                       add_failed_connection_entry(domain, new_conn->controller, result);
+                       add_failed_connection_entry(domain->name, new_conn->controller, result);
                cli_shutdown(new_conn->cli);
                return result;
        }
@@ -291,7 +292,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
  setup cli_state struct
 ************************************************************************/
 
-NTSTATUS cm_fresh_connection(const char *domain, const int pipe_index,
+NTSTATUS cm_fresh_connection(struct winbindd_domain *domain, const int pipe_index,
                               struct cli_state **cli)
 {
        NTSTATUS result;
@@ -338,13 +339,13 @@ static BOOL connection_ok(struct winbindd_cm_conn *conn)
 /* Search the cache for a connection. If there is a broken one,
    shut it down properly and return NULL. */
 
-static void find_cm_connection(const char *domain, const char *pipe_name,
+static void find_cm_connection(struct winbindd_domain *domain, const char *pipe_name,
                               struct winbindd_cm_conn **conn_out) 
 {
        struct winbindd_cm_conn *conn;
 
        for (conn = cm_conns; conn; ) {
-               if (strequal(conn->domain, domain) && 
+               if (strequal(conn->domain, domain->name) && 
                    strequal(conn->pipe_name, pipe_name)) {
                        if (!connection_ok(conn)) {
                                /* Dead connection - remove it. */
@@ -367,7 +368,7 @@ static void find_cm_connection(const char *domain, const char *pipe_name,
 
 /* Initialize a new connection up to the RPC BIND. */
 
-static NTSTATUS new_cm_connection(const char *domain, const char *pipe_name,
+static NTSTATUS new_cm_connection(struct winbindd_domain *domain, const char *pipe_name,
                                  struct winbindd_cm_conn **conn_out)
 {
        struct winbindd_cm_conn *conn;
@@ -380,7 +381,7 @@ static NTSTATUS new_cm_connection(const char *domain, const char *pipe_name,
                
        if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) {
                DEBUG(3, ("Could not open a connection to %s for %s (%s)\n", 
-                         domain, pipe_name, nt_errstr(result)));
+                         domain->name, pipe_name, nt_errstr(result)));
                SAFE_FREE(conn);
                return result;
        }
@@ -392,7 +393,7 @@ static NTSTATUS new_cm_connection(const char *domain, const char *pipe_name,
 
 /* Get a connection to the remote DC and open the pipe.  If there is already a connection, use that */
 
-static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name,
+static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, const char *pipe_name,
                                          struct winbindd_cm_conn **conn_out)
 {
        find_cm_connection(domain, pipe_name, conn_out);
@@ -406,7 +407,7 @@ static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_n
 /**********************************************************************************
 **********************************************************************************/
 
-BOOL cm_check_for_native_mode_win2k( const char *domain )
+BOOL cm_check_for_native_mode_win2k( struct winbindd_domain *domain )
 {
        NTSTATUS                result;
        struct winbindd_cm_conn conn;
@@ -419,7 +420,7 @@ BOOL cm_check_for_native_mode_win2k( const char *domain )
        
        if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
                DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n", 
-                         domain, nt_errstr(result)));
+                         domain->name, nt_errstr(result)));
                return False;
        }
        
@@ -450,7 +451,7 @@ done:
 
 /* Return a LSA policy handle on a domain */
 
-NTSTATUS cm_get_lsa_handle(const char *domain, CLI_POLICY_HND **return_hnd)
+NTSTATUS cm_get_lsa_handle(struct winbindd_domain *domain, CLI_POLICY_HND **return_hnd)
 {
        struct winbindd_cm_conn *conn;
        uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
@@ -503,7 +504,7 @@ NTSTATUS cm_get_lsa_handle(const char *domain, CLI_POLICY_HND **return_hnd)
 
 /* Return a SAM policy handle on a domain */
 
-NTSTATUS cm_get_sam_handle(char *domain, CLI_POLICY_HND **return_hnd)
+NTSTATUS cm_get_sam_handle(struct winbindd_domain *domain, CLI_POLICY_HND **return_hnd)
 { 
        struct winbindd_cm_conn *conn;
        uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
@@ -561,7 +562,7 @@ NTSTATUS cm_get_sam_handle(char *domain, CLI_POLICY_HND **return_hnd)
 /* Get a handle on a netlogon pipe.  This is a bit of a hack to re-use the
    netlogon pipe as no handle is returned. */
 
-NTSTATUS cm_get_netlogon_cli(const char *domain, 
+NTSTATUS cm_get_netlogon_cli(struct winbindd_domain *domain, 
                             const unsigned char *trust_passwd, 
                             uint32 sec_channel_type,
                             BOOL fresh,
@@ -571,7 +572,6 @@ NTSTATUS cm_get_netlogon_cli(const char *domain,
        struct winbindd_cm_conn *conn;
        fstring lock_name;
        BOOL got_mutex;
-       struct winbindd_domain *wb_domain = NULL;
 
        if (!cli)
                return NT_STATUS_INVALID_PARAMETER;
@@ -613,16 +613,9 @@ NTSTATUS cm_get_netlogon_cli(const char *domain,
        if ( sec_channel_type == SEC_CHAN_DOMAIN )
                fstr_sprintf(conn->cli->mach_acct, "%s$", lp_workgroup());
                        
-       /* we need the short form of the domain name for the schanel
-          rpc bind.  What if we fail?  I don't think we should ever get 
-          a request for a domain name not in our list but I'm not bailing 
-          out if we do since I'm not 10% certain about this   --jerry */
-          
-       if ( (wb_domain = find_domain_from_name( domain )) != NULL ) {
-               DEBUG(5,("cm_get_netlogon_cli: Using short for of domain name [%s] for netlogon rpc bind\n",
-                       wb_domain->name));
-               fstrcpy( conn->cli->domain, wb_domain->name);
-       }
+               
+       fstrcpy( conn->cli->domain, domain->name);
+       
        
        result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd);
        
index 63bda0d1df9fe6ecc974fb4ff4b1ea691c60d796..08b5be827d1faea93a486faf3ec98799573c07de 100644 (file)
@@ -37,7 +37,8 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
         struct cli_state *cli;
        uint32 sec_channel_type;
        const char *contact_domain_name = NULL;
-       
+       struct winbindd_domain *contact_domain;
+
        DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
 
        /* Get trust account password */
@@ -57,12 +58,19 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
        
        if ( !contact_domain_name || !*contact_domain_name )
                contact_domain_name = lp_workgroup();
-               
+       
+       contact_domain = find_domain_from_name(contact_domain_name);
+        if (!contact_domain) {
+               result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+                DEBUG(1, ("%s is not a trusted domain\n", contact_domain_name));
+                goto done;
+        }
+       
         /* This call does a cli_nt_setup_creds() which implicitly checks
            the trust account password. */
        /* Don't shut this down - it belongs to the connection cache code */
        
-        result = cm_get_netlogon_cli(contact_domain_name,
+        result = cm_get_netlogon_cli(contact_domain,
                trust_passwd, sec_channel_type, True, &cli);
 
         if (!NT_STATUS_IS_OK(result)) {
index 54513b1bc1e72398a2f705a6a83ca3a1ff38c6b9..196ceea9a06db86572401c616d070a771a79ebeb 100644 (file)
@@ -75,7 +75,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
        int attempts = 0;
        unsigned char local_lm_response[24];
        unsigned char local_nt_response[24];
-       const char *contact_domain;
+       struct winbindd_domain *contact_domain;
        BOOL retry;
 
        /* Ensure null termination */
@@ -107,21 +107,15 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
        lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response));
        nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response));
        
-       if ( !get_trust_pw(name_domain, trust_passwd, &last_change_time, &sec_channel_type) ) {
-               result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-               goto done;
-       }
-
        /* what domain should we contact? */
        
        if ( IS_DC ) {
-               if (!find_domain_from_name(name_domain)) {
-                       DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n", 
+               if (!(contact_domain = find_domain_from_name(name_domain))) {
+                       DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", 
                                  state->request.data.auth.user, name_domain, name_user, name_domain)); 
                        result = NT_STATUS_NO_SUCH_USER;
                        goto done;
                }
-               contact_domain = name_domain;
                
        } else {
                if (is_myname(name_domain)) {
@@ -129,8 +123,20 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
                        result =  NT_STATUS_NO_SUCH_USER;
                        goto done;
                }
-               contact_domain = lp_workgroup();
+
+               if (!(contact_domain = find_our_domain())) {
+                       DEBUG(1, ("Authenticatoin for [%s] -> [%s]\\[%s] in our domain failed - we can't find our domain!\n", 
+                                 state->request.data.auth.user, name_domain, name_user)); 
+                       result = NT_STATUS_NO_SUCH_USER;
+                       goto done;
+               }
+       }
+
+       if ( !get_trust_pw(contact_domain->name, trust_passwd, &last_change_time, &sec_channel_type) ) {
+               result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               goto done;
        }
+
        /* check authentication loop */
 
        do {
@@ -194,7 +200,10 @@ done:
        
        state->response.data.auth.nt_status = NT_STATUS_V(result);
        fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
-       fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
+
+       /* we might have given a more useful error above */
+       if (!*state->response.data.auth.error_string) 
+               fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
        state->response.data.auth.pam_error = nt_status_to_pam(result);
 
        DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", 
@@ -221,10 +230,10 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
         NET_USER_INFO_3 info3;
         struct cli_state *cli = NULL;
        TALLOC_CTX *mem_ctx = NULL;
-       char *user = NULL;
-       const char *domain = NULL;
+       char *name_user = NULL;
+       const char *name_domain = NULL;
        const char *workstation;
-       const char *contact_domain;
+       struct winbindd_domain *contact_domain;
        DOM_CRED ret_creds;
        int attempts = 0;
        BOOL retry;
@@ -255,7 +264,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
                goto done;
        }
 
-        if (pull_utf8_talloc(mem_ctx, &user, state->request.data.auth_crap.user) == (size_t)-1) {
+        if (pull_utf8_talloc(mem_ctx, &name_user, state->request.data.auth_crap.user) == (size_t)-1) {
                DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n"));
                result = NT_STATUS_UNSUCCESSFUL;
                goto done;
@@ -268,24 +277,19 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
                        result = NT_STATUS_UNSUCCESSFUL;
                        goto done;
                }
-               domain = dom;
+               name_domain = dom;
        } else if (lp_winbind_use_default_domain()) {
-               domain = lp_workgroup();
+               name_domain = lp_workgroup();
        } else {
                DEBUG(5,("no domain specified with username (%s) - failing auth\n", 
-                        user));
-               result = NT_STATUS_INVALID_PARAMETER;
+                        name_user));
+               result = NT_STATUS_NO_SUCH_USER;
                goto done;
        }
 
        DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid,
-                 domain, user));
+                 name_domain, name_user));
           
-       if ( !get_trust_pw(domain, trust_passwd, &last_change_time, &sec_channel_type) ) {
-               result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-               goto done;
-       }
-
        if (*state->request.data.auth_crap.workstation) {
                char *wrk = NULL;
                if (pull_utf8_talloc(mem_ctx, &wrk, state->request.data.auth_crap.workstation) == (size_t)-1) {
@@ -310,25 +314,39 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
        lm_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len);
        nt_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len);
        
+       /* what domain should we contact? */
+       
+
        /* what domain should we contact? */
        
        if ( IS_DC ) {
-               if (!find_domain_from_name(domain)) {
-                       DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n", 
-                                 state->request.data.auth.user, domain, user, domain)); 
+               if (!(contact_domain = find_domain_from_name(name_domain))) {
+                       DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", 
+                                 state->request.data.auth.user, name_domain, name_user, name_domain)); 
                        result = NT_STATUS_NO_SUCH_USER;
                        goto done;
                }
-               contact_domain = domain;
+               
        } else {
-               if (is_myname(domain)) {
-                       DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", domain));
+               if (is_myname(name_domain)) {
+                       DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
                        result =  NT_STATUS_NO_SUCH_USER;
                        goto done;
                }
-               contact_domain = lp_workgroup();
+
+               if (!(contact_domain = find_our_domain())) {
+                       DEBUG(1, ("Authenticatoin for [%s] -> [%s]\\[%s] in our domain failed - we can't find our domain!\n", 
+                                 state->request.data.auth.user, name_domain, name_user)); 
+                       result = NT_STATUS_NO_SUCH_USER;
+                       goto done;
+               }
        }
                
+       if ( !get_trust_pw(contact_domain->name, trust_passwd, &last_change_time, &sec_channel_type) ) {
+               result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               goto done;
+       }
+
        do {
                ZERO_STRUCT(info3);
                ZERO_STRUCT(ret_creds);
@@ -345,7 +363,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
 
                result = cli_netlogon_sam_network_logon(cli, mem_ctx,
                                                        &ret_creds,
-                                                       user, domain,
+                                                       name_user, name_domain,
                                                        workstation,
                                                        state->request.data.auth_crap.chal, 
                                                        lm_resp, nt_resp, 
@@ -369,7 +387,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
                if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) {
                        DEBUG(3,("winbindd_pam_auth_crap: sam_logon returned ACCESS_DENIED.  Maybe the trust account "
                                "password was changed and we didn't know it.  Killing connections to domain %s\n",
-                               domain));
+                               contact_domain->name));
                        winbindd_cm_flush();
                        retry = True;
                        cli = NULL;
@@ -381,7 +399,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
         
        if (NT_STATUS_IS_OK(result)) {
                netsamlogon_cache_store( cli->mem_ctx, &info3 );
-               wcache_invalidate_samlogon(find_domain_from_name(domain), &info3);
+               wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);
                
                if (state->request.flags & WBFLAG_PAM_INFO3_NDR) {
                        result = append_info3_as_ndr(mem_ctx, state, &info3);
@@ -393,12 +411,12 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
                        const char *nt_username, *nt_domain;
                        if (!(nt_username = unistr2_tdup(mem_ctx, &(info3.uni_user_name)))) {
                                /* If the server didn't give us one, just use the one we sent them */
-                               nt_username = user;
+                               nt_username = name_user;
                        }
                        
                        if (!(nt_domain = unistr2_tdup(mem_ctx, &(info3.uni_logon_dom)))) {
                                /* If the server didn't give us one, just use the one we sent them */
-                               nt_domain = domain;
+                               nt_domain = name_domain;
                        }
 
                        fill_domain_username(username_out, nt_domain, nt_username);
@@ -437,8 +455,8 @@ done:
 
        DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, 
              ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", 
-              domain,
-              user,
+              name_domain,
+              name_user,
               state->response.data.auth.nt_status_string,
               state->response.data.auth.pam_error));         
 
@@ -456,10 +474,19 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
        char *oldpass, *newpass;
        fstring domain, user;
        CLI_POLICY_HND *hnd;
+       TALLOC_CTX *mem_ctx;
+       struct winbindd_domain *contact_domain;
 
        DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid,
                state->request.data.chauthtok.user));
 
+       if (!(mem_ctx = talloc_init("winbind password change for (utf8) %s", 
+                                   state->request.data.chauthtok.user))) {
+               DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n"));
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
        /* Setup crap */
 
        if (state == NULL)
@@ -467,7 +494,7 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
 
        parse_domain_user(state->request.data.chauthtok.user, domain, user);
 
-       if (!find_domain_from_name(domain)) {
+       if (!(contact_domain = find_domain_from_name(domain))) {
                DEBUG(3, ("Cannot change password for [%s] -> [%s]\\[%s] as %s is not a trusted domain\n", 
                          state->request.data.chauthtok.user, domain, user, domain)); 
                result = NT_STATUS_NO_SUCH_USER;
@@ -481,17 +508,15 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
 
        /* Get sam handle */
 
-       if ( NT_STATUS_IS_ERR(result = cm_get_sam_handle(domain, &hnd)) ) {
+       if ( NT_STATUS_IS_ERR(result = cm_get_sam_handle(contact_domain, &hnd)) ) {
                DEBUG(1, ("could not get SAM handle on DC for %s\n", domain));
                goto done;
        }
 
-       if (!cli_oem_change_password(hnd->cli, user, newpass, oldpass)) {
+       if (!NT_STATUS_IS_OK(result = cli_samr_chgpasswd_user(hnd->cli, mem_ctx, 
+                                                             user, newpass, oldpass))) {
                DEBUG(1, ("password change failed for user %s/%s\n", domain, 
                          user));
-               result = NT_STATUS_WRONG_PASSWORD;
-       } else {
-               result = NT_STATUS_OK;
        }
 
 done:    
@@ -507,5 +532,8 @@ done:
               state->response.data.auth.nt_status_string,
               state->response.data.auth.pam_error));         
 
+       if (mem_ctx)
+               talloc_destroy(mem_ctx);
+
        return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
 }
index 813621f3f7f17994b62cca23cfc3ade2c60f2e00..f619aa3564aa0d7faa4a632afcbc6f05253788b1 100644 (file)
@@ -53,7 +53,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
        do {
                /* Get sam handle */
 
-               if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)) )
+               if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
                        return result;
 
                /* Get domain handle */
@@ -163,7 +163,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
 
        retry = 0;
        do {
-               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
+               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
                        return result;
 
                status = cli_samr_open_domain(hnd->cli, mem_ctx,
@@ -228,7 +228,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
 
        retry = 0;
        do {
-               if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)) )
+               if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) )
                        return result;
 
                result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol, 
@@ -300,7 +300,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
 
        retry = 0;
        do {
-               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd))) {
+               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd))) {
                        return result;
                }
         
@@ -340,7 +340,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
 
        retry = 0;
        do {
-               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd)))
+               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
                        return result;
         
                result = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol,
@@ -409,7 +409,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
        do {
                /* Get sam handle; if we fail here there is no hope */
                
-               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd))) 
+               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) 
                        goto done;
                        
                /* Get domain handle */
@@ -510,7 +510,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
        do {
                /* Get sam handle; if we fail here there is no hope */
                
-               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))           
+               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))                 
                        goto done;
 
                /* Get domain handle */
@@ -598,7 +598,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
        retry = 0;
        do {
                /* Get sam handle */
-               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
+               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
                        goto done;
 
                /* Get domain handle */
@@ -876,7 +876,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
                }
 #endif /* HAVE_LDAP */
                /* Get sam handle */
-               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)))
+               if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)))
                        goto done;
 
                /* Get domain handle */
@@ -932,7 +932,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
 
        retry = 0;
        do {
-               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(lp_workgroup(), &hnd)))
+               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(find_our_domain(), &hnd)))
                        goto done;
 
                result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx,
@@ -961,7 +961,7 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
        retry = 0;
        do {
                /* Get lsa handle */
-               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd)))
+               if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain, &hnd)))
                        goto done;
 
                result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
index 1f9537ac25522bfce32419805c99f7c187844269..22192e458275ba5679c0e4fd827fb8c84f408744 100644 (file)
@@ -82,7 +82,6 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
                                                  DOM_SID *sid)
 {
        struct winbindd_domain *domain;
-       char *contact_name;
        const char *alternative_name = NULL;
        
        /* ignore alt_name if we are not in an AD domain */
@@ -135,12 +134,11 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
                sid_copy(&domain->sid, sid);
        }
        
-       /* see if this is a native mode win2k domain (use realm name if possible) */
+       /* see if this is a native mode win2k domain */
           
-       contact_name = *domain->alt_name ? domain->alt_name : domain->name;
-       domain->native_mode = cm_check_for_native_mode_win2k( contact_name );
+       domain->native_mode = cm_check_for_native_mode_win2k( domain );
        
-       DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", contact_name,
+       DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain->name,
                domain->native_mode ? "native" : "mixed (or NT4)" ));
 
        /* Link to domain list */
@@ -298,7 +296,7 @@ BOOL init_domain_list(void)
  *
  * @note Do *not* pass lp_workgroup() to this function.  domain_list
  *       may modify it's value, and free that pointer.  Instead, our local
- *       domain may be found by looking at the first entry in domain_list()
+ *       domain may be found by calling find_our_domain().
  *       directly.
  *
  *