Missed on instance of external creds.
[samba.git] / source / lib / netapi / joindomain.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  NetApi Join Support
4  *  Copyright (C) Guenther Deschner 2007
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 "lib/netapi/joindomain.h"
22
23 static WERROR NetJoinDomainLocal(TALLOC_CTX *mem_ctx,
24                                  const char *server_name,
25                                  const char *domain_name,
26                                  const char *account_ou,
27                                  const char *Account,
28                                  const char *password,
29                                  uint32_t join_flags)
30 {
31         struct libnet_JoinCtx *r = NULL;
32         WERROR werr;
33
34         werr = libnet_init_JoinCtx(mem_ctx, &r);
35         W_ERROR_NOT_OK_RETURN(werr);
36
37         if (!server_name || !domain_name) {
38                 return WERR_INVALID_PARAM;
39         }
40
41         r->in.server_name = talloc_strdup(mem_ctx, server_name);
42         W_ERROR_HAVE_NO_MEMORY(r->in.server_name);
43
44         r->in.domain_name = talloc_strdup(mem_ctx, domain_name);
45         W_ERROR_HAVE_NO_MEMORY(r->in.domain_name);
46
47         if (account_ou) {
48                 r->in.account_ou = talloc_strdup(mem_ctx, account_ou);
49                 W_ERROR_HAVE_NO_MEMORY(r->in.account_ou);
50         }
51
52         if (Account) {
53                 r->in.admin_account = talloc_strdup(mem_ctx, Account);
54                 W_ERROR_HAVE_NO_MEMORY(r->in.admin_account);
55         }
56
57         if (password) {
58                 r->in.password = talloc_strdup(mem_ctx, password);
59                 W_ERROR_HAVE_NO_MEMORY(r->in.password);
60         }
61
62         r->in.join_flags = join_flags;
63         r->in.modify_config = true;
64
65         return libnet_Join(mem_ctx, r);
66 }
67
68 static WERROR NetJoinDomainRemote(TALLOC_CTX *mem_ctx,
69                                   const char *server_name,
70                                   const char *domain_name,
71                                   const char *account_ou,
72                                   const char *Account,
73                                   const char *password,
74                                   uint32_t join_flags)
75 {
76         struct cli_state *cli = NULL;
77         struct rpc_pipe_client *pipe_cli = NULL;
78         struct wkssvc_PasswordBuffer encrypted_password;
79         NTSTATUS status;
80         WERROR werr;
81         unsigned int old_timeout = 0;
82
83         ZERO_STRUCT(encrypted_password);
84
85         status = cli_full_connection(&cli, NULL, server_name,
86                                      NULL, 0,
87                                      "IPC$", "IPC",
88                                      ctx->username,
89                                      ctx->workgroup,
90                                      ctx->password,
91                                      0, Undefined, NULL);
92
93         if (!NT_STATUS_IS_OK(status)) {
94                 werr = ntstatus_to_werror(status);
95                 goto done;
96         }
97
98         old_timeout = cli_set_timeout(cli, 60000);
99
100         pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
101                                             &status);
102         if (!pipe_cli) {
103                 werr = ntstatus_to_werror(status);
104                 goto done;
105         };
106
107         if (password) {
108                 encode_wkssvc_join_password_buffer(mem_ctx,
109                                                    password,
110                                                    &cli->user_session_key,
111                                                    &encrypted_password);
112         }
113
114         old_timeout = cli_set_timeout(cli, 60000);
115
116         status = rpccli_wkssvc_NetrJoinDomain2(pipe_cli, mem_ctx,
117                                                server_name, domain_name,
118                                                account_ou, Account,
119                                                &encrypted_password,
120                                                join_flags, &werr);
121         if (!NT_STATUS_IS_OK(status)) {
122                 werr = ntstatus_to_werror(status);
123                 goto done;
124         }
125
126  done:
127         if (cli) {
128                 cli_set_timeout(cli, old_timeout);
129                 cli_shutdown(cli);
130         }
131
132         return werr;
133 }
134
135 WERROR NetJoinDomain(const char *server_name,
136                      const char *domain_name,
137                      const char *account_ou,
138                      const char *Account,
139                      const char *password,
140                      uint32_t join_flags)
141 {
142         TALLOC_CTX *mem_ctx = NULL;
143         WERROR werr;
144
145         mem_ctx = talloc_init("NetJoinDomain");
146         if (!mem_ctx) {
147                 werr = WERR_NOMEM;
148                 goto done;
149         }
150
151         if (!domain_name) {
152                 werr = WERR_INVALID_PARAM;
153                 goto done;
154         }
155
156         if (!server_name || is_myname_or_ipaddr(server_name)) {
157
158                 const char *dc = NULL;
159
160                 /* FIXME: DsGetDcName */
161                 if (server_name == NULL) {
162                         dc = domain_name;
163                 } else {
164                         dc = domain_name;
165                 }
166
167                 werr = NetJoinDomainLocal(mem_ctx,
168                                           dc,
169                                           domain_name,
170                                           account_ou,
171                                           Account,
172                                           password,
173                                           join_flags);
174
175                 goto done;
176         }
177
178         werr = NetJoinDomainRemote(mem_ctx,
179                                    server_name,
180                                    domain_name,
181                                    account_ou,
182                                    Account,
183                                    password,
184                                    join_flags);
185 done:
186         TALLOC_FREE(mem_ctx);
187
188         return werr;
189 }
190
191 WERROR NetUnjoinDomain(const char *server_name,
192                        const char *account,
193                        const char *password,
194                        uint32_t unjoin_flags)
195 {
196         TALLOC_CTX *mem_ctx = NULL;
197         struct cli_state *cli = NULL;
198         struct rpc_pipe_client *pipe_cli = NULL;
199         struct wkssvc_PasswordBuffer encrypted_password;
200         NTSTATUS status;
201         WERROR werr;
202         unsigned int old_timeout = 0;
203
204         ZERO_STRUCT(encrypted_password);
205
206         mem_ctx = talloc_init("NetUnjoinDomain");
207         if (!mem_ctx) {
208                 werr = WERR_NOMEM;
209                 goto done;
210         }
211
212         if (!server_name || is_myname_or_ipaddr(server_name)) {
213                 werr = WERR_NOT_SUPPORTED;
214                 goto done;
215         }
216
217         status = cli_full_connection(&cli, NULL, server_name,
218                                      NULL, 0,
219                                      "IPC$", "IPC",
220                                      ctx->username,
221                                      ctx->workgroup,
222                                      ctx->password,
223                                      0, Undefined, NULL);
224
225         if (!NT_STATUS_IS_OK(status)) {
226                 werr = ntstatus_to_werror(status);
227                 goto done;
228         }
229
230         old_timeout = cli_set_timeout(cli, 60000);
231
232         pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
233                                             &status);
234         if (!pipe_cli) {
235                 werr = ntstatus_to_werror(status);
236                 goto done;
237         };
238
239         if (password) {
240                 encode_wkssvc_join_password_buffer(mem_ctx,
241                                                    password,
242                                                    &cli->user_session_key,
243                                                    &encrypted_password);
244         }
245
246         old_timeout = cli_set_timeout(cli, 60000);
247
248         status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, mem_ctx,
249                                                  server_name,
250                                                  account,
251                                                  &encrypted_password,
252                                                  unjoin_flags,
253                                                  &werr);
254         if (!NT_STATUS_IS_OK(status)) {
255                 werr = ntstatus_to_werror(status);
256                 goto done;
257         }
258
259  done:
260         if (cli) {
261                 cli_set_timeout(cli, old_timeout);
262                 cli_shutdown(cli);
263         }
264         TALLOC_FREE(mem_ctx);
265
266         return werr;
267 }
268
269 WERROR NetGetJoinInformation(const char *server_name,
270                              const char **name_buffer,
271                              uint16_t *name_type)
272 {
273         TALLOC_CTX *mem_ctx = NULL;
274         struct cli_state *cli = NULL;
275         struct rpc_pipe_client *pipe_cli = NULL;
276         NTSTATUS status;
277         WERROR werr;
278
279         mem_ctx = talloc_init("NetGetJoinInformation");
280         if (!mem_ctx) {
281                 werr = WERR_NOMEM;
282                 goto done;
283         }
284
285         if (!server_name || is_myname_or_ipaddr(server_name)) {
286                 if ((lp_security() == SEC_ADS) && lp_realm()) {
287                         *name_buffer = SMB_STRDUP(lp_realm());
288                 } else {
289                         *name_buffer = SMB_STRDUP(lp_workgroup());
290                 }
291                 if (!*name_buffer) {
292                         werr = WERR_NOMEM;
293                         goto done;
294                 }
295                 switch (lp_server_role()) {
296                         case ROLE_DOMAIN_MEMBER:
297                         case ROLE_DOMAIN_PDC:
298                         case ROLE_DOMAIN_BDC:
299                                 *name_type = NetSetupDomainName;
300                                 break;
301                         case ROLE_STANDALONE:
302                         default:
303                                 *name_type = NetSetupWorkgroupName;
304                                 break;
305                 }
306
307                 werr = WERR_OK;
308                 goto done;
309         }
310
311         status = cli_full_connection(&cli, NULL, server_name,
312                                      NULL, 0,
313                                      "IPC$", "IPC",
314                                      ctx->username,
315                                      ctx->workgroup,
316                                      ctx->password,
317                                      0, Undefined, NULL);
318
319         if (!NT_STATUS_IS_OK(status)) {
320                 werr = ntstatus_to_werror(status);
321                 goto done;
322         }
323
324         pipe_cli = cli_rpc_pipe_open_noauth(cli, PI_WKSSVC,
325                                             &status);
326         if (!pipe_cli) {
327                 werr = ntstatus_to_werror(status);
328                 goto done;
329         };
330
331         status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, mem_ctx,
332                                                       server_name,
333                                                       name_buffer,
334                                                       (enum wkssvc_NetJoinStatus *)name_type,
335                                                       &werr);
336         if (!NT_STATUS_IS_OK(status)) {
337                 werr = ntstatus_to_werror(status);
338                 goto done;
339         }
340
341  done:
342         if (cli) {
343                 cli_shutdown(cli);
344         }
345         TALLOC_FREE(mem_ctx);
346
347         return werr;
348 }