dnsp: Parse TXT records
[Samba/gebeck_regimport.git] / source3 / libnet / libnet_samsync_ldif.c
blob454f0a9c41b37c7974a9b582cb4bdf4d03674b0d
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"
28 #include "smbldap.h"
30 #ifdef HAVE_LDAP
32 /* uid's and gid's for writing deltas to ldif */
33 static uint32 ldif_gid = 999;
34 static uint32 ldif_uid = 999;
36 /* global counters */
37 static uint32_t g_index = 0;
38 static uint32_t a_index = 0;
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;
49 typedef struct _accountmap {
50 uint32_t rid;
51 const char *cn;
52 } ACCOUNTMAP;
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;
69 /****************************************************************
70 ****************************************************************/
72 static NTSTATUS populate_ldap_for_ldif(const char *sid,
73 const char *suffix,
74 const char *builtin_sid,
75 FILE *add_fd)
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;
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;
90 memcpy(suffix_attr, suffix, len);
91 suffix_attr[len] = '\0';
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);
104 user_suffix = lp_ldap_user_suffix();
105 if (user_suffix == NULL) {
106 SAFE_FREE(suffix_attr);
107 return NT_STATUS_NO_MEMORY;
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);
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;
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);
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;
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);
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;
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);
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);
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);
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);
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);
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);
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");
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);
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);
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);
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;
334 /****************************************************************
335 ****************************************************************/
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)
344 char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
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;
356 accountmap[0].rid = 512;
357 accountmap[0].cn = talloc_strdup(mem_ctx, "Domain Admins");
358 if (accountmap[0].cn == NULL) {
359 goto err;
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;
371 accountmap[1].rid = 513;
372 accountmap[1].cn = talloc_strdup(mem_ctx, "Domain Users");
373 if (accountmap[1].cn == NULL) {
374 goto err;
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;
386 accountmap[2].rid = 514;
387 accountmap[2].cn = talloc_strdup(mem_ctx, "Domain Guests");
388 if (accountmap[2].cn == NULL) {
389 goto err;
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;
401 accountmap[3].rid = 515;
402 accountmap[3].cn = talloc_strdup(mem_ctx, "Domain Computers");
403 if (accountmap[3].cn == NULL) {
404 goto err;
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;
416 accountmap[4].rid = 515;
417 accountmap[4].cn = talloc_strdup(mem_ctx, "Administrators");
418 if (accountmap[4].cn == NULL) {
419 goto err;
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;
431 accountmap[5].rid = 550;
432 accountmap[5].cn = talloc_strdup(mem_ctx, "Print Operators");
433 if (accountmap[5].cn == NULL) {
434 goto err;
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;
446 accountmap[6].rid = 551;
447 accountmap[6].cn = talloc_strdup(mem_ctx, "Backup Operators");
448 if (accountmap[6].cn == NULL) {
449 goto err;
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;
461 accountmap[7].rid = 551;
462 accountmap[7].cn = talloc_strdup(mem_ctx, "Replicators");
463 if (accountmap[7].cn == NULL) {
464 goto err;
467 SAFE_FREE(group_attr);
469 return NT_STATUS_OK;
471 err:
473 SAFE_FREE(group_attr);
474 return NT_STATUS_NO_MEMORY;
478 * This is a crap routine, but I think it's the quickest way to solve the
479 * UTF8->base64 problem.
482 static int fprintf_attr(FILE *add_fd, const char *attr_name,
483 const char *fmt, ...)
485 va_list ap;
486 char *value, *p, *base64;
487 DATA_BLOB base64_blob;
488 bool do_base64 = false;
489 int res;
491 va_start(ap, fmt);
492 value = talloc_vasprintf(NULL, fmt, ap);
493 va_end(ap);
495 SMB_ASSERT(value != NULL);
497 for (p=value; *p; p++) {
498 if (*p & 0x80) {
499 do_base64 = true;
500 break;
504 if (!do_base64) {
505 bool only_whitespace = true;
506 for (p=value; *p; p++) {
508 * I know that this not multibyte safe, but we break
509 * on the first non-whitespace character anyway.
511 if (!isspace(*p)) {
512 only_whitespace = false;
513 break;
516 if (only_whitespace) {
517 do_base64 = true;
521 if (!do_base64) {
522 res = fprintf(add_fd, "%s: %s\n", attr_name, value);
523 TALLOC_FREE(value);
524 return res;
527 base64_blob.data = (unsigned char *)value;
528 base64_blob.length = strlen(value);
530 base64 = base64_encode_data_blob(value, base64_blob);
531 SMB_ASSERT(base64 != NULL);
533 res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
534 TALLOC_FREE(value);
535 return res;
538 /****************************************************************
539 ****************************************************************/
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)
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(), '=', ',');
552 /* Set up the group type (always 2 for group info) */
553 grouptype = 2;
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++;
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;
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);
598 SAFE_FREE(group_attr);
599 /* Return */
600 return NT_STATUS_OK;
603 /****************************************************************
604 ****************************************************************/
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)
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;
626 memset(zero_buf, '\0', sizeof(zero_buf));
628 /* Get the username */
629 fstrcpy(username, r->account_name.string);
631 /* Get the rid */
632 rid = r->rid;
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);
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");
647 ou = lp_ldap_user_suffix();
648 } else {
649 ou = lp_ldap_machine_suffix();
650 snprintf(homedir, sizeof(homedir), "/machinehomedir");
653 /* Get the logon script */
654 fstrcpy(logonscript, r->logon_script.string);
656 /* Get the home drive */
657 fstrcpy(homedrive, r->home_drive.string);
659 /* Get the home path */
660 fstrcpy(homepath, r->home_directory.string);
662 /* Get the description */
663 fstrcpy(description, r->description.string);
665 /* Get the display name */
666 fstrcpy(fullname, r->full_name.string);
668 /* Get the profile path */
669 fstrcpy(profilepath, r->profile_path.string);
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);
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);
682 unix_time = nt_time_to_unix(r->last_password_change);
684 /* Increment the uid for the new user */
685 ldif_uid++;
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;
692 if (i == alloced){
693 DEBUG(1, ("Could not find rid %d in groupmap array\n",
694 group_rid));
695 return NT_STATUS_UNSUCCESSFUL;
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;
703 /* Set up sambaAcctFlags */
704 flags = pdb_encode_acct_ctrl(r->acct_flags,
705 NEW_PW_FORMAT_SPACE_PADDED_LEN);
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);
752 /* Return */
753 return NT_STATUS_OK;
756 /****************************************************************
757 ****************************************************************/
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)
767 fstring aliasname, description;
768 uint32 grouptype = 0, g_rid = 0;
769 char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
771 /* Get the alias name */
772 fstrcpy(aliasname, r->alias_name.string);
774 /* Get the alias description */
775 fstrcpy(description, r->description.string);
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;
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
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++;
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;
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);
836 SAFE_FREE(group_attr);
837 /* Return */
838 return NT_STATUS_OK;
841 /****************************************************************
842 ****************************************************************/
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)
850 fstring group_dn;
851 uint32 group_rid = 0, rid = 0;
852 int i, j, k;
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;
860 if (j == alloced){
861 DEBUG(1, ("Could not find rid %d in groupmap array\n",
862 group_rid));
863 return NT_STATUS_UNSUCCESSFUL;
865 snprintf(group_dn, sizeof(group_dn), "%s", groupmap[j].group_dn);
866 fprintf(mod_fd, "dn: %s\n", group_dn);
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;
874 if (k == alloced){
875 DEBUG(1, ("Could not find rid %d in "
876 "accountmap array\n", rid));
877 return NT_STATUS_UNSUCCESSFUL;
879 fprintf(mod_fd, "memberUid: %s\n", accountmap[k].cn);
881 fprintf(mod_fd, "\n");
883 fflush(mod_fd);
885 /* Return */
886 return NT_STATUS_OK;
889 /****************************************************************
890 ****************************************************************/
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)
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";
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);
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);
916 if (*ctx && (*ctx)->initialized) {
917 return NT_STATUS_OK;
920 r = TALLOC_ZERO_P(mem_ctx, struct samsync_ldif_context);
921 NT_STATUS_HAVE_NO_MEMORY(r);
923 /* Get the ldap suffix */
924 r->suffix = lp_ldap_suffix();
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;
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;
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;
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;
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;
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;
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;
975 /* Remember how many we malloced */
976 r->num_alloced = 8;
978 /* Initial database population */
979 if (database_id == SAM_DATABASE_DOMAIN) {
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;
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;
1000 r->initialized = true;
1002 *ctx = r;
1004 return NT_STATUS_OK;
1005 done:
1006 TALLOC_FREE(r);
1007 return status;
1010 /****************************************************************
1011 ****************************************************************/
1013 static void ldif_free_context(struct samsync_ldif_context *r)
1015 if (!r) {
1016 return;
1019 /* Close and delete the ldif files */
1020 if (r->add_file) {
1021 fclose(r->add_file);
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)));
1030 if (r->mod_file) {
1031 fclose(r->mod_file);
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)));
1040 if (r->ldif_file && (r->ldif_file != stdout)) {
1041 fclose(r->ldif_file);
1044 TALLOC_FREE(r);
1047 /****************************************************************
1048 ****************************************************************/
1050 static void ldif_write_output(enum netr_SamDatabaseID database_id,
1051 struct samsync_ldif_context *l)
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);
1067 fseek(l->add_file, 0, SEEK_SET);
1068 transfer_file(fileno(l->add_file), fileno(l->ldif_file), (size_t) -1);
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);
1083 fseek(l->mod_file, 0, SEEK_SET);
1084 transfer_file(fileno(l->mod_file), fileno(l->ldif_file), (size_t) -1);
1087 /****************************************************************
1088 ****************************************************************/
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)
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);
1102 switch (r->delta_type) {
1103 case NETR_DELTA_DOMAIN:
1104 break;
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;
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;
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;
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;
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 */
1163 return NT_STATUS_OK;
1166 /****************************************************************
1167 ****************************************************************/
1169 static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx,
1170 struct samsync_ldif_context *l,
1171 uint32_t num_entries)
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);
1179 l->accountmap = TALLOC_REALLOC_ARRAY(mem_ctx,
1180 l->accountmap,
1181 ACCOUNTMAP,
1182 num_entries + l->num_alloced);
1184 if (l->groupmap == NULL || l->accountmap == NULL) {
1185 DEBUG(1,("GROUPMAP talloc failed\n"));
1186 return NT_STATUS_NO_MEMORY;
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);
1195 /* Remember how many we alloced this time */
1196 l->num_alloced += num_entries;
1198 return NT_STATUS_OK;
1201 /****************************************************************
1202 ****************************************************************/
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)
1209 NTSTATUS status;
1210 struct samsync_ldif_context *ldif_ctx =
1211 (struct samsync_ldif_context *)ctx->private_data;
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;
1222 ctx->private_data = ldif_ctx;
1224 return NT_STATUS_OK;
1227 /****************************************************************
1228 ****************************************************************/
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)
1236 NTSTATUS status;
1237 int i;
1238 struct samsync_ldif_context *ldif_ctx =
1239 (struct samsync_ldif_context *)ctx->private_data;
1241 status = ldif_realloc_maps(mem_ctx, ldif_ctx, r->num_deltas);
1242 if (!NT_STATUS_IS_OK(status)) {
1243 goto failed;
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;
1255 return NT_STATUS_OK;
1257 failed:
1258 ldif_free_context(ldif_ctx);
1259 ctx->private_data = NULL;
1261 return status;
1264 /****************************************************************
1265 ****************************************************************/
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)
1272 struct samsync_ldif_context *ldif_ctx =
1273 (struct samsync_ldif_context *)ctx->private_data;
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);
1283 ldif_free_context(ldif_ctx);
1284 ctx->private_data = NULL;
1286 return NT_STATUS_OK;
1289 #else /* HAVE_LDAP */
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)
1296 return NT_STATUS_NOT_SUPPORTED;
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)
1305 return NT_STATUS_NOT_SUPPORTED;
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)
1313 return NT_STATUS_NOT_SUPPORTED;
1316 #endif
1318 const struct samsync_ops libnet_samsync_ldif_ops = {
1319 .startup = init_ldif,
1320 .process_objects = fetch_sam_entries_ldif,
1321 .finish = close_ldif,