Fix coverity CID#116. Resource leak on error path.
[Samba/bb.git] / source / libnet / libnet_samsync_ldif.c
blobcee0e17e37bd57d396c05716f78bbd431ad3495f
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"
29 #ifdef HAVE_LDAP
31 /* uid's and gid's for writing deltas to ldif */
32 static uint32 ldif_gid = 999;
33 static uint32 ldif_uid = 999;
35 /* global counters */
36 static uint32_t g_index = 0;
37 static uint32_t a_index = 0;
39 /* Structure for mapping accounts to groups */
40 /* Array element is the group rid */
41 typedef struct _groupmap {
42 uint32_t rid;
43 uint32_t gidNumber;
44 const char *sambaSID;
45 const char *group_dn;
46 } GROUPMAP;
48 typedef struct _accountmap {
49 uint32_t rid;
50 const char *cn;
51 } ACCOUNTMAP;
53 struct samsync_ldif_context {
54 GROUPMAP *groupmap;
55 ACCOUNTMAP *accountmap;
56 bool initialized;
57 const char *add_template;
58 const char *mod_template;
59 char *add_name;
60 char *mod_name;
61 FILE *add_file;
62 FILE *mod_file;
63 FILE *ldif_file;
64 const char *suffix;
65 int num_alloced;
68 /****************************************************************
69 ****************************************************************/
71 static NTSTATUS populate_ldap_for_ldif(const char *sid,
72 const char *suffix,
73 const char *builtin_sid,
74 FILE *add_fd)
76 const char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix;
77 char *user_attr=NULL, *group_attr=NULL;
78 char *suffix_attr;
79 int len;
81 /* Get the suffix attribute */
82 suffix_attr = sstring_sub(suffix, '=', ',');
83 if (suffix_attr == NULL) {
84 len = strlen(suffix);
85 suffix_attr = (char*)SMB_MALLOC(len+1);
86 memcpy(suffix_attr, suffix, len);
87 suffix_attr[len] = '\0';
90 /* Write the base */
91 fprintf(add_fd, "# %s\n", suffix);
92 fprintf(add_fd, "dn: %s\n", suffix);
93 fprintf(add_fd, "objectClass: dcObject\n");
94 fprintf(add_fd, "objectClass: organization\n");
95 fprintf(add_fd, "o: %s\n", suffix_attr);
96 fprintf(add_fd, "dc: %s\n", suffix_attr);
97 fprintf(add_fd, "\n");
98 fflush(add_fd);
100 user_suffix = lp_ldap_user_suffix();
101 if (user_suffix == NULL) {
102 SAFE_FREE(suffix_attr);
103 return NT_STATUS_NO_MEMORY;
105 /* If it exists and is distinct from other containers,
106 Write the Users entity */
107 if (*user_suffix && strcmp(user_suffix, suffix)) {
108 user_attr = sstring_sub(lp_ldap_user_suffix(), '=', ',');
109 fprintf(add_fd, "# %s\n", user_suffix);
110 fprintf(add_fd, "dn: %s\n", user_suffix);
111 fprintf(add_fd, "objectClass: organizationalUnit\n");
112 fprintf(add_fd, "ou: %s\n", user_attr);
113 fprintf(add_fd, "\n");
114 fflush(add_fd);
118 group_suffix = lp_ldap_group_suffix();
119 if (group_suffix == NULL) {
120 SAFE_FREE(suffix_attr);
121 SAFE_FREE(user_attr);
122 return NT_STATUS_NO_MEMORY;
124 /* If it exists and is distinct from other containers,
125 Write the Groups entity */
126 if (*group_suffix && strcmp(group_suffix, suffix)) {
127 group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
128 fprintf(add_fd, "# %s\n", group_suffix);
129 fprintf(add_fd, "dn: %s\n", group_suffix);
130 fprintf(add_fd, "objectClass: organizationalUnit\n");
131 fprintf(add_fd, "ou: %s\n", group_attr);
132 fprintf(add_fd, "\n");
133 fflush(add_fd);
136 /* If it exists and is distinct from other containers,
137 Write the Computers entity */
138 machine_suffix = lp_ldap_machine_suffix();
139 if (machine_suffix == NULL) {
140 SAFE_FREE(suffix_attr);
141 SAFE_FREE(user_attr);
142 SAFE_FREE(group_attr);
143 return NT_STATUS_NO_MEMORY;
145 if (*machine_suffix && strcmp(machine_suffix, user_suffix) &&
146 strcmp(machine_suffix, suffix)) {
147 char *machine_ou = NULL;
148 fprintf(add_fd, "# %s\n", machine_suffix);
149 fprintf(add_fd, "dn: %s\n", machine_suffix);
150 fprintf(add_fd, "objectClass: organizationalUnit\n");
151 /* this isn't totally correct as it assumes that
152 there _must_ be an ou. just fixing memleak now. jmcd */
153 machine_ou = sstring_sub(lp_ldap_machine_suffix(), '=', ',');
154 fprintf(add_fd, "ou: %s\n", machine_ou);
155 SAFE_FREE(machine_ou);
156 fprintf(add_fd, "\n");
157 fflush(add_fd);
160 /* If it exists and is distinct from other containers,
161 Write the IdMap entity */
162 idmap_suffix = lp_ldap_idmap_suffix();
163 if (idmap_suffix == NULL) {
164 SAFE_FREE(suffix_attr);
165 SAFE_FREE(user_attr);
166 SAFE_FREE(group_attr);
167 return NT_STATUS_NO_MEMORY;
169 if (*idmap_suffix &&
170 strcmp(idmap_suffix, user_suffix) &&
171 strcmp(idmap_suffix, suffix)) {
172 char *s;
173 fprintf(add_fd, "# %s\n", idmap_suffix);
174 fprintf(add_fd, "dn: %s\n", idmap_suffix);
175 fprintf(add_fd, "ObjectClass: organizationalUnit\n");
176 s = sstring_sub(lp_ldap_idmap_suffix(), '=', ',');
177 fprintf(add_fd, "ou: %s\n", s);
178 SAFE_FREE(s);
179 fprintf(add_fd, "\n");
180 fflush(add_fd);
183 /* Write the domain entity */
184 fprintf(add_fd, "# %s, %s\n", lp_workgroup(), suffix);
185 fprintf(add_fd, "dn: sambaDomainName=%s,%s\n", lp_workgroup(),
186 suffix);
187 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_DOMINFO);
188 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_IDPOOL);
189 fprintf(add_fd, "sambaDomainName: %s\n", lp_workgroup());
190 fprintf(add_fd, "sambaSID: %s\n", sid);
191 fprintf(add_fd, "uidNumber: %d\n", ++ldif_uid);
192 fprintf(add_fd, "gidNumber: %d\n", ++ldif_gid);
193 fprintf(add_fd, "\n");
194 fflush(add_fd);
196 /* Write the Domain Admins entity */
197 fprintf(add_fd, "# Domain Admins, %s, %s\n", group_attr,
198 suffix);
199 fprintf(add_fd, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr,
200 suffix);
201 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
202 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
203 fprintf(add_fd, "cn: Domain Admins\n");
204 fprintf(add_fd, "memberUid: Administrator\n");
205 fprintf(add_fd, "description: Netbios Domain Administrators\n");
206 fprintf(add_fd, "gidNumber: 512\n");
207 fprintf(add_fd, "sambaSID: %s-512\n", sid);
208 fprintf(add_fd, "sambaGroupType: 2\n");
209 fprintf(add_fd, "displayName: Domain Admins\n");
210 fprintf(add_fd, "\n");
211 fflush(add_fd);
213 /* Write the Domain Users entity */
214 fprintf(add_fd, "# Domain Users, %s, %s\n", group_attr,
215 suffix);
216 fprintf(add_fd, "dn: cn=Domain Users,ou=%s,%s\n", group_attr,
217 suffix);
218 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
219 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
220 fprintf(add_fd, "cn: Domain Users\n");
221 fprintf(add_fd, "description: Netbios Domain Users\n");
222 fprintf(add_fd, "gidNumber: 513\n");
223 fprintf(add_fd, "sambaSID: %s-513\n", sid);
224 fprintf(add_fd, "sambaGroupType: 2\n");
225 fprintf(add_fd, "displayName: Domain Users\n");
226 fprintf(add_fd, "\n");
227 fflush(add_fd);
229 /* Write the Domain Guests entity */
230 fprintf(add_fd, "# Domain Guests, %s, %s\n", group_attr,
231 suffix);
232 fprintf(add_fd, "dn: cn=Domain Guests,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 Guests\n");
237 fprintf(add_fd, "description: Netbios Domain Guests\n");
238 fprintf(add_fd, "gidNumber: 514\n");
239 fprintf(add_fd, "sambaSID: %s-514\n", sid);
240 fprintf(add_fd, "sambaGroupType: 2\n");
241 fprintf(add_fd, "displayName: Domain Guests\n");
242 fprintf(add_fd, "\n");
243 fflush(add_fd);
245 /* Write the Domain Computers entity */
246 fprintf(add_fd, "# Domain Computers, %s, %s\n", group_attr,
247 suffix);
248 fprintf(add_fd, "dn: cn=Domain Computers,ou=%s,%s\n",
249 group_attr, suffix);
250 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
251 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
252 fprintf(add_fd, "gidNumber: 515\n");
253 fprintf(add_fd, "cn: Domain Computers\n");
254 fprintf(add_fd, "description: Netbios Domain Computers accounts\n");
255 fprintf(add_fd, "sambaSID: %s-515\n", sid);
256 fprintf(add_fd, "sambaGroupType: 2\n");
257 fprintf(add_fd, "displayName: Domain Computers\n");
258 fprintf(add_fd, "\n");
259 fflush(add_fd);
261 /* Write the Admininistrators Groups entity */
262 fprintf(add_fd, "# Administrators, %s, %s\n", group_attr,
263 suffix);
264 fprintf(add_fd, "dn: cn=Administrators,ou=%s,%s\n", group_attr,
265 suffix);
266 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
267 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
268 fprintf(add_fd, "gidNumber: 544\n");
269 fprintf(add_fd, "cn: Administrators\n");
270 fprintf(add_fd, "description: Netbios Domain Members can fully administer the computer/sambaDomainName\n");
271 fprintf(add_fd, "sambaSID: %s-544\n", builtin_sid);
272 fprintf(add_fd, "sambaGroupType: 5\n");
273 fprintf(add_fd, "displayName: Administrators\n");
274 fprintf(add_fd, "\n");
276 /* Write the Print Operator entity */
277 fprintf(add_fd, "# Print Operators, %s, %s\n", group_attr,
278 suffix);
279 fprintf(add_fd, "dn: cn=Print Operators,ou=%s,%s\n",
280 group_attr, suffix);
281 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
282 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
283 fprintf(add_fd, "gidNumber: 550\n");
284 fprintf(add_fd, "cn: Print Operators\n");
285 fprintf(add_fd, "description: Netbios Domain Print Operators\n");
286 fprintf(add_fd, "sambaSID: %s-550\n", builtin_sid);
287 fprintf(add_fd, "sambaGroupType: 5\n");
288 fprintf(add_fd, "displayName: Print Operators\n");
289 fprintf(add_fd, "\n");
290 fflush(add_fd);
292 /* Write the Backup Operators entity */
293 fprintf(add_fd, "# Backup Operators, %s, %s\n", group_attr,
294 suffix);
295 fprintf(add_fd, "dn: cn=Backup Operators,ou=%s,%s\n",
296 group_attr, suffix);
297 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
298 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
299 fprintf(add_fd, "gidNumber: 551\n");
300 fprintf(add_fd, "cn: Backup Operators\n");
301 fprintf(add_fd, "description: Netbios Domain Members can bypass file security to back up files\n");
302 fprintf(add_fd, "sambaSID: %s-551\n", builtin_sid);
303 fprintf(add_fd, "sambaGroupType: 5\n");
304 fprintf(add_fd, "displayName: Backup Operators\n");
305 fprintf(add_fd, "\n");
306 fflush(add_fd);
308 /* Write the Replicators entity */
309 fprintf(add_fd, "# Replicators, %s, %s\n", group_attr, suffix);
310 fprintf(add_fd, "dn: cn=Replicators,ou=%s,%s\n", group_attr,
311 suffix);
312 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
313 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
314 fprintf(add_fd, "gidNumber: 552\n");
315 fprintf(add_fd, "cn: Replicators\n");
316 fprintf(add_fd, "description: Netbios Domain Supports file replication in a sambaDomainName\n");
317 fprintf(add_fd, "sambaSID: %s-552\n", builtin_sid);
318 fprintf(add_fd, "sambaGroupType: 5\n");
319 fprintf(add_fd, "displayName: Replicators\n");
320 fprintf(add_fd, "\n");
321 fflush(add_fd);
323 /* Deallocate memory, and return */
324 SAFE_FREE(suffix_attr);
325 SAFE_FREE(user_attr);
326 SAFE_FREE(group_attr);
327 return NT_STATUS_OK;
330 /****************************************************************
331 ****************************************************************/
333 static NTSTATUS map_populate_groups(TALLOC_CTX *mem_ctx,
334 GROUPMAP *groupmap,
335 ACCOUNTMAP *accountmap,
336 const char *sid,
337 const char *suffix,
338 const char *builtin_sid)
340 char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
342 /* Map the groups created by populate_ldap_for_ldif */
343 groupmap[0].rid = 512;
344 groupmap[0].gidNumber = 512;
345 groupmap[0].sambaSID = talloc_asprintf(mem_ctx, "%s-512", sid);
346 groupmap[0].group_dn = talloc_asprintf(mem_ctx,
347 "cn=Domain Admins,ou=%s,%s", group_attr, suffix);
348 NT_STATUS_HAVE_NO_MEMORY(groupmap[0].sambaSID);
349 NT_STATUS_HAVE_NO_MEMORY(groupmap[0].group_dn);
351 accountmap[0].rid = 512;
352 accountmap[0].cn = talloc_strdup(mem_ctx, "Domain Admins");
353 NT_STATUS_HAVE_NO_MEMORY(accountmap[0].cn);
355 groupmap[1].rid = 513;
356 groupmap[1].gidNumber = 513;
357 groupmap[1].sambaSID = talloc_asprintf(mem_ctx, "%s-513", sid);
358 groupmap[1].group_dn = talloc_asprintf(mem_ctx,
359 "cn=Domain Users,ou=%s,%s", group_attr, suffix);
360 NT_STATUS_HAVE_NO_MEMORY(groupmap[1].sambaSID);
361 NT_STATUS_HAVE_NO_MEMORY(groupmap[1].group_dn);
363 accountmap[1].rid = 513;
364 accountmap[1].cn = talloc_strdup(mem_ctx, "Domain Users");
365 NT_STATUS_HAVE_NO_MEMORY(accountmap[1].cn);
367 groupmap[2].rid = 514;
368 groupmap[2].gidNumber = 514;
369 groupmap[2].sambaSID = talloc_asprintf(mem_ctx, "%s-514", sid);
370 groupmap[2].group_dn = talloc_asprintf(mem_ctx,
371 "cn=Domain Guests,ou=%s,%s", group_attr, suffix);
372 NT_STATUS_HAVE_NO_MEMORY(groupmap[2].sambaSID);
373 NT_STATUS_HAVE_NO_MEMORY(groupmap[2].group_dn);
375 accountmap[2].rid = 514;
376 accountmap[2].cn = talloc_strdup(mem_ctx, "Domain Guests");
377 NT_STATUS_HAVE_NO_MEMORY(accountmap[2].cn);
379 groupmap[3].rid = 515;
380 groupmap[3].gidNumber = 515;
381 groupmap[3].sambaSID = talloc_asprintf(mem_ctx, "%s-515", sid);
382 groupmap[3].group_dn = talloc_asprintf(mem_ctx,
383 "cn=Domain Computers,ou=%s,%s", group_attr, suffix);
384 NT_STATUS_HAVE_NO_MEMORY(groupmap[3].sambaSID);
385 NT_STATUS_HAVE_NO_MEMORY(groupmap[3].group_dn);
387 accountmap[3].rid = 515;
388 accountmap[3].cn = talloc_strdup(mem_ctx, "Domain Computers");
389 NT_STATUS_HAVE_NO_MEMORY(accountmap[3].cn);
391 groupmap[4].rid = 544;
392 groupmap[4].gidNumber = 544;
393 groupmap[4].sambaSID = talloc_asprintf(mem_ctx, "%s-544", builtin_sid);
394 groupmap[4].group_dn = talloc_asprintf(mem_ctx,
395 "cn=Administrators,ou=%s,%s", group_attr, suffix);
396 NT_STATUS_HAVE_NO_MEMORY(groupmap[4].sambaSID);
397 NT_STATUS_HAVE_NO_MEMORY(groupmap[4].group_dn);
399 accountmap[4].rid = 515;
400 accountmap[4].cn = talloc_strdup(mem_ctx, "Administrators");
401 NT_STATUS_HAVE_NO_MEMORY(accountmap[4].cn);
403 groupmap[5].rid = 550;
404 groupmap[5].gidNumber = 550;
405 groupmap[5].sambaSID = talloc_asprintf(mem_ctx, "%s-550", builtin_sid);
406 groupmap[5].group_dn = talloc_asprintf(mem_ctx,
407 "cn=Print Operators,ou=%s,%s", group_attr, suffix);
408 NT_STATUS_HAVE_NO_MEMORY(groupmap[5].sambaSID);
409 NT_STATUS_HAVE_NO_MEMORY(groupmap[5].group_dn);
411 accountmap[5].rid = 550;
412 accountmap[5].cn = talloc_strdup(mem_ctx, "Print Operators");
413 NT_STATUS_HAVE_NO_MEMORY(accountmap[5].cn);
415 groupmap[6].rid = 551;
416 groupmap[6].gidNumber = 551;
417 groupmap[6].sambaSID = talloc_asprintf(mem_ctx, "%s-551", builtin_sid);
418 groupmap[6].group_dn = talloc_asprintf(mem_ctx,
419 "cn=Backup Operators,ou=%s,%s", group_attr, suffix);
420 NT_STATUS_HAVE_NO_MEMORY(groupmap[6].sambaSID);
421 NT_STATUS_HAVE_NO_MEMORY(groupmap[6].group_dn);
423 accountmap[6].rid = 551;
424 accountmap[6].cn = talloc_strdup(mem_ctx, "Backup Operators");
425 NT_STATUS_HAVE_NO_MEMORY(accountmap[6].cn);
427 groupmap[7].rid = 552;
428 groupmap[7].gidNumber = 552;
429 groupmap[7].sambaSID = talloc_asprintf(mem_ctx, "%s-552", builtin_sid);
430 groupmap[7].group_dn = talloc_asprintf(mem_ctx,
431 "cn=Replicators,ou=%s,%s", group_attr, suffix);
432 NT_STATUS_HAVE_NO_MEMORY(groupmap[7].sambaSID);
433 NT_STATUS_HAVE_NO_MEMORY(groupmap[7].group_dn);
435 accountmap[7].rid = 551;
436 accountmap[7].cn = talloc_strdup(mem_ctx, "Replicators");
437 NT_STATUS_HAVE_NO_MEMORY(accountmap[7].cn);
439 SAFE_FREE(group_attr);
441 return NT_STATUS_OK;
445 * This is a crap routine, but I think it's the quickest way to solve the
446 * UTF8->base64 problem.
449 static int fprintf_attr(FILE *add_fd, const char *attr_name,
450 const char *fmt, ...)
452 va_list ap;
453 char *value, *p, *base64;
454 DATA_BLOB base64_blob;
455 bool do_base64 = false;
456 int res;
458 va_start(ap, fmt);
459 value = talloc_vasprintf(NULL, fmt, ap);
460 va_end(ap);
462 SMB_ASSERT(value != NULL);
464 for (p=value; *p; p++) {
465 if (*p & 0x80) {
466 do_base64 = true;
467 break;
471 if (!do_base64) {
472 bool only_whitespace = true;
473 for (p=value; *p; p++) {
475 * I know that this not multibyte safe, but we break
476 * on the first non-whitespace character anyway.
478 if (!isspace(*p)) {
479 only_whitespace = false;
480 break;
483 if (only_whitespace) {
484 do_base64 = true;
488 if (!do_base64) {
489 res = fprintf(add_fd, "%s: %s\n", attr_name, value);
490 TALLOC_FREE(value);
491 return res;
494 base64_blob.data = (unsigned char *)value;
495 base64_blob.length = strlen(value);
497 base64 = base64_encode_data_blob(value, base64_blob);
498 SMB_ASSERT(base64 != NULL);
500 res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
501 TALLOC_FREE(value);
502 return res;
505 /****************************************************************
506 ****************************************************************/
508 static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx,
509 struct netr_DELTA_GROUP *r,
510 GROUPMAP *groupmap,
511 FILE *add_fd,
512 const char *sid,
513 const char *suffix)
515 const char *groupname = r->group_name.string;
516 uint32 grouptype = 0, g_rid = 0;
517 char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
519 /* Set up the group type (always 2 for group info) */
520 grouptype = 2;
522 /* These groups are entered by populate_ldap_for_ldif */
523 if (strcmp(groupname, "Domain Admins") == 0 ||
524 strcmp(groupname, "Domain Users") == 0 ||
525 strcmp(groupname, "Domain Guests") == 0 ||
526 strcmp(groupname, "Domain Computers") == 0 ||
527 strcmp(groupname, "Administrators") == 0 ||
528 strcmp(groupname, "Print Operators") == 0 ||
529 strcmp(groupname, "Backup Operators") == 0 ||
530 strcmp(groupname, "Replicators") == 0) {
531 SAFE_FREE(group_attr);
532 return NT_STATUS_OK;
533 } else {
534 /* Increment the gid for the new group */
535 ldif_gid++;
538 /* Map the group rid, gid, and dn */
539 g_rid = r->rid;
540 groupmap->rid = g_rid;
541 groupmap->gidNumber = ldif_gid;
542 groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
543 groupmap->group_dn = talloc_asprintf(mem_ctx,
544 "cn=%s,ou=%s,%s", groupname, group_attr, suffix);
545 if (groupmap->sambaSID == NULL || groupmap->group_dn == NULL) {
546 SAFE_FREE(group_attr);
547 return NT_STATUS_NO_MEMORY;
550 /* Write the data to the temporary add ldif file */
551 fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr,
552 suffix);
553 fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", groupname, group_attr,
554 suffix);
555 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
556 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
557 fprintf_attr(add_fd, "cn", "%s", groupname);
558 fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
559 fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
560 fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
561 fprintf_attr(add_fd, "displayName", "%s", groupname);
562 fprintf(add_fd, "\n");
563 fflush(add_fd);
565 SAFE_FREE(group_attr);
566 /* Return */
567 return NT_STATUS_OK;
570 /****************************************************************
571 ****************************************************************/
573 static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx,
574 struct netr_DELTA_USER *r,
575 GROUPMAP *groupmap,
576 ACCOUNTMAP *accountmap,
577 FILE *add_fd,
578 const char *sid,
579 const char *suffix,
580 int alloced)
582 fstring username, logonscript, homedrive, homepath = "", homedir = "";
583 fstring hex_nt_passwd, hex_lm_passwd;
584 fstring description, profilepath, fullname, sambaSID;
585 char *flags, *user_rdn;
586 const char *ou;
587 const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
588 uchar zero_buf[16];
589 uint32 rid = 0, group_rid = 0, gidNumber = 0;
590 time_t unix_time;
591 int i, ret;
593 memset(zero_buf, '\0', sizeof(zero_buf));
595 /* Get the username */
596 fstrcpy(username, r->account_name.string);
598 /* Get the rid */
599 rid = r->rid;
601 /* Map the rid and username for group member info later */
602 accountmap->rid = rid;
603 accountmap->cn = talloc_strdup(mem_ctx, username);
604 NT_STATUS_HAVE_NO_MEMORY(accountmap->cn);
606 /* Get the home directory */
607 if (r->acct_flags & ACB_NORMAL) {
608 fstrcpy(homedir, r->home_directory.string);
609 if (!*homedir) {
610 snprintf(homedir, sizeof(homedir), "/home/%s", username);
611 } else {
612 snprintf(homedir, sizeof(homedir), "/nobodyshomedir");
614 ou = lp_ldap_user_suffix();
615 } else {
616 ou = lp_ldap_machine_suffix();
617 snprintf(homedir, sizeof(homedir), "/machinehomedir");
620 /* Get the logon script */
621 fstrcpy(logonscript, r->logon_script.string);
623 /* Get the home drive */
624 fstrcpy(homedrive, r->home_drive.string);
626 /* Get the home path */
627 fstrcpy(homepath, r->home_directory.string);
629 /* Get the description */
630 fstrcpy(description, r->description.string);
632 /* Get the display name */
633 fstrcpy(fullname, r->full_name.string);
635 /* Get the profile path */
636 fstrcpy(profilepath, r->profile_path.string);
638 /* Get lm and nt password data */
639 if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
640 pdb_sethexpwd(hex_lm_passwd, r->lmpassword.hash, r->acct_flags);
641 } else {
642 pdb_sethexpwd(hex_lm_passwd, NULL, 0);
644 if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
645 pdb_sethexpwd(hex_nt_passwd, r->ntpassword.hash, r->acct_flags);
646 } else {
647 pdb_sethexpwd(hex_nt_passwd, NULL, 0);
649 unix_time = nt_time_to_unix(r->last_password_change);
651 /* Increment the uid for the new user */
652 ldif_uid++;
654 /* Set up group id and sambaSID for the user */
655 group_rid = r->primary_gid;
656 for (i=0; i<alloced; i++) {
657 if (groupmap[i].rid == group_rid) break;
659 if (i == alloced){
660 DEBUG(1, ("Could not find rid %d in groupmap array\n",
661 group_rid));
662 return NT_STATUS_UNSUCCESSFUL;
664 gidNumber = groupmap[i].gidNumber;
665 ret = snprintf(sambaSID, sizeof(sambaSID), "%s", groupmap[i].sambaSID);
666 if (ret < 0 || ret == sizeof(sambaSID)) {
667 return NT_STATUS_UNSUCCESSFUL;
670 /* Set up sambaAcctFlags */
671 flags = pdb_encode_acct_ctrl(r->acct_flags,
672 NEW_PW_FORMAT_SPACE_PADDED_LEN);
674 /* Add the user to the temporary add ldif file */
675 /* this isn't quite right...we can't assume there's just OU=. jmcd */
676 user_rdn = sstring_sub(ou, '=', ',');
677 fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
678 fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
679 suffix);
680 SAFE_FREE(user_rdn);
681 fprintf(add_fd, "ObjectClass: top\n");
682 fprintf(add_fd, "objectClass: inetOrgPerson\n");
683 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT);
684 fprintf(add_fd, "objectClass: shadowAccount\n");
685 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT);
686 fprintf_attr(add_fd, "cn", "%s", username);
687 fprintf_attr(add_fd, "sn", "%s", username);
688 fprintf_attr(add_fd, "uid", "%s", username);
689 fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
690 fprintf(add_fd, "gidNumber: %d\n", gidNumber);
691 fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
692 if (*homepath)
693 fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
694 if (*homedrive)
695 fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
696 if (*logonscript)
697 fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
698 fprintf(add_fd, "loginShell: %s\n",
699 ((r->acct_flags & ACB_NORMAL) ?
700 "/bin/bash" : "/bin/false"));
701 fprintf(add_fd, "gecos: System User\n");
702 if (*description)
703 fprintf_attr(add_fd, "description", "%s", description);
704 fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
705 fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
706 if(*fullname)
707 fprintf_attr(add_fd, "displayName", "%s", fullname);
708 if(*profilepath)
709 fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
710 if (strcmp(nopasswd, hex_lm_passwd) != 0)
711 fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
712 if (strcmp(nopasswd, hex_nt_passwd) != 0)
713 fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd);
714 fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time);
715 fprintf(add_fd, "sambaAcctFlags: %s\n", flags);
716 fprintf(add_fd, "\n");
717 fflush(add_fd);
719 /* Return */
720 return NT_STATUS_OK;
723 /****************************************************************
724 ****************************************************************/
726 static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx,
727 struct netr_DELTA_ALIAS *r,
728 GROUPMAP *groupmap,
729 FILE *add_fd,
730 const char *sid,
731 const char *suffix,
732 enum netr_SamDatabaseID database_id)
734 fstring aliasname, description;
735 uint32 grouptype = 0, g_rid = 0;
736 char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
738 /* Get the alias name */
739 fstrcpy(aliasname, r->alias_name.string);
741 /* Get the alias description */
742 fstrcpy(description, r->description.string);
744 /* Set up the group type */
745 switch (database_id) {
746 case SAM_DATABASE_DOMAIN:
747 grouptype = 4;
748 break;
749 case SAM_DATABASE_BUILTIN:
750 grouptype = 5;
751 break;
752 default:
753 grouptype = 4;
754 break;
758 These groups are entered by populate_ldap_for_ldif
759 Note that populate creates a group called Relicators,
760 but NT returns a group called Replicator
762 if (strcmp(aliasname, "Domain Admins") == 0 ||
763 strcmp(aliasname, "Domain Users") == 0 ||
764 strcmp(aliasname, "Domain Guests") == 0 ||
765 strcmp(aliasname, "Domain Computers") == 0 ||
766 strcmp(aliasname, "Administrators") == 0 ||
767 strcmp(aliasname, "Print Operators") == 0 ||
768 strcmp(aliasname, "Backup Operators") == 0 ||
769 strcmp(aliasname, "Replicator") == 0) {
770 SAFE_FREE(group_attr);
771 return NT_STATUS_OK;
772 } else {
773 /* Increment the gid for the new group */
774 ldif_gid++;
777 /* Map the group rid and gid */
778 g_rid = r->rid;
779 groupmap->gidNumber = ldif_gid;
780 groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
781 if (groupmap->sambaSID == NULL) {
782 SAFE_FREE(group_attr);
783 return NT_STATUS_NO_MEMORY;
786 /* Write the data to the temporary add ldif file */
787 fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr,
788 suffix);
789 fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", aliasname, group_attr,
790 suffix);
791 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
792 fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
793 fprintf(add_fd, "cn: %s\n", aliasname);
794 fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
795 fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
796 fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
797 fprintf_attr(add_fd, "displayName", "%s", aliasname);
798 if (description[0])
799 fprintf_attr(add_fd, "description", "%s", description);
800 fprintf(add_fd, "\n");
801 fflush(add_fd);
803 SAFE_FREE(group_attr);
804 /* Return */
805 return NT_STATUS_OK;
808 /****************************************************************
809 ****************************************************************/
811 static NTSTATUS fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER *r,
812 uint32_t id_rid,
813 GROUPMAP *groupmap,
814 ACCOUNTMAP *accountmap,
815 FILE *mod_fd, int alloced)
817 fstring group_dn;
818 uint32 group_rid = 0, rid = 0;
819 int i, j, k;
821 /* Get the dn for the group */
822 if (r->num_rids > 0) {
823 group_rid = id_rid;
824 for (j=0; j<alloced; j++) {
825 if (groupmap[j].rid == group_rid) break;
827 if (j == alloced){
828 DEBUG(1, ("Could not find rid %d in groupmap array\n",
829 group_rid));
830 return NT_STATUS_UNSUCCESSFUL;
832 snprintf(group_dn, sizeof(group_dn), "%s", groupmap[j].group_dn);
833 fprintf(mod_fd, "dn: %s\n", group_dn);
835 /* Get the cn for each member */
836 for (i=0; i < r->num_rids; i++) {
837 rid = r->rids[i];
838 for (k=0; k<alloced; k++) {
839 if (accountmap[k].rid == rid) break;
841 if (k == alloced){
842 DEBUG(1, ("Could not find rid %d in "
843 "accountmap array\n", rid));
844 return NT_STATUS_UNSUCCESSFUL;
846 fprintf(mod_fd, "memberUid: %s\n", accountmap[k].cn);
848 fprintf(mod_fd, "\n");
850 fflush(mod_fd);
852 /* Return */
853 return NT_STATUS_OK;
856 /****************************************************************
857 ****************************************************************/
859 static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx,
860 enum netr_SamDatabaseID database_id,
861 const char *ldif_filename,
862 const char *domain_sid_str,
863 struct samsync_ldif_context **ctx)
865 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
866 struct samsync_ldif_context *r;
867 const char *add_template = "/tmp/add.ldif.XXXXXX";
868 const char *mod_template = "/tmp/mod.ldif.XXXXXX";
869 const char *builtin_sid = "S-1-5-32";
871 /* Get other smb.conf data */
872 if (!(lp_workgroup()) || !*(lp_workgroup())) {
873 DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
874 exit(1);
877 /* Get the ldap suffix */
878 if (!(lp_ldap_suffix()) || !*(lp_ldap_suffix())) {
879 DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
880 exit(1);
883 if (*ctx && (*ctx)->initialized) {
884 return NT_STATUS_OK;
887 r = TALLOC_ZERO_P(mem_ctx, struct samsync_ldif_context);
888 NT_STATUS_HAVE_NO_MEMORY(r);
890 /* Get the ldap suffix */
891 r->suffix = lp_ldap_suffix();
893 /* Ensure we have an output file */
894 if (ldif_filename) {
895 r->ldif_file = fopen(ldif_filename, "a");
896 } else {
897 r->ldif_file = stdout;
900 if (!r->ldif_file) {
901 fprintf(stderr, "Could not open %s\n", ldif_filename);
902 DEBUG(1, ("Could not open %s\n", ldif_filename));
903 status = NT_STATUS_UNSUCCESSFUL;
904 goto done;
907 r->add_template = talloc_strdup(mem_ctx, add_template);
908 r->mod_template = talloc_strdup(mem_ctx, mod_template);
909 if (!r->add_template || !r->mod_template) {
910 status = NT_STATUS_NO_MEMORY;
911 goto done;
914 r->add_name = talloc_strdup(mem_ctx, add_template);
915 r->mod_name = talloc_strdup(mem_ctx, mod_template);
916 if (!r->add_name || !r->mod_name) {
917 status = NT_STATUS_NO_MEMORY;
918 goto done;
921 /* Open the add and mod ldif files */
922 if (!(r->add_file = fdopen(smb_mkstemp(r->add_name),"w"))) {
923 DEBUG(1, ("Could not open %s\n", r->add_name));
924 status = NT_STATUS_UNSUCCESSFUL;
925 goto done;
927 if (!(r->mod_file = fdopen(smb_mkstemp(r->mod_name),"w"))) {
928 DEBUG(1, ("Could not open %s\n", r->mod_name));
929 status = NT_STATUS_UNSUCCESSFUL;
930 goto done;
933 /* Allocate initial memory for groupmap and accountmap arrays */
934 r->groupmap = TALLOC_ZERO_ARRAY(mem_ctx, GROUPMAP, 8);
935 r->accountmap = TALLOC_ZERO_ARRAY(mem_ctx, ACCOUNTMAP, 8);
936 if (r->groupmap == NULL || r->accountmap == NULL) {
937 DEBUG(1,("GROUPMAP talloc failed\n"));
938 status = NT_STATUS_NO_MEMORY;
939 goto done;
942 /* Remember how many we malloced */
943 r->num_alloced = 8;
945 /* Initial database population */
946 if (database_id == SAM_DATABASE_DOMAIN) {
948 status = populate_ldap_for_ldif(domain_sid_str,
949 r->suffix,
950 builtin_sid,
951 r->add_file);
952 if (!NT_STATUS_IS_OK(status)) {
953 goto done;
956 status = map_populate_groups(mem_ctx,
957 r->groupmap,
958 r->accountmap,
959 domain_sid_str,
960 r->suffix,
961 builtin_sid);
962 if (!NT_STATUS_IS_OK(status)) {
963 goto done;
967 r->initialized = true;
969 *ctx = r;
971 return NT_STATUS_OK;
972 done:
973 TALLOC_FREE(r);
974 return status;
977 /****************************************************************
978 ****************************************************************/
980 static void ldif_free_context(struct samsync_ldif_context *r)
982 if (!r) {
983 return;
986 /* Close and delete the ldif files */
987 if (r->add_file) {
988 fclose(r->add_file);
991 if ((r->add_name != NULL) &&
992 strcmp(r->add_name, r->add_template) && (unlink(r->add_name))) {
993 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
994 r->add_name, strerror(errno)));
997 if (r->mod_file) {
998 fclose(r->mod_file);
1001 if ((r->mod_name != NULL) &&
1002 strcmp(r->mod_name, r->mod_template) && (unlink(r->mod_name))) {
1003 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1004 r->mod_name, strerror(errno)));
1007 if (r->ldif_file && (r->ldif_file != stdout)) {
1008 fclose(r->ldif_file);
1011 TALLOC_FREE(r);
1014 /****************************************************************
1015 ****************************************************************/
1017 static void ldif_write_output(enum netr_SamDatabaseID database_id,
1018 struct samsync_ldif_context *l)
1020 /* Write ldif data to the user's file */
1021 if (database_id == SAM_DATABASE_DOMAIN) {
1022 fprintf(l->ldif_file,
1023 "# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
1024 fprintf(l->ldif_file,
1025 "# =================================\n\n");
1026 fflush(l->ldif_file);
1027 } else if (database_id == SAM_DATABASE_BUILTIN) {
1028 fprintf(l->ldif_file,
1029 "# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
1030 fprintf(l->ldif_file,
1031 "# ==================================\n\n");
1032 fflush(l->ldif_file);
1034 fseek(l->add_file, 0, SEEK_SET);
1035 transfer_file(fileno(l->add_file), fileno(l->ldif_file), (size_t) -1);
1037 if (database_id == SAM_DATABASE_DOMAIN) {
1038 fprintf(l->ldif_file,
1039 "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
1040 fprintf(l->ldif_file,
1041 "# ====================================\n\n");
1042 fflush(l->ldif_file);
1043 } else if (database_id == SAM_DATABASE_BUILTIN) {
1044 fprintf(l->ldif_file,
1045 "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
1046 fprintf(l->ldif_file,
1047 "# =====================================\n\n");
1048 fflush(l->ldif_file);
1050 fseek(l->mod_file, 0, SEEK_SET);
1051 transfer_file(fileno(l->mod_file), fileno(l->ldif_file), (size_t) -1);
1054 /****************************************************************
1055 ****************************************************************/
1057 static NTSTATUS fetch_sam_entry_ldif(TALLOC_CTX *mem_ctx,
1058 enum netr_SamDatabaseID database_id,
1059 struct netr_DELTA_ENUM *r,
1060 struct samsync_context *ctx,
1061 uint32_t *a_index_p,
1062 uint32_t *g_index_p)
1064 union netr_DELTA_UNION u = r->delta_union;
1065 union netr_DELTA_ID_UNION id = r->delta_id_union;
1066 struct samsync_ldif_context *l =
1067 talloc_get_type_abort(ctx->private_data, struct samsync_ldif_context);
1069 switch (r->delta_type) {
1070 case NETR_DELTA_DOMAIN:
1071 break;
1073 case NETR_DELTA_GROUP:
1074 fetch_group_info_to_ldif(mem_ctx,
1075 u.group,
1076 &l->groupmap[*g_index_p],
1077 l->add_file,
1078 ctx->domain_sid_str,
1079 l->suffix);
1080 (*g_index_p)++;
1081 break;
1083 case NETR_DELTA_USER:
1084 fetch_account_info_to_ldif(mem_ctx,
1085 u.user,
1086 l->groupmap,
1087 &l->accountmap[*a_index_p],
1088 l->add_file,
1089 ctx->domain_sid_str,
1090 l->suffix,
1091 l->num_alloced);
1092 (*a_index_p)++;
1093 break;
1095 case NETR_DELTA_ALIAS:
1096 fetch_alias_info_to_ldif(mem_ctx,
1097 u.alias,
1098 &l->groupmap[*g_index_p],
1099 l->add_file,
1100 ctx->domain_sid_str,
1101 l->suffix,
1102 database_id);
1103 (*g_index_p)++;
1104 break;
1106 case NETR_DELTA_GROUP_MEMBER:
1107 fetch_groupmem_info_to_ldif(u.group_member,
1108 id.rid,
1109 l->groupmap,
1110 l->accountmap,
1111 l->mod_file,
1112 l->num_alloced);
1113 break;
1115 case NETR_DELTA_ALIAS_MEMBER:
1116 case NETR_DELTA_POLICY:
1117 case NETR_DELTA_ACCOUNT:
1118 case NETR_DELTA_TRUSTED_DOMAIN:
1119 case NETR_DELTA_SECRET:
1120 case NETR_DELTA_RENAME_GROUP:
1121 case NETR_DELTA_RENAME_USER:
1122 case NETR_DELTA_RENAME_ALIAS:
1123 case NETR_DELTA_DELETE_GROUP:
1124 case NETR_DELTA_DELETE_USER:
1125 case NETR_DELTA_MODIFY_COUNT:
1126 default:
1127 break;
1128 } /* end of switch */
1130 return NT_STATUS_OK;
1133 /****************************************************************
1134 ****************************************************************/
1136 static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx,
1137 struct samsync_ldif_context *l,
1138 uint32_t num_entries)
1140 /* Re-allocate memory for groupmap and accountmap arrays */
1141 l->groupmap = TALLOC_REALLOC_ARRAY(mem_ctx,
1142 l->groupmap,
1143 GROUPMAP,
1144 num_entries + l->num_alloced);
1146 l->accountmap = TALLOC_REALLOC_ARRAY(mem_ctx,
1147 l->accountmap,
1148 ACCOUNTMAP,
1149 num_entries + l->num_alloced);
1151 if (l->groupmap == NULL || l->accountmap == NULL) {
1152 DEBUG(1,("GROUPMAP talloc failed\n"));
1153 return NT_STATUS_NO_MEMORY;
1156 /* Initialize the new records */
1157 memset(&(l->groupmap[l->num_alloced]), 0,
1158 sizeof(GROUPMAP) * num_entries);
1159 memset(&(l->accountmap[l->num_alloced]), 0,
1160 sizeof(ACCOUNTMAP) * num_entries);
1162 /* Remember how many we alloced this time */
1163 l->num_alloced += num_entries;
1165 return NT_STATUS_OK;
1168 /****************************************************************
1169 ****************************************************************/
1171 static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
1172 struct samsync_context *ctx,
1173 enum netr_SamDatabaseID database_id,
1174 uint64_t *sequence_num)
1176 NTSTATUS status;
1177 struct samsync_ldif_context *ldif_ctx =
1178 (struct samsync_ldif_context *)ctx->private_data;
1180 status = ldif_init_context(mem_ctx,
1181 database_id,
1182 ctx->output_filename,
1183 ctx->domain_sid_str,
1184 &ldif_ctx);
1185 if (!NT_STATUS_IS_OK(status)) {
1186 return status;
1189 ctx->private_data = ldif_ctx;
1191 return NT_STATUS_OK;
1194 /****************************************************************
1195 ****************************************************************/
1197 static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
1198 enum netr_SamDatabaseID database_id,
1199 struct netr_DELTA_ENUM_ARRAY *r,
1200 uint64_t *sequence_num,
1201 struct samsync_context *ctx)
1203 NTSTATUS status;
1204 int i;
1205 struct samsync_ldif_context *ldif_ctx =
1206 (struct samsync_ldif_context *)ctx->private_data;
1208 status = ldif_realloc_maps(mem_ctx, ldif_ctx, r->num_deltas);
1209 if (!NT_STATUS_IS_OK(status)) {
1210 goto failed;
1213 for (i = 0; i < r->num_deltas; i++) {
1214 status = fetch_sam_entry_ldif(mem_ctx, database_id,
1215 &r->delta_enum[i], ctx,
1216 &a_index, &g_index);
1217 if (!NT_STATUS_IS_OK(status)) {
1218 goto failed;
1222 return NT_STATUS_OK;
1224 failed:
1225 ldif_free_context(ldif_ctx);
1226 ctx->private_data = NULL;
1228 return status;
1231 /****************************************************************
1232 ****************************************************************/
1234 static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
1235 struct samsync_context *ctx,
1236 enum netr_SamDatabaseID database_id,
1237 uint64_t sequence_num)
1239 struct samsync_ldif_context *ldif_ctx =
1240 (struct samsync_ldif_context *)ctx->private_data;
1242 /* This was the last query */
1243 ldif_write_output(database_id, ldif_ctx);
1244 if (ldif_ctx->ldif_file != stdout) {
1245 ctx->result_message = talloc_asprintf(ctx,
1246 "Vampired %d accounts and %d groups to %s",
1247 a_index, g_index, ctx->output_filename);
1250 ldif_free_context(ldif_ctx);
1251 ctx->private_data = NULL;
1253 return NT_STATUS_OK;
1256 #else /* HAVE_LDAP */
1258 static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
1259 struct samsync_context *ctx,
1260 enum netr_SamDatabaseID database_id,
1261 uint64_t *sequence_num)
1263 return NT_STATUS_NOT_SUPPORTED;
1266 static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
1267 enum netr_SamDatabaseID database_id,
1268 struct netr_DELTA_ENUM_ARRAY *r,
1269 uint64_t *sequence_num,
1270 struct samsync_context *ctx)
1272 return NT_STATUS_NOT_SUPPORTED;
1275 static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
1276 struct samsync_context *ctx,
1277 enum netr_SamDatabaseID database_id,
1278 uint64_t sequence_num)
1280 return NT_STATUS_NOT_SUPPORTED;
1283 #endif
1285 const struct samsync_ops libnet_samsync_ldif_ops = {
1286 .startup = init_ldif,
1287 .process_objects = fetch_sam_entries_ldif,
1288 .finish = close_ldif,