ctdb-server: Remove duplicate logic
[samba4-gss.git] / source4 / lib / policy / gp_ldap.c
blob67b329b12957d95f4771437fcef1ea01df8b5ecb
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
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.
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.
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/>.
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"
34 struct gpo_stringmap {
35 const char *str;
36 uint32_t flags;
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 }
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 }
49 static NTSTATUS parse_gpo(TALLOC_CTX *mem_ctx, struct ldb_message *msg, struct gp_object **ret)
51 struct gp_object *gpo = talloc(mem_ctx, struct gp_object);
52 enum ndr_err_code ndr_err;
53 const DATA_BLOB *data;
55 NT_STATUS_HAVE_NO_MEMORY(gpo);
57 gpo->dn = talloc_strdup(mem_ctx, ldb_dn_get_linearized(msg->dn));
58 if (gpo->dn == NULL) {
59 TALLOC_FREE(gpo);
60 return NT_STATUS_NO_MEMORY;
63 DEBUG(9, ("Parsing GPO LDAP data for %s\n", gpo->dn));
65 gpo->display_name = talloc_strdup(gpo, ldb_msg_find_attr_as_string(msg, "displayName", ""));
66 if (gpo->display_name == NULL) {
67 TALLOC_FREE(gpo);
68 return NT_STATUS_NO_MEMORY;
71 gpo->name = talloc_strdup(gpo, ldb_msg_find_attr_as_string(msg, "name", ""));
72 if (gpo->name == NULL) {
73 TALLOC_FREE(gpo);
74 return NT_STATUS_NO_MEMORY;
77 gpo->flags = ldb_msg_find_attr_as_uint(msg, "flags", 0);
78 gpo->version = ldb_msg_find_attr_as_uint(msg, "versionNumber", 0);
80 gpo->file_sys_path = talloc_strdup(gpo, ldb_msg_find_attr_as_string(msg, "gPCFileSysPath", ""));
81 if (gpo->file_sys_path == NULL) {
82 TALLOC_FREE(gpo);
83 return NT_STATUS_NO_MEMORY;
86 /* Pull the security descriptor through the NDR library */
87 data = ldb_msg_find_ldb_val(msg, "nTSecurityDescriptor");
88 gpo->security_descriptor = talloc(gpo, struct security_descriptor);
89 if (gpo->security_descriptor == NULL) {
90 TALLOC_FREE(gpo);
91 return NT_STATUS_NO_MEMORY;
94 ndr_err = ndr_pull_struct_blob(data,
95 mem_ctx,
96 gpo->security_descriptor,
97 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
98 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
99 return ndr_map_error2ntstatus(ndr_err);
102 *ret = gpo;
103 return NT_STATUS_OK;
106 NTSTATUS gp_get_gpo_flags(TALLOC_CTX *mem_ctx, uint32_t flags, const char ***ret)
108 unsigned int i, count=0;
109 const char **flag_strs = talloc_array(mem_ctx, const char *, 1);
111 NT_STATUS_HAVE_NO_MEMORY(flag_strs);
113 flag_strs[0] = NULL;
115 for (i = 0; gpo_flags[i].str != NULL; i++) {
116 if (flags & gpo_flags[i].flags) {
117 flag_strs = talloc_realloc(mem_ctx, flag_strs, const char *, count+2);
118 NT_STATUS_HAVE_NO_MEMORY(flag_strs);
119 flag_strs[count] = gpo_flags[i].str;
120 flag_strs[count+1] = NULL;
121 count++;
124 *ret = flag_strs;
125 return NT_STATUS_OK;
128 NTSTATUS gp_get_gplink_options(TALLOC_CTX *mem_ctx, uint32_t options, const char ***ret)
130 unsigned int i, count=0;
131 const char **flag_strs = talloc_array(mem_ctx, const char *, 1);
133 NT_STATUS_HAVE_NO_MEMORY(flag_strs);
134 flag_strs[0] = NULL;
136 for (i = 0; gplink_options[i].str != NULL; i++) {
137 if (options & gplink_options[i].flags) {
138 flag_strs = talloc_realloc(mem_ctx, flag_strs, const char *, count+2);
139 NT_STATUS_HAVE_NO_MEMORY(flag_strs);
140 flag_strs[count] = gplink_options[i].str;
141 flag_strs[count+1] = NULL;
142 count++;
145 *ret = flag_strs;
146 return NT_STATUS_OK;
149 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)
156 struct libnet_LookupDCs *io;
157 char *url;
158 struct libnet_context *net_ctx;
159 struct ldb_context *ldb_ctx;
160 NTSTATUS rv;
162 /* Initialise the libnet context */
163 net_ctx = libnet_context_init(ev_ctx, lp_ctx);
164 net_ctx->cred = credentials;
166 /* Prepare libnet lookup structure for looking a DC (PDC is correct). */
167 io = talloc_zero(mem_ctx, struct libnet_LookupDCs);
168 NT_STATUS_HAVE_NO_MEMORY(io);
169 io->in.name_type = NBT_NAME_PDC;
170 io->in.domain_name = lpcfg_workgroup(lp_ctx);
172 /* Find Active DC's */
173 rv = libnet_LookupDCs(net_ctx, mem_ctx, io);
174 if (!NT_STATUS_IS_OK(rv)) {
175 DEBUG(0, ("Failed to lookup DCs in domain\n"));
176 return rv;
179 /* Connect to ldap://DC_NAME with all relevant contexts*/
180 url = talloc_asprintf(mem_ctx, "ldap://%s", io->out.dcs[0].name);
181 NT_STATUS_HAVE_NO_MEMORY(url);
182 ldb_ctx = ldb_wrap_connect(mem_ctx, net_ctx->event_ctx, lp_ctx,
183 url, NULL, net_ctx->cred, 0);
184 if (ldb_ctx == NULL) {
185 DEBUG(0, ("Can't connect to DC's LDAP with url %s\n", url));
186 return NT_STATUS_UNSUCCESSFUL;
189 *gp_ctx = talloc_zero(mem_ctx, struct gp_context);
190 NT_STATUS_HAVE_NO_MEMORY(gp_ctx);
192 (*gp_ctx)->lp_ctx = lp_ctx;
193 (*gp_ctx)->credentials = credentials;
194 (*gp_ctx)->ev_ctx = ev_ctx;
195 (*gp_ctx)->ldb_ctx = ldb_ctx;
196 (*gp_ctx)->active_dc = talloc_reference(*gp_ctx, &io->out.dcs[0]);
198 /* We don't need to keep the libnet context */
199 talloc_free(net_ctx);
200 return NT_STATUS_OK;
203 NTSTATUS gp_list_all_gpos(struct gp_context *gp_ctx, struct gp_object ***ret)
205 struct ldb_result *result;
206 int rv;
207 NTSTATUS status;
208 TALLOC_CTX *mem_ctx;
209 struct ldb_dn *dn;
210 struct gp_object **gpo;
211 unsigned int i; /* same as in struct ldb_result */
212 const char **attrs;
214 /* Create a forked memory context, as a base for everything here */
215 mem_ctx = talloc_new(gp_ctx);
216 NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
218 /* Create full ldb dn of the policies base object */
219 dn = ldb_get_default_basedn(gp_ctx->ldb_ctx);
220 rv = ldb_dn_add_child(dn, ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, "CN=Policies,CN=System"));
221 if (!rv) {
222 DEBUG(0, ("Can't append subtree to DN\n"));
223 talloc_free(mem_ctx);
224 return NT_STATUS_UNSUCCESSFUL;
227 DEBUG(10, ("Searching for policies in DN: %s\n", ldb_dn_get_linearized(dn)));
229 attrs = talloc_array(mem_ctx, const char *, 7);
230 if (attrs == NULL) {
231 TALLOC_FREE(mem_ctx);
232 return NT_STATUS_NO_MEMORY;
235 attrs[0] = "nTSecurityDescriptor";
236 attrs[1] = "versionNumber";
237 attrs[2] = "flags";
238 attrs[3] = "name";
239 attrs[4] = "displayName";
240 attrs[5] = "gPCFileSysPath";
241 attrs[6] = NULL;
243 rv = ldb_search(gp_ctx->ldb_ctx, mem_ctx, &result, dn, LDB_SCOPE_ONELEVEL, attrs, "(objectClass=groupPolicyContainer)");
244 if (rv != LDB_SUCCESS) {
245 DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
246 talloc_free(mem_ctx);
247 return NT_STATUS_UNSUCCESSFUL;
250 gpo = talloc_array(gp_ctx, struct gp_object *, result->count+1);
251 if (gpo == NULL) {
252 TALLOC_FREE(mem_ctx);
253 return NT_STATUS_NO_MEMORY;
256 gpo[result->count] = NULL;
258 for (i = 0; i < result->count; i++) {
259 status = parse_gpo(gp_ctx, result->msgs[i], &gpo[i]);
260 if (!NT_STATUS_IS_OK(status)) {
261 DEBUG(0, ("Failed to parse GPO.\n"));
262 talloc_free(mem_ctx);
263 return status;
267 talloc_free(mem_ctx);
269 *ret = gpo;
270 return NT_STATUS_OK;
273 NTSTATUS gp_get_gpo_info(struct gp_context *gp_ctx, const char *dn_str, struct gp_object **ret)
275 struct ldb_result *result;
276 struct ldb_dn *dn;
277 struct gp_object *gpo;
278 int rv;
279 NTSTATUS status;
280 TALLOC_CTX *mem_ctx;
281 const char **attrs;
283 /* Create a forked memory context, as a base for everything here */
284 mem_ctx = talloc_new(gp_ctx);
285 NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
287 /* Create an ldb dn struct for the dn string */
288 dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
290 attrs = talloc_array(mem_ctx, const char *, 7);
291 if (attrs == NULL) {
292 TALLOC_FREE(mem_ctx);
293 return NT_STATUS_NO_MEMORY;
296 attrs[0] = "nTSecurityDescriptor";
297 attrs[1] = "versionNumber";
298 attrs[2] = "flags";
299 attrs[3] = "name";
300 attrs[4] = "displayName";
301 attrs[5] = "gPCFileSysPath";
302 attrs[6] = NULL;
304 rv = ldb_search(gp_ctx->ldb_ctx,
305 mem_ctx,
306 &result,
308 LDB_SCOPE_BASE,
309 attrs,
310 "objectClass=groupPolicyContainer");
311 if (rv != LDB_SUCCESS) {
312 DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
313 talloc_free(mem_ctx);
314 return NT_STATUS_UNSUCCESSFUL;
317 /* We expect exactly one record */
318 if (result->count != 1) {
319 DEBUG(0, ("Could not find GPC with dn %s\n", dn_str));
320 talloc_free(mem_ctx);
321 return NT_STATUS_NOT_FOUND;
324 status = parse_gpo(gp_ctx, result->msgs[0], &gpo);
325 if (!NT_STATUS_IS_OK(status)) {
326 DEBUG(0, ("Failed to parse GPO.\n"));
327 talloc_free(mem_ctx);
328 return status;
331 talloc_free(mem_ctx);
333 *ret = gpo;
334 return NT_STATUS_OK;
337 static NTSTATUS parse_gplink (TALLOC_CTX *mem_ctx, const char *gplink_str, struct gp_link ***ret)
339 int start, idx=0;
340 int pos;
341 struct gp_link **gplinks;
342 char *buf, *end;
343 const char *gplink_start = "[LDAP://";
345 gplinks = talloc_array(mem_ctx, struct gp_link *, 1);
346 NT_STATUS_HAVE_NO_MEMORY(gplinks);
348 gplinks[0] = NULL;
350 /* Assuming every gPLink starts with "[LDAP://" */
351 start = strlen(gplink_start);
353 for (pos = start; pos < strlen(gplink_str); pos++) {
354 if (gplink_str[pos] == ';') {
355 gplinks = talloc_realloc(mem_ctx, gplinks, struct gp_link *, idx+2);
356 NT_STATUS_HAVE_NO_MEMORY(gplinks);
357 gplinks[idx] = talloc(mem_ctx, struct gp_link);
358 NT_STATUS_HAVE_NO_MEMORY(gplinks[idx]);
359 gplinks[idx]->dn = talloc_strndup(mem_ctx,
360 gplink_str + start,
361 pos - start);
362 if (gplinks[idx]->dn == NULL) {
363 TALLOC_FREE(gplinks);
364 return NT_STATUS_NO_MEMORY;
367 for (start = pos + 1; gplink_str[pos] != ']'; pos++);
369 buf = talloc_strndup(gplinks, gplink_str + start, pos - start);
370 if (buf == NULL) {
371 TALLOC_FREE(gplinks);
372 return NT_STATUS_NO_MEMORY;
374 gplinks[idx]->options = (uint32_t) strtoll(buf, &end, 0);
375 talloc_free(buf);
377 /* Set the last entry in the array to be NULL */
378 gplinks[idx + 1] = NULL;
380 /* Increment the array index, the string position past
381 the next "[LDAP://", and set the start reference */
382 idx++;
383 pos += strlen(gplink_start)+1;
384 start = pos;
388 *ret = gplinks;
389 return NT_STATUS_OK;
393 NTSTATUS gp_get_gplinks(struct gp_context *gp_ctx, const char *dn_str, struct gp_link ***ret)
395 TALLOC_CTX *mem_ctx;
396 struct ldb_dn *dn;
397 struct ldb_result *result;
398 struct gp_link **gplinks;
399 char *gplink_str;
400 int rv;
401 unsigned int i;
402 NTSTATUS status;
404 /* Create a forked memory context, as a base for everything here */
405 mem_ctx = talloc_new(gp_ctx);
406 NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
408 dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
410 rv = ldb_search(gp_ctx->ldb_ctx, mem_ctx, &result, dn, LDB_SCOPE_BASE, NULL, "(objectclass=*)");
411 if (rv != LDB_SUCCESS) {
412 DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
413 talloc_free(mem_ctx);
414 return NT_STATUS_UNSUCCESSFUL;
417 for (i = 0; i < result->count; i++) {
418 struct ldb_message_element *element = \
419 ldb_msg_find_element(result->msgs[i], "gPLink");
420 if (element != NULL) {
421 SMB_ASSERT(element->num_values > 0);
422 gplink_str = talloc_strdup(
423 mem_ctx,
424 (char *) element->values[0].data);
425 if (gplink_str == NULL) {
426 TALLOC_FREE(mem_ctx);
427 return NT_STATUS_NO_MEMORY;
429 goto found;
432 gplink_str = talloc_strdup(mem_ctx, "");
433 if (gplink_str == NULL) {
434 TALLOC_FREE(mem_ctx);
435 return NT_STATUS_NO_MEMORY;
438 found:
440 status = parse_gplink(gp_ctx, gplink_str, &gplinks);
441 if (!NT_STATUS_IS_OK(status)) {
442 DEBUG(0, ("Failed to parse gPLink\n"));
443 return status;
446 talloc_free(mem_ctx);
448 *ret = gplinks;
449 return NT_STATUS_OK;
452 NTSTATUS gp_list_gpos(struct gp_context *gp_ctx, struct security_token *token, const char ***ret)
454 TALLOC_CTX *mem_ctx;
455 const char **gpos;
456 struct ldb_result *result;
457 char *sid;
458 struct ldb_dn *dn;
459 struct ldb_message_element *element;
460 bool inherit;
461 const char *attrs[] = { "objectClass", NULL };
462 int rv;
463 NTSTATUS status;
464 unsigned int count = 0;
465 unsigned int i;
466 enum {
467 ACCOUNT_TYPE_USER = 0,
468 ACCOUNT_TYPE_MACHINE = 1
469 } account_type;
471 /* Create a forked memory context, as a base for everything here */
472 mem_ctx = talloc_new(gp_ctx);
473 NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
475 sid = ldap_encode_ndr_dom_sid(mem_ctx,
476 &token->sids[PRIMARY_USER_SID_INDEX]);
477 NT_STATUS_HAVE_NO_MEMORY(sid);
479 /* Find the user DN and objectclass via the sid from the security token */
480 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 if (rv != LDB_SUCCESS) {
488 DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv),
489 ldb_errstring(gp_ctx->ldb_ctx)));
490 talloc_free(mem_ctx);
491 return NT_STATUS_UNSUCCESSFUL;
493 if (result->count != 1) {
494 DEBUG(0, ("Could not find user with sid %s.\n", sid));
495 talloc_free(mem_ctx);
496 return NT_STATUS_UNSUCCESSFUL;
498 DEBUG(10,("Found DN for this user: %s\n", ldb_dn_get_linearized(result->msgs[0]->dn)));
500 element = ldb_msg_find_element(result->msgs[0], "objectClass");
502 /* We need to know if this account is a user or machine. */
503 account_type = ACCOUNT_TYPE_USER;
504 for (i = 0; i < element->num_values; i++) {
505 if (strcmp((char *)element->values[i].data, "computer") == 0) {
506 account_type = ACCOUNT_TYPE_MACHINE;
507 DEBUG(10, ("This user is a machine\n"));
511 gpos = talloc_array(gp_ctx, const char *, 1);
512 if (gpos == NULL) {
513 TALLOC_FREE(mem_ctx);
514 return NT_STATUS_NO_MEMORY;
516 gpos[0] = NULL;
518 /* Walk through the containers until we hit the root */
519 inherit = 1;
520 dn = ldb_dn_get_parent(mem_ctx, result->msgs[0]->dn);
521 while (ldb_dn_compare_base(ldb_get_default_basedn(gp_ctx->ldb_ctx), dn) == 0) {
522 const char *gpo_attrs[] = { "gPLink", "gPOptions", NULL };
523 struct gp_link **gplinks;
524 enum gpo_inheritance gpoptions;
526 DEBUG(10, ("Getting gPLinks for DN: %s\n", ldb_dn_get_linearized(dn)));
528 /* Get the gPLink and gPOptions attributes from the container */
529 rv = ldb_search(gp_ctx->ldb_ctx,
530 mem_ctx,
531 &result,
533 LDB_SCOPE_BASE,
534 gpo_attrs,
535 "objectclass=*");
536 if (rv != LDB_SUCCESS) {
537 DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv),
538 ldb_errstring(gp_ctx->ldb_ctx)));
539 talloc_free(mem_ctx);
540 return NT_STATUS_UNSUCCESSFUL;
543 /* Parse the gPLink attribute, put it into a nice struct array */
544 status = parse_gplink(mem_ctx, ldb_msg_find_attr_as_string(result->msgs[0], "gPLink", ""), &gplinks);
545 if (!NT_STATUS_IS_OK(status)) {
546 DEBUG(0, ("Failed to parse gPLink\n"));
547 talloc_free(mem_ctx);
548 return status;
551 /* Check all group policy links on this container */
552 for (i = 0; gplinks[i] != NULL; i++) {
553 struct gp_object *gpo;
554 uint32_t access_granted;
556 /* If inheritance was blocked at a higher level and this
557 * gplink is not enforced, it should not be applied */
558 if (!inherit && !(gplinks[i]->options & GPLINK_OPT_ENFORCE))
559 continue;
561 /* Don't apply disabled links */
562 if (gplinks[i]->options & GPLINK_OPT_DISABLE)
563 continue;
565 /* Get GPO information */
566 status = gp_get_gpo_info(gp_ctx, gplinks[i]->dn, &gpo);
567 if (!NT_STATUS_IS_OK(status)) {
568 DEBUG(0, ("Failed to get gpo information for %s\n", gplinks[i]->dn));
569 talloc_free(mem_ctx);
570 return status;
573 /* If the account does not have read access, this GPO does not apply
574 * to this account */
575 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 if (!NT_STATUS_IS_OK(status)) {
580 continue;
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 if ((account_type == ACCOUNT_TYPE_USER &&
587 (gpo->flags & GPO_FLAG_USER_DISABLE)) ||
588 (account_type == ACCOUNT_TYPE_MACHINE &&
589 (gpo->flags & GPO_FLAG_MACHINE_DISABLE))) {
590 continue;
593 /* Add the GPO to the list */
594 gpos = talloc_realloc(gp_ctx, gpos, const char *, count+2);
595 if (gpos == NULL) {
596 TALLOC_FREE(mem_ctx);
597 return NT_STATUS_NO_MEMORY;
599 gpos[count] = talloc_strdup(gp_ctx, gplinks[i]->dn);
600 if (gpos[count] == NULL) {
601 TALLOC_FREE(mem_ctx);
602 return NT_STATUS_NO_MEMORY;
604 gpos[count+1] = NULL;
605 count++;
607 /* Clean up */
608 talloc_free(gpo);
611 /* If inheritance is blocked, then we should only add enforced gPLinks
612 * higher up */
613 gpoptions = ldb_msg_find_attr_as_uint(result->msgs[0], "gPOptions", 0);
614 if (gpoptions == GPO_BLOCK_INHERITANCE) {
615 inherit = 0;
617 dn = ldb_dn_get_parent(mem_ctx, dn);
620 talloc_free(mem_ctx);
622 *ret = gpos;
623 return NT_STATUS_OK;
626 NTSTATUS gp_set_gplink(struct gp_context *gp_ctx, const char *dn_str, struct gp_link *gplink)
628 TALLOC_CTX *mem_ctx;
629 struct ldb_result *result;
630 struct ldb_dn *dn;
631 struct ldb_message *msg;
632 const char *attrs[] = { "gPLink", NULL };
633 const char *gplink_str;
634 int rv;
635 char *start;
637 /* Create a forked memory context, as a base for everything here */
638 mem_ctx = talloc_new(gp_ctx);
639 NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
641 dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
643 rv = ldb_search(gp_ctx->ldb_ctx, mem_ctx, &result, dn, LDB_SCOPE_BASE, attrs, "(objectclass=*)");
644 if (rv != LDB_SUCCESS) {
645 DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
646 talloc_free(mem_ctx);
647 return NT_STATUS_UNSUCCESSFUL;
650 if (result->count != 1) {
651 talloc_free(mem_ctx);
652 return NT_STATUS_NOT_FOUND;
655 gplink_str = ldb_msg_find_attr_as_string(result->msgs[0], "gPLink", "");
657 /* If this GPO link already exists, alter the options, else add it */
658 if ((start = strcasestr(gplink_str, gplink->dn)) != NULL) {
659 start += strlen(gplink->dn);
660 *start = '\0';
661 start++;
662 while (*start != ']' && *start != '\0') {
663 start++;
665 gplink_str = talloc_asprintf(mem_ctx, "%s;%d%s", gplink_str, gplink->options, start);
666 if (gplink_str == NULL) {
667 TALLOC_FREE(mem_ctx);
668 return NT_STATUS_NO_MEMORY;
671 } else {
672 /* Prepend the new GPO link to the string. This list is backwards in priority. */
673 gplink_str = talloc_asprintf(mem_ctx, "[LDAP://%s;%d]%s", gplink->dn, gplink->options, gplink_str);
674 if (gplink_str == NULL) {
675 TALLOC_FREE(mem_ctx);
676 return NT_STATUS_NO_MEMORY;
682 msg = ldb_msg_new(mem_ctx);
683 if (msg == NULL) {
684 TALLOC_FREE(mem_ctx);
685 return NT_STATUS_NO_MEMORY;
688 msg->dn = dn;
690 rv = ldb_msg_add_string(msg, "gPLink", gplink_str);
691 if (rv != LDB_SUCCESS) {
692 DEBUG(0, ("LDB message add string failed: %s\n", ldb_strerror(rv)));
693 talloc_free(mem_ctx);
694 return NT_STATUS_UNSUCCESSFUL;
696 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
698 rv = ldb_modify(gp_ctx->ldb_ctx, msg);
699 if (rv != LDB_SUCCESS) {
700 DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
701 talloc_free(mem_ctx);
702 return NT_STATUS_UNSUCCESSFUL;
705 talloc_free(mem_ctx);
706 return NT_STATUS_OK;
709 NTSTATUS gp_del_gplink(struct gp_context *gp_ctx, const char *dn_str, const char *gplink_dn)
711 TALLOC_CTX *mem_ctx;
712 struct ldb_result *result;
713 struct ldb_dn *dn;
714 struct ldb_message *msg;
715 const char *attrs[] = { "gPLink", NULL };
716 const char *gplink_str, *search_string;
717 int rv;
718 char *p;
720 /* Create a forked memory context, as a base for everything here */
721 mem_ctx = talloc_new(gp_ctx);
722 NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
724 dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
726 rv = ldb_search(gp_ctx->ldb_ctx, mem_ctx, &result, dn, LDB_SCOPE_BASE, attrs, "(objectclass=*)");
727 if (rv != LDB_SUCCESS) {
728 DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
729 talloc_free(mem_ctx);
730 return NT_STATUS_UNSUCCESSFUL;
733 if (result->count != 1) {
734 talloc_free(mem_ctx);
735 return NT_STATUS_NOT_FOUND;
738 gplink_str = ldb_msg_find_attr_as_string(result->msgs[0], "gPLink", "");
740 /* If this GPO link already exists, alter the options, else add it */
741 search_string = talloc_asprintf(mem_ctx, "[LDAP://%s]", gplink_dn);
742 if (search_string == NULL) {
743 TALLOC_FREE(mem_ctx);
744 return NT_STATUS_NO_MEMORY;
747 p = strcasestr(gplink_str, search_string);
748 if (p == NULL) {
749 talloc_free(mem_ctx);
750 return NT_STATUS_NOT_FOUND;
753 *p = '\0';
754 p++;
755 while (*p != ']' && *p != '\0') {
756 p++;
758 p++;
759 gplink_str = talloc_asprintf(mem_ctx, "%s%s", gplink_str, p);
760 if (gplink_str == NULL) {
761 TALLOC_FREE(mem_ctx);
762 return NT_STATUS_NO_MEMORY;
766 msg = ldb_msg_new(mem_ctx);
767 if (msg == NULL) {
768 TALLOC_FREE(mem_ctx);
769 return NT_STATUS_NO_MEMORY;
772 msg->dn = dn;
774 if (strcmp(gplink_str, "") == 0) {
775 rv = ldb_msg_add_empty(msg, "gPLink", LDB_FLAG_MOD_DELETE, NULL);
776 if (rv != LDB_SUCCESS) {
777 DEBUG(0, ("LDB message add empty element failed: %s\n", ldb_strerror(rv)));
778 talloc_free(mem_ctx);
779 return NT_STATUS_UNSUCCESSFUL;
781 } else {
782 rv = ldb_msg_add_string(msg, "gPLink", gplink_str);
783 if (rv != LDB_SUCCESS) {
784 DEBUG(0, ("LDB message add string failed: %s\n", ldb_strerror(rv)));
785 talloc_free(mem_ctx);
786 return NT_STATUS_UNSUCCESSFUL;
788 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
790 rv = ldb_modify(gp_ctx->ldb_ctx, msg);
791 if (rv != LDB_SUCCESS) {
792 DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
793 talloc_free(mem_ctx);
794 return NT_STATUS_UNSUCCESSFUL;
797 talloc_free(mem_ctx);
798 return NT_STATUS_OK;
801 NTSTATUS gp_get_inheritance(struct gp_context *gp_ctx, const char *dn_str, enum gpo_inheritance *inheritance)
803 TALLOC_CTX *mem_ctx;
804 struct ldb_result *result;
805 struct ldb_dn *dn;
806 const char *attrs[] = { "gPOptions", NULL };
807 int rv;
809 /* Create a forked memory context, as a base for everything here */
810 mem_ctx = talloc_new(gp_ctx);
811 NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
813 dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
815 rv = ldb_search(gp_ctx->ldb_ctx, mem_ctx, &result, dn, LDB_SCOPE_BASE, attrs, "(objectclass=*)");
816 if (rv != LDB_SUCCESS) {
817 DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv), ldb_errstring(gp_ctx->ldb_ctx)));
818 talloc_free(mem_ctx);
819 return NT_STATUS_UNSUCCESSFUL;
822 if (result->count != 1) {
823 talloc_free(mem_ctx);
824 return NT_STATUS_NOT_FOUND;
827 *inheritance = ldb_msg_find_attr_as_uint(result->msgs[0], "gPOptions", 0);
829 talloc_free(mem_ctx);
830 return NT_STATUS_OK;
833 NTSTATUS gp_set_inheritance(struct gp_context *gp_ctx, const char *dn_str, enum gpo_inheritance inheritance)
835 char *inheritance_string;
836 struct ldb_message *msg;
837 int rv;
839 msg = ldb_msg_new(gp_ctx);
840 NT_STATUS_HAVE_NO_MEMORY(msg);
842 msg->dn = ldb_dn_new(msg, gp_ctx->ldb_ctx, dn_str);
844 inheritance_string = talloc_asprintf(msg, "%d", inheritance);
845 if (inheritance_string == NULL) {
846 TALLOC_FREE(msg);
847 return NT_STATUS_NO_MEMORY;
850 rv = ldb_msg_add_string(msg, "gPOptions", inheritance_string);
851 if (rv != LDB_SUCCESS) {
852 DEBUG(0, ("LDB message add string failed: %s\n", ldb_strerror(rv)));
853 talloc_free(msg);
854 return NT_STATUS_UNSUCCESSFUL;
856 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
858 rv = ldb_modify(gp_ctx->ldb_ctx, msg);
859 if (rv != LDB_SUCCESS) {
860 DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
861 talloc_free(msg);
862 return NT_STATUS_UNSUCCESSFUL;
865 talloc_free(msg);
866 return NT_STATUS_OK;
869 NTSTATUS gp_create_ldap_gpo(struct gp_context *gp_ctx, struct gp_object *gpo)
871 struct ldb_message *msg;
872 TALLOC_CTX *mem_ctx;
873 int rv;
874 char *dn_str, *flags_str, *version_str;
875 struct ldb_dn *child_dn, *gpo_dn;
877 mem_ctx = talloc_new(gp_ctx);
878 NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
880 /* CN={GUID} */
881 msg = ldb_msg_new(mem_ctx);
882 if (msg == NULL) {
883 TALLOC_FREE(mem_ctx);
884 return NT_STATUS_NO_MEMORY;
887 msg->dn = ldb_get_default_basedn(gp_ctx->ldb_ctx);
888 dn_str = talloc_asprintf(mem_ctx, "CN=%s,CN=Policies,CN=System", gpo->name);
889 if (dn_str == NULL) {
890 TALLOC_FREE(mem_ctx);
891 return NT_STATUS_NO_MEMORY;
894 child_dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
895 rv = ldb_dn_add_child(msg->dn, child_dn);
896 if (!rv) goto ldb_msg_add_error;
898 flags_str = talloc_asprintf(mem_ctx, "%d", gpo->flags);
899 if (flags_str == NULL) {
900 TALLOC_FREE(mem_ctx);
901 return NT_STATUS_NO_MEMORY;
904 version_str = talloc_asprintf(mem_ctx, "%d", gpo->version);
905 if (version_str == NULL) {
906 TALLOC_FREE(mem_ctx);
907 return NT_STATUS_NO_MEMORY;
910 rv = ldb_msg_add_string(msg, "objectClass", "top");
911 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
912 rv = ldb_msg_add_string(msg, "objectClass", "container");
913 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
914 rv = ldb_msg_add_string(msg, "objectClass", "groupPolicyContainer");
915 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
916 rv = ldb_msg_add_string(msg, "displayName", gpo->display_name);
917 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
918 rv = ldb_msg_add_string(msg, "name", gpo->name);
919 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
920 rv = ldb_msg_add_string(msg, "CN", gpo->name);
921 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
922 rv = ldb_msg_add_string(msg, "gPCFileSysPath", gpo->file_sys_path);
923 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
924 rv = ldb_msg_add_string(msg, "flags", flags_str);
925 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
926 rv = ldb_msg_add_string(msg, "versionNumber", version_str);
927 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
928 rv = ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE");
929 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
930 rv = ldb_msg_add_string(msg, "gpCFunctionalityVersion", "2");
931 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
933 rv = ldb_add(gp_ctx->ldb_ctx, msg);
934 if (rv != LDB_SUCCESS) {
935 DEBUG(0, ("LDB add error: %s\n", ldb_errstring(gp_ctx->ldb_ctx)));
936 talloc_free(mem_ctx);
937 return NT_STATUS_UNSUCCESSFUL;
940 gpo_dn = msg->dn;
942 /* CN=User */
943 msg = ldb_msg_new(mem_ctx);
944 if (msg == NULL) {
945 TALLOC_FREE(mem_ctx);
946 return NT_STATUS_NO_MEMORY;
949 msg->dn = ldb_dn_copy(mem_ctx, gpo_dn);
950 child_dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, "CN=User");
951 rv = ldb_dn_add_child(msg->dn, child_dn);
952 if (!rv) goto ldb_msg_add_error;
954 rv = ldb_msg_add_string(msg, "objectClass", "top");
955 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
956 rv = ldb_msg_add_string(msg, "objectClass", "container");
957 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
958 rv = ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE");
959 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
960 rv = ldb_msg_add_string(msg, "CN", "User");
961 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
962 rv = ldb_msg_add_string(msg, "name", "User");
963 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
965 rv = ldb_add(gp_ctx->ldb_ctx, msg);
966 if (rv != LDB_SUCCESS) {
967 DEBUG(0, ("LDB add error: %s\n", ldb_errstring(gp_ctx->ldb_ctx)));
968 talloc_free(mem_ctx);
969 return NT_STATUS_UNSUCCESSFUL;
972 /* CN=Machine */
973 msg = ldb_msg_new(mem_ctx);
974 if (msg == NULL) {
975 TALLOC_FREE(mem_ctx);
976 return NT_STATUS_NO_MEMORY;
979 msg->dn = ldb_dn_copy(mem_ctx, gpo_dn);
980 child_dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, "CN=Machine");
981 rv = ldb_dn_add_child(msg->dn, child_dn);
982 if (!rv) goto ldb_msg_add_error;
984 rv = ldb_msg_add_string(msg, "objectClass", "top");
985 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
986 rv = ldb_msg_add_string(msg, "objectClass", "container");
987 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
988 rv = ldb_msg_add_string(msg, "showInAdvancedViewOnly", "TRUE");
989 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
990 rv = ldb_msg_add_string(msg, "CN", "Machine");
991 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
992 rv = ldb_msg_add_string(msg, "name", "Machine");
993 if (rv != LDB_SUCCESS) goto ldb_msg_add_error;
995 rv = ldb_add(gp_ctx->ldb_ctx, msg);
996 if (rv != LDB_SUCCESS) {
997 DEBUG(0, ("LDB add error: %s\n", ldb_errstring(gp_ctx->ldb_ctx)));
998 talloc_free(mem_ctx);
999 return NT_STATUS_UNSUCCESSFUL;
1002 gpo->dn = talloc_strdup(gpo, ldb_dn_get_linearized(gpo_dn));
1003 if (gpo->dn == NULL) {
1004 TALLOC_FREE(mem_ctx);
1005 return NT_STATUS_NO_MEMORY;
1008 talloc_free(mem_ctx);
1009 return NT_STATUS_OK;
1011 ldb_msg_add_error:
1012 DEBUG(0, ("LDB Error adding element to ldb message\n"));
1013 talloc_free(mem_ctx);
1014 return NT_STATUS_UNSUCCESSFUL;
1017 NTSTATUS gp_set_ads_acl (struct gp_context *gp_ctx, const char *dn_str, const struct security_descriptor *sd)
1019 TALLOC_CTX *mem_ctx;
1020 DATA_BLOB data;
1021 enum ndr_err_code ndr_err;
1022 struct ldb_message *msg;
1023 int rv;
1025 /* Create a forked memory context to clean up easily */
1026 mem_ctx = talloc_new(gp_ctx);
1027 NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
1029 /* Push the security descriptor through the NDR library */
1030 ndr_err = ndr_push_struct_blob(&data,
1031 mem_ctx,
1033 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
1034 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1035 return ndr_map_error2ntstatus(ndr_err);
1039 /* Create a LDB message */
1040 msg = ldb_msg_new(mem_ctx);
1041 if (msg == NULL) {
1042 TALLOC_FREE(mem_ctx);
1043 return NT_STATUS_NO_MEMORY;
1046 msg->dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
1048 rv = ldb_msg_add_value(msg, "nTSecurityDescriptor", &data, NULL);
1049 if (rv != LDB_SUCCESS) {
1050 DEBUG(0, ("LDB message add element failed for adding nTSecurityDescriptor: %s\n", ldb_strerror(rv)));
1051 talloc_free(mem_ctx);
1052 return NT_STATUS_UNSUCCESSFUL;
1054 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1056 rv = ldb_modify(gp_ctx->ldb_ctx, msg);
1057 if (rv != LDB_SUCCESS) {
1058 DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
1059 talloc_free(mem_ctx);
1060 return NT_STATUS_UNSUCCESSFUL;
1063 talloc_free(mem_ctx);
1064 return NT_STATUS_OK;
1067 /* This function sets flags, version and displayName on a GPO */
1068 NTSTATUS gp_set_ldap_gpo(struct gp_context *gp_ctx, struct gp_object *gpo)
1070 int rv;
1071 TALLOC_CTX *mem_ctx;
1072 struct ldb_message *msg;
1073 char *version_str, *flags_str;
1075 mem_ctx = talloc_new(gp_ctx);
1077 msg = ldb_msg_new(mem_ctx);
1078 if (msg == NULL) {
1079 TALLOC_FREE(mem_ctx);
1080 return NT_STATUS_NO_MEMORY;
1083 msg->dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, gpo->dn);
1085 version_str = talloc_asprintf(mem_ctx, "%d", gpo->version);
1086 if (msg == NULL) {
1087 TALLOC_FREE(mem_ctx);
1088 return NT_STATUS_NO_MEMORY;
1091 flags_str = talloc_asprintf(mem_ctx, "%d", gpo->flags);
1092 if (msg == NULL) {
1093 TALLOC_FREE(mem_ctx);
1094 return NT_STATUS_NO_MEMORY;
1097 rv = ldb_msg_add_string(msg, "flags", flags_str);
1098 if (rv != LDB_SUCCESS) {
1099 DEBUG(0, ("LDB message add string failed for flags: %s\n", ldb_strerror(rv)));
1100 talloc_free(mem_ctx);
1101 return NT_STATUS_UNSUCCESSFUL;
1103 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1105 rv = ldb_msg_add_string(msg, "version", version_str);
1106 if (rv != LDB_SUCCESS) {
1107 DEBUG(0, ("LDB message add string failed for version: %s\n", ldb_strerror(rv)));
1108 talloc_free(mem_ctx);
1109 return NT_STATUS_UNSUCCESSFUL;
1111 msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
1113 rv = ldb_msg_add_string(msg, "displayName", gpo->display_name);
1114 if (rv != LDB_SUCCESS) {
1115 DEBUG(0, ("LDB message add string failed for displayName: %s\n", ldb_strerror(rv)));
1116 talloc_free(mem_ctx);
1117 return NT_STATUS_UNSUCCESSFUL;
1119 msg->elements[2].flags = LDB_FLAG_MOD_REPLACE;
1121 rv = ldb_modify(gp_ctx->ldb_ctx, msg);
1122 if (rv != LDB_SUCCESS) {
1123 DEBUG(0, ("LDB modify failed: %s\n", ldb_strerror(rv)));
1124 talloc_free(mem_ctx);
1125 return NT_STATUS_UNSUCCESSFUL;
1128 talloc_free(mem_ctx);
1129 return NT_STATUS_OK;