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