samldb: Allow automatic generation of mAPIIDs
[sfrench/samba-autobuild/.git] / source4 / lib / policy / gp_ldap.c
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 static NTSTATUS parse_gpo(TALLOC_CTX *mem_ctx, struct ldb_message *msg, struct gp_object **ret)
50 {
51         struct gp_object *gpo = talloc(mem_ctx, struct gp_object);
52         enum ndr_err_code ndr_err;
53         const DATA_BLOB *data;
54
55         NT_STATUS_HAVE_NO_MEMORY(gpo);
56
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;
61         }
62
63         DEBUG(9, ("Parsing GPO LDAP data for %s\n", gpo->dn));
64
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;
69         }
70
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;
75         }
76
77         gpo->flags = ldb_msg_find_attr_as_uint(msg, "flags", 0);
78         gpo->version = ldb_msg_find_attr_as_uint(msg, "versionNumber", 0);
79
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;
84         }
85
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;
92         }
93
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);
100         }
101
102         *ret = gpo;
103         return NT_STATUS_OK;
104 }
105
106 NTSTATUS gp_get_gpo_flags(TALLOC_CTX *mem_ctx, uint32_t flags, const char ***ret)
107 {
108         unsigned int i, count=0;
109         const char **flag_strs = talloc_array(mem_ctx, const char *, 1);
110
111         NT_STATUS_HAVE_NO_MEMORY(flag_strs);
112
113         flag_strs[0] = NULL;
114
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++;
122                 }
123         }
124         *ret = flag_strs;
125         return NT_STATUS_OK;
126 }
127
128 NTSTATUS gp_get_gplink_options(TALLOC_CTX *mem_ctx, uint32_t options, const char ***ret)
129 {
130         unsigned int i, count=0;
131         const char **flag_strs = talloc_array(mem_ctx, const char *, 1);
132
133         NT_STATUS_HAVE_NO_MEMORY(flag_strs);
134         flag_strs[0] = NULL;
135
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++;
143                 }
144         }
145         *ret = flag_strs;
146         return NT_STATUS_OK;
147 }
148
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)
154 {
155
156         struct libnet_LookupDCs *io;
157         char *url;
158         struct libnet_context *net_ctx;
159         struct ldb_context *ldb_ctx;
160         NTSTATUS rv;
161
162         /* Initialise the libnet context */
163         net_ctx = libnet_context_init(ev_ctx, lp_ctx);
164         net_ctx->cred = credentials;
165
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);
171
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;
177         }
178
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;
187         }
188
189         *gp_ctx = talloc_zero(mem_ctx, struct gp_context);
190         NT_STATUS_HAVE_NO_MEMORY(gp_ctx);
191
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]);
197
198         /* We don't need to keep the libnet context */
199         talloc_free(net_ctx);
200         return NT_STATUS_OK;
201 }
202
203 NTSTATUS gp_list_all_gpos(struct gp_context *gp_ctx, struct gp_object ***ret)
204 {
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;
213
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);
217
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;
225         }
226
227         DEBUG(10, ("Searching for policies in DN: %s\n", ldb_dn_get_linearized(dn)));
228
229         attrs = talloc_array(mem_ctx, const char *, 7);
230         if (attrs == NULL) {
231                 TALLOC_FREE(mem_ctx);
232                 return NT_STATUS_NO_MEMORY;
233         }
234
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;
242
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;
248         }
249
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;
254         }
255
256         gpo[result->count] = NULL;
257
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;
264                 }
265         }
266
267         talloc_free(mem_ctx);
268
269         *ret = gpo;
270         return NT_STATUS_OK;
271 }
272
273 NTSTATUS gp_get_gpo_info(struct gp_context *gp_ctx, const char *dn_str, struct gp_object **ret)
274 {
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;
282
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);
286
287         /* Create an ldb dn struct for the dn string */
288         dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
289
290         attrs = talloc_array(mem_ctx, const char *, 7);
291         if (attrs == NULL) {
292                 TALLOC_FREE(mem_ctx);
293                 return NT_STATUS_NO_MEMORY;
294         }
295
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;
303
304         rv = ldb_search(gp_ctx->ldb_ctx,
305                         mem_ctx,
306                         &result,
307                         dn,
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;
315         }
316
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;
322         }
323
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;
329         }
330
331         talloc_free(mem_ctx);
332
333         *ret = gpo;
334         return NT_STATUS_OK;
335 }
336
337 static NTSTATUS parse_gplink (TALLOC_CTX *mem_ctx, const char *gplink_str, struct gp_link ***ret)
338 {
339         int start, idx=0;
340         int pos;
341         struct gp_link **gplinks;
342         char *buf, *end;
343         const char *gplink_start = "[LDAP://";
344
345         gplinks = talloc_array(mem_ctx, struct gp_link *, 1);
346         NT_STATUS_HAVE_NO_MEMORY(gplinks);
347
348         gplinks[0] = NULL;
349
350         /* Assuming every gPLink starts with "[LDAP://" */
351         start = strlen(gplink_start);
352
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;
365                         }
366
367                         for (start = pos + 1; gplink_str[pos] != ']'; pos++);
368
369                         buf = talloc_strndup(gplinks, gplink_str + start, pos - start);
370                         if (buf == NULL) {
371                                 TALLOC_FREE(gplinks);
372                                 return NT_STATUS_NO_MEMORY;
373                         }
374                         gplinks[idx]->options = (uint32_t) strtoll(buf, &end, 0);
375                         talloc_free(buf);
376
377                         /* Set the last entry in the array to be NULL */
378                         gplinks[idx + 1] = NULL;
379
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;
385                 }
386         }
387
388         *ret = gplinks;
389         return NT_STATUS_OK;
390 }
391
392
393 NTSTATUS gp_get_gplinks(struct gp_context *gp_ctx, const char *dn_str, struct gp_link ***ret)
394 {
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, j;
402         NTSTATUS status;
403
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);
407
408         dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
409
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;
415         }
416
417         for (i = 0; i < result->count; i++) {
418                 for (j = 0; j < result->msgs[i]->num_elements; j++) {
419                         struct ldb_message_element *element = &result->msgs[i]->elements[j];
420
421                         if (strcmp(element->name, "gPLink") == 0) {
422                                 SMB_ASSERT(element->num_values > 0);
423                                 gplink_str = talloc_strdup(mem_ctx, (char *) element->values[0].data);
424                                 if (gplink_str == NULL) {
425                                         TALLOC_FREE(mem_ctx);
426                                         return NT_STATUS_NO_MEMORY;
427                                 }
428                                 goto found;
429                         }
430                 }
431         }
432         gplink_str = talloc_strdup(mem_ctx, "");
433         if (gplink_str == NULL) {
434                 TALLOC_FREE(mem_ctx);
435                 return NT_STATUS_NO_MEMORY;
436         }
437
438         found:
439
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;
444         }
445
446         talloc_free(mem_ctx);
447
448         *ret = gplinks;
449         return NT_STATUS_OK;
450 }
451
452 NTSTATUS gp_list_gpos(struct gp_context *gp_ctx, struct security_token *token, const char ***ret)
453 {
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;
470
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);
474
475         sid = ldap_encode_ndr_dom_sid(mem_ctx,
476                                       &token->sids[PRIMARY_USER_SID_INDEX]);
477         NT_STATUS_HAVE_NO_MEMORY(sid);
478
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;
492         }
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;
497         }
498         DEBUG(10,("Found DN for this user: %s\n", ldb_dn_get_linearized(result->msgs[0]->dn)));
499
500         element = ldb_msg_find_element(result->msgs[0], "objectClass");
501
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"));
508                 }
509         }
510
511         gpos = talloc_array(gp_ctx, const char *, 1);
512         if (gpos == NULL) {
513                 TALLOC_FREE(mem_ctx);
514                 return NT_STATUS_NO_MEMORY;
515         }
516         gpos[0] = NULL;
517
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;
525
526                 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                 rv = ldb_search(gp_ctx->ldb_ctx,
530                                 mem_ctx,
531                                 &result,
532                                 dn,
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;
541                 }
542
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;
549                 }
550
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;
555
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;
560
561                         /* Don't apply disabled links */
562                         if (gplinks[i]->options & GPLINK_OPT_DISABLE)
563                                 continue;
564
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;
571                         }
572
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;
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                         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;
591                         }
592
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;
598                         }
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;
603                         }
604                         gpos[count+1] = NULL;
605                         count++;
606
607                         /* Clean up */
608                         talloc_free(gpo);
609                 }
610
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;
616                 }
617                 dn = ldb_dn_get_parent(mem_ctx, dn);
618         }
619
620         talloc_free(mem_ctx);
621
622         *ret = gpos;
623         return NT_STATUS_OK;
624 }
625
626 NTSTATUS gp_set_gplink(struct gp_context *gp_ctx, const char *dn_str, struct gp_link *gplink)
627 {
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;
636
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);
640
641         dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
642
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;
648         }
649
650         if (result->count != 1) {
651                 talloc_free(mem_ctx);
652                 return NT_STATUS_NOT_FOUND;
653         }
654
655         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         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++;
664                 }
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;
669                 }
670
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;
677                 }
678         }
679
680
681
682         msg = ldb_msg_new(mem_ctx);
683         if (msg == NULL) {
684                 TALLOC_FREE(mem_ctx);
685                 return NT_STATUS_NO_MEMORY;
686         }
687
688         msg->dn = dn;
689
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;
695         }
696         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
697
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;
703         }
704
705         talloc_free(mem_ctx);
706         return NT_STATUS_OK;
707 }
708
709 NTSTATUS gp_del_gplink(struct gp_context *gp_ctx, const char *dn_str, const char *gplink_dn)
710 {
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;
719
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);
723
724         dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
725
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;
731         }
732
733         if (result->count != 1) {
734                 talloc_free(mem_ctx);
735                 return NT_STATUS_NOT_FOUND;
736         }
737
738         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         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;
745         }
746
747         p = strcasestr(gplink_str, search_string);
748         if (p == NULL) {
749                 talloc_free(mem_ctx);
750                 return NT_STATUS_NOT_FOUND;
751         }
752
753         *p = '\0';
754         p++;
755         while (*p != ']' && *p != '\0') {
756                 p++;
757         }
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;
763         }
764
765
766         msg = ldb_msg_new(mem_ctx);
767         if (msg == NULL) {
768                 TALLOC_FREE(mem_ctx);
769                 return NT_STATUS_NO_MEMORY;
770         }
771
772         msg->dn = dn;
773
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;
780                 }
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;
787                 }
788                 msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
789         }
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;
795         }
796
797         talloc_free(mem_ctx);
798         return NT_STATUS_OK;
799 }
800
801 NTSTATUS gp_get_inheritance(struct gp_context *gp_ctx, const char *dn_str, enum gpo_inheritance *inheritance)
802 {
803         TALLOC_CTX *mem_ctx;
804         struct ldb_result *result;
805         struct ldb_dn *dn;
806         const char *attrs[] = { "gPOptions", NULL };
807         int rv;
808
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);
812
813         dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
814
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;
820         }
821
822         if (result->count != 1) {
823                 talloc_free(mem_ctx);
824                 return NT_STATUS_NOT_FOUND;
825         }
826
827         *inheritance = ldb_msg_find_attr_as_uint(result->msgs[0], "gPOptions", 0);
828
829         talloc_free(mem_ctx);
830         return NT_STATUS_OK;
831 }
832
833 NTSTATUS gp_set_inheritance(struct gp_context *gp_ctx, const char *dn_str, enum gpo_inheritance inheritance)
834 {
835         char *inheritance_string;
836         struct ldb_message *msg;
837         int rv;
838
839         msg = ldb_msg_new(gp_ctx);
840         NT_STATUS_HAVE_NO_MEMORY(msg);
841
842         msg->dn = ldb_dn_new(msg, gp_ctx->ldb_ctx, dn_str);
843
844         inheritance_string = talloc_asprintf(msg, "%d", inheritance);
845         if (inheritance_string == NULL) {
846                 TALLOC_FREE(msg);
847                 return NT_STATUS_NO_MEMORY;
848         }
849
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;
855         }
856         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
857
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;
863         }
864
865         talloc_free(msg);
866         return NT_STATUS_OK;
867 }
868
869 NTSTATUS gp_create_ldap_gpo(struct gp_context *gp_ctx, struct gp_object *gpo)
870 {
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;
876
877         mem_ctx = talloc_new(gp_ctx);
878         NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
879
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;
885         }
886
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;
892         }
893
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;
897
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;
902         }
903
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;
908         }
909
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;
932
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;
938         }
939
940         gpo_dn = msg->dn;
941
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;
947         }
948
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;
953
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;
964
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;
970         }
971
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;
977         }
978
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;
983
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;
994
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;
1000         }
1001
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;
1006         }
1007
1008         talloc_free(mem_ctx);
1009         return NT_STATUS_OK;
1010
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;
1015 }
1016
1017 NTSTATUS gp_set_ads_acl (struct gp_context *gp_ctx, const char *dn_str, const struct security_descriptor *sd)
1018 {
1019         TALLOC_CTX *mem_ctx;
1020         DATA_BLOB data;
1021         enum ndr_err_code ndr_err;
1022         struct ldb_message *msg;
1023         int rv;
1024
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);
1028
1029         /* Push the security descriptor through the NDR library */
1030         ndr_err = ndr_push_struct_blob(&data,
1031                         mem_ctx,
1032                         sd,
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);
1036         }
1037
1038
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;
1044         }
1045
1046         msg->dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, dn_str);
1047
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;
1053         }
1054         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1055
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;
1061         }
1062
1063         talloc_free(mem_ctx);
1064         return NT_STATUS_OK;
1065 }
1066
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)
1069 {
1070         int rv;
1071         TALLOC_CTX *mem_ctx;
1072         struct ldb_message *msg;
1073         char *version_str, *flags_str;
1074
1075         mem_ctx = talloc_new(gp_ctx);
1076
1077         msg = ldb_msg_new(mem_ctx);
1078         if (msg == NULL) {
1079                 TALLOC_FREE(mem_ctx);
1080                 return NT_STATUS_NO_MEMORY;
1081         }
1082
1083         msg->dn = ldb_dn_new(mem_ctx, gp_ctx->ldb_ctx, gpo->dn);
1084
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;
1089         }
1090
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;
1095         }
1096
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;
1102         }
1103         msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
1104
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;
1110         }
1111         msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
1112
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;
1118         }
1119         msg->elements[2].flags = LDB_FLAG_MOD_REPLACE;
1120
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;
1126         }
1127
1128         talloc_free(mem_ctx);
1129         return NT_STATUS_OK;
1130 }