utils/net_domain.c

説明を見る。
00001 /* 
00002    Samba Unix/Linux SMB client library 
00003    net ads commands
00004    Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
00005    Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
00006    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
00007    Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013    
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018    
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
00022 */
00023 
00024 #include "includes.h"
00025 #include "utils/net.h"
00026 
00027 /* Macro for checking RPC error codes to make things more readable */
00028 
00029 #define CHECK_RPC_ERR(rpc, msg) \
00030         if (!NT_STATUS_IS_OK(result = rpc)) { \
00031                 DEBUG(0, (msg ": %s\n", nt_errstr(result))); \
00032                 goto done; \
00033         }
00034 
00035 #define CHECK_RPC_ERR_DEBUG(rpc, debug_args) \
00036         if (!NT_STATUS_IS_OK(result = rpc)) { \
00037                 DEBUG(0, debug_args); \
00038                 goto done; \
00039         }
00040 
00041 /*******************************************************************
00042  Leave an AD domain.  Windows XP disables the machine account.
00043  We'll try the same.  The old code would do an LDAP delete.
00044  That only worked using the machine creds because added the machine
00045  with full control to the computer object's ACL.
00046 *******************************************************************/
00047 
00048 NTSTATUS netdom_leave_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, 
00049                          DOM_SID *dom_sid )
00050 {       
00051         struct rpc_pipe_client *pipe_hnd = NULL;
00052         POLICY_HND sam_pol, domain_pol, user_pol;
00053         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00054         char *acct_name;
00055         uint32 flags = 0x3e8;
00056         const char *const_acct_name;
00057         uint32 user_rid;
00058         uint32 num_rids, *name_types, *user_rids;
00059         SAM_USERINFO_CTR ctr, *qctr = NULL;
00060         SAM_USER_INFO_16 p16;
00061 
00062         /* Open the domain */
00063         
00064         if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status)) == NULL ) {
00065                 DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
00066                         nt_errstr(status) ));
00067                 return status;
00068         }
00069 
00070         status = rpccli_samr_connect(pipe_hnd, mem_ctx, 
00071                         SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
00072         if ( !NT_STATUS_IS_OK(status) )
00073                 return status;
00074 
00075         
00076         status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
00077                         SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
00078         if ( !NT_STATUS_IS_OK(status) )
00079                 return status;
00080 
00081         /* Create domain user */
00082         
00083         acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); 
00084         strlower_m(acct_name);
00085         const_acct_name = acct_name;
00086 
00087         status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
00088                         &domain_pol, flags, 1, &const_acct_name, 
00089                         &num_rids, &user_rids, &name_types);
00090         if ( !NT_STATUS_IS_OK(status) )
00091                 return status;
00092 
00093         if ( name_types[0] != SID_NAME_USER) {
00094                 DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
00095                 return NT_STATUS_INVALID_WORKSTATION;
00096         }
00097 
00098         user_rid = user_rids[0];
00099                 
00100         /* Open handle on user */
00101 
00102         status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
00103                         SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
00104         if ( !NT_STATUS_IS_OK(status) ) {
00105                 goto done;
00106         }
00107         
00108         /* Get user info */
00109 
00110         status = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol, 16, &qctr);
00111         if ( !NT_STATUS_IS_OK(status) ) {
00112                 rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
00113                 goto done;
00114         }
00115 
00116         /* now disable and setuser info */
00117         
00118         ZERO_STRUCT(ctr);
00119         ctr.switch_value = 16;
00120         ctr.info.id16 = &p16;
00121 
00122         p16.acb_info = qctr->info.id16->acb_info | ACB_DISABLED;
00123 
00124         status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16, 
00125                                         &cli->user_session_key, &ctr);
00126 
00127         rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
00128 
00129 done:
00130         rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
00131         rpccli_samr_close(pipe_hnd, mem_ctx, &sam_pol);
00132         
00133         cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
00134         
00135         return status;
00136 }
00137 
00138 /*******************************************************************
00139  Store the machine password and domain SID
00140  ********************************************************************/
00141 
00142 int netdom_store_machine_account( const char *domain, DOM_SID *sid, const char *pw )
00143 {
00144         if (!secrets_store_domain_sid(domain, sid)) {
00145                 DEBUG(1,("Failed to save domain sid\n"));
00146                 return -1;
00147         }
00148 
00149         if (!secrets_store_machine_password(pw, domain, SEC_CHAN_WKSTA)) {
00150                 DEBUG(1,("Failed to save machine password\n"));
00151                 return -1;
00152         }
00153 
00154         return 0;
00155 }
00156 
00157 /*******************************************************************
00158  ********************************************************************/
00159 
00160 NTSTATUS netdom_get_domain_sid( TALLOC_CTX *mem_ctx, struct cli_state *cli, 
00161                                 char **domain, DOM_SID **sid )
00162 {
00163         struct rpc_pipe_client *pipe_hnd = NULL;
00164         POLICY_HND lsa_pol;
00165         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00166 
00167         if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &status)) == NULL ) {
00168                 DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n",
00169                         nt_errstr(status) ));
00170                 return status;
00171         }
00172 
00173         status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
00174                         SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
00175         if ( !NT_STATUS_IS_OK(status) )
00176                 return status;
00177 
00178         status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, 
00179                         &lsa_pol, 5, domain, sid);
00180         if ( !NT_STATUS_IS_OK(status) )
00181                 return status;
00182 
00183         rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
00184         cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
00185 
00186         /* Bail out if domain didn't get set. */
00187         if (!domain) {
00188                 DEBUG(0, ("Could not get domain name.\n"));
00189                 return NT_STATUS_UNSUCCESSFUL;
00190         }
00191         
00192         return NT_STATUS_OK;
00193 }
00194 
00195 /*******************************************************************
00196  Do the domain join
00197  ********************************************************************/
00198  
00199 NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, 
00200                            DOM_SID *dom_sid, const char *clear_pw,
00201                            enum netdom_domain_t dom_type )
00202 {       
00203         struct rpc_pipe_client *pipe_hnd = NULL;
00204         POLICY_HND sam_pol, domain_pol, user_pol;
00205         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
00206         char *acct_name;
00207         const char *const_acct_name;
00208         uint32 user_rid;
00209         uint32 num_rids, *name_types, *user_rids;
00210         uint32 flags = 0x3e8;
00211         uint32 acb_info = ACB_WSTRUST;
00212         uint32 acct_flags=0;
00213         uint32 fields_present;
00214         uchar pwbuf[532];
00215         SAM_USERINFO_CTR ctr;
00216         SAM_USER_INFO_24 p24;
00217         SAM_USER_INFO_25 p25;
00218         const int infolevel = 25;
00219         struct MD5Context md5ctx;
00220         uchar md5buffer[16];
00221         DATA_BLOB digested_session_key;
00222         uchar md4_trust_password[16];
00223 
00224         /* Open the domain */
00225         
00226         if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status)) == NULL ) {
00227                 DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
00228                         nt_errstr(status) ));
00229                 return status;
00230         }
00231 
00232         status = rpccli_samr_connect(pipe_hnd, mem_ctx, 
00233                         SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
00234         if ( !NT_STATUS_IS_OK(status) )
00235                 return status;
00236 
00237         
00238         status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
00239                         SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
00240         if ( !NT_STATUS_IS_OK(status) )
00241                 return status;
00242 
00243         /* Create domain user */
00244         
00245         acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); 
00246         strlower_m(acct_name);
00247         const_acct_name = acct_name;
00248 
00249         /* Don't try to set any acb_info flags other than ACB_WSTRUST */
00250 
00251         acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
00252                 SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
00253                 SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
00254                 SAMR_USER_SETATTR;
00255         DEBUG(10, ("Creating account with flags: %d\n",acct_flags));
00256         status = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
00257                         acct_name, acb_info, acct_flags, &user_pol, &user_rid);
00258 
00259         if ( !NT_STATUS_IS_OK(status) 
00260                 && !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) 
00261         {
00262                 d_fprintf(stderr, "Creation of workstation account failed\n");
00263 
00264                 /* If NT_STATUS_ACCESS_DENIED then we have a valid
00265                    username/password combo but the user does not have
00266                    administrator access. */
00267 
00268                 if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED))
00269                         d_fprintf(stderr, "User specified does not have administrator privileges\n");
00270 
00271                 return status;
00272         }
00273 
00274         /* We *must* do this.... don't ask... */
00275 
00276         if (NT_STATUS_IS_OK(status)) {
00277                 rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
00278         }
00279 
00280         status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
00281                         &domain_pol, flags, 1, &const_acct_name, 
00282                         &num_rids, &user_rids, &name_types);
00283         if ( !NT_STATUS_IS_OK(status) )
00284                 return status;
00285 
00286         if ( name_types[0] != SID_NAME_USER) {
00287                 DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
00288                 return NT_STATUS_INVALID_WORKSTATION;
00289         }
00290 
00291         user_rid = user_rids[0];
00292                 
00293         /* Open handle on user */
00294 
00295         status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
00296                         SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
00297         if (!NT_STATUS_IS_OK(status)) {
00298                 return status;
00299         }
00300         
00301         /* Create a random machine account password and generate the hash */
00302 
00303         E_md4hash(clear_pw, md4_trust_password);
00304         encode_pw_buffer(pwbuf, clear_pw, STR_UNICODE);
00305         
00306         generate_random_buffer((uint8*)md5buffer, sizeof(md5buffer));
00307         digested_session_key = data_blob_talloc(mem_ctx, 0, 16);
00308         
00309         MD5Init(&md5ctx);
00310         MD5Update(&md5ctx, md5buffer, sizeof(md5buffer));
00311         MD5Update(&md5ctx, cli->user_session_key.data, cli->user_session_key.length);
00312         MD5Final(digested_session_key.data, &md5ctx);
00313         
00314         SamOEMhashBlob(pwbuf, sizeof(pwbuf), &digested_session_key);
00315         memcpy(&pwbuf[516], md5buffer, sizeof(md5buffer));
00316 
00317         /* Fill in the additional account flags now */
00318 
00319         acb_info |= ACB_PWNOEXP;
00320         if ( dom_type == ND_TYPE_AD ) {
00321 #if !defined(ENCTYPE_ARCFOUR_HMAC)
00322                 acb_info |= ACB_USE_DES_KEY_ONLY;
00323 #endif
00324                 ;;
00325         }
00326 
00327         /* Set password and account flags on machine account */
00328 
00329         ZERO_STRUCT(ctr);
00330         ZERO_STRUCT(p25);
00331 
00332         fields_present = ACCT_NT_PWD_SET | ACCT_LM_PWD_SET | ACCT_FLAGS;
00333         init_sam_user_info25P(&p25, fields_present, acb_info, (char *)pwbuf);
00334 
00335         ctr.switch_value = infolevel;
00336         ctr.info.id25    = &p25;
00337 
00338         status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol,
00339                                            infolevel, &cli->user_session_key, &ctr);
00340 
00341         if (NT_STATUS_EQUAL(status, NT_STATUS(DCERPC_FAULT_INVALID_TAG))) {
00342 
00343                 uchar pwbuf2[516];
00344 
00345                 ZERO_STRUCT(p24);
00346 
00347                 encode_pw_buffer(pwbuf2, clear_pw, STR_UNICODE);
00348 
00349                 /* retry with level 24 */
00350                 init_sam_user_info24(&p24, (char *)pwbuf2, 24);
00351 
00352                 ctr.switch_value = 24;
00353                 ctr.info.id24    = &p24;
00354 
00355                 status = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx,
00356                                                   &user_pol,
00357                                                   24,
00358                                                   &cli->user_session_key,
00359                                                   &ctr);
00360         }
00361 
00362         if ( !NT_STATUS_IS_OK(status) ) {
00363                 d_fprintf( stderr, "Failed to set password for machine account (%s)\n", 
00364                         nt_errstr(status));
00365                 return status;
00366         }
00367 
00368         rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
00369         cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
00370         
00371         return status;
00372 }
00373 

Sambaに対してSat Aug 29 21:23:28 2009に生成されました。  doxygen 1.4.7