93aae609834f044347e12d8fdf575d74035a855f
[sfrench/samba-autobuild/.git] / source4 / samba_tool / gpo.c
1 /*
2    Samba Unix/Linux SMB client library
3    net ads commands for Group Policy
4
5    Copyright (C) 2005-2008 Guenther Deschner
6    Copyright (C) 2009 Wilco Baan Hofman
7
8    Based on Guenther's work in net_ads_gpo.h (samba 3)
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "samba_tool/samba_tool.h"
26 #include "lib/ldb/include/ldb.h"
27 #include "auth/auth.h"
28 #include "param/param.h"
29 #include "libcli/security/sddl.h"
30 #include "dsdb/samdb/samdb.h"
31 #include "dsdb/common/util.h"
32 #include "lib/policy/policy.h"
33
34 static int net_gpo_list_all_usage(struct net_context *ctx, int argc, const char **argv)
35 {
36         d_printf("Syntax: samba-tool gpo listall [options]\n");
37         d_printf("For a list of available options, please type samba-tool gpo listall --help\n");
38         return 0;
39 }
40
41 static int net_gpo_list_all(struct net_context *ctx, int argc, const char **argv)
42 {
43         struct gp_context *gp_ctx;
44         struct gp_object **gpo;
45         const char **gpo_flags;
46         unsigned int i, j;
47         NTSTATUS rv;
48
49         rv = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
50         if (!NT_STATUS_IS_OK(rv)) {
51                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(rv)));
52                 return 1;
53         }
54
55         rv = gp_list_all_gpos(gp_ctx, &gpo);
56         if (!NT_STATUS_IS_OK(rv)) {
57                 DEBUG(0, ("Failed to list all GPO's: %s\n", get_friendly_nt_error_msg(rv)));
58                 talloc_free(gp_ctx);
59                 return 1;
60         }
61
62         for (i = 0; gpo[i] != NULL; i++) {
63                 gp_get_gpo_flags(gp_ctx, gpo[i]->flags, &gpo_flags);
64
65                 d_printf("GPO          : %s\n", gpo[i]->name);
66                 d_printf("display name : %s\n", gpo[i]->display_name);
67                 d_printf("path         : %s\n", gpo[i]->file_sys_path);
68                 d_printf("dn           : %s\n", gpo[i]->dn);
69                 d_printf("version      : %d\n", gpo[i]->version);
70                 if (gpo_flags[0] == NULL) {
71                         d_printf("flags        : NONE\n");
72                 } else {
73                         d_printf("flags        : %s\n", gpo_flags[0]);
74                         for (j = 1; gpo_flags[j] != NULL; j++) {
75                                 d_printf("               %s\n", gpo_flags[i]);
76                         }
77                 }
78                 d_printf("\n");
79                 talloc_free(gpo_flags);
80         }
81         talloc_free(gp_ctx);
82
83         return 0;
84 }
85
86 static int net_gpo_get_gpo_usage(struct net_context *ctx, int argc, const char **argv)
87 {
88         d_printf("Syntax: samba-tool gpo show <dn> [options]\n");
89         d_printf("For a list of available options, please type samba-tool gpo show --help\n");
90         return 0;
91 }
92
93 static int net_gpo_get_gpo(struct net_context *ctx, int argc, const char **argv)
94 {
95         struct gp_context *gp_ctx;
96         struct gp_object *gpo;
97         const char **gpo_flags;
98         char *sddl;
99         int i;
100         NTSTATUS rv;
101
102         if (argc != 1) {
103                 return net_gpo_get_gpo_usage(ctx, argc, argv);
104         }
105
106
107         rv = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
108         if (!NT_STATUS_IS_OK(rv)) {
109                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(rv)));
110                 return 1;
111         }
112
113         rv = gp_get_gpo_info(gp_ctx, argv[0], &gpo);
114         if (!NT_STATUS_IS_OK(rv)) {
115                 DEBUG(0, ("Failed to get GPO: %s\n", get_friendly_nt_error_msg(rv)));
116                 talloc_free(gp_ctx);
117                 return 1;
118         }
119
120         gp_get_gpo_flags(gp_ctx, gpo->flags, &gpo_flags);
121
122         d_printf("GPO          : %s\n", gpo->name);
123         d_printf("display name : %s\n", gpo->display_name);
124         d_printf("path         : %s\n", gpo->file_sys_path);
125         d_printf("dn           : %s\n", gpo->dn);
126         d_printf("version      : %d\n", gpo->version);
127         if (gpo_flags[0] == NULL) {
128                 d_printf("flags        : NONE\n");
129         } else {
130                 d_printf("flags        : %s\n", gpo_flags[0]);
131                 for (i = 1; gpo_flags[i] != NULL; i++) {
132                         d_printf("               %s\n", gpo_flags[i]);
133                 }
134         }
135         sddl = sddl_encode(gp_ctx, gpo->security_descriptor, samdb_domain_sid(gp_ctx->ldb_ctx));
136         if (sddl != NULL) {
137                 d_printf("ACL          : %s\n", sddl);
138         }
139
140         d_printf("\n");
141
142         talloc_free(gp_ctx);
143         return 0;
144 }
145
146 static int net_gpo_link_get_usage(struct net_context *ctx, int argc, const char **argv)
147 {
148         d_printf("Syntax: samba-tool gpo getlink <dn> [options]\n");
149         d_printf("For a list of available options, please type samba-tool gpo getlink --help\n");
150         return 0;
151 }
152
153 static int net_gpo_link_get(struct net_context *ctx, int argc, const char **argv)
154 {
155         struct gp_context *gp_ctx;
156         struct gp_link **links;
157         NTSTATUS rv;
158         unsigned int i,j;
159         const char **options;
160
161         if (argc != 1) {
162                 return net_gpo_link_get_usage(ctx, argc, argv);
163         }
164
165         rv = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
166         if (!NT_STATUS_IS_OK(rv)) {
167                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(rv)));
168                 return 1;
169         }
170
171         rv = gp_get_gplinks(gp_ctx, argv[0], &links);
172         if (!NT_STATUS_IS_OK(rv)) {
173                 DEBUG(0, ("Failed to get gplinks: %s\n", get_friendly_nt_error_msg(rv)));
174                 talloc_free(gp_ctx);
175                 return 1;
176         }
177
178         for (i = 0; links[i] != NULL; i++) {
179                 gp_get_gplink_options(gp_ctx, links[i]->options, &options);
180
181                 d_printf("GPO DN  : %s\n", links[i]->dn);
182                 if (options[0] == NULL) {
183                         d_printf("Options : NONE\n");
184                 } else {
185                         d_printf("Options : %s\n", options[0]);
186                         for (j = 1; options[j] != NULL; j++) {
187                                 d_printf("        : %s\n", options[j]);
188                         }
189                 }
190                 d_printf("\n");
191
192                 talloc_free(options);
193         }
194
195         talloc_free(gp_ctx);
196
197         return 0;
198 }
199
200 static int net_gpo_list_usage(struct net_context *ctx, int argc, const char **argv)
201 {
202         d_printf("Syntax: samba-tool gpo list <username> [options]\n");
203         d_printf("For a list of available options, please type samba-tool gpo list --help\n");
204         return 0;
205 }
206
207 static int net_gpo_list(struct net_context *ctx, int argc, const char **argv)
208 {
209         struct gp_context *gp_ctx;
210         struct ldb_result *result;
211         struct auth_serversupplied_info *server_info;
212         struct auth_session_info *session_info;
213         DATA_BLOB dummy = { NULL, 0 };
214         const char **gpos;
215         NTSTATUS status;
216         int rv;
217         unsigned int i;
218
219         if (argc != 1) {
220                 return net_gpo_list_usage(ctx, argc, argv);
221         }
222
223         status = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
224         if (!NT_STATUS_IS_OK(status)) {
225                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(status)));
226                 return 1;
227         }
228
229         /* Find the user in the directory. We need extended DN's for group expansion
230          * in authsam_make_server_info */
231         rv = dsdb_search(gp_ctx->ldb_ctx,
232                         gp_ctx,
233                         &result,
234                         ldb_get_default_basedn(gp_ctx->ldb_ctx),
235                         LDB_SCOPE_SUBTREE,
236                         NULL,
237                         DSDB_SEARCH_SHOW_EXTENDED_DN,
238                         "(&(objectClass=user)(sAMAccountName=%s))", argv[0]);
239         if (rv != LDB_SUCCESS) {
240                 DEBUG(0, ("LDB search failed: %s\n%s\n", ldb_strerror(rv),ldb_errstring(gp_ctx->ldb_ctx)));
241                 talloc_free(gp_ctx);
242                 return 1;
243         }
244
245         /* We expect exactly one record */
246         if (result->count != 1) {
247                 DEBUG(0, ("Could not find SAM account with name %s\n", argv[0]));
248                 talloc_free(gp_ctx);
249                 return 1;
250         }
251
252         /* We need the server info, as this will contain the groups of this
253          * user, needed for a token */
254         status = authsam_make_server_info(gp_ctx,
255                         gp_ctx->ldb_ctx,
256                         lpcfg_netbios_name(gp_ctx->lp_ctx),
257                         lpcfg_sam_name(gp_ctx->lp_ctx),
258                         ldb_get_default_basedn(gp_ctx->ldb_ctx),
259                         result->msgs[0],
260                         dummy,
261                         dummy,
262                         &server_info);
263         if (!NT_STATUS_IS_OK(status)) {
264                 DEBUG(0, ("Failed to make server information: %s\n", get_friendly_nt_error_msg(status)));
265                 talloc_free(gp_ctx);
266                 return 1;
267         }
268
269         /* The session info will contain the security token for this user */
270         status = auth_generate_session_info(gp_ctx, gp_ctx->lp_ctx, gp_ctx->ldb_ctx, server_info, 0, &session_info);
271         if (!NT_STATUS_IS_OK(status)) {
272                 DEBUG(0, ("Failed to generate session information: %s\n", get_friendly_nt_error_msg(status)));
273                 talloc_free(gp_ctx);
274                 return 1;
275         }
276
277         status = gp_list_gpos(gp_ctx, session_info->security_token, &gpos);
278         if (!NT_STATUS_IS_OK(status)) {
279                 DEBUG(0, ("Failed to list gpos for user %s: %s\n", argv[0],
280                                 get_friendly_nt_error_msg(status)));
281                 talloc_free(gp_ctx);
282                 return 1;
283         }
284
285         d_printf("GPO's for user %s:\n", argv[0]);
286         for (i = 0; gpos[i] != NULL; i++) {
287                 d_printf("\t%s\n", gpos[i]);
288         }
289
290         talloc_free(gp_ctx);
291         return 0;
292 }
293
294 static int net_gpo_link_set_usage(struct net_context *ctx, int argc, const char **argv)
295 {
296         d_printf("Syntax: samba-tool gpo setlink <container> <gpo> ['disable'] ['enforce'] [options]\n");
297         d_printf("For a list of available options, please type samba-tool gpo setlink --help\n");
298         return 0;
299 }
300
301 static int net_gpo_link_set(struct net_context *ctx, int argc, const char **argv)
302 {
303         struct gp_link *gplink = talloc_zero(ctx, struct gp_link);
304         struct gp_context *gp_ctx;
305         unsigned int i;
306         NTSTATUS status;
307
308         if (argc < 2) {
309                 return net_gpo_link_set_usage(ctx, argc, argv);
310         }
311
312         if (argc >= 3) {
313                 for (i = 2; i < argc; i++) {
314                         if (strcmp(argv[i], "disable") == 0) {
315                                 gplink->options |= GPLINK_OPT_DISABLE;
316                         }
317                         if (strcmp(argv[i], "enforce") == 0) {
318                                 gplink->options |= GPLINK_OPT_ENFORCE;
319                         }
320                 }
321         }
322         gplink->dn = argv[1];
323
324         status = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
325         if (!NT_STATUS_IS_OK(status)) {
326                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(status)));
327                 return 1;
328         }
329
330         status = gp_set_gplink(gp_ctx, argv[0], gplink);
331         if (!NT_STATUS_IS_OK(status)) {
332                 DEBUG(0, ("Failed to set GPO link on container: %s\n", get_friendly_nt_error_msg(status)));
333                 return 1;
334         }
335         d_printf("Set link on container.\nCurrent Group Policy links:\n");
336
337         /* Display current links */
338         net_gpo_link_get(ctx, 1, argv);
339
340         talloc_free(gp_ctx);
341         return 0;
342 }
343
344 static int net_gpo_link_del_usage(struct net_context *ctx, int argc, const char **argv)
345 {
346         d_printf("Syntax: samba-tool gpo dellink <container> <gpo> [options]\n");
347         d_printf("For a list of available options, please type samba-tool gpo dellink --help\n");
348         return 0;
349 }
350
351 static int net_gpo_link_del(struct net_context *ctx, int argc, const char **argv)
352 {
353         struct gp_context *gp_ctx;
354         NTSTATUS status;
355
356         if (argc != 2) {
357                 return net_gpo_link_del_usage(ctx, argc, argv);
358         }
359
360         status = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
361         if (!NT_STATUS_IS_OK(status)) {
362                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(status)));
363                 return 1;
364         }
365
366         status = gp_del_gplink(gp_ctx, argv[0], argv[1]);
367         if (!NT_STATUS_IS_OK(status)) {
368                 DEBUG(0, ("Failed to delete gplink: %s\n", get_friendly_nt_error_msg(status)));
369                 talloc_free(gp_ctx);
370                 return 1;
371         }
372         d_printf("Deleted gplink.\nCurrent Group Policy links:\n\n");
373
374         /* Display current links */
375         net_gpo_link_get(ctx, 1, argv);
376
377         talloc_free(gp_ctx);
378         return 0;
379 }
380
381 static int net_gpo_inheritance_get_usage(struct net_context *ctx, int argc, const char **argv)
382 {
383         d_printf("Syntax: samba-tool gpo getinheritance <container> [options]\n");
384         d_printf("For a list of available options, please type samba-tool gpo getinheritance --help\n");
385         return 0;
386 }
387
388 static int net_gpo_inheritance_get(struct net_context *ctx, int argc, const char **argv)
389 {
390         struct gp_context *gp_ctx;
391         enum gpo_inheritance inheritance;
392         NTSTATUS status;
393
394         if (argc != 1) {
395                 return net_gpo_inheritance_get_usage(ctx, argc, argv);
396         }
397
398         status = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
399         if (!NT_STATUS_IS_OK(status)) {
400                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(status)));
401                 return 1;
402         }
403
404         status = gp_get_inheritance(gp_ctx, argv[0], &inheritance);
405         if (!NT_STATUS_IS_OK(status)) {
406                 DEBUG(0, ("Failed to set GPO link on container: %s\n", get_friendly_nt_error_msg(status)));
407                 talloc_free(gp_ctx);
408                 return 1;
409         }
410
411         if (inheritance == GPO_BLOCK_INHERITANCE) {
412                 d_printf("container has GPO_BLOCK_INHERITANCE\n");
413         } else {
414                 d_printf("container has GPO_INHERIT\n");
415         }
416
417         talloc_free(gp_ctx);
418         return 0;
419 }
420
421 static int net_gpo_inheritance_set_usage(struct net_context *ctx, int argc, const char **argv)
422 {
423         d_printf("Syntax: samba-tool gpo setinheritance <container> <\"block\"|\"inherit\"> [options]\n");
424         d_printf("For a list of available options, please type samba-tool gpo setinheritance --help\n");
425         return 0;
426 }
427
428 static int net_gpo_inheritance_set(struct net_context *ctx, int argc, const char **argv)
429 {
430         struct gp_context *gp_ctx;
431         enum gpo_inheritance inheritance;
432         NTSTATUS status;
433
434         if (argc != 2) {
435                 return net_gpo_inheritance_set_usage(ctx, argc, argv);
436         }
437
438         if (strcmp(argv[1], "inherit") == 0) {
439                 inheritance = GPO_INHERIT;
440         } else if (strcmp(argv[1], "block") == 0) {
441                 inheritance = GPO_BLOCK_INHERITANCE;
442         } else {
443                 return net_gpo_inheritance_set_usage(ctx, argc, argv);
444         }
445
446         status = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
447         if (!NT_STATUS_IS_OK(status)) {
448                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(status)));
449                 return 1;
450         }
451
452         status = gp_set_inheritance(gp_ctx, argv[0], inheritance);
453         if (!NT_STATUS_IS_OK(status)) {
454                 DEBUG(0, ("Failed to set GPO link on container: %s\n", get_friendly_nt_error_msg(status)));
455                 talloc_free(gp_ctx);
456                 return 1;
457         }
458
459         /* Display current links */
460         net_gpo_inheritance_get(ctx, 1, argv);
461
462         return 0;
463 }
464
465 static int net_gpo_fetch_usage(struct net_context *ctx, int argc, const char **argv)
466 {
467         d_printf("Syntax: samba-tool gpo fetch <container> [options]\n");
468         d_printf("For a list of available options, please type samba-tool gpo fetch --help\n");
469         return 0;
470 }
471
472 static int net_gpo_fetch(struct net_context *ctx, int argc, const char **argv)
473 {
474         struct gp_context *gp_ctx;
475         struct gp_object *gpo;
476         const char *path;
477         NTSTATUS rv;
478
479         if (argc != 1) {
480                 return net_gpo_fetch_usage(ctx, argc, argv);
481         }
482
483         rv = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
484         if (!NT_STATUS_IS_OK(rv)) {
485                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(rv)));
486                 return 1;
487         }
488
489         rv = gp_get_gpo_info(gp_ctx, argv[0], &gpo);
490         if (!NT_STATUS_IS_OK(rv)) {
491                 DEBUG(0, ("Failed to get GPO: %s\n", get_friendly_nt_error_msg(rv)));
492                 talloc_free(gp_ctx);
493                 return 1;
494         }
495
496         rv = gp_fetch_gpt(gp_ctx, gpo, &path);
497         if (!NT_STATUS_IS_OK(rv)) {
498                 DEBUG(0, ("Failed to fetch GPO: %s\n", get_friendly_nt_error_msg(rv)));
499                 talloc_free(gp_ctx);
500                 return 1;
501         }
502         d_printf("%s\n", path);
503
504         return 0;
505 }
506 static int net_gpo_create_usage(struct net_context *ctx, int argc, const char **argv)
507 {
508         d_printf("Syntax: samba-tool gpo create <displayname> [options]\n");
509         d_printf("For a list of available options, please type samba-tool gpo create --help\n");
510         return 0;
511 }
512
513 static int net_gpo_create(struct net_context *ctx, int argc, const char **argv)
514 {
515         struct gp_context *gp_ctx;
516         struct gp_object *gpo;
517         NTSTATUS rv;
518
519         if (argc != 1) {
520                 return net_gpo_create_usage(ctx, argc, argv);
521         }
522
523         rv = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
524         if (!NT_STATUS_IS_OK(rv)) {
525                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(rv)));
526                 return 1;
527         }
528
529         rv = gp_create_gpo(gp_ctx, argv[0], &gpo);
530         if (!NT_STATUS_IS_OK(rv)) {
531                 DEBUG(0, ("Failed to create GPO: %s\n", get_friendly_nt_error_msg(rv)));
532                 talloc_free(gp_ctx);
533                 return 1;
534         }
535
536
537         return 0;
538 }
539
540 static int net_gpo_set_acl_usage(struct net_context *ctx, int argc, const char **argv)
541 {
542         d_printf("Syntax: samba-tool gpo setacl <dn> <sddl> [options]\n");
543         d_printf("For a list of available options, please type samba-tool gpo setacl --help\n");
544         return 0;
545 }
546
547 static int net_gpo_set_acl(struct net_context *ctx, int argc, const char **argv)
548 {
549         struct gp_context *gp_ctx;
550         struct security_descriptor *sd;
551         NTSTATUS rv;
552
553         if (argc != 2) {
554                 return net_gpo_set_acl_usage(ctx, argc, argv);
555         }
556
557         rv = gp_init(ctx, ctx->lp_ctx, ctx->credentials, ctx->event_ctx, &gp_ctx);
558         if (!NT_STATUS_IS_OK(rv)) {
559                 DEBUG(0, ("Failed to connect to DC's LDAP: %s\n", get_friendly_nt_error_msg(rv)));
560                 return 1;
561         }
562
563         /* Convert sddl to security descriptor */
564         sd = sddl_decode(gp_ctx, argv[1], samdb_domain_sid(gp_ctx->ldb_ctx));
565         if (sd == NULL) {
566                 DEBUG(0, ("Invalid SDDL\n"));
567                 talloc_free(gp_ctx);
568                 return 1;
569         }
570
571         rv = gp_set_acl(gp_ctx, argv[0], sd);
572         if (!NT_STATUS_IS_OK(rv)) {
573                 DEBUG(0, ("Failed to set ACL on GPO: %s\n", get_friendly_nt_error_msg(rv)));
574                 talloc_free(gp_ctx);
575                 return 1;
576         }
577
578         talloc_free(gp_ctx);
579         return 0;
580 }
581
582
583
584 static const struct net_functable net_gpo_functable[] = {
585         { "listall", "List all GPO's on a DC\n", net_gpo_list_all, net_gpo_list_all_usage },
586         { "list", "List all active GPO's for a machine/user\n", net_gpo_list, net_gpo_list_usage },
587         { "show", "Show information for a GPO\n", net_gpo_get_gpo, net_gpo_get_gpo_usage },
588         { "getlink", "List gPLink of container\n", net_gpo_link_get, net_gpo_link_get_usage },
589         { "setlink", "Link a GPO to a container\n", net_gpo_link_set, net_gpo_link_set_usage },
590         { "dellink", "Delete GPO link from a container\n", net_gpo_link_del, net_gpo_link_del_usage },
591         { "getinheritance", "Get inheritance flag from a container\n", net_gpo_inheritance_get, net_gpo_inheritance_get_usage },
592         { "setinheritance", "Set inheritance flag on a container\n", net_gpo_inheritance_set, net_gpo_inheritance_set_usage },
593         { "fetch", "Download a GPO\n", net_gpo_fetch, net_gpo_fetch_usage },
594         { "create", "Create a GPO\n", net_gpo_create, net_gpo_create_usage },
595         { "setacl", "Set ACL on a GPO\n", net_gpo_set_acl, net_gpo_set_acl_usage },
596         { NULL, NULL }
597 };
598
599 int net_gpo_usage(struct net_context *ctx, int argc, const char **argv)
600 {
601         d_printf("Syntax: samba-tool gpo <command> [options]\n");
602         d_printf("For available commands, please type samba-tool gpo help\n");
603         return 0;
604 }
605
606 int net_gpo(struct net_context *ctx, int argc, const char **argv)
607 {
608         return net_run_function(ctx, argc, argv, net_gpo_functable, net_gpo_usage);
609 }