dsdb-acl: give error string if we can not obtain the schema
[Samba/gebeck_regimport.git] / source3 / libnet / libnet_samsync_ldif.c
blobc492b9fda514ef28406cc554fcd6a1f7bc4e7792
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 "transfer_file.h"
29 #include "passdb.h"
30 #include "passdb/pdb_ldap_schema.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;
72 Returns the substring from src between the first occurrence of
73 the char "front" and the first occurence of the char "back".
74 Mallocs the return string which must be freed. Not for use
75 with wide character strings.
77 static char *sstring_sub(const char *src, char front, char back)
79 char *temp1, *temp2, *temp3;
80 ptrdiff_t len;
82 temp1 = strchr(src, front);
83 if (temp1 == NULL) return NULL;
84 temp2 = strchr(src, back);
85 if (temp2 == NULL) return NULL;
86 len = temp2 - temp1;
87 if (len <= 0) return NULL;
88 temp3 = (char*)SMB_MALLOC(len);
89 if (temp3 == NULL) {
90 DEBUG(1,("Malloc failure in sstring_sub\n"));
91 return NULL;
93 memcpy(temp3, temp1+1, len-1);
94 temp3[len-1] = '\0';
95 return temp3;
98 /****************************************************************
99 ****************************************************************/
101 static NTSTATUS populate_ldap_for_ldif(const char *sid,
102 const char *suffix,
103 const char *builtin_sid,
104 FILE *add_fd)
106 const char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix;
107 char *user_attr=NULL, *group_attr=NULL;
108 char *suffix_attr;
109 int len;
111 /* Get the suffix attribute */
112 suffix_attr = sstring_sub(suffix, '=', ',');
113 if (suffix_attr == NULL) {
114 len = strlen(suffix);
115 suffix_attr = (char*)SMB_MALLOC(len+1);
116 if (!suffix_attr) {
117 return NT_STATUS_NO_MEMORY;
119 memcpy(suffix_attr, suffix, len);
120 suffix_attr[len] = '\0';
123 /* Write the base */
124 fprintf(add_fd, "# %s\n", suffix);
125 fprintf(add_fd, "dn: %s\n", suffix);
126 fprintf(add_fd, "objectClass: dcObject\n");
127 fprintf(add_fd, "objectClass: organization\n");
128 fprintf(add_fd, "o: %s\n", suffix_attr);
129 fprintf(add_fd, "dc: %s\n", suffix_attr);
130 fprintf(add_fd, "\n");
131 fflush(add_fd);
133 user_suffix = lp_ldap_user_suffix(talloc_tos());
134 if (user_suffix == NULL) {
135 SAFE_FREE(suffix_attr);
136 return NT_STATUS_NO_MEMORY;
138 /* If it exists and is distinct from other containers,
139 Write the Users entity */
140 if (*user_suffix && strcmp(user_suffix, suffix)) {
141 user_attr = sstring_sub(lp_ldap_user_suffix(talloc_tos()), '=', ',');
142 fprintf(add_fd, "# %s\n", user_suffix);
143 fprintf(add_fd, "dn: %s\n", user_suffix);
144 fprintf(add_fd, "objectClass: organizationalUnit\n");
145 fprintf(add_fd, "ou: %s\n", user_attr);
146 fprintf(add_fd, "\n");
147 fflush(add_fd);
151 group_suffix = lp_ldap_group_suffix(talloc_tos());
152 if (group_suffix == NULL) {
153 SAFE_FREE(suffix_attr);
154 SAFE_FREE(user_attr);
155 return NT_STATUS_NO_MEMORY;
157 /* If it exists and is distinct from other containers,
158 Write the Groups entity */
159 if (*group_suffix && strcmp(group_suffix, suffix)) {
160 group_attr = sstring_sub(lp_ldap_group_suffix(talloc_tos()), '=', ',');
161 fprintf(add_fd, "# %s\n", group_suffix);
162 fprintf(add_fd, "dn: %s\n", group_suffix);
163 fprintf(add_fd, "objectClass: organizationalUnit\n");
164 fprintf(add_fd, "ou: %s\n", group_attr);
165 fprintf(add_fd, "\n");
166 fflush(add_fd);
169 /* If it exists and is distinct from other containers,
170 Write the Computers entity */
171 machine_suffix = lp_ldap_machine_suffix(talloc_tos());
172 if (machine_suffix == NULL) {
173 SAFE_FREE(suffix_attr);
174 SAFE_FREE(user_attr);
175 SAFE_FREE(group_attr);
176 return NT_STATUS_NO_MEMORY;
178 if (*machine_suffix && strcmp(machine_suffix, user_suffix) &&
179 strcmp(machine_suffix, suffix)) {
180 char *machine_ou = NULL;
181 fprintf(add_fd, "# %s\n", machine_suffix);
182 fprintf(add_fd, "dn: %s\n", machine_suffix);
183 fprintf(add_fd, "objectClass: organizationalUnit\n");
184 /* this isn't totally correct as it assumes that
185 there _must_ be an ou. just fixing memleak now. jmcd */
186 machine_ou = sstring_sub(lp_ldap_machine_suffix(talloc_tos()), '=', ',');
187 fprintf(add_fd, "ou: %s\n", machine_ou);
188 SAFE_FREE(machine_ou);
189 fprintf(add_fd, "\n");
190 fflush(add_fd);
193 /* If it exists and is distinct from other containers,
194 Write the IdMap entity */
195 idmap_suffix = lp_ldap_idmap_suffix(talloc_tos());
196 if (idmap_suffix == NULL) {
197 SAFE_FREE(suffix_attr);
198 SAFE_FREE(user_attr);
199 SAFE_FREE(group_attr);
200 return NT_STATUS_NO_MEMORY;
202 if (*idmap_suffix &&
203 strcmp(idmap_suffix, user_suffix) &&
204 strcmp(idmap_suffix, suffix)) {
205 char *s;
206 fprintf(add_fd, "# %s\n", idmap_suffix);
207 fprintf(add_fd, "dn: %s\n", idmap_suffix);
208 fprintf(add_fd, "ObjectClass: organizationalUnit\n");
209 s = sstring_sub(lp_ldap_idmap_suffix(talloc_tos()), '=', ',');
210 fprintf(add_fd, "ou: %s\n", s);
211 SAFE_FREE(s);
212 fprintf(add_fd, "\n");
213 fflush(add_fd);
216 /* Write the domain entity */
217 fprintf(add_fd, "# %s, %s\n", lp_workgroup(), suffix);
218 fprintf(add_fd, "dn: sambaDomainName=%s,%s\n", lp_workgroup(),
219 suffix);
220 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_DOMINFO);
221 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_IDPOOL);
222 fprintf(add_fd, "sambaDomainName: %s\n", lp_workgroup());
223 fprintf(add_fd, "sambaSID: %s\n", sid);
224 fprintf(add_fd, "uidNumber: %d\n", ++ldif_uid);
225 fprintf(add_fd, "gidNumber: %d\n", ++ldif_gid);
226 fprintf(add_fd, "\n");
227 fflush(add_fd);
229 /* Write the Domain Admins entity */
230 fprintf(add_fd, "# Domain Admins, %s, %s\n", group_attr,
231 suffix);
232 fprintf(add_fd, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr,
233 suffix);
234 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
235 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
236 fprintf(add_fd, "cn: Domain Admins\n");
237 fprintf(add_fd, "memberUid: Administrator\n");
238 fprintf(add_fd, "description: Netbios Domain Administrators\n");
239 fprintf(add_fd, "gidNumber: 512\n");
240 fprintf(add_fd, "sambaSID: %s-512\n", sid);
241 fprintf(add_fd, "sambaGroupType: 2\n");
242 fprintf(add_fd, "displayName: Domain Admins\n");
243 fprintf(add_fd, "\n");
244 fflush(add_fd);
246 /* Write the Domain Users entity */
247 fprintf(add_fd, "# Domain Users, %s, %s\n", group_attr,
248 suffix);
249 fprintf(add_fd, "dn: cn=Domain Users,ou=%s,%s\n", group_attr,
250 suffix);
251 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
252 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
253 fprintf(add_fd, "cn: Domain Users\n");
254 fprintf(add_fd, "description: Netbios Domain Users\n");
255 fprintf(add_fd, "gidNumber: 513\n");
256 fprintf(add_fd, "sambaSID: %s-513\n", sid);
257 fprintf(add_fd, "sambaGroupType: 2\n");
258 fprintf(add_fd, "displayName: Domain Users\n");
259 fprintf(add_fd, "\n");
260 fflush(add_fd);
262 /* Write the Domain Guests entity */
263 fprintf(add_fd, "# Domain Guests, %s, %s\n", group_attr,
264 suffix);
265 fprintf(add_fd, "dn: cn=Domain Guests,ou=%s,%s\n", group_attr,
266 suffix);
267 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
268 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
269 fprintf(add_fd, "cn: Domain Guests\n");
270 fprintf(add_fd, "description: Netbios Domain Guests\n");
271 fprintf(add_fd, "gidNumber: 514\n");
272 fprintf(add_fd, "sambaSID: %s-514\n", sid);
273 fprintf(add_fd, "sambaGroupType: 2\n");
274 fprintf(add_fd, "displayName: Domain Guests\n");
275 fprintf(add_fd, "\n");
276 fflush(add_fd);
278 /* Write the Domain Computers entity */
279 fprintf(add_fd, "# Domain Computers, %s, %s\n", group_attr,
280 suffix);
281 fprintf(add_fd, "dn: cn=Domain Computers,ou=%s,%s\n",
282 group_attr, suffix);
283 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
284 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
285 fprintf(add_fd, "gidNumber: 515\n");
286 fprintf(add_fd, "cn: Domain Computers\n");
287 fprintf(add_fd, "description: Netbios Domain Computers accounts\n");
288 fprintf(add_fd, "sambaSID: %s-515\n", sid);
289 fprintf(add_fd, "sambaGroupType: 2\n");
290 fprintf(add_fd, "displayName: Domain Computers\n");
291 fprintf(add_fd, "\n");
292 fflush(add_fd);
294 /* Write the Admininistrators Groups entity */
295 fprintf(add_fd, "# Administrators, %s, %s\n", group_attr,
296 suffix);
297 fprintf(add_fd, "dn: cn=Administrators,ou=%s,%s\n", group_attr,
298 suffix);
299 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
300 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
301 fprintf(add_fd, "gidNumber: 544\n");
302 fprintf(add_fd, "cn: Administrators\n");
303 fprintf(add_fd, "description: Netbios Domain Members can fully administer the computer/sambaDomainName\n");
304 fprintf(add_fd, "sambaSID: %s-544\n", builtin_sid);
305 fprintf(add_fd, "sambaGroupType: 5\n");
306 fprintf(add_fd, "displayName: Administrators\n");
307 fprintf(add_fd, "\n");
309 /* Write the Print Operator entity */
310 fprintf(add_fd, "# Print Operators, %s, %s\n", group_attr,
311 suffix);
312 fprintf(add_fd, "dn: cn=Print Operators,ou=%s,%s\n",
313 group_attr, suffix);
314 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
315 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
316 fprintf(add_fd, "gidNumber: 550\n");
317 fprintf(add_fd, "cn: Print Operators\n");
318 fprintf(add_fd, "description: Netbios Domain Print Operators\n");
319 fprintf(add_fd, "sambaSID: %s-550\n", builtin_sid);
320 fprintf(add_fd, "sambaGroupType: 5\n");
321 fprintf(add_fd, "displayName: Print Operators\n");
322 fprintf(add_fd, "\n");
323 fflush(add_fd);
325 /* Write the Backup Operators entity */
326 fprintf(add_fd, "# Backup Operators, %s, %s\n", group_attr,
327 suffix);
328 fprintf(add_fd, "dn: cn=Backup Operators,ou=%s,%s\n",
329 group_attr, suffix);
330 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
331 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
332 fprintf(add_fd, "gidNumber: 551\n");
333 fprintf(add_fd, "cn: Backup Operators\n");
334 fprintf(add_fd, "description: Netbios Domain Members can bypass file security to back up files\n");
335 fprintf(add_fd, "sambaSID: %s-551\n", builtin_sid);
336 fprintf(add_fd, "sambaGroupType: 5\n");
337 fprintf(add_fd, "displayName: Backup Operators\n");
338 fprintf(add_fd, "\n");
339 fflush(add_fd);
341 /* Write the Replicators entity */
342 fprintf(add_fd, "# Replicators, %s, %s\n", group_attr, suffix);
343 fprintf(add_fd, "dn: cn=Replicators,ou=%s,%s\n", group_attr,
344 suffix);
345 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
346 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
347 fprintf(add_fd, "gidNumber: 552\n");
348 fprintf(add_fd, "cn: Replicators\n");
349 fprintf(add_fd, "description: Netbios Domain Supports file replication in a sambaDomainName\n");
350 fprintf(add_fd, "sambaSID: %s-552\n", builtin_sid);
351 fprintf(add_fd, "sambaGroupType: 5\n");
352 fprintf(add_fd, "displayName: Replicators\n");
353 fprintf(add_fd, "\n");
354 fflush(add_fd);
356 /* Deallocate memory, and return */
357 SAFE_FREE(suffix_attr);
358 SAFE_FREE(user_attr);
359 SAFE_FREE(group_attr);
360 return NT_STATUS_OK;
363 /****************************************************************
364 ****************************************************************/
366 static NTSTATUS map_populate_groups(TALLOC_CTX *mem_ctx,
367 GROUPMAP *groupmap,
368 ACCOUNTMAP *accountmap,
369 const char *sid,
370 const char *suffix,
371 const char *builtin_sid)
373 char *group_attr = sstring_sub(lp_ldap_group_suffix(talloc_tos()), '=', ',');
375 /* Map the groups created by populate_ldap_for_ldif */
376 groupmap[0].rid = 512;
377 groupmap[0].gidNumber = 512;
378 groupmap[0].sambaSID = talloc_asprintf(mem_ctx, "%s-512", sid);
379 groupmap[0].group_dn = talloc_asprintf(mem_ctx,
380 "cn=Domain Admins,ou=%s,%s", group_attr, suffix);
381 if (groupmap[0].sambaSID == NULL || groupmap[0].group_dn == NULL) {
382 goto err;
385 accountmap[0].rid = 512;
386 accountmap[0].cn = talloc_strdup(mem_ctx, "Domain Admins");
387 if (accountmap[0].cn == NULL) {
388 goto err;
391 groupmap[1].rid = 513;
392 groupmap[1].gidNumber = 513;
393 groupmap[1].sambaSID = talloc_asprintf(mem_ctx, "%s-513", sid);
394 groupmap[1].group_dn = talloc_asprintf(mem_ctx,
395 "cn=Domain Users,ou=%s,%s", group_attr, suffix);
396 if (groupmap[1].sambaSID == NULL || groupmap[1].group_dn == NULL) {
397 goto err;
400 accountmap[1].rid = 513;
401 accountmap[1].cn = talloc_strdup(mem_ctx, "Domain Users");
402 if (accountmap[1].cn == NULL) {
403 goto err;
406 groupmap[2].rid = 514;
407 groupmap[2].gidNumber = 514;
408 groupmap[2].sambaSID = talloc_asprintf(mem_ctx, "%s-514", sid);
409 groupmap[2].group_dn = talloc_asprintf(mem_ctx,
410 "cn=Domain Guests,ou=%s,%s", group_attr, suffix);
411 if (groupmap[2].sambaSID == NULL || groupmap[2].group_dn == NULL) {
412 goto err;
415 accountmap[2].rid = 514;
416 accountmap[2].cn = talloc_strdup(mem_ctx, "Domain Guests");
417 if (accountmap[2].cn == NULL) {
418 goto err;
421 groupmap[3].rid = 515;
422 groupmap[3].gidNumber = 515;
423 groupmap[3].sambaSID = talloc_asprintf(mem_ctx, "%s-515", sid);
424 groupmap[3].group_dn = talloc_asprintf(mem_ctx,
425 "cn=Domain Computers,ou=%s,%s", group_attr, suffix);
426 if (groupmap[3].sambaSID == NULL || groupmap[3].group_dn == NULL) {
427 goto err;
430 accountmap[3].rid = 515;
431 accountmap[3].cn = talloc_strdup(mem_ctx, "Domain Computers");
432 if (accountmap[3].cn == NULL) {
433 goto err;
436 groupmap[4].rid = 544;
437 groupmap[4].gidNumber = 544;
438 groupmap[4].sambaSID = talloc_asprintf(mem_ctx, "%s-544", builtin_sid);
439 groupmap[4].group_dn = talloc_asprintf(mem_ctx,
440 "cn=Administrators,ou=%s,%s", group_attr, suffix);
441 if (groupmap[4].sambaSID == NULL || groupmap[4].group_dn == NULL) {
442 goto err;
445 accountmap[4].rid = 515;
446 accountmap[4].cn = talloc_strdup(mem_ctx, "Administrators");
447 if (accountmap[4].cn == NULL) {
448 goto err;
451 groupmap[5].rid = 550;
452 groupmap[5].gidNumber = 550;
453 groupmap[5].sambaSID = talloc_asprintf(mem_ctx, "%s-550", builtin_sid);
454 groupmap[5].group_dn = talloc_asprintf(mem_ctx,
455 "cn=Print Operators,ou=%s,%s", group_attr, suffix);
456 if (groupmap[5].sambaSID == NULL || groupmap[5].group_dn == NULL) {
457 goto err;
460 accountmap[5].rid = 550;
461 accountmap[5].cn = talloc_strdup(mem_ctx, "Print Operators");
462 if (accountmap[5].cn == NULL) {
463 goto err;
466 groupmap[6].rid = 551;
467 groupmap[6].gidNumber = 551;
468 groupmap[6].sambaSID = talloc_asprintf(mem_ctx, "%s-551", builtin_sid);
469 groupmap[6].group_dn = talloc_asprintf(mem_ctx,
470 "cn=Backup Operators,ou=%s,%s", group_attr, suffix);
471 if (groupmap[6].sambaSID == NULL || groupmap[6].group_dn == NULL) {
472 goto err;
475 accountmap[6].rid = 551;
476 accountmap[6].cn = talloc_strdup(mem_ctx, "Backup Operators");
477 if (accountmap[6].cn == NULL) {
478 goto err;
481 groupmap[7].rid = 552;
482 groupmap[7].gidNumber = 552;
483 groupmap[7].sambaSID = talloc_asprintf(mem_ctx, "%s-552", builtin_sid);
484 groupmap[7].group_dn = talloc_asprintf(mem_ctx,
485 "cn=Replicators,ou=%s,%s", group_attr, suffix);
486 if (groupmap[7].sambaSID == NULL || groupmap[7].group_dn == NULL) {
487 goto err;
490 accountmap[7].rid = 551;
491 accountmap[7].cn = talloc_strdup(mem_ctx, "Replicators");
492 if (accountmap[7].cn == NULL) {
493 goto err;
496 SAFE_FREE(group_attr);
498 return NT_STATUS_OK;
500 err:
502 SAFE_FREE(group_attr);
503 return NT_STATUS_NO_MEMORY;
507 * This is a crap routine, but I think it's the quickest way to solve the
508 * UTF8->base64 problem.
511 static int fprintf_attr(FILE *add_fd, const char *attr_name,
512 const char *fmt, ...)
514 va_list ap;
515 char *value, *p, *base64;
516 DATA_BLOB base64_blob;
517 bool do_base64 = false;
518 int res;
520 va_start(ap, fmt);
521 value = talloc_vasprintf(NULL, fmt, ap);
522 va_end(ap);
524 SMB_ASSERT(value != NULL);
526 for (p=value; *p; p++) {
527 if (*p & 0x80) {
528 do_base64 = true;
529 break;
533 if (!do_base64) {
534 bool only_whitespace = true;
535 for (p=value; *p; p++) {
537 * I know that this not multibyte safe, but we break
538 * on the first non-whitespace character anyway.
540 if (!isspace(*p)) {
541 only_whitespace = false;
542 break;
545 if (only_whitespace) {
546 do_base64 = true;
550 if (!do_base64) {
551 res = fprintf(add_fd, "%s: %s\n", attr_name, value);
552 TALLOC_FREE(value);
553 return res;
556 base64_blob.data = (unsigned char *)value;
557 base64_blob.length = strlen(value);
559 base64 = base64_encode_data_blob(value, base64_blob);
560 SMB_ASSERT(base64 != NULL);
562 res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
563 TALLOC_FREE(value);
564 return res;
567 /****************************************************************
568 ****************************************************************/
570 static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx,
571 struct netr_DELTA_GROUP *r,
572 GROUPMAP *groupmap,
573 FILE *add_fd,
574 const char *sid,
575 const char *suffix)
577 const char *groupname = r->group_name.string;
578 uint32 grouptype = 0, g_rid = 0;
579 char *group_attr = sstring_sub(lp_ldap_group_suffix(talloc_tos()), '=', ',');
581 /* Set up the group type (always 2 for group info) */
582 grouptype = 2;
584 /* These groups are entered by populate_ldap_for_ldif */
585 if (strcmp(groupname, "Domain Admins") == 0 ||
586 strcmp(groupname, "Domain Users") == 0 ||
587 strcmp(groupname, "Domain Guests") == 0 ||
588 strcmp(groupname, "Domain Computers") == 0 ||
589 strcmp(groupname, "Administrators") == 0 ||
590 strcmp(groupname, "Print Operators") == 0 ||
591 strcmp(groupname, "Backup Operators") == 0 ||
592 strcmp(groupname, "Replicators") == 0) {
593 SAFE_FREE(group_attr);
594 return NT_STATUS_OK;
595 } else {
596 /* Increment the gid for the new group */
597 ldif_gid++;
600 /* Map the group rid, gid, and dn */
601 g_rid = r->rid;
602 groupmap->rid = g_rid;
603 groupmap->gidNumber = ldif_gid;
604 groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
605 groupmap->group_dn = talloc_asprintf(mem_ctx,
606 "cn=%s,ou=%s,%s", groupname, group_attr, suffix);
607 if (groupmap->sambaSID == NULL || groupmap->group_dn == NULL) {
608 SAFE_FREE(group_attr);
609 return NT_STATUS_NO_MEMORY;
612 /* Write the data to the temporary add ldif file */
613 fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr,
614 suffix);
615 fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", groupname, group_attr,
616 suffix);
617 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
618 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
619 fprintf_attr(add_fd, "cn", "%s", groupname);
620 fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
621 fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
622 fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
623 fprintf_attr(add_fd, "displayName", "%s", groupname);
624 fprintf(add_fd, "\n");
625 fflush(add_fd);
627 SAFE_FREE(group_attr);
628 /* Return */
629 return NT_STATUS_OK;
632 /****************************************************************
633 ****************************************************************/
635 static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx,
636 struct netr_DELTA_USER *r,
637 GROUPMAP *groupmap,
638 ACCOUNTMAP *accountmap,
639 FILE *add_fd,
640 const char *sid,
641 const char *suffix,
642 int alloced)
644 fstring username, logonscript, homedrive, homepath = "", homedir = "";
645 fstring hex_nt_passwd, hex_lm_passwd;
646 fstring description, profilepath, fullname, sambaSID;
647 char *flags, *user_rdn;
648 const char *ou;
649 const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
650 uchar zero_buf[16];
651 uint32 rid = 0, group_rid = 0, gidNumber = 0;
652 time_t unix_time;
653 int i, ret;
655 memset(zero_buf, '\0', sizeof(zero_buf));
657 /* Get the username */
658 fstrcpy(username, r->account_name.string);
660 /* Get the rid */
661 rid = r->rid;
663 /* Map the rid and username for group member info later */
664 accountmap->rid = rid;
665 accountmap->cn = talloc_strdup(mem_ctx, username);
666 NT_STATUS_HAVE_NO_MEMORY(accountmap->cn);
668 /* Get the home directory */
669 if (r->acct_flags & ACB_NORMAL) {
670 fstrcpy(homedir, r->home_directory.string);
671 if (!*homedir) {
672 snprintf(homedir, sizeof(homedir), "/home/%s", username);
673 } else {
674 snprintf(homedir, sizeof(homedir), "/nobodyshomedir");
676 ou = lp_ldap_user_suffix(talloc_tos());
677 } else {
678 ou = lp_ldap_machine_suffix(talloc_tos());
679 snprintf(homedir, sizeof(homedir), "/machinehomedir");
682 /* Get the logon script */
683 fstrcpy(logonscript, r->logon_script.string);
685 /* Get the home drive */
686 fstrcpy(homedrive, r->home_drive.string);
688 /* Get the home path */
689 fstrcpy(homepath, r->home_directory.string);
691 /* Get the description */
692 fstrcpy(description, r->description.string);
694 /* Get the display name */
695 fstrcpy(fullname, r->full_name.string);
697 /* Get the profile path */
698 fstrcpy(profilepath, r->profile_path.string);
700 /* Get lm and nt password data */
701 if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
702 pdb_sethexpwd(hex_lm_passwd, r->lmpassword.hash, r->acct_flags);
703 } else {
704 pdb_sethexpwd(hex_lm_passwd, NULL, 0);
706 if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
707 pdb_sethexpwd(hex_nt_passwd, r->ntpassword.hash, r->acct_flags);
708 } else {
709 pdb_sethexpwd(hex_nt_passwd, NULL, 0);
711 unix_time = nt_time_to_unix(r->last_password_change);
713 /* Increment the uid for the new user */
714 ldif_uid++;
716 /* Set up group id and sambaSID for the user */
717 group_rid = r->primary_gid;
718 for (i=0; i<alloced; i++) {
719 if (groupmap[i].rid == group_rid) break;
721 if (i == alloced){
722 DEBUG(1, ("Could not find rid %d in groupmap array\n",
723 group_rid));
724 return NT_STATUS_UNSUCCESSFUL;
726 gidNumber = groupmap[i].gidNumber;
727 ret = snprintf(sambaSID, sizeof(sambaSID), "%s", groupmap[i].sambaSID);
728 if (ret < 0 || ret == sizeof(sambaSID)) {
729 return NT_STATUS_UNSUCCESSFUL;
732 /* Set up sambaAcctFlags */
733 flags = pdb_encode_acct_ctrl(r->acct_flags,
734 NEW_PW_FORMAT_SPACE_PADDED_LEN);
736 /* Add the user to the temporary add ldif file */
737 /* this isn't quite right...we can't assume there's just OU=. jmcd */
738 user_rdn = sstring_sub(ou, '=', ',');
739 fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
740 fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
741 suffix);
742 SAFE_FREE(user_rdn);
743 fprintf(add_fd, "ObjectClass: top\n");
744 fprintf(add_fd, "objectClass: inetOrgPerson\n");
745 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT);
746 fprintf(add_fd, "objectClass: shadowAccount\n");
747 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT);
748 fprintf_attr(add_fd, "cn", "%s", username);
749 fprintf_attr(add_fd, "sn", "%s", username);
750 fprintf_attr(add_fd, "uid", "%s", username);
751 fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
752 fprintf(add_fd, "gidNumber: %d\n", gidNumber);
753 fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
754 if (*homepath)
755 fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
756 if (*homedrive)
757 fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
758 if (*logonscript)
759 fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
760 fprintf(add_fd, "loginShell: %s\n",
761 ((r->acct_flags & ACB_NORMAL) ?
762 "/bin/bash" : "/bin/false"));
763 fprintf(add_fd, "gecos: System User\n");
764 if (*description)
765 fprintf_attr(add_fd, "description", "%s", description);
766 fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
767 fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
768 if(*fullname)
769 fprintf_attr(add_fd, "displayName", "%s", fullname);
770 if(*profilepath)
771 fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
772 if (strcmp(nopasswd, hex_lm_passwd) != 0)
773 fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
774 if (strcmp(nopasswd, hex_nt_passwd) != 0)
775 fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd);
776 fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time);
777 fprintf(add_fd, "sambaAcctFlags: %s\n", flags);
778 fprintf(add_fd, "\n");
779 fflush(add_fd);
781 /* Return */
782 return NT_STATUS_OK;
785 /****************************************************************
786 ****************************************************************/
788 static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx,
789 struct netr_DELTA_ALIAS *r,
790 GROUPMAP *groupmap,
791 FILE *add_fd,
792 const char *sid,
793 const char *suffix,
794 enum netr_SamDatabaseID database_id)
796 fstring aliasname, description;
797 uint32 grouptype = 0, g_rid = 0;
798 char *group_attr = sstring_sub(lp_ldap_group_suffix(talloc_tos()), '=', ',');
800 /* Get the alias name */
801 fstrcpy(aliasname, r->alias_name.string);
803 /* Get the alias description */
804 fstrcpy(description, r->description.string);
806 /* Set up the group type */
807 switch (database_id) {
808 case SAM_DATABASE_DOMAIN:
809 grouptype = 4;
810 break;
811 case SAM_DATABASE_BUILTIN:
812 grouptype = 5;
813 break;
814 default:
815 grouptype = 4;
816 break;
820 These groups are entered by populate_ldap_for_ldif
821 Note that populate creates a group called Relicators,
822 but NT returns a group called Replicator
824 if (strcmp(aliasname, "Domain Admins") == 0 ||
825 strcmp(aliasname, "Domain Users") == 0 ||
826 strcmp(aliasname, "Domain Guests") == 0 ||
827 strcmp(aliasname, "Domain Computers") == 0 ||
828 strcmp(aliasname, "Administrators") == 0 ||
829 strcmp(aliasname, "Print Operators") == 0 ||
830 strcmp(aliasname, "Backup Operators") == 0 ||
831 strcmp(aliasname, "Replicator") == 0) {
832 SAFE_FREE(group_attr);
833 return NT_STATUS_OK;
834 } else {
835 /* Increment the gid for the new group */
836 ldif_gid++;
839 /* Map the group rid and gid */
840 g_rid = r->rid;
841 groupmap->gidNumber = ldif_gid;
842 groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
843 if (groupmap->sambaSID == NULL) {
844 SAFE_FREE(group_attr);
845 return NT_STATUS_NO_MEMORY;
848 /* Write the data to the temporary add ldif file */
849 fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr,
850 suffix);
851 fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", aliasname, group_attr,
852 suffix);
853 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
854 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
855 fprintf(add_fd, "cn: %s\n", aliasname);
856 fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
857 fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
858 fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
859 fprintf_attr(add_fd, "displayName", "%s", aliasname);
860 if (description[0])
861 fprintf_attr(add_fd, "description", "%s", description);
862 fprintf(add_fd, "\n");
863 fflush(add_fd);
865 SAFE_FREE(group_attr);
866 /* Return */
867 return NT_STATUS_OK;
870 /****************************************************************
871 ****************************************************************/
873 static NTSTATUS fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER *r,
874 uint32_t id_rid,
875 GROUPMAP *groupmap,
876 ACCOUNTMAP *accountmap,
877 FILE *mod_fd, int alloced)
879 fstring group_dn;
880 uint32 group_rid = 0, rid = 0;
881 int i, j, k;
883 /* Get the dn for the group */
884 if (r->num_rids > 0) {
885 group_rid = id_rid;
886 for (j=0; j<alloced; j++) {
887 if (groupmap[j].rid == group_rid) break;
889 if (j == alloced){
890 DEBUG(1, ("Could not find rid %d in groupmap array\n",
891 group_rid));
892 return NT_STATUS_UNSUCCESSFUL;
894 snprintf(group_dn, sizeof(group_dn), "%s", groupmap[j].group_dn);
895 fprintf(mod_fd, "dn: %s\n", group_dn);
897 /* Get the cn for each member */
898 for (i=0; i < r->num_rids; i++) {
899 rid = r->rids[i];
900 for (k=0; k<alloced; k++) {
901 if (accountmap[k].rid == rid) break;
903 if (k == alloced){
904 DEBUG(1, ("Could not find rid %d in "
905 "accountmap array\n", rid));
906 return NT_STATUS_UNSUCCESSFUL;
908 fprintf(mod_fd, "memberUid: %s\n", accountmap[k].cn);
910 fprintf(mod_fd, "\n");
912 fflush(mod_fd);
914 /* Return */
915 return NT_STATUS_OK;
918 /****************************************************************
919 ****************************************************************/
921 static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx,
922 enum netr_SamDatabaseID database_id,
923 const char *ldif_filename,
924 const char *domain_sid_str,
925 struct samsync_ldif_context **ctx)
927 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
928 struct samsync_ldif_context *r;
929 const char *add_template = "/tmp/add.ldif.XXXXXX";
930 const char *mod_template = "/tmp/mod.ldif.XXXXXX";
931 const char *builtin_sid = "S-1-5-32";
933 r = talloc_zero(mem_ctx, struct samsync_ldif_context);
934 NT_STATUS_HAVE_NO_MEMORY(r);
936 /* Get the ldap suffix */
937 r->suffix = lp_ldap_suffix(talloc_tos());
939 /* Get other smb.conf data */
940 if (!(lp_workgroup()) || !*(lp_workgroup())) {
941 DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
942 exit(1);
945 /* Get the ldap suffix */
946 if (!r->suffix || !*r->suffix) {
947 DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
948 exit(1);
951 if (*ctx && (*ctx)->initialized) {
952 return NT_STATUS_OK;
955 /* Ensure we have an output file */
956 if (ldif_filename) {
957 r->ldif_file = fopen(ldif_filename, "a");
958 } else {
959 r->ldif_file = stdout;
962 if (!r->ldif_file) {
963 fprintf(stderr, "Could not open %s\n", ldif_filename);
964 DEBUG(1, ("Could not open %s\n", ldif_filename));
965 status = NT_STATUS_UNSUCCESSFUL;
966 goto done;
969 r->add_template = talloc_strdup(mem_ctx, add_template);
970 r->mod_template = talloc_strdup(mem_ctx, mod_template);
971 if (!r->add_template || !r->mod_template) {
972 status = NT_STATUS_NO_MEMORY;
973 goto done;
976 r->add_name = talloc_strdup(mem_ctx, add_template);
977 r->module_name = talloc_strdup(mem_ctx, mod_template);
978 if (!r->add_name || !r->module_name) {
979 status = NT_STATUS_NO_MEMORY;
980 goto done;
983 /* Open the add and mod ldif files */
984 if (!(r->add_file = fdopen(mkstemp(r->add_name),"w"))) {
985 DEBUG(1, ("Could not open %s\n", r->add_name));
986 status = NT_STATUS_UNSUCCESSFUL;
987 goto done;
989 if (!(r->mod_file = fdopen(mkstemp(r->module_name),"w"))) {
990 DEBUG(1, ("Could not open %s\n", r->module_name));
991 status = NT_STATUS_UNSUCCESSFUL;
992 goto done;
995 /* Allocate initial memory for groupmap and accountmap arrays */
996 r->groupmap = talloc_zero_array(mem_ctx, GROUPMAP, 8);
997 r->accountmap = talloc_zero_array(mem_ctx, ACCOUNTMAP, 8);
998 if (r->groupmap == NULL || r->accountmap == NULL) {
999 DEBUG(1,("GROUPMAP talloc failed\n"));
1000 status = NT_STATUS_NO_MEMORY;
1001 goto done;
1004 /* Remember how many we malloced */
1005 r->num_alloced = 8;
1007 /* Initial database population */
1008 if (database_id == SAM_DATABASE_DOMAIN) {
1010 status = populate_ldap_for_ldif(domain_sid_str,
1011 r->suffix,
1012 builtin_sid,
1013 r->add_file);
1014 if (!NT_STATUS_IS_OK(status)) {
1015 goto done;
1018 status = map_populate_groups(mem_ctx,
1019 r->groupmap,
1020 r->accountmap,
1021 domain_sid_str,
1022 r->suffix,
1023 builtin_sid);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 goto done;
1029 r->initialized = true;
1031 *ctx = r;
1033 return NT_STATUS_OK;
1034 done:
1035 TALLOC_FREE(r);
1036 return status;
1039 /****************************************************************
1040 ****************************************************************/
1042 static void ldif_free_context(struct samsync_ldif_context *r)
1044 if (!r) {
1045 return;
1048 /* Close and delete the ldif files */
1049 if (r->add_file) {
1050 fclose(r->add_file);
1053 if ((r->add_name != NULL) &&
1054 strcmp(r->add_name, r->add_template) && (unlink(r->add_name))) {
1055 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1056 r->add_name, strerror(errno)));
1059 if (r->mod_file) {
1060 fclose(r->mod_file);
1063 if ((r->module_name != NULL) &&
1064 strcmp(r->module_name, r->mod_template) && (unlink(r->module_name))) {
1065 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1066 r->module_name, strerror(errno)));
1069 if (r->ldif_file && (r->ldif_file != stdout)) {
1070 fclose(r->ldif_file);
1073 TALLOC_FREE(r);
1076 /****************************************************************
1077 ****************************************************************/
1079 static void ldif_write_output(enum netr_SamDatabaseID database_id,
1080 struct samsync_ldif_context *l)
1082 /* Write ldif data to the user's file */
1083 if (database_id == SAM_DATABASE_DOMAIN) {
1084 fprintf(l->ldif_file,
1085 "# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
1086 fprintf(l->ldif_file,
1087 "# =================================\n\n");
1088 fflush(l->ldif_file);
1089 } else if (database_id == SAM_DATABASE_BUILTIN) {
1090 fprintf(l->ldif_file,
1091 "# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
1092 fprintf(l->ldif_file,
1093 "# ==================================\n\n");
1094 fflush(l->ldif_file);
1096 fseek(l->add_file, 0, SEEK_SET);
1097 transfer_file(fileno(l->add_file), fileno(l->ldif_file), (size_t) -1);
1099 if (database_id == SAM_DATABASE_DOMAIN) {
1100 fprintf(l->ldif_file,
1101 "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
1102 fprintf(l->ldif_file,
1103 "# ====================================\n\n");
1104 fflush(l->ldif_file);
1105 } else if (database_id == SAM_DATABASE_BUILTIN) {
1106 fprintf(l->ldif_file,
1107 "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
1108 fprintf(l->ldif_file,
1109 "# =====================================\n\n");
1110 fflush(l->ldif_file);
1112 fseek(l->mod_file, 0, SEEK_SET);
1113 transfer_file(fileno(l->mod_file), fileno(l->ldif_file), (size_t) -1);
1116 /****************************************************************
1117 ****************************************************************/
1119 static NTSTATUS fetch_sam_entry_ldif(TALLOC_CTX *mem_ctx,
1120 enum netr_SamDatabaseID database_id,
1121 struct netr_DELTA_ENUM *r,
1122 struct samsync_context *ctx,
1123 uint32_t *a_index_p,
1124 uint32_t *g_index_p)
1126 union netr_DELTA_UNION u = r->delta_union;
1127 union netr_DELTA_ID_UNION id = r->delta_id_union;
1128 struct samsync_ldif_context *l =
1129 talloc_get_type_abort(ctx->private_data, struct samsync_ldif_context);
1131 switch (r->delta_type) {
1132 case NETR_DELTA_DOMAIN:
1133 break;
1135 case NETR_DELTA_GROUP:
1136 fetch_group_info_to_ldif(mem_ctx,
1137 u.group,
1138 &l->groupmap[*g_index_p],
1139 l->add_file,
1140 ctx->domain_sid_str,
1141 l->suffix);
1142 (*g_index_p)++;
1143 break;
1145 case NETR_DELTA_USER:
1146 fetch_account_info_to_ldif(mem_ctx,
1147 u.user,
1148 l->groupmap,
1149 &l->accountmap[*a_index_p],
1150 l->add_file,
1151 ctx->domain_sid_str,
1152 l->suffix,
1153 l->num_alloced);
1154 (*a_index_p)++;
1155 break;
1157 case NETR_DELTA_ALIAS:
1158 fetch_alias_info_to_ldif(mem_ctx,
1159 u.alias,
1160 &l->groupmap[*g_index_p],
1161 l->add_file,
1162 ctx->domain_sid_str,
1163 l->suffix,
1164 database_id);
1165 (*g_index_p)++;
1166 break;
1168 case NETR_DELTA_GROUP_MEMBER:
1169 fetch_groupmem_info_to_ldif(u.group_member,
1170 id.rid,
1171 l->groupmap,
1172 l->accountmap,
1173 l->mod_file,
1174 l->num_alloced);
1175 break;
1177 case NETR_DELTA_ALIAS_MEMBER:
1178 case NETR_DELTA_POLICY:
1179 case NETR_DELTA_ACCOUNT:
1180 case NETR_DELTA_TRUSTED_DOMAIN:
1181 case NETR_DELTA_SECRET:
1182 case NETR_DELTA_RENAME_GROUP:
1183 case NETR_DELTA_RENAME_USER:
1184 case NETR_DELTA_RENAME_ALIAS:
1185 case NETR_DELTA_DELETE_GROUP:
1186 case NETR_DELTA_DELETE_USER:
1187 case NETR_DELTA_MODIFY_COUNT:
1188 default:
1189 break;
1190 } /* end of switch */
1192 return NT_STATUS_OK;
1195 /****************************************************************
1196 ****************************************************************/
1198 static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx,
1199 struct samsync_ldif_context *l,
1200 uint32_t num_entries)
1202 /* Re-allocate memory for groupmap and accountmap arrays */
1203 l->groupmap = talloc_realloc(mem_ctx,
1204 l->groupmap,
1205 GROUPMAP,
1206 num_entries + l->num_alloced);
1208 l->accountmap = talloc_realloc(mem_ctx,
1209 l->accountmap,
1210 ACCOUNTMAP,
1211 num_entries + l->num_alloced);
1213 if (l->groupmap == NULL || l->accountmap == NULL) {
1214 DEBUG(1,("GROUPMAP talloc failed\n"));
1215 return NT_STATUS_NO_MEMORY;
1218 /* Initialize the new records */
1219 memset(&(l->groupmap[l->num_alloced]), 0,
1220 sizeof(GROUPMAP) * num_entries);
1221 memset(&(l->accountmap[l->num_alloced]), 0,
1222 sizeof(ACCOUNTMAP) * num_entries);
1224 /* Remember how many we alloced this time */
1225 l->num_alloced += num_entries;
1227 return NT_STATUS_OK;
1230 /****************************************************************
1231 ****************************************************************/
1233 static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
1234 struct samsync_context *ctx,
1235 enum netr_SamDatabaseID database_id,
1236 uint64_t *sequence_num)
1238 NTSTATUS status;
1239 struct samsync_ldif_context *ldif_ctx =
1240 (struct samsync_ldif_context *)ctx->private_data;
1242 status = ldif_init_context(mem_ctx,
1243 database_id,
1244 ctx->output_filename,
1245 ctx->domain_sid_str,
1246 &ldif_ctx);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 return status;
1251 ctx->private_data = ldif_ctx;
1253 return NT_STATUS_OK;
1256 /****************************************************************
1257 ****************************************************************/
1259 static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
1260 enum netr_SamDatabaseID database_id,
1261 struct netr_DELTA_ENUM_ARRAY *r,
1262 uint64_t *sequence_num,
1263 struct samsync_context *ctx)
1265 NTSTATUS status;
1266 int i;
1267 struct samsync_ldif_context *ldif_ctx =
1268 (struct samsync_ldif_context *)ctx->private_data;
1270 status = ldif_realloc_maps(mem_ctx, ldif_ctx, r->num_deltas);
1271 if (!NT_STATUS_IS_OK(status)) {
1272 goto failed;
1275 for (i = 0; i < r->num_deltas; i++) {
1276 status = fetch_sam_entry_ldif(mem_ctx, database_id,
1277 &r->delta_enum[i], ctx,
1278 &a_index, &g_index);
1279 if (!NT_STATUS_IS_OK(status)) {
1280 goto failed;
1284 return NT_STATUS_OK;
1286 failed:
1287 ldif_free_context(ldif_ctx);
1288 ctx->private_data = NULL;
1290 return status;
1293 /****************************************************************
1294 ****************************************************************/
1296 static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
1297 struct samsync_context *ctx,
1298 enum netr_SamDatabaseID database_id,
1299 uint64_t sequence_num)
1301 struct samsync_ldif_context *ldif_ctx =
1302 (struct samsync_ldif_context *)ctx->private_data;
1304 /* This was the last query */
1305 ldif_write_output(database_id, ldif_ctx);
1306 if (ldif_ctx->ldif_file != stdout) {
1307 ctx->result_message = talloc_asprintf(ctx,
1308 "Vampired %d accounts and %d groups to %s",
1309 a_index, g_index, ctx->output_filename);
1312 ldif_free_context(ldif_ctx);
1313 ctx->private_data = NULL;
1315 return NT_STATUS_OK;
1318 #else /* HAVE_LDAP */
1320 static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
1321 struct samsync_context *ctx,
1322 enum netr_SamDatabaseID database_id,
1323 uint64_t *sequence_num)
1325 return NT_STATUS_NOT_SUPPORTED;
1328 static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
1329 enum netr_SamDatabaseID database_id,
1330 struct netr_DELTA_ENUM_ARRAY *r,
1331 uint64_t *sequence_num,
1332 struct samsync_context *ctx)
1334 return NT_STATUS_NOT_SUPPORTED;
1337 static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
1338 struct samsync_context *ctx,
1339 enum netr_SamDatabaseID database_id,
1340 uint64_t sequence_num)
1342 return NT_STATUS_NOT_SUPPORTED;
1345 #endif
1347 const struct samsync_ops libnet_samsync_ldif_ops = {
1348 .startup = init_ldif,
1349 .process_objects = fetch_sam_entries_ldif,
1350 .finish = close_ldif,