r18981: * cleanup some vestiges of old cli_reg.c code and mark some TODO
[tprouty/samba.git] / source / libgpo / gpo_util.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  Group Policy Object Support
4  *  Copyright (C) Guenther Deschner 2005
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 2 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)
171 {
172         int lvl = 10;
173         int i;
174
175         if (gp_ext == NULL) {
176                 return;
177         }
178
179         DEBUG(lvl,("---------------------\n\n"));
180         DEBUGADD(lvl,("name:\t\t\t%s\n", gp_ext->gp_extension));
181
182         for (i=0; i< gp_ext->num_exts; i++) {
183
184                 DEBUGADD(lvl,("extension:\t\t\t%s\n", gp_ext->extensions_guid[i]));
185                 DEBUGADD(lvl,("extension (name):\t\t\t%s\n", gp_ext->extensions[i]));
186                 
187                 DEBUGADD(lvl,("snapin:\t\t\t%s\n", gp_ext->snapins_guid[i]));
188                 DEBUGADD(lvl,("snapin (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) 
193 {
194         int lvl = 1;
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_user));
206         DEBUGADD(lvl,("version_machine:\t%d (0x%04x)\n", gpo->version_machine, gpo->version_machine));
207         DEBUGADD(lvl,("filesyspath:\t\t%s\n", gpo->file_sys_path));
208         DEBUGADD(lvl,("dspath:\t\t%s\n", gpo->ds_path));
209
210         DEBUGADD(lvl,("options:\t\t%d ", gpo->options));
211         if (gpo->options & GPFLAGS_USER_SETTINGS_DISABLED) {
212                 DEBUGADD(lvl,("GPFLAGS_USER_SETTINGS_DISABLED ")); 
213         }
214         if (gpo->options & GPFLAGS_MACHINE_SETTINGS_DISABLED) {
215                 DEBUGADD(lvl,("GPFLAGS_MACHINE_SETTINGS_DISABLED")); 
216         }
217         DEBUGADD(lvl,("\n"));
218
219         DEBUGADD(lvl,("link:\t\t\t%s\n", gpo->link));
220         DEBUGADD(lvl,("link_type:\t\t%d ", gpo->link_type));
221         switch (gpo->link_type) {
222         case GP_LINK_UNKOWN:
223                 DEBUGADD(lvl,("GP_LINK_UNKOWN\n"));
224                 break;
225         case GP_LINK_OU:
226                 DEBUGADD(lvl,("GP_LINK_OU\n"));
227                 break;
228         case GP_LINK_DOMAIN:
229                 DEBUGADD(lvl,("GP_LINK_DOMAIN\n"));
230                 break;
231         case GP_LINK_SITE:
232                 DEBUGADD(lvl,("GP_LINK_SITE\n"));
233                 break;
234         case GP_LINK_MACHINE:
235                 DEBUGADD(lvl,("GP_LINK_MACHINE\n"));
236                 break;
237         default:
238                 break;
239         }
240
241         if (gpo->machine_extensions) {
242
243                 struct GP_EXT gp_ext;
244                 ADS_STATUS status;
245
246                 DEBUGADD(lvl,("machine_extensions:\t%s\n", gpo->machine_extensions));
247
248                 status = ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, &gp_ext);
249                 if (!ADS_ERR_OK(status)) {
250                         return;
251                 }
252                 dump_gp_ext(&gp_ext);
253         }
254         
255         if (gpo->user_extensions) {
256         
257                 struct GP_EXT gp_ext;
258                 ADS_STATUS status;
259                 
260                 DEBUGADD(lvl,("user_extensions:\t%s\n", gpo->user_extensions));
261
262                 status = ads_parse_gp_ext(mem_ctx, gpo->user_extensions, &gp_ext);
263                 if (!ADS_ERR_OK(status)) {
264                         return;
265                 }
266                 dump_gp_ext(&gp_ext);
267         }
268 };
269
270 void dump_gplink(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct GP_LINK *gp_link)
271 {
272         ADS_STATUS status;
273         int i;
274         int lvl = 10;
275
276         if (gp_link == NULL) {
277                 return;
278         }
279
280         DEBUG(lvl,("---------------------\n\n"));
281
282         DEBUGADD(lvl,("gplink: %s\n", gp_link->gp_link));
283         DEBUGADD(lvl,("gpopts: %d ", gp_link->gp_opts));
284         switch (gp_link->gp_opts) {
285         case GPOPTIONS_INHERIT:
286                 DEBUGADD(lvl,("GPOPTIONS_INHERIT\n"));
287                 break;
288         case GPOPTIONS_BLOCK_INHERITANCE:
289                 DEBUGADD(lvl,("GPOPTIONS_BLOCK_INHERITANCE\n"));
290                 break;
291         default:
292                 break;
293         }
294
295         DEBUGADD(lvl,("num links: %d\n", gp_link->num_links));
296
297         for (i = 0; i < gp_link->num_links; i++) {
298         
299                 DEBUGADD(lvl,("---------------------\n\n"));
300         
301                 DEBUGADD(lvl,("link: #%d\n", i + 1));
302                 DEBUGADD(lvl,("name: %s\n", gp_link->link_names[i]));
303
304                 DEBUGADD(lvl,("opt: %d ", gp_link->link_opts[i]));
305                 if (gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED) {
306                         DEBUGADD(lvl,("GPO_LINK_OPT_ENFORCED "));
307                 }
308                 if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
309                         DEBUGADD(lvl,("GPO_LINK_OPT_DISABLED"));
310                 }
311                 DEBUGADD(lvl,("\n"));
312
313                 if (ads != NULL && mem_ctx != NULL) {
314
315                         struct GROUP_POLICY_OBJECT gpo;
316
317                         status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i], NULL, NULL, &gpo);
318                         if (!ADS_ERR_OK(status)) {
319                                 DEBUG(lvl,("get gpo for %s failed: %s\n", gp_link->link_names[i], ads_errstr(status)));
320                                 return;
321                         }
322                         dump_gpo(mem_ctx, &gpo);
323                 }
324         }
325 }
326
327 ADS_STATUS process_extension_with_snapin(ADS_STRUCT *ads,
328                                          TALLOC_CTX *mem_ctx,
329                                          const char *extension_guid,
330                                          const char *snapin_guid)
331 {
332         int i;
333
334         for (i=0; gpo_cse_snapin_extensions[i].guid_string; i++) {
335         
336                 if (strcmp(gpo_cse_snapin_extensions[i].guid_string, snapin_guid) == 0) {
337                 
338                         return gpo_cse_snapin_extensions[i].snapin_fn(ads, mem_ctx, 
339                                                                       extension_guid, snapin_guid);
340                 }
341         }
342
343         DEBUG(10,("process_extension_with_snapin: no snapin handler for extension %s (%s) found\n", 
344                 extension_guid, snapin_guid));
345
346         return ADS_ERROR(LDAP_SUCCESS);
347 }
348
349 ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads,
350                              TALLOC_CTX *mem_ctx,
351                              struct GROUP_POLICY_OBJECT *gpo,
352                              const char *extension_guid,
353                              uint32 flags)
354 {
355         ADS_STATUS status;
356         struct GP_EXT gp_ext;
357         int i;
358         
359         if (flags & GPO_LIST_FLAG_MACHINE) {
360
361                 if (gpo->machine_extensions) {
362
363                         status = ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, &gp_ext);
364
365                         if (!ADS_ERR_OK(status)) {
366                                 return status;
367                         }
368
369                 } else {
370                         /* nothing to apply */
371                         return ADS_ERROR(LDAP_SUCCESS);
372                 }
373         
374         } else {
375
376                 if (gpo->user_extensions) {
377                 
378                         status = ads_parse_gp_ext(mem_ctx, gpo->user_extensions, &gp_ext);
379
380                         if (!ADS_ERR_OK(status)) {
381                                 return status;
382                         }
383                 } else {
384                         /* nothing to apply */
385                         return ADS_ERROR(LDAP_SUCCESS);
386                 }
387         }
388
389         for (i=0; i<gp_ext.num_exts; i++) {
390
391                 if (extension_guid && !strequal(extension_guid, gp_ext.extensions_guid[i])) {
392                         continue;
393                 }
394
395                 status = process_extension_with_snapin(ads, mem_ctx, gp_ext.extensions_guid[i], 
396                                                        gp_ext.snapins_guid[i]);
397                 if (!ADS_ERR_OK(status)) {
398                         return status;
399                 }
400         }
401
402         return ADS_ERROR(LDAP_SUCCESS);
403 }
404
405 ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
406                                 TALLOC_CTX *mem_ctx,
407                                 struct GROUP_POLICY_OBJECT **gpo_list,
408                                 const char *extensions_guid,
409                                 uint32 flags)
410 {
411         ADS_STATUS status;
412         struct GROUP_POLICY_OBJECT *gpo = *gpo_list;
413
414         for (gpo = *gpo_list; gpo; gpo = gpo->next) {
415         
416                 status = gpo_process_a_gpo(ads, mem_ctx, gpo, 
417                                            extensions_guid, flags);
418         
419                 if (!ADS_ERR_OK(status)) {
420                         return status;
421                 }
422
423         }
424
425         return ADS_ERROR(LDAP_SUCCESS);
426 }
427
428 ADS_STATUS gpo_snapin_handler_none(ADS_STRUCT *ads, 
429                                    TALLOC_CTX *mem_ctx, 
430                                    const char *extension_guid, 
431                                    const char *snapin_guid)
432 {
433         DEBUG(10,("gpo_snapin_handler_none\n"));
434
435         return ADS_ERROR(LDAP_SUCCESS);
436 }
437
438 ADS_STATUS gpo_snapin_handler_security_settings(ADS_STRUCT *ads, 
439                                                 TALLOC_CTX *mem_ctx, 
440                                                 const char *extension_guid, 
441                                                 const char *snapin_guid)
442 {
443         DEBUG(10,("gpo_snapin_handler_security_settings\n"));
444
445         return ADS_ERROR(LDAP_SUCCESS);
446 }
447
448 ADS_STATUS gpo_lockout_policy(ADS_STRUCT *ads,
449                               TALLOC_CTX *mem_ctx,
450                               const char *hostname,
451                               SAM_UNK_INFO_12 *lockout_policy)
452 {
453         return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
454 }
455
456 ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
457                                TALLOC_CTX *mem_ctx,
458                                const char *hostname,
459                                SAM_UNK_INFO_1 *password_policy)
460 {
461         ADS_STATUS status;
462         struct GROUP_POLICY_OBJECT *gpo_list;
463         const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
464         char *filter, *dn;
465         LDAPMessage *res = NULL;
466         uint32 uac;
467
468         filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", hostname);
469         if (filter == NULL) {
470                 return ADS_ERROR(LDAP_NO_MEMORY);
471         }
472
473         status = ads_do_search_all(ads, ads->config.bind_path,
474                                    LDAP_SCOPE_SUBTREE,
475                                    filter, attrs, &res);
476         
477         if (!ADS_ERR_OK(status)) {
478                 return status;
479         }
480
481         if (ads_count_replies(ads, res) != 1) {
482                 ads_msgfree(ads, res);
483                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
484         }
485
486         dn = ads_get_dn(ads, res);
487         if (dn == NULL) {
488                 ads_msgfree(ads, res);
489                 return ADS_ERROR(LDAP_NO_MEMORY);
490         }
491
492         if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
493                 ads_msgfree(ads, res);
494                 ads_memfree(ads, dn);
495                 return ADS_ERROR(LDAP_NO_MEMORY);
496         }
497
498         ads_msgfree(ads, res);
499
500         if (!(uac & UF_WORKSTATION_TRUST_ACCOUNT)) {
501                 ads_memfree(ads, dn);
502                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
503         }
504
505         status = ads_get_gpo_list(ads, mem_ctx, dn, GPO_LIST_FLAG_MACHINE, &gpo_list);
506         if (!ADS_ERR_OK(status)) {
507                 ads_memfree(ads, dn);
508                 return status;
509         }
510
511         ads_memfree(ads, dn);
512
513         status = gpo_process_gpo_list(ads, mem_ctx, &gpo_list, 
514                                       cse_gpo_name_to_guid_string("Security"), 
515                                       GPO_LIST_FLAG_MACHINE); 
516         if (!ADS_ERR_OK(status)) {
517                 return status;
518         }
519
520         return ADS_ERROR(LDAP_SUCCESS);
521 }
522
523 #endif /* HAVE_LDAP */