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