source: trunk/server/source3/lib/netapi/joindomain.c@ 480

Last change on this file since 480 was 414, checked in by Herwig Bauernfeind, 16 years ago

Samba 3.5.0: Initial import

File size: 12.5 KB
Line 
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#include "libcli/auth/libcli_auth.h"
28#include "../librpc/gen_ndr/cli_wkssvc.h"
29
30/****************************************************************
31****************************************************************/
32
33WERROR NetJoinDomain_l(struct libnetapi_ctx *mem_ctx,
34 struct NetJoinDomain *r)
35{
36 struct libnet_JoinCtx *j = NULL;
37 WERROR werr;
38
39 if (!r->in.domain) {
40 return WERR_INVALID_PARAM;
41 }
42
43 werr = libnet_init_JoinCtx(mem_ctx, &j);
44 W_ERROR_NOT_OK_RETURN(werr);
45
46 j->in.domain_name = talloc_strdup(mem_ctx, r->in.domain);
47 W_ERROR_HAVE_NO_MEMORY(j->in.domain_name);
48
49 if (r->in.join_flags & WKSSVC_JOIN_FLAGS_JOIN_TYPE) {
50 NTSTATUS status;
51 struct netr_DsRGetDCNameInfo *info = NULL;
52 const char *dc = NULL;
53 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
54 DS_WRITABLE_REQUIRED |
55 DS_RETURN_DNS_NAME;
56 status = dsgetdcname(mem_ctx, NULL, r->in.domain,
57 NULL, NULL, flags, &info);
58 if (!NT_STATUS_IS_OK(status)) {
59 libnetapi_set_error_string(mem_ctx,
60 "%s", get_friendly_nt_error_msg(status));
61 return ntstatus_to_werror(status);
62 }
63
64 dc = strip_hostname(info->dc_unc);
65 j->in.dc_name = talloc_strdup(mem_ctx, dc);
66 W_ERROR_HAVE_NO_MEMORY(j->in.dc_name);
67 }
68
69 if (r->in.account_ou) {
70 j->in.account_ou = talloc_strdup(mem_ctx, r->in.account_ou);
71 W_ERROR_HAVE_NO_MEMORY(j->in.account_ou);
72 }
73
74 if (r->in.account) {
75 j->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
76 W_ERROR_HAVE_NO_MEMORY(j->in.admin_account);
77 }
78
79 if (r->in.password) {
80 j->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
81 W_ERROR_HAVE_NO_MEMORY(j->in.admin_password);
82 }
83
84 j->in.join_flags = r->in.join_flags;
85 j->in.modify_config = true;
86 j->in.debug = true;
87
88 werr = libnet_Join(mem_ctx, j);
89 if (!W_ERROR_IS_OK(werr) && j->out.error_string) {
90 libnetapi_set_error_string(mem_ctx, "%s", j->out.error_string);
91 }
92 TALLOC_FREE(j);
93
94 return werr;
95}
96
97/****************************************************************
98****************************************************************/
99
100WERROR NetJoinDomain_r(struct libnetapi_ctx *ctx,
101 struct NetJoinDomain *r)
102{
103 struct rpc_pipe_client *pipe_cli = NULL;
104 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
105 NTSTATUS status;
106 WERROR werr;
107 unsigned int old_timeout = 0;
108
109 werr = libnetapi_open_pipe(ctx, r->in.server,
110 &ndr_table_wkssvc.syntax_id,
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 &pipe_cli->auth->user_session_key,
120 &encrypted_password);
121 }
122
123 old_timeout = rpccli_set_timeout(pipe_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 (pipe_cli && old_timeout) {
140 rpccli_set_timeout(pipe_cli, old_timeout);
141 }
142
143 return werr;
144}
145/****************************************************************
146****************************************************************/
147
148WERROR NetUnjoinDomain_l(struct libnetapi_ctx *mem_ctx,
149 struct NetUnjoinDomain *r)
150{
151 struct libnet_UnjoinCtx *u = NULL;
152 struct dom_sid domain_sid;
153 const char *domain = NULL;
154 WERROR werr;
155
156 if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
157 return WERR_SETUP_NOT_JOINED;
158 }
159
160 werr = libnet_init_UnjoinCtx(mem_ctx, &u);
161 W_ERROR_NOT_OK_RETURN(werr);
162
163 if (lp_realm()) {
164 domain = lp_realm();
165 } else {
166 domain = lp_workgroup();
167 }
168
169 if (r->in.server_name) {
170 u->in.dc_name = talloc_strdup(mem_ctx, r->in.server_name);
171 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
172 } else {
173 NTSTATUS status;
174 struct netr_DsRGetDCNameInfo *info = NULL;
175 const char *dc = NULL;
176 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
177 DS_WRITABLE_REQUIRED |
178 DS_RETURN_DNS_NAME;
179 status = dsgetdcname(mem_ctx, NULL, domain,
180 NULL, NULL, flags, &info);
181 if (!NT_STATUS_IS_OK(status)) {
182 libnetapi_set_error_string(mem_ctx,
183 "failed to find DC for domain %s: %s",
184 domain,
185 get_friendly_nt_error_msg(status));
186 return ntstatus_to_werror(status);
187 }
188
189 dc = strip_hostname(info->dc_unc);
190 u->in.dc_name = talloc_strdup(mem_ctx, dc);
191 W_ERROR_HAVE_NO_MEMORY(u->in.dc_name);
192
193 u->in.domain_name = domain;
194 }
195
196 if (r->in.account) {
197 u->in.admin_account = talloc_strdup(mem_ctx, r->in.account);
198 W_ERROR_HAVE_NO_MEMORY(u->in.admin_account);
199 }
200
201 if (r->in.password) {
202 u->in.admin_password = talloc_strdup(mem_ctx, r->in.password);
203 W_ERROR_HAVE_NO_MEMORY(u->in.admin_password);
204 }
205
206 u->in.domain_name = domain;
207 u->in.unjoin_flags = r->in.unjoin_flags;
208 u->in.delete_machine_account = false;
209 u->in.modify_config = true;
210 u->in.debug = true;
211
212 u->in.domain_sid = &domain_sid;
213
214 werr = libnet_Unjoin(mem_ctx, u);
215 if (!W_ERROR_IS_OK(werr) && u->out.error_string) {
216 libnetapi_set_error_string(mem_ctx, "%s", u->out.error_string);
217 }
218 TALLOC_FREE(u);
219
220 return werr;
221}
222
223/****************************************************************
224****************************************************************/
225
226WERROR NetUnjoinDomain_r(struct libnetapi_ctx *ctx,
227 struct NetUnjoinDomain *r)
228{
229 struct rpc_pipe_client *pipe_cli = NULL;
230 struct wkssvc_PasswordBuffer *encrypted_password = NULL;
231 NTSTATUS status;
232 WERROR werr;
233 unsigned int old_timeout = 0;
234
235 werr = libnetapi_open_pipe(ctx, r->in.server_name,
236 &ndr_table_wkssvc.syntax_id,
237 &pipe_cli);
238 if (!W_ERROR_IS_OK(werr)) {
239 goto done;
240 }
241
242 if (r->in.password) {
243 encode_wkssvc_join_password_buffer(ctx,
244 r->in.password,
245 &pipe_cli->auth->user_session_key,
246 &encrypted_password);
247 }
248
249 old_timeout = rpccli_set_timeout(pipe_cli, 60000);
250
251 status = rpccli_wkssvc_NetrUnjoinDomain2(pipe_cli, ctx,
252 r->in.server_name,
253 r->in.account,
254 encrypted_password,
255 r->in.unjoin_flags,
256 &werr);
257 if (!NT_STATUS_IS_OK(status)) {
258 werr = ntstatus_to_werror(status);
259 goto done;
260 }
261
262 done:
263 if (pipe_cli && old_timeout) {
264 rpccli_set_timeout(pipe_cli, old_timeout);
265 }
266
267 return werr;
268}
269
270/****************************************************************
271****************************************************************/
272
273WERROR NetGetJoinInformation_r(struct libnetapi_ctx *ctx,
274 struct NetGetJoinInformation *r)
275{
276 struct rpc_pipe_client *pipe_cli = NULL;
277 NTSTATUS status;
278 WERROR werr;
279 const char *buffer = NULL;
280
281 werr = libnetapi_open_pipe(ctx, r->in.server_name,
282 &ndr_table_wkssvc.syntax_id,
283 &pipe_cli);
284 if (!W_ERROR_IS_OK(werr)) {
285 goto done;
286 }
287
288 status = rpccli_wkssvc_NetrGetJoinInformation(pipe_cli, ctx,
289 r->in.server_name,
290 &buffer,
291 (enum wkssvc_NetJoinStatus *)r->out.name_type,
292 &werr);
293 if (!NT_STATUS_IS_OK(status)) {
294 werr = ntstatus_to_werror(status);
295 goto done;
296 }
297
298 *r->out.name_buffer = talloc_strdup(ctx, buffer);
299 W_ERROR_HAVE_NO_MEMORY(*r->out.name_buffer);
300
301 done:
302 return werr;
303}
304
305/****************************************************************
306****************************************************************/
307
308WERROR NetGetJoinInformation_l(struct libnetapi_ctx *ctx,
309 struct NetGetJoinInformation *r)
310{
311 if ((lp_security() == SEC_ADS) && lp_realm()) {
312 *r->out.name_buffer = talloc_strdup(ctx, lp_realm());
313 } else {
314 *r->out.name_buffer = talloc_strdup(ctx, lp_workgroup());
315 }
316 if (!*r->out.name_buffer) {
317 return WERR_NOMEM;
318 }
319
320 switch (lp_server_role()) {
321 case ROLE_DOMAIN_MEMBER:
322 case ROLE_DOMAIN_PDC:
323 case ROLE_DOMAIN_BDC:
324 *r->out.name_type = NetSetupDomainName;
325 break;
326 case ROLE_STANDALONE:
327 default:
328 *r->out.name_type = NetSetupWorkgroupName;
329 break;
330 }
331
332 return WERR_OK;
333}
334
335/****************************************************************
336****************************************************************/
337
338WERROR NetGetJoinableOUs_l(struct libnetapi_ctx *ctx,
339 struct NetGetJoinableOUs *r)
340{
341#ifdef WITH_ADS
342 NTSTATUS status;
343 ADS_STATUS ads_status;
344 ADS_STRUCT *ads = NULL;
345 struct netr_DsRGetDCNameInfo *info = NULL;
346 const char *dc = NULL;
347 uint32_t flags = DS_DIRECTORY_SERVICE_REQUIRED |
348 DS_RETURN_DNS_NAME;
349
350 status = dsgetdcname(ctx, NULL, r->in.domain,
351 NULL, NULL, flags, &info);
352 if (!NT_STATUS_IS_OK(status)) {
353 libnetapi_set_error_string(ctx, "%s",