loadparm.c: Added machine password timeout parameter - set to 7 days be default.
authorJeremy Allison <jra@samba.org>
Wed, 27 May 1998 00:30:52 +0000 (00:30 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 27 May 1998 00:30:52 +0000 (00:30 +0000)
password.c: Added code to tell server.c when machine password needs changing.
server.c: Change machine password in idle cycles if it needs it.
smbpassfile.c: Fixed up length calculations for machine password file.
smbpasswd.c: Moved domain joining code/machine password changing code.
lib/rpc/client/cli_netlogon.c: And this is where it now lives.
Jeremy.
(This used to be commit b8fedca6191de96159df0d1d17082d82e8e44773)

source3/include/proto.h
source3/param/loadparm.c
source3/passdb/passdb.c
source3/passdb/smbpassfile.c
source3/rpc_client/cli_netlogon.c
source3/smbd/password.c
source3/smbd/server.c
source3/utils/smbpasswd.c

index 48cda0456160b807110836412583db6e1f77bba4..3086c6cd242e55969bb90219d428b7ba65d8adfc 100644 (file)
@@ -250,6 +250,7 @@ BOOL cli_net_srv_pwset(struct cli_state *cli, uint8 hashed_mach_pwd[16]);
 BOOL cli_net_sam_logon(struct cli_state *cli, NET_ID_INFO_CTR *ctr, 
                        NET_USER_INFO_3 *user_info3);
 BOOL cli_net_sam_logoff(struct cli_state *cli, NET_ID_INFO_CTR *ctr);
+BOOL change_trust_account_password( char *domain, char *remote_machine_list);
 
 /*The following definitions come from  lib/rpc/client/cli_pipe.c  */
 
@@ -1017,6 +1018,7 @@ int lp_client_code_page(void);
 int lp_announce_as(void);
 int lp_lm_announce(void);
 int lp_lm_interval(void);
+int lp_machine_password_timeout(void);
 int lp_ldap_port(void);
 char *lp_preexec(int );
 char *lp_postexec(int );
index b17ca83d4d3ab22ff080b694b7cc2d24755da41d..83aa2666a7188ce941a0502c9b59af52d712caa5 100644 (file)
@@ -172,6 +172,7 @@ typedef struct
   int shmem_size;
   int client_code_page;
   int announce_as;   /* This is initialised in init_globals */
+  int machine_password_timeout;
 #ifdef USE_LDAP
   int ldap_port;
 #endif /* USE_LDAP */
@@ -591,6 +592,7 @@ static struct parm_struct parm_table[] =
   {"domain allow hosts",P_STRING, P_GLOBAL, &Globals.szDomainHostsallow, NULL,   NULL,  0},
   {"domain hosts deny", P_STRING, P_GLOBAL, &Globals.szDomainHostsdeny,  NULL,   NULL,  0},
   {"domain deny hosts", P_STRING, P_GLOBAL, &Globals.szDomainHostsdeny,  NULL,   NULL,  0},
+  {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout,  NULL,   NULL,  0},
 
   {"Logon Options", P_SEP, P_SEPARATOR},
   {"logon script",     P_STRING,  P_GLOBAL, &Globals.szLogonScript,     NULL,   NULL,  0},
@@ -758,6 +760,7 @@ static void init_globals(void)
   Globals.max_ttl = 60*60*24*3; /* 3 days default */
   Globals.max_wins_ttl = 60*60*24*6; /* 6 days default */
   Globals.min_wins_ttl = 60*60*6; /* 6 hours default */
+  Globals.machine_password_timeout = 60*60*24*7; /* 7 days default */
   Globals.ReadSize = 16*1024;
   Globals.lm_announce = 2;   /* = Auto: send only if LM clients found */
   Globals.lm_interval = 60;
@@ -1050,6 +1053,7 @@ FN_GLOBAL_INTEGER(lp_client_code_page,&Globals.client_code_page)
 FN_GLOBAL_INTEGER(lp_announce_as,&Globals.announce_as)
 FN_GLOBAL_INTEGER(lp_lm_announce,&Globals.lm_announce)
 FN_GLOBAL_INTEGER(lp_lm_interval,&Globals.lm_interval)
+FN_GLOBAL_INTEGER(lp_machine_password_timeout,&Globals.machine_password_timeout)
 
 #ifdef USE_LDAP
 FN_GLOBAL_INTEGER(lp_ldap_port,&Globals.ldap_port)
index fa4a39e836fe8dde356802f03502f407768ed88a..5bb20fce982709f0f0029252808811168341efca 100644 (file)
@@ -1101,4 +1101,3 @@ BOOL pdb_rid_is_user(uint32 rid)
    */
   return True;
 }
-
index c9d030f5290904ea8a3a45817fd5aaea15154afe..3988fd1c78495ed7ccbb9a285c744608cfa6d307 100644 (file)
@@ -27,6 +27,7 @@ int pw_file_lock_depth = 0;
 /***************************************************************
  Signal function to tell us we timed out.
 ****************************************************************/
+
 static void gotalarm_sig(void)
 {
   gotalarm = 1;
@@ -36,6 +37,7 @@ static void gotalarm_sig(void)
  Lock or unlock a fd for a known lock type. Abandon after waitsecs 
  seconds.
 ****************************************************************/
+
 BOOL do_file_lock(int fd, int waitsecs, int type)
 {
   struct flock    lock;
@@ -68,6 +70,7 @@ BOOL do_file_lock(int fd, int waitsecs, int type)
 /***************************************************************
  Lock an fd. Abandon after waitsecs seconds.
 ****************************************************************/
+
 BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
 {
   if (fd < 0)
@@ -89,6 +92,7 @@ BOOL pw_file_lock(int fd, int type, int secs, int *plock_depth)
 /***************************************************************
  Unlock an fd. Abandon after waitsecs seconds.
 ****************************************************************/
+
 BOOL pw_file_unlock(int fd, int *plock_depth)
 {
   BOOL ret=True;
@@ -110,6 +114,7 @@ static FILE *mach_passwd_fp;
 /************************************************************************
  Routine to get the name for a trust account file.
 ************************************************************************/
+
 static void get_trust_account_file_name( char *domain, char *name, char *mac_file)
 {
   unsigned int mac_file_len;
@@ -138,6 +143,7 @@ static void get_trust_account_file_name( char *domain, char *name, char *mac_fil
 /************************************************************************
  Routine to lock the trust account password file for a domain.
 ************************************************************************/
+
 BOOL trust_password_lock( char *domain, char *name, BOOL update)
 {
   pstring mac_file;
@@ -176,6 +182,7 @@ BOOL trust_password_lock( char *domain, char *name, BOOL update)
 /************************************************************************
  Routine to unlock the trust account password file for a domain.
 ************************************************************************/
+
 BOOL trust_password_unlock(void)
 {
   BOOL ret = pw_file_unlock(fileno(mach_passwd_fp), &mach_passwd_lock_depth);
@@ -187,6 +194,7 @@ BOOL trust_password_unlock(void)
 /************************************************************************
  Routine to delete the trust account password file for a domain.
 ************************************************************************/
+
 BOOL trust_password_delete( char *domain, char *name )
 {
   pstring mac_file;
@@ -199,6 +207,7 @@ BOOL trust_password_delete( char *domain, char *name )
  Routine to get the trust account password for a domain.
  The user of this function must have locked the trust password file.
 ************************************************************************/
+
 BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_time)
 {
   char linebuf[256];
@@ -223,13 +232,17 @@ BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_t
     return False;
   }
 
+  if(linebuf[strlen(linebuf)-1] == '\n')
+    linebuf[strlen(linebuf)-1] = '\0';
+
   /*
    * The length of the line read
    * must be 45 bytes ( <---XXXX 32 bytes-->:TLC-12345678
    */
 
   if(strlen(linebuf) != 45) {
-    DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length).\n"));
+    DEBUG(0,("get_trust_account_password: Malformed trust password file (wrong length \
+- was %d, should be 45).\n", strlen(linebuf)));
 #ifdef DEBUG_PASSWORD
     DEBUG(100,("get_trust_account_password: line = |%s|\n", linebuf));
 #endif
@@ -279,6 +292,7 @@ BOOL get_trust_account_password( unsigned char *ret_pwd, time_t *pass_last_set_t
  Routine to get the trust account password for a domain.
  The user of this function must have locked the trust password file.
 ************************************************************************/
+
 BOOL set_trust_account_password( unsigned char *md4_new_pwd)
 {
   char linebuf[64];
@@ -295,7 +309,7 @@ BOOL set_trust_account_password( unsigned char *md4_new_pwd)
 
   slprintf(&linebuf[32], 32, ":TLC-%08X\n", (unsigned)time(NULL));
 
-  if(fwrite( linebuf, 1, 45, mach_passwd_fp)!= 45) {
+  if(fwrite( linebuf, 1, 46, mach_passwd_fp)!= 46) {
     DEBUG(0,("set_trust_account_password: Failed to write file. Warning - the trust \
 account is now invalid. Please recreate. Error was %s.\n", strerror(errno) ));
     return False;
@@ -304,4 +318,3 @@ account is now invalid. Please recreate. Error was %s.\n", strerror(errno) ));
   fflush(mach_passwd_fp);
   return True;
 }
-
index 6f96f392fbb607d9abc5249f5b9e4b8feffdc338..7d79d88c46ef2c5da1164f0a6d89ad6121bcd67a 100644 (file)
@@ -463,3 +463,168 @@ password ?).\n", cli->desthost ));
 
   return ok;
 }
+
+/*********************************************************
+ Change the domain password on the PDC.
+**********************************************************/
+
+static BOOL modify_trust_password( char *domain, char *remote_machine, 
+                          unsigned char orig_trust_passwd_hash[16],
+                          unsigned char new_trust_passwd_hash[16])
+{
+  struct in_addr dest_ip;
+  struct cli_state cli;
+
+  memset(&cli, '\0', sizeof(struct cli_state));
+  if(cli_initialise(&cli) == False) {
+    DEBUG(0,("modify_trust_password: unable to initialize client connection.\n"));
+    return False;
+  }
+
+  if(!resolve_name( remote_machine, &dest_ip)) {
+    DEBUG(0,("modify_trust_password: Can't resolve address for %s\n", remote_machine));
+    return False;
+  }
+
+  if (ismyip(dest_ip)) {
+    DEBUG(0,("modify_trust_password: Machine %s is one of our addresses. Cannot add \
+to ourselves.\n", remote_machine));
+    return False;
+  }
+
+  if (!cli_connect(&cli, remote_machine, &dest_ip)) {
+    DEBUG(0,("modify_trust_password: unable to connect to SMB server on \
+machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
+    return False;
+  }
+    
+  if (!cli_session_request(&cli, remote_machine, 0x20, global_myname)) {
+    DEBUG(0,("modify_trust_password: machine %s rejected the session setup. \
+Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
+    cli_shutdown(&cli);
+    return False;
+  }
+
+  cli.protocol = PROTOCOL_NT1;
+    
+  if (!cli_negprot(&cli)) {
+    DEBUG(0,("modify_trust_password: machine %s rejected the negotiate protocol. \
+Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
+    cli_shutdown(&cli);
+    return False;
+  }
+  if (cli.protocol != PROTOCOL_NT1) {
+    DEBUG(0,("modify_trust_password: machine %s didn't negotiate NT protocol.\n", 
+            remote_machine));
+    cli_shutdown(&cli);
+    return False;
+  }
+    
+  /*
+   * Do an anonymous session setup.
+   */
+    
+  if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
+    DEBUG(0,("modify_trust_password: machine %s rejected the session setup. \
+Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
+    cli_shutdown(&cli);
+    return False;
+  }
+    
+  if (!(cli.sec_mode & 1)) {
+    DEBUG(0,("modify_trust_password: machine %s isn't in user level security mode\n",
+          remote_machine));
+    cli_shutdown(&cli);
+    return False;
+  }
+    
+  if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
+    DEBUG(0,("modify_trust_password: machine %s rejected the tconX on the IPC$ share. \
+Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
+    cli_shutdown(&cli);
+    return False;
+  }
+
+  /*
+   * Ok - we have an anonymous connection to the IPC$ share.
+   * Now start the NT Domain stuff :-).
+   */
+    
+  if(cli_nt_session_open(&cli, PIPE_NETLOGON, False) == False) {
+    DEBUG(0,("modify_trust_password: unable to open the domain client session to \
+machine %s. Error was : %s.\n", remote_machine, cli_errstr(&cli)));
+    cli_nt_session_close(&cli);
+    cli_ulogoff(&cli);
+    cli_shutdown(&cli);
+    return False;
+  } 
+  
+  if(cli_nt_setup_creds(&cli, orig_trust_passwd_hash) == False) {
+    DEBUG(0,("modify_trust_password: unable to setup the PDC credentials to machine \
+%s. Error was : %s.\n", remote_machine, cli_errstr(&cli)));
+    cli_nt_session_close(&cli);
+    cli_ulogoff(&cli);
+    cli_shutdown(&cli);
+    return False;
+  } 
+
+  if( cli_nt_srv_pwset( &cli,new_trust_passwd_hash ) == False) {
+    DEBUG(0,("modify_trust_password: unable to change password for machine %s in domain \
+%s to Domain controller %s. Error was %s.\n", global_myname, domain, remote_machine, 
+                            cli_errstr(&cli)));
+    cli_close(&cli, cli.nt_pipe_fnum);
+    cli_ulogoff(&cli);
+    cli_shutdown(&cli);
+    return False;
+  }
+
+  cli_nt_session_close(&cli);
+  cli_ulogoff(&cli);
+  cli_shutdown(&cli);
+
+  return True;
+}
+
+/************************************************************************
+ Change the trust account password for a domain.
+ The user of this function must have locked the trust password file for
+ update.
+************************************************************************/
+
+BOOL change_trust_account_password( char *domain, char *remote_machine_list)
+{
+  fstring remote_machine;
+  unsigned char old_trust_passwd_hash[16];
+  unsigned char new_trust_passwd_hash[16];
+  time_t lct;
+
+  if(!get_trust_account_password( old_trust_passwd_hash, &lct)) {
+    DEBUG(0,("change_trust_account_password: unable to read the machine \
+account password for domain %s.\n", domain));
+    return False;
+  }
+
+  /*
+   * Create the new (random) password.
+   */
+  generate_random_buffer( new_trust_passwd_hash, 16, True);
+
+  while(remote_machine_list && next_token( &remote_machine_list, 
+                                           remote_machine, LIST_SEP)) {
+    strupper(remote_machine);
+    if(modify_trust_password( domain, remote_machine, 
+                              old_trust_passwd_hash, new_trust_passwd_hash)) {
+      DEBUG(0,("%s : change_trust_account_password: Changed password for \
+domain %s.\n", timestring(), domain));
+      /*
+       * Return the result of trying to write the new password
+       * back into the trust account file.
+       */
+      return set_trust_account_password(new_trust_passwd_hash);
+    }
+  }
+
+  DEBUG(0,("%s : change_trust_account_password: Failed to change password for \
+domain %s.\n", timestring(), domain));
+  return False;
+}
index 0f2efcc1da9917c70b88f92eda73ef483057f62f..48fd7cbe24e889d9fa57980becfc65c2b5153c31 100644 (file)
@@ -28,6 +28,8 @@
 extern int DEBUGLEVEL;
 extern int Protocol;
 
+BOOL global_machine_pasword_needs_changing;
+
 /* users from session setup */
 static pstring session_users="";
 
@@ -1972,8 +1974,6 @@ BOOL domain_client_validate( char *user, char *domain,
     }
   }
 
-  become_root(False);
-
   /*
    * Get the machine account password.
    */
@@ -1992,13 +1992,14 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup ));
 
   trust_password_unlock();
 
-  unbecome_root(False);
-
   /* 
    * Here we should check the last change time to see if the machine
    * password needs changing..... TODO... JRA. 
    */
 
+  if(time(NULL) > lct + lp_machine_password_timeout())
+    global_machine_pasword_needs_changing = True;
+
   /*
    * At this point, smb_apasswd points to the lanman response to
    * the challenge in local_challenge, and smb_ntpasswd points to
index 2b2ebb5304e041cf87eb98fd7f26b8de943ea2f9..408d5cd068235dbbe8e4502104f6de8ca6a15f3d 100644 (file)
@@ -50,6 +50,7 @@ extern BOOL use_mangled_map;
 extern BOOL short_case_preserve;
 extern BOOL case_mangle;
 time_t smb_last_time=(time_t)0;
+extern BOOL global_machine_pasword_needs_changing;
 
 extern int smb_read_error;
 
@@ -4950,6 +4951,52 @@ static void process(void)
         DEBUG(2,("%s Closing idle connection 2\n",timestring()));
         return;
       }
+
+      if(global_machine_pasword_needs_changing)
+      {
+        unsigned char trust_passwd_hash[16];
+        time_t lct;
+        pstring remote_machine_list;
+
+        /*
+         * We're in domain level security, and the code that
+         * read the machine password flagged that the machine
+         * password needs changing.
+         */
+
+        /*
+         * First, open the machine password file with an exclusive lock.
+         */
+
+        if(!trust_password_lock( global_myworkgroup, global_myname, True)) {
+          DEBUG(0,("process: unable to open the machine account password file for \
+machine %s in domain %s.\n", global_myname, global_myworkgroup ));
+          continue;
+        }
+
+        if(!get_trust_account_password( trust_passwd_hash, &lct)) {
+          DEBUG(0,("process: unable to read the machine account password for \
+machine %s in domain %s.\n", global_myname, global_myworkgroup ));
+          trust_password_unlock();
+          continue;
+        }
+
+        /*
+         * Make sure someone else hasn't already done this.
+         */
+
+        if(t < lct + lp_machine_password_timeout()) {
+          trust_password_unlock();
+          global_machine_pasword_needs_changing = False;
+          continue;
+        }
+
+        pstrcpy(remote_machine_list, lp_passwordserver());
+
+        change_trust_account_password( global_myworkgroup, remote_machine_list);
+        trust_password_unlock();
+        global_machine_pasword_needs_changing = False;
+      }
     }
 
     if(got_smb)
index 8e744c86410360f2882ef76387c470e986a019e4..c9742fc4987172aba37d165f773798f4bc1eb568 100644 (file)
@@ -43,157 +43,30 @@ static void usage(char *name, BOOL is_root)
 Join a domain.
 **********************************************************/
 
-static int setup_account( char *domain, char *remote_machine, 
-                          unsigned char orig_trust_passwd_hash[16],
-                          unsigned char new_trust_passwd_hash[16])
-{
-  struct in_addr dest_ip;
-  struct cli_state cli;
-
-  memset(&cli, '\0', sizeof(struct cli_state));
-  if(cli_initialise(&cli) == False) {
-    fprintf(stderr, "%s: unable to initialize client connection.\n", prog_name);
-    return 1;
-  }
-
-  if(!resolve_name( remote_machine, &dest_ip)) {
-    fprintf(stderr, "%s: Can't resolve address for %s\n", prog_name, remote_machine);
-    return 1;
-  }
-
-  if (ismyip(dest_ip)) {
-    fprintf(stderr,"%s: Machine %s is one of our addresses. Cannot add to ourselves.\n", prog_name,
-           remote_machine);
-    return 1;
-  }
-
-  if (!cli_connect(&cli, remote_machine, &dest_ip)) {
-    fprintf(stderr, "%s: unable to connect to SMB server on \
-machine %s. Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli) );
-    return 1;
-  }
-    
-  if (!cli_session_request(&cli, remote_machine, 0x20, global_myname)) {
-    fprintf(stderr, "%s: machine %s rejected the session setup. \
-Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli) );
-    cli_shutdown(&cli);
-    return 1;
-  }
-    
-  cli.protocol = PROTOCOL_NT1;
-    
-  if (!cli_negprot(&cli)) {
-    fprintf(stderr, "%s: machine %s rejected the negotiate protocol. \
-Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli) );
-    cli_shutdown(&cli);
-    return 1;
-  }
-  if (cli.protocol != PROTOCOL_NT1) {
-    fprintf(stderr, "%s: machine %s didn't negotiate NT protocol.\n", prog_name, remote_machine);
-    cli_shutdown(&cli);
-    return 1;
-  }
-    
-  /*
-   * Do an anonymous session setup.
-   */
-    
-  if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
-    fprintf(stderr, "%s: machine %s rejected the session setup. \
-Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli) );
-    cli_shutdown(&cli);
-    return 1;
-  }
-    
-  if (!(cli.sec_mode & 1)) {
-    fprintf(stderr, "%s: machine %s isn't in user level security mode\n", prog_name, remote_machine);
-    cli_shutdown(&cli);
-    return 1;
-  }
-    
-  if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
-    fprintf(stderr, "%s: machine %s rejected the tconX on the IPC$ share. \
-Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli) );
-    cli_shutdown(&cli);
-    return 1;
-  }
-
-  /*
-   * Ok - we have an anonymous connection to the IPC$ share.
-   * Now start the NT Domain stuff :-).
-   */
-    
-  if(cli_nt_session_open(&cli, PIPE_NETLOGON, False) == False) {
-    fprintf(stderr, "%s: unable to open the domain client session to \
-machine %s. Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli));
-    cli_nt_session_close(&cli);
-    cli_ulogoff(&cli);
-    cli_shutdown(&cli);
-    return 1;
-  } 
-  
-  if(cli_nt_setup_creds(&cli, orig_trust_passwd_hash) == False) {
-    fprintf(stderr, "%s: unable to setup the PDC credentials to machine \
-%s. Error was : %s.\n", prog_name, remote_machine, cli_errstr(&cli));
-    cli_nt_session_close(&cli);
-    cli_ulogoff(&cli);
-    cli_shutdown(&cli);
-    return 1;
-  } 
-
-  if( cli_nt_srv_pwset( &cli,new_trust_passwd_hash ) == False) {
-    fprintf(stderr, "%s: unable to change password for machine %s in domain \
-%s to Domain controller %s. Error was %s.\n", prog_name, global_myname, domain, remote_machine, 
-                            cli_errstr(&cli));
-    cli_close(&cli, cli.nt_pipe_fnum);
-    cli_ulogoff(&cli);
-    cli_shutdown(&cli);
-    return 1; 
-  }
-
-  cli_nt_session_close(&cli);
-  cli_ulogoff(&cli);
-  cli_shutdown(&cli);
-
-  return 0;
-}
-
-/*********************************************************
-Join a domain.
-**********************************************************/
-
 static int join_domain( char *domain, char *remote)
 {
-  fstring remote_machine;
-  char *p;
+  pstring remote_machine;
   fstring trust_passwd;
-  unsigned char trust_passwd_hash[16];
-  unsigned char new_trust_passwd_hash[16];
-  int ret = 1;
+  unsigned char orig_trust_passwd_hash[16];
+  BOOL ret;
 
-  fstrcpy(remote_machine, remote ? remote : "");
+  pstrcpy(remote_machine, remote ? remote : "");
   fstrcpy(trust_passwd, global_myname);
   strlower(trust_passwd);
-  E_md4hash( (uchar *)trust_passwd, trust_passwd_hash);
-
-  generate_random_buffer( new_trust_passwd_hash, 16, True);
+  E_md4hash( (uchar *)trust_passwd, orig_trust_passwd_hash);
 
   /* Ensure that we are not trying to join a
      domain if we are locally set up as a domain
      controller. */
 
   if(lp_domain_controller() && strequal(lp_workgroup(), domain)) {
-    fprintf(stderr, "%s: Cannot join domain %s as we already configured as domain controller \
-for that domain.\n", prog_name, domain);
+    fprintf(stderr, "%s: Cannot join domain %s as we already configured as \
+domain controller for that domain.\n", prog_name, domain);
     return 1;
   }
 
   /*
-   * Write the new machine password.
-   */
-
-  /*
-   * Get the machine account password.
+   * Create the machine account password file.
    */
   if(!trust_password_lock( domain, global_myname, True)) {
     fprintf(stderr, "%s: unable to open the machine account password file for \
@@ -201,53 +74,42 @@ machine %s in domain %s.\n", prog_name, global_myname, domain);
     return 1;
   }
 
-  if(!set_trust_account_password( new_trust_passwd_hash)) {              
-    fprintf(stderr, "%s: unable to read the machine account password for \
+  /*
+   * Write the old machine account password.
+   */
+
+  if(!set_trust_account_password( orig_trust_passwd_hash)) {              
+    fprintf(stderr, "%s: unable to write the machine account password for \
 machine %s in domain %s.\n", prog_name, global_myname, domain);
     trust_password_unlock();
     return 1;
   }
 
-  trust_password_unlock();
-
   /*
    * If we are given a remote machine assume this is the PDC.
    */
 
-  if(remote != NULL) {
-    strupper(remote_machine);
-    ret = setup_account( domain, remote_machine, trust_passwd_hash, new_trust_passwd_hash);
-    if(ret == 0)
-      printf("%s: Joined domain %s.\n", prog_name, domain);
-  } else {
-    /*
-     * Treat each name in the 'password server =' line as a potential
-     * PDC/BDC. Contact each in turn and try and authenticate and
-     * change the machine account password.
-     */
-
-    p = lp_passwordserver();
+  if(remote == NULL)
+    pstrcpy(remote_machine, lp_passwordserver());
 
-    if(!*p)
-      fprintf(stderr, "%s: No password server list given in smb.conf - \
+  if(!*remote_machine) {
+    fprintf(stderr, "%s: No password server list given in smb.conf - \
 unable to join domain.\n", prog_name);
-
-    while(p && next_token( &p, remote_machine, LIST_SEP)) {
-
-      strupper(remote_machine);
-      if(setup_account( domain, remote_machine, trust_passwd_hash, new_trust_passwd_hash) == 0) {
-        printf("%s: Joined domain %s.\n", prog_name, domain);
-        return 0;
-      }
-    }
+    trust_password_unlock();
+    return 1;
   }
 
-  if(ret) {
+  ret = change_trust_account_password( domain, remote_machine);
+  trust_password_unlock();
+
+  if(!ret) {
     trust_password_delete( domain, global_myname);
     fprintf(stderr,"%s: Unable to join domain %s.\n", prog_name, domain);
+  } else {
+    printf("%s: Joined domain %s.\n", prog_name, domain);
   }
 
-  return ret;
+  return (int)ret;
 }
 
 /*********************************************************