e5d28735ed764d3e0b71b997ee632f4d786b32ef
[vlendec/samba-autobuild/.git] / source3 / lib / netapi / joindomain.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  NetApi Join Support
4  *  Copyright (C) Guenther Deschner 2007-2008
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21 #include "ads.h"
22 #include "librpc/gen_ndr/libnetapi.h"
23 #include "libcli/auth/libcli_auth.h"
24 #include "lib/netapi/netapi.h"
25 #include "lib/netapi/netapi_private.h"
26 #include "lib/netapi/libnetapi.h"
27 #include "librpc/gen_ndr/libnet_join.h"
28 #include "libnet/libnet_join.h"
29 #include "../librpc/gen_ndr/ndr_wkssvc_c.h"
30 #include "secrets.h"
31
32 /****************************************************************
33 ****************************************************************/
34
35 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
36                        struct NetJoinDomain *r)
37 {
38         struct libnet_JoinCtx *j = NULL;
39         struct libnetapi_private_ctx *priv;
40         WERROR werr;
41
42         priv = talloc_get_type_abort(mem_ctx->private_data,
43                 struct libnetapi_private_ctx);
44
45         if (!r->in.domain) {
46                 return WERR_INVALID_PARAM;
47         }
48
49         werr = libnet_init_JoinCtx(mem_ctx, &j);
50         W_ERROR_NOT_OK_RETURN(werr);
51
52         j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
53         W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
54
55         if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
56                 NTSTATUS status;
57                 struct netr_DsRGetDCNameInfo *info = NULL;
58                 const char *dc = NULL;
59                 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
60                                  DS_WRITABLE_REQUIRED |
61                                  DS_RETURN_DNS_NAME;
62                 status = dsgetdcname(mem_ctx, priv->msg_ctx, r->in.domain,
63                                      NULL, NULL, flags, &info);
64                 if (!NT_STATUS_IS_OK(status)) {
65                         libnetapi_set_error_string(mem_ctx,
66                                 "%s", get_friendly_nt_error_msg(status));
67                         return ntstatus_to_werror(status);
68                 }
69
70                 dc = strip_hostname(info->dc_unc);
71                 j->in.dc_name = talloc_strdup(mem_ctx, dc);
72                 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
73         }
74
75         if (r->in.account_ou) {
76                 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
77                 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
78         }
79
80         if (r->in.account) {
81                 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
82                 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
83         }
84
85         if (r->in.password) {
86                 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
87                 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
88         }
89
90         j->in.join_flags = r->in.join_flags;
91         j->in.modify_config = true;
92         j->in.debug = true;
93
94         werr = libnet_Join(mem_ctx, j);
95         if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
96                 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
97         }
98         TALLOC_FREE(j);
99
100         return werr;
101 }
102
103 /****************************************************************
104 ****************************************************************/
105
106 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
107                        struct NetJoinDomain *r)
108 {
109         struct rpc_pipe_client *pipe_cli = NULL;
110         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
111         NTSTATUS status;
112         WERROR werr;
113         unsigned int old_timeout = 0;
114         struct dcerpc_binding_handle *b;
115
116         werr = libnetapi_open_pipe(ctx, r->in.server,
117                                    &ndr_table_wkssvc.syntax_id,
118                                    &pipe_cli);
119         if (!W_ERROR_IS_OK(werr)) {
120                 goto done;
121         }
122
123         b = pipe_cli->binding_handle;
124
125         if (r->in.password) {
126                 encode_wkssvc_join_password_buffer(ctx,
127                                                    r->in.password,
128                                                    &pipe_cli->auth->user_session_key,
129                                                    &encrypted_password);
130         }
131
132         old_timeout = rpccli_set_timeout(pipe_cli, 600000);
133
134         status = dcerpc_wkssvc_NetrJoinDomain2(b, talloc_tos(),
135                                                r->in.server,
136                                                r->in.domain,
137                                                r->in.account_ou,
138                                                r->in.account,
139                                                encrypted_password,
140                                                r->in.join_flags,
141                                                &werr);
142         if (!NT_STATUS_IS_OK(status)) {
143                 werr = ntstatus_to_werror(status);
144                 goto done;
145         }
146
147  done:
148         if (pipe_cli && old_timeout) {
149                 rpccli_set_timeout(pipe_cli, old_timeout);
150         }
151
152         return werr;
153 }
154 /****************************************************************
155 ****************************************************************/
156
157 WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
158                          struct NetUnjoinDomain *r)
159 {
160         struct libnet_UnjoinCtx *u = NULL;
161         struct dom_sid domain_sid;
162         const char *domain = NULL;
163         WERROR werr;
164         struct libnetapi_private_ctx *priv;
165
166         priv = talloc_get_type_abort(mem_ctx->private_data,
167                 struct libnetapi_private_ctx);
168
169         if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
170                 return WERR_SETUP_NOT_JOINED;
171         }
172
173         werr = libnet_init_UnjoinCtx(mem_ctx, &u);
174         W_ERROR_NOT_OK_RETURN(werr);
175
176         if (lp_realm()) {
177                 domain = lp_realm();
178         } else {
179                 domain = lp_workgroup();
180         }
181
182         if (r->in.server_name) {
183                 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
184                 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
185         } else {
186                 NTSTATUS status;
187                 struct netr_DsRGetDCNameInfo *info = NULL;
188                 const char *dc = NULL;
189                 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
190                                  DS_WRITABLE_REQUIRED |
191                                  DS_RETURN_DNS_NAME;
192                 status = dsgetdcname(mem_ctx, priv->msg_ctx, domain,
193                                      NULL, NULL, flags, &info);
194                 if (!NT_STATUS_IS_OK(status)) {
195                         libnetapi_set_error_string(mem_ctx,
196                                 "failed to find DC for domain %s: %s",
197                                 domain,
198                                 get_friendly_nt_error_msg(status));
199                         return ntstatus_to_werror(status);
200                 }
201
202                 dc = strip_hostname(info->dc_unc);
203                 u->in.dc_name = talloc_strdup(mem_ctx, dc);
204                 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
205
206                 u->in.domain_name = domain;
207         }
208
209         if (r->in.account) {
210                 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
211                 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
212         }
213
214         if (r->in.password) {
215                 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
216                 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
217         }
218
219         u->in.domain_name = domain;
220         u->in.unjoin_flags = r->in.unjoin_flags;
221         u->in.delete_machine_account = false;
222         u->in.modify_config = true;
223         u->in.debug = true;
224
225         u->in.domain_sid = &domain_sid;
226
227         werr = libnet_Unjoin(mem_ctx, u);
228         if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
229                 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
230         }
231         TALLOC_FREE(u);
232
233         return werr;
234 }
235
236 /****************************************************************
237 ****************************************************************/
238
239 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
240                          struct NetUnjoinDomain *r)
241 {
242         struct rpc_pipe_client *pipe_cli = NULL;
243         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
244         NTSTATUS status;
245         WERROR werr;
246         unsigned int old_timeout = 0;
247         struct dcerpc_binding_handle *b;
248
249         werr = libnetapi_open_pipe(ctx, r->in.server_name,
250                                    &ndr_table_wkssvc.syntax_id,
251                                    &pipe_cli);
252         if (!W_ERROR_IS_OK(werr)) {
253                 goto done;
254         }
255
256         b = pipe_cli->binding_handle;
257
258         if (r->in.password) {
259                 encode_wkssvc_join_password_buffer(ctx,
260                                                    r->in.password,
261                                                    &pipe_cli->auth->user_session_key,
262                                                    &encrypted_password);
263         }
264
265         old_timeout = rpccli_set_timeout(pipe_cli, 60000);
266
267         status = dcerpc_wkssvc_NetrUnjoinDomain2(b, talloc_tos(),
268                                                  r->in.server_name,
269                                                  r->in.account,
270                                                  encrypted_password,
271                                                  r->in.unjoin_flags,
272                                                  &werr);
273         if (!NT_STATUS_IS_OK(status)) {
274                 werr = ntstatus_to_werror(status);
275                 goto done;
276         }
277
278  done:
279         if (pipe_cli && old_timeout) {
280                 rpccli_set_timeout(pipe_cli, old_timeout);
281         }
282
283         return werr;
284 }
285
286 /****************************************************************
287 ****************************************************************/
288
289 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
290                                struct NetGetJoinInformation *r)
291 {
292         struct rpc_pipe_client *pipe_cli = NULL;
293         NTSTATUS status;
294         WERROR werr;
295         const char *buffer = NULL;
296         struct dcerpc_binding_handle *b;
297
298         werr = libnetapi_open_pipe(ctx, r->in.server_name,
299                                    &ndr_table_wkssvc.syntax_id,
300                                    &pipe_cli);
301         if (!W_ERROR_IS_OK(werr)) {
302                 goto done;
303         }
304
305         b = pipe_cli->binding_handle;
306
307         status = dcerpc_wkssvc_NetrGetJoinInformation(b, talloc_tos(),
308                                                       r->in.server_name,
309                                                       &buffer,
310                                                       (enum wkssvc_NetJoinStatus *)r->out.name_type,
311                                                       &werr);
312         if (!NT_STATUS_IS_OK(status)) {
313                 werr = ntstatus_to_werror(status);
314                 goto done;
315         }
316
317         if (!W_ERROR_IS_OK(werr)) {
318                 goto done;
319         }
320
321         *r->out.name_buffer = talloc_strdup(ctx, buffer);
322         W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
323
324  done:
325         return werr;
326 }
327
328 /****************************************************************
329 ****************************************************************/
330
331 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
332                                struct NetGetJoinInformation *r)
333 {
334         if ((lp_security() == SEC_ADS) && lp_realm()) {
335                 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
336         } else {
337                 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
338         }
339         if (!*r->out.name_buffer) {
340                 return WERR_NOMEM;
341         }
342
343         switch (lp_server_role()) {
344                 case ROLE_DOMAIN_MEMBER:
345                 case ROLE_DOMAIN_PDC:
346                 case ROLE_DOMAIN_BDC:
347                         *r->out.name_type = NetSetupDomainName;
348                         break;
349                 case ROLE_STANDALONE:
350                 default:
351                         *r->out.name_type = NetSetupWorkgroupName;
352                         break;
353         }
354
355         return WERR_OK;
356 }
357
358 /****************************************************************
359 ****************************************************************/
360
361 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
362                            struct NetGetJoinableOUs *r)
363 {
364 #ifdef WITH_ADS
365         NTSTATUS status;
366         ADS_STATUS ads_status;
367         ADS_STRUCT *ads = NULL;
368         struct netr_DsRGetDCNameInfo *info = NULL;
369         const char *dc = NULL;
370         uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
371                          DS_RETURN_DNS_NAME;
372         struct libnetapi_private_ctx *priv;
373
374         priv = talloc_get_type_abort(ctx->private_data,
375                 struct libnetapi_private_ctx);
376
377         status = dsgetdcname(ctx, priv->msg_ctx, r->in.domain,
378                              NULL, NULL, flags, &info);
379         if (!NT_STATUS_IS_OK(status)) {
380                 libnetapi_set_error_string(ctx, "%s",
381                         get_friendly_nt_error_msg(status));
382                 return ntstatus_to_werror(status);
383         }
384
385         dc = strip_hostname(info->dc_unc);
386
387         ads = ads_init(info->domain_name, info->domain_name, dc);
388         if (!ads) {
389                 return WERR_GENERAL_FAILURE;
390         }
391
392         SAFE_FREE(ads->auth.user_name);
393         if (r->in.account) {
394                 ads->auth.user_name = SMB_STRDUP(r->in.account);
395         } else if (ctx->username) {
396                 ads->auth.user_name = SMB_STRDUP(ctx->username);
397         }
398
399         SAFE_FREE(ads->auth.password);
400         if (r->in.password) {
401                 ads->auth.password = SMB_STRDUP(r->in.password);
402         } else if (ctx->password) {
403                 ads->auth.password = SMB_STRDUP(ctx->password);
404         }
405
406         ads_status = ads_connect_user_creds(ads);
407         if (!ADS_ERR_OK(ads_status)) {
408                 ads_destroy(&ads);
409                 return WERR_DEFAULT_JOIN_REQUIRED;
410         }
411
412         ads_status = ads_get_joinable_ous(ads, ctx,
413                                           (char ***)r->out.ous,
414                                           (size_t *)r->out.ou_count);
415         if (!ADS_ERR_OK(ads_status)) {
416                 ads_destroy(&ads);
417                 return WERR_DEFAULT_JOIN_REQUIRED;
418         }
419
420         ads_destroy(&ads);
421         return WERR_OK;
422 #else
423         return WERR_NOT_SUPPORTED;
424 #endif
425 }
426
427 /****************************************************************
428 ****************************************************************/
429
430 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
431                            struct NetGetJoinableOUs *r)
432 {
433         struct rpc_pipe_client *pipe_cli = NULL;
434         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
435         NTSTATUS status;
436         WERROR werr;
437         struct dcerpc_binding_handle *b;
438
439         werr = libnetapi_open_pipe(ctx, r->in.server_name,
440                                    &ndr_table_wkssvc.syntax_id,
441                                    &pipe_cli);
442         if (!W_ERROR_IS_OK(werr)) {
443                 goto done;
444         }
445
446         b = pipe_cli->binding_handle;
447
448         if (r->in.password) {
449                 encode_wkssvc_join_password_buffer(ctx,
450                                                    r->in.password,
451                                                    &pipe_cli->auth->user_session_key,
452                                                    &encrypted_password);
453         }
454
455         status = dcerpc_wkssvc_NetrGetJoinableOus2(b, talloc_tos(),
456                                                    r->in.server_name,
457                                                    r->in.domain,
458                                                    r->in.account,
459                                                    encrypted_password,
460                                                    r->out.ou_count,
461                                                    r->out.ous,
462                                                    &werr);
463         if (!NT_STATUS_IS_OK(status)) {
464                 werr = ntstatus_to_werror(status);
465                 goto done;
466         }
467
468  done:
469         return werr;
470 }
471
472 /****************************************************************
473 ****************************************************************/
474
475 WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
476                                   struct NetRenameMachineInDomain *r)
477 {
478         struct rpc_pipe_client *pipe_cli = NULL;
479         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
480         NTSTATUS status;
481         WERROR werr;
482         struct dcerpc_binding_handle *b;
483
484         werr = libnetapi_open_pipe(ctx, r->in.server_name,
485                                    &ndr_table_wkssvc.syntax_id,
486                                    &pipe_cli);
487         if (!W_ERROR_IS_OK(werr)) {
488                 goto done;
489         }
490
491         b = pipe_cli->binding_handle;
492
493         if (r->in.password) {
494                 encode_wkssvc_join_password_buffer(ctx,
495                                                    r->in.password,
496                                                    &pipe_cli->auth->user_session_key,
497                                                    &encrypted_password);
498         }
499
500         status = dcerpc_wkssvc_NetrRenameMachineInDomain2(b, talloc_tos(),
501                                                           r->in.server_name,
502                                                           r->in.new_machine_name,
503                                                           r->in.account,
504                                                           encrypted_password,
505                                                           r->in.rename_options,
506                                                           &werr);
507         if (!NT_STATUS_IS_OK(status)) {
508                 werr = ntstatus_to_werror(status);
509                 goto done;
510         }
511
512  done:
513         return werr;
514 }
515
516 /****************************************************************
517 ****************************************************************/
518
519 WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
520                                   struct NetRenameMachineInDomain *r)
521 {
522         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);
523 }