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