nfs4acl.idl: rename interface to nfs4acl.idl to avoid naming clash in the python...
[Samba.git] / source3 / libnet / libnet_samsync_ldif.c
blobdafeadea3c7724d1aa399827b79889e69e98570a
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"
32 #include "lib/util/base64.h"
34 #ifdef HAVE_LDAP
36 /* uid's and gid's for writing deltas to ldif */
37 static uint32_t ldif_gid = 999;
38 static uint32_t ldif_uid = 999;
40 /* global counters */
41 static uint32_t g_index = 0;
42 static uint32_t a_index = 0;
44 /* Structure for mapping accounts to groups */
45 /* Array element is the group rid */
46 typedef struct _groupmap {
47 uint32_t rid;
48 uint32_t gidNumber;
49 const char *sambaSID;
50 const char *group_dn;
51 } GROUPMAP;
53 typedef struct _accountmap {
54 uint32_t rid;
55 const char *cn;
56 } ACCOUNTMAP;
58 struct samsync_ldif_context {
59 GROUPMAP *groupmap;
60 ACCOUNTMAP *accountmap;
61 bool initialized;
62 const char *add_template;
63 const char *mod_template;
64 char *add_name;
65 char *module_name;
66 FILE *add_file;
67 FILE *mod_file;
68 FILE *ldif_file;
69 const char *suffix;
70 int num_alloced;
74 Returns the substring from src between the first occurrence of
75 the char "front" and the first occurence of the char "back".
76 Mallocs the return string which must be freed. Not for use
77 with wide character strings.
79 static char *sstring_sub(const char *src, char front, char back)
81 char *temp1, *temp2, *temp3;
82 ptrdiff_t len;
84 temp1 = strchr(src, front);
85 if (temp1 == NULL) return NULL;
86 temp2 = strchr(src, back);
87 if (temp2 == NULL) return NULL;
88 len = temp2 - temp1;
89 if (len <= 0) return NULL;
90 temp3 = (char*)SMB_MALLOC(len);
91 if (temp3 == NULL) {
92 DEBUG(1,("Malloc failure in sstring_sub\n"));
93 return NULL;
95 memcpy(temp3, temp1+1, len-1);
96 temp3[len-1] = '\0';
97 return temp3;
100 /****************************************************************
101 ****************************************************************/
103 static NTSTATUS populate_ldap_for_ldif(const char *sid,
104 const char *suffix,
105 const char *builtin_sid,
106 FILE *add_fd)
108 const char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix;
109 char *user_attr=NULL, *group_attr=NULL;
110 char *suffix_attr;
111 int len;
113 /* Get the suffix attribute */
114 suffix_attr = sstring_sub(suffix, '=', ',');
115 if (suffix_attr == NULL) {
116 len = strlen(suffix);
117 suffix_attr = (char*)SMB_MALLOC(len+1);
118 if (!suffix_attr) {
119 return NT_STATUS_NO_MEMORY;
121 memcpy(suffix_attr, suffix, len);
122 suffix_attr[len] = '\0';
125 /* Write the base */
126 fprintf(add_fd, "# %s\n", suffix);
127 fprintf(add_fd, "dn: %s\n", suffix);
128 fprintf(add_fd, "objectClass: dcObject\n");
129 fprintf(add_fd, "objectClass: organization\n");
130 fprintf(add_fd, "o: %s\n", suffix_attr);
131 fprintf(add_fd, "dc: %s\n", suffix_attr);
132 fprintf(add_fd, "\n");
133 fflush(add_fd);
135 user_suffix = lp_ldap_user_suffix(talloc_tos());
136 if (user_suffix == NULL) {
137 SAFE_FREE(suffix_attr);
138 return NT_STATUS_NO_MEMORY;
140 /* If it exists and is distinct from other containers,
141 Write the Users entity */
142 if (*user_suffix && strcmp(user_suffix, suffix)) {
143 user_attr = sstring_sub(lp_ldap_user_suffix(talloc_tos()), '=', ',');
144 fprintf(add_fd, "# %s\n", user_suffix);
145 fprintf(add_fd, "dn: %s\n", user_suffix);
146 fprintf(add_fd, "objectClass: organizationalUnit\n");
147 fprintf(add_fd, "ou: %s\n", user_attr);
148 fprintf(add_fd, "\n");
149 fflush(add_fd);
153 group_suffix = lp_ldap_group_suffix(talloc_tos());
154 if (group_suffix == NULL) {
155 SAFE_FREE(suffix_attr);
156 SAFE_FREE(user_attr);
157 return NT_STATUS_NO_MEMORY;
159 /* If it exists and is distinct from other containers,
160 Write the Groups entity */
161 if (*group_suffix && strcmp(group_suffix, suffix)) {
162 group_attr = sstring_sub(lp_ldap_group_suffix(talloc_tos()), '=', ',');
163 fprintf(add_fd, "# %s\n", group_suffix);
164 fprintf(add_fd, "dn: %s\n", group_suffix);
165 fprintf(add_fd, "objectClass: organizationalUnit\n");
166 fprintf(add_fd, "ou: %s\n", group_attr);
167 fprintf(add_fd, "\n");
168 fflush(add_fd);
171 /* If it exists and is distinct from other containers,
172 Write the Computers entity */
173 machine_suffix = lp_ldap_machine_suffix(talloc_tos());
174 if (machine_suffix == NULL) {
175 SAFE_FREE(suffix_attr);
176 SAFE_FREE(user_attr);
177 SAFE_FREE(group_attr);
178 return NT_STATUS_NO_MEMORY;
180 if (*machine_suffix && strcmp(machine_suffix, user_suffix) &&
181 strcmp(machine_suffix, suffix)) {
182 char *machine_ou = NULL;
183 fprintf(add_fd, "# %s\n", machine_suffix);
184 fprintf(add_fd, "dn: %s\n", machine_suffix);
185 fprintf(add_fd, "objectClass: organizationalUnit\n");
186 /* this isn't totally correct as it assumes that
187 there _must_ be an ou. just fixing memleak now. jmcd */
188 machine_ou = sstring_sub(lp_ldap_machine_suffix(talloc_tos()), '=', ',');
189 fprintf(add_fd, "ou: %s\n", machine_ou);
190 SAFE_FREE(machine_ou);
191 fprintf(add_fd, "\n");
192 fflush(add_fd);
195 /* If it exists and is distinct from other containers,
196 Write the IdMap entity */
197 idmap_suffix = lp_ldap_idmap_suffix(talloc_tos());
198 if (idmap_suffix == NULL) {
199 SAFE_FREE(suffix_attr);
200 SAFE_FREE(user_attr);
201 SAFE_FREE(group_attr);
202 return NT_STATUS_NO_MEMORY;
204 if (*idmap_suffix &&
205 strcmp(idmap_suffix, user_suffix) &&
206 strcmp(idmap_suffix, suffix)) {
207 char *s;
208 fprintf(add_fd, "# %s\n", idmap_suffix);
209 fprintf(add_fd, "dn: %s\n", idmap_suffix);
210 fprintf(add_fd, "ObjectClass: organizationalUnit\n");
211 s = sstring_sub(lp_ldap_idmap_suffix(talloc_tos()), '=', ',');
212 fprintf(add_fd, "ou: %s\n", s);
213 SAFE_FREE(s);
214 fprintf(add_fd, "\n");
215 fflush(add_fd);
218 /* Write the domain entity */
219 fprintf(add_fd, "# %s, %s\n", lp_workgroup(), suffix);
220 fprintf(add_fd, "dn: sambaDomainName=%s,%s\n", lp_workgroup(),
221 suffix);
222 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_DOMINFO);
223 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_IDPOOL);
224 fprintf(add_fd, "sambaDomainName: %s\n", lp_workgroup());
225 fprintf(add_fd, "sambaSID: %s\n", sid);
226 fprintf(add_fd, "uidNumber: %d\n", ++ldif_uid);
227 fprintf(add_fd, "gidNumber: %d\n", ++ldif_gid);
228 fprintf(add_fd, "\n");
229 fflush(add_fd);
231 /* Write the Domain Admins entity */
232 fprintf(add_fd, "# Domain Admins, %s, %s\n", group_attr,
233 suffix);
234 fprintf(add_fd, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr,
235 suffix);
236 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
237 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
238 fprintf(add_fd, "cn: Domain Admins\n");
239 fprintf(add_fd, "memberUid: Administrator\n");
240 fprintf(add_fd, "description: Netbios Domain Administrators\n");
241 fprintf(add_fd, "gidNumber: 512\n");
242 fprintf(add_fd, "sambaSID: %s-512\n", sid);
243 fprintf(add_fd, "sambaGroupType: 2\n");
244 fprintf(add_fd, "displayName: Domain Admins\n");
245 fprintf(add_fd, "\n");
246 fflush(add_fd);
248 /* Write the Domain Users entity */
249 fprintf(add_fd, "# Domain Users, %s, %s\n", group_attr,
250 suffix);
251 fprintf(add_fd, "dn: cn=Domain Users,ou=%s,%s\n", group_attr,
252 suffix);
253 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
254 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
255 fprintf(add_fd, "cn: Domain Users\n");
256 fprintf(add_fd, "description: Netbios Domain Users\n");
257 fprintf(add_fd, "gidNumber: 513\n");
258 fprintf(add_fd, "sambaSID: %s-513\n", sid);
259 fprintf(add_fd, "sambaGroupType: 2\n");
260 fprintf(add_fd, "displayName: Domain Users\n");
261 fprintf(add_fd, "\n");
262 fflush(add_fd);
264 /* Write the Domain Guests entity */
265 fprintf(add_fd, "# Domain Guests, %s, %s\n", group_attr,
266 suffix);
267 fprintf(add_fd, "dn: cn=Domain Guests,ou=%s,%s\n", group_attr,
268 suffix);
269 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
270 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
271 fprintf(add_fd, "cn: Domain Guests\n");
272 fprintf(add_fd, "description: Netbios Domain Guests\n");
273 fprintf(add_fd, "gidNumber: 514\n");
274 fprintf(add_fd, "sambaSID: %s-514\n", sid);
275 fprintf(add_fd, "sambaGroupType: 2\n");
276 fprintf(add_fd, "displayName: Domain Guests\n");
277 fprintf(add_fd, "\n");
278 fflush(add_fd);
280 /* Write the Domain Computers entity */
281 fprintf(add_fd, "# Domain Computers, %s, %s\n", group_attr,
282 suffix);
283 fprintf(add_fd, "dn: cn=Domain Computers,ou=%s,%s\n",
284 group_attr, suffix);
285 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
286 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
287 fprintf(add_fd, "gidNumber: 515\n");
288 fprintf(add_fd, "cn: Domain Computers\n");
289 fprintf(add_fd, "description: Netbios Domain Computers accounts\n");
290 fprintf(add_fd, "sambaSID: %s-515\n", sid);
291 fprintf(add_fd, "sambaGroupType: 2\n");
292 fprintf(add_fd, "displayName: Domain Computers\n");
293 fprintf(add_fd, "\n");
294 fflush(add_fd);
296 /* Write the Admininistrators Groups entity */
297 fprintf(add_fd, "# Administrators, %s, %s\n", group_attr,
298 suffix);
299 fprintf(add_fd, "dn: cn=Administrators,ou=%s,%s\n", group_attr,
300 suffix);
301 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
302 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
303 fprintf(add_fd, "gidNumber: 544\n");
304 fprintf(add_fd, "cn: Administrators\n");
305 fprintf(add_fd, "description: Netbios Domain Members can fully administer the computer/sambaDomainName\n");
306 fprintf(add_fd, "sambaSID: %s-544\n", builtin_sid);
307 fprintf(add_fd, "sambaGroupType: 5\n");
308 fprintf(add_fd, "displayName: Administrators\n");
309 fprintf(add_fd, "\n");
311 /* Write the Print Operator entity */
312 fprintf(add_fd, "# Print Operators, %s, %s\n", group_attr,
313 suffix);
314 fprintf(add_fd, "dn: cn=Print Operators,ou=%s,%s\n",
315 group_attr, suffix);
316 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
317 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
318 fprintf(add_fd, "gidNumber: 550\n");
319 fprintf(add_fd, "cn: Print Operators\n");
320 fprintf(add_fd, "description: Netbios Domain Print Operators\n");
321 fprintf(add_fd, "sambaSID: %s-550\n", builtin_sid);
322 fprintf(add_fd, "sambaGroupType: 5\n");
323 fprintf(add_fd, "displayName: Print Operators\n");
324 fprintf(add_fd, "\n");
325 fflush(add_fd);
327 /* Write the Backup Operators entity */
328 fprintf(add_fd, "# Backup Operators, %s, %s\n", group_attr,
329 suffix);
330 fprintf(add_fd, "dn: cn=Backup Operators,ou=%s,%s\n",
331 group_attr, suffix);
332 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
333 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
334 fprintf(add_fd, "gidNumber: 551\n");
335 fprintf(add_fd, "cn: Backup Operators\n");
336 fprintf(add_fd, "description: Netbios Domain Members can bypass file security to back up files\n");
337 fprintf(add_fd, "sambaSID: %s-551\n", builtin_sid);
338 fprintf(add_fd, "sambaGroupType: 5\n");
339 fprintf(add_fd, "displayName: Backup Operators\n");
340 fprintf(add_fd, "\n");
341 fflush(add_fd);
343 /* Write the Replicators entity */
344 fprintf(add_fd, "# Replicators, %s, %s\n", group_attr, suffix);
345 fprintf(add_fd, "dn: cn=Replicators,ou=%s,%s\n", group_attr,
346 suffix);
347 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
348 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
349 fprintf(add_fd, "gidNumber: 552\n");
350 fprintf(add_fd, "cn: Replicators\n");
351 fprintf(add_fd, "description: Netbios Domain Supports file replication in a sambaDomainName\n");
352 fprintf(add_fd, "sambaSID: %s-552\n", builtin_sid);
353 fprintf(add_fd, "sambaGroupType: 5\n");
354 fprintf(add_fd, "displayName: Replicators\n");
355 fprintf(add_fd, "\n");
356 fflush(add_fd);
358 /* Deallocate memory, and return */
359 SAFE_FREE(suffix_attr);
360 SAFE_FREE(user_attr);
361 SAFE_FREE(group_attr);
362 return NT_STATUS_OK;
365 /****************************************************************
366 ****************************************************************/
368 static NTSTATUS map_populate_groups(TALLOC_CTX *mem_ctx,
369 GROUPMAP *groupmap,
370 ACCOUNTMAP *accountmap,
371 const char *sid,
372 const char *suffix,
373 const char *builtin_sid)
375 char *group_attr = sstring_sub(lp_ldap_group_suffix(talloc_tos()), '=', ',');
377 /* Map the groups created by populate_ldap_for_ldif */
378 groupmap[0].rid = 512;
379 groupmap[0].gidNumber = 512;
380 groupmap[0].sambaSID = talloc_asprintf(mem_ctx, "%s-512", sid);
381 groupmap[0].group_dn = talloc_asprintf(mem_ctx,
382 "cn=Domain Admins,ou=%s,%s", group_attr, suffix);
383 if (groupmap[0].sambaSID == NULL || groupmap[0].group_dn == NULL) {
384 goto err;
387 accountmap[0].rid = 512;
388 accountmap[0].cn = talloc_strdup(mem_ctx, "Domain Admins");
389 if (accountmap[0].cn == NULL) {
390 goto err;
393 groupmap[1].rid = 513;
394 groupmap[1].gidNumber = 513;
395 groupmap[1].sambaSID = talloc_asprintf(mem_ctx, "%s-513", sid);
396 groupmap[1].group_dn = talloc_asprintf(mem_ctx,
397 "cn=Domain Users,ou=%s,%s", group_attr, suffix);
398 if (groupmap[1].sambaSID == NULL || groupmap[1].group_dn == NULL) {
399 goto err;
402 accountmap[1].rid = 513;
403 accountmap[1].cn = talloc_strdup(mem_ctx, "Domain Users");
404 if (accountmap[1].cn == NULL) {
405 goto err;
408 groupmap[2].rid = 514;
409 groupmap[2].gidNumber = 514;
410 groupmap[2].sambaSID = talloc_asprintf(mem_ctx, "%s-514", sid);
411 groupmap[2].group_dn = talloc_asprintf(mem_ctx,
412 "cn=Domain Guests,ou=%s,%s", group_attr, suffix);
413 if (groupmap[2].sambaSID == NULL || groupmap[2].group_dn == NULL) {
414 goto err;
417 accountmap[2].rid = 514;
418 accountmap[2].cn = talloc_strdup(mem_ctx, "Domain Guests");
419 if (accountmap[2].cn == NULL) {
420 goto err;
423 groupmap[3].rid = 515;
424 groupmap[3].gidNumber = 515;
425 groupmap[3].sambaSID = talloc_asprintf(mem_ctx, "%s-515", sid);
426 groupmap[3].group_dn = talloc_asprintf(mem_ctx,
427 "cn=Domain Computers,ou=%s,%s", group_attr, suffix);
428 if (groupmap[3].sambaSID == NULL || groupmap[3].group_dn == NULL) {
429 goto err;
432 accountmap[3].rid = 515;
433 accountmap[3].cn = talloc_strdup(mem_ctx, "Domain Computers");
434 if (accountmap[3].cn == NULL) {
435 goto err;
438 groupmap[4].rid = 544;
439 groupmap[4].gidNumber = 544;
440 groupmap[4].sambaSID = talloc_asprintf(mem_ctx, "%s-544", builtin_sid);
441 groupmap[4].group_dn = talloc_asprintf(mem_ctx,
442 "cn=Administrators,ou=%s,%s", group_attr, suffix);
443 if (groupmap[4].sambaSID == NULL || groupmap[4].group_dn == NULL) {
444 goto err;
447 accountmap[4].rid = 515;
448 accountmap[4].cn = talloc_strdup(mem_ctx, "Administrators");
449 if (accountmap[4].cn == NULL) {
450 goto err;
453 groupmap[5].rid = 550;
454 groupmap[5].gidNumber = 550;
455 groupmap[5].sambaSID = talloc_asprintf(mem_ctx, "%s-550", builtin_sid);
456 groupmap[5].group_dn = talloc_asprintf(mem_ctx,
457 "cn=Print Operators,ou=%s,%s", group_attr, suffix);
458 if (groupmap[5].sambaSID == NULL || groupmap[5].group_dn == NULL) {
459 goto err;
462 accountmap[5].rid = 550;
463 accountmap[5].cn = talloc_strdup(mem_ctx, "Print Operators");
464 if (accountmap[5].cn == NULL) {
465 goto err;
468 groupmap[6].rid = 551;
469 groupmap[6].gidNumber = 551;
470 groupmap[6].sambaSID = talloc_asprintf(mem_ctx, "%s-551", builtin_sid);
471 groupmap[6].group_dn = talloc_asprintf(mem_ctx,
472 "cn=Backup Operators,ou=%s,%s", group_attr, suffix);
473 if (groupmap[6].sambaSID == NULL || groupmap[6].group_dn == NULL) {
474 goto err;
477 accountmap[6].rid = 551;
478 accountmap[6].cn = talloc_strdup(mem_ctx, "Backup Operators");
479 if (accountmap[6].cn == NULL) {
480 goto err;
483 groupmap[7].rid = 552;
484 groupmap[7].gidNumber = 552;
485 groupmap[7].sambaSID = talloc_asprintf(mem_ctx, "%s-552", builtin_sid);
486 groupmap[7].group_dn = talloc_asprintf(mem_ctx,
487 "cn=Replicators,ou=%s,%s", group_attr, suffix);
488 if (groupmap[7].sambaSID == NULL || groupmap[7].group_dn == NULL) {
489 goto err;
492 accountmap[7].rid = 551;
493 accountmap[7].cn = talloc_strdup(mem_ctx, "Replicators");
494 if (accountmap[7].cn == NULL) {
495 goto err;
498 SAFE_FREE(group_attr);
500 return NT_STATUS_OK;
502 err:
504 SAFE_FREE(group_attr);
505 return NT_STATUS_NO_MEMORY;
509 * This is a crap routine, but I think it's the quickest way to solve the
510 * UTF8->base64 problem.
513 static int fprintf_attr(FILE *add_fd, const char *attr_name,
514 const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
516 static int fprintf_attr(FILE *add_fd, const char *attr_name,
517 const char *fmt, ...)
519 va_list ap;
520 char *value, *p, *base64;
521 DATA_BLOB base64_blob;
522 bool do_base64 = false;
523 int res;
525 va_start(ap, fmt);
526 value = talloc_vasprintf(NULL, fmt, ap);
527 va_end(ap);
529 SMB_ASSERT(value != NULL);
531 for (p=value; *p; p++) {
532 if (*p & 0x80) {
533 do_base64 = true;
534 break;
538 if (!do_base64) {
539 bool only_whitespace = true;
540 for (p=value; *p; p++) {
542 * I know that this not multibyte safe, but we break
543 * on the first non-whitespace character anyway.
545 if (!isspace(*p)) {
546 only_whitespace = false;
547 break;
550 if (only_whitespace) {
551 do_base64 = true;
555 if (!do_base64) {
556 res = fprintf(add_fd, "%s: %s\n", attr_name, value);
557 TALLOC_FREE(value);
558 return res;
561 base64_blob.data = (unsigned char *)value;
562 base64_blob.length = strlen(value);
564 base64 = base64_encode_data_blob(value, base64_blob);
565 SMB_ASSERT(base64 != NULL);
567 res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
568 TALLOC_FREE(value);
569 return res;
572 /****************************************************************
573 ****************************************************************/
575 static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx,
576 struct netr_DELTA_GROUP *r,
577 GROUPMAP *groupmap,
578 FILE *add_fd,
579 const char *sid,
580 const char *suffix)
582 const char *groupname = r->group_name.string;
583 uint32_t grouptype = 0, g_rid = 0;
584 char *group_attr = sstring_sub(lp_ldap_group_suffix(talloc_tos()), '=', ',');
586 /* Set up the group type (always 2 for group info) */
587 grouptype = 2;
589 /* These groups are entered by populate_ldap_for_ldif */
590 if (strcmp(groupname, "Domain Admins") == 0 ||
591 strcmp(groupname, "Domain Users") == 0 ||
592 strcmp(groupname, "Domain Guests") == 0 ||
593 strcmp(groupname, "Domain Computers") == 0 ||
594 strcmp(groupname, "Administrators") == 0 ||
595 strcmp(groupname, "Print Operators") == 0 ||
596 strcmp(groupname, "Backup Operators") == 0 ||
597 strcmp(groupname, "Replicators") == 0) {
598 SAFE_FREE(group_attr);
599 return NT_STATUS_OK;
600 } else {
601 /* Increment the gid for the new group */
602 ldif_gid++;
605 /* Map the group rid, gid, and dn */
606 g_rid = r->rid;
607 groupmap->rid = g_rid;
608 groupmap->gidNumber = ldif_gid;
609 groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
610 groupmap->group_dn = talloc_asprintf(mem_ctx,
611 "cn=%s,ou=%s,%s", groupname, group_attr, suffix);
612 if (groupmap->sambaSID == NULL || groupmap->group_dn == NULL) {
613 SAFE_FREE(group_attr);
614 return NT_STATUS_NO_MEMORY;
617 /* Write the data to the temporary add ldif file */
618 fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr,
619 suffix);
620 fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", groupname, group_attr,
621 suffix);
622 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
623 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
624 fprintf_attr(add_fd, "cn", "%s", groupname);
625 fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
626 fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
627 fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
628 fprintf_attr(add_fd, "displayName", "%s", groupname);
629 fprintf(add_fd, "\n");
630 fflush(add_fd);
632 SAFE_FREE(group_attr);
633 /* Return */
634 return NT_STATUS_OK;
637 /****************************************************************
638 ****************************************************************/
640 static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx,
641 struct netr_DELTA_USER *r,
642 GROUPMAP *groupmap,
643 ACCOUNTMAP *accountmap,
644 FILE *add_fd,
645 const char *sid,
646 const char *suffix,
647 int alloced)
649 fstring username, logonscript, homedrive, homepath = "", homedir = "";
650 fstring hex_nt_passwd, hex_lm_passwd;
651 fstring description, profilepath, fullname, sambaSID;
652 char *flags, *user_rdn;
653 const char *ou;
654 const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
655 uchar zero_buf[16];
656 uint32_t rid = 0, group_rid = 0, gidNumber = 0;
657 time_t unix_time;
658 int i, ret;
660 memset(zero_buf, '\0', sizeof(zero_buf));
662 /* Get the username */
663 fstrcpy(username, r->account_name.string);
665 /* Get the rid */
666 rid = r->rid;
668 /* Map the rid and username for group member info later */
669 accountmap->rid = rid;
670 accountmap->cn = talloc_strdup(mem_ctx, username);
671 NT_STATUS_HAVE_NO_MEMORY(accountmap->cn);
673 /* Get the home directory */
674 if (r->acct_flags & ACB_NORMAL) {
675 fstrcpy(homedir, r->home_directory.string);
676 if (!*homedir) {
677 snprintf(homedir, sizeof(homedir), "/home/%s", username);
678 } else {
679 snprintf(homedir, sizeof(homedir), "/nobodyshomedir");
681 ou = lp_ldap_user_suffix(talloc_tos());
682 } else {
683 ou = lp_ldap_machine_suffix(talloc_tos());
684 snprintf(homedir, sizeof(homedir), "/machinehomedir");
687 /* Get the logon script */
688 fstrcpy(logonscript, r->logon_script.string);
690 /* Get the home drive */
691 fstrcpy(homedrive, r->home_drive.string);
693 /* Get the home path */
694 fstrcpy(homepath, r->home_directory.string);
696 /* Get the description */
697 fstrcpy(description, r->description.string);
699 /* Get the display name */
700 fstrcpy(fullname, r->full_name.string);
702 /* Get the profile path */
703 fstrcpy(profilepath, r->profile_path.string);
705 /* Get lm and nt password data */
706 if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
707 pdb_sethexpwd(hex_lm_passwd, r->lmpassword.hash, r->acct_flags);
708 } else {
709 pdb_sethexpwd(hex_lm_passwd, NULL, 0);
711 if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
712 pdb_sethexpwd(hex_nt_passwd, r->ntpassword.hash, r->acct_flags);
713 } else {
714 pdb_sethexpwd(hex_nt_passwd, NULL, 0);
716 unix_time = nt_time_to_unix(r->last_password_change);
718 /* Increment the uid for the new user */
719 ldif_uid++;
721 /* Set up group id and sambaSID for the user */
722 group_rid = r->primary_gid;
723 for (i=0; i<alloced; i++) {
724 if (groupmap[i].rid == group_rid) break;
726 if (i == alloced){
727 DEBUG(1, ("Could not find rid %d in groupmap array\n",
728 group_rid));
729 return NT_STATUS_UNSUCCESSFUL;
731 gidNumber = groupmap[i].gidNumber;
732 ret = snprintf(sambaSID, sizeof(sambaSID), "%s", groupmap[i].sambaSID);
733 if (ret < 0 || ret == sizeof(sambaSID)) {
734 return NT_STATUS_UNSUCCESSFUL;
737 /* Set up sambaAcctFlags */
738 flags = pdb_encode_acct_ctrl(r->acct_flags,
739 NEW_PW_FORMAT_SPACE_PADDED_LEN);
741 /* Add the user to the temporary add ldif file */
742 /* this isn't quite right...we can't assume there's just OU=. jmcd */
743 user_rdn = sstring_sub(ou, '=', ',');
744 fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
745 fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
746 suffix);
747 SAFE_FREE(user_rdn);
748 fprintf(add_fd, "ObjectClass: top\n");
749 fprintf(add_fd, "objectClass: inetOrgPerson\n");
750 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT);
751 fprintf(add_fd, "objectClass: shadowAccount\n");
752 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT);
753 fprintf_attr(add_fd, "cn", "%s", username);
754 fprintf_attr(add_fd, "sn", "%s", username);
755 fprintf_attr(add_fd, "uid", "%s", username);
756 fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
757 fprintf(add_fd, "gidNumber: %d\n", gidNumber);
758 fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
759 if (*homepath)
760 fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
761 if (*homedrive)
762 fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
763 if (*logonscript)
764 fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
765 fprintf(add_fd, "loginShell: %s\n",
766 ((r->acct_flags & ACB_NORMAL) ?
767 "/bin/bash" : "/bin/false"));
768 fprintf(add_fd, "gecos: System User\n");
769 if (*description)
770 fprintf_attr(add_fd, "description", "%s", description);
771 fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
772 fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
773 if(*fullname)
774 fprintf_attr(add_fd, "displayName", "%s", fullname);
775 if(*profilepath)
776 fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
777 if (strcmp(nopasswd, hex_lm_passwd) != 0)
778 fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
779 if (strcmp(nopasswd, hex_nt_passwd) != 0)
780 fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd);
781 fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time);
782 fprintf(add_fd, "sambaAcctFlags: %s\n", flags);
783 fprintf(add_fd, "\n");
784 fflush(add_fd);
786 /* Return */
787 return NT_STATUS_OK;
790 /****************************************************************
791 ****************************************************************/
793 static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx,
794 struct netr_DELTA_ALIAS *r,
795 GROUPMAP *groupmap,
796 FILE *add_fd,
797 const char *sid,
798 const char *suffix,
799 enum netr_SamDatabaseID database_id)
801 fstring aliasname, description;
802 uint32_t grouptype = 0, g_rid = 0;
803 char *group_attr = sstring_sub(lp_ldap_group_suffix(talloc_tos()), '=', ',');
805 /* Get the alias name */
806 fstrcpy(aliasname, r->alias_name.string);
808 /* Get the alias description */
809 fstrcpy(description, r->description.string);
811 /* Set up the group type */
812 switch (database_id) {
813 case SAM_DATABASE_DOMAIN:
814 grouptype = 4;
815 break;
816 case SAM_DATABASE_BUILTIN:
817 grouptype = 5;
818 break;
819 default:
820 grouptype = 4;
821 break;
825 These groups are entered by populate_ldap_for_ldif
826 Note that populate creates a group called Relicators,
827 but NT returns a group called Replicator
829 if (strcmp(aliasname, "Domain Admins") == 0 ||
830 strcmp(aliasname, "Domain Users") == 0 ||
831 strcmp(aliasname, "Domain Guests") == 0 ||
832 strcmp(aliasname, "Domain Computers") == 0 ||
833 strcmp(aliasname, "Administrators") == 0 ||
834 strcmp(aliasname, "Print Operators") == 0 ||
835 strcmp(aliasname, "Backup Operators") == 0 ||
836 strcmp(aliasname, "Replicator") == 0) {
837 SAFE_FREE(group_attr);
838 return NT_STATUS_OK;
839 } else {
840 /* Increment the gid for the new group */
841 ldif_gid++;
844 /* Map the group rid and gid */
845 g_rid = r->rid;
846 groupmap->gidNumber = ldif_gid;
847 groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
848 if (groupmap->sambaSID == NULL) {
849 SAFE_FREE(group_attr);
850 return NT_STATUS_NO_MEMORY;
853 /* Write the data to the temporary add ldif file */
854 fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr,
855 suffix);
856 fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", aliasname, group_attr,
857 suffix);
858 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
859 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
860 fprintf(add_fd, "cn: %s\n", aliasname);
861 fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
862 fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
863 fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
864 fprintf_attr(add_fd, "displayName", "%s", aliasname);
865 if (description[0])
866 fprintf_attr(add_fd, "description", "%s", description);
867 fprintf(add_fd, "\n");
868 fflush(add_fd);
870 SAFE_FREE(group_attr);
871 /* Return */
872 return NT_STATUS_OK;
875 /****************************************************************
876 ****************************************************************/
878 static NTSTATUS fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER *r,
879 uint32_t id_rid,
880 GROUPMAP *groupmap,
881 ACCOUNTMAP *accountmap,
882 FILE *mod_fd, int alloced)
884 fstring group_dn;
885 uint32_t group_rid = 0, rid = 0;
886 int i, j, k;
888 /* Get the dn for the group */
889 if (r->num_rids > 0) {
890 group_rid = id_rid;
891 for (j=0; j<alloced; j++) {
892 if (groupmap[j].rid == group_rid) break;
894 if (j == alloced){
895 DEBUG(1, ("Could not find rid %d in groupmap array\n",
896 group_rid));
897 return NT_STATUS_UNSUCCESSFUL;
899 snprintf(group_dn, sizeof(group_dn), "%s", groupmap[j].group_dn);
900 fprintf(mod_fd, "dn: %s\n", group_dn);
902 /* Get the cn for each member */
903 for (i=0; i < r->num_rids; i++) {
904 rid = r->rids[i];
905 for (k=0; k<alloced; k++) {
906 if (accountmap[k].rid == rid) break;
908 if (k == alloced){
909 DEBUG(1, ("Could not find rid %d in "
910 "accountmap array\n", rid));
911 return NT_STATUS_UNSUCCESSFUL;
913 fprintf(mod_fd, "memberUid: %s\n", accountmap[k].cn);
915 fprintf(mod_fd, "\n");
917 fflush(mod_fd);
919 /* Return */
920 return NT_STATUS_OK;
923 /****************************************************************
924 ****************************************************************/
926 static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx,
927 enum netr_SamDatabaseID database_id,
928 const char *ldif_filename,
929 const char *domain_sid_str,
930 struct samsync_ldif_context **ctx)
932 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
933 struct samsync_ldif_context *r;
934 const char *add_template = "/tmp/add.ldif.XXXXXX";
935 const char *mod_template = "/tmp/mod.ldif.XXXXXX";
936 const char *builtin_sid = "S-1-5-32";
937 mode_t mask;
938 int fd;
940 r = talloc_zero(mem_ctx, struct samsync_ldif_context);
941 NT_STATUS_HAVE_NO_MEMORY(r);
943 /* Get the ldap suffix */
944 r->suffix = lp_ldap_suffix(talloc_tos());
946 /* Get other smb.conf data */
947 if (!(lp_workgroup()) || !*(lp_workgroup())) {
948 DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
949 exit(1);
952 /* Get the ldap suffix */
953 if (!r->suffix || !*r->suffix) {
954 DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
955 exit(1);
958 if (*ctx && (*ctx)->initialized) {
959 return NT_STATUS_OK;
962 /* Ensure we have an output file */
963 if (ldif_filename) {
964 r->ldif_file = fopen(ldif_filename, "a");
965 } else {
966 r->ldif_file = stdout;
969 if (!r->ldif_file) {
970 fprintf(stderr, "Could not open %s\n", ldif_filename);
971 DEBUG(1, ("Could not open %s\n", ldif_filename));
972 status = NT_STATUS_UNSUCCESSFUL;
973 goto done;
976 r->add_template = talloc_strdup(mem_ctx, add_template);
977 r->mod_template = talloc_strdup(mem_ctx, mod_template);
978 if (!r->add_template || !r->mod_template) {
979 status = NT_STATUS_NO_MEMORY;
980 goto done;
983 r->add_name = talloc_strdup(mem_ctx, add_template);
984 r->module_name = talloc_strdup(mem_ctx, mod_template);
985 if (!r->add_name || !r->module_name) {
986 status = NT_STATUS_NO_MEMORY;
987 goto done;
990 mask = umask(S_IRWXO | S_IRWXG);
991 fd = mkstemp(r->add_name);
992 umask(mask);
993 if (fd < 0) {
994 DEBUG(1, ("Could not create %s\n", r->add_name));
995 status = NT_STATUS_UNSUCCESSFUL;
996 goto done;
999 /* Open the add and mod ldif files */
1000 r->add_file = fdopen(fd, "w");
1001 if (r->add_file == NULL) {
1002 DEBUG(1, ("Could not open %s\n", r->add_name));
1003 close(fd);
1004 status = NT_STATUS_UNSUCCESSFUL;
1005 goto done;
1008 mask = umask(S_IRWXO | S_IRWXG);
1009 fd = mkstemp(r->module_name);
1010 umask(mask);
1011 if (fd < 0) {
1012 DEBUG(1, ("Could not create %s\n", r->module_name));
1013 status = NT_STATUS_UNSUCCESSFUL;
1014 goto done;
1017 r->mod_file = fdopen(fd, "w");
1018 if (r->mod_file == NULL) {
1019 DEBUG(1, ("Could not open %s\n", r->module_name));
1020 close(fd);
1021 status = NT_STATUS_UNSUCCESSFUL;
1022 goto done;
1025 /* Allocate initial memory for groupmap and accountmap arrays */
1026 r->groupmap = talloc_zero_array(mem_ctx, GROUPMAP, 8);
1027 r->accountmap = talloc_zero_array(mem_ctx, ACCOUNTMAP, 8);
1028 if (r->groupmap == NULL || r->accountmap == NULL) {
1029 DEBUG(1,("GROUPMAP talloc failed\n"));
1030 status = NT_STATUS_NO_MEMORY;
1031 goto done;
1034 /* Remember how many we malloced */
1035 r->num_alloced = 8;
1037 /* Initial database population */
1038 if (database_id == SAM_DATABASE_DOMAIN) {
1040 status = populate_ldap_for_ldif(domain_sid_str,
1041 r->suffix,
1042 builtin_sid,
1043 r->add_file);
1044 if (!NT_STATUS_IS_OK(status)) {
1045 goto done;
1048 status = map_populate_groups(mem_ctx,
1049 r->groupmap,
1050 r->accountmap,
1051 domain_sid_str,
1052 r->suffix,
1053 builtin_sid);
1054 if (!NT_STATUS_IS_OK(status)) {
1055 goto done;
1059 r->initialized = true;
1061 *ctx = r;
1063 return NT_STATUS_OK;
1064 done:
1065 TALLOC_FREE(r);
1066 return status;
1069 /****************************************************************
1070 ****************************************************************/
1072 static void ldif_free_context(struct samsync_ldif_context *r)
1074 if (!r) {
1075 return;
1078 /* Close and delete the ldif files */
1079 if (r->add_file) {
1080 fclose(r->add_file);
1083 if ((r->add_name != NULL) &&
1084 strcmp(r->add_name, r->add_template) && (unlink(r->add_name))) {
1085 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1086 r->add_name, strerror(errno)));
1089 if (r->mod_file) {
1090 fclose(r->mod_file);
1093 if ((r->module_name != NULL) &&
1094 strcmp(r->module_name, r->mod_template) && (unlink(r->module_name))) {
1095 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1096 r->module_name, strerror(errno)));
1099 if (r->ldif_file && (r->ldif_file != stdout)) {
1100 fclose(r->ldif_file);
1103 TALLOC_FREE(r);
1106 /****************************************************************
1107 ****************************************************************/
1109 static void ldif_write_output(enum netr_SamDatabaseID database_id,
1110 struct samsync_ldif_context *l)
1112 /* Write ldif data to the user's file */
1113 if (database_id == SAM_DATABASE_DOMAIN) {
1114 fprintf(l->ldif_file,
1115 "# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
1116 fprintf(l->ldif_file,
1117 "# =================================\n\n");
1118 fflush(l->ldif_file);
1119 } else if (database_id == SAM_DATABASE_BUILTIN) {
1120 fprintf(l->ldif_file,
1121 "# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
1122 fprintf(l->ldif_file,
1123 "# ==================================\n\n");
1124 fflush(l->ldif_file);
1126 fseek(l->add_file, 0, SEEK_SET);
1127 transfer_file(fileno(l->add_file), fileno(l->ldif_file), (size_t) -1);
1129 if (database_id == SAM_DATABASE_DOMAIN) {
1130 fprintf(l->ldif_file,
1131 "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
1132 fprintf(l->ldif_file,
1133 "# ====================================\n\n");
1134 fflush(l->ldif_file);
1135 } else if (database_id == SAM_DATABASE_BUILTIN) {
1136 fprintf(l->ldif_file,
1137 "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
1138 fprintf(l->ldif_file,
1139 "# =====================================\n\n");
1140 fflush(l->ldif_file);
1142 fseek(l->mod_file, 0, SEEK_SET);
1143 transfer_file(fileno(l->mod_file), fileno(l->ldif_file), (size_t) -1);
1146 /****************************************************************
1147 ****************************************************************/
1149 static NTSTATUS fetch_sam_entry_ldif(TALLOC_CTX *mem_ctx,
1150 enum netr_SamDatabaseID database_id,
1151 struct netr_DELTA_ENUM *r,
1152 struct samsync_context *ctx,
1153 uint32_t *a_index_p,
1154 uint32_t *g_index_p)
1156 union netr_DELTA_UNION u = r->delta_union;
1157 union netr_DELTA_ID_UNION id = r->delta_id_union;
1158 struct samsync_ldif_context *l =
1159 talloc_get_type_abort(ctx->private_data, struct samsync_ldif_context);
1161 switch (r->delta_type) {
1162 case NETR_DELTA_DOMAIN:
1163 break;
1165 case NETR_DELTA_GROUP:
1166 fetch_group_info_to_ldif(mem_ctx,
1167 u.group,
1168 &l->groupmap[*g_index_p],
1169 l->add_file,
1170 ctx->domain_sid_str,
1171 l->suffix);
1172 (*g_index_p)++;
1173 break;
1175 case NETR_DELTA_USER:
1176 fetch_account_info_to_ldif(mem_ctx,
1177 u.user,
1178 l->groupmap,
1179 &l->accountmap[*a_index_p],
1180 l->add_file,
1181 ctx->domain_sid_str,
1182 l->suffix,
1183 l->num_alloced);
1184 (*a_index_p)++;
1185 break;
1187 case NETR_DELTA_ALIAS:
1188 fetch_alias_info_to_ldif(mem_ctx,
1189 u.alias,
1190 &l->groupmap[*g_index_p],
1191 l->add_file,
1192 ctx->domain_sid_str,
1193 l->suffix,
1194 database_id);
1195 (*g_index_p)++;
1196 break;
1198 case NETR_DELTA_GROUP_MEMBER:
1199 fetch_groupmem_info_to_ldif(u.group_member,
1200 id.rid,
1201 l->groupmap,
1202 l->accountmap,
1203 l->mod_file,
1204 l->num_alloced);
1205 break;
1207 case NETR_DELTA_ALIAS_MEMBER:
1208 case NETR_DELTA_POLICY:
1209 case NETR_DELTA_ACCOUNT:
1210 case NETR_DELTA_TRUSTED_DOMAIN:
1211 case NETR_DELTA_SECRET:
1212 case NETR_DELTA_RENAME_GROUP:
1213 case NETR_DELTA_RENAME_USER:
1214 case NETR_DELTA_RENAME_ALIAS:
1215 case NETR_DELTA_DELETE_GROUP:
1216 case NETR_DELTA_DELETE_USER:
1217 case NETR_DELTA_MODIFY_COUNT:
1218 default:
1219 break;
1220 } /* end of switch */
1222 return NT_STATUS_OK;
1225 /****************************************************************
1226 ****************************************************************/
1228 static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx,
1229 struct samsync_ldif_context *l,
1230 uint32_t num_entries)
1232 /* Re-allocate memory for groupmap and accountmap arrays */
1233 l->groupmap = talloc_realloc(mem_ctx,
1234 l->groupmap,
1235 GROUPMAP,
1236 num_entries + l->num_alloced);
1238 l->accountmap = talloc_realloc(mem_ctx,
1239 l->accountmap,
1240 ACCOUNTMAP,
1241 num_entries + l->num_alloced);
1243 if (l->groupmap == NULL || l->accountmap == NULL) {
1244 DEBUG(1,("GROUPMAP talloc failed\n"));
1245 return NT_STATUS_NO_MEMORY;
1248 /* Initialize the new records */
1249 memset(&(l->groupmap[l->num_alloced]), 0,
1250 sizeof(GROUPMAP) * num_entries);
1251 memset(&(l->accountmap[l->num_alloced]), 0,
1252 sizeof(ACCOUNTMAP) * num_entries);
1254 /* Remember how many we alloced this time */
1255 l->num_alloced += num_entries;
1257 return NT_STATUS_OK;
1260 /****************************************************************
1261 ****************************************************************/
1263 static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
1264 struct samsync_context *ctx,
1265 enum netr_SamDatabaseID database_id,
1266 uint64_t *sequence_num)
1268 NTSTATUS status;
1269 struct samsync_ldif_context *ldif_ctx =
1270 (struct samsync_ldif_context *)ctx->private_data;
1272 status = ldif_init_context(mem_ctx,
1273 database_id,
1274 ctx->output_filename,
1275 ctx->domain_sid_str,
1276 &ldif_ctx);
1277 if (!NT_STATUS_IS_OK(status)) {
1278 return status;
1281 ctx->private_data = ldif_ctx;
1283 return NT_STATUS_OK;
1286 /****************************************************************
1287 ****************************************************************/
1289 static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
1290 enum netr_SamDatabaseID database_id,
1291 struct netr_DELTA_ENUM_ARRAY *r,
1292 uint64_t *sequence_num,
1293 struct samsync_context *ctx)
1295 NTSTATUS status;
1296 int i;
1297 struct samsync_ldif_context *ldif_ctx =
1298 (struct samsync_ldif_context *)ctx->private_data;
1300 status = ldif_realloc_maps(mem_ctx, ldif_ctx, r->num_deltas);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 goto failed;
1305 for (i = 0; i < r->num_deltas; i++) {
1306 status = fetch_sam_entry_ldif(mem_ctx, database_id,
1307 &r->delta_enum[i], ctx,
1308 &a_index, &g_index);
1309 if (!NT_STATUS_IS_OK(status)) {
1310 goto failed;
1314 return NT_STATUS_OK;
1316 failed:
1317 ldif_free_context(ldif_ctx);
1318 ctx->private_data = NULL;
1320 return status;
1323 /****************************************************************
1324 ****************************************************************/
1326 static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
1327 struct samsync_context *ctx,
1328 enum netr_SamDatabaseID database_id,
1329 uint64_t sequence_num)
1331 struct samsync_ldif_context *ldif_ctx =
1332 (struct samsync_ldif_context *)ctx->private_data;
1334 /* This was the last query */
1335 ldif_write_output(database_id, ldif_ctx);
1336 if (ldif_ctx->ldif_file != stdout) {
1337 ctx->result_message = talloc_asprintf(ctx,
1338 "Vampired %d accounts and %d groups to %s",
1339 a_index, g_index, ctx->output_filename);
1342 ldif_free_context(ldif_ctx);
1343 ctx->private_data = NULL;
1345 return NT_STATUS_OK;
1348 #else /* HAVE_LDAP */
1350 static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
1351 struct samsync_context *ctx,
1352 enum netr_SamDatabaseID database_id,
1353 uint64_t *sequence_num)
1355 return NT_STATUS_NOT_SUPPORTED;
1358 static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
1359 enum netr_SamDatabaseID database_id,
1360 struct netr_DELTA_ENUM_ARRAY *r,
1361 uint64_t *sequence_num,
1362 struct samsync_context *ctx)
1364 return NT_STATUS_NOT_SUPPORTED;
1367 static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
1368 struct samsync_context *ctx,
1369 enum netr_SamDatabaseID database_id,
1370 uint64_t sequence_num)
1372 return NT_STATUS_NOT_SUPPORTED;
1375 #endif
1377 const struct samsync_ops libnet_samsync_ldif_ops = {
1378 .startup = init_ldif,
1379 .process_objects = fetch_sam_entries_ldif,
1380 .finish = close_ldif,