Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * Group Policy Object Support
4 : * Copyright (C) Jelmer Vernooij 2008
5 : * Copyright (C) Wilco Baan Hofman 2008-2010
6 : *
7 : * This program is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * This program is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 : #include "includes.h"
21 : #include "param/param.h"
22 : #include <ldb.h>
23 : #include "lib/ldb-samba/ldb_wrap.h"
24 : #include "auth/credentials/credentials.h"
25 : #include "../librpc/gen_ndr/nbt.h"
26 : #include "libcli/libcli.h"
27 : #include "libnet/libnet.h"
28 : #include "../librpc/gen_ndr/ndr_security.h"
29 : #include "../libcli/security/security.h"
30 : #include "libcli/ldap/ldap_ndr.h"
31 : #include "../lib/talloc/talloc.h"
32 : #include "lib/policy/policy.h"
33 :
34 : struct gpo_stringmap {
35 : const char *str;
36 : uint32_t flags;
37 : };
38 : static const struct gpo_stringmap gplink_options [] = {
39 : { "GPLINK_OPT_DISABLE", GPLINK_OPT_DISABLE },
40 : { "GPLINK_OPT_ENFORCE", GPLINK_OPT_ENFORCE },
41 : { NULL, 0 }
42 : };
43 : static const struct gpo_stringmap gpo_flags [] = {
44 : { "GPO_FLAG_USER_DISABLE", GPO_FLAG_USER_DISABLE },
45 : { "GPO_FLAG_MACHINE_DISABLE", GPO_FLAG_MACHINE_DISABLE },
46 : { NULL, 0 }
47 : };
48 :
49 0 : static NTSTATUS parse_gpo(TALLOC_CTX *mem_ctx, struct ldb_message *msg, struct gp_object **ret)
50 : {
51 0 : struct gp_object *gpo = talloc(mem_ctx, struct gp_object);
52 0 : enum ndr_err_code ndr_err;
53 0 : const DATA_BLOB *data;
54 :
55 0 : NT_STATUS_HAVE_NO_MEMORY(gpo);
56 :
57 0 : gpo->dn = talloc_strdup(mem_ctx, ldb_dn_get_linearized(msg->dn));
58 0 : if (gpo->dn == NULL) {
59 0 : TALLOC_FREE(gpo);
60 0 : return NT_STATUS_NO_MEMORY;
61 : }
62 :
63 0 : DEBUG(9, ("Parsing GPO LDAP data for %s\n", gpo->dn));
64 :
65 0 : gpo->display_name = talloc_strdup(gpo, ldb_msg_find_attr_as_string(msg, "displayName", ""));
66 0 : if (gpo->display_name == NULL) {
67 0 : TALLOC_FREE(gpo);
68 0 : return NT_STATUS_NO_MEMORY;
69 : }
70 :
71 0 : gpo->name = talloc_strdup(gpo, ldb_msg_find_attr_as_string(msg, "name", ""));
72 0 : if (gpo->name == NULL) {
73 0 : TALLOC_FREE(gpo);
74 0 : return NT_STATUS_NO_MEMORY;
75 : }
76 :
77 0 : gpo->flags = ldb_msg_find_attr_as_uint(msg, "flags", 0);
78 0 : gpo->version = ldb_msg_find_attr_as_uint(msg, "versionNumber", 0);
79 :
80 0 : gpo->file_sys_path = talloc_strdup(gpo, ldb_msg_find_attr_as_string(msg, "gPCFileSysPath", ""));
81 0 : if (gpo->file_sys_path == NULL) {
82 0 : TALLOC_FREE(gpo);
83 0 : return NT_STATUS_NO_MEMORY;
84 : }
85 :
86 : /* Pull the security descriptor through the NDR library */
87 0 : data = ldb_msg_find_ldb_val(msg, "nTSecurityDescriptor");
88 0 : gpo->security_descriptor = talloc(gpo, struct security_descriptor);
89 0 : if (gpo->security_descriptor == NULL) {
90 0 : TALLOC_FREE(gpo);
91 0 : return NT_STATUS_NO_MEMORY;
92 : }
93 :
94 0 : ndr_err = ndr_pull_struct_blob(data,
95 : mem_ctx,
96 0 : gpo->security_descriptor,
97 : (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
98 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
99 0 : return ndr_map_error2ntstatus(ndr_err);
100 : }
101 :
102 0 : *ret = gpo;
103 0 : return NT_STATUS_OK;
104 : }
105 :
106 43 : NTSTATUS gp_get_gpo_flags(TALLOC_CTX *mem_ctx, uint32_t flags, const char ***ret)
107 : {
108 43 : unsigned int i, count=0;
109 43 : const char **flag_strs = talloc_array(mem_ctx, const char *, 1);
110 :
111 43 : NT_STATUS_HAVE_NO_MEMORY(flag_strs);
112 :
113 43 : flag_strs[0] = NULL;
114 :
115 129 : for (i = 0; gpo_flags[i].str != NULL; i++) {
116 86 : if (flags & gpo_flags[i].flags) {
117 1 : flag_strs = talloc_realloc(mem_ctx, flag_strs, const char *, count+2);
118 1 : NT_STATUS_HAVE_NO_MEMORY(flag_strs);
119 1 : flag_strs[count] = gpo_flags[i].str;
120 1 : flag_strs[count+1] = NULL;
121 1 : count++;
122 : }
123 : }
124 43 : *ret = flag_strs;
125 43 : return NT_STATUS_OK;
126 : }
127 :
128 1 : NTSTATUS gp_get_gplink_options(TALLOC_CTX *mem_ctx, uint32_t options, const char ***ret)
129 : {
130 1 : unsigned int i, count=0;
131 1 : const char **flag_strs = talloc_array(mem_ctx, const char *, 1);
132 :
133 1 : NT_STATUS_HAVE_NO_MEMORY(flag_strs);
134 1 : flag_strs[0] = NULL;
135 :
136 3 : for (i = 0; gplink_options[i].str != NULL; i++) {
137 2 : if (options & gplink_options[i].flags) {
138 1 : flag_strs = talloc_realloc(mem_ctx, flag_strs, const char *, count+2);
139 1 : NT_STATUS_HAVE_NO_MEMORY(flag_strs);
140 1 : flag_strs[count] = gplink_options[i].str;
141 1 : flag_strs[count+1] = NULL;
142 1 : count++;
143 : }
144 : }
145 1 : *ret = flag_strs;
146 1 : return NT_STATUS_OK;
147 : }
148 :
149 0 : NTSTATUS gp_init(TALLOC_CTX *mem_ctx,
150 : struct loadparm_context *lp_ctx,
151 : struct cli_credentials *credentials,
152 : struct tevent_context *ev_ctx,
153 : struct gp_context **gp_ctx)
154 : {
155 :
156 0 : struct libnet_LookupDCs *io;
157 0 : char *url;
158 0 : struct libnet_context *net_ctx;
159 0 : struct ldb_context *ldb_ctx;
160 0 : NTSTATUS rv;
161 :
162 : /* Initialise the libnet context */
163 0 : net_ctx = libnet_context_init(ev_ctx, lp_ctx);
164 0 : net_ctx->cred = credentials;
165 :
166 : /* Prepare libnet lookup structure for looking a DC (PDC is correct). */
167 0 : io = talloc_zero(mem_ctx, struct libnet_LookupDCs);
168 0 : NT_STATUS_HAVE_NO_MEMORY(io);
169 0 : io->in.name_type = NBT_NAME_PDC;
170 0 : io->in.domain_name = lpcfg_workgroup(lp_ctx);
171 :
172 : /* Find Active DC's */
173 0 : rv = libnet_LookupDCs(net_ctx, mem_ctx, io);
174 0 : if (!NT_STATUS_IS_OK(rv)) {
175 0 : DEBUG(0, ("Failed to lookup DCs in domain\n"));
176 0 : return rv;
177 : }
178 :
179 : /* Connect to ldap://DC_NAME with all relevant contexts*/
180 0 : url = talloc_asprintf(mem_ctx, "ldap://%s", io->out.dcs[0].name);
181 0 : NT_STATUS_HAVE_NO_MEMORY(url);
182 0 : ldb_ctx = ldb_wrap_connect(mem_ctx, net_ctx->event_ctx, lp_ctx,
183 : url, NULL, net_ctx->cred, 0);
184 0 : if (ldb_ctx == NULL) {
185 0 : DEBUG(0, ("Can't connect to DC's LDAP with url %s\n", url));
186 0 : return NT_STATUS_UNSUCCESSFUL;
187 : }
188 :
189 0 : *gp_ctx = talloc_zero(mem_ctx, struct gp_context);
190 0 : NT_STATUS_HAVE_NO_MEMORY(gp_ctx);
191 :
192 0 : (*gp_ctx)->lp_ctx = lp_ctx;
193 0 : (*gp_ctx)->credentials = credentials;
194 0 : (*gp_ctx)->ev_ctx = ev_ctx;
195 0 : (*gp_ctx)->ldb_ctx = ldb_ctx;
196 0 : (*gp_ctx)->active_dc = talloc_reference(*gp_ctx, &io->out.dcs[0]);
197 :
198 : /* We don't need to keep the libnet context */
199 0 : talloc_free(net_ctx);
200 0 : return NT_STATUS_OK;
201 : }
202 :
203 0 : NTSTATUS gp_list_all_gpos(struct gp_context *gp_ctx, struct gp_object ***ret)
204 : {
205 0 : struct ldb_result *result;
206 0 : int rv;
207 0 : NTSTATUS status;
208 0 : TALLOC_CTX *mem_ctx;
209 0 : struct ldb_dn *dn;
210 0 : struct gp_object **gpo;
211 0 : unsigned int i; /* same as in struct ldb_result */
212 0 : const char **attrs;
213 :
214 : /* Create a forked memory context, as a base for everything here */
215 0 : mem_ctx = talloc_new(gp_ctx);
216 0 : NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
217 :
218 : /* Create full ldb dn of the policies base object */
219 0 : dn = ldb_get_default_basedn(gp_ctx->ldb_ctx);
220 0 : rv = ldb_dn_add_child(dn, ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, "CN=Policies,CN=System"));
221 0 : if (!rv) {
222 0 : DEBUG(0, ("Can't append subtree to DN\n"));
223 0 : talloc_free(mem_ctx);
224 0 : return NT_STATUS_UNSUCCESSFUL;
225 : }
226 :
227 0 : DEBUG(10, ("Searching for policies in DN: %s\n", ldb_dn_get_linearized(dn)));
228 :
229 0 : attrs = talloc_array(mem_ctx, const char *, 7);
230 0 : if (attrs == NULL) {
231 0 : TALLOC_FREE(mem_ctx);
232 0 : return NT_STATUS_NO_MEMORY;
233 : }
234 :
235 0 : attrs[0] = "nTSecurityDescriptor";
236 0 : attrs[1] = "versionNumber";
237 0 : attrs[2] = "flags";
238 0 : attrs[3] = "name";
239 0 : attrs[4] = "displayName";
240 0 : attrs[5] = "gPCFileSysPath";
241 0 : attrs[6] = NULL;
242 :
243 0 : rv = ldb_search(gp_ctx->ldb_ctx, mem_ctx, &result, dn, LDB_SCOPE_ONELEVEL, attrs, "(objectClass=groupPolicyContainer)");
244 0 : if (rv != LDB_SUCCESS) {
245 0 : DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
246 0 : talloc_free(mem_ctx);
247 0 : return NT_STATUS_UNSUCCESSFUL;
248 : }
249 :
250 0 : gpo = talloc_array(gp_ctx, struct gp_object *, result->count+1);
251 0 : if (gpo == NULL) {
252 0 : TALLOC_FREE(mem_ctx);
253 0 : return NT_STATUS_NO_MEMORY;
254 : }
255 :
256 0 : gpo[result->count] = NULL;
257 :
258 0 : for (i = 0; i < result->count; i++) {
259 0 : status = parse_gpo(gp_ctx, result->msgs[i], &gpo[i]);
260 0 : if (!NT_STATUS_IS_OK(status)) {
261 0 : DEBUG(0, ("Failed to parse GPO.\n"));
262 0 : talloc_free(mem_ctx);
263 0 : return status;
264 : }
265 : }
266 :
267 0 : talloc_free(mem_ctx);
268 :
269 0 : *ret = gpo;
270 0 : return NT_STATUS_OK;
271 : }
272 :
273 0 : NTSTATUS gp_get_gpo_info(struct gp_context *gp_ctx, const char *dn_str, struct gp_object **ret)
274 : {
275 0 : struct ldb_result *result;
276 0 : struct ldb_dn *dn;
277 0 : struct gp_object *gpo;
278 0 : int rv;
279 0 : NTSTATUS status;
280 0 : TALLOC_CTX *mem_ctx;
281 0 : const char **attrs;
282 :
283 : /* Create a forked memory context, as a base for everything here */
284 0 : mem_ctx = talloc_new(gp_ctx);
285 0 : NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
286 :
287 : /* Create an ldb dn struct for the dn string */
288 0 : dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
289 :
290 0 : attrs = talloc_array(mem_ctx, const char *, 7);
291 0 : if (attrs == NULL) {
292 0 : TALLOC_FREE(mem_ctx);
293 0 : return NT_STATUS_NO_MEMORY;
294 : }
295 :
296 0 : attrs[0] = "nTSecurityDescriptor";
297 0 : attrs[1] = "versionNumber";
298 0 : attrs[2] = "flags";
299 0 : attrs[3] = "name";
300 0 : attrs[4] = "displayName";
301 0 : attrs[5] = "gPCFileSysPath";
302 0 : attrs[6] = NULL;
303 :
304 0 : rv = ldb_search(gp_ctx->ldb_ctx,
305 : mem_ctx,
306 : &result,
307 : dn,
308 : LDB_SCOPE_BASE,
309 : attrs,
310 : "objectClass=groupPolicyContainer");
311 0 : if (rv != LDB_SUCCESS) {
312 0 : DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
313 0 : talloc_free(mem_ctx);
314 0 : return NT_STATUS_UNSUCCESSFUL;
315 : }
316 :
317 : /* We expect exactly one record */
318 0 : if (result->count != 1) {
319 0 : DEBUG(0, ("Could not find GPC with dn %s\n", dn_str));
320 0 : talloc_free(mem_ctx);
321 0 : return NT_STATUS_NOT_FOUND;
322 : }
323 :
324 0 : status = parse_gpo(gp_ctx, result->msgs[0], &gpo);
325 0 : if (!NT_STATUS_IS_OK(status)) {
326 0 : DEBUG(0, ("Failed to parse GPO.\n"));
327 0 : talloc_free(mem_ctx);
328 0 : return status;
329 : }
330 :
331 0 : talloc_free(mem_ctx);
332 :
333 0 : *ret = gpo;
334 0 : return NT_STATUS_OK;
335 : }
336 :
337 0 : static NTSTATUS parse_gplink (TALLOC_CTX *mem_ctx, const char *gplink_str, struct gp_link ***ret)
338 : {
339 0 : int start, idx=0;
340 0 : int pos;
341 0 : struct gp_link **gplinks;
342 0 : char *buf, *end;
343 0 : const char *gplink_start = "[LDAP://";
344 :
345 0 : gplinks = talloc_array(mem_ctx, struct gp_link *, 1);
346 0 : NT_STATUS_HAVE_NO_MEMORY(gplinks);
347 :
348 0 : gplinks[0] = NULL;
349 :
350 : /* Assuming every gPLink starts with "[LDAP://" */
351 0 : start = strlen(gplink_start);
352 :
353 0 : for (pos = start; pos < strlen(gplink_str); pos++) {
354 0 : if (gplink_str[pos] == ';') {
355 0 : gplinks = talloc_realloc(mem_ctx, gplinks, struct gp_link *, idx+2);
356 0 : NT_STATUS_HAVE_NO_MEMORY(gplinks);
357 0 : gplinks[idx] = talloc(mem_ctx, struct gp_link);
358 0 : NT_STATUS_HAVE_NO_MEMORY(gplinks[idx]);
359 0 : gplinks[idx]->dn = talloc_strndup(mem_ctx,
360 : gplink_str + start,
361 0 : pos - start);
362 0 : if (gplinks[idx]->dn == NULL) {
363 0 : TALLOC_FREE(gplinks);
364 0 : return NT_STATUS_NO_MEMORY;
365 : }
366 :
367 0 : for (start = pos + 1; gplink_str[pos] != ']'; pos++);
368 :
369 0 : buf = talloc_strndup(gplinks, gplink_str + start, pos - start);
370 0 : if (buf == NULL) {
371 0 : TALLOC_FREE(gplinks);
372 0 : return NT_STATUS_NO_MEMORY;
373 : }
374 0 : gplinks[idx]->options = (uint32_t) strtoll(buf, &end, 0);
375 0 : talloc_free(buf);
376 :
377 : /* Set the last entry in the array to be NULL */
378 0 : gplinks[idx + 1] = NULL;
379 :
380 : /* Increment the array index, the string position past
381 : the next "[LDAP://", and set the start reference */
382 0 : idx++;
383 0 : pos += strlen(gplink_start)+1;
384 0 : start = pos;
385 : }
386 : }
387 :
388 0 : *ret = gplinks;
389 0 : return NT_STATUS_OK;
390 : }
391 :
392 :
393 0 : NTSTATUS gp_get_gplinks(struct gp_context *gp_ctx, const char *dn_str, struct gp_link ***ret)
394 : {
395 0 : TALLOC_CTX *mem_ctx;
396 0 : struct ldb_dn *dn;
397 0 : struct ldb_result *result;
398 0 : struct gp_link **gplinks;
399 0 : char *gplink_str;
400 0 : int rv;
401 0 : unsigned int i;
402 0 : NTSTATUS status;
403 :
404 : /* Create a forked memory context, as a base for everything here */
405 0 : mem_ctx = talloc_new(gp_ctx);
406 0 : NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
407 :
408 0 : dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
409 :
410 0 : rv = ldb_search(gp_ctx->ldb_ctx, mem_ctx, &result, dn, LDB_SCOPE_BASE, NULL, "(objectclass=*)");
411 0 : if (rv != LDB_SUCCESS) {
412 0 : DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
413 0 : talloc_free(mem_ctx);
414 0 : return NT_STATUS_UNSUCCESSFUL;
415 : }
416 :
417 0 : for (i = 0; i < result->count; i++) {
418 0 : struct ldb_message_element *element = \
419 0 : ldb_msg_find_element(result->msgs[i], "gPLink");
420 0 : if (element != NULL) {
421 0 : SMB_ASSERT(element->num_values > 0);
422 0 : gplink_str = talloc_strdup(
423 : mem_ctx,
424 0 : (char *) element->values[0].data);
425 0 : if (gplink_str == NULL) {
426 0 : TALLOC_FREE(mem_ctx);
427 0 : return NT_STATUS_NO_MEMORY;
428 : }
429 0 : goto found;
430 : }
431 : }
432 0 : gplink_str = talloc_strdup(mem_ctx, "");
433 0 : if (gplink_str == NULL) {
434 0 : TALLOC_FREE(mem_ctx);
435 0 : return NT_STATUS_NO_MEMORY;
436 : }
437 :
438 0 : found:
439 :
440 0 : status = parse_gplink(gp_ctx, gplink_str, &gplinks);
441 0 : if (!NT_STATUS_IS_OK(status)) {
442 0 : DEBUG(0, ("Failed to parse gPLink\n"));
443 0 : return status;
444 : }
445 :
446 0 : talloc_free(mem_ctx);
447 :
448 0 : *ret = gplinks;
449 0 : return NT_STATUS_OK;
450 : }
451 :
452 0 : NTSTATUS gp_list_gpos(struct gp_context *gp_ctx, struct security_token *token, const char ***ret)
453 : {
454 0 : TALLOC_CTX *mem_ctx;
455 0 : const char **gpos;
456 0 : struct ldb_result *result;
457 0 : char *sid;
458 0 : struct ldb_dn *dn;
459 0 : struct ldb_message_element *element;
460 0 : bool inherit;
461 0 : const char *attrs[] = { "objectClass", NULL };
462 0 : int rv;
463 0 : NTSTATUS status;
464 0 : unsigned int count = 0;
465 0 : unsigned int i;
466 0 : enum {
467 : ACCOUNT_TYPE_USER = 0,
468 : ACCOUNT_TYPE_MACHINE = 1
469 : } account_type;
470 :
471 : /* Create a forked memory context, as a base for everything here */
472 0 : mem_ctx = talloc_new(gp_ctx);
473 0 : NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
474 :
475 0 : sid = ldap_encode_ndr_dom_sid(mem_ctx,
476 0 : &token->sids[PRIMARY_USER_SID_INDEX]);
477 0 : NT_STATUS_HAVE_NO_MEMORY(sid);
478 :
479 : /* Find the user DN and objectclass via the sid from the security token */
480 0 : rv = ldb_search(gp_ctx->ldb_ctx,
481 : mem_ctx,
482 : &result,
483 : ldb_get_default_basedn(gp_ctx->ldb_ctx),
484 : LDB_SCOPE_SUBTREE,
485 : attrs,
486 : "(&(objectclass=user)(objectSid=%s))", sid);
487 0 : if (rv != LDB_SUCCESS) {
488 0 : DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv),
489 : ldb_errstring(gp_ctx->ldb_ctx)));
490 0 : talloc_free(mem_ctx);
491 0 : return NT_STATUS_UNSUCCESSFUL;
492 : }
493 0 : if (result->count != 1) {
494 0 : DEBUG(0, ("Could not find user with sid %s.\n", sid));
495 0 : talloc_free(mem_ctx);
496 0 : return NT_STATUS_UNSUCCESSFUL;
497 : }
498 0 : DEBUG(10,("Found DN for this user: %s\n", ldb_dn_get_linearized(result->msgs[0]->dn)));
499 :
500 0 : element = ldb_msg_find_element(result->msgs[0], "objectClass");
501 :
502 : /* We need to know if this account is a user or machine. */
503 0 : account_type = ACCOUNT_TYPE_USER;
504 0 : for (i = 0; i < element->num_values; i++) {
505 0 : if (strcmp((char *)element->values[i].data, "computer") == 0) {
506 0 : account_type = ACCOUNT_TYPE_MACHINE;
507 0 : DEBUG(10, ("This user is a machine\n"));
508 : }
509 : }
510 :
511 0 : gpos = talloc_array(gp_ctx, const char *, 1);
512 0 : if (gpos == NULL) {
513 0 : TALLOC_FREE(mem_ctx);
514 0 : return NT_STATUS_NO_MEMORY;
515 : }
516 0 : gpos[0] = NULL;
517 :
518 : /* Walk through the containers until we hit the root */
519 0 : inherit = 1;
520 0 : dn = ldb_dn_get_parent(mem_ctx, result->msgs[0]->dn);
521 0 : while (ldb_dn_compare_base(ldb_get_default_basedn(gp_ctx->ldb_ctx), dn) == 0) {
522 0 : const char *gpo_attrs[] = { "gPLink", "gPOptions", NULL };
523 0 : struct gp_link **gplinks;
524 0 : enum gpo_inheritance gpoptions;
525 :
526 0 : DEBUG(10, ("Getting gPLinks for DN: %s\n", ldb_dn_get_linearized(dn)));
527 :
528 : /* Get the gPLink and gPOptions attributes from the container */
529 0 : rv = ldb_search(gp_ctx->ldb_ctx,
530 : mem_ctx,
531 : &result,
532 : dn,
533 : LDB_SCOPE_BASE,
534 : gpo_attrs,
535 : "objectclass=*");
536 0 : if (rv != LDB_SUCCESS) {
537 0 : DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv),
538 : ldb_errstring(gp_ctx->ldb_ctx)));
539 0 : talloc_free(mem_ctx);
540 0 : return NT_STATUS_UNSUCCESSFUL;
541 : }
542 :
543 : /* Parse the gPLink attribute, put it into a nice struct array */
544 0 : status = parse_gplink(mem_ctx, ldb_msg_find_attr_as_string(result->msgs[0], "gPLink", ""), &gplinks);
545 0 : if (!NT_STATUS_IS_OK(status)) {
546 0 : DEBUG(0, ("Failed to parse gPLink\n"));
547 0 : talloc_free(mem_ctx);
548 0 : return status;
549 : }
550 :
551 : /* Check all group policy links on this container */
552 0 : for (i = 0; gplinks[i] != NULL; i++) {
553 0 : struct gp_object *gpo;
554 0 : uint32_t access_granted;
555 :
556 : /* If inheritance was blocked at a higher level and this
557 : * gplink is not enforced, it should not be applied */
558 0 : if (!inherit && !(gplinks[i]->options & GPLINK_OPT_ENFORCE))
559 0 : continue;
560 :
561 : /* Don't apply disabled links */
562 0 : if (gplinks[i]->options & GPLINK_OPT_DISABLE)
563 0 : continue;
564 :
565 : /* Get GPO information */
566 0 : status = gp_get_gpo_info(gp_ctx, gplinks[i]->dn, &gpo);
567 0 : if (!NT_STATUS_IS_OK(status)) {
568 0 : DEBUG(0, ("Failed to get gpo information for %s\n", gplinks[i]->dn));
569 0 : talloc_free(mem_ctx);
570 0 : return status;
571 : }
572 :
573 : /* If the account does not have read access, this GPO does not apply
574 : * to this account */
575 0 : status = se_access_check(gpo->security_descriptor,
576 : token,
577 : (SEC_STD_READ_CONTROL | SEC_ADS_LIST | SEC_ADS_READ_PROP),
578 : &access_granted);
579 0 : if (!NT_STATUS_IS_OK(status)) {
580 0 : continue;
581 : }
582 :
583 : /* If the account is a user and the GPO has user disabled flag, or
584 : * a machine and the GPO has machine disabled flag, this GPO does
585 : * not apply to this account */
586 0 : if ((account_type == ACCOUNT_TYPE_USER &&
587 0 : (gpo->flags & GPO_FLAG_USER_DISABLE)) ||
588 0 : (account_type == ACCOUNT_TYPE_MACHINE &&
589 0 : (gpo->flags & GPO_FLAG_MACHINE_DISABLE))) {
590 0 : continue;
591 : }
592 :
593 : /* Add the GPO to the list */
594 0 : gpos = talloc_realloc(gp_ctx, gpos, const char *, count+2);
595 0 : if (gpos == NULL) {
596 0 : TALLOC_FREE(mem_ctx);
597 0 : return NT_STATUS_NO_MEMORY;
598 : }
599 0 : gpos[count] = talloc_strdup(gp_ctx, gplinks[i]->dn);
600 0 : if (gpos[count] == NULL) {
601 0 : TALLOC_FREE(mem_ctx);
602 0 : return NT_STATUS_NO_MEMORY;
603 : }
604 0 : gpos[count+1] = NULL;
605 0 : count++;
606 :
607 : /* Clean up */
608 0 : talloc_free(gpo);
609 : }
610 :
611 : /* If inheritance is blocked, then we should only add enforced gPLinks
612 : * higher up */
613 0 : gpoptions = ldb_msg_find_attr_as_uint(result->msgs[0], "gPOptions", 0);
614 0 : if (gpoptions == GPO_BLOCK_INHERITANCE) {
615 0 : inherit = 0;
616 : }
617 0 : dn = ldb_dn_get_parent(mem_ctx, dn);
618 : }
619 :
620 0 : talloc_free(mem_ctx);
621 :
622 0 : *ret = gpos;
623 0 : return NT_STATUS_OK;
624 : }
625 :
626 0 : NTSTATUS gp_set_gplink(struct gp_context *gp_ctx, const char *dn_str, struct gp_link *gplink)
627 : {
628 0 : TALLOC_CTX *mem_ctx;
629 0 : struct ldb_result *result;
630 0 : struct ldb_dn *dn;
631 0 : struct ldb_message *msg;
632 0 : const char *attrs[] = { "gPLink", NULL };
633 0 : const char *gplink_str;
634 0 : int rv;
635 0 : char *start;
636 :
637 : /* Create a forked memory context, as a base for everything here */
638 0 : mem_ctx = talloc_new(gp_ctx);
639 0 : NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
640 :
641 0 : dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
642 :
643 0 : rv = ldb_search(gp_ctx->ldb_ctx, mem_ctx, &result, dn, LDB_SCOPE_BASE, attrs, "(objectclass=*)");
644 0 : if (rv != LDB_SUCCESS) {
645 0 : DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
646 0 : talloc_free(mem_ctx);
647 0 : return NT_STATUS_UNSUCCESSFUL;
648 : }
649 :
650 0 : if (result->count != 1) {
651 0 : talloc_free(mem_ctx);
652 0 : return NT_STATUS_NOT_FOUND;
653 : }
654 :
655 0 : gplink_str = ldb_msg_find_attr_as_string(result->msgs[0], "gPLink", "");
656 :
657 : /* If this GPO link already exists, alter the options, else add it */
658 0 : if ((start = strcasestr(gplink_str, gplink->dn)) != NULL) {
659 0 : start += strlen(gplink->dn);
660 0 : *start = '\0';
661 0 : start++;
662 0 : while (*start != ']' && *start != '\0') {
663 0 : start++;
664 : }
665 0 : gplink_str = talloc_asprintf(mem_ctx, "%s;%d%s", gplink_str, gplink->options, start);
666 0 : if (gplink_str == NULL) {
667 0 : TALLOC_FREE(mem_ctx);
668 0 : return NT_STATUS_NO_MEMORY;
669 : }
670 :
671 : } else {
672 : /* Prepend the new GPO link to the string. This list is backwards in priority. */
673 0 : gplink_str = talloc_asprintf(mem_ctx, "[LDAP://%s;%d]%s", gplink->dn, gplink->options, gplink_str);
674 0 : if (gplink_str == NULL) {
675 0 : TALLOC_FREE(mem_ctx);
676 0 : return NT_STATUS_NO_MEMORY;
677 : }
678 : }
679 :
680 :
681 :
682 0 : msg = ldb_msg_new(mem_ctx);
683 0 : if (msg == NULL) {
684 0 : TALLOC_FREE(mem_ctx);
685 0 : return NT_STATUS_NO_MEMORY;
686 : }
687 :
688 0 : msg->dn = dn;
689 :
690 0 : rv = ldb_msg_add_string(msg, "gPLink", gplink_str);
691 0 : if (rv != LDB_SUCCESS) {
692 0 : DEBUG(0, ("LDB message add string failed: %s\n", ldb_strerror(rv)));
693 0 : talloc_free(mem_ctx);
694 0 : return NT_STATUS_UNSUCCESSFUL;
695 : }
696 0 : msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
697 :
698 0 : rv = ldb_modify(gp_ctx->ldb_ctx, msg);
699 0 : if (rv != LDB_SUCCESS) {
700 0 : DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
701 0 : talloc_free(mem_ctx);
702 0 : return NT_STATUS_UNSUCCESSFUL;
703 : }
704 :
705 0 : talloc_free(mem_ctx);
706 0 : return NT_STATUS_OK;
707 : }
708 :
709 0 : NTSTATUS gp_del_gplink(struct gp_context *gp_ctx, const char *dn_str, const char *gplink_dn)
710 : {
711 0 : TALLOC_CTX *mem_ctx;
712 0 : struct ldb_result *result;
713 0 : struct ldb_dn *dn;
714 0 : struct ldb_message *msg;
715 0 : const char *attrs[] = { "gPLink", NULL };
716 0 : const char *gplink_str, *search_string;
717 0 : int rv;
718 0 : char *p;
719 :
720 : /* Create a forked memory context, as a base for everything here */
721 0 : mem_ctx = talloc_new(gp_ctx);
722 0 : NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
723 :
724 0 : dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
725 :
726 0 : rv = ldb_search(gp_ctx->ldb_ctx, mem_ctx, &result, dn, LDB_SCOPE_BASE, attrs, "(objectclass=*)");
727 0 : if (rv != LDB_SUCCESS) {
728 0 : DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
729 0 : talloc_free(mem_ctx);
730 0 : return NT_STATUS_UNSUCCESSFUL;
731 : }
732 :
733 0 : if (result->count != 1) {
734 0 : talloc_free(mem_ctx);
735 0 : return NT_STATUS_NOT_FOUND;
736 : }
737 :
738 0 : gplink_str = ldb_msg_find_attr_as_string(result->msgs[0], "gPLink", "");
739 :
740 : /* If this GPO link already exists, alter the options, else add it */
741 0 : search_string = talloc_asprintf(mem_ctx, "[LDAP://%s]", gplink_dn);
742 0 : if (search_string == NULL) {
743 0 : TALLOC_FREE(mem_ctx);
744 0 : return NT_STATUS_NO_MEMORY;
745 : }
746 :
747 0 : p = strcasestr(gplink_str, search_string);
748 0 : if (p == NULL) {
749 0 : talloc_free(mem_ctx);
750 0 : return NT_STATUS_NOT_FOUND;
751 : }
752 :
753 0 : *p = '\0';
754 0 : p++;
755 0 : while (*p != ']' && *p != '\0') {
756 0 : p++;
757 : }
758 0 : p++;
759 0 : gplink_str = talloc_asprintf(mem_ctx, "%s%s", gplink_str, p);
760 0 : if (gplink_str == NULL) {
761 0 : TALLOC_FREE(mem_ctx);
762 0 : return NT_STATUS_NO_MEMORY;
763 : }
764 :
765 :
766 0 : msg = ldb_msg_new(mem_ctx);
767 0 : if (msg == NULL) {
768 0 : TALLOC_FREE(mem_ctx);
769 0 : return NT_STATUS_NO_MEMORY;
770 : }
771 :
772 0 : msg->dn = dn;
773 :
774 0 : if (strcmp(gplink_str, "") == 0) {
775 0 : rv = ldb_msg_add_empty(msg, "gPLink", LDB_FLAG_MOD_DELETE, NULL);
776 0 : if (rv != LDB_SUCCESS) {
777 0 : DEBUG(0, ("LDB message add empty element failed: %s\n", ldb_strerror(rv)));
778 0 : talloc_free(mem_ctx);
779 0 : return NT_STATUS_UNSUCCESSFUL;
780 : }
781 : } else {
782 0 : rv = ldb_msg_add_string(msg, "gPLink", gplink_str);
783 0 : if (rv != LDB_SUCCESS) {
784 0 : DEBUG(0, ("LDB message add string failed: %s\n", ldb_strerror(rv)));
785 0 : talloc_free(mem_ctx);
786 0 : return NT_STATUS_UNSUCCESSFUL;
787 : }
788 0 : msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
789 : }
790 0 : rv = ldb_modify(gp_ctx->ldb_ctx, msg);
791 0 : if (rv != LDB_SUCCESS) {
792 0 : DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
793 0 : talloc_free(mem_ctx);
794 0 : return NT_STATUS_UNSUCCESSFUL;
795 : }
796 :
797 0 : talloc_free(mem_ctx);
798 0 : return NT_STATUS_OK;
799 : }
800 :
801 0 : NTSTATUS gp_get_inheritance(struct gp_context *gp_ctx, const char *dn_str, enum gpo_inheritance *inheritance)
802 : {
803 0 : TALLOC_CTX *mem_ctx;
804 0 : struct ldb_result *result;
805 0 : struct ldb_dn *dn;
806 0 : const char *attrs[] = { "gPOptions", NULL };
807 0 : int rv;
808 :
809 : /* Create a forked memory context, as a base for everything here */
810 0 : mem_ctx = talloc_new(gp_ctx);
811 0 : NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
812 :
813 0 : dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
814 :
815 0 : rv = ldb_search(gp_ctx->ldb_ctx, mem_ctx, &result, dn, LDB_SCOPE_BASE, attrs, "(objectclass=*)");
816 0 : if (rv != LDB_SUCCESS) {
817 0 : DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
818 0 : talloc_free(mem_ctx);
819 0 : return NT_STATUS_UNSUCCESSFUL;
820 : }
821 :
822 0 : if (result->count != 1) {
823 0 : talloc_free(mem_ctx);
824 0 : return NT_STATUS_NOT_FOUND;
825 : }
826 :
827 0 : *inheritance = ldb_msg_find_attr_as_uint(result->msgs[0], "gPOptions", 0);
828 :
829 0 : talloc_free(mem_ctx);
830 0 : return NT_STATUS_OK;
831 : }
832 :
833 0 : NTSTATUS gp_set_inheritance(struct gp_context *gp_ctx, const char *dn_str, enum gpo_inheritance inheritance)
834 : {
835 0 : char *inheritance_string;
836 0 : struct ldb_message *msg;
837 0 : int rv;
838 :
839 0 : msg = ldb_msg_new(gp_ctx);
840 0 : NT_STATUS_HAVE_NO_MEMORY(msg);
841 :
842 0 : msg->dn = ldb_dn_new(msg, gp_ctx->ldb_ctx, dn_str);
843 :
844 0 : inheritance_string = talloc_asprintf(msg, "%d", inheritance);
845 0 : if (inheritance_string == NULL) {
846 0 : TALLOC_FREE(msg);
847 0 : return NT_STATUS_NO_MEMORY;
848 : }
849 :
850 0 : rv = ldb_msg_add_string(msg, "gPOptions", inheritance_string);
851 0 : if (rv != LDB_SUCCESS) {
852 0 : DEBUG(0, ("LDB message add string failed: %s\n", ldb_strerror(rv)));
853 0 : talloc_free(msg);
854 0 : return NT_STATUS_UNSUCCESSFUL;
855 : }
856 0 : msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
857 :
858 0 : rv = ldb_modify(gp_ctx->ldb_ctx, msg);
859 0 : if (rv != LDB_SUCCESS) {
860 0 : DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
861 0 : talloc_free(msg);
862 0 : return NT_STATUS_UNSUCCESSFUL;
863 : }
864 :
865 0 : talloc_free(msg);
866 0 : return NT_STATUS_OK;
867 : }
868 :
869 0 : NTSTATUS gp_create_ldap_gpo(struct gp_context *gp_ctx, struct gp_object *gpo)
870 : {
871 0 : struct ldb_message *msg;
872 0 : TALLOC_CTX *mem_ctx;
873 0 : int rv;
874 0 : char *dn_str, *flags_str, *version_str;
875 0 : struct ldb_dn *child_dn, *gpo_dn;
876 :
877 0 : mem_ctx = talloc_new(gp_ctx);
878 0 : NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
879 :
880 : /* CN={GUID} */
881 0 : msg = ldb_msg_new(mem_ctx);
882 0 : if (msg == NULL) {
883 0 : TALLOC_FREE(mem_ctx);
884 0 : return NT_STATUS_NO_MEMORY;
885 : }
886 :
887 0 : msg->dn = ldb_get_default_basedn(gp_ctx->ldb_ctx);
888 0 : dn_str = talloc_asprintf(mem_ctx, "CN=%s,CN=Policies,CN=System", gpo->name);
889 0 : if (dn_str == NULL) {
890 0 : TALLOC_FREE(mem_ctx);
891 0 : return NT_STATUS_NO_MEMORY;
892 : }
893 :
894 0 : child_dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
895 0 : rv = ldb_dn_add_child(msg->dn, child_dn);
896 0 : if (!rv) goto ldb_msg_add_error;
897 :
898 0 : flags_str = talloc_asprintf(mem_ctx, "%d", gpo->flags);
899 0 : if (flags_str == NULL) {
900 0 : TALLOC_FREE(mem_ctx);
901 0 : return NT_STATUS_NO_MEMORY;
902 : }
903 :
904 0 : version_str = talloc_asprintf(mem_ctx, "%d", gpo->version);
905 0 : if (version_str == NULL) {
906 0 : TALLOC_FREE(mem_ctx);
907 0 : return NT_STATUS_NO_MEMORY;
908 : }
909 :
910 0 : rv = ldb_msg_add_string(msg, "objectClass", "top");
911 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
912 0 : rv = ldb_msg_add_string(msg, "objectClass", "container");
913 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
914 0 : rv = ldb_msg_add_string(msg, "objectClass", "groupPolicyContainer");
915 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
916 0 : rv = ldb_msg_add_string(msg, "displayName", gpo->display_name);
917 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
918 0 : rv = ldb_msg_add_string(msg, "name", gpo->name);
919 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
920 0 : rv = ldb_msg_add_string(msg, "CN", gpo->name);
921 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
922 0 : rv = ldb_msg_add_string(msg, "gPCFileSysPath", gpo->file_sys_path);
923 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
924 0 : rv = ldb_msg_add_string(msg, "flags", flags_str);
925 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
926 0 : rv = ldb_msg_add_string(msg, "versionNumber", version_str);
927 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
928 0 : rv = ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE");
929 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
930 0 : rv = ldb_msg_add_string(msg, "gpCFunctionalityVersion", "2");
931 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
932 :
933 0 : rv = ldb_add(gp_ctx->ldb_ctx, msg);
934 0 : if (rv != LDB_SUCCESS) {
935 0 : DEBUG(0, ("LDB add error: %s\n", ldb_errstring(gp_ctx->ldb_ctx)));
936 0 : talloc_free(mem_ctx);
937 0 : return NT_STATUS_UNSUCCESSFUL;
938 : }
939 :
940 0 : gpo_dn = msg->dn;
941 :
942 : /* CN=User */
943 0 : msg = ldb_msg_new(mem_ctx);
944 0 : if (msg == NULL) {
945 0 : TALLOC_FREE(mem_ctx);
946 0 : return NT_STATUS_NO_MEMORY;
947 : }
948 :
949 0 : msg->dn = ldb_dn_copy(mem_ctx, gpo_dn);
950 0 : child_dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, "CN=User");
951 0 : rv = ldb_dn_add_child(msg->dn, child_dn);
952 0 : if (!rv) goto ldb_msg_add_error;
953 :
954 0 : rv = ldb_msg_add_string(msg, "objectClass", "top");
955 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
956 0 : rv = ldb_msg_add_string(msg, "objectClass", "container");
957 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
958 0 : rv = ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE");
959 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
960 0 : rv = ldb_msg_add_string(msg, "CN", "User");
961 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
962 0 : rv = ldb_msg_add_string(msg, "name", "User");
963 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
964 :
965 0 : rv = ldb_add(gp_ctx->ldb_ctx, msg);
966 0 : if (rv != LDB_SUCCESS) {
967 0 : DEBUG(0, ("LDB add error: %s\n", ldb_errstring(gp_ctx->ldb_ctx)));
968 0 : talloc_free(mem_ctx);
969 0 : return NT_STATUS_UNSUCCESSFUL;
970 : }
971 :
972 : /* CN=Machine */
973 0 : msg = ldb_msg_new(mem_ctx);
974 0 : if (msg == NULL) {
975 0 : TALLOC_FREE(mem_ctx);
976 0 : return NT_STATUS_NO_MEMORY;
977 : }
978 :
979 0 : msg->dn = ldb_dn_copy(mem_ctx, gpo_dn);
980 0 : child_dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, "CN=Machine");
981 0 : rv = ldb_dn_add_child(msg->dn, child_dn);
982 0 : if (!rv) goto ldb_msg_add_error;
983 :
984 0 : rv = ldb_msg_add_string(msg, "objectClass", "top");
985 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
986 0 : rv = ldb_msg_add_string(msg, "objectClass", "container");
987 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
988 0 : rv = ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE");
989 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
990 0 : rv = ldb_msg_add_string(msg, "CN", "Machine");
991 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
992 0 : rv = ldb_msg_add_string(msg, "name", "Machine");
993 0 : if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
994 :
995 0 : rv = ldb_add(gp_ctx->ldb_ctx, msg);
996 0 : if (rv != LDB_SUCCESS) {
997 0 : DEBUG(0, ("LDB add error: %s\n", ldb_errstring(gp_ctx->ldb_ctx)));
998 0 : talloc_free(mem_ctx);
999 0 : return NT_STATUS_UNSUCCESSFUL;
1000 : }
1001 :
1002 0 : gpo->dn = talloc_strdup(gpo, ldb_dn_get_linearized(gpo_dn));
1003 0 : if (gpo->dn == NULL) {
1004 0 : TALLOC_FREE(mem_ctx);
1005 0 : return NT_STATUS_NO_MEMORY;
1006 : }
1007 :
1008 0 : talloc_free(mem_ctx);
1009 0 : return NT_STATUS_OK;
1010 :
1011 0 : ldb_msg_add_error:
1012 0 : DEBUG(0, ("LDB Error adding element to ldb message\n"));
1013 0 : talloc_free(mem_ctx);
1014 0 : return NT_STATUS_UNSUCCESSFUL;
1015 : }
1016 :
1017 0 : NTSTATUS gp_set_ads_acl (struct gp_context *gp_ctx, const char *dn_str, const struct security_descriptor *sd)
1018 : {
1019 0 : TALLOC_CTX *mem_ctx;
1020 0 : DATA_BLOB data;
1021 0 : enum ndr_err_code ndr_err;
1022 0 : struct ldb_message *msg;
1023 0 : int rv;
1024 :
1025 : /* Create a forked memory context to clean up easily */
1026 0 : mem_ctx = talloc_new(gp_ctx);
1027 0 : NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
1028 :
1029 : /* Push the security descriptor through the NDR library */
1030 0 : ndr_err = ndr_push_struct_blob(&data,
1031 : mem_ctx,
1032 : sd,
1033 : (ndr_push_flags_fn_t)ndr_push_security_descriptor);
1034 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1035 0 : return ndr_map_error2ntstatus(ndr_err);
1036 : }
1037 :
1038 :
1039 : /* Create a LDB message */
1040 0 : msg = ldb_msg_new(mem_ctx);
1041 0 : if (msg == NULL) {
1042 0 : TALLOC_FREE(mem_ctx);
1043 0 : return NT_STATUS_NO_MEMORY;
1044 : }
1045 :
1046 0 : msg->dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
1047 :
1048 0 : rv = ldb_msg_add_value(msg, "nTSecurityDescriptor", &data, NULL);
1049 0 : if (rv != LDB_SUCCESS) {
1050 0 : DEBUG(0, ("LDB message add element failed for adding nTSecurityDescriptor: %s\n", ldb_strerror(rv)));
1051 0 : talloc_free(mem_ctx);
1052 0 : return NT_STATUS_UNSUCCESSFUL;
1053 : }
1054 0 : msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1055 :
1056 0 : rv = ldb_modify(gp_ctx->ldb_ctx, msg);
1057 0 : if (rv != LDB_SUCCESS) {
1058 0 : DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
1059 0 : talloc_free(mem_ctx);
1060 0 : return NT_STATUS_UNSUCCESSFUL;
1061 : }
1062 :
1063 0 : talloc_free(mem_ctx);
1064 0 : return NT_STATUS_OK;
1065 : }
1066 :
1067 : /* This function sets flags, version and displayName on a GPO */
1068 0 : NTSTATUS gp_set_ldap_gpo(struct gp_context *gp_ctx, struct gp_object *gpo)
1069 : {
1070 0 : int rv;
1071 0 : TALLOC_CTX *mem_ctx;
1072 0 : struct ldb_message *msg;
1073 0 : char *version_str, *flags_str;
1074 :
1075 0 : mem_ctx = talloc_new(gp_ctx);
1076 :
1077 0 : msg = ldb_msg_new(mem_ctx);
1078 0 : if (msg == NULL) {
1079 0 : TALLOC_FREE(mem_ctx);
1080 0 : return NT_STATUS_NO_MEMORY;
1081 : }
1082 :
1083 0 : msg->dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, gpo->dn);
1084 :
1085 0 : version_str = talloc_asprintf(mem_ctx, "%d", gpo->version);
1086 0 : if (msg == NULL) {
1087 0 : TALLOC_FREE(mem_ctx);
1088 0 : return NT_STATUS_NO_MEMORY;
1089 : }
1090 :
1091 0 : flags_str = talloc_asprintf(mem_ctx, "%d", gpo->flags);
1092 0 : if (msg == NULL) {
1093 0 : TALLOC_FREE(mem_ctx);
1094 0 : return NT_STATUS_NO_MEMORY;
1095 : }
1096 :
1097 0 : rv = ldb_msg_add_string(msg, "flags", flags_str);
1098 0 : if (rv != LDB_SUCCESS) {
1099 0 : DEBUG(0, ("LDB message add string failed for flags: %s\n", ldb_strerror(rv)));
1100 0 : talloc_free(mem_ctx);
1101 0 : return NT_STATUS_UNSUCCESSFUL;
1102 : }
1103 0 : msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1104 :
1105 0 : rv = ldb_msg_add_string(msg, "version", version_str);
1106 0 : if (rv != LDB_SUCCESS) {
1107 0 : DEBUG(0, ("LDB message add string failed for version: %s\n", ldb_strerror(rv)));
1108 0 : talloc_free(mem_ctx);
1109 0 : return NT_STATUS_UNSUCCESSFUL;
1110 : }
1111 0 : msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
1112 :
1113 0 : rv = ldb_msg_add_string(msg, "displayName", gpo->display_name);
1114 0 : if (rv != LDB_SUCCESS) {
1115 0 : DEBUG(0, ("LDB message add string failed for displayName: %s\n", ldb_strerror(rv)));
1116 0 : talloc_free(mem_ctx);
1117 0 : return NT_STATUS_UNSUCCESSFUL;
1118 : }
1119 0 : msg->elements[2].flags = LDB_FLAG_MOD_REPLACE;
1120 :
1121 0 : rv = ldb_modify(gp_ctx->ldb_ctx, msg);
1122 0 : if (rv != LDB_SUCCESS) {
1123 0 : DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
1124 0 : talloc_free(mem_ctx);
1125 0 : return NT_STATUS_UNSUCCESSFUL;
1126 : }
1127 :
1128 0 : talloc_free(mem_ctx);
1129 0 : return NT_STATUS_OK;
1130 : }
|