3c66325abec62c91df05aa79ad0a98843d806536
[sfrench/samba-autobuild/.git] / source3 / utils / net_ads_gpo.c
1 /*
2    Samba Unix/Linux SMB client library
3    net ads commands for Group Policy
4    Copyright (C) 2005-2008 Guenther Deschner (gd@samba.org)
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "utils/net.h"
22
23 #ifdef HAVE_ADS
24
25 static int net_ads_gpo_refresh(struct net_context *c, int argc, const char **argv)
26 {
27         TALLOC_CTX *mem_ctx;
28         ADS_STRUCT *ads;
29         ADS_STATUS status;
30         const char *dn = NULL;
31         struct GROUP_POLICY_OBJECT *gpo_list = NULL;
32         struct GROUP_POLICY_OBJECT *read_list = NULL;
33         uint32 uac = 0;
34         uint32 flags = 0;
35         struct GROUP_POLICY_OBJECT *gpo;
36         NTSTATUS result;
37         struct nt_user_token *token = NULL;
38
39         if (argc < 1 || c->display_usage) {
40                 d_printf("Usage:\n"
41                          "net ads gpo refresh <username|machinename>\n"
42                          "  Lists all GPOs assigned to an account and "
43                          "downloads them\n"
44                          "    username\tUser to refresh GPOs for\n"
45                          "    machinename\tMachine to refresh GPOs for\n");
46                 return -1;
47         }
48
49         mem_ctx = talloc_init("net_ads_gpo_refresh");
50         if (mem_ctx == NULL) {
51                 return -1;
52         }
53
54         status = ads_startup(c, false, &ads);
55         if (!ADS_ERR_OK(status)) {
56                 d_printf("failed to connect AD server: %s\n", ads_errstr(status));
57                 goto out;
58         }
59
60         status = ads_find_samaccount(ads, mem_ctx, argv[0], &uac, &dn);
61         if (!ADS_ERR_OK(status)) {
62                 d_printf("failed to find samaccount for %s\n", argv[0]);
63                 goto out;
64         }
65
66         if (uac & UF_WORKSTATION_TRUST_ACCOUNT) {
67                 flags |= GPO_LIST_FLAG_MACHINE;
68         }
69
70         d_printf("\n%s: '%s' has dn: '%s'\n\n",
71                 (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user",
72                 argv[0], dn);
73
74         d_printf("* fetching token ");
75         if (uac & UF_WORKSTATION_TRUST_ACCOUNT) {
76                 status = gp_get_machine_token(ads, mem_ctx, dn, &token);
77         } else {
78                 status = ads_get_sid_token(ads, mem_ctx, dn, &token);
79         }
80
81         if (!ADS_ERR_OK(status)) {
82                 d_printf("failed: %s\n", ads_errstr(status));
83                 goto out;
84         }
85         d_printf("finished\n");
86
87         d_printf("* fetching GPO List ");
88         status = ads_get_gpo_list(ads, mem_ctx, dn, flags, token, &gpo_list);
89         if (!ADS_ERR_OK(status)) {
90                 d_printf("failed: %s\n", ads_errstr(status));
91                 goto out;
92         }
93         d_printf("finished\n");
94
95         d_printf("* refreshing Group Policy Data ");
96         if (!NT_STATUS_IS_OK(result = check_refresh_gpo_list(ads, mem_ctx,
97                                                              flags,
98                                                              gpo_list))) {
99                 d_printf("failed: %s\n", nt_errstr(result));
100                 goto out;
101         }
102         d_printf("finished\n");
103
104         d_printf("* storing GPO list to registry ");
105
106         {
107                 WERROR werr = gp_reg_state_store(mem_ctx, flags, dn,
108                                                  token, gpo_list);
109                 if (!W_ERROR_IS_OK(werr)) {
110                         d_printf("failed: %s\n", dos_errstr(werr));
111                         goto out;
112                 }
113         }
114
115         d_printf("finished\n");
116
117         if (c->opt_verbose) {
118
119                 d_printf("* dumping GPO list\n");
120
121                 for (gpo = gpo_list; gpo; gpo = gpo->next) {
122
123                         dump_gpo(ads, mem_ctx, gpo, 0);
124 #if 0
125                 char *server, *share, *nt_path, *unix_path;
126
127                 d_printf("--------------------------------------\n");
128                 d_printf("Name:\t\t\t%s\n", gpo->display_name);
129                 d_printf("LDAP GPO version:\t%d (user: %d, machine: %d)\n",
130                         gpo->version,
131                         GPO_VERSION_USER(gpo->version),
132                         GPO_VERSION_MACHINE(gpo->version));
133
134                 result = gpo_explode_filesyspath(mem_ctx, gpo->file_sys_path,
135                                                  &server, &share, &nt_path,
136                                                  &unix_path);
137                 if (!NT_STATUS_IS_OK(result)) {
138                         d_printf("got: %s\n", nt_errstr(result));
139                 }
140
141                 d_printf("GPO stored on server: %s, share: %s\n", server, share);
142                 d_printf("\tremote path:\t%s\n", nt_path);
143                 d_printf("\tlocal path:\t%s\n", unix_path);
144 #endif
145                 }
146         }
147
148         d_printf("* re-reading GPO list from registry ");
149
150         {
151                 WERROR werr = gp_reg_state_read(mem_ctx, flags,
152                                                 &token->user_sids[0],
153                                                 &read_list);
154                 if (!W_ERROR_IS_OK(werr)) {
155                         d_printf("failed: %s\n", dos_errstr(werr));
156                         goto out;
157                 }
158         }
159
160         d_printf("finished\n");
161
162         if (c->opt_verbose) {
163
164                 d_printf("* dumping GPO list from registry\n");
165
166                 for (gpo = read_list; gpo; gpo = gpo->next) {
167
168                         dump_gpo(ads, mem_ctx, gpo, 0);
169
170 #if 0
171                 char *server, *share, *nt_path, *unix_path;
172
173                 d_printf("--------------------------------------\n");
174                 d_printf("Name:\t\t\t%s\n", gpo->display_name);
175                 d_printf("LDAP GPO version:\t%d (user: %d, machine: %d)\n",
176                         gpo->version,
177                         GPO_VERSION_USER(gpo->version),
178                         GPO_VERSION_MACHINE(gpo->version));
179
180                 result = gpo_explode_filesyspath(mem_ctx, gpo->file_sys_path,
181                                                  &server, &share, &nt_path,
182                                                  &unix_path);
183                 if (!NT_STATUS_IS_OK(result)) {
184                         d_printf("got: %s\n", nt_errstr(result));
185                 }
186
187                 d_printf("GPO stored on server: %s, share: %s\n", server, share);
188                 d_printf("\tremote path:\t%s\n", nt_path);
189                 d_printf("\tlocal path:\t%s\n", unix_path);
190 #endif
191                 }
192         }
193
194  out:
195         ads_destroy(&ads);
196         talloc_destroy(mem_ctx);
197         return 0;
198 }
199
200 static int net_ads_gpo_list_all(struct net_context *c, int argc, const char **argv)
201 {
202         ADS_STRUCT *ads;
203         ADS_STATUS status;
204         LDAPMessage *res = NULL;
205         int num_reply = 0;
206         LDAPMessage *msg = NULL;
207         struct GROUP_POLICY_OBJECT gpo;
208         TALLOC_CTX *mem_ctx;
209         char *dn;
210         const char *attrs[] = {
211                 "versionNumber",
212                 "flags",
213                 "gPCFileSysPath",
214                 "displayName",
215                 "name",
216                 "gPCMachineExtensionNames",
217                 "gPCUserExtensionNames",
218                 "ntSecurityDescriptor",
219                 NULL
220         };
221
222         if (c->display_usage) {
223                 d_printf("Usage:\n"
224                          "net ads gpo listall\n"
225                          "    List all GPOs on the DC\n");
226                 return 0;
227         }
228
229         mem_ctx = talloc_init("net_ads_gpo_list_all");
230         if (mem_ctx == NULL) {
231                 return -1;
232         }
233
234         status = ads_startup(c, false, &ads);
235         if (!ADS_ERR_OK(status)) {
236                 goto out;
237         }
238
239         status = ads_do_search_all_sd_flags(ads, ads->config.bind_path,
240                                             LDAP_SCOPE_SUBTREE,
241                                             "(objectclass=groupPolicyContainer)",
242                                             attrs,
243                                             DACL_SECURITY_INFORMATION,
244                                             &res);
245
246         if (!ADS_ERR_OK(status)) {
247                 d_printf("search failed: %s\n", ads_errstr(status));
248                 goto out;
249         }
250
251         num_reply = ads_count_replies(ads, res);
252
253         d_printf("Got %d replies\n\n", num_reply);
254
255         /* dump the results */
256         for (msg = ads_first_entry(ads, res);
257              msg;
258              msg = ads_next_entry(ads, msg)) {
259
260                 if ((dn = ads_get_dn(ads, msg)) == NULL) {
261                         goto out;
262                 }
263
264                 status = ads_parse_gpo(ads, mem_ctx, msg, dn, &gpo);
265
266                 if (!ADS_ERR_OK(status)) {
267                         d_printf("ads_parse_gpo failed: %s\n",
268                                 ads_errstr(status));
269                         ads_memfree(ads, dn);
270                         goto out;
271                 }
272
273                 dump_gpo(ads, mem_ctx, &gpo, 0);
274                 ads_memfree(ads, dn);
275         }
276
277 out:
278         ads_msgfree(ads, res);
279
280         talloc_destroy(mem_ctx);
281         ads_destroy(&ads);
282
283         return 0;
284 }
285
286 static int net_ads_gpo_list(struct net_context *c, int argc, const char **argv)
287 {
288         ADS_STRUCT *ads;
289         ADS_STATUS status;
290         LDAPMessage *res = NULL;
291         TALLOC_CTX *mem_ctx;
292         const char *dn = NULL;
293         uint32 uac = 0;
294         uint32 flags = 0;
295         struct GROUP_POLICY_OBJECT *gpo_list;
296         struct nt_user_token *token = NULL;
297
298         if (argc < 1 || c->display_usage) {
299                 d_printf("Usage:\n"
300                          "net ads gpo list <username|machinename>\n"
301                          "  Lists all GPOs for machine/user\n"
302                          "    username\tUser to list GPOs for\n"
303                          "    machinename\tMachine to list GPOs for\n");
304                 return -1;
305         }
306
307         mem_ctx = talloc_init("net_ads_gpo_list");
308         if (mem_ctx == NULL) {
309                 goto out;
310         }
311
312         status = ads_startup(c, false, &ads);
313         if (!ADS_ERR_OK(status)) {
314                 goto out;
315         }
316
317         status = ads_find_samaccount(ads, mem_ctx, argv[0], &uac, &dn);
318         if (!ADS_ERR_OK(status)) {
319                 goto out;
320         }
321
322         if (uac & UF_WORKSTATION_TRUST_ACCOUNT) {
323                 flags |= GPO_LIST_FLAG_MACHINE;
324         }
325
326         d_printf("%s: '%s' has dn: '%s'\n",
327                 (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user",
328                 argv[0], dn);
329
330         if (uac & UF_WORKSTATION_TRUST_ACCOUNT) {
331                 status = gp_get_machine_token(ads, mem_ctx, dn, &token);
332         } else {
333                 status = ads_get_sid_token(ads, mem_ctx, dn, &token);
334         }
335
336         if (!ADS_ERR_OK(status)) {
337                 goto out;
338         }
339
340         status = ads_get_gpo_list(ads, mem_ctx, dn, flags, token, &gpo_list);
341         if (!ADS_ERR_OK(status)) {
342                 goto out;
343         }
344
345         dump_gpo_list(ads, mem_ctx, gpo_list, 0);
346
347 out:
348         ads_msgfree(ads, res);
349
350         talloc_destroy(mem_ctx);
351         ads_destroy(&ads);
352
353         return 0;
354 }
355
356 #if 0
357 static int net_ads_gpo_apply(struct net_context *c, int argc, const char **argv)
358 {
359         TALLOC_CTX *mem_ctx;
360         ADS_STRUCT *ads;
361         ADS_STATUS status;
362         const char *dn = NULL;
363         struct GROUP_POLICY_OBJECT *gpo_list;
364         uint32 uac = 0;
365         uint32 flags = 0;
366         struct nt_user_token *token = NULL;
367         const char *filter = NULL;
368
369         if (argc < 1 || c->display_usage) {
370                 d_printf("Usage:\n"
371                          "net ads gpo apply <username|machinename>\n"
372                          "  Apply GPOs for machine/user\n"
373                          "    username\tUsername to apply GPOs for\n"
374                          "    machinename\tMachine to apply GPOs for\n");
375                 return -1;
376         }
377
378         mem_ctx = talloc_init("net_ads_gpo_apply");
379         if (mem_ctx == NULL) {
380                 goto out;
381         }
382
383         if (argc >= 2) {
384                 filter = cse_gpo_name_to_guid_string(argv[1]);
385         }
386
387         status = ads_startup(c, false, &ads);
388         if (!ADS_ERR_OK(status)) {
389                 d_printf("got: %s\n", ads_errstr(status));
390                 goto out;
391         }
392
393         status = ads_find_samaccount(ads, mem_ctx, argv[0], &uac, &dn);
394         if (!ADS_ERR_OK(status)) {
395                 d_printf("failed to find samaccount for %s: %s\n",
396                         argv[0], ads_errstr(status));
397                 goto out;
398         }
399
400         if (uac & UF_WORKSTATION_TRUST_ACCOUNT) {
401                 flags |= GPO_LIST_FLAG_MACHINE;
402         }
403
404         if (opt_verbose) {
405                 flags |= GPO_INFO_FLAG_VERBOSE;
406         }
407
408         d_printf("%s: '%s' has dn: '%s'\n",
409                 (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user",
410                 argv[0], dn);
411
412         if (uac & UF_WORKSTATION_TRUST_ACCOUNT) {
413                 status = gp_get_machine_token(ads, mem_ctx, dn, &token);
414         } else {
415                 status = ads_get_sid_token(ads, mem_ctx, dn, &token);
416         }
417
418         if (!ADS_ERR_OK(status)) {
419                 goto out;
420         }
421
422         status = ads_get_gpo_list(ads, mem_ctx, dn, flags, token, &gpo_list);
423         if (!ADS_ERR_OK(status)) {
424                 goto out;
425         }
426
427         status = gpo_process_gpo_list(ads, mem_ctx, token, gpo_list,
428                                       filter, flags);
429         if (!ADS_ERR_OK(status)) {
430                 d_printf("failed to process gpo list: %s\n",
431                         ads_errstr(status));
432                 goto out;
433         }
434
435 out:
436         ads_destroy(&ads);
437         talloc_destroy(mem_ctx);
438         return 0;
439 }
440 #endif
441
442 static int net_ads_gpo_link_get(struct net_context *c, int argc, const char **argv)
443 {
444         ADS_STRUCT *ads;
445         ADS_STATUS status;
446         TALLOC_CTX *mem_ctx;
447         struct GP_LINK gp_link;
448
449         if (argc < 1 || c->display_usage) {
450                 d_printf("Usage:\n"
451                          "net ads gpo linkget <container>\n"
452                          "  Lists gPLink of a containter\n"
453                          "    container\tContainer to get link for\n");
454                 return -1;
455         }
456
457         mem_ctx = talloc_init("add_gpo_link");
458         if (mem_ctx == NULL) {
459                 return -1;
460         }
461
462         status = ads_startup(c, false, &ads);
463         if (!ADS_ERR_OK(status)) {
464                 goto out;
465         }
466
467         status = ads_get_gpo_link(ads, mem_ctx, argv[0], &gp_link);
468         if (!ADS_ERR_OK(status)) {
469                 d_printf("get link for %s failed: %s\n", argv[0],
470                         ads_errstr(status));
471                 goto out;
472         }
473
474         dump_gplink(ads, mem_ctx, &gp_link);
475
476 out:
477         talloc_destroy(mem_ctx);
478         ads_destroy(&ads);
479
480         return 0;
481 }
482
483 static int net_ads_gpo_link_add(struct net_context *c, int argc, const char **argv)
484 {
485         ADS_STRUCT *ads;
486         ADS_STATUS status;
487         uint32 gpo_opt = 0;
488         TALLOC_CTX *mem_ctx;
489
490         if (argc < 2 || c->display_usage) {
491                 d_printf("Usage:\n"
492                          "net ads gpo linkadd <linkdn> <gpodn> [options]\n"
493                          "  Link a container to a GPO\n"
494                          "    linkdn\tContainer to link to a GPO\n"
495                          "    gpodn\tGPO to link container to\n");
496                 d_printf("note: DNs must be provided properly escaped.\n");
497                 d_printf("See RFC 4514 for details\n");
498                 return -1;
499         }
500
501         mem_ctx = talloc_init("add_gpo_link");
502         if (mem_ctx == NULL) {
503                 return -1;
504         }
505
506         if (argc == 3) {
507                 gpo_opt = atoi(argv[2]);
508         }
509
510         status = ads_startup(c, false, &ads);
511         if (!ADS_ERR_OK(status)) {
512                 goto out;
513         }
514
515         status = ads_add_gpo_link(ads, mem_ctx, argv[0], argv[1], gpo_opt);
516         if (!ADS_ERR_OK(status)) {
517                 d_printf("link add failed: %s\n", ads_errstr(status));
518                 goto out;
519         }
520
521 out:
522         talloc_destroy(mem_ctx);
523         ads_destroy(&ads);
524
525         return 0;
526 }
527
528 #if 0 /* broken */
529
530 static int net_ads_gpo_link_delete(struct net_context *c, int argc, const char **argv)
531 {
532         ADS_STRUCT *ads;
533         ADS_STATUS status;
534         TALLOC_CTX *mem_ctx;
535
536         if (argc < 2 || c->display_usage) {
537                 d_printf("Usage:\n"
538                          "net ads gpo linkdelete <linkdn> <gpodn>\n"
539                          "  Delete a GPO link\n"
540                          "    <linkdn>\tContainer to delete GPO from\n"
541                          "    <gpodn>\tGPO to delete from container\n");
542                 return -1;
543         }
544
545         mem_ctx = talloc_init("delete_gpo_link");
546         if (mem_ctx == NULL) {
547                 return -1;
548         }
549
550         status = ads_startup(c, false, &ads);
551         if (!ADS_ERR_OK(status)) {
552                 goto out;
553         }
554
555         status = ads_delete_gpo_link(ads, mem_ctx, argv[0], argv[1]);
556         if (!ADS_ERR_OK(status)) {
557                 d_printf("delete link failed: %s\n", ads_errstr(status));
558                 goto out;
559         }
560
561 out:
562         talloc_destroy(mem_ctx);
563         ads_destroy(&ads);
564
565         return 0;
566 }
567
568 #endif
569
570 static int net_ads_gpo_get_gpo(struct net_context *c, int argc, const char **argv)
571 {
572         ADS_STRUCT *ads;
573         ADS_STATUS status;
574         TALLOC_CTX *mem_ctx;
575         struct GROUP_POLICY_OBJECT gpo;
576
577         if (argc < 1 || c->display_usage) {
578                 d_printf("Usage:\n"
579                          "net ads gpo getgpo <gpo>\n"
580                          "  List speciefied GPO\n"
581                          "    gpo\t\tGPO to list\n");
582                 return -1;
583         }
584
585         mem_ctx = talloc_init("ads_gpo_get_gpo");
586         if (mem_ctx == NULL) {
587                 return -1;
588         }
589
590         status = ads_startup(c, false, &ads);
591         if (!ADS_ERR_OK(status)) {
592                 goto out;
593         }
594
595         if (strnequal(argv[0], "CN={", strlen("CN={"))) {
596                 status = ads_get_gpo(ads, mem_ctx, argv[0], NULL, NULL, &gpo);
597         } else {
598                 status = ads_get_gpo(ads, mem_ctx, NULL, argv[0], NULL, &gpo);
599         }
600
601         if (!ADS_ERR_OK(status)) {
602                 d_printf("get gpo for [%s] failed: %s\n", argv[0],
603                         ads_errstr(status));
604                 goto out;
605         }
606
607         dump_gpo(ads, mem_ctx, &gpo, 1);
608
609 out:
610         talloc_destroy(mem_ctx);
611         ads_destroy(&ads);
612
613         return 0;
614 }
615
616 int net_ads_gpo(struct net_context *c, int argc, const char **argv)
617 {
618         struct functable func[] = {
619 #if 0
620                 {
621                         "apply",
622                         net_ads_gpo_apply,
623                         NET_TRANSPORT_ADS,
624                         "Apply GPO to container",
625                         "net ads gpo apply\n"
626                         "    Apply GPO to container"
627                 },
628 #endif
629                 {
630                         "getgpo",
631                         net_ads_gpo_get_gpo,
632                         NET_TRANSPORT_ADS,
633                         "List specified GPO",
634                         "net ads gpo getgpo\n"
635                         "    List specified GPO"
636                 },
637                 {
638                         "linkadd",
639                         net_ads_gpo_link_add,
640                         NET_TRANSPORT_ADS,
641                         "Link a container to a GPO",
642                         "net ads gpo linkadd\n"
643                         "    Link a container to a GPO"
644                 },
645 #if 0
646                 {
647                         "linkdelete",
648                         net_ads_gpo_link_delete,
649                         NET_TRANSPORT_ADS,
650                         "Delete GPO link from a container",
651                         "net ads gpo linkdelete\n"
652                         "    Delete GPO link from a container"
653                 },
654 #endif
655                 {
656                         "linkget",
657                         net_ads_gpo_link_get,
658                         NET_TRANSPORT_ADS,
659                         "Lists gPLink of containter",
660                         "net ads gpo linkget\n"
661                         "    Lists gPLink of containter"
662                 },
663                 {
664                         "list",
665                         net_ads_gpo_list,
666                         NET_TRANSPORT_ADS,
667                         "Lists all GPOs for machine/user",
668                         "net ads gpo list\n"
669                         "    Lists all GPOs for machine/user"
670                 },
671                 {
672                         "listall",
673                         net_ads_gpo_list_all,
674                         NET_TRANSPORT_ADS,
675                         "Lists all GPOs on a DC",
676                         "net ads gpo listall\n"
677                         "    Lists all GPOs on a DC"
678                 },
679                 {
680                         "refresh",
681                         net_ads_gpo_refresh,
682                         NET_TRANSPORT_ADS,
683                         "Lists all GPOs assigned to an account and downloads "
684                         "them",
685                         "net ads gpo refresh\n"
686                         "    Lists all GPOs assigned to an account and "
687                         "downloads them"
688                 },
689                 {NULL, NULL, 0, NULL, NULL}
690         };
691
692         return net_run_function(c, argc, argv, "net ads gpo", func);
693 }
694
695 #endif /* HAVE_ADS */