1 /*
2  *  Unix SMB/CIFS implementation.
3  *  NetApi Samr Support
4  *  Copyright (C) Guenther Deschner 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 #include "lib/netapi/netapi.h"
22 #include "lib/netapi/netapi_private.h"
23 #include "rpc_client/rpc_client.h"
24 #include "../librpc/gen_ndr/ndr_samr_c.h"
25 #include "rpc_client/cli_samr.h"
26 #include "rpc_client/init_lsa.h"
27 #include "../libcli/security/security.h"
28 
29 /****************************************************************
30 ****************************************************************/
31 
libnetapi_samr_open_domain(struct libnetapi_ctx * mem_ctx,struct rpc_pipe_client * pipe_cli,uint32_t connect_mask,uint32_t domain_mask,struct policy_handle * connect_handle,struct policy_handle * domain_handle,struct dom_sid2 ** domain_sid)32 WERROR libnetapi_samr_open_domain(struct libnetapi_ctx *mem_ctx,
33 				  struct rpc_pipe_client *pipe_cli,
34 				  uint32_t connect_mask,
35 				  uint32_t domain_mask,
36 				  struct policy_handle *connect_handle,
37 				  struct policy_handle *domain_handle,
38 				  struct dom_sid2 **domain_sid)
39 {
40 	NTSTATUS status, result;
41 	WERROR werr;
42 	struct libnetapi_private_ctx *priv;
43 	uint32_t resume_handle = 0;
44 	uint32_t num_entries = 0;
45 	struct samr_SamArray *sam = NULL;
46 	const char *domain_name = NULL;
47 	struct lsa_String lsa_domain_name;
48 	bool domain_found = false;
49 	int i;
50 	struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
51 
52 	priv = talloc_get_type_abort(mem_ctx->private_data,
53 		struct libnetapi_private_ctx);
54 
55 	if (is_valid_policy_hnd(&priv->samr.connect_handle)) {
56 		if ((priv->samr.connect_mask & connect_mask) == connect_mask) {
57 			*connect_handle = priv->samr.connect_handle;
58 		} else {
59 			libnetapi_samr_close_connect_handle(mem_ctx,
60 				&priv->samr.connect_handle);
61 		}
62 	}
63 
64 	if (is_valid_policy_hnd(&priv->samr.domain_handle)) {
65 		if ((priv->samr.domain_mask & domain_mask) == domain_mask) {
66 			*domain_handle = priv->samr.domain_handle;
67 		} else {
68 			libnetapi_samr_close_domain_handle(mem_ctx,
69 				&priv->samr.domain_handle);
70 		}
71 	}
72 
73 	if (priv->samr.domain_sid) {
74 		*domain_sid = priv->samr.domain_sid;
75 	}
76 
77 	if (is_valid_policy_hnd(&priv->samr.connect_handle) &&
78 	    ((priv->samr.connect_mask & connect_mask) == connect_mask) &&
79 	    is_valid_policy_hnd(&priv->samr.domain_handle) &&
80 	    (priv->samr.domain_mask & domain_mask) == domain_mask) {
81 		return WERR_OK;
82 	}
83 
84 	if (!is_valid_policy_hnd(connect_handle)) {
85 		status = dcerpc_try_samr_connects(pipe_cli->binding_handle, mem_ctx,
86 						  pipe_cli->srv_name_slash,
87 						  connect_mask,
88 						  connect_handle,
89 						  &result);
90 		if (!NT_STATUS_IS_OK(status)) {
91 			werr = ntstatus_to_werror(status);
92 			goto done;
93 		}
94 		if (!NT_STATUS_IS_OK(result)) {
95 			werr = ntstatus_to_werror(result);
96 			goto done;
97 		}
98 	}
99 
100 	status = dcerpc_samr_EnumDomains(b, mem_ctx,
101 					 connect_handle,
102 					 &resume_handle,
103 					 &sam,
104 					 0xffffffff,
105 					 &num_entries,
106 					 &result);
107 	if (!NT_STATUS_IS_OK(status)) {
108 		werr = ntstatus_to_werror(status);
109 		goto done;
110 	}
111 	if (!NT_STATUS_IS_OK(result)) {
112 		werr = ntstatus_to_werror(result);
113 		goto done;
114 	}
115 
116 	for (i=0; i<num_entries; i++) {
117 
118 		domain_name = sam->entries[i].name.string;
119 
120 		if (strequal(domain_name, builtin_domain_name())) {
121 			continue;
122 		}
123 
124 		domain_found = true;
125 		break;
126 	}
127 
128 	if (!domain_found) {
129 		werr = WERR_NO_SUCH_DOMAIN;
130 		goto done;
131 	}
132 
133 	init_lsa_String(&lsa_domain_name, domain_name);
134 
135 	status = dcerpc_samr_LookupDomain(b, mem_ctx,
136 					  connect_handle,
137 					  &lsa_domain_name,
138 					  domain_sid,
139 					  &result);
140 	if (!NT_STATUS_IS_OK(status)) {
141 		werr = ntstatus_to_werror(status);
142 		goto done;
143 	}
144 	if (!NT_STATUS_IS_OK(result)) {
145 		werr = ntstatus_to_werror(result);
146 		goto done;
147 	}
148 
149 	status = dcerpc_samr_OpenDomain(b, mem_ctx,
150 					connect_handle,
151 					domain_mask,
152 					*domain_sid,
153 					domain_handle,
154 					&result);
155 	if (!NT_STATUS_IS_OK(status)) {
156 		werr = ntstatus_to_werror(status);
157 		goto done;
158 	}
159 	if (!NT_STATUS_IS_OK(result)) {
160 		werr = ntstatus_to_werror(result);
161 		goto done;
162 	}
163 
164 	priv->samr.cli			= pipe_cli;
165 
166 	priv->samr.domain_name		= domain_name;
167 	priv->samr.domain_sid		= *domain_sid;
168 
169 	priv->samr.connect_mask		= connect_mask;
170 	priv->samr.connect_handle	= *connect_handle;
171 
172 	priv->samr.domain_mask		= domain_mask;
173 	priv->samr.domain_handle	= *domain_handle;
174 
175 	werr = WERR_OK;
176 
177  done:
178 	return werr;
179 }
180 
181 /****************************************************************
182 ****************************************************************/
183 
libnetapi_samr_open_builtin_domain(struct libnetapi_ctx * mem_ctx,struct rpc_pipe_client * pipe_cli,uint32_t connect_mask,uint32_t builtin_mask,struct policy_handle * connect_handle,struct policy_handle * builtin_handle)184 WERROR libnetapi_samr_open_builtin_domain(struct libnetapi_ctx *mem_ctx,
185 					  struct rpc_pipe_client *pipe_cli,
186 					  uint32_t connect_mask,
187 					  uint32_t builtin_mask,
188 					  struct policy_handle *connect_handle,
189 					  struct policy_handle *builtin_handle)
190 {
191 	NTSTATUS status, result;
192 	WERROR werr;
193 	struct libnetapi_private_ctx *priv;
194 	struct dcerpc_binding_handle *b = pipe_cli->binding_handle;
195 
196 	priv = talloc_get_type_abort(mem_ctx->private_data,
197 		struct libnetapi_private_ctx);
198 
199 	if (is_valid_policy_hnd(&priv->samr.connect_handle)) {
200 		if ((priv->samr.connect_mask & connect_mask) == connect_mask) {
201 			*connect_handle = priv->samr.connect_handle;
202 		} else {
203 			libnetapi_samr_close_connect_handle(mem_ctx,
204 				&priv->samr.connect_handle);
205 		}
206 	}
207 
208 	if (is_valid_policy_hnd(&priv->samr.builtin_handle)) {
209 		if ((priv->samr.builtin_mask & builtin_mask) == builtin_mask) {
210 			*builtin_handle = priv->samr.builtin_handle;
211 		} else {
212 			libnetapi_samr_close_builtin_handle(mem_ctx,
213 				&priv->samr.builtin_handle);
214 		}
215 	}
216 
217 	if (is_valid_policy_hnd(&priv->samr.connect_handle) &&
218 	    ((priv->samr.connect_mask & connect_mask) == connect_mask) &&
219 	    is_valid_policy_hnd(&priv->samr.builtin_handle) &&
220 	    (priv->samr.builtin_mask & builtin_mask) == builtin_mask) {
221 		return WERR_OK;
222 	}
223 
224 	if (!is_valid_policy_hnd(connect_handle)) {
225 		status = dcerpc_try_samr_connects(pipe_cli->binding_handle, mem_ctx,
226 						  pipe_cli->srv_name_slash,
227 						  connect_mask,
228 						  connect_handle,
229 						  &result);
230 		if (!NT_STATUS_IS_OK(status)) {
231 			werr = ntstatus_to_werror(status);
232 			goto done;
233 		}
234 		if (!NT_STATUS_IS_OK(result)) {
235 			werr = ntstatus_to_werror(result);
236 			goto done;
237 		}
238 	}
239 
240 	status = dcerpc_samr_OpenDomain(b, mem_ctx,
241 					connect_handle,
242 					builtin_mask,
243 					discard_const_p(struct dom_sid, &global_sid_Builtin),
244 					builtin_handle,
245 					&result);
246 	if (!NT_STATUS_IS_OK(status)) {
247 		werr = ntstatus_to_werror(status);
248 		goto done;
249 	}
250 	if (!NT_STATUS_IS_OK(result)) {
251 		werr = ntstatus_to_werror(result);
252 		goto done;
253 	}
254 
255 	priv->samr.cli			= pipe_cli;
256 
257 	priv->samr.connect_mask		= connect_mask;
258 	priv->samr.connect_handle	= *connect_handle;
259 
260 	priv->samr.builtin_mask		= builtin_mask;
261 	priv->samr.builtin_handle	= *builtin_handle;
262 
263 	werr = WERR_OK;
264 
265  done:
266 	return werr;
267 }
268 
269 /****************************************************************
270 ****************************************************************/
271 
libnetapi_samr_close_domain_handle(struct libnetapi_ctx * ctx,struct policy_handle * handle)272 void libnetapi_samr_close_domain_handle(struct libnetapi_ctx *ctx,
273 					struct policy_handle *handle)
274 {
275 	struct libnetapi_private_ctx *priv;
276 	struct dcerpc_binding_handle *b;
277 	NTSTATUS result;
278 
279 	if (!is_valid_policy_hnd(handle)) {
280 		return;
281 	}
282 
283 	priv = talloc_get_type_abort(ctx->private_data,
284 		struct libnetapi_private_ctx);
285 
286 	if (!ndr_policy_handle_equal(handle, &priv->samr.domain_handle)) {
287 		return;
288 	}
289 
290 	b = priv->samr.cli->binding_handle;
291 
292 	dcerpc_samr_Close(b, ctx, handle, &result);
293 
294 	ZERO_STRUCT(priv->samr.domain_handle);
295 }
296 
297 /****************************************************************
298 ****************************************************************/
299 
libnetapi_samr_close_builtin_handle(struct libnetapi_ctx * ctx,struct policy_handle * handle)300 void libnetapi_samr_close_builtin_handle(struct libnetapi_ctx *ctx,
301 					 struct policy_handle *handle)
302 {
303 	struct libnetapi_private_ctx *priv;
304 	struct dcerpc_binding_handle *b;
305 	NTSTATUS result;
306 
307 	if (!is_valid_policy_hnd(handle)) {
308 		return;
309 	}
310 
311 	priv = talloc_get_type_abort(ctx->private_data,
312 		struct libnetapi_private_ctx);
313 
314 	if (!ndr_policy_handle_equal(handle, &priv->samr.builtin_handle)) {
315 		return;
316 	}
317 
318 	b = priv->samr.cli->binding_handle;
319 
320 	dcerpc_samr_Close(b, ctx, handle, &result);
321 
322 	ZERO_STRUCT(priv->samr.builtin_handle);
323 }
324 
325 /****************************************************************
326 ****************************************************************/
327 
libnetapi_samr_close_connect_handle(struct libnetapi_ctx * ctx,struct policy_handle * handle)328 void libnetapi_samr_close_connect_handle(struct libnetapi_ctx *ctx,
329 					 struct policy_handle *handle)
330 {
331 	struct libnetapi_private_ctx *priv;
332 	struct dcerpc_binding_handle *b;
333 	NTSTATUS result;
334 
335 	if (!is_valid_policy_hnd(handle)) {
336 		return;
337 	}
338 
339 	priv = talloc_get_type_abort(ctx->private_data,
340 		struct libnetapi_private_ctx);
341 
342 	if (!ndr_policy_handle_equal(handle, &priv->samr.connect_handle)) {
343 		return;
344 	}
345 
346 	b = priv->samr.cli->binding_handle;
347 
348 	dcerpc_samr_Close(b, ctx, handle, &result);
349 
350 	ZERO_STRUCT(priv->samr.connect_handle);
351 }
352 
353 /****************************************************************
354 ****************************************************************/
355 
libnetapi_samr_free(struct libnetapi_ctx * ctx)356 void libnetapi_samr_free(struct libnetapi_ctx *ctx)
357 {
358 	struct libnetapi_private_ctx *priv;
359 
360 	if (!ctx->private_data) {
361 		return;
362 	}
363 
364 	priv = talloc_get_type_abort(ctx->private_data,
365 		struct libnetapi_private_ctx);
366 
367 	libnetapi_samr_close_domain_handle(ctx, &priv->samr.domain_handle);
368 	libnetapi_samr_close_builtin_handle(ctx, &priv->samr.builtin_handle);
369 	libnetapi_samr_close_connect_handle(ctx, &priv->samr.connect_handle);
370 }
371