r24771: Use infolevel 25 to set the machine account's password (just like winxp).
authorRafal Szczesniak <mimir@samba.org>
Wed, 29 Aug 2007 11:02:04 +0000 (11:02 +0000)
committerGünther Deschner <gd@samba.org>
Thu, 31 Jan 2008 09:28:01 +0000 (10:28 +0100)
This correctly updates pwdLastSet field on win2k3 server.

rafal

source/rpc_parse/parse_samr.c
source/utils/net_domain.c

index 0d83e454ef2ad8a58fab48fa2faa5a842b274641..d452c1fe82e9543c3d391f9b87d417997e99a750 100644 (file)
@@ -5870,6 +5870,25 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time,  /* all z
        }
 }
 
+
+/*************************************************************************
+ init_samr_user_info25P
+ fields_present = ACCT_NT_PWD_SET | ACCT_LM_PWD_SET | ACCT_FLAGS
+*************************************************************************/
+
+void init_sam_user_info25P(SAM_USER_INFO_25 * usr,
+                          uint32 fields_present, uint32 acb_info,
+                          char newpass[532])
+{
+       usr->fields_present = fields_present;
+       ZERO_STRUCT(usr->padding1);
+       ZERO_STRUCT(usr->padding2);
+
+       usr->acb_info = acb_info;
+       memcpy(usr->pass, newpass, sizeof(usr->pass));
+}
+
+
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
index ac7e0dad7337bb953469cf4c4c9190c16b1f9f70..533bb9c6989cc6a62af1435873e5b35fb448f14f 100644 (file)
@@ -210,10 +210,14 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
        uint32 flags = 0x3e8;
        uint32 acb_info = ACB_WSTRUST;
        uint32 acct_flags=0;
-       uchar pwbuf[516];
+       uint32 fields_present;
+       uchar pwbuf[532];
        SAM_USERINFO_CTR ctr;
-       SAM_USER_INFO_24 p24;
-       SAM_USER_INFO_16 p16;
+       SAM_USER_INFO_25 p25;
+       const int infolevel = 25;
+       struct MD5Context md5ctx;
+       uchar md5buffer[16];
+       DATA_BLOB digested_session_key;
        uchar md4_trust_password[16];
 
        /* Open the domain */
@@ -289,44 +293,25 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
 
        status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
                        SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
-       
-       /* Create a random machine account password */
-
-       E_md4hash( clear_pw, md4_trust_password);
-       encode_pw_buffer(pwbuf, clear_pw, STR_UNICODE);
-
-       /* Set password on machine account */
-
-       ZERO_STRUCT(ctr);
-       ZERO_STRUCT(p24);
-
-       init_sam_user_info24(&p24, (char *)pwbuf,24);
-
-       ctr.switch_value = 24;
-       ctr.info.id24 = &p24;
-
-       status = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 
-                       24, &cli->user_session_key, &ctr);
-
-       if ( !NT_STATUS_IS_OK(status) ) {
-               d_fprintf( stderr, "Failed to set password for machine account (%s)\n", 
-                       nt_errstr(status));
+       if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
+       
+       /* Create a random machine account password and generate the hash */
 
-
-       /* Why do we have to try to (re-)set the ACB to be the same as what
-          we passed in the samr_create_dom_user() call?  When a NT
-          workstation is joined to a domain by an administrator the
-          acb_info is set to 0x80.  For a normal user with "Add
-          workstations to the domain" rights the acb_info is 0x84.  I'm
-          not sure whether it is supposed to make a difference or not.  NT
-          seems to cope with either value so don't bomb out if the set
-          userinfo2 level 0x10 fails.  -tpot */
-
-       ZERO_STRUCT(ctr);
-       ctr.switch_value = 16;
-       ctr.info.id16 = &p16;
+       E_md4hash(clear_pw, md4_trust_password);
+       encode_pw_buffer(pwbuf, clear_pw, STR_UNICODE);
+       
+       generate_random_buffer((uint8*)md5buffer, sizeof(md5buffer));
+       digested_session_key = data_blob_talloc(mem_ctx, 0, 16);
+       
+       MD5Init(&md5ctx);
+       MD5Update(&md5ctx, md5buffer, sizeof(md5buffer));
+       MD5Update(&md5ctx, cli->user_session_key.data, cli->user_session_key.length);
+       MD5Final(digested_session_key.data, &md5ctx);
+       
+       SamOEMhashBlob(pwbuf, sizeof(pwbuf), &digested_session_key);
+       memcpy(&pwbuf[516], md5buffer, sizeof(md5buffer));
 
        /* Fill in the additional account flags now */
 
@@ -338,10 +323,25 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
                ;;
        }
 
-       init_sam_user_info16(&p16, acb_info);
+       /* Set password and account flags on machine account */
 
-       status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16, 
-                                       &cli->user_session_key, &ctr);
+       ZERO_STRUCT(ctr);
+       ZERO_STRUCT(p25);
+
+       fields_present = ACCT_NT_PWD_SET | ACCT_LM_PWD_SET | ACCT_FLAGS;
+       init_sam_user_info25P(&p25, fields_present, acb_info, (char *)pwbuf);
+
+       ctr.switch_value = infolevel;
+       ctr.info.id25    = &p25;
+
+       status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol,
+                                          infolevel, &cli->user_session_key, &ctr);
+
+       if ( !NT_STATUS_IS_OK(status) ) {
+               d_fprintf( stderr, "Failed to set password for machine account (%s)\n", 
+                       nt_errstr(status));
+               return status;
+       }
 
        rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
        cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */