~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/libnet/libnet_samsync_ldif.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
   dump the remote SAM using rpc samsync operations
 
4
 
 
5
   Copyright (C) Andrew Tridgell 2002
 
6
   Copyright (C) Tim Potter 2001,2002
 
7
   Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
 
8
   Modified by Volker Lendecke 2002
 
9
   Copyright (C) Jeremy Allison 2005.
 
10
   Copyright (C) Guenther Deschner 2008.
 
11
 
 
12
   This program is free software; you can redistribute it and/or modify
 
13
   it under the terms of the GNU General Public License as published by
 
14
   the Free Software Foundation; either version 3 of the License, or
 
15
   (at your option) any later version.
 
16
 
 
17
   This program is distributed in the hope that it will be useful,
 
18
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
   GNU General Public License for more details.
 
21
 
 
22
   You should have received a copy of the GNU General Public License
 
23
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
24
*/
 
25
 
 
26
#include "includes.h"
 
27
#include "libnet/libnet_samsync.h"
 
28
 
 
29
#ifdef HAVE_LDAP
 
30
 
 
31
/* uid's and gid's for writing deltas to ldif */
 
32
static uint32 ldif_gid = 999;
 
33
static uint32 ldif_uid = 999;
 
34
 
 
35
/* global counters */
 
36
static uint32_t g_index = 0;
 
37
static uint32_t a_index = 0;
 
38
 
 
39
/* Structure for mapping accounts to groups */
 
40
/* Array element is the group rid */
 
41
typedef struct _groupmap {
 
42
        uint32_t rid;
 
43
        uint32_t gidNumber;
 
44
        const char *sambaSID;
 
45
        const char *group_dn;
 
46
} GROUPMAP;
 
47
 
 
48
typedef struct _accountmap {
 
49
        uint32_t rid;
 
50
        const char *cn;
 
51
} ACCOUNTMAP;
 
52
 
 
53
struct samsync_ldif_context {
 
54
        GROUPMAP *groupmap;
 
55
        ACCOUNTMAP *accountmap;
 
56
        bool initialized;
 
57
        const char *add_template;
 
58
        const char *mod_template;
 
59
        char *add_name;
 
60
        char *mod_name;
 
61
        FILE *add_file;
 
62
        FILE *mod_file;
 
63
        FILE *ldif_file;
 
64
        const char *suffix;
 
65
        int num_alloced;
 
66
};
 
67
 
 
68
/****************************************************************
 
69
****************************************************************/
 
70
 
 
71
static NTSTATUS populate_ldap_for_ldif(const char *sid,
 
72
                                       const char *suffix,
 
73
                                       const char *builtin_sid,
 
74
                                       FILE *add_fd)
 
75
{
 
76
        const char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix;
 
77
        char *user_attr=NULL, *group_attr=NULL;
 
78
        char *suffix_attr;
 
79
        int len;
 
80
 
 
81
        /* Get the suffix attribute */
 
82
        suffix_attr = sstring_sub(suffix, '=', ',');
 
83
        if (suffix_attr == NULL) {
 
84
                len = strlen(suffix);
 
85
                suffix_attr = (char*)SMB_MALLOC(len+1);
 
86
                memcpy(suffix_attr, suffix, len);
 
87
                suffix_attr[len] = '\0';
 
88
        }
 
89
 
 
90
        /* Write the base */
 
91
        fprintf(add_fd, "# %s\n", suffix);
 
92
        fprintf(add_fd, "dn: %s\n", suffix);
 
93
        fprintf(add_fd, "objectClass: dcObject\n");
 
94
        fprintf(add_fd, "objectClass: organization\n");
 
95
        fprintf(add_fd, "o: %s\n", suffix_attr);
 
96
        fprintf(add_fd, "dc: %s\n", suffix_attr);
 
97
        fprintf(add_fd, "\n");
 
98
        fflush(add_fd);
 
99
 
 
100
        user_suffix = lp_ldap_user_suffix();
 
101
        if (user_suffix == NULL) {
 
102
                SAFE_FREE(suffix_attr);
 
103
                return NT_STATUS_NO_MEMORY;
 
104
        }
 
105
        /* If it exists and is distinct from other containers,
 
106
           Write the Users entity */
 
107
        if (*user_suffix && strcmp(user_suffix, suffix)) {
 
108
                user_attr = sstring_sub(lp_ldap_user_suffix(), '=', ',');
 
109
                fprintf(add_fd, "# %s\n", user_suffix);
 
110
                fprintf(add_fd, "dn: %s\n", user_suffix);
 
111
                fprintf(add_fd, "objectClass: organizationalUnit\n");
 
112
                fprintf(add_fd, "ou: %s\n", user_attr);
 
113
                fprintf(add_fd, "\n");
 
114
                fflush(add_fd);
 
115
        }
 
116
 
 
117
 
 
118
        group_suffix = lp_ldap_group_suffix();
 
119
        if (group_suffix == NULL) {
 
120
                SAFE_FREE(suffix_attr);
 
121
                SAFE_FREE(user_attr);
 
122
                return NT_STATUS_NO_MEMORY;
 
123
        }
 
124
        /* If it exists and is distinct from other containers,
 
125
           Write the Groups entity */
 
126
        if (*group_suffix && strcmp(group_suffix, suffix)) {
 
127
                group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
 
128
                fprintf(add_fd, "# %s\n", group_suffix);
 
129
                fprintf(add_fd, "dn: %s\n", group_suffix);
 
130
                fprintf(add_fd, "objectClass: organizationalUnit\n");
 
131
                fprintf(add_fd, "ou: %s\n", group_attr);
 
132
                fprintf(add_fd, "\n");
 
133
                fflush(add_fd);
 
134
        }
 
135
 
 
136
        /* If it exists and is distinct from other containers,
 
137
           Write the Computers entity */
 
138
        machine_suffix = lp_ldap_machine_suffix();
 
139
        if (machine_suffix == NULL) {
 
140
                SAFE_FREE(suffix_attr);
 
141
                SAFE_FREE(user_attr);
 
142
                SAFE_FREE(group_attr);
 
143
                return NT_STATUS_NO_MEMORY;
 
144
        }
 
145
        if (*machine_suffix && strcmp(machine_suffix, user_suffix) &&
 
146
            strcmp(machine_suffix, suffix)) {
 
147
                char *machine_ou = NULL;
 
148
                fprintf(add_fd, "# %s\n", machine_suffix);
 
149
                fprintf(add_fd, "dn: %s\n", machine_suffix);
 
150
                fprintf(add_fd, "objectClass: organizationalUnit\n");
 
151
                /* this isn't totally correct as it assumes that
 
152
                   there _must_ be an ou. just fixing memleak now. jmcd */
 
153
                machine_ou = sstring_sub(lp_ldap_machine_suffix(), '=', ',');
 
154
                fprintf(add_fd, "ou: %s\n", machine_ou);
 
155
                SAFE_FREE(machine_ou);
 
156
                fprintf(add_fd, "\n");
 
157
                fflush(add_fd);
 
158
        }
 
159
 
 
160
        /* If it exists and is distinct from other containers,
 
161
           Write the IdMap entity */
 
162
        idmap_suffix = lp_ldap_idmap_suffix();
 
163
        if (idmap_suffix == NULL) {
 
164
                SAFE_FREE(suffix_attr);
 
165
                SAFE_FREE(user_attr);
 
166
                SAFE_FREE(group_attr);
 
167
                return NT_STATUS_NO_MEMORY;
 
168
        }
 
169
        if (*idmap_suffix &&
 
170
            strcmp(idmap_suffix, user_suffix) &&
 
171
            strcmp(idmap_suffix, suffix)) {
 
172
                char *s;
 
173
                fprintf(add_fd, "# %s\n", idmap_suffix);
 
174
                fprintf(add_fd, "dn: %s\n", idmap_suffix);
 
175
                fprintf(add_fd, "ObjectClass: organizationalUnit\n");
 
176
                s = sstring_sub(lp_ldap_idmap_suffix(), '=', ',');
 
177
                fprintf(add_fd, "ou: %s\n", s);
 
178
                SAFE_FREE(s);
 
179
                fprintf(add_fd, "\n");
 
180
                fflush(add_fd);
 
181
        }
 
182
 
 
183
        /* Write the domain entity */
 
184
        fprintf(add_fd, "# %s, %s\n", lp_workgroup(), suffix);
 
185
        fprintf(add_fd, "dn: sambaDomainName=%s,%s\n", lp_workgroup(),
 
186
                suffix);
 
187
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_DOMINFO);
 
188
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_IDPOOL);
 
189
        fprintf(add_fd, "sambaDomainName: %s\n", lp_workgroup());
 
190
        fprintf(add_fd, "sambaSID: %s\n", sid);
 
191
        fprintf(add_fd, "uidNumber: %d\n", ++ldif_uid);
 
192
        fprintf(add_fd, "gidNumber: %d\n", ++ldif_gid);
 
193
        fprintf(add_fd, "\n");
 
194
        fflush(add_fd);
 
195
 
 
196
        /* Write the Domain Admins entity */
 
197
        fprintf(add_fd, "# Domain Admins, %s, %s\n", group_attr,
 
198
                suffix);
 
199
        fprintf(add_fd, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr,
 
200
                suffix);
 
201
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 
202
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 
203
        fprintf(add_fd, "cn: Domain Admins\n");
 
204
        fprintf(add_fd, "memberUid: Administrator\n");
 
205
        fprintf(add_fd, "description: Netbios Domain Administrators\n");
 
206
        fprintf(add_fd, "gidNumber: 512\n");
 
207
        fprintf(add_fd, "sambaSID: %s-512\n", sid);
 
208
        fprintf(add_fd, "sambaGroupType: 2\n");
 
209
        fprintf(add_fd, "displayName: Domain Admins\n");
 
210
        fprintf(add_fd, "\n");
 
211
        fflush(add_fd);
 
212
 
 
213
        /* Write the Domain Users entity */
 
214
        fprintf(add_fd, "# Domain Users, %s, %s\n", group_attr,
 
215
                suffix);
 
216
        fprintf(add_fd, "dn: cn=Domain Users,ou=%s,%s\n", group_attr,
 
217
                suffix);
 
218
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 
219
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 
220
        fprintf(add_fd, "cn: Domain Users\n");
 
221
        fprintf(add_fd, "description: Netbios Domain Users\n");
 
222
        fprintf(add_fd, "gidNumber: 513\n");
 
223
        fprintf(add_fd, "sambaSID: %s-513\n", sid);
 
224
        fprintf(add_fd, "sambaGroupType: 2\n");
 
225
        fprintf(add_fd, "displayName: Domain Users\n");
 
226
        fprintf(add_fd, "\n");
 
227
        fflush(add_fd);
 
228
 
 
229
        /* Write the Domain Guests entity */
 
230
        fprintf(add_fd, "# Domain Guests, %s, %s\n", group_attr,
 
231
                suffix);
 
232
        fprintf(add_fd, "dn: cn=Domain Guests,ou=%s,%s\n", group_attr,
 
233
                suffix);
 
234
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 
235
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 
236
        fprintf(add_fd, "cn: Domain Guests\n");
 
237
        fprintf(add_fd, "description: Netbios Domain Guests\n");
 
238
        fprintf(add_fd, "gidNumber: 514\n");
 
239
        fprintf(add_fd, "sambaSID: %s-514\n", sid);
 
240
        fprintf(add_fd, "sambaGroupType: 2\n");
 
241
        fprintf(add_fd, "displayName: Domain Guests\n");
 
242
        fprintf(add_fd, "\n");
 
243
        fflush(add_fd);
 
244
 
 
245
        /* Write the Domain Computers entity */
 
246
        fprintf(add_fd, "# Domain Computers, %s, %s\n", group_attr,
 
247
                suffix);
 
248
        fprintf(add_fd, "dn: cn=Domain Computers,ou=%s,%s\n",
 
249
                group_attr, suffix);
 
250
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 
251
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 
252
        fprintf(add_fd, "gidNumber: 515\n");
 
253
        fprintf(add_fd, "cn: Domain Computers\n");
 
254
        fprintf(add_fd, "description: Netbios Domain Computers accounts\n");
 
255
        fprintf(add_fd, "sambaSID: %s-515\n", sid);
 
256
        fprintf(add_fd, "sambaGroupType: 2\n");
 
257
        fprintf(add_fd, "displayName: Domain Computers\n");
 
258
        fprintf(add_fd, "\n");
 
259
        fflush(add_fd);
 
260
 
 
261
        /* Write the Admininistrators Groups entity */
 
262
        fprintf(add_fd, "# Administrators, %s, %s\n", group_attr,
 
263
                suffix);
 
264
        fprintf(add_fd, "dn: cn=Administrators,ou=%s,%s\n", group_attr,
 
265
                suffix);
 
266
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 
267
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 
268
        fprintf(add_fd, "gidNumber: 544\n");
 
269
        fprintf(add_fd, "cn: Administrators\n");
 
270
        fprintf(add_fd, "description: Netbios Domain Members can fully administer the computer/sambaDomainName\n");
 
271
        fprintf(add_fd, "sambaSID: %s-544\n", builtin_sid);
 
272
        fprintf(add_fd, "sambaGroupType: 5\n");
 
273
        fprintf(add_fd, "displayName: Administrators\n");
 
274
        fprintf(add_fd, "\n");
 
275
 
 
276
        /* Write the Print Operator entity */
 
277
        fprintf(add_fd, "# Print Operators, %s, %s\n", group_attr,
 
278
                suffix);
 
279
        fprintf(add_fd, "dn: cn=Print Operators,ou=%s,%s\n",
 
280
                group_attr, suffix);
 
281
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 
282
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 
283
        fprintf(add_fd, "gidNumber: 550\n");
 
284
        fprintf(add_fd, "cn: Print Operators\n");
 
285
        fprintf(add_fd, "description: Netbios Domain Print Operators\n");
 
286
        fprintf(add_fd, "sambaSID: %s-550\n", builtin_sid);
 
287
        fprintf(add_fd, "sambaGroupType: 5\n");
 
288
        fprintf(add_fd, "displayName: Print Operators\n");
 
289
        fprintf(add_fd, "\n");
 
290
        fflush(add_fd);
 
291
 
 
292
        /* Write the Backup Operators entity */
 
293
        fprintf(add_fd, "# Backup Operators, %s, %s\n", group_attr,
 
294
                suffix);
 
295
        fprintf(add_fd, "dn: cn=Backup Operators,ou=%s,%s\n",
 
296
                group_attr, suffix);
 
297
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 
298
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 
299
        fprintf(add_fd, "gidNumber: 551\n");
 
300
        fprintf(add_fd, "cn: Backup Operators\n");
 
301
        fprintf(add_fd, "description: Netbios Domain Members can bypass file security to back up files\n");
 
302
        fprintf(add_fd, "sambaSID: %s-551\n", builtin_sid);
 
303
        fprintf(add_fd, "sambaGroupType: 5\n");
 
304
        fprintf(add_fd, "displayName: Backup Operators\n");
 
305
        fprintf(add_fd, "\n");
 
306
        fflush(add_fd);
 
307
 
 
308
        /* Write the Replicators entity */
 
309
        fprintf(add_fd, "# Replicators, %s, %s\n", group_attr, suffix);
 
310
        fprintf(add_fd, "dn: cn=Replicators,ou=%s,%s\n", group_attr,
 
311
                suffix);
 
312
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 
313
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 
314
        fprintf(add_fd, "gidNumber: 552\n");
 
315
        fprintf(add_fd, "cn: Replicators\n");
 
316
        fprintf(add_fd, "description: Netbios Domain Supports file replication in a sambaDomainName\n");
 
317
        fprintf(add_fd, "sambaSID: %s-552\n", builtin_sid);
 
318
        fprintf(add_fd, "sambaGroupType: 5\n");
 
319
        fprintf(add_fd, "displayName: Replicators\n");
 
320
        fprintf(add_fd, "\n");
 
321
        fflush(add_fd);
 
322
 
 
323
        /* Deallocate memory, and return */
 
324
        SAFE_FREE(suffix_attr);
 
325
        SAFE_FREE(user_attr);
 
326
        SAFE_FREE(group_attr);
 
327
        return NT_STATUS_OK;
 
328
}
 
329
 
 
330
/****************************************************************
 
331
****************************************************************/
 
332
 
 
333
static NTSTATUS map_populate_groups(TALLOC_CTX *mem_ctx,
 
334
                                    GROUPMAP *groupmap,
 
335
                                    ACCOUNTMAP *accountmap,
 
336
                                    const char *sid,
 
337
                                    const char *suffix,
 
338
                                    const char *builtin_sid)
 
339
{
 
340
        char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
 
341
 
 
342
        /* Map the groups created by populate_ldap_for_ldif */
 
343
        groupmap[0].rid         = 512;
 
344
        groupmap[0].gidNumber   = 512;
 
345
        groupmap[0].sambaSID    = talloc_asprintf(mem_ctx, "%s-512", sid);
 
346
        groupmap[0].group_dn    = talloc_asprintf(mem_ctx,
 
347
                "cn=Domain Admins,ou=%s,%s", group_attr, suffix);
 
348
        if (groupmap[0].sambaSID == NULL || groupmap[0].group_dn == NULL) {
 
349
                goto err;
 
350
        }
 
351
 
 
352
        accountmap[0].rid       = 512;
 
353
        accountmap[0].cn        = talloc_strdup(mem_ctx, "Domain Admins");
 
354
        if (accountmap[0].cn == NULL) {
 
355
                goto err;
 
356
        }
 
357
 
 
358
        groupmap[1].rid         = 513;
 
359
        groupmap[1].gidNumber   = 513;
 
360
        groupmap[1].sambaSID    = talloc_asprintf(mem_ctx, "%s-513", sid);
 
361
        groupmap[1].group_dn    = talloc_asprintf(mem_ctx,
 
362
                "cn=Domain Users,ou=%s,%s", group_attr, suffix);
 
363
        if (groupmap[1].sambaSID == NULL || groupmap[1].group_dn == NULL) {
 
364
                goto err;
 
365
        }
 
366
 
 
367
        accountmap[1].rid       = 513;
 
368
        accountmap[1].cn        = talloc_strdup(mem_ctx, "Domain Users");
 
369
        if (accountmap[1].cn == NULL) {
 
370
                goto err;
 
371
        }
 
372
 
 
373
        groupmap[2].rid         = 514;
 
374
        groupmap[2].gidNumber   = 514;
 
375
        groupmap[2].sambaSID    = talloc_asprintf(mem_ctx, "%s-514", sid);
 
376
        groupmap[2].group_dn    = talloc_asprintf(mem_ctx,
 
377
                "cn=Domain Guests,ou=%s,%s", group_attr, suffix);
 
378
        if (groupmap[2].sambaSID == NULL || groupmap[2].group_dn == NULL) {
 
379
                goto err;
 
380
        }
 
381
 
 
382
        accountmap[2].rid       = 514;
 
383
        accountmap[2].cn        = talloc_strdup(mem_ctx, "Domain Guests");
 
384
        if (accountmap[2].cn == NULL) {
 
385
                goto err;
 
386
        }
 
387
 
 
388
        groupmap[3].rid         = 515;
 
389
        groupmap[3].gidNumber   = 515;
 
390
        groupmap[3].sambaSID    = talloc_asprintf(mem_ctx, "%s-515", sid);
 
391
        groupmap[3].group_dn    = talloc_asprintf(mem_ctx,
 
392
                "cn=Domain Computers,ou=%s,%s", group_attr, suffix);
 
393
        if (groupmap[3].sambaSID == NULL || groupmap[3].group_dn == NULL) {
 
394
                goto err;
 
395
        }
 
396
 
 
397
        accountmap[3].rid       = 515;
 
398
        accountmap[3].cn        = talloc_strdup(mem_ctx, "Domain Computers");
 
399
        if (accountmap[3].cn == NULL) {
 
400
                goto err;
 
401
        }
 
402
 
 
403
        groupmap[4].rid         = 544;
 
404
        groupmap[4].gidNumber   = 544;
 
405
        groupmap[4].sambaSID    = talloc_asprintf(mem_ctx, "%s-544", builtin_sid);
 
406
        groupmap[4].group_dn    = talloc_asprintf(mem_ctx,
 
407
                "cn=Administrators,ou=%s,%s", group_attr, suffix);
 
408
        if (groupmap[4].sambaSID == NULL || groupmap[4].group_dn == NULL) {
 
409
                goto err;
 
410
        }
 
411
 
 
412
        accountmap[4].rid       = 515;
 
413
        accountmap[4].cn        = talloc_strdup(mem_ctx, "Administrators");
 
414
        if (accountmap[4].cn == NULL) {
 
415
                goto err;
 
416
        }
 
417
 
 
418
        groupmap[5].rid         = 550;
 
419
        groupmap[5].gidNumber   = 550;
 
420
        groupmap[5].sambaSID    = talloc_asprintf(mem_ctx, "%s-550", builtin_sid);
 
421
        groupmap[5].group_dn    = talloc_asprintf(mem_ctx,
 
422
                "cn=Print Operators,ou=%s,%s", group_attr, suffix);
 
423
        if (groupmap[5].sambaSID == NULL || groupmap[5].group_dn == NULL) {
 
424
                goto err;
 
425
        }
 
426
 
 
427
        accountmap[5].rid       = 550;
 
428
        accountmap[5].cn        = talloc_strdup(mem_ctx, "Print Operators");
 
429
        if (accountmap[5].cn == NULL) {
 
430
                goto err;
 
431
        }
 
432
 
 
433
        groupmap[6].rid         = 551;
 
434
        groupmap[6].gidNumber   = 551;
 
435
        groupmap[6].sambaSID    = talloc_asprintf(mem_ctx, "%s-551", builtin_sid);
 
436
        groupmap[6].group_dn    = talloc_asprintf(mem_ctx,
 
437
                "cn=Backup Operators,ou=%s,%s", group_attr, suffix);
 
438
        if (groupmap[6].sambaSID == NULL || groupmap[6].group_dn == NULL) {
 
439
                goto err;
 
440
        }
 
441
 
 
442
        accountmap[6].rid       = 551;
 
443
        accountmap[6].cn        = talloc_strdup(mem_ctx, "Backup Operators");
 
444
        if (accountmap[6].cn == NULL) {
 
445
                goto err;
 
446
        }
 
447
 
 
448
        groupmap[7].rid         = 552;
 
449
        groupmap[7].gidNumber   = 552;
 
450
        groupmap[7].sambaSID    = talloc_asprintf(mem_ctx, "%s-552", builtin_sid);
 
451
        groupmap[7].group_dn    = talloc_asprintf(mem_ctx,
 
452
                "cn=Replicators,ou=%s,%s", group_attr, suffix);
 
453
        if (groupmap[7].sambaSID == NULL || groupmap[7].group_dn == NULL) {
 
454
                goto err;
 
455
        }
 
456
 
 
457
        accountmap[7].rid       = 551;
 
458
        accountmap[7].cn        = talloc_strdup(mem_ctx, "Replicators");
 
459
        if (accountmap[7].cn == NULL) {
 
460
                goto err;
 
461
        }
 
462
 
 
463
        SAFE_FREE(group_attr);
 
464
 
 
465
        return NT_STATUS_OK;
 
466
 
 
467
  err:
 
468
 
 
469
        SAFE_FREE(group_attr);
 
470
        return NT_STATUS_NO_MEMORY;
 
471
}
 
472
 
 
473
/*
 
474
 * This is a crap routine, but I think it's the quickest way to solve the
 
475
 * UTF8->base64 problem.
 
476
 */
 
477
 
 
478
static int fprintf_attr(FILE *add_fd, const char *attr_name,
 
479
                        const char *fmt, ...)
 
480
{
 
481
        va_list ap;
 
482
        char *value, *p, *base64;
 
483
        DATA_BLOB base64_blob;
 
484
        bool do_base64 = false;
 
485
        int res;
 
486
 
 
487
        va_start(ap, fmt);
 
488
        value = talloc_vasprintf(NULL, fmt, ap);
 
489
        va_end(ap);
 
490
 
 
491
        SMB_ASSERT(value != NULL);
 
492
 
 
493
        for (p=value; *p; p++) {
 
494
                if (*p & 0x80) {
 
495
                        do_base64 = true;
 
496
                        break;
 
497
                }
 
498
        }
 
499
 
 
500
        if (!do_base64) {
 
501
                bool only_whitespace = true;
 
502
                for (p=value; *p; p++) {
 
503
                        /*
 
504
                         * I know that this not multibyte safe, but we break
 
505
                         * on the first non-whitespace character anyway.
 
506
                         */
 
507
                        if (!isspace(*p)) {
 
508
                                only_whitespace = false;
 
509
                                break;
 
510
                        }
 
511
                }
 
512
                if (only_whitespace) {
 
513
                        do_base64 = true;
 
514
                }
 
515
        }
 
516
 
 
517
        if (!do_base64) {
 
518
                res = fprintf(add_fd, "%s: %s\n", attr_name, value);
 
519
                TALLOC_FREE(value);
 
520
                return res;
 
521
        }
 
522
 
 
523
        base64_blob.data = (unsigned char *)value;
 
524
        base64_blob.length = strlen(value);
 
525
 
 
526
        base64 = base64_encode_data_blob(value, base64_blob);
 
527
        SMB_ASSERT(base64 != NULL);
 
528
 
 
529
        res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
 
530
        TALLOC_FREE(value);
 
531
        return res;
 
532
}
 
533
 
 
534
/****************************************************************
 
535
****************************************************************/
 
536
 
 
537
static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx,
 
538
                                         struct netr_DELTA_GROUP *r,
 
539
                                         GROUPMAP *groupmap,
 
540
                                         FILE *add_fd,
 
541
                                         const char *sid,
 
542
                                         const char *suffix)
 
543
{
 
544
        const char *groupname = r->group_name.string;
 
545
        uint32 grouptype = 0, g_rid = 0;
 
546
        char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
 
547
 
 
548
        /* Set up the group type (always 2 for group info) */
 
549
        grouptype = 2;
 
550
 
 
551
        /* These groups are entered by populate_ldap_for_ldif */
 
552
        if (strcmp(groupname, "Domain Admins") == 0 ||
 
553
            strcmp(groupname, "Domain Users") == 0 ||
 
554
            strcmp(groupname, "Domain Guests") == 0 ||
 
555
            strcmp(groupname, "Domain Computers") == 0 ||
 
556
            strcmp(groupname, "Administrators") == 0 ||
 
557
            strcmp(groupname, "Print Operators") == 0 ||
 
558
            strcmp(groupname, "Backup Operators") == 0 ||
 
559
            strcmp(groupname, "Replicators") == 0) {
 
560
                SAFE_FREE(group_attr);
 
561
                return NT_STATUS_OK;
 
562
        } else {
 
563
                /* Increment the gid for the new group */
 
564
                ldif_gid++;
 
565
        }
 
566
 
 
567
        /* Map the group rid, gid, and dn */
 
568
        g_rid = r->rid;
 
569
        groupmap->rid = g_rid;
 
570
        groupmap->gidNumber = ldif_gid;
 
571
        groupmap->sambaSID      = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
 
572
        groupmap->group_dn      = talloc_asprintf(mem_ctx,
 
573
             "cn=%s,ou=%s,%s", groupname, group_attr, suffix);
 
574
        if (groupmap->sambaSID == NULL || groupmap->group_dn == NULL) {
 
575
                SAFE_FREE(group_attr);
 
576
                return NT_STATUS_NO_MEMORY;
 
577
        }
 
578
 
 
579
        /* Write the data to the temporary add ldif file */
 
580
        fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr,
 
581
                suffix);
 
582
        fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", groupname, group_attr,
 
583
                     suffix);
 
584
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 
585
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 
586
        fprintf_attr(add_fd, "cn", "%s", groupname);
 
587
        fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
 
588
        fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
 
589
        fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
 
590
        fprintf_attr(add_fd, "displayName", "%s", groupname);
 
591
        fprintf(add_fd, "\n");
 
592
        fflush(add_fd);
 
593
 
 
594
        SAFE_FREE(group_attr);
 
595
        /* Return */
 
596
        return NT_STATUS_OK;
 
597
}
 
598
 
 
599
/****************************************************************
 
600
****************************************************************/
 
601
 
 
602
static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx,
 
603
                                           struct netr_DELTA_USER *r,
 
604
                                           GROUPMAP *groupmap,
 
605
                                           ACCOUNTMAP *accountmap,
 
606
                                           FILE *add_fd,
 
607
                                           const char *sid,
 
608
                                           const char *suffix,
 
609
                                           int alloced)
 
610
{
 
611
        fstring username, logonscript, homedrive, homepath = "", homedir = "";
 
612
        fstring hex_nt_passwd, hex_lm_passwd;
 
613
        fstring description, profilepath, fullname, sambaSID;
 
614
        char *flags, *user_rdn;
 
615
        const char *ou;
 
616
        const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
 
617
        uchar zero_buf[16];
 
618
        uint32 rid = 0, group_rid = 0, gidNumber = 0;
 
619
        time_t unix_time;
 
620
        int i, ret;
 
621
 
 
622
        memset(zero_buf, '\0', sizeof(zero_buf));
 
623
 
 
624
        /* Get the username */
 
625
        fstrcpy(username, r->account_name.string);
 
626
 
 
627
        /* Get the rid */
 
628
        rid = r->rid;
 
629
 
 
630
        /* Map the rid and username for group member info later */
 
631
        accountmap->rid = rid;
 
632
        accountmap->cn = talloc_strdup(mem_ctx, username);
 
633
        NT_STATUS_HAVE_NO_MEMORY(accountmap->cn);
 
634
 
 
635
        /* Get the home directory */
 
636
        if (r->acct_flags & ACB_NORMAL) {
 
637
                fstrcpy(homedir, r->home_directory.string);
 
638
                if (!*homedir) {
 
639
                        snprintf(homedir, sizeof(homedir), "/home/%s", username);
 
640
                } else {
 
641
                        snprintf(homedir, sizeof(homedir), "/nobodyshomedir");
 
642
                }
 
643
                ou = lp_ldap_user_suffix();
 
644
        } else {
 
645
                ou = lp_ldap_machine_suffix();
 
646
                snprintf(homedir, sizeof(homedir), "/machinehomedir");
 
647
        }
 
648
 
 
649
        /* Get the logon script */
 
650
        fstrcpy(logonscript, r->logon_script.string);
 
651
 
 
652
        /* Get the home drive */
 
653
        fstrcpy(homedrive, r->home_drive.string);
 
654
 
 
655
        /* Get the home path */
 
656
        fstrcpy(homepath, r->home_directory.string);
 
657
 
 
658
        /* Get the description */
 
659
        fstrcpy(description, r->description.string);
 
660
 
 
661
        /* Get the display name */
 
662
        fstrcpy(fullname, r->full_name.string);
 
663
 
 
664
        /* Get the profile path */
 
665
        fstrcpy(profilepath, r->profile_path.string);
 
666
 
 
667
        /* Get lm and nt password data */
 
668
        if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
 
669
                pdb_sethexpwd(hex_lm_passwd, r->lmpassword.hash, r->acct_flags);
 
670
        } else {
 
671
                pdb_sethexpwd(hex_lm_passwd, NULL, 0);
 
672
        }
 
673
        if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
 
674
                pdb_sethexpwd(hex_nt_passwd, r->ntpassword.hash, r->acct_flags);
 
675
        } else {
 
676
                pdb_sethexpwd(hex_nt_passwd, NULL, 0);
 
677
        }
 
678
        unix_time = nt_time_to_unix(r->last_password_change);
 
679
 
 
680
        /* Increment the uid for the new user */
 
681
        ldif_uid++;
 
682
 
 
683
        /* Set up group id and sambaSID for the user */
 
684
        group_rid = r->primary_gid;
 
685
        for (i=0; i<alloced; i++) {
 
686
                if (groupmap[i].rid == group_rid) break;
 
687
        }
 
688
        if (i == alloced){
 
689
                DEBUG(1, ("Could not find rid %d in groupmap array\n",
 
690
                          group_rid));
 
691
                return NT_STATUS_UNSUCCESSFUL;
 
692
        }
 
693
        gidNumber = groupmap[i].gidNumber;
 
694
        ret = snprintf(sambaSID, sizeof(sambaSID), "%s", groupmap[i].sambaSID);
 
695
        if (ret < 0 || ret == sizeof(sambaSID)) {
 
696
                return NT_STATUS_UNSUCCESSFUL;
 
697
        }
 
698
 
 
699
        /* Set up sambaAcctFlags */
 
700
        flags = pdb_encode_acct_ctrl(r->acct_flags,
 
701
                                     NEW_PW_FORMAT_SPACE_PADDED_LEN);
 
702
 
 
703
        /* Add the user to the temporary add ldif file */
 
704
        /* this isn't quite right...we can't assume there's just OU=. jmcd */
 
705
        user_rdn = sstring_sub(ou, '=', ',');
 
706
        fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
 
707
        fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
 
708
                     suffix);
 
709
        SAFE_FREE(user_rdn);
 
710
        fprintf(add_fd, "ObjectClass: top\n");
 
711
        fprintf(add_fd, "objectClass: inetOrgPerson\n");
 
712
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT);
 
713
        fprintf(add_fd, "objectClass: shadowAccount\n");
 
714
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT);
 
715
        fprintf_attr(add_fd, "cn", "%s", username);
 
716
        fprintf_attr(add_fd, "sn", "%s", username);
 
717
        fprintf_attr(add_fd, "uid", "%s", username);
 
718
        fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
 
719
        fprintf(add_fd, "gidNumber: %d\n", gidNumber);
 
720
        fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
 
721
        if (*homepath)
 
722
                fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
 
723
        if (*homedrive)
 
724
                fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
 
725
        if (*logonscript)
 
726
                fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
 
727
        fprintf(add_fd, "loginShell: %s\n",
 
728
                ((r->acct_flags & ACB_NORMAL) ?
 
729
                 "/bin/bash" : "/bin/false"));
 
730
        fprintf(add_fd, "gecos: System User\n");
 
731
        if (*description)
 
732
                fprintf_attr(add_fd, "description", "%s", description);
 
733
        fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
 
734
        fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
 
735
        if(*fullname)
 
736
                fprintf_attr(add_fd, "displayName", "%s", fullname);
 
737
        if(*profilepath)
 
738
                fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
 
739
        if (strcmp(nopasswd, hex_lm_passwd) != 0)
 
740
                fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
 
741
        if (strcmp(nopasswd, hex_nt_passwd) != 0)
 
742
                fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd);
 
743
        fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time);
 
744
        fprintf(add_fd, "sambaAcctFlags: %s\n", flags);
 
745
        fprintf(add_fd, "\n");
 
746
        fflush(add_fd);
 
747
 
 
748
        /* Return */
 
749
        return NT_STATUS_OK;
 
750
}
 
751
 
 
752
/****************************************************************
 
753
****************************************************************/
 
754
 
 
755
static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx,
 
756
                                         struct netr_DELTA_ALIAS *r,
 
757
                                         GROUPMAP *groupmap,
 
758
                                         FILE *add_fd,
 
759
                                         const char *sid,
 
760
                                         const char *suffix,
 
761
                                         enum netr_SamDatabaseID database_id)
 
762
{
 
763
        fstring aliasname, description;
 
764
        uint32 grouptype = 0, g_rid = 0;
 
765
        char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
 
766
 
 
767
        /* Get the alias name */
 
768
        fstrcpy(aliasname, r->alias_name.string);
 
769
 
 
770
        /* Get the alias description */
 
771
        fstrcpy(description, r->description.string);
 
772
 
 
773
        /* Set up the group type */
 
774
        switch (database_id) {
 
775
        case SAM_DATABASE_DOMAIN:
 
776
                grouptype = 4;
 
777
                break;
 
778
        case SAM_DATABASE_BUILTIN:
 
779
                grouptype = 5;
 
780
                break;
 
781
        default:
 
782
                grouptype = 4;
 
783
                break;
 
784
        }
 
785
 
 
786
        /*
 
787
          These groups are entered by populate_ldap_for_ldif
 
788
          Note that populate creates a group called Relicators,
 
789
          but NT returns a group called Replicator
 
790
        */
 
791
        if (strcmp(aliasname, "Domain Admins") == 0 ||
 
792
            strcmp(aliasname, "Domain Users") == 0 ||
 
793
            strcmp(aliasname, "Domain Guests") == 0 ||
 
794
            strcmp(aliasname, "Domain Computers") == 0 ||
 
795
            strcmp(aliasname, "Administrators") == 0 ||
 
796
            strcmp(aliasname, "Print Operators") == 0 ||
 
797
            strcmp(aliasname, "Backup Operators") == 0 ||
 
798
            strcmp(aliasname, "Replicator") == 0) {
 
799
                SAFE_FREE(group_attr);
 
800
                return NT_STATUS_OK;
 
801
        } else {
 
802
                /* Increment the gid for the new group */
 
803
                ldif_gid++;
 
804
        }
 
805
 
 
806
        /* Map the group rid and gid */
 
807
        g_rid = r->rid;
 
808
        groupmap->gidNumber = ldif_gid;
 
809
        groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
 
810
        if (groupmap->sambaSID == NULL) {
 
811
                SAFE_FREE(group_attr);
 
812
                return NT_STATUS_NO_MEMORY;
 
813
        }
 
814
 
 
815
        /* Write the data to the temporary add ldif file */
 
816
        fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr,
 
817
                suffix);
 
818
        fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", aliasname, group_attr,
 
819
                     suffix);
 
820
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
 
821
        fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
 
822
        fprintf(add_fd, "cn: %s\n", aliasname);
 
823
        fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
 
824
        fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
 
825
        fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
 
826
        fprintf_attr(add_fd, "displayName", "%s", aliasname);
 
827
        if (description[0])
 
828
                fprintf_attr(add_fd, "description", "%s", description);
 
829
        fprintf(add_fd, "\n");
 
830
        fflush(add_fd);
 
831
 
 
832
        SAFE_FREE(group_attr);
 
833
        /* Return */
 
834
        return NT_STATUS_OK;
 
835
}
 
836
 
 
837
/****************************************************************
 
838
****************************************************************/
 
839
 
 
840
static NTSTATUS fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER *r,
 
841
                                            uint32_t id_rid,
 
842
                                            GROUPMAP *groupmap,
 
843
                                            ACCOUNTMAP *accountmap,
 
844
                                            FILE *mod_fd, int alloced)
 
845
{
 
846
        fstring group_dn;
 
847
        uint32 group_rid = 0, rid = 0;
 
848
        int i, j, k;
 
849
 
 
850
        /* Get the dn for the group */
 
851
        if (r->num_rids > 0) {
 
852
                group_rid = id_rid;
 
853
                for (j=0; j<alloced; j++) {
 
854
                        if (groupmap[j].rid == group_rid) break;
 
855
                }
 
856
                if (j == alloced){
 
857
                        DEBUG(1, ("Could not find rid %d in groupmap array\n",
 
858
                                  group_rid));
 
859
                        return NT_STATUS_UNSUCCESSFUL;
 
860
                }
 
861
                snprintf(group_dn, sizeof(group_dn), "%s", groupmap[j].group_dn);
 
862
                fprintf(mod_fd, "dn: %s\n", group_dn);
 
863
 
 
864
                /* Get the cn for each member */
 
865
                for (i=0; i < r->num_rids; i++) {
 
866
                        rid = r->rids[i];
 
867
                        for (k=0; k<alloced; k++) {
 
868
                                if (accountmap[k].rid == rid) break;
 
869
                        }
 
870
                        if (k == alloced){
 
871
                                DEBUG(1, ("Could not find rid %d in "
 
872
                                          "accountmap array\n", rid));
 
873
                                return NT_STATUS_UNSUCCESSFUL;
 
874
                        }
 
875
                        fprintf(mod_fd, "memberUid: %s\n", accountmap[k].cn);
 
876
                }
 
877
                fprintf(mod_fd, "\n");
 
878
        }
 
879
        fflush(mod_fd);
 
880
 
 
881
        /* Return */
 
882
        return NT_STATUS_OK;
 
883
}
 
884
 
 
885
/****************************************************************
 
886
****************************************************************/
 
887
 
 
888
static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx,
 
889
                                  enum netr_SamDatabaseID database_id,
 
890
                                  const char *ldif_filename,
 
891
                                  const char *domain_sid_str,
 
892
                                  struct samsync_ldif_context **ctx)
 
893
{
 
894
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
 
895
        struct samsync_ldif_context *r;
 
896
        const char *add_template = "/tmp/add.ldif.XXXXXX";
 
897
        const char *mod_template = "/tmp/mod.ldif.XXXXXX";
 
898
        const char *builtin_sid = "S-1-5-32";
 
899
 
 
900
        /* Get other smb.conf data */
 
901
        if (!(lp_workgroup()) || !*(lp_workgroup())) {
 
902
                DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
 
903
                exit(1);
 
904
        }
 
905
 
 
906
        /* Get the ldap suffix */
 
907
        if (!(lp_ldap_suffix()) || !*(lp_ldap_suffix())) {
 
908
                DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
 
909
                exit(1);
 
910
        }
 
911
 
 
912
        if (*ctx && (*ctx)->initialized) {
 
913
                return NT_STATUS_OK;
 
914
        }
 
915
 
 
916
        r = TALLOC_ZERO_P(mem_ctx, struct samsync_ldif_context);
 
917
        NT_STATUS_HAVE_NO_MEMORY(r);
 
918
 
 
919
        /* Get the ldap suffix */
 
920
        r->suffix = lp_ldap_suffix();
 
921
 
 
922
        /* Ensure we have an output file */
 
923
        if (ldif_filename) {
 
924
                r->ldif_file = fopen(ldif_filename, "a");
 
925
        } else {
 
926
                r->ldif_file = stdout;
 
927
        }
 
928
 
 
929
        if (!r->ldif_file) {
 
930
                fprintf(stderr, "Could not open %s\n", ldif_filename);
 
931
                DEBUG(1, ("Could not open %s\n", ldif_filename));
 
932
                status = NT_STATUS_UNSUCCESSFUL;
 
933
                goto done;
 
934
        }
 
935
 
 
936
        r->add_template = talloc_strdup(mem_ctx, add_template);
 
937
        r->mod_template = talloc_strdup(mem_ctx, mod_template);
 
938
        if (!r->add_template || !r->mod_template) {
 
939
                status = NT_STATUS_NO_MEMORY;
 
940
                goto done;
 
941
        }
 
942
 
 
943
        r->add_name = talloc_strdup(mem_ctx, add_template);
 
944
        r->mod_name = talloc_strdup(mem_ctx, mod_template);
 
945
        if (!r->add_name || !r->mod_name) {
 
946
                status = NT_STATUS_NO_MEMORY;
 
947
                goto done;
 
948
        }
 
949
 
 
950
        /* Open the add and mod ldif files */
 
951
        if (!(r->add_file = fdopen(smb_mkstemp(r->add_name),"w"))) {
 
952
                DEBUG(1, ("Could not open %s\n", r->add_name));
 
953
                status = NT_STATUS_UNSUCCESSFUL;
 
954
                goto done;
 
955
        }
 
956
        if (!(r->mod_file = fdopen(smb_mkstemp(r->mod_name),"w"))) {
 
957
                DEBUG(1, ("Could not open %s\n", r->mod_name));
 
958
                status = NT_STATUS_UNSUCCESSFUL;
 
959
                goto done;
 
960
        }
 
961
 
 
962
        /* Allocate initial memory for groupmap and accountmap arrays */
 
963
        r->groupmap = TALLOC_ZERO_ARRAY(mem_ctx, GROUPMAP, 8);
 
964
        r->accountmap = TALLOC_ZERO_ARRAY(mem_ctx, ACCOUNTMAP, 8);
 
965
        if (r->groupmap == NULL || r->accountmap == NULL) {
 
966
                DEBUG(1,("GROUPMAP talloc failed\n"));
 
967
                status = NT_STATUS_NO_MEMORY;
 
968
                goto done;
 
969
        }
 
970
 
 
971
        /* Remember how many we malloced */
 
972
        r->num_alloced = 8;
 
973
 
 
974
        /* Initial database population */
 
975
        if (database_id == SAM_DATABASE_DOMAIN) {
 
976
 
 
977
                status = populate_ldap_for_ldif(domain_sid_str,
 
978
                                                r->suffix,
 
979
                                                builtin_sid,
 
980
                                                r->add_file);
 
981
                if (!NT_STATUS_IS_OK(status)) {
 
982
                        goto done;
 
983
                }
 
984
 
 
985
                status = map_populate_groups(mem_ctx,
 
986
                                             r->groupmap,
 
987
                                             r->accountmap,
 
988
                                             domain_sid_str,
 
989
                                             r->suffix,
 
990
                                             builtin_sid);
 
991
                if (!NT_STATUS_IS_OK(status)) {
 
992
                        goto done;
 
993
                }
 
994
        }
 
995
 
 
996
        r->initialized = true;
 
997
 
 
998
        *ctx = r;
 
999
 
 
1000
        return NT_STATUS_OK;
 
1001
 done:
 
1002
        TALLOC_FREE(r);
 
1003
        return status;
 
1004
}
 
1005
 
 
1006
/****************************************************************
 
1007
****************************************************************/
 
1008
 
 
1009
static void ldif_free_context(struct samsync_ldif_context *r)
 
1010
{
 
1011
        if (!r) {
 
1012
                return;
 
1013
        }
 
1014
 
 
1015
        /* Close and delete the ldif files */
 
1016
        if (r->add_file) {
 
1017
                fclose(r->add_file);
 
1018
        }
 
1019
 
 
1020
        if ((r->add_name != NULL) &&
 
1021
            strcmp(r->add_name, r->add_template) && (unlink(r->add_name))) {
 
1022
                DEBUG(1,("unlink(%s) failed, error was (%s)\n",
 
1023
                         r->add_name, strerror(errno)));
 
1024
        }
 
1025
 
 
1026
        if (r->mod_file) {
 
1027
                fclose(r->mod_file);
 
1028
        }
 
1029
 
 
1030
        if ((r->mod_name != NULL) &&
 
1031
            strcmp(r->mod_name, r->mod_template) && (unlink(r->mod_name))) {
 
1032
                DEBUG(1,("unlink(%s) failed, error was (%s)\n",
 
1033
                         r->mod_name, strerror(errno)));
 
1034
        }
 
1035
 
 
1036
        if (r->ldif_file && (r->ldif_file != stdout)) {
 
1037
                fclose(r->ldif_file);
 
1038
        }
 
1039
 
 
1040
        TALLOC_FREE(r);
 
1041
}
 
1042
 
 
1043
/****************************************************************
 
1044
****************************************************************/
 
1045
 
 
1046
static void ldif_write_output(enum netr_SamDatabaseID database_id,
 
1047
                              struct samsync_ldif_context *l)
 
1048
{
 
1049
        /* Write ldif data to the user's file */
 
1050
        if (database_id == SAM_DATABASE_DOMAIN) {
 
1051
                fprintf(l->ldif_file,
 
1052
                        "# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
 
1053
                fprintf(l->ldif_file,
 
1054
                        "# =================================\n\n");
 
1055
                fflush(l->ldif_file);
 
1056
        } else if (database_id == SAM_DATABASE_BUILTIN) {
 
1057
                fprintf(l->ldif_file,
 
1058
                        "# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
 
1059
                fprintf(l->ldif_file,
 
1060
                        "# ==================================\n\n");
 
1061
                fflush(l->ldif_file);
 
1062
        }
 
1063
        fseek(l->add_file, 0, SEEK_SET);
 
1064
        transfer_file(fileno(l->add_file), fileno(l->ldif_file), (size_t) -1);
 
1065
 
 
1066
        if (database_id == SAM_DATABASE_DOMAIN) {
 
1067
                fprintf(l->ldif_file,
 
1068
                        "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
 
1069
                fprintf(l->ldif_file,
 
1070
                        "# ====================================\n\n");
 
1071
                fflush(l->ldif_file);
 
1072
        } else if (database_id == SAM_DATABASE_BUILTIN) {
 
1073
                fprintf(l->ldif_file,
 
1074
                        "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
 
1075
                fprintf(l->ldif_file,
 
1076
                        "# =====================================\n\n");
 
1077
                fflush(l->ldif_file);
 
1078
        }
 
1079
        fseek(l->mod_file, 0, SEEK_SET);
 
1080
        transfer_file(fileno(l->mod_file), fileno(l->ldif_file), (size_t) -1);
 
1081
}
 
1082
 
 
1083
/****************************************************************
 
1084
****************************************************************/
 
1085
 
 
1086
static NTSTATUS fetch_sam_entry_ldif(TALLOC_CTX *mem_ctx,
 
1087
                                     enum netr_SamDatabaseID database_id,
 
1088
                                     struct netr_DELTA_ENUM *r,
 
1089
                                     struct samsync_context *ctx,
 
1090
                                     uint32_t *a_index_p,
 
1091
                                     uint32_t *g_index_p)
 
1092
{
 
1093
        union netr_DELTA_UNION u = r->delta_union;
 
1094
        union netr_DELTA_ID_UNION id = r->delta_id_union;
 
1095
        struct samsync_ldif_context *l =
 
1096
                talloc_get_type_abort(ctx->private_data, struct samsync_ldif_context);
 
1097
 
 
1098
        switch (r->delta_type) {
 
1099
                case NETR_DELTA_DOMAIN:
 
1100
                        break;
 
1101
 
 
1102
                case NETR_DELTA_GROUP:
 
1103
                        fetch_group_info_to_ldif(mem_ctx,
 
1104
                                                 u.group,
 
1105
                                                 &l->groupmap[*g_index_p],
 
1106
                                                 l->add_file,
 
1107
                                                 ctx->domain_sid_str,
 
1108
                                                 l->suffix);
 
1109
                        (*g_index_p)++;
 
1110
                        break;
 
1111
 
 
1112
                case NETR_DELTA_USER:
 
1113
                        fetch_account_info_to_ldif(mem_ctx,
 
1114
                                                   u.user,
 
1115
                                                   l->groupmap,
 
1116
                                                   &l->accountmap[*a_index_p],
 
1117
                                                   l->add_file,
 
1118
                                                   ctx->domain_sid_str,
 
1119
                                                   l->suffix,
 
1120
                                                   l->num_alloced);
 
1121
                        (*a_index_p)++;
 
1122
                        break;
 
1123
 
 
1124
                case NETR_DELTA_ALIAS:
 
1125
                        fetch_alias_info_to_ldif(mem_ctx,
 
1126
                                                 u.alias,
 
1127
                                                 &l->groupmap[*g_index_p],
 
1128
                                                 l->add_file,
 
1129
                                                 ctx->domain_sid_str,
 
1130
                                                 l->suffix,
 
1131
                                                 database_id);
 
1132
                        (*g_index_p)++;
 
1133
                        break;
 
1134
 
 
1135
                case NETR_DELTA_GROUP_MEMBER:
 
1136
                        fetch_groupmem_info_to_ldif(u.group_member,
 
1137
                                                    id.rid,
 
1138
                                                    l->groupmap,
 
1139
                                                    l->accountmap,
 
1140
                                                    l->mod_file,
 
1141
                                                    l->num_alloced);
 
1142
                        break;
 
1143
 
 
1144
                case NETR_DELTA_ALIAS_MEMBER:
 
1145
                case NETR_DELTA_POLICY:
 
1146
                case NETR_DELTA_ACCOUNT:
 
1147
                case NETR_DELTA_TRUSTED_DOMAIN:
 
1148
                case NETR_DELTA_SECRET:
 
1149
                case NETR_DELTA_RENAME_GROUP:
 
1150
                case NETR_DELTA_RENAME_USER:
 
1151
                case NETR_DELTA_RENAME_ALIAS:
 
1152
                case NETR_DELTA_DELETE_GROUP:
 
1153
                case NETR_DELTA_DELETE_USER:
 
1154
                case NETR_DELTA_MODIFY_COUNT:
 
1155
                default:
 
1156
                        break;
 
1157
        } /* end of switch */
 
1158
 
 
1159
        return NT_STATUS_OK;
 
1160
}
 
1161
 
 
1162
/****************************************************************
 
1163
****************************************************************/
 
1164
 
 
1165
static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx,
 
1166
                                  struct samsync_ldif_context *l,
 
1167
                                  uint32_t num_entries)
 
1168
{
 
1169
        /* Re-allocate memory for groupmap and accountmap arrays */
 
1170
        l->groupmap = TALLOC_REALLOC_ARRAY(mem_ctx,
 
1171
                                           l->groupmap,
 
1172
                                           GROUPMAP,
 
1173
                                           num_entries + l->num_alloced);
 
1174
 
 
1175
        l->accountmap = TALLOC_REALLOC_ARRAY(mem_ctx,
 
1176
                                             l->accountmap,
 
1177
                                             ACCOUNTMAP,
 
1178
                                             num_entries + l->num_alloced);
 
1179
 
 
1180
        if (l->groupmap == NULL || l->accountmap == NULL) {
 
1181
                DEBUG(1,("GROUPMAP talloc failed\n"));
 
1182
                return NT_STATUS_NO_MEMORY;
 
1183
        }
 
1184
 
 
1185
        /* Initialize the new records */
 
1186
        memset(&(l->groupmap[l->num_alloced]), 0,
 
1187
               sizeof(GROUPMAP) * num_entries);
 
1188
        memset(&(l->accountmap[l->num_alloced]), 0,
 
1189
               sizeof(ACCOUNTMAP) * num_entries);
 
1190
 
 
1191
        /* Remember how many we alloced this time */
 
1192
        l->num_alloced += num_entries;
 
1193
 
 
1194
        return NT_STATUS_OK;
 
1195
}
 
1196
 
 
1197
/****************************************************************
 
1198
****************************************************************/
 
1199
 
 
1200
static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
 
1201
                          struct samsync_context *ctx,
 
1202
                          enum netr_SamDatabaseID database_id,
 
1203
                          uint64_t *sequence_num)
 
1204
{
 
1205
        NTSTATUS status;
 
1206
        struct samsync_ldif_context *ldif_ctx =
 
1207
                (struct samsync_ldif_context *)ctx->private_data;
 
1208
 
 
1209
        status = ldif_init_context(mem_ctx,
 
1210
                                   database_id,
 
1211
                                   ctx->output_filename,
 
1212
                                   ctx->domain_sid_str,
 
1213
                                   &ldif_ctx);
 
1214
        if (!NT_STATUS_IS_OK(status)) {
 
1215
                return status;
 
1216
        }
 
1217
 
 
1218
        ctx->private_data = ldif_ctx;
 
1219
 
 
1220
        return NT_STATUS_OK;
 
1221
}
 
1222
 
 
1223
/****************************************************************
 
1224
****************************************************************/
 
1225
 
 
1226
static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
 
1227
                                       enum netr_SamDatabaseID database_id,
 
1228
                                       struct netr_DELTA_ENUM_ARRAY *r,
 
1229
                                       uint64_t *sequence_num,
 
1230
                                       struct samsync_context *ctx)
 
1231
{
 
1232
        NTSTATUS status;
 
1233
        int i;
 
1234
        struct samsync_ldif_context *ldif_ctx =
 
1235
                (struct samsync_ldif_context *)ctx->private_data;
 
1236
 
 
1237
        status = ldif_realloc_maps(mem_ctx, ldif_ctx, r->num_deltas);
 
1238
        if (!NT_STATUS_IS_OK(status)) {
 
1239
                goto failed;
 
1240
        }
 
1241
 
 
1242
        for (i = 0; i < r->num_deltas; i++) {
 
1243
                status = fetch_sam_entry_ldif(mem_ctx, database_id,
 
1244
                                              &r->delta_enum[i], ctx,
 
1245
                                              &a_index, &g_index);
 
1246
                if (!NT_STATUS_IS_OK(status)) {
 
1247
                        goto failed;
 
1248
                }
 
1249
        }
 
1250
 
 
1251
        return NT_STATUS_OK;
 
1252
 
 
1253
 failed:
 
1254
        ldif_free_context(ldif_ctx);
 
1255
        ctx->private_data = NULL;
 
1256
 
 
1257
        return status;
 
1258
}
 
1259
 
 
1260
/****************************************************************
 
1261
****************************************************************/
 
1262
 
 
1263
static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
 
1264
                           struct samsync_context *ctx,
 
1265
                           enum netr_SamDatabaseID database_id,
 
1266
                           uint64_t sequence_num)
 
1267
{
 
1268
        struct samsync_ldif_context *ldif_ctx =
 
1269
                (struct samsync_ldif_context *)ctx->private_data;
 
1270
 
 
1271
        /* This was the last query */
 
1272
        ldif_write_output(database_id, ldif_ctx);
 
1273
        if (ldif_ctx->ldif_file != stdout) {
 
1274
                ctx->result_message = talloc_asprintf(ctx,
 
1275
                        "Vampired %d accounts and %d groups to %s",
 
1276
                        a_index, g_index, ctx->output_filename);
 
1277
        }
 
1278
 
 
1279
        ldif_free_context(ldif_ctx);
 
1280
        ctx->private_data = NULL;
 
1281
 
 
1282
        return NT_STATUS_OK;
 
1283
}
 
1284
 
 
1285
#else /* HAVE_LDAP */
 
1286
 
 
1287
static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
 
1288
                          struct samsync_context *ctx,
 
1289
                          enum netr_SamDatabaseID database_id,
 
1290
                          uint64_t *sequence_num)
 
1291
{
 
1292
        return NT_STATUS_NOT_SUPPORTED;
 
1293
}
 
1294
 
 
1295
static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
 
1296
                                       enum netr_SamDatabaseID database_id,
 
1297
                                       struct netr_DELTA_ENUM_ARRAY *r,
 
1298
                                       uint64_t *sequence_num,
 
1299
                                       struct samsync_context *ctx)
 
1300
{
 
1301
        return NT_STATUS_NOT_SUPPORTED;
 
1302
}
 
1303
 
 
1304
static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
 
1305
                           struct samsync_context *ctx,
 
1306
                           enum netr_SamDatabaseID database_id,
 
1307
                           uint64_t sequence_num)
 
1308
{
 
1309
        return NT_STATUS_NOT_SUPPORTED;
 
1310
}
 
1311
 
 
1312
#endif
 
1313
 
 
1314
const struct samsync_ops libnet_samsync_ldif_ops = {
 
1315
        .startup                = init_ldif,
 
1316
        .process_objects        = fetch_sam_entries_ldif,
 
1317
        .finish                 = close_ldif,
 
1318
};