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