sync 3.0 into HEAD for the last time
[vlendec/samba-autobuild/.git] / source3 / nsswitch / winbindd_cm.c
index f07117b5ab8680b9a38ce7d044f0d564f569aafc..8513a46f8f2ebb2514a43f7181c98440c2e55193 100644 (file)
@@ -116,7 +116,8 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
                               struct winbindd_cm_conn *new_conn)
 {
        NTSTATUS result;
-       char *ipc_username, *ipc_domain, *ipc_password;
+       char *machine_password; 
+       char *machine_krb5_principal, *ipc_username, *ipc_domain, *ipc_password;
        struct in_addr dc_ip;
        int i;
        BOOL retry = True;
@@ -137,10 +138,15 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
                
        /* Initialise SMB connection */
 
-       cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
+       /* 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) {
+               SAFE_FREE(machine_password);
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n", 
-             new_conn->controller, global_myname(), ipc_domain, ipc_username));
+       cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
 
        for (i = 0; retry && (i < 3); i++) {
                BOOL got_mutex;
@@ -150,12 +156,99 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
                        continue;
                }
                
-               result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller, 
-                                            &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, 
-                                            ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, 
-                                            Undefined, &retry);
-               
-               secrets_named_mutex_release(new_conn->controller);
+               new_conn->cli = NULL;
+               result = cli_start_connection(&new_conn->cli, global_myname(), 
+                                             new_conn->controller, 
+                                             &dc_ip, 0, Undefined, 
+                                             CLI_FULL_CONNECTION_USE_KERBEROS, 
+                                             &retry);
+
+               if (NT_STATUS_IS_OK(result)) {
+
+                       /* reset the error code */
+                       result = NT_STATUS_UNSUCCESSFUL; 
+
+                       /* Krb5 session */
+                       
+                       if ((lp_security() == SEC_ADS) 
+                               && (new_conn->cli->protocol >= PROTOCOL_NT1 && new_conn->cli->capabilities & CAP_EXTENDED_SECURITY)) {
+                               new_conn->cli->use_kerberos = True;
+                               DEBUG(5, ("connecting to %s from %s with kerberos principal [%s]\n", 
+                                         new_conn->controller, global_myname(), machine_krb5_principal));
+
+                               result = NT_STATUS_OK;
+
+                               if (!cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, 
+                                                             machine_password, 
+                                                             domain)) {
+                                       result = cli_nt_error(new_conn->cli);
+                                       DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result)));
+                                       if (NT_STATUS_IS_OK(result)) 
+                                               result = NT_STATUS_UNSUCCESSFUL;
+                               }
+                       }
+                       new_conn->cli->use_kerberos = False;
+                       
+                       /* only do this is we have a username/password for thr IPC$ connection */
+                       
+                       if ( !NT_STATUS_IS_OK(result) 
+                               && new_conn->cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE
+                               && strlen(ipc_username) )
+                       {       
+                               DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n", 
+                                         new_conn->controller, global_myname(), ipc_domain, ipc_username));
+
+                               result = NT_STATUS_OK;
+
+                               if (!cli_session_setup(new_conn->cli, ipc_username, 
+                                                      ipc_password, strlen(ipc_password)+1, 
+                                                      ipc_password, strlen(ipc_password)+1, 
+                                                      domain)) {
+                                       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)) 
+                                               result = NT_STATUS_UNSUCCESSFUL;
+                               }
+                       }
+                       
+                       /* anonymous is all that is left if we get to here */
+                       
+                       if (!NT_STATUS_IS_OK(result)) { 
+                       
+                               DEBUG(5, ("anonymous connection attempt to %s from %s\n", 
+                                         new_conn->controller, global_myname()));
+                                         
+                               result = NT_STATUS_OK;
+
+                               if (!cli_session_setup(new_conn->cli, "", NULL, 0, NULL, 0, "")) 
+                               {
+                                       result = cli_nt_error(new_conn->cli);
+                                       DEBUG(4,("failed anonymous session setup with %s\n", nt_errstr(result)));
+                                       if (NT_STATUS_IS_OK(result)) 
+                                               result = NT_STATUS_UNSUCCESSFUL;
+                               } 
+                               
+                       }
+
+                       if (NT_STATUS_IS_OK(result) && !cli_send_tconX(new_conn->cli, "IPC$", "IPC",
+                                                                      "", 0)) {
+                               result = cli_nt_error(new_conn->cli);
+                               DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result)));
+                               cli_shutdown(new_conn->cli);
+                               if (NT_STATUS_IS_OK(result)) {
+                                       result = NT_STATUS_UNSUCCESSFUL;
+                               }
+                       }
+               }
+
+               if (NT_STATUS_IS_OK(result)) {
+                       struct ntuser_creds creds;
+                       init_creds(&creds, ipc_username, ipc_domain, ipc_password);
+                       cli_init_creds(new_conn->cli, &creds);
+               }
+
+               if (got_mutex)
+                       secrets_named_mutex_release(new_conn->controller);
 
                if (NT_STATUS_IS_OK(result))
                        break;
@@ -164,6 +257,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index,
        SAFE_FREE(ipc_username);
        SAFE_FREE(ipc_domain);
        SAFE_FREE(ipc_password);
+       SAFE_FREE(machine_password);
 
        if (!NT_STATUS_IS_OK(result)) {
                add_failed_connection_entry(domain, new_conn->controller, result);
@@ -479,6 +573,7 @@ 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;
@@ -520,6 +615,17 @@ 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);
+       }
+       
        result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd);
        
        if (got_mutex)