net: use netapi for NetFileClose.
[Samba/bb.git] / source / libnet / libnet_samsync_ldif.c
blobcbae22aad3941c9ad5bd78ee075da0999506085c
1 /*
2 Unix SMB/CIFS implementation.
3 dump the remote SAM using rpc samsync operations
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.
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.
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.
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/>.
26 #include "includes.h"
27 #include "libnet/libnet_samsync.h"
29 #ifdef HAVE_LDAP
31 /* uid's and gid's for writing deltas to ldif */
32 static uint32 ldif_gid = 999;
33 static uint32 ldif_uid = 999;
35 /* Structure for mapping accounts to groups */
36 /* Array element is the group rid */
37 typedef struct _groupmap {
38 uint32_t rid;
39 uint32_t gidNumber;
40 const char *sambaSID;
41 const char *group_dn;
42 } GROUPMAP;
44 typedef struct _accountmap {
45 uint32_t rid;
46 const char *cn;
47 } ACCOUNTMAP;
49 struct samsync_ldif_context {
50 GROUPMAP *groupmap;
51 ACCOUNTMAP *accountmap;
52 bool initialized;
53 const char *add_template;
54 const char *mod_template;
55 char *add_name;
56 char *mod_name;
57 FILE *add_file;
58 FILE *mod_file;
59 FILE *ldif_file;
60 const char *suffix;
61 int num_alloced;
64 /****************************************************************
65 ****************************************************************/
67 static NTSTATUS populate_ldap_for_ldif(const char *sid,
68 const char *suffix,
69 const char *builtin_sid,
70 FILE *add_fd)
72 const char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix;
73 char *user_attr=NULL, *group_attr=NULL;
74 char *suffix_attr;
75 int len;
77 /* Get the suffix attribute */
78 suffix_attr = sstring_sub(suffix, '=', ',');
79 if (suffix_attr == NULL) {
80 len = strlen(suffix);
81 suffix_attr = (char*)SMB_MALLOC(len+1);
82 memcpy(suffix_attr, suffix, len);
83 suffix_attr[len] = '\0';
86 /* Write the base */
87 fprintf(add_fd, "# %s\n", suffix);
88 fprintf(add_fd, "dn: %s\n", suffix);
89 fprintf(add_fd, "objectClass: dcObject\n");
90 fprintf(add_fd, "objectClass: organization\n");
91 fprintf(add_fd, "o: %s\n", suffix_attr);
92 fprintf(add_fd, "dc: %s\n", suffix_attr);
93 fprintf(add_fd, "\n");
94 fflush(add_fd);
96 user_suffix = lp_ldap_user_suffix();
97 if (user_suffix == NULL) {
98 SAFE_FREE(suffix_attr);
99 return NT_STATUS_NO_MEMORY;
101 /* If it exists and is distinct from other containers,
102 Write the Users entity */
103 if (*user_suffix && strcmp(user_suffix, suffix)) {
104 user_attr = sstring_sub(lp_ldap_user_suffix(), '=', ',');
105 fprintf(add_fd, "# %s\n", user_suffix);
106 fprintf(add_fd, "dn: %s\n", user_suffix);
107 fprintf(add_fd, "objectClass: organizationalUnit\n");
108 fprintf(add_fd, "ou: %s\n", user_attr);
109 fprintf(add_fd, "\n");
110 fflush(add_fd);
114 group_suffix = lp_ldap_group_suffix();
115 if (group_suffix == NULL) {
116 SAFE_FREE(suffix_attr);
117 SAFE_FREE(user_attr);
118 return NT_STATUS_NO_MEMORY;
120 /* If it exists and is distinct from other containers,
121 Write the Groups entity */
122 if (*group_suffix && strcmp(group_suffix, suffix)) {
123 group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
124 fprintf(add_fd, "# %s\n", group_suffix);
125 fprintf(add_fd, "dn: %s\n", group_suffix);
126 fprintf(add_fd, "objectClass: organizationalUnit\n");
127 fprintf(add_fd, "ou: %s\n", group_attr);
128 fprintf(add_fd, "\n");
129 fflush(add_fd);
132 /* If it exists and is distinct from other containers,
133 Write the Computers entity */
134 machine_suffix = lp_ldap_machine_suffix();
135 if (machine_suffix == NULL) {
136 SAFE_FREE(suffix_attr);
137 SAFE_FREE(user_attr);
138 SAFE_FREE(group_attr);
139 return NT_STATUS_NO_MEMORY;
141 if (*machine_suffix && strcmp(machine_suffix, user_suffix) &&
142 strcmp(machine_suffix, suffix)) {
143 char *machine_ou = NULL;
144 fprintf(add_fd, "# %s\n", machine_suffix);
145 fprintf(add_fd, "dn: %s\n", machine_suffix);
146 fprintf(add_fd, "objectClass: organizationalUnit\n");
147 /* this isn't totally correct as it assumes that
148 there _must_ be an ou. just fixing memleak now. jmcd */
149 machine_ou = sstring_sub(lp_ldap_machine_suffix(), '=', ',');
150 fprintf(add_fd, "ou: %s\n", machine_ou);
151 SAFE_FREE(machine_ou);
152 fprintf(add_fd, "\n");
153 fflush(add_fd);
156 /* If it exists and is distinct from other containers,
157 Write the IdMap entity */
158 idmap_suffix = lp_ldap_idmap_suffix();
159 if (idmap_suffix == NULL) {
160 SAFE_FREE(suffix_attr);
161 SAFE_FREE(user_attr);
162 SAFE_FREE(group_attr);
163 return NT_STATUS_NO_MEMORY;
165 if (*idmap_suffix &&
166 strcmp(idmap_suffix, user_suffix) &&
167 strcmp(idmap_suffix, suffix)) {
168 char *s;
169 fprintf(add_fd, "# %s\n", idmap_suffix);
170 fprintf(add_fd, "dn: %s\n", idmap_suffix);
171 fprintf(add_fd, "ObjectClass: organizationalUnit\n");
172 s = sstring_sub(lp_ldap_idmap_suffix(), '=', ',');
173 fprintf(add_fd, "ou: %s\n", s);
174 SAFE_FREE(s);
175 fprintf(add_fd, "\n");
176 fflush(add_fd);
179 /* Write the domain entity */
180 fprintf(add_fd, "# %s, %s\n", lp_workgroup(), suffix);
181 fprintf(add_fd, "dn: sambaDomainName=%s,%s\n", lp_workgroup(),
182 suffix);
183 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_DOMINFO);
184 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_IDPOOL);
185 fprintf(add_fd, "sambaDomainName: %s\n", lp_workgroup());
186 fprintf(add_fd, "sambaSID: %s\n", sid);
187 fprintf(add_fd, "uidNumber: %d\n", ++ldif_uid);
188 fprintf(add_fd, "gidNumber: %d\n", ++ldif_gid);
189 fprintf(add_fd, "\n");
190 fflush(add_fd);
192 /* Write the Domain Admins entity */
193 fprintf(add_fd, "# Domain Admins, %s, %s\n", group_attr,
194 suffix);
195 fprintf(add_fd, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr,
196 suffix);
197 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
198 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
199 fprintf(add_fd, "cn: Domain Admins\n");
200 fprintf(add_fd, "memberUid: Administrator\n");
201 fprintf(add_fd, "description: Netbios Domain Administrators\n");
202 fprintf(add_fd, "gidNumber: 512\n");
203 fprintf(add_fd, "sambaSID: %s-512\n", sid);
204 fprintf(add_fd, "sambaGroupType: 2\n");
205 fprintf(add_fd, "displayName: Domain Admins\n");
206 fprintf(add_fd, "\n");
207 fflush(add_fd);
209 /* Write the Domain Users entity */
210 fprintf(add_fd, "# Domain Users, %s, %s\n", group_attr,
211 suffix);
212 fprintf(add_fd, "dn: cn=Domain Users,ou=%s,%s\n", group_attr,
213 suffix);
214 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
215 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
216 fprintf(add_fd, "cn: Domain Users\n");
217 fprintf(add_fd, "description: Netbios Domain Users\n");
218 fprintf(add_fd, "gidNumber: 513\n");
219 fprintf(add_fd, "sambaSID: %s-513\n", sid);
220 fprintf(add_fd, "sambaGroupType: 2\n");
221 fprintf(add_fd, "displayName: Domain Users\n");
222 fprintf(add_fd, "\n");
223 fflush(add_fd);
225 /* Write the Domain Guests entity */
226 fprintf(add_fd, "# Domain Guests, %s, %s\n", group_attr,
227 suffix);
228 fprintf(add_fd, "dn: cn=Domain Guests,ou=%s,%s\n", group_attr,
229 suffix);
230 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
231 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
232 fprintf(add_fd, "cn: Domain Guests\n");
233 fprintf(add_fd, "description: Netbios Domain Guests\n");
234 fprintf(add_fd, "gidNumber: 514\n");
235 fprintf(add_fd, "sambaSID: %s-514\n", sid);
236 fprintf(add_fd, "sambaGroupType: 2\n");
237 fprintf(add_fd, "displayName: Domain Guests\n");
238 fprintf(add_fd, "\n");
239 fflush(add_fd);
241 /* Write the Domain Computers entity */
242 fprintf(add_fd, "# Domain Computers, %s, %s\n", group_attr,
243 suffix);
244 fprintf(add_fd, "dn: cn=Domain Computers,ou=%s,%s\n",
245 group_attr, suffix);
246 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
247 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
248 fprintf(add_fd, "gidNumber: 515\n");
249 fprintf(add_fd, "cn: Domain Computers\n");
250 fprintf(add_fd, "description: Netbios Domain Computers accounts\n");
251 fprintf(add_fd, "sambaSID: %s-515\n", sid);
252 fprintf(add_fd, "sambaGroupType: 2\n");
253 fprintf(add_fd, "displayName: Domain Computers\n");
254 fprintf(add_fd, "\n");
255 fflush(add_fd);
257 /* Write the Admininistrators Groups entity */
258 fprintf(add_fd, "# Administrators, %s, %s\n", group_attr,
259 suffix);
260 fprintf(add_fd, "dn: cn=Administrators,ou=%s,%s\n", group_attr,
261 suffix);
262 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
263 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
264 fprintf(add_fd, "gidNumber: 544\n");
265 fprintf(add_fd, "cn: Administrators\n");
266 fprintf(add_fd, "description: Netbios Domain Members can fully administer the computer/sambaDomainName\n");
267 fprintf(add_fd, "sambaSID: %s-544\n", builtin_sid);
268 fprintf(add_fd, "sambaGroupType: 5\n");
269 fprintf(add_fd, "displayName: Administrators\n");
270 fprintf(add_fd, "\n");
272 /* Write the Print Operator entity */
273 fprintf(add_fd, "# Print Operators, %s, %s\n", group_attr,
274 suffix);
275 fprintf(add_fd, "dn: cn=Print Operators,ou=%s,%s\n",
276 group_attr, suffix);
277 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
278 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
279 fprintf(add_fd, "gidNumber: 550\n");
280 fprintf(add_fd, "cn: Print Operators\n");
281 fprintf(add_fd, "description: Netbios Domain Print Operators\n");
282 fprintf(add_fd, "sambaSID: %s-550\n", builtin_sid);
283 fprintf(add_fd, "sambaGroupType: 5\n");
284 fprintf(add_fd, "displayName: Print Operators\n");
285 fprintf(add_fd, "\n");
286 fflush(add_fd);
288 /* Write the Backup Operators entity */
289 fprintf(add_fd, "# Backup Operators, %s, %s\n", group_attr,
290 suffix);
291 fprintf(add_fd, "dn: cn=Backup Operators,ou=%s,%s\n",
292 group_attr, suffix);
293 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
294 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
295 fprintf(add_fd, "gidNumber: 551\n");
296 fprintf(add_fd, "cn: Backup Operators\n");
297 fprintf(add_fd, "description: Netbios Domain Members can bypass file security to back up files\n");
298 fprintf(add_fd, "sambaSID: %s-551\n", builtin_sid);
299 fprintf(add_fd, "sambaGroupType: 5\n");
300 fprintf(add_fd, "displayName: Backup Operators\n");
301 fprintf(add_fd, "\n");
302 fflush(add_fd);
304 /* Write the Replicators entity */
305 fprintf(add_fd, "# Replicators, %s, %s\n", group_attr, suffix);
306 fprintf(add_fd, "dn: cn=Replicators,ou=%s,%s\n", group_attr,
307 suffix);
308 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
309 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
310 fprintf(add_fd, "gidNumber: 552\n");
311 fprintf(add_fd, "cn: Replicators\n");
312 fprintf(add_fd, "description: Netbios Domain Supports file replication in a sambaDomainName\n");
313 fprintf(add_fd, "sambaSID: %s-552\n", builtin_sid);
314 fprintf(add_fd, "sambaGroupType: 5\n");
315 fprintf(add_fd, "displayName: Replicators\n");
316 fprintf(add_fd, "\n");
317 fflush(add_fd);
319 /* Deallocate memory, and return */
320 SAFE_FREE(suffix_attr);
321 SAFE_FREE(user_attr);
322 SAFE_FREE(group_attr);
323 return NT_STATUS_OK;
326 /****************************************************************
327 ****************************************************************/
329 static NTSTATUS map_populate_groups(TALLOC_CTX *mem_ctx,
330 GROUPMAP *groupmap,
331 ACCOUNTMAP *accountmap,
332 const char *sid,
333 const char *suffix,
334 const char *builtin_sid)
336 char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
338 /* Map the groups created by populate_ldap_for_ldif */
339 groupmap[0].rid = 512;
340 groupmap[0].gidNumber = 512;
341 groupmap[0].sambaSID = talloc_asprintf(mem_ctx, "%s-512", sid);
342 groupmap[0].group_dn = talloc_asprintf(mem_ctx,
343 "cn=Domain Admins,ou=%s,%s", group_attr, suffix);
344 NT_STATUS_HAVE_NO_MEMORY(groupmap[0].sambaSID);
345 NT_STATUS_HAVE_NO_MEMORY(groupmap[0].group_dn);
347 accountmap[0].rid = 512;
348 accountmap[0].cn = talloc_strdup(mem_ctx, "Domain Admins");
349 NT_STATUS_HAVE_NO_MEMORY(accountmap[0].cn);
351 groupmap[1].rid = 513;
352 groupmap[1].gidNumber = 513;
353 groupmap[1].sambaSID = talloc_asprintf(mem_ctx, "%s-513", sid);
354 groupmap[1].group_dn = talloc_asprintf(mem_ctx,
355 "cn=Domain Users,ou=%s,%s", group_attr, suffix);
356 NT_STATUS_HAVE_NO_MEMORY(groupmap[1].sambaSID);
357 NT_STATUS_HAVE_NO_MEMORY(groupmap[1].group_dn);
359 accountmap[1].rid = 513;
360 accountmap[1].cn = talloc_strdup(mem_ctx, "Domain Users");
361 NT_STATUS_HAVE_NO_MEMORY(accountmap[1].cn);
363 groupmap[2].rid = 514;
364 groupmap[2].gidNumber = 514;
365 groupmap[2].sambaSID = talloc_asprintf(mem_ctx, "%s-514", sid);
366 groupmap[2].group_dn = talloc_asprintf(mem_ctx,
367 "cn=Domain Guests,ou=%s,%s", group_attr, suffix);
368 NT_STATUS_HAVE_NO_MEMORY(groupmap[2].sambaSID);
369 NT_STATUS_HAVE_NO_MEMORY(groupmap[2].group_dn);
371 accountmap[2].rid = 514;
372 accountmap[2].cn = talloc_strdup(mem_ctx, "Domain Guests");
373 NT_STATUS_HAVE_NO_MEMORY(accountmap[2].cn);
375 groupmap[3].rid = 515;
376 groupmap[3].gidNumber = 515;
377 groupmap[3].sambaSID = talloc_asprintf(mem_ctx, "%s-515", sid);
378 groupmap[3].group_dn = talloc_asprintf(mem_ctx,
379 "cn=Domain Computers,ou=%s,%s", group_attr, suffix);
380 NT_STATUS_HAVE_NO_MEMORY(groupmap[3].sambaSID);
381 NT_STATUS_HAVE_NO_MEMORY(groupmap[3].group_dn);
383 accountmap[3].rid = 515;
384 accountmap[3].cn = talloc_strdup(mem_ctx, "Domain Computers");
385 NT_STATUS_HAVE_NO_MEMORY(accountmap[3].cn);
387 groupmap[4].rid = 544;
388 groupmap[4].gidNumber = 544;
389 groupmap[4].sambaSID = talloc_asprintf(mem_ctx, "%s-544", builtin_sid);
390 groupmap[4].group_dn = talloc_asprintf(mem_ctx,
391 "cn=Administrators,ou=%s,%s", group_attr, suffix);
392 NT_STATUS_HAVE_NO_MEMORY(groupmap[4].sambaSID);
393 NT_STATUS_HAVE_NO_MEMORY(groupmap[4].group_dn);
395 accountmap[4].rid = 515;
396 accountmap[4].cn = talloc_strdup(mem_ctx, "Administrators");
397 NT_STATUS_HAVE_NO_MEMORY(accountmap[4].cn);
399 groupmap[5].rid = 550;
400 groupmap[5].gidNumber = 550;
401 groupmap[5].sambaSID = talloc_asprintf(mem_ctx, "%s-550", builtin_sid);
402 groupmap[5].group_dn = talloc_asprintf(mem_ctx,
403 "cn=Print Operators,ou=%s,%s", group_attr, suffix);
404 NT_STATUS_HAVE_NO_MEMORY(groupmap[5].sambaSID);
405 NT_STATUS_HAVE_NO_MEMORY(groupmap[5].group_dn);
407 accountmap[5].rid = 550;
408 accountmap[5].cn = talloc_strdup(mem_ctx, "Print Operators");
409 NT_STATUS_HAVE_NO_MEMORY(accountmap[5].cn);
411 groupmap[6].rid = 551;
412 groupmap[6].gidNumber = 551;
413 groupmap[6].sambaSID = talloc_asprintf(mem_ctx, "%s-551", builtin_sid);
414 groupmap[6].group_dn = talloc_asprintf(mem_ctx,
415 "cn=Backup Operators,ou=%s,%s", group_attr, suffix);
416 NT_STATUS_HAVE_NO_MEMORY(groupmap[6].sambaSID);
417 NT_STATUS_HAVE_NO_MEMORY(groupmap[6].group_dn);
419 accountmap[6].rid = 551;
420 accountmap[6].cn = talloc_strdup(mem_ctx, "Backup Operators");
421 NT_STATUS_HAVE_NO_MEMORY(accountmap[6].cn);
423 groupmap[7].rid = 552;
424 groupmap[7].gidNumber = 552;
425 groupmap[7].sambaSID = talloc_asprintf(mem_ctx, "%s-552", builtin_sid);
426 groupmap[7].group_dn = talloc_asprintf(mem_ctx,
427 "cn=Replicators,ou=%s,%s", group_attr, suffix);
428 NT_STATUS_HAVE_NO_MEMORY(groupmap[7].sambaSID);
429 NT_STATUS_HAVE_NO_MEMORY(groupmap[7].group_dn);
431 accountmap[7].rid = 551;
432 accountmap[7].cn = talloc_strdup(mem_ctx, "Replicators");
433 NT_STATUS_HAVE_NO_MEMORY(accountmap[7].cn);
435 SAFE_FREE(group_attr);
437 return NT_STATUS_OK;
441 * This is a crap routine, but I think it's the quickest way to solve the
442 * UTF8->base64 problem.
445 static int fprintf_attr(FILE *add_fd, const char *attr_name,
446 const char *fmt, ...)
448 va_list ap;
449 char *value, *p, *base64;
450 DATA_BLOB base64_blob;
451 bool do_base64 = false;
452 int res;
454 va_start(ap, fmt);
455 value = talloc_vasprintf(NULL, fmt, ap);
456 va_end(ap);
458 SMB_ASSERT(value != NULL);
460 for (p=value; *p; p++) {
461 if (*p & 0x80) {
462 do_base64 = true;
463 break;
467 if (!do_base64) {
468 bool only_whitespace = true;
469 for (p=value; *p; p++) {
471 * I know that this not multibyte safe, but we break
472 * on the first non-whitespace character anyway.
474 if (!isspace(*p)) {
475 only_whitespace = false;
476 break;
479 if (only_whitespace) {
480 do_base64 = true;
484 if (!do_base64) {
485 res = fprintf(add_fd, "%s: %s\n", attr_name, value);
486 TALLOC_FREE(value);
487 return res;
490 base64_blob.data = (unsigned char *)value;
491 base64_blob.length = strlen(value);
493 base64 = base64_encode_data_blob(value, base64_blob);
494 SMB_ASSERT(base64 != NULL);
496 res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
497 TALLOC_FREE(value);
498 return res;
501 /****************************************************************
502 ****************************************************************/
504 static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx,
505 struct netr_DELTA_GROUP *r,
506 GROUPMAP *groupmap,
507 FILE *add_fd,
508 const char *sid,
509 const char *suffix)
511 const char *groupname = r->group_name.string;
512 uint32 grouptype = 0, g_rid = 0;
513 char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
515 /* Set up the group type (always 2 for group info) */
516 grouptype = 2;
518 /* These groups are entered by populate_ldap_for_ldif */
519 if (strcmp(groupname, "Domain Admins") == 0 ||
520 strcmp(groupname, "Domain Users") == 0 ||
521 strcmp(groupname, "Domain Guests") == 0 ||
522 strcmp(groupname, "Domain Computers") == 0 ||
523 strcmp(groupname, "Administrators") == 0 ||
524 strcmp(groupname, "Print Operators") == 0 ||
525 strcmp(groupname, "Backup Operators") == 0 ||
526 strcmp(groupname, "Replicators") == 0) {
527 SAFE_FREE(group_attr);
528 return NT_STATUS_OK;
529 } else {
530 /* Increment the gid for the new group */
531 ldif_gid++;
534 /* Map the group rid, gid, and dn */
535 g_rid = r->rid;
536 groupmap->rid = g_rid;
537 groupmap->gidNumber = ldif_gid;
538 groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
539 groupmap->group_dn = talloc_asprintf(mem_ctx,
540 "cn=%s,ou=%s,%s", groupname, group_attr, suffix);
541 NT_STATUS_HAVE_NO_MEMORY(groupmap->sambaSID);
542 NT_STATUS_HAVE_NO_MEMORY(groupmap->group_dn);
544 /* Write the data to the temporary add ldif file */
545 fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr,
546 suffix);
547 fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", groupname, group_attr,
548 suffix);
549 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
550 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
551 fprintf_attr(add_fd, "cn", "%s", groupname);
552 fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
553 fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
554 fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
555 fprintf_attr(add_fd, "displayName", "%s", groupname);
556 fprintf(add_fd, "\n");
557 fflush(add_fd);
559 SAFE_FREE(group_attr);
560 /* Return */
561 return NT_STATUS_OK;
564 /****************************************************************
565 ****************************************************************/
567 static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx,
568 struct netr_DELTA_USER *r,
569 GROUPMAP *groupmap,
570 ACCOUNTMAP *accountmap,
571 FILE *add_fd,
572 const char *sid,
573 const char *suffix,
574 int alloced)
576 fstring username, logonscript, homedrive, homepath = "", homedir = "";
577 fstring hex_nt_passwd, hex_lm_passwd;
578 fstring description, profilepath, fullname, sambaSID;
579 uchar lm_passwd[16], nt_passwd[16];
580 char *flags, *user_rdn;
581 const char *ou;
582 const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
583 static uchar zero_buf[16];
584 uint32 rid = 0, group_rid = 0, gidNumber = 0;
585 time_t unix_time;
586 int i;
588 /* Get the username */
589 fstrcpy(username, r->account_name.string);
591 /* Get the rid */
592 rid = r->rid;
594 /* Map the rid and username for group member info later */
595 accountmap->rid = rid;
596 accountmap->cn = talloc_strdup(mem_ctx, username);
597 NT_STATUS_HAVE_NO_MEMORY(accountmap->cn);
599 /* Get the home directory */
600 if (r->acct_flags & ACB_NORMAL) {
601 fstrcpy(homedir, r->home_directory.string);
602 if (!*homedir) {
603 snprintf(homedir, sizeof(homedir), "/home/%s", username);
604 } else {
605 snprintf(homedir, sizeof(homedir), "/nobodyshomedir");
607 ou = lp_ldap_user_suffix();
608 } else {
609 ou = lp_ldap_machine_suffix();
610 snprintf(homedir, sizeof(homedir), "/machinehomedir");
613 /* Get the logon script */
614 fstrcpy(logonscript, r->logon_script.string);
616 /* Get the home drive */
617 fstrcpy(homedrive, r->home_drive.string);
619 /* Get the home path */
620 fstrcpy(homepath, r->home_directory.string);
622 /* Get the description */
623 fstrcpy(description, r->description.string);
625 /* Get the display name */
626 fstrcpy(fullname, r->full_name.string);
628 /* Get the profile path */
629 fstrcpy(profilepath, r->profile_path.string);
631 /* Get lm and nt password data */
632 if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
633 sam_pwd_hash(r->rid, r->lmpassword.hash, lm_passwd, 0);
634 pdb_sethexpwd(hex_lm_passwd, lm_passwd, r->acct_flags);
635 } else {
636 pdb_sethexpwd(hex_lm_passwd, NULL, 0);
638 if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
639 sam_pwd_hash(r->rid, r->ntpassword.hash, nt_passwd, 0);
640 pdb_sethexpwd(hex_nt_passwd, nt_passwd, r->acct_flags);
641 } else {
642 pdb_sethexpwd(hex_nt_passwd, NULL, 0);
644 unix_time = nt_time_to_unix(r->last_password_change);
646 /* Increment the uid for the new user */
647 ldif_uid++;
649 /* Set up group id and sambaSID for the user */
650 group_rid = r->primary_gid;
651 for (i=0; i<alloced; i++) {
652 if (groupmap[i].rid == group_rid) break;
654 if (i == alloced){
655 DEBUG(1, ("Could not find rid %d in groupmap array\n",
656 group_rid));
657 return NT_STATUS_UNSUCCESSFUL;
659 gidNumber = groupmap[i].gidNumber;
660 snprintf(sambaSID, sizeof(sambaSID), groupmap[i].sambaSID);
662 /* Set up sambaAcctFlags */
663 flags = pdb_encode_acct_ctrl(r->acct_flags,
664 NEW_PW_FORMAT_SPACE_PADDED_LEN);
666 /* Add the user to the temporary add ldif file */
667 /* this isn't quite right...we can't assume there's just OU=. jmcd */
668 user_rdn = sstring_sub(ou, '=', ',');
669 fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
670 fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
671 suffix);
672 SAFE_FREE(user_rdn);
673 fprintf(add_fd, "ObjectClass: top\n");
674 fprintf(add_fd, "objectClass: inetOrgPerson\n");
675 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT);
676 fprintf(add_fd, "objectClass: shadowAccount\n");
677 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT);
678 fprintf_attr(add_fd, "cn", "%s", username);
679 fprintf_attr(add_fd, "sn", "%s", username);
680 fprintf_attr(add_fd, "uid", "%s", username);
681 fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
682 fprintf(add_fd, "gidNumber: %d\n", gidNumber);
683 fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
684 if (*homepath)
685 fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
686 if (*homedrive)
687 fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
688 if (*logonscript)
689 fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
690 fprintf(add_fd, "loginShell: %s\n",
691 ((r->acct_flags & ACB_NORMAL) ?
692 "/bin/bash" : "/bin/false"));
693 fprintf(add_fd, "gecos: System User\n");
694 if (*description)
695 fprintf_attr(add_fd, "description", "%s", description);
696 fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
697 fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
698 if(*fullname)
699 fprintf_attr(add_fd, "displayName", "%s", fullname);
700 if(*profilepath)
701 fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
702 if (strcmp(nopasswd, hex_lm_passwd) != 0)
703 fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
704 if (strcmp(nopasswd, hex_nt_passwd) != 0)
705 fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd);
706 fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time);
707 fprintf(add_fd, "sambaAcctFlags: %s\n", flags);
708 fprintf(add_fd, "\n");
709 fflush(add_fd);
711 /* Return */
712 return NT_STATUS_OK;
715 /****************************************************************
716 ****************************************************************/
718 static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx,
719 struct netr_DELTA_ALIAS *r,
720 GROUPMAP *groupmap,
721 FILE *add_fd,
722 const char *sid,
723 const char *suffix,
724 enum netr_SamDatabaseID database_id)
726 fstring aliasname, description;
727 uint32 grouptype = 0, g_rid = 0;
728 char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
730 /* Get the alias name */
731 fstrcpy(aliasname, r->alias_name.string);
733 /* Get the alias description */
734 fstrcpy(description, r->description.string);
736 /* Set up the group type */
737 switch (database_id) {
738 case SAM_DATABASE_DOMAIN:
739 grouptype = 4;
740 break;
741 case SAM_DATABASE_BUILTIN:
742 grouptype = 5;
743 break;
744 default:
745 grouptype = 4;
746 break;
750 These groups are entered by populate_ldap_for_ldif
751 Note that populate creates a group called Relicators,
752 but NT returns a group called Replicator
754 if (strcmp(aliasname, "Domain Admins") == 0 ||
755 strcmp(aliasname, "Domain Users") == 0 ||
756 strcmp(aliasname, "Domain Guests") == 0 ||
757 strcmp(aliasname, "Domain Computers") == 0 ||
758 strcmp(aliasname, "Administrators") == 0 ||
759 strcmp(aliasname, "Print Operators") == 0 ||
760 strcmp(aliasname, "Backup Operators") == 0 ||
761 strcmp(aliasname, "Replicator") == 0) {
762 SAFE_FREE(group_attr);
763 return NT_STATUS_OK;
764 } else {
765 /* Increment the gid for the new group */
766 ldif_gid++;
769 /* Map the group rid and gid */
770 g_rid = r->rid;
771 groupmap->gidNumber = ldif_gid;
772 groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
773 NT_STATUS_HAVE_NO_MEMORY(groupmap->sambaSID);
775 /* Write the data to the temporary add ldif file */
776 fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr,
777 suffix);
778 fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", aliasname, group_attr,
779 suffix);
780 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
781 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
782 fprintf(add_fd, "cn: %s\n", aliasname);
783 fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
784 fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
785 fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
786 fprintf_attr(add_fd, "displayName", "%s", aliasname);
787 if (description[0])
788 fprintf_attr(add_fd, "description", "%s", description);
789 fprintf(add_fd, "\n");
790 fflush(add_fd);
792 SAFE_FREE(group_attr);
793 /* Return */
794 return NT_STATUS_OK;
797 /****************************************************************
798 ****************************************************************/
800 static NTSTATUS fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER *r,
801 uint32_t id_rid,
802 GROUPMAP *groupmap,
803 ACCOUNTMAP *accountmap,
804 FILE *mod_fd, int alloced)
806 fstring group_dn;
807 uint32 group_rid = 0, rid = 0;
808 int i, j, k;
810 /* Get the dn for the group */
811 if (r->num_rids > 0) {
812 group_rid = id_rid;
813 for (j=0; j<alloced; j++) {
814 if (groupmap[j].rid == group_rid) break;
816 if (j == alloced){
817 DEBUG(1, ("Could not find rid %d in groupmap array\n",
818 group_rid));
819 return NT_STATUS_UNSUCCESSFUL;
821 snprintf(group_dn, sizeof(group_dn), "%s", groupmap[j].group_dn);
822 fprintf(mod_fd, "dn: %s\n", group_dn);
824 /* Get the cn for each member */
825 for (i=0; i < r->num_rids; i++) {
826 rid = r->rids[i];
827 for (k=0; k<alloced; k++) {
828 if (accountmap[k].rid == rid) break;
830 if (k == alloced){
831 DEBUG(1, ("Could not find rid %d in "
832 "accountmap array\n", rid));
833 return NT_STATUS_UNSUCCESSFUL;
835 fprintf(mod_fd, "memberUid: %s\n", accountmap[k].cn);
837 fprintf(mod_fd, "\n");
839 fflush(mod_fd);
841 /* Return */
842 return NT_STATUS_OK;
845 /****************************************************************
846 ****************************************************************/
848 static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx,
849 enum netr_SamDatabaseID database_id,
850 const char *ldif_filename,
851 const char *domain_sid_str,
852 struct samsync_ldif_context **ctx)
854 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
855 struct samsync_ldif_context *r;
856 const char *add_template = "/tmp/add.ldif.XXXXXX";
857 const char *mod_template = "/tmp/mod.ldif.XXXXXX";
858 const char *builtin_sid = "S-1-5-32";
860 /* Get other smb.conf data */
861 if (!(lp_workgroup()) || !*(lp_workgroup())) {
862 DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
863 exit(1);
866 /* Get the ldap suffix */
867 if (!(lp_ldap_suffix()) || !*(lp_ldap_suffix())) {
868 DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
869 exit(1);
872 if (*ctx && (*ctx)->initialized) {
873 return NT_STATUS_OK;
876 r = TALLOC_ZERO_P(mem_ctx, struct samsync_ldif_context);
877 NT_STATUS_HAVE_NO_MEMORY(r);
879 /* Get the ldap suffix */
880 r->suffix = lp_ldap_suffix();
882 /* Ensure we have an output file */
883 if (ldif_filename) {
884 r->ldif_file = fopen(ldif_filename, "a");
885 } else {
886 r->ldif_file = stdout;
889 if (!r->ldif_file) {
890 fprintf(stderr, "Could not open %s\n", ldif_filename);
891 DEBUG(1, ("Could not open %s\n", ldif_filename));
892 status = NT_STATUS_UNSUCCESSFUL;
893 goto done;
896 r->add_template = talloc_strdup(mem_ctx, add_template);
897 r->mod_template = talloc_strdup(mem_ctx, mod_template);
898 if (!r->add_template || !r->mod_template) {
899 status = NT_STATUS_NO_MEMORY;
900 goto done;
903 r->add_name = talloc_strdup(mem_ctx, add_template);
904 r->mod_name = talloc_strdup(mem_ctx, mod_template);
905 if (!r->add_name || !r->mod_name) {
906 status = NT_STATUS_NO_MEMORY;
907 goto done;
910 /* Open the add and mod ldif files */
911 if (!(r->add_file = fdopen(smb_mkstemp(r->add_name),"w"))) {
912 DEBUG(1, ("Could not open %s\n", r->add_name));
913 status = NT_STATUS_UNSUCCESSFUL;
914 goto done;
916 if (!(r->mod_file = fdopen(smb_mkstemp(r->mod_name),"w"))) {
917 DEBUG(1, ("Could not open %s\n", r->mod_name));
918 status = NT_STATUS_UNSUCCESSFUL;
919 goto done;
922 /* Allocate initial memory for groupmap and accountmap arrays */
923 r->groupmap = TALLOC_ZERO_ARRAY(mem_ctx, GROUPMAP, 8);
924 r->accountmap = TALLOC_ZERO_ARRAY(mem_ctx, ACCOUNTMAP, 8);
925 if (r->groupmap == NULL || r->accountmap == NULL) {
926 DEBUG(1,("GROUPMAP talloc failed\n"));
927 status = NT_STATUS_NO_MEMORY;
928 goto done;
931 /* Remember how many we malloced */
932 r->num_alloced = 8;
934 /* Initial database population */
935 if (database_id == SAM_DATABASE_DOMAIN) {
937 status = populate_ldap_for_ldif(domain_sid_str,
938 r->suffix,
939 builtin_sid,
940 r->add_file);
941 if (!NT_STATUS_IS_OK(status)) {
942 goto done;
945 status = map_populate_groups(mem_ctx,
946 r->groupmap,
947 r->accountmap,
948 domain_sid_str,
949 r->suffix,
950 builtin_sid);
951 if (!NT_STATUS_IS_OK(status)) {
952 goto done;
956 r->initialized = true;
958 *ctx = r;
960 return NT_STATUS_OK;
961 done:
962 TALLOC_FREE(r);
963 return status;
966 /****************************************************************
967 ****************************************************************/
969 static void ldif_free_context(struct samsync_ldif_context *r)
971 if (!r) {
972 return;
975 /* Close and delete the ldif files */
976 if (r->add_file) {
977 fclose(r->add_file);
980 if ((r->add_name != NULL) &&
981 strcmp(r->add_name, r->add_template) && (unlink(r->add_name))) {
982 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
983 r->add_name, strerror(errno)));
986 if (r->mod_file) {
987 fclose(r->mod_file);
990 if ((r->mod_name != NULL) &&
991 strcmp(r->mod_name, r->mod_template) && (unlink(r->mod_name))) {
992 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
993 r->mod_name, strerror(errno)));
996 if (r->ldif_file && (r->ldif_file != stdout)) {
997 fclose(r->ldif_file);
1000 TALLOC_FREE(r);
1003 /****************************************************************
1004 ****************************************************************/
1006 static void ldif_write_output(enum netr_SamDatabaseID database_id,
1007 struct samsync_ldif_context *l)
1009 /* Write ldif data to the user's file */
1010 if (database_id == SAM_DATABASE_DOMAIN) {
1011 fprintf(l->ldif_file,
1012 "# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
1013 fprintf(l->ldif_file,
1014 "# =================================\n\n");
1015 fflush(l->ldif_file);
1016 } else if (database_id == SAM_DATABASE_BUILTIN) {
1017 fprintf(l->ldif_file,
1018 "# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
1019 fprintf(l->ldif_file,
1020 "# ==================================\n\n");
1021 fflush(l->ldif_file);
1023 fseek(l->add_file, 0, SEEK_SET);
1024 transfer_file(fileno(l->add_file), fileno(l->ldif_file), (size_t) -1);
1026 if (database_id == SAM_DATABASE_DOMAIN) {
1027 fprintf(l->ldif_file,
1028 "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
1029 fprintf(l->ldif_file,
1030 "# ====================================\n\n");
1031 fflush(l->ldif_file);
1032 } else if (database_id == SAM_DATABASE_BUILTIN) {
1033 fprintf(l->ldif_file,
1034 "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
1035 fprintf(l->ldif_file,
1036 "# =====================================\n\n");
1037 fflush(l->ldif_file);
1039 fseek(l->mod_file, 0, SEEK_SET);
1040 transfer_file(fileno(l->mod_file), fileno(l->ldif_file), (size_t) -1);
1043 /****************************************************************
1044 ****************************************************************/
1046 static NTSTATUS fetch_sam_entry_ldif(TALLOC_CTX *mem_ctx,
1047 enum netr_SamDatabaseID database_id,
1048 struct netr_DELTA_ENUM *r,
1049 struct samsync_context *ctx,
1050 uint32_t *a_index,
1051 uint32_t *g_index)
1053 union netr_DELTA_UNION u = r->delta_union;
1054 union netr_DELTA_ID_UNION id = r->delta_id_union;
1055 struct samsync_ldif_context *l =
1056 talloc_get_type_abort(ctx->private_data, struct samsync_ldif_context);
1058 switch (r->delta_type) {
1059 case NETR_DELTA_DOMAIN:
1060 break;
1062 case NETR_DELTA_GROUP:
1063 fetch_group_info_to_ldif(mem_ctx,
1064 u.group,
1065 &l->groupmap[*g_index],
1066 l->add_file,
1067 ctx->domain_sid_str,
1068 l->suffix);
1069 (*g_index)++;
1070 break;
1072 case NETR_DELTA_USER:
1073 fetch_account_info_to_ldif(mem_ctx,
1074 u.user,
1075 l->groupmap,
1076 &l->accountmap[*a_index],
1077 l->add_file,
1078 ctx->domain_sid_str,
1079 l->suffix,
1080 l->num_alloced);
1081 (*a_index)++;
1082 break;
1084 case NETR_DELTA_ALIAS:
1085 fetch_alias_info_to_ldif(mem_ctx,
1086 u.alias,
1087 &l->groupmap[*g_index],
1088 l->add_file,
1089 ctx->domain_sid_str,
1090 l->suffix,
1091 database_id);
1092 (*g_index)++;
1093 break;
1095 case NETR_DELTA_GROUP_MEMBER:
1096 fetch_groupmem_info_to_ldif(u.group_member,
1097 id.rid,
1098 l->groupmap,
1099 l->accountmap,
1100 l->mod_file,
1101 l->num_alloced);
1102 break;
1104 case NETR_DELTA_ALIAS_MEMBER:
1105 case NETR_DELTA_POLICY:
1106 case NETR_DELTA_ACCOUNT:
1107 case NETR_DELTA_TRUSTED_DOMAIN:
1108 case NETR_DELTA_SECRET:
1109 case NETR_DELTA_RENAME_GROUP:
1110 case NETR_DELTA_RENAME_USER:
1111 case NETR_DELTA_RENAME_ALIAS:
1112 case NETR_DELTA_DELETE_GROUP:
1113 case NETR_DELTA_DELETE_USER:
1114 case NETR_DELTA_MODIFY_COUNT:
1115 default:
1116 break;
1117 } /* end of switch */
1119 return NT_STATUS_OK;
1122 /****************************************************************
1123 ****************************************************************/
1125 static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx,
1126 struct samsync_ldif_context *l,
1127 uint32_t num_entries)
1129 /* Re-allocate memory for groupmap and accountmap arrays */
1130 l->groupmap = TALLOC_REALLOC_ARRAY(mem_ctx,
1131 l->groupmap,
1132 GROUPMAP,
1133 num_entries + l->num_alloced);
1135 l->accountmap = TALLOC_REALLOC_ARRAY(mem_ctx,
1136 l->accountmap,
1137 ACCOUNTMAP,
1138 num_entries + l->num_alloced);
1140 if (l->groupmap == NULL || l->accountmap == NULL) {
1141 DEBUG(1,("GROUPMAP talloc failed\n"));
1142 return NT_STATUS_NO_MEMORY;
1145 /* Initialize the new records */
1146 memset(&(l->groupmap[l->num_alloced]), 0,
1147 sizeof(GROUPMAP) * num_entries);
1148 memset(&(l->accountmap[l->num_alloced]), 0,
1149 sizeof(ACCOUNTMAP) * num_entries);
1151 /* Remember how many we alloced this time */
1152 l->num_alloced += num_entries;
1154 return NT_STATUS_OK;
1157 /****************************************************************
1158 ****************************************************************/
1160 NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
1161 enum netr_SamDatabaseID database_id,
1162 struct netr_DELTA_ENUM_ARRAY *r,
1163 bool last_query,
1164 struct samsync_context *ctx)
1166 NTSTATUS status;
1167 int i;
1168 uint32_t g_index = 0, a_index = 0;
1169 struct samsync_ldif_context *ldif_ctx =
1170 (struct samsync_ldif_context *)ctx->private_data;
1172 status = ldif_init_context(mem_ctx,
1173 database_id,
1174 ctx->output_filename,
1175 ctx->domain_sid_str,
1176 &ldif_ctx);
1177 if (!NT_STATUS_IS_OK(status)) {
1178 goto failed;
1181 ctx->private_data = ldif_ctx;
1183 status = ldif_realloc_maps(mem_ctx, ldif_ctx, r->num_deltas);
1184 if (!NT_STATUS_IS_OK(status)) {
1185 goto failed;
1188 for (i = 0; i < r->num_deltas; i++) {
1189 status = fetch_sam_entry_ldif(mem_ctx, database_id,
1190 &r->delta_enum[i], ctx,
1191 &a_index, &g_index);
1192 if (!NT_STATUS_IS_OK(status)) {
1193 goto failed;
1197 /* This was the last query */
1198 if (last_query) {
1199 ldif_write_output(database_id, ldif_ctx);
1200 if (ldif_ctx->ldif_file != stdout) {
1201 ctx->result_message = talloc_asprintf(mem_ctx,
1202 "Vampired %d accounts and %d groups to %s",
1203 a_index, g_index, ctx->output_filename);
1205 ldif_free_context(ldif_ctx);
1206 ctx->private_data = NULL;
1209 return NT_STATUS_OK;
1211 failed:
1212 ldif_free_context(ldif_ctx);
1213 ctx->private_data = NULL;
1215 return status;
1218 #else /* HAVE_LDAP */
1220 NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
1221 enum netr_SamDatabaseID database_id,
1222 struct netr_DELTA_ENUM_ARRAY *r,
1223 bool last_query,
1224 struct samsync_context *ctx)
1226 return NT_STATUS_NOT_SUPPORTED;
1229 #endif