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