r23779: Change from v2 or later to v3 or later.
[bbaumbach/samba-autobuild/.git] / source3 / libgpo / gpo_util.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Group Policy Object Support
4  *  Copyright (C) Guenther Deschner 2005-2006
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, write to the Free Software
18  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20
21 #include "includes.h"
22
23 #ifdef HAVE_LDAP
24
25 #define DEFAULT_DOMAIN_POLICY "Default Domain Policy"
26 #define DEFAULT_DOMAIN_CONTROLLERS_POLICY "Default Domain Controllers Policy"
27
28 /* should we store a parsed guid ? */
29 struct gpo_table {
30         const char *name;
31         const char *guid_string;
32 };
33
34 struct snapin_table {
35         const char *name;
36         const char *guid_string;
37         ADS_STATUS (*snapin_fn)(ADS_STRUCT *, TALLOC_CTX *mem_ctx, const char *, const char *);
38 };
39
40 #if 0 /* unused */
41 static struct gpo_table gpo_default_policy[] = {
42         { DEFAULT_DOMAIN_POLICY, 
43                 "31B2F340-016D-11D2-945F-00C04FB984F9" },
44         { DEFAULT_DOMAIN_CONTROLLERS_POLICY, 
45                 "6AC1786C-016F-11D2-945F-00C04fB984F9" },
46         { NULL, NULL }
47 };
48 #endif
49
50 /* the following is seen in gPCMachineExtensionNames or gPCUserExtensionNames */
51
52 static struct gpo_table gpo_cse_extensions[] = {
53         { "Administrative Templates Extension", 
54                 "35378EAC-683F-11D2-A89A-00C04FBBCFA2" }, /* Registry Policy ? */
55         { "Microsoft Disc Quota", 
56                 "3610EDA5-77EF-11D2-8DC5-00C04FA31A66" },
57         { "EFS recovery", 
58                 "B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A" },
59         { "Folder Redirection", 
60                 "25537BA6-77A8-11D2-9B6C-0000F8080861" },
61         { "IP Security", 
62                 "E437BC1C-AA7D-11D2-A382-00C04F991E27" },
63         { "Internet Explorer Branding", 
64                 "A2E30F80-D7DE-11d2-BBDE-00C04F86AE3B" },
65         { "QoS Packet Scheduler", 
66                 "426031c0-0b47-4852-b0ca-ac3d37bfcb39" },
67         { "Scripts", 
68                 "42B5FAAE-6536-11D2-AE5A-0000F87571E3" },
69         { "Security", 
70                 "827D319E-6EAC-11D2-A4EA-00C04F79F83A" },
71         { "Software Installation", 
72                 "C6DC5466-785A-11D2-84D0-00C04FB169F7" },
73         { "Wireless Group Policy", 
74                 "0ACDD40C-75AC-BAA0-BF6DE7E7FE63" },
75         { NULL, NULL }
76 };
77
78 /* guess work */
79 static struct snapin_table gpo_cse_snapin_extensions[] = {
80         { "Administrative Templates", 
81                 "0F6B957D-509E-11D1-A7CC-0000F87571E3", gpo_snapin_handler_none },
82         { "Certificates", 
83                 "53D6AB1D-2488-11D1-A28C-00C04FB94F17", gpo_snapin_handler_none },
84         { "EFS recovery policy processing", 
85                 "B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A", gpo_snapin_handler_none },
86         { "Folder Redirection policy processing", 
87                 "25537BA6-77A8-11D2-9B6C-0000F8080861", gpo_snapin_handler_none },
88         { "Folder Redirection", 
89                 "88E729D6-BDC1-11D1-BD2A-00C04FB9603F", gpo_snapin_handler_none },
90         { "Registry policy processing", 
91                 "35378EAC-683F-11D2-A89A-00C04FBBCFA2", gpo_snapin_handler_none },
92         { "Remote Installation Services", 
93                 "3060E8CE-7020-11D2-842D-00C04FA372D4", gpo_snapin_handler_none },
94         { "Security Settings", 
95                 "803E14A0-B4FB-11D0-A0D0-00A0C90F574B", gpo_snapin_handler_security_settings },
96         { "Security policy processing", 
97                 "827D319E-6EAC-11D2-A4EA-00C04F79F83A", gpo_snapin_handler_security_settings },
98         { "unknown", 
99                 "3060E8D0-7020-11D2-842D-00C04FA372D4", gpo_snapin_handler_none },
100         { "unknown2", 
101                 "53D6AB1B-2488-11D1-A28C-00C04FB94F17", gpo_snapin_handler_none },
102         { NULL, NULL, NULL }
103 };
104
105 static const char *name_to_guid_string(const char *name, struct gpo_table *table)
106 {
107         int i;
108
109         for (i = 0; table[i].name; i++) {
110                 if (strequal(name, table[i].name)) {
111                         return table[i].guid_string;
112                 }
113         }
114         
115         return NULL;
116 }
117
118 static const char *guid_string_to_name(const char *guid_string, struct gpo_table *table)
119 {
120         int i;
121
122         for (i = 0; table[i].guid_string; i++) {
123                 if (strequal(guid_string, table[i].guid_string)) {
124                         return table[i].name;
125                 }
126         }
127         
128         return NULL;
129 }
130
131 static const char *snapin_guid_string_to_name(const char *guid_string, 
132                                               struct snapin_table *table)
133 {
134         int i;
135         for (i = 0; table[i].guid_string; i++) {
136                 if (strequal(guid_string, table[i].guid_string)) {
137                         return table[i].name;
138                 }
139         }
140         return NULL;
141 }
142
143 #if 0 /* unused */
144 static const char *default_gpo_name_to_guid_string(const char *name)
145 {
146         return name_to_guid_string(name, gpo_default_policy);
147 }
148
149 static const char *default_gpo_guid_string_to_name(const char *guid)
150 {
151         return guid_string_to_name(guid, gpo_default_policy);
152 }
153 #endif
154
155 const char *cse_gpo_guid_string_to_name(const char *guid)
156 {
157         return guid_string_to_name(guid, gpo_cse_extensions);
158 }
159
160 static const char *cse_gpo_name_to_guid_string(const char *name)
161 {
162         return name_to_guid_string(name, gpo_cse_extensions);
163 }
164
165 const char *cse_snapin_gpo_guid_string_to_name(const char *guid)
166 {
167         return snapin_guid_string_to_name(guid, gpo_cse_snapin_extensions);
168 }
169
170 void dump_gp_ext(struct GP_EXT *gp_ext, int debuglevel)
171 {
172         int lvl = debuglevel;
173         int i;
174
175         if (gp_ext == NULL) {
176                 return;
177         }
178
179         DEBUG(lvl,("\t---------------------\n\n"));
180         DEBUGADD(lvl,("\tname:\t\t\t%s\n", gp_ext->gp_extension));
181
182         for (i=0; i< gp_ext->num_exts; i++) {
183
184                 DEBUGADD(lvl,("\textension:\t\t\t%s\n", gp_ext->extensions_guid[i]));
185                 DEBUGADD(lvl,("\textension (name):\t\t\t%s\n", gp_ext->extensions[i]));
186                 
187                 DEBUGADD(lvl,("\tsnapin:\t\t\t%s\n", gp_ext->snapins_guid[i]));
188                 DEBUGADD(lvl,("\tsnapin (name):\t\t\t%s\n", gp_ext->snapins[i]));
189         }
190 }
191
192 void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo, int debuglevel) 
193 {
194         int lvl = debuglevel;
195
196         if (gpo == NULL) {
197                 return;
198         }
199
200         DEBUG(lvl,("---------------------\n\n"));
201
202         DEBUGADD(lvl,("name:\t\t\t%s\n", gpo->name));
203         DEBUGADD(lvl,("displayname:\t\t%s\n", gpo->display_name));
204         DEBUGADD(lvl,("version:\t\t%d (0x%08x)\n", gpo->version, gpo->version));
205         DEBUGADD(lvl,("version_user:\t\t%d (0x%04x)\n", GPO_VERSION_USER(gpo->version), 
206                                                         GPO_VERSION_USER(gpo->version)));
207         DEBUGADD(lvl,("version_machine:\t%d (0x%04x)\n", GPO_VERSION_MACHINE(gpo->version), 
208                                                          GPO_VERSION_MACHINE(gpo->version)));
209         DEBUGADD(lvl,("filesyspath:\t\t%s\n", gpo->file_sys_path));
210         DEBUGADD(lvl,("dspath:\t\t%s\n", gpo->ds_path));
211
212         DEBUGADD(lvl,("options:\t\t%d ", gpo->options));
213         if (gpo->options & GPFLAGS_USER_SETTINGS_DISABLED) {
214                 DEBUGADD(lvl,("GPFLAGS_USER_SETTINGS_DISABLED ")); 
215         }
216         if (gpo->options & GPFLAGS_MACHINE_SETTINGS_DISABLED) {
217                 DEBUGADD(lvl,("GPFLAGS_MACHINE_SETTINGS_DISABLED")); 
218         }
219         DEBUGADD(lvl,("\n"));
220
221         DEBUGADD(lvl,("link:\t\t\t%s\n", gpo->link));
222         DEBUGADD(lvl,("link_type:\t\t%d ", gpo->link_type));
223         switch (gpo->link_type) {
224                 case GP_LINK_UNKOWN:
225                         DEBUGADD(lvl,("GP_LINK_UNKOWN\n"));
226                         break;
227                 case GP_LINK_OU:
228                         DEBUGADD(lvl,("GP_LINK_OU\n"));
229                         break;
230                 case GP_LINK_DOMAIN:
231                         DEBUGADD(lvl,("GP_LINK_DOMAIN\n"));
232                         break;
233                 case GP_LINK_SITE:
234                         DEBUGADD(lvl,("GP_LINK_SITE\n"));
235                         break;
236                 case GP_LINK_MACHINE:
237                         DEBUGADD(lvl,("GP_LINK_MACHINE\n"));
238                         break;
239                 default:
240                         break;
241         }
242
243         DEBUGADD(lvl,("machine_extensions:\t%s\n", gpo->machine_extensions));
244
245         if (gpo->machine_extensions) {
246
247                 struct GP_EXT *gp_ext = NULL;
248                 ADS_STATUS status;
249
250                 status = ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, &gp_ext);
251                 if (!ADS_ERR_OK(status)) {
252                         return;
253                 }
254                 dump_gp_ext(gp_ext, lvl);
255         }
256         
257         DEBUGADD(lvl,("user_extensions:\t%s\n", gpo->user_extensions));
258
259         if (gpo->user_extensions) {
260         
261                 struct GP_EXT *gp_ext = NULL;
262                 ADS_STATUS status;
263                 
264                 status = ads_parse_gp_ext(mem_ctx, gpo->user_extensions, &gp_ext);
265                 if (!ADS_ERR_OK(status)) {
266                         return;
267                 }
268                 dump_gp_ext(gp_ext, lvl);
269         }
270 }
271
272 /****************************************************************
273 ****************************************************************/
274
275 void dump_gpo_list(TALLOC_CTX *mem_ctx, 
276                    struct GROUP_POLICY_OBJECT *gpo_list, 
277                    int debuglevel)
278 {
279         struct GROUP_POLICY_OBJECT *gpo = NULL;
280
281         for (gpo = gpo_list; gpo; gpo = gpo->next) {
282                 dump_gpo(mem_ctx, gpo, debuglevel);
283         }
284 }
285
286 /****************************************************************
287 ****************************************************************/
288
289 void dump_gplink(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct GP_LINK *gp_link)
290 {
291         ADS_STATUS status;
292         int i;
293         int lvl = 10;
294
295         if (gp_link == NULL) {
296                 return;
297         }
298
299         DEBUG(lvl,("---------------------\n\n"));
300
301         DEBUGADD(lvl,("gplink: %s\n", gp_link->gp_link));
302         DEBUGADD(lvl,("gpopts: %d ", gp_link->gp_opts));
303         switch (gp_link->gp_opts) {
304                 case GPOPTIONS_INHERIT:
305                         DEBUGADD(lvl,("GPOPTIONS_INHERIT\n"));
306                         break;
307                 case GPOPTIONS_BLOCK_INHERITANCE:
308                         DEBUGADD(lvl,("GPOPTIONS_BLOCK_INHERITANCE\n"));
309                         break;
310                 default:
311                         break;
312         }
313
314         DEBUGADD(lvl,("num links: %d\n", gp_link->num_links));
315
316         for (i = 0; i < gp_link->num_links; i++) {
317         
318                 DEBUGADD(lvl,("---------------------\n\n"));
319         
320                 DEBUGADD(lvl,("link: #%d\n", i + 1));
321                 DEBUGADD(lvl,("name: %s\n", gp_link->link_names[i]));
322
323                 DEBUGADD(lvl,("opt: %d ", gp_link->link_opts[i]));
324                 if (gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED) {
325                         DEBUGADD(lvl,("GPO_LINK_OPT_ENFORCED "));
326                 }
327                 if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
328                         DEBUGADD(lvl,("GPO_LINK_OPT_DISABLED"));
329                 }
330                 DEBUGADD(lvl,("\n"));
331
332                 if (ads != NULL && mem_ctx != NULL) {
333
334                         struct GROUP_POLICY_OBJECT gpo;
335
336                         status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i], NULL, NULL, &gpo);
337                         if (!ADS_ERR_OK(status)) {
338                                 DEBUG(lvl,("get gpo for %s failed: %s\n", gp_link->link_names[i], ads_errstr(status)));
339                                 return;
340                         }
341                         dump_gpo(mem_ctx, &gpo, lvl);
342                 }
343         }
344 }
345
346 /****************************************************************
347 ****************************************************************/
348
349 ADS_STATUS process_extension_with_snapin(ADS_STRUCT *ads,
350                                          TALLOC_CTX *mem_ctx,
351                                          const char *extension_guid,
352                                          const char *snapin_guid)
353 {
354         int i;
355
356         for (i=0; gpo_cse_snapin_extensions[i].guid_string; i++) {
357         
358                 if (strcmp(gpo_cse_snapin_extensions[i].guid_string, snapin_guid) == 0) {
359                 
360                         return gpo_cse_snapin_extensions[i].snapin_fn(ads, mem_ctx, 
361                                                                       extension_guid, snapin_guid);
362                 }
363         }
364
365         DEBUG(10,("process_extension_with_snapin: no snapin handler for extension %s (%s) found\n", 
366                 extension_guid, snapin_guid));
367
368         return ADS_SUCCESS;
369 }
370
371 /****************************************************************
372 ****************************************************************/
373
374 ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads,
375                              TALLOC_CTX *mem_ctx,
376                              struct GROUP_POLICY_OBJECT *gpo,
377                              const char *extension_guid_filter,
378                              uint32 flags)
379 {
380         ADS_STATUS status;
381         struct GP_EXT *gp_ext = NULL;
382         int i;
383         
384         if (flags & GPO_LIST_FLAG_MACHINE) {
385
386                 if (gpo->machine_extensions) {
387
388                         status = ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, &gp_ext);
389
390                         if (!ADS_ERR_OK(status)) {
391                                 return status;
392                         }
393
394                 } else {
395                         /* nothing to apply */
396                         return ADS_SUCCESS;
397                 }
398         
399         } else {
400
401                 if (gpo->user_extensions) {
402                 
403                         status = ads_parse_gp_ext(mem_ctx, gpo->user_extensions, &gp_ext);
404
405                         if (!ADS_ERR_OK(status)) {
406                                 return status;
407                         }
408                 } else {
409                         /* nothing to apply */
410                         return ADS_SUCCESS;
411                 }
412         }
413
414         for (i=0; i<gp_ext->num_exts; i++) {
415
416                 if (extension_guid_filter && !strequal(extension_guid_filter, gp_ext->extensions_guid[i])) {
417                         continue;
418                 }
419
420                 status = process_extension_with_snapin(ads, mem_ctx,
421                                                        gp_ext->extensions_guid[i], 
422                                                        gp_ext->snapins_guid[i]);
423                 if (!ADS_ERR_OK(status)) {
424                         return status;
425                 }
426         }
427
428         return ADS_SUCCESS;
429 }
430
431 /****************************************************************
432 ****************************************************************/
433
434 ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
435                                 TALLOC_CTX *mem_ctx,
436                                 struct GROUP_POLICY_OBJECT *gpo_list,
437                                 const char *extensions_guid,
438                                 uint32 flags)
439 {
440         ADS_STATUS status;
441         struct GROUP_POLICY_OBJECT *gpo;
442
443         for (gpo = gpo_list; gpo; gpo = gpo->next) {
444         
445                 status = gpo_process_a_gpo(ads, mem_ctx, gpo, 
446                                            extensions_guid, flags);
447         
448                 if (!ADS_ERR_OK(status)) {
449                         return status;
450                 }
451
452         }
453
454         return ADS_SUCCESS;
455 }
456
457 ADS_STATUS gpo_snapin_handler_none(ADS_STRUCT *ads, 
458                                    TALLOC_CTX *mem_ctx, 
459                                    const char *extension_guid, 
460                                    const char *snapin_guid)
461 {
462         DEBUG(10,("gpo_snapin_handler_none\n"));
463
464         return ADS_SUCCESS;
465 }
466
467 ADS_STATUS gpo_snapin_handler_security_settings(ADS_STRUCT *ads, 
468                                                 TALLOC_CTX *mem_ctx, 
469                                                 const char *extension_guid, 
470                                                 const char *snapin_guid)
471 {
472         DEBUG(10,("gpo_snapin_handler_security_settings\n"));
473
474         return ADS_SUCCESS;
475 }
476
477 ADS_STATUS gpo_lockout_policy(ADS_STRUCT *ads,
478                               TALLOC_CTX *mem_ctx,
479                               const char *hostname,
480                               SAM_UNK_INFO_12 *lockout_policy)
481 {
482         return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
483 }
484
485 /****************************************************************
486 ****************************************************************/
487
488 ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
489                                TALLOC_CTX *mem_ctx,
490                                const char *hostname,
491                                SAM_UNK_INFO_1 *password_policy)
492 {
493         ADS_STATUS status;
494         struct GROUP_POLICY_OBJECT *gpo_list;
495         const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
496         char *filter, *dn;
497         LDAPMessage *res = NULL;
498         uint32 uac;
499
500         filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", hostname);
501         if (filter == NULL) {
502                 return ADS_ERROR(LDAP_NO_MEMORY);
503         }
504
505         status = ads_do_search_all(ads, ads->config.bind_path,
506                                    LDAP_SCOPE_SUBTREE,
507                                    filter, attrs, &res);
508         
509         if (!ADS_ERR_OK(status)) {
510                 return status;
511         }
512
513         if (ads_count_replies(ads, res) != 1) {
514                 ads_msgfree(ads, res);
515                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
516         }
517
518         dn = ads_get_dn(ads, res);
519         if (dn == NULL) {
520                 ads_msgfree(ads, res);
521                 return ADS_ERROR(LDAP_NO_MEMORY);
522         }
523
524         if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
525                 ads_msgfree(ads, res);
526                 ads_memfree(ads, dn);
527                 return ADS_ERROR(LDAP_NO_MEMORY);
528         }
529
530         ads_msgfree(ads, res);
531
532         if (!(uac & UF_WORKSTATION_TRUST_ACCOUNT)) {
533                 ads_memfree(ads, dn);
534                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
535         }
536
537         status = ads_get_gpo_list(ads, mem_ctx, dn, GPO_LIST_FLAG_MACHINE, &gpo_list);
538         if (!ADS_ERR_OK(status)) {
539                 ads_memfree(ads, dn);
540                 return status;
541         }
542
543         ads_memfree(ads, dn);
544
545         status = gpo_process_gpo_list(ads, mem_ctx, gpo_list, 
546                                       cse_gpo_name_to_guid_string("Security"), 
547                                       GPO_LIST_FLAG_MACHINE); 
548         if (!ADS_ERR_OK(status)) {
549                 return status;
550         }
551
552         return ADS_SUCCESS;
553 }
554
555 /****************************************************************
556  check wether the version number in a GROUP_POLICY_OBJECT match those of the
557  locally stored version. If not, fetch the required policy via CIFS
558 ****************************************************************/
559
560 NTSTATUS check_refresh_gpo(ADS_STRUCT *ads, 
561                            TALLOC_CTX *mem_ctx,
562                            struct GROUP_POLICY_OBJECT *gpo,
563                            struct cli_state **cli_out)
564 {
565         NTSTATUS result;
566         char *server = NULL;
567         char *share = NULL;
568         char *nt_path = NULL;
569         char *unix_path = NULL;
570         uint32 sysvol_gpt_version = 0;
571         char *display_name = NULL;
572         struct cli_state *cli = NULL;
573
574         result = gpo_explode_filesyspath(mem_ctx, gpo->file_sys_path, 
575                                          &server, &share, &nt_path, &unix_path);
576
577         if (!NT_STATUS_IS_OK(result)) {
578                 goto out;
579         }
580
581         result = gpo_get_sysvol_gpt_version(mem_ctx, 
582                                             unix_path,
583                                             &sysvol_gpt_version,
584                                             &display_name);
585         if (!NT_STATUS_IS_OK(result) && 
586             !NT_STATUS_EQUAL(result, NT_STATUS_NO_SUCH_FILE)) {
587                 DEBUG(10,("check_refresh_gpo: failed to get local gpt version: %s\n", 
588                         nt_errstr(result)));
589                 goto out;
590         }
591
592         while (gpo->version > sysvol_gpt_version) {
593
594                 DEBUG(1,("check_refresh_gpo: need to refresh GPO\n"));
595
596                 if (*cli_out == NULL) {
597
598                         result = cli_full_connection(&cli, global_myname(), 
599                                                      server, /* ads->config.ldap_server_name, */
600                                                      NULL, 0,
601                                                      share, "A:",
602                                                      ads->auth.user_name, NULL, ads->auth.password,
603                                                      CLI_FULL_CONNECTION_USE_KERBEROS,
604                                                      Undefined, NULL);
605                         if (!NT_STATUS_IS_OK(result)) {
606                                 DEBUG(10,("check_refresh_gpo: failed to connect: %s\n", nt_errstr(result)));
607                                 goto out;
608                         }
609
610                         *cli_out = cli;
611                 }
612
613                 result = gpo_fetch_files(mem_ctx, *cli_out, gpo);
614                 if (!NT_STATUS_IS_OK(result)) {
615                         goto out;
616                 }
617
618                 result = gpo_get_sysvol_gpt_version(mem_ctx, 
619                                                     unix_path, 
620                                                     &sysvol_gpt_version,
621                                                     &display_name); 
622                 if (!NT_STATUS_IS_OK(result)) {
623                         DEBUG(10,("check_refresh_gpo: failed to get local gpt version: %s\n", 
624                                 nt_errstr(result)));
625                         goto out;
626                 }
627                 
628                 if (gpo->version == sysvol_gpt_version) {
629                         break;
630                 }
631         } 
632
633         DEBUG(10,("Name:\t\t\t%s\n", gpo->display_name));
634         DEBUGADD(10,("sysvol GPT version:\t%d (user: %d, machine: %d)\n", 
635                 sysvol_gpt_version, 
636                 GPO_VERSION_USER(sysvol_gpt_version), 
637                 GPO_VERSION_MACHINE(sysvol_gpt_version))); 
638         DEBUGADD(10,("LDAP GPO version:\t%d (user: %d, machine: %d)\n", 
639                 gpo->version,
640                 GPO_VERSION_USER(gpo->version),
641                 GPO_VERSION_MACHINE(gpo->version)));
642
643         result = NT_STATUS_OK;
644
645  out:
646         return result;
647
648 }
649
650 /****************************************************************
651  check wether the version numbers in the gpo_list match the locally stored, if
652  not, go and get each required GPO via CIFS
653  ****************************************************************/
654
655 NTSTATUS check_refresh_gpo_list(ADS_STRUCT *ads, 
656                                 TALLOC_CTX *mem_ctx, 
657                                 struct GROUP_POLICY_OBJECT *gpo_list)
658 {
659         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
660         struct cli_state *cli = NULL;
661         struct GROUP_POLICY_OBJECT *gpo;
662
663         if (!gpo_list) {
664                 return NT_STATUS_INVALID_PARAMETER;
665         }
666
667         for (gpo = gpo_list; gpo; gpo = gpo->next) {
668
669                 result = check_refresh_gpo(ads, mem_ctx, gpo, &cli);
670                 if (!NT_STATUS_IS_OK(result)) {
671                         goto out;
672                 }
673         }
674
675         result = NT_STATUS_OK;
676
677  out:
678         if (cli) {
679                 cli_shutdown(cli);
680         }
681
682         return result;
683 }
684
685 #endif /* HAVE_LDAP */