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