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/>.
27 #include "system/filesys.h"
28 #include "libnet/libnet_samsync.h"
29 #include "transfer_file.h"
31 #include "passdb/pdb_ldap_schema.h"
32 #include "lib/util/base64.h"
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;
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
{
53 typedef struct _accountmap
{
58 struct samsync_ldif_context
{
60 ACCOUNTMAP
*accountmap
;
62 const char *add_template
;
63 const char *mod_template
;
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
;
84 temp1
= strchr(src
, front
);
85 if (temp1
== NULL
) return NULL
;
86 temp2
= strchr(src
, back
);
87 if (temp2
== NULL
) return NULL
;
89 if (len
<= 0) return NULL
;
90 temp3
= (char*)SMB_MALLOC(len
);
92 DEBUG(1,("Malloc failure in sstring_sub\n"));
95 memcpy(temp3
, temp1
+1, len
-1);
100 /****************************************************************
101 ****************************************************************/
103 static NTSTATUS
populate_ldap_for_ldif(const char *sid
,
105 const char *builtin_sid
,
108 const char *user_suffix
, *group_suffix
, *machine_suffix
, *idmap_suffix
;
109 char *user_attr
=NULL
, *group_attr
=NULL
;
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);
119 return NT_STATUS_NO_MEMORY
;
121 memcpy(suffix_attr
, suffix
, len
);
122 suffix_attr
[len
] = '\0';
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");
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");
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");
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");
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
;
205 strcmp(idmap_suffix
, user_suffix
) &&
206 strcmp(idmap_suffix
, suffix
)) {
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
);
214 fprintf(add_fd
, "\n");
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(),
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");
231 /* Write the Domain Admins entity */
232 fprintf(add_fd
, "# Domain Admins, %s, %s\n", group_attr
,
234 fprintf(add_fd
, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr
,
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");
248 /* Write the Domain Users entity */
249 fprintf(add_fd
, "# Domain Users, %s, %s\n", group_attr
,
251 fprintf(add_fd
, "dn: cn=Domain Users,ou=%s,%s\n", group_attr
,
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");
264 /* Write the Domain Guests entity */
265 fprintf(add_fd
, "# Domain Guests, %s, %s\n", group_attr
,
267 fprintf(add_fd
, "dn: cn=Domain Guests,ou=%s,%s\n", group_attr
,
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");
280 /* Write the Domain Computers entity */
281 fprintf(add_fd
, "# Domain Computers, %s, %s\n", group_attr
,
283 fprintf(add_fd
, "dn: cn=Domain Computers,ou=%s,%s\n",
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");
296 /* Write the Admininistrators Groups entity */
297 fprintf(add_fd
, "# Administrators, %s, %s\n", group_attr
,
299 fprintf(add_fd
, "dn: cn=Administrators,ou=%s,%s\n", group_attr
,
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
,
314 fprintf(add_fd
, "dn: cn=Print Operators,ou=%s,%s\n",
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");
327 /* Write the Backup Operators entity */
328 fprintf(add_fd
, "# Backup Operators, %s, %s\n", group_attr
,
330 fprintf(add_fd
, "dn: cn=Backup Operators,ou=%s,%s\n",
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");
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
,
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");
358 /* Deallocate memory, and return */
359 SAFE_FREE(suffix_attr
);
360 SAFE_FREE(user_attr
);
361 SAFE_FREE(group_attr
);
365 /****************************************************************
366 ****************************************************************/
368 static NTSTATUS
map_populate_groups(TALLOC_CTX
*mem_ctx
,
370 ACCOUNTMAP
*accountmap
,
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
) {
387 accountmap
[0].rid
= 512;
388 accountmap
[0].cn
= talloc_strdup(mem_ctx
, "Domain Admins");
389 if (accountmap
[0].cn
== NULL
) {
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
) {
402 accountmap
[1].rid
= 513;
403 accountmap
[1].cn
= talloc_strdup(mem_ctx
, "Domain Users");
404 if (accountmap
[1].cn
== NULL
) {
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
) {
417 accountmap
[2].rid
= 514;
418 accountmap
[2].cn
= talloc_strdup(mem_ctx
, "Domain Guests");
419 if (accountmap
[2].cn
== NULL
) {
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
) {
432 accountmap
[3].rid
= 515;
433 accountmap
[3].cn
= talloc_strdup(mem_ctx
, "Domain Computers");
434 if (accountmap
[3].cn
== NULL
) {
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
) {
447 accountmap
[4].rid
= 515;
448 accountmap
[4].cn
= talloc_strdup(mem_ctx
, "Administrators");
449 if (accountmap
[4].cn
== NULL
) {
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
) {
462 accountmap
[5].rid
= 550;
463 accountmap
[5].cn
= talloc_strdup(mem_ctx
, "Print Operators");
464 if (accountmap
[5].cn
== NULL
) {
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
) {
477 accountmap
[6].rid
= 551;
478 accountmap
[6].cn
= talloc_strdup(mem_ctx
, "Backup Operators");
479 if (accountmap
[6].cn
== NULL
) {
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
) {
492 accountmap
[7].rid
= 551;
493 accountmap
[7].cn
= talloc_strdup(mem_ctx
, "Replicators");
494 if (accountmap
[7].cn
== NULL
) {
498 SAFE_FREE(group_attr
);
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
, ...)
520 char *value
, *p
, *base64
;
521 DATA_BLOB base64_blob
;
522 bool do_base64
= false;
526 value
= talloc_vasprintf(NULL
, fmt
, ap
);
529 SMB_ASSERT(value
!= NULL
);
531 for (p
=value
; *p
; p
++) {
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.
546 only_whitespace
= false;
550 if (only_whitespace
) {
556 res
= fprintf(add_fd
, "%s: %s\n", attr_name
, value
);
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
);
572 /****************************************************************
573 ****************************************************************/
575 static NTSTATUS
fetch_group_info_to_ldif(TALLOC_CTX
*mem_ctx
,
576 struct netr_DELTA_GROUP
*r
,
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) */
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
);
601 /* Increment the gid for the new group */
605 /* Map the group rid, gid, and dn */
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
,
620 fprintf_attr(add_fd
, "dn", "cn=%s,ou=%s,%s", groupname
, group_attr
,
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");
632 SAFE_FREE(group_attr
);
637 /****************************************************************
638 ****************************************************************/
640 static NTSTATUS
fetch_account_info_to_ldif(TALLOC_CTX
*mem_ctx
,
641 struct netr_DELTA_USER
*r
,
643 ACCOUNTMAP
*accountmap
,
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
;
654 const char* nopasswd
= "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
656 uint32_t rid
= 0, group_rid
= 0, gidNumber
= 0;
660 memset(zero_buf
, '\0', sizeof(zero_buf
));
662 /* Get the username */
663 fstrcpy(username
, r
->account_name
.string
);
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
);
677 snprintf(homedir
, sizeof(homedir
), "/home/%s", username
);
679 snprintf(homedir
, sizeof(homedir
), "/nobodyshomedir");
681 ou
= lp_ldap_user_suffix(talloc_tos());
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
);
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
);
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 */
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;
727 DEBUG(1, ("Could not find rid %d in groupmap array\n",
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
,
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
);
760 fprintf_attr(add_fd
, "sambaHomePath", "%s", homepath
);
762 fprintf_attr(add_fd
, "sambaHomeDrive", "%s", homedrive
);
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");
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
);
774 fprintf_attr(add_fd
, "displayName", "%s", fullname
);
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");
790 /****************************************************************
791 ****************************************************************/
793 static NTSTATUS
fetch_alias_info_to_ldif(TALLOC_CTX
*mem_ctx
,
794 struct netr_DELTA_ALIAS
*r
,
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
:
816 case SAM_DATABASE_BUILTIN
:
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
);
840 /* Increment the gid for the new group */
844 /* Map the group rid and gid */
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
,
856 fprintf_attr(add_fd
, "dn", "cn=%s,ou=%s,%s", aliasname
, group_attr
,
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
);
866 fprintf_attr(add_fd
, "description", "%s", description
);
867 fprintf(add_fd
, "\n");
870 SAFE_FREE(group_attr
);
875 /****************************************************************
876 ****************************************************************/
878 static NTSTATUS
fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER
*r
,
881 ACCOUNTMAP
*accountmap
,
882 FILE *mod_fd
, int alloced
)
885 uint32_t group_rid
= 0, rid
= 0;
888 /* Get the dn for the group */
889 if (r
->num_rids
> 0) {
891 for (j
=0; j
<alloced
; j
++) {
892 if (groupmap
[j
].rid
== group_rid
) break;
895 DEBUG(1, ("Could not find rid %d in groupmap array\n",
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
++) {
905 for (k
=0; k
<alloced
; k
++) {
906 if (accountmap
[k
].rid
== rid
) break;
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");
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";
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"));
952 /* Get the ldap suffix */
953 if (!r
->suffix
|| !*r
->suffix
) {
954 DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
958 if (*ctx
&& (*ctx
)->initialized
) {
962 /* Ensure we have an output file */
964 r
->ldif_file
= fopen(ldif_filename
, "a");
966 r
->ldif_file
= stdout
;
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
;
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
;
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
;
990 mask
= umask(S_IRWXO
| S_IRWXG
);
991 fd
= mkstemp(r
->add_name
);
994 DEBUG(1, ("Could not create %s\n", r
->add_name
));
995 status
= NT_STATUS_UNSUCCESSFUL
;
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
));
1004 status
= NT_STATUS_UNSUCCESSFUL
;
1008 mask
= umask(S_IRWXO
| S_IRWXG
);
1009 fd
= mkstemp(r
->module_name
);
1012 DEBUG(1, ("Could not create %s\n", r
->module_name
));
1013 status
= NT_STATUS_UNSUCCESSFUL
;
1017 r
->mod_file
= fdopen(fd
, "w");
1018 if (r
->mod_file
== NULL
) {
1019 DEBUG(1, ("Could not open %s\n", r
->module_name
));
1021 status
= NT_STATUS_UNSUCCESSFUL
;
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
;
1034 /* Remember how many we malloced */
1037 /* Initial database population */
1038 if (database_id
== SAM_DATABASE_DOMAIN
) {
1040 status
= populate_ldap_for_ldif(domain_sid_str
,
1044 if (!NT_STATUS_IS_OK(status
)) {
1048 status
= map_populate_groups(mem_ctx
,
1054 if (!NT_STATUS_IS_OK(status
)) {
1059 r
->initialized
= true;
1063 return NT_STATUS_OK
;
1069 /****************************************************************
1070 ****************************************************************/
1072 static void ldif_free_context(struct samsync_ldif_context
*r
)
1078 /* Close and delete the ldif files */
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
)));
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
);
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
:
1165 case NETR_DELTA_GROUP
:
1166 fetch_group_info_to_ldif(mem_ctx
,
1168 &l
->groupmap
[*g_index_p
],
1170 ctx
->domain_sid_str
,
1175 case NETR_DELTA_USER
:
1176 fetch_account_info_to_ldif(mem_ctx
,
1179 &l
->accountmap
[*a_index_p
],
1181 ctx
->domain_sid_str
,
1187 case NETR_DELTA_ALIAS
:
1188 fetch_alias_info_to_ldif(mem_ctx
,
1190 &l
->groupmap
[*g_index_p
],
1192 ctx
->domain_sid_str
,
1198 case NETR_DELTA_GROUP_MEMBER
:
1199 fetch_groupmem_info_to_ldif(u
.group_member
,
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
:
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
,
1236 num_entries
+ l
->num_alloced
);
1238 l
->accountmap
= talloc_realloc(mem_ctx
,
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
)
1269 struct samsync_ldif_context
*ldif_ctx
=
1270 (struct samsync_ldif_context
*)ctx
->private_data
;
1272 status
= ldif_init_context(mem_ctx
,
1274 ctx
->output_filename
,
1275 ctx
->domain_sid_str
,
1277 if (!NT_STATUS_IS_OK(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
)
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
)) {
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
)) {
1314 return NT_STATUS_OK
;
1317 ldif_free_context(ldif_ctx
);
1318 ctx
->private_data
= NULL
;
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
;
1377 const struct samsync_ops libnet_samsync_ldif_ops
= {
1378 .startup
= init_ldif
,
1379 .process_objects
= fetch_sam_entries_ldif
,
1380 .finish
= close_ldif
,