~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/libgpo/gpext/registry.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Unix SMB/CIFS implementation.
 
3
 *  Group Policy Support
 
4
 *  Copyright (C) Guenther Deschner 2007-2008
 
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
 
 
22
#define GP_EXT_NAME "registry"
 
23
 
 
24
/* more info can be found at:
 
25
 * http://msdn2.microsoft.com/en-us/library/aa374407.aspx */
 
26
 
 
27
#define GP_REGPOL_FILE  "Registry.pol"
 
28
 
 
29
#define GP_REGPOL_FILE_SIGNATURE 0x67655250 /* 'PReg' */
 
30
#define GP_REGPOL_FILE_VERSION 1
 
31
 
 
32
static TALLOC_CTX *ctx = NULL;
 
33
 
 
34
struct gp_registry_file_header {
 
35
        uint32_t signature;
 
36
        uint32_t version;
 
37
};
 
38
 
 
39
struct gp_registry_file_entry {
 
40
        UNISTR key;
 
41
        UNISTR value;
 
42
        enum winreg_Type type;
 
43
        size_t size;
 
44
        uint8_t *data;
 
45
};
 
46
 
 
47
struct gp_registry_file {
 
48
        struct gp_registry_file_header header;
 
49
        size_t num_entries;
 
50
        struct gp_registry_entry *entries;
 
51
};
 
52
 
 
53
/****************************************************************
 
54
****************************************************************/
 
55
 
 
56
static bool reg_parse_header(const char *desc,
 
57
                             struct gp_registry_file_header *header,
 
58
                             prs_struct *ps,
 
59
                             int depth)
 
60
{
 
61
        if (!header)
 
62
                return false;
 
63
 
 
64
        prs_debug(ps, depth, desc, "reg_parse_header");
 
65
        depth++;
 
66
 
 
67
        if (!prs_uint32("signature", ps, depth, &header->signature))
 
68
                return false;
 
69
 
 
70
        if (!prs_uint32("version", ps, depth, &header->version))
 
71
                return false;
 
72
 
 
73
        return true;
 
74
}
 
75
 
 
76
/****************************************************************
 
77
****************************************************************/
 
78
 
 
79
static bool reg_parse_and_verify_ucs2_char(const char *desc,
 
80
                                           char character,
 
81
                                           prs_struct *ps,
 
82
                                           int depth)
 
83
{
 
84
        uint16_t tmp;
 
85
 
 
86
        if (!prs_uint16(desc, ps, depth, &tmp))
 
87
                return false;
 
88
 
 
89
        if (tmp != UCS2_CHAR(character))
 
90
                return false;
 
91
 
 
92
        return true;
 
93
}
 
94
 
 
95
/****************************************************************
 
96
****************************************************************/
 
97
 
 
98
static bool reg_parse_init(prs_struct *ps, int depth)
 
99
{
 
100
        return reg_parse_and_verify_ucs2_char("initiator '['", '[',
 
101
                                              ps, depth);
 
102
}
 
103
 
 
104
/****************************************************************
 
105
****************************************************************/
 
106
 
 
107
static bool reg_parse_sep(prs_struct *ps, int depth)
 
108
{
 
109
        return reg_parse_and_verify_ucs2_char("separator ';'", ';',
 
110
                                              ps, depth);
 
111
}
 
112
 
 
113
/****************************************************************
 
114
****************************************************************/
 
115
 
 
116
static bool reg_parse_term(prs_struct *ps, int depth)
 
117
{
 
118
        return reg_parse_and_verify_ucs2_char("terminator ']'", ']',
 
119
                                              ps, depth);
 
120
}
 
121
 
 
122
 
 
123
/****************************************************************
 
124
* [key;value;type;size;data]
 
125
****************************************************************/
 
126
 
 
127
static bool reg_parse_entry(TALLOC_CTX *mem_ctx,
 
128
                            const char *desc,
 
129
                            struct gp_registry_file_entry *entry,
 
130
                            prs_struct *ps,
 
131
                            int depth)
 
132
{
 
133
        uint32_t size = 0;
 
134
 
 
135
        if (!entry)
 
136
                return false;
 
137
 
 
138
        prs_debug(ps, depth, desc, "reg_parse_entry");
 
139
        depth++;
 
140
 
 
141
        ZERO_STRUCTP(entry);
 
142
 
 
143
        if (!reg_parse_init(ps, depth))
 
144
                return false;
 
145
 
 
146
        if (!prs_unistr("key", ps, depth, &entry->key))
 
147
                return false;
 
148
 
 
149
        if (!reg_parse_sep(ps, depth))
 
150
                return false;
 
151
 
 
152
        if (!prs_unistr("value", ps, depth, &entry->value))
 
153
                return false;
 
154
 
 
155
        if (!reg_parse_sep(ps, depth))
 
156
                return false;
 
157
 
 
158
        if (!prs_uint32("type", ps, depth, &entry->type))
 
159
                return false;
 
160
 
 
161
        if (!reg_parse_sep(ps, depth))
 
162
                return false;
 
163
 
 
164
        if (!prs_uint32("size", ps, depth, &size))
 
165
                return false;
 
166
 
 
167
        entry->size = size;
 
168
 
 
169
        if (!reg_parse_sep(ps, depth))
 
170
                return false;
 
171
 
 
172
        if (entry->size) {
 
173
                entry->data = TALLOC_ZERO_ARRAY(mem_ctx, uint8, entry->size);
 
174
                if (!entry->data)
 
175
                        return false;
 
176
        }
 
177
 
 
178
        if (!prs_uint8s(false, "data", ps, depth, entry->data, entry->size))
 
179
                return false;
 
180
 
 
181
        if (!reg_parse_term(ps, depth))
 
182
                return false;
 
183
 
 
184
        return true;
 
185
}
 
186
 
 
187
/****************************************************************
 
188
****************************************************************/
 
189
 
 
190
static bool reg_parse_value(TALLOC_CTX *mem_ctx,
 
191
                            char **value,
 
192
                            enum gp_reg_action *action)
 
193
{
 
194
        if (!*value) {
 
195
                *action = GP_REG_ACTION_ADD_KEY;
 
196
                return true;
 
197
        }
 
198
 
 
199
        if (strncmp(*value, "**", 2) != 0) {
 
200
                *action = GP_REG_ACTION_ADD_VALUE;
 
201
                return true;
 
202
        }
 
203
 
 
204
        if (strnequal(*value, "**DelVals.", 10)) {
 
205
                *action = GP_REG_ACTION_DEL_ALL_VALUES;
 
206
                return true;
 
207
        }
 
208
 
 
209
        if (strnequal(*value, "**Del.", 6)) {
 
210
                *value = talloc_strdup(mem_ctx, *value + 6);
 
211
                *action = GP_REG_ACTION_DEL_VALUE;
 
212
                return true;
 
213
        }
 
214
 
 
215
        if (strnequal(*value, "**SecureKey", 11)) {
 
216
                if (strnequal(*value, "**SecureKey=1", 13)) {
 
217
                        *action = GP_REG_ACTION_SEC_KEY_SET;
 
218
                        return true;
 
219
                }
 
220
 
 
221
 /*************** not tested from here on ***************/
 
222
                if (strnequal(*value, "**SecureKey=0", 13)) {
 
223
                        smb_panic("not supported: **SecureKey=0");
 
224
                        *action = GP_REG_ACTION_SEC_KEY_RESET;
 
225
                        return true;
 
226
                }
 
227
                DEBUG(0,("unknown: SecureKey: %s\n", *value));
 
228
                smb_panic("not supported SecureKey method");
 
229
                return false;
 
230
        }
 
231
 
 
232
        if (strnequal(*value, "**DeleteValues", strlen("**DeleteValues"))) {
 
233
                smb_panic("not supported: **DeleteValues");
 
234
                *action = GP_REG_ACTION_DEL_VALUES;
 
235
                return false;
 
236
        }
 
237
 
 
238
        if (strnequal(*value, "**DeleteKeys", strlen("**DeleteKeys"))) {
 
239
                smb_panic("not supported: **DeleteKeys");
 
240
                *action = GP_REG_ACTION_DEL_KEYS;
 
241
                return false;
 
242
        }
 
243
 
 
244
        DEBUG(0,("unknown value: %s\n", *value));
 
245
        smb_panic(*value);
 
246
        return false;
 
247
}
 
248
 
 
249
/****************************************************************
 
250
****************************************************************/
 
251
 
 
252
static bool gp_reg_entry_from_file_entry(TALLOC_CTX *mem_ctx,
 
253
                                         struct gp_registry_file_entry *file_entry,
 
254
                                         struct gp_registry_entry **reg_entry)
 
255
{
 
256
        struct registry_value *data = NULL;
 
257
        struct gp_registry_entry *entry = NULL;
 
258
        char *key = NULL;
 
259
        char *value = NULL;
 
260
        enum gp_reg_action action = GP_REG_ACTION_NONE;
 
261
        size_t converted_size;
 
262
 
 
263
        ZERO_STRUCTP(*reg_entry);
 
264
 
 
265
        data = TALLOC_ZERO_P(mem_ctx, struct registry_value);
 
266
        if (!data)
 
267
                return false;
 
268
 
 
269
        if (strlen_w((const smb_ucs2_t *)file_entry->key.buffer) <= 0)
 
270
                return false;
 
271
 
 
272
        if (!pull_ucs2_talloc(mem_ctx, &key, file_entry->key.buffer,
 
273
                              &converted_size))
 
274
        {
 
275
                return false;
 
276
        }
 
277
 
 
278
        if (strlen_w((const smb_ucs2_t *)file_entry->value.buffer) > 0 &&
 
279
            !pull_ucs2_talloc(mem_ctx, &value, file_entry->value.buffer,
 
280
                              &converted_size))
 
281
        {
 
282
                        return false;
 
283
        }
 
284
 
 
285
        if (!reg_parse_value(mem_ctx, &value, &action))
 
286
                return false;
 
287
 
 
288
        data->type = file_entry->type;
 
289
 
 
290
        switch (data->type) {
 
291
                case REG_DWORD:
 
292
                        data->v.dword = atoi((char *)file_entry->data);
 
293
                        break;
 
294
                case REG_BINARY:
 
295
                        data->v.binary = data_blob_talloc(mem_ctx,
 
296
                                                          file_entry->data,
 
297
                                                          file_entry->size);
 
298
                        break;
 
299
                case REG_NONE:
 
300
                        break;
 
301
                case REG_SZ:
 
302
                        if (!pull_ucs2_talloc(mem_ctx, &data->v.sz.str,
 
303
                                              (const smb_ucs2_t *)
 
304
                                              file_entry->data,
 
305
                                              &data->v.sz.len)) {
 
306
                                data->v.sz.len = -1;
 
307
                        }
 
308
 
 
309
                        break;
 
310
                case REG_DWORD_BIG_ENDIAN:
 
311
                case REG_EXPAND_SZ:
 
312
                case REG_LINK:
 
313
                case REG_MULTI_SZ:
 
314
                case REG_QWORD:
 
315
/*              case REG_DWORD_LITTLE_ENDIAN: */
 
316
/*              case REG_QWORD_LITTLE_ENDIAN: */
 
317
                        printf("not yet implemented: %d\n", data->type);
 
318
                        return false;
 
319
                default:
 
320
                        printf("invalid reg type defined: %d\n", data->type);
 
321
                        return false;
 
322
 
 
323
        }
 
324
 
 
325
        entry = TALLOC_ZERO_P(mem_ctx, struct gp_registry_entry);
 
326
        if (!entry)
 
327
                return false;
 
328
 
 
329
        entry->key = key;
 
330
        entry->value = value;
 
331
        entry->data = data;
 
332
        entry->action = action;
 
333
 
 
334
        *reg_entry = entry;
 
335
 
 
336
        return true;
 
337
}
 
338
 
 
339
/****************************************************************
 
340
* [key;value;type;size;data][key;value;type;size;data]...
 
341
****************************************************************/
 
342
 
 
343
static bool reg_parse_entries(TALLOC_CTX *mem_ctx,
 
344
                              const char *desc,
 
345
                              struct gp_registry_entry **entries,
 
346
                              size_t *num_entries,
 
347
                              prs_struct *ps,
 
348
                              int depth)
 
349
{
 
350
 
 
351
        if (!entries || !num_entries)
 
352
                return false;
 
353
 
 
354
        prs_debug(ps, depth, desc, "reg_parse_entries");
 
355
        depth++;
 
356
 
 
357
        *entries = NULL;
 
358
        *num_entries = 0;
 
359
 
 
360
        while (ps->buffer_size > ps->data_offset) {
 
361
 
 
362
                struct gp_registry_file_entry f_entry;
 
363
                struct gp_registry_entry *r_entry = NULL;
 
364
 
 
365
                if (!reg_parse_entry(mem_ctx, desc, &f_entry,
 
366
                                     ps, depth))
 
367
                        return false;
 
368
 
 
369
                if (!gp_reg_entry_from_file_entry(mem_ctx,
 
370
                                                  &f_entry,
 
371
                                                  &r_entry))
 
372
                        return false;
 
373
 
 
374
                if (!add_gp_registry_entry_to_array(mem_ctx,
 
375
                                                    r_entry,
 
376
                                                    entries,
 
377
                                                    num_entries))
 
378
                        return false;
 
379
        }
 
380
 
 
381
        return true;
 
382
}
 
383
 
 
384
/****************************************************************
 
385
****************************************************************/
 
386
 
 
387
static NTSTATUS reg_parse_registry(TALLOC_CTX *mem_ctx,
 
388
                                   uint32_t flags,
 
389
                                   const char *filename,
 
390
                                   struct gp_registry_entry **entries,
 
391
                                   size_t *num_entries)
 
392
{
 
393
        uint16_t *buf = NULL;
 
394
        size_t n = 0;
 
395
        NTSTATUS status;
 
396
        prs_struct ps;
 
397
        struct gp_registry_file *reg_file;
 
398
        const char *real_filename = NULL;
 
399
 
 
400
        reg_file = TALLOC_ZERO_P(mem_ctx, struct gp_registry_file);
 
401
        NT_STATUS_HAVE_NO_MEMORY(reg_file);
 
402
 
 
403
        status = gp_find_file(mem_ctx,
 
404
                              flags,
 
405
                              filename,
 
406
                              GP_REGPOL_FILE,
 
407
                              &real_filename);
 
408
        if (!NT_STATUS_IS_OK(status)) {
 
409
                TALLOC_FREE(reg_file);
 
410
                return status;
 
411
        }
 
412
 
 
413
        buf = (uint16 *)file_load(real_filename, &n, 0, NULL);
 
414
        if (!buf) {
 
415
                TALLOC_FREE(reg_file);
 
416
                return NT_STATUS_CANNOT_LOAD_REGISTRY_FILE;
 
417
        }
 
418
 
 
419
        if (!prs_init(&ps, n, mem_ctx, UNMARSHALL)) {
 
420
                status = NT_STATUS_NO_MEMORY;
 
421
                goto out;
 
422
        }
 
423
 
 
424
        if (!prs_copy_data_in(&ps, (char *)buf, n)) {
 
425
                status = NT_STATUS_NO_MEMORY;
 
426
                goto out;
 
427
        }
 
428
 
 
429
        prs_set_offset(&ps, 0);
 
430
 
 
431
        if (!reg_parse_header("header", &reg_file->header, &ps, 0)) {
 
432
                status = NT_STATUS_REGISTRY_IO_FAILED;
 
433
                goto out;
 
434
        }
 
435
 
 
436
        if (reg_file->header.signature != GP_REGPOL_FILE_SIGNATURE) {
 
437
                status = NT_STATUS_INVALID_PARAMETER;
 
438
                goto out;
 
439
        }
 
440
 
 
441
        if (reg_file->header.version != GP_REGPOL_FILE_VERSION) {
 
442
                status = NT_STATUS_INVALID_PARAMETER;
 
443
                goto out;
 
444
        }
 
445
 
 
446
        if (!reg_parse_entries(mem_ctx, "entries", &reg_file->entries,
 
447
                               &reg_file->num_entries, &ps, 0)) {
 
448
                status = NT_STATUS_REGISTRY_IO_FAILED;
 
449
                goto out;
 
450
        }
 
451
 
 
452
        *entries = reg_file->entries;
 
453
        *num_entries = reg_file->num_entries;
 
454
 
 
455
        status = NT_STATUS_OK;
 
456
 
 
457
 out:
 
458
        TALLOC_FREE(buf);
 
459
        prs_mem_free(&ps);
 
460
 
 
461
        return status;
 
462
}
 
463
 
 
464
/****************************************************************
 
465
****************************************************************/
 
466
 
 
467
static WERROR reg_apply_registry(TALLOC_CTX *mem_ctx,
 
468
                                 const struct nt_user_token *token,
 
469
                                 struct registry_key *root_key,
 
470
                                 uint32_t flags,
 
471
                                 struct gp_registry_entry *entries,
 
472
                                 size_t num_entries)
 
473
{
 
474
        struct gp_registry_context *reg_ctx = NULL;
 
475
        WERROR werr;
 
476
        size_t i;
 
477
 
 
478
        if (num_entries == 0) {
 
479
                return WERR_OK;
 
480
        }
 
481
 
 
482
#if 0
 
483
        if (flags & GPO_LIST_FLAG_MACHINE) {
 
484
                werr = gp_init_reg_ctx(mem_ctx, KEY_HKLM, REG_KEY_WRITE,
 
485
                                       get_system_token(),
 
486
                                       &reg_ctx);
 
487
        } else {
 
488
                werr = gp_init_reg_ctx(mem_ctx, KEY_HKCU, REG_KEY_WRITE,
 
489
                                       token,
 
490
                                       &reg_ctx);
 
491
        }
 
492
        W_ERROR_NOT_OK_RETURN(werr);
 
493
#endif
 
494
        for (i=0; i<num_entries; i++) {
 
495
 
 
496
                /* FIXME: maybe we should check here if we attempt to go beyond
 
497
                 * the 4 allowed reg keys */
 
498
 
 
499
                werr = reg_apply_registry_entry(mem_ctx, root_key,
 
500
                                                reg_ctx,
 
501
                                                &(entries)[i],
 
502
                                                token, flags);
 
503
                if (!W_ERROR_IS_OK(werr)) {
 
504
                        DEBUG(0,("failed to apply registry: %s\n",
 
505
                                win_errstr(werr)));
 
506
                        goto done;
 
507
                }
 
508
        }
 
509
 
 
510
done:
 
511
        gp_free_reg_ctx(reg_ctx);
 
512
        return werr;
 
513
}
 
514
 
 
515
 
 
516
/****************************************************************
 
517
****************************************************************/
 
518
 
 
519
static NTSTATUS registry_process_group_policy(ADS_STRUCT *ads,
 
520
                                              TALLOC_CTX *mem_ctx,
 
521
                                              uint32_t flags,
 
522
                                              struct registry_key *root_key,
 
523
                                              const struct nt_user_token *token,
 
524
                                              struct GROUP_POLICY_OBJECT *gpo,
 
525
                                              const char *extension_guid,
 
526
                                              const char *snapin_guid)
 
527
{
 
528
        NTSTATUS status;
 
529
        WERROR werr;
 
530
        struct gp_registry_entry *entries = NULL;
 
531
        size_t num_entries = 0;
 
532
        char *unix_path = NULL;
 
533
 
 
534
        debug_gpext_header(0, "registry_process_group_policy", flags, gpo,
 
535
                           extension_guid, snapin_guid);
 
536
 
 
537
        status = gpo_get_unix_path(mem_ctx, gpo, &unix_path);
 
538
        NT_STATUS_NOT_OK_RETURN(status);
 
539
 
 
540
        status = reg_parse_registry(mem_ctx,
 
541
                                    flags,
 
542
                                    unix_path,
 
543
                                    &entries,
 
544
                                    &num_entries);
 
545
        if (!NT_STATUS_IS_OK(status)) {
 
546
                DEBUG(0,("failed to parse registry: %s\n",
 
547
                        nt_errstr(status)));
 
548
                return status;
 
549
        }
 
550
 
 
551
        dump_reg_entries(flags, "READ", entries, num_entries);
 
552
 
 
553
        werr = reg_apply_registry(mem_ctx, token, root_key, flags,
 
554
                                  entries, num_entries);
 
555
        if (!W_ERROR_IS_OK(werr)) {
 
556
                DEBUG(0,("failed to apply registry: %s\n",
 
557
                        win_errstr(werr)));
 
558
                return werror_to_ntstatus(werr);
 
559
        }
 
560
 
 
561
        return NT_STATUS_OK;
 
562
}
 
563
 
 
564
/****************************************************************
 
565
****************************************************************/
 
566
 
 
567
static NTSTATUS registry_get_reg_config(TALLOC_CTX *mem_ctx,
 
568
                                        struct gp_extension_reg_info **reg_info)
 
569
{
 
570
        NTSTATUS status;
 
571
        struct gp_extension_reg_info *info = NULL;
 
572
        struct gp_extension_reg_table table[] = {
 
573
                { "ProcessGroupPolicy", REG_SZ, "registry_process_group_policy" },
 
574
                { NULL, REG_NONE, NULL }
 
575
        };
 
576
 
 
577
        info = TALLOC_ZERO_P(mem_ctx, struct gp_extension_reg_info);
 
578
        NT_STATUS_HAVE_NO_MEMORY(info);
 
579
 
 
580
        status = gp_ext_info_add_entry(mem_ctx, GP_EXT_NAME,
 
581
                                       GP_EXT_GUID_REGISTRY,
 
582
                                       table, info);
 
583
        NT_STATUS_NOT_OK_RETURN(status);
 
584
 
 
585
        *reg_info = info;
 
586
 
 
587
        return NT_STATUS_OK;
 
588
}
 
589
 
 
590
/****************************************************************
 
591
****************************************************************/
 
592
 
 
593
static NTSTATUS registry_initialize(TALLOC_CTX *mem_ctx)
 
594
{
 
595
        return NT_STATUS_OK;
 
596
}
 
597
 
 
598
/****************************************************************
 
599
****************************************************************/
 
600
 
 
601
static NTSTATUS registry_shutdown(void)
 
602
{
 
603
        NTSTATUS status;
 
604
 
 
605
        status = unregister_gp_extension(GP_EXT_NAME);
 
606
        if (NT_STATUS_IS_OK(status)) {
 
607
                return status;
 
608
        }
 
609
 
 
610
        TALLOC_FREE(ctx);
 
611
 
 
612
        return NT_STATUS_OK;
 
613
}
 
614
 
 
615
/****************************************************************
 
616
****************************************************************/
 
617
 
 
618
static struct gp_extension_methods registry_methods = {
 
619
        .initialize             = registry_initialize,
 
620
        .process_group_policy   = registry_process_group_policy,
 
621
        .get_reg_config         = registry_get_reg_config,
 
622
        .shutdown               = registry_shutdown
 
623
};
 
624
 
 
625
/****************************************************************
 
626
****************************************************************/
 
627
 
 
628
NTSTATUS gpext_registry_init(void)
 
629
{
 
630
        NTSTATUS status;
 
631
 
 
632
        ctx = talloc_init("gpext_registry_init");
 
633
        NT_STATUS_HAVE_NO_MEMORY(ctx);
 
634
 
 
635
        status = register_gp_extension(ctx, SMB_GPEXT_INTERFACE_VERSION,
 
636
                                       GP_EXT_NAME, GP_EXT_GUID_REGISTRY,
 
637
                                       &registry_methods);
 
638
        if (!NT_STATUS_IS_OK(status)) {
 
639
                TALLOC_FREE(ctx);
 
640
        }
 
641
 
 
642
        return status;
 
643
}