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