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