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