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