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