werror: replace WERR_SETUP_NOT_JOINED with WERR_NERR_SETUPNOTJOINED in source3/lib...
[metze/samba/wip.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 "rpc_client/cli_pipe.h"
31 #include "secrets.h"
32
33 /****************************************************************
34 ****************************************************************/
35
36 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
37                        struct NetJoinDomain *r)
38 {
39         struct libnet_JoinCtx *j = NULL;
40         struct libnetapi_private_ctx *priv;
41         WERROR werr;
42
43         priv = talloc_get_type_abort(mem_ctx->private_data,
44                 struct libnetapi_private_ctx);
45
46         if (!r->in.domain) {
47                 return WERR_INVALID_PARAMETER;
48         }
49
50         werr = libnet_init_JoinCtx(mem_ctx, &j);
51         W_ERROR_NOT_OK_RETURN(werr);
52
53         j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
54         W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
55
56         if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
57                 NTSTATUS status;
58                 struct netr_DsRGetDCNameInfo *info = NULL;
59                 const char *dc = NULL;
60                 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
61                                  DS_WRITABLE_REQUIRED |
62                                  DS_RETURN_DNS_NAME;
63                 status = dsgetdcname(mem_ctx, priv->msg_ctx, r->in.domain,
64                                      NULL, NULL, flags, &info);
65                 if (!NT_STATUS_IS_OK(status)) {
66                         libnetapi_set_error_string(mem_ctx,
67                                 "%s", get_friendly_nt_error_msg(status));
68                         return ntstatus_to_werror(status);
69                 }
70
71                 dc = strip_hostname(info->dc_unc);
72                 j->in.dc_name = talloc_strdup(mem_ctx, dc);
73                 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
74         }
75
76         if (r->in.account_ou) {
77                 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
78                 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
79         }
80
81         if (r->in.account) {
82                 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
83                 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
84         }
85
86         if (r->in.password) {
87                 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
88                 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
89         }
90
91         j->in.join_flags = r->in.join_flags;
92         j->in.modify_config = true;
93         j->in.debug = true;
94
95         werr = libnet_Join(mem_ctx, j);
96         if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
97                 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
98         }
99         TALLOC_FREE(j);
100
101         return werr;
102 }
103
104 /****************************************************************
105 ****************************************************************/
106
107 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
108                        struct NetJoinDomain *r)
109 {
110         struct rpc_pipe_client *pipe_cli = NULL;
111         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
112         NTSTATUS status;
113         WERROR werr;
114         unsigned int old_timeout = 0;
115         struct dcerpc_binding_handle *b;
116         DATA_BLOB session_key;
117
118         if (IS_DC) {
119                 return WERR_SETUP_DOMAIN_CONTROLLER;
120         }
121
122         werr = libnetapi_open_pipe(ctx, r->in.server,
123                                    &ndr_table_wkssvc,
124                                    &pipe_cli);
125         if (!W_ERROR_IS_OK(werr)) {
126                 goto done;
127         }
128
129         b = pipe_cli->binding_handle;
130
131         if (r->in.password) {
132
133                 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
134                 if (!NT_STATUS_IS_OK(status)) {
135                         werr = ntstatus_to_werror(status);
136                         goto done;
137                 }
138
139                 encode_wkssvc_join_password_buffer(ctx,
140                                                    r->in.password,
141                                                    &session_key,
142                                                    &encrypted_password);
143         }
144
145         old_timeout = rpccli_set_timeout(pipe_cli, 600000);
146
147         status = dcerpc_wkssvc_NetrJoinDomain2(b, talloc_tos(),
148                                                r->in.server,
149                                                r->in.domain,
150                                                r->in.account_ou,
151                                                r->in.account,
152                                                encrypted_password,
153                                                r->in.join_flags,
154                                                &werr);
155         if (!NT_STATUS_IS_OK(status)) {
156                 werr = ntstatus_to_werror(status);
157                 goto done;
158         }
159
160  done:
161         if (pipe_cli && old_timeout) {
162                 rpccli_set_timeout(pipe_cli, old_timeout);
163         }
164
165         return werr;
166 }
167 /****************************************************************
168 ****************************************************************/
169
170 WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
171                          struct NetUnjoinDomain *r)
172 {
173         struct libnet_UnjoinCtx *u = NULL;
174         struct dom_sid domain_sid;
175         const char *domain = NULL;
176         WERROR werr;
177         struct libnetapi_private_ctx *priv;
178         const char *realm = lp_realm();
179
180         priv = talloc_get_type_abort(mem_ctx->private_data,
181                 struct libnetapi_private_ctx);
182
183         if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
184                 return WERR_NERR_SETUPNOTJOINED;
185         }
186
187         werr = libnet_init_UnjoinCtx(mem_ctx, &u);
188         W_ERROR_NOT_OK_RETURN(werr);
189
190         if (realm[0] != '\0') {
191                 domain = realm;
192         } else {
193                 domain = lp_workgroup();
194         }
195
196         if (r->in.server_name) {
197                 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
198                 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
199         } else {
200                 NTSTATUS status;
201                 struct netr_DsRGetDCNameInfo *info = NULL;
202                 const char *dc = NULL;
203                 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
204                                  DS_WRITABLE_REQUIRED |
205                                  DS_RETURN_DNS_NAME;
206                 status = dsgetdcname(mem_ctx, priv->msg_ctx, domain,
207                                      NULL, NULL, flags, &info);
208                 if (!NT_STATUS_IS_OK(status)) {
209                         libnetapi_set_error_string(mem_ctx,
210                                 "failed to find DC for domain %s: %s",
211                                 domain,
212                                 get_friendly_nt_error_msg(status));
213                         return ntstatus_to_werror(status);
214                 }
215
216                 dc = strip_hostname(info->dc_unc);
217                 u->in.dc_name = talloc_strdup(mem_ctx, dc);
218                 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
219
220                 u->in.domain_name = domain;
221         }
222
223         if (r->in.account) {
224                 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
225                 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
226         }
227
228         if (r->in.password) {
229                 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
230                 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
231         }
232
233         u->in.domain_name = domain;
234         u->in.unjoin_flags = r->in.unjoin_flags;
235         u->in.delete_machine_account = false;
236         u->in.modify_config = true;
237         u->in.debug = true;
238
239         u->in.domain_sid = &domain_sid;
240
241         werr = libnet_Unjoin(mem_ctx, u);
242         if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
243                 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
244         }
245         TALLOC_FREE(u);
246
247         return werr;
248 }
249
250 /****************************************************************
251 ****************************************************************/
252
253 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
254                          struct NetUnjoinDomain *r)
255 {
256         struct rpc_pipe_client *pipe_cli = NULL;
257         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
258         NTSTATUS status;
259         WERROR werr;
260         unsigned int old_timeout = 0;
261         struct dcerpc_binding_handle *b;
262         DATA_BLOB session_key;
263
264         werr = libnetapi_open_pipe(ctx, r->in.server_name,
265                                    &ndr_table_wkssvc,
266                                    &pipe_cli);
267         if (!W_ERROR_IS_OK(werr)) {
268                 goto done;
269         }
270
271         b = pipe_cli->binding_handle;
272
273         if (r->in.password) {
274
275                 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
276                 if (!NT_STATUS_IS_OK(status)) {
277                         werr = ntstatus_to_werror(status);
278                         goto done;
279                 }
280
281                 encode_wkssvc_join_password_buffer(ctx,
282                                                    r->in.password,
283                                                    &session_key,
284                                                    &encrypted_password);
285         }
286
287         old_timeout = rpccli_set_timeout(pipe_cli, 60000);
288
289         status = dcerpc_wkssvc_NetrUnjoinDomain2(b, talloc_tos(),
290                                                  r->in.server_name,
291                                                  r->in.account,
292                                                  encrypted_password,
293                                                  r->in.unjoin_flags,
294                                                  &werr);
295         if (!NT_STATUS_IS_OK(status)) {
296                 werr = ntstatus_to_werror(status);
297                 goto done;
298         }
299
300  done:
301         if (pipe_cli && old_timeout) {
302                 rpccli_set_timeout(pipe_cli, old_timeout);
303         }
304
305         return werr;
306 }
307
308 /****************************************************************
309 ****************************************************************/
310
311 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
312                                struct NetGetJoinInformation *r)
313 {
314         struct rpc_pipe_client *pipe_cli = NULL;
315         NTSTATUS status;
316         WERROR werr;
317         const char *buffer = NULL;
318         struct dcerpc_binding_handle *b;
319
320         werr = libnetapi_open_pipe(ctx, r->in.server_name,
321                                    &ndr_table_wkssvc,
322                                    &pipe_cli);
323         if (!W_ERROR_IS_OK(werr)) {
324                 goto done;
325         }
326
327         b = pipe_cli->binding_handle;
328
329         status = dcerpc_wkssvc_NetrGetJoinInformation(b, talloc_tos(),
330                                                       r->in.server_name,
331                                                       &buffer,
332                                                       (enum wkssvc_NetJoinStatus *)r->out.name_type,
333                                                       &werr);
334         if (!NT_STATUS_IS_OK(status)) {
335                 werr = ntstatus_to_werror(status);
336                 goto done;
337         }
338
339         if (!W_ERROR_IS_OK(werr)) {
340                 goto done;
341         }
342
343         *r->out.name_buffer = talloc_strdup(ctx, buffer);
344         W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
345
346  done:
347         return werr;
348 }
349
350 /****************************************************************
351 ****************************************************************/
352
353 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
354                                struct NetGetJoinInformation *r)
355 {
356         const char *realm = lp_realm();
357
358         if ((lp_security() == SEC_ADS) && realm[0] != '\0') {
359                 *r->out.name_buffer = talloc_strdup(ctx, realm);
360         } else {
361                 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
362         }
363         if (!*r->out.name_buffer) {
364                 return WERR_NOT_ENOUGH_MEMORY;
365         }
366
367         switch (lp_server_role()) {
368                 case ROLE_DOMAIN_MEMBER:
369                 case ROLE_DOMAIN_PDC:
370                 case ROLE_DOMAIN_BDC:
371                         *r->out.name_type = NetSetupDomainName;
372                         break;
373                 case ROLE_STANDALONE:
374                 default:
375                         *r->out.name_type = NetSetupWorkgroupName;
376                         break;
377         }
378
379         return WERR_OK;
380 }
381
382 /****************************************************************
383 ****************************************************************/
384
385 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
386                            struct NetGetJoinableOUs *r)
387 {
388 #ifdef HAVE_ADS
389         NTSTATUS status;
390         ADS_STATUS ads_status;
391         ADS_STRUCT *ads = NULL;
392         struct netr_DsRGetDCNameInfo *info = NULL;
393         const char *dc = NULL;
394         uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
395                          DS_RETURN_DNS_NAME;
396         struct libnetapi_private_ctx *priv;
397         char **p;
398         size_t s;
399
400         priv = talloc_get_type_abort(ctx->private_data,
401                 struct libnetapi_private_ctx);
402
403         status = dsgetdcname(ctx, priv->msg_ctx, r->in.domain,
404                              NULL, NULL, flags, &info);
405         if (!NT_STATUS_IS_OK(status)) {
406                 libnetapi_set_error_string(ctx, "%s",
407                         get_friendly_nt_error_msg(status));
408                 return ntstatus_to_werror(status);
409         }
410
411         dc = strip_hostname(info->dc_unc);
412
413         ads = ads_init(info->domain_name, info->domain_name, dc);
414         if (!ads) {
415                 return WERR_GEN_FAILURE;
416         }
417
418         SAFE_FREE(ads->auth.user_name);
419         if (r->in.account) {
420                 ads->auth.user_name = SMB_STRDUP(r->in.account);
421         } else if (ctx->username) {
422                 ads->auth.user_name = SMB_STRDUP(ctx->username);
423         }
424
425         SAFE_FREE(ads->auth.password);
426         if (r->in.password) {
427                 ads->auth.password = SMB_STRDUP(r->in.password);
428         } else if (ctx->password) {
429                 ads->auth.password = SMB_STRDUP(ctx->password);
430         }
431
432         ads_status = ads_connect_user_creds(ads);
433         if (!ADS_ERR_OK(ads_status)) {
434                 ads_destroy(&ads);
435                 return WERR_DEFAULT_JOIN_REQUIRED;
436         }
437
438         ads_status = ads_get_joinable_ous(ads, ctx, &p, &s);
439         if (!ADS_ERR_OK(ads_status)) {
440                 ads_destroy(&ads);
441                 return WERR_DEFAULT_JOIN_REQUIRED;
442         }
443         *r->out.ous = discard_const_p(const char *, p);
444         *r->out.ou_count = s;
445
446         ads_destroy(&ads);
447         return WERR_OK;
448 #else
449         return WERR_NOT_SUPPORTED;
450 #endif
451 }
452
453 /****************************************************************
454 ****************************************************************/
455
456 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
457                            struct NetGetJoinableOUs *r)
458 {
459         struct rpc_pipe_client *pipe_cli = NULL;
460         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
461         NTSTATUS status;
462         WERROR werr;
463         struct dcerpc_binding_handle *b;
464         DATA_BLOB session_key;
465
466         werr = libnetapi_open_pipe(ctx, r->in.server_name,
467                                    &ndr_table_wkssvc,
468                                    &pipe_cli);
469         if (!W_ERROR_IS_OK(werr)) {
470                 goto done;
471         }
472
473         b = pipe_cli->binding_handle;
474
475         if (r->in.password) {
476
477                 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
478                 if (!NT_STATUS_IS_OK(status)) {
479                         werr = ntstatus_to_werror(status);
480                         goto done;
481                 }
482
483                 encode_wkssvc_join_password_buffer(ctx,
484                                                    r->in.password,
485                                                    &session_key,
486                                                    &encrypted_password);
487         }
488
489         status = dcerpc_wkssvc_NetrGetJoinableOus2(b, talloc_tos(),
490                                                    r->in.server_name,
491                                                    r->in.domain,
492                                                    r->in.account,
493                                                    encrypted_password,
494                                                    r->out.ou_count,
495                                                    r->out.ous,
496                                                    &werr);
497         if (!NT_STATUS_IS_OK(status)) {
498                 werr = ntstatus_to_werror(status);
499                 goto done;
500         }
501
502  done:
503         return werr;
504 }
505
506 /****************************************************************
507 ****************************************************************/
508
509 WERROR NetRenameMachineInDomain_r(struct libnetapi_ctx *ctx,
510                                   struct NetRenameMachineInDomain *r)
511 {
512         struct rpc_pipe_client *pipe_cli = NULL;
513         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
514         NTSTATUS status;
515         WERROR werr;
516         struct dcerpc_binding_handle *b;
517         DATA_BLOB session_key;
518
519         werr = libnetapi_open_pipe(ctx, r->in.server_name,
520                                    &ndr_table_wkssvc,
521                                    &pipe_cli);
522         if (!W_ERROR_IS_OK(werr)) {
523                 goto done;
524         }
525
526         b = pipe_cli->binding_handle;
527
528         if (r->in.password) {
529
530                 status = cli_get_session_key(talloc_tos(), pipe_cli, &session_key);
531                 if (!NT_STATUS_IS_OK(status)) {
532                         werr = ntstatus_to_werror(status);
533                         goto done;
534                 }
535
536                 encode_wkssvc_join_password_buffer(ctx,
537                                                    r->in.password,
538                                                    &session_key,
539                                                    &encrypted_password);
540         }
541
542         status = dcerpc_wkssvc_NetrRenameMachineInDomain2(b, talloc_tos(),
543                                                           r->in.server_name,
544                                                           r->in.new_machine_name,
545                                                           r->in.account,
546                                                           encrypted_password,
547                                                           r->in.rename_options,
548                                                           &werr);
549         if (!NT_STATUS_IS_OK(status)) {
550                 werr = ntstatus_to_werror(status);
551                 goto done;
552         }
553
554  done:
555         return werr;
556 }
557
558 /****************************************************************
559 ****************************************************************/
560
561 WERROR NetRenameMachineInDomain_l(struct libnetapi_ctx *ctx,
562                                   struct NetRenameMachineInDomain *r)
563 {
564         LIBNETAPI_REDIRECT_TO_LOCALHOST(ctx, r, NetRenameMachineInDomain);
565 }