netapi: make libnetapi_open_ipc_connection static.
[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
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 "libnet/libnet.h"
27
28 /****************************************************************
29 ****************************************************************/
30
31 WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
32                        struct NetJoinDomain *r)
33 {
34         struct libnet_JoinCtx *j = NULL;
35         WERROR werr;
36
37         if (!r->in.domain) {
38                 return WERR_INVALID_PARAM;
39         }
40
41         werr = libnet_init_JoinCtx(mem_ctx, &j);
42         W_ERROR_NOT_OK_RETURN(werr);
43
44         j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
45         W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
46
47         if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
48                 NTSTATUS status;
49                 struct netr_DsRGetDCNameInfo *info = NULL;
50                 const char *dc = NULL;
51                 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
52                                  DS_WRITABLE_REQUIRED |
53                                  DS_RETURN_DNS_NAME;
54                 status = dsgetdcname(mem_ctx, NULL, r->in.domain,
55                                      NULL, NULL, flags, &info);
56                 if (!NT_STATUS_IS_OK(status)) {
57                         libnetapi_set_error_string(mem_ctx,
58                                 "%s", get_friendly_nt_error_msg(status));
59                         return ntstatus_to_werror(status);
60                 }
61
62                 dc = strip_hostname(info->dc_unc);
63                 j->in.dc_name = talloc_strdup(mem_ctx, dc);
64                 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
65         }
66
67         if (r->in.account_ou) {
68                 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
69                 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
70         }
71
72         if (r->in.account) {
73                 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
74                 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
75         }
76
77         if (r->in.password) {
78                 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
79                 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
80         }
81
82         j->in.join_flags = r->in.join_flags;
83         j->in.modify_config = true;
84         j->in.debug = true;
85
86         werr = libnet_Join(mem_ctx, j);
87         if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
88                 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
89         }
90         TALLOC_FREE(j);
91
92         return werr;
93 }
94
95 /****************************************************************
96 ****************************************************************/
97
98 WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
99                        struct NetJoinDomain *r)
100 {
101         struct cli_state *cli = NULL;
102         struct rpc_pipe_client *pipe_cli = NULL;
103         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
104         NTSTATUS status;
105         WERROR werr;
106         unsigned int old_timeout = 0;
107
108         werr = libnetapi_open_pipe(ctx, r->in.server,
109                                    &ndr_table_wkssvc.syntax_id,
110                                    &cli,
111                                    &pipe_cli);
112         if (!W_ERROR_IS_OK(werr)) {
113                 goto done;
114         }
115
116         if (r->in.password) {
117                 encode_wkssvc_join_password_buffer(ctx,
118                                                    r->in.password,
119                                                    &cli->user_session_key,
120                                                    &encrypted_password);
121         }
122
123         old_timeout = cli_set_timeout(cli, 600000);
124
125         status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, ctx,
126                                                r->in.server,
127                                                r->in.domain,
128                                                r->in.account_ou,
129                                                r->in.account,
130                                                encrypted_password,
131                                                r->in.join_flags,
132                                                &werr);
133         if (!NT_STATUS_IS_OK(status)) {
134                 werr = ntstatus_to_werror(status);
135                 goto done;
136         }
137
138  done:
139         if (cli) {
140                 if (old_timeout) {
141                         cli_set_timeout(cli, old_timeout);
142                 }
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.modify_config = true;
211         u->in.debug = true;
212
213         u->in.domain_sid = &domain_sid;
214
215         werr = libnet_Unjoin(mem_ctx, u);
216         if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
217                 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
218         }
219         TALLOC_FREE(u);
220
221         return werr;
222 }
223
224 /****************************************************************
225 ****************************************************************/
226
227 WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
228                          struct NetUnjoinDomain *r)
229 {
230         struct cli_state *cli = NULL;
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                                    &cli,
240                                    &pipe_cli);
241         if (!W_ERROR_IS_OK(werr)) {
242                 goto done;
243         }
244
245         if (r->in.password) {
246                 encode_wkssvc_join_password_buffer(ctx,
247                                                    r->in.password,
248                                                    &cli->user_session_key,
249                                                    &encrypted_password);
250         }
251
252         old_timeout = cli_set_timeout(cli, 60000);
253
254         status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
255                                                  r->in.server_name,
256                                                  r->in.account,
257                                                  encrypted_password,
258                                                  r->in.unjoin_flags,
259                                                  &werr);
260         if (!NT_STATUS_IS_OK(status)) {
261                 werr = ntstatus_to_werror(status);
262                 goto done;
263         }
264
265  done:
266         if (cli) {
267                 if (old_timeout) {
268                         cli_set_timeout(cli, old_timeout);
269                 }
270         }
271
272         return werr;
273 }
274
275 /****************************************************************
276 ****************************************************************/
277
278 WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
279                                struct NetGetJoinInformation *r)
280 {
281         struct cli_state *cli = NULL;
282         struct rpc_pipe_client *pipe_cli = NULL;
283         NTSTATUS status;
284         WERROR werr;
285         const char *buffer = NULL;
286
287         werr = libnetapi_open_pipe(ctx, r->in.server_name,
288                                    &ndr_table_wkssvc.syntax_id,
289                                    &cli,
290                                    &pipe_cli);
291         if (!W_ERROR_IS_OK(werr)) {
292                 goto done;
293         }
294
295         status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
296                                                       r->in.server_name,
297                                                       &buffer,
298                                                       (enum wkssvc_NetJoinStatus *)r->out.name_type,
299                                                       &werr);
300         if (!NT_STATUS_IS_OK(status)) {
301                 werr = ntstatus_to_werror(status);
302                 goto done;
303         }
304
305         *r->out.name_buffer = talloc_strdup(ctx, buffer);
306         W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
307
308  done:
309         return werr;
310 }
311
312 /****************************************************************
313 ****************************************************************/
314
315 WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
316                                struct NetGetJoinInformation *r)
317 {
318         if ((lp_security() == SEC_ADS) && lp_realm()) {
319                 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
320         } else {
321                 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
322         }
323         if (!*r->out.name_buffer) {
324                 return WERR_NOMEM;
325         }
326
327         switch (lp_server_role()) {
328                 case ROLE_DOMAIN_MEMBER:
329                 case ROLE_DOMAIN_PDC:
330                 case ROLE_DOMAIN_BDC:
331                         *r->out.name_type = NetSetupDomainName;
332                         break;
333                 case ROLE_STANDALONE:
334                 default:
335                         *r->out.name_type = NetSetupWorkgroupName;
336                         break;
337         }
338
339         return WERR_OK;
340 }
341
342 /****************************************************************
343 ****************************************************************/
344
345 WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
346                            struct NetGetJoinableOUs *r)
347 {
348 #ifdef WITH_ADS
349         NTSTATUS status;
350         ADS_STATUS ads_status;
351         ADS_STRUCT *ads = NULL;
352         struct netr_DsRGetDCNameInfo *info = NULL;
353         const char *dc = NULL;
354         uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
355                          DS_RETURN_DNS_NAME;
356
357         status = dsgetdcname(ctx, NULL, r->in.domain,
358                              NULL, NULL, flags, &info);
359         if (!NT_STATUS_IS_OK(status)) {
360                 libnetapi_set_error_string(ctx, "%s",
361                         get_friendly_nt_error_msg(status));
362                 return ntstatus_to_werror(status);
363         }
364
365         dc = strip_hostname(info->dc_unc);
366
367         ads = ads_init(r->in.domain, r->in.domain, dc);
368         if (!ads) {
369                 return WERR_GENERAL_FAILURE;
370         }
371
372         SAFE_FREE(ads->auth.user_name);
373         if (r->in.account) {
374                 ads->auth.user_name = SMB_STRDUP(r->in.account);
375         } else if (ctx->username) {
376                 ads->auth.user_name = SMB_STRDUP(ctx->username);
377         }
378
379         SAFE_FREE(ads->auth.password);
380         if (r->in.password) {
381                 ads->auth.password = SMB_STRDUP(r->in.password);
382         } else if (ctx->password) {
383                 ads->auth.password = SMB_STRDUP(ctx->password);
384         }
385
386         ads_status = ads_connect_user_creds(ads);
387         if (!ADS_ERR_OK(ads_status)) {
388                 ads_destroy(&ads);
389                 return WERR_DEFAULT_JOIN_REQUIRED;
390         }
391
392         ads_status = ads_get_joinable_ous(ads, ctx,
393                                           (char ***)r->out.ous,
394                                           (size_t *)r->out.ou_count);
395         if (!ADS_ERR_OK(ads_status)) {
396                 ads_destroy(&ads);
397                 return WERR_DEFAULT_JOIN_REQUIRED;
398         }
399
400         ads_destroy(&ads);
401         return WERR_OK;
402 #else
403         return WERR_NOT_SUPPORTED;
404 #endif
405 }
406
407 /****************************************************************
408 ****************************************************************/
409
410 WERROR NetGetJoinableOUs_r(struct libnetapi_ctx *ctx,
411                            struct NetGetJoinableOUs *r)
412 {
413         struct cli_state *cli = NULL;
414         struct rpc_pipe_client *pipe_cli = NULL;
415         struct wkssvc_PasswordBuffer *encrypted_password = NULL;
416         NTSTATUS status;
417         WERROR werr;
418
419         werr = libnetapi_open_pipe(ctx, r->in.server_name,
420                                    &ndr_table_wkssvc.syntax_id,
421                                    &cli,
422                                    &pipe_cli);
423         if (!W_ERROR_IS_OK(werr)) {
424                 goto done;
425         }
426
427         if (r->in.password) {
428                 encode_wkssvc_join_password_buffer(ctx,
429                                                    r->in.password,
430                                                    &cli->user_session_key,
431                                                    &encrypted_password);
432         }
433
434         status = rpccli_wkssvc_NetrGetJoinableOus2(pipe_cli, ctx,
435                                                    r->in.server_name,
436                                                    r->in.domain,
437                                                    r->in.account,
438                                                    encrypted_password,
439                                                    r->out.ou_count,
440                                                    r->out.ous,
441                                                    &werr);
442         if (!NT_STATUS_IS_OK(status)) {
443                 werr = ntstatus_to_werror(status);
444                 goto done;
445         }
446
447  done:
448         if (cli) {
449                 cli_shutdown(cli);
450         }
451
452         return werr;
453 }