2
Samba Unix/Linux SMB client library
4
Copyright (C) 2001 Andrew Tridgell (tridge@samba.org)
5
Copyright (C) 2001 Remus Koos (remuskoos@yahoo.com)
6
Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
7
Copyright (C) 2006 Gerald (Jerry) Carter (jerry@samba.org)
9
This program is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2 of the License, or
12
(at your option) any later version.
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU General Public License for more details.
19
You should have received a copy of the GNU General Public License
20
along with this program; if not, write to the Free Software
21
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
#include "utils/net.h"
27
/* Macro for checking RPC error codes to make things more readable */
29
#define CHECK_RPC_ERR(rpc, msg) \
30
if (!NT_STATUS_IS_OK(result = rpc)) { \
31
DEBUG(0, (msg ": %s\n", nt_errstr(result))); \
35
#define CHECK_RPC_ERR_DEBUG(rpc, debug_args) \
36
if (!NT_STATUS_IS_OK(result = rpc)) { \
37
DEBUG(0, debug_args); \
41
/*******************************************************************
42
Leave an AD domain. Windows XP disables the machine account.
43
We'll try the same. The old code would do an LDAP delete.
44
That only worked using the machine creds because added the machine
45
with full control to the computer object's ACL.
46
*******************************************************************/
48
NTSTATUS netdom_leave_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
51
struct rpc_pipe_client *pipe_hnd = NULL;
52
POLICY_HND sam_pol, domain_pol, user_pol;
53
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
56
const char *const_acct_name;
58
uint32 num_rids, *name_types, *user_rids;
59
SAM_USERINFO_CTR ctr, *qctr = NULL;
64
if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status)) == NULL ) {
65
DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
70
status = rpccli_samr_connect(pipe_hnd, mem_ctx,
71
SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
72
if ( !NT_STATUS_IS_OK(status) )
76
status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
77
SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
78
if ( !NT_STATUS_IS_OK(status) )
81
/* Create domain user */
83
acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname());
84
strlower_m(acct_name);
85
const_acct_name = acct_name;
87
status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
88
&domain_pol, flags, 1, &const_acct_name,
89
&num_rids, &user_rids, &name_types);
90
if ( !NT_STATUS_IS_OK(status) )
93
if ( name_types[0] != SID_NAME_USER) {
94
DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
95
return NT_STATUS_INVALID_WORKSTATION;
98
user_rid = user_rids[0];
100
/* Open handle on user */
102
status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
103
SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
104
if ( !NT_STATUS_IS_OK(status) ) {
110
status = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol, 16, &qctr);
111
if ( !NT_STATUS_IS_OK(status) ) {
112
rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
116
/* now disable and setuser info */
119
ctr.switch_value = 16;
120
ctr.info.id16 = &p16;
122
p16.acb_info = qctr->info.id16->acb_info | ACB_DISABLED;
124
status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16,
125
&cli->user_session_key, &ctr);
127
rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
130
rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
131
rpccli_samr_close(pipe_hnd, mem_ctx, &sam_pol);
133
cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
138
/*******************************************************************
139
Store the machine password and domain SID
140
********************************************************************/
142
int netdom_store_machine_account( const char *domain, DOM_SID *sid, const char *pw )
144
if (!secrets_store_domain_sid(domain, sid)) {
145
DEBUG(1,("Failed to save domain sid\n"));
149
if (!secrets_store_machine_password(pw, domain, SEC_CHAN_WKSTA)) {
150
DEBUG(1,("Failed to save machine password\n"));
157
/*******************************************************************
158
********************************************************************/
160
NTSTATUS netdom_get_domain_sid( TALLOC_CTX *mem_ctx, struct cli_state *cli, DOM_SID **sid )
162
struct rpc_pipe_client *pipe_hnd = NULL;
164
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
167
if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &status)) == NULL ) {
168
DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n",
169
nt_errstr(status) ));
173
status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
174
SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
175
if ( !NT_STATUS_IS_OK(status) )
178
status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx,
179
&lsa_pol, 5, &domain, sid);
180
if ( !NT_STATUS_IS_OK(status) )
183
rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
184
cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
186
/* Bail out if domain didn't get set. */
188
DEBUG(0, ("Could not get domain name.\n"));
189
return NT_STATUS_UNSUCCESSFUL;
195
/*******************************************************************
197
********************************************************************/
199
NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli,
200
DOM_SID *dom_sid, const char *clear_pw,
201
enum netdom_domain_t dom_type )
203
struct rpc_pipe_client *pipe_hnd = NULL;
204
POLICY_HND sam_pol, domain_pol, user_pol;
205
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
207
const char *const_acct_name;
209
uint32 num_rids, *name_types, *user_rids;
210
uint32 flags = 0x3e8;
211
uint32 acb_info = ACB_WSTRUST;
213
SAM_USERINFO_CTR ctr;
214
SAM_USER_INFO_24 p24;
215
SAM_USER_INFO_16 p16;
216
uchar md4_trust_password[16];
218
/* Open the domain */
220
if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status)) == NULL ) {
221
DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
222
nt_errstr(status) ));
226
status = rpccli_samr_connect(pipe_hnd, mem_ctx,
227
SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
228
if ( !NT_STATUS_IS_OK(status) )
232
status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
233
SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
234
if ( !NT_STATUS_IS_OK(status) )
237
/* Create domain user */
239
acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname());
240
strlower_m(acct_name);
241
const_acct_name = acct_name;
243
/* Don't try to set any acb_info flags other than ACB_WSTRUST */
245
status = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
246
acct_name, acb_info, 0xe005000b, &user_pol, &user_rid);
248
if ( !NT_STATUS_IS_OK(status)
249
&& !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS))
251
d_fprintf(stderr, "Creation of workstation account failed\n");
253
/* If NT_STATUS_ACCESS_DENIED then we have a valid
254
username/password combo but the user does not have
255
administrator access. */
257
if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED))
258
d_fprintf(stderr, "User specified does not have administrator privileges\n");
263
/* We *must* do this.... don't ask... */
265
if (NT_STATUS_IS_OK(status)) {
266
rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
269
status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
270
&domain_pol, flags, 1, &const_acct_name,
271
&num_rids, &user_rids, &name_types);
272
if ( !NT_STATUS_IS_OK(status) )
275
if ( name_types[0] != SID_NAME_USER) {
276
DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
277
return NT_STATUS_INVALID_WORKSTATION;
280
user_rid = user_rids[0];
282
/* Open handle on user */
284
status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
285
SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
287
/* Create a random machine account password */
289
E_md4hash( clear_pw, md4_trust_password);
290
encode_pw_buffer(pwbuf, clear_pw, STR_UNICODE);
292
/* Set password on machine account */
297
init_sam_user_info24(&p24, (char *)pwbuf,24);
299
ctr.switch_value = 24;
300
ctr.info.id24 = &p24;
302
status = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol,
303
24, &cli->user_session_key, &ctr);
305
if ( !NT_STATUS_IS_OK(status) ) {
306
d_fprintf( stderr, "Failed to set password for machine account (%s)\n",
312
/* Why do we have to try to (re-)set the ACB to be the same as what
313
we passed in the samr_create_dom_user() call? When a NT
314
workstation is joined to a domain by an administrator the
315
acb_info is set to 0x80. For a normal user with "Add
316
workstations to the domain" rights the acb_info is 0x84. I'm
317
not sure whether it is supposed to make a difference or not. NT
318
seems to cope with either value so don't bomb out if the set
319
userinfo2 level 0x10 fails. -tpot */
322
ctr.switch_value = 16;
323
ctr.info.id16 = &p16;
325
/* Fill in the additional account flags now */
327
acb_info |= ACB_PWNOEXP;
328
if ( dom_type == ND_TYPE_AD ) {
329
#if !defined(ENCTYPE_ARCFOUR_HMAC)
330
acb_info |= ACB_USE_DES_KEY_ONLY;
335
init_sam_user_info16(&p16, acb_info);
337
status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16,
338
&cli->user_session_key, &ctr);
340
rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
341
cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */