Add my copyright.
[samba.git] / source3 / utils / net_domain.c
index 4f7bc8ddecde48223c70f5b539819db75900a25c..1a84c6cbc60ee850423b99017642dca9b630f416 100644 (file)
@@ -5,10 +5,11 @@
    Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
    Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
+   Copyright (C) 2008 Guenther Deschner (gd@samba.org)
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -17,8 +18,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  
 */
 
 #include "includes.h"
@@ -52,12 +52,11 @@ NTSTATUS netdom_leave_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
        POLICY_HND sam_pol, domain_pol, user_pol;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        char *acct_name;
-       uint32 flags = 0x3e8;
-       const char *const_acct_name;
        uint32 user_rid;
-       uint32 num_rids, *name_types, *user_rids;
-       SAM_USERINFO_CTR ctr, *qctr = NULL;
-       SAM_USER_INFO_16 p16;
+       struct lsa_String lsa_acct_name;
+       struct samr_Ids user_rids;
+       struct samr_Ids name_types;
+       union samr_UserInfo *info = NULL;
 
        /* Open the domain */
        
@@ -67,14 +66,19 @@ NTSTATUS netdom_leave_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
                return status;
        }
 
-       status = rpccli_samr_connect(pipe_hnd, mem_ctx, 
-                       SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
+       status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
+                                     pipe_hnd->cli->desthost,
+                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                     &sam_pol);
        if ( !NT_STATUS_IS_OK(status) )
                return status;
 
-       
-       status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
-                       SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
+
+       status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
+                                       &sam_pol,
+                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                       dom_sid,
+                                       &domain_pol);
        if ( !NT_STATUS_IS_OK(status) )
                return status;
 
@@ -82,53 +86,61 @@ NTSTATUS netdom_leave_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
        
        acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); 
        strlower_m(acct_name);
-       const_acct_name = acct_name;
 
-       status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
-                       &domain_pol, flags, 1, &const_acct_name, 
-                       &num_rids, &user_rids, &name_types);
+       init_lsa_String(&lsa_acct_name, acct_name);
+
+       status = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
+                                        &domain_pol,
+                                        1,
+                                        &lsa_acct_name,
+                                        &user_rids,
+                                        &name_types);
        if ( !NT_STATUS_IS_OK(status) )
                return status;
 
-       if ( name_types[0] != SID_NAME_USER) {
-               DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
+       if ( name_types.ids[0] != SID_NAME_USER) {
+               DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types.ids[0]));
                return NT_STATUS_INVALID_WORKSTATION;
        }
 
-       user_rid = user_rids[0];
+       user_rid = user_rids.ids[0];
                
        /* Open handle on user */
 
-       status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
-                       SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
+       status = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
+                                     &domain_pol,
+                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                     user_rid,
+                                     &user_pol);
        if ( !NT_STATUS_IS_OK(status) ) {
                goto done;
        }
        
        /* Get user info */
 
-       status = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol, 16, &qctr);
+       status = rpccli_samr_QueryUserInfo(pipe_hnd, mem_ctx,
+                                          &user_pol,
+                                          16,
+                                          &info);
        if ( !NT_STATUS_IS_OK(status) ) {
-               rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+               rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
                goto done;
        }
 
        /* now disable and setuser info */
-       
-       ZERO_STRUCT(ctr);
-       ctr.switch_value = 16;
-       ctr.info.id16 = &p16;
 
-       p16.acb_info = qctr->info.id16->acb_info | ACB_DISABLED;
+       info->info16.acct_flags |= ACB_DISABLED;
 
-       status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16, 
-                                       &cli->user_session_key, &ctr);
+       status = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
+                                        &user_pol,
+                                        16,
+                                        info);
 
-       rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+       rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
 
 done:
-       rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
-       rpccli_samr_close(pipe_hnd, mem_ctx, &sam_pol);
+       rpccli_samr_Close(pipe_hnd, mem_ctx, &domain_pol);
+       rpccli_samr_Close(pipe_hnd, mem_ctx, &sam_pol);
        
        cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
        
@@ -158,11 +170,12 @@ int netdom_store_machine_account( const char *domain, DOM_SID *sid, const char *
  ********************************************************************/
 
 NTSTATUS netdom_get_domain_sid( TALLOC_CTX *mem_ctx, struct cli_state *cli, 
-                               char **domain, DOM_SID **sid )
+                               const char **domain, DOM_SID **sid )
 {
        struct rpc_pipe_client *pipe_hnd = NULL;
        POLICY_HND lsa_pol;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       union lsa_PolicyInformation *info = NULL;
 
        if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &status)) == NULL ) {
                DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n",
@@ -175,11 +188,16 @@ NTSTATUS netdom_get_domain_sid( TALLOC_CTX *mem_ctx, struct cli_state *cli,
        if ( !NT_STATUS_IS_OK(status) )
                return status;
 
-       status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, 
-                       &lsa_pol, 5, domain, sid);
+       status = rpccli_lsa_QueryInfoPolicy(pipe_hnd, mem_ctx,
+                                           &lsa_pol,
+                                           LSA_POLICY_INFO_ACCOUNT_DOMAIN,
+                                           &info);
        if ( !NT_STATUS_IS_OK(status) )
                return status;
 
+       *domain = info->account_domain.name.string;
+       *sid = info->account_domain.sid;
+
        rpccli_lsa_Close(pipe_hnd, mem_ctx, &lsa_pol);
        cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
 
@@ -204,16 +222,19 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
        POLICY_HND sam_pol, domain_pol, user_pol;
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        char *acct_name;
-       const char *const_acct_name;
+       struct lsa_String lsa_acct_name;
        uint32 user_rid;
-       uint32 num_rids, *name_types, *user_rids;
-       uint32 flags = 0x3e8;
        uint32 acb_info = ACB_WSTRUST;
-       uchar pwbuf[516];
-       SAM_USERINFO_CTR ctr;
-       SAM_USER_INFO_24 p24;
-       SAM_USER_INFO_16 p16;
+       uint32 acct_flags;
+       uchar pwbuf[532];
+       struct MD5Context md5ctx;
+       uchar md5buffer[16];
+       DATA_BLOB digested_session_key;
        uchar md4_trust_password[16];
+       uint32_t access_granted = 0;
+       struct samr_Ids user_rids;
+       struct samr_Ids name_types;
+       union samr_UserInfo info;
 
        /* Open the domain */
        
@@ -223,14 +244,19 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
                return status;
        }
 
-       status = rpccli_samr_connect(pipe_hnd, mem_ctx, 
-                       SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
+       status = rpccli_samr_Connect2(pipe_hnd, mem_ctx,
+                                     pipe_hnd->cli->desthost,
+                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                     &sam_pol);
        if ( !NT_STATUS_IS_OK(status) )
                return status;
 
-       
-       status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
-                       SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
+
+       status = rpccli_samr_OpenDomain(pipe_hnd, mem_ctx,
+                                       &sam_pol,
+                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                       dom_sid,
+                                       &domain_pol);
        if ( !NT_STATUS_IS_OK(status) )
                return status;
 
@@ -238,12 +264,26 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
        
        acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); 
        strlower_m(acct_name);
-       const_acct_name = acct_name;
 
-       /* Don't try to set any acb_info flags other than ACB_WSTRUST */
+       init_lsa_String(&lsa_acct_name, acct_name);
 
-       status = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
-                       acct_name, acb_info, 0xe005000b, &user_pol, &user_rid);
+       /* Don't try to set any acb_info flags other than ACB_WSTRUST */
+       acct_flags = SEC_GENERIC_READ | SEC_GENERIC_WRITE | SEC_GENERIC_EXECUTE |
+                    SEC_STD_WRITE_DAC | SEC_STD_DELETE |
+                    SAMR_USER_ACCESS_SET_PASSWORD |
+                    SAMR_USER_ACCESS_GET_ATTRIBUTES |
+                    SAMR_USER_ACCESS_SET_ATTRIBUTES;
+
+       DEBUG(10, ("Creating account with flags: %d\n",acct_flags));
+
+       status = rpccli_samr_CreateUser2(pipe_hnd, mem_ctx,
+                                        &domain_pol,
+                                        &lsa_acct_name,
+                                        acb_info,
+                                        acct_flags,
+                                        &user_pol,
+                                        &access_granted,
+                                        &user_rid);
 
        if ( !NT_STATUS_IS_OK(status) 
                && !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) 
@@ -263,64 +303,51 @@ NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
        /* We *must* do this.... don't ask... */
 
        if (NT_STATUS_IS_OK(status)) {
-               rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+               rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
        }
 
-       status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
-                       &domain_pol, flags, 1, &const_acct_name, 
-                       &num_rids, &user_rids, &name_types);
+       status = rpccli_samr_LookupNames(pipe_hnd, mem_ctx,
+                                        &domain_pol,
+                                        1,
+                                        &lsa_acct_name,
+                                        &user_rids,
+                                        &name_types);
        if ( !NT_STATUS_IS_OK(status) )
                return status;
 
-       if ( name_types[0] != SID_NAME_USER) {
-               DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
+       if ( name_types.ids[0] != SID_NAME_USER) {
+               DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types.ids[0]));
                return NT_STATUS_INVALID_WORKSTATION;
        }
 
-       user_rid = user_rids[0];
+       user_rid = user_rids.ids[0];
                
        /* Open handle on user */
 
-       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));
+       status = rpccli_samr_OpenUser(pipe_hnd, mem_ctx,
+                                     &domain_pol,
+                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                     user_rid,
+                                     &user_pol);
+       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 */
 
@@ -332,12 +359,27 @@ 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 */
+       ZERO_STRUCT(info.info25);
+       info.info25.info.fields_present = ACCT_NT_PWD_SET |
+                                         ACCT_LM_PWD_SET |
+                                         SAMR_FIELD_ACCT_FLAGS;
+       info.info25.info.acct_flags = acb_info;
+       memcpy(&info.info25.password.data, pwbuf, sizeof(pwbuf));
+
 
-       status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16, 
-                                       &cli->user_session_key, &ctr);
+       status = rpccli_samr_SetUserInfo(pipe_hnd, mem_ctx,
+                                        &user_pol,
+                                        25,
+                                        &info);
+
+       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);
+       rpccli_samr_Close(pipe_hnd, mem_ctx, &user_pol);
        cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
        
        return status;