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 "libnet/libnet_samsync.h"
29 #include "transfer_file.h"
34 /* uid's and gid's for writing deltas to ldif */
35 static uint32 ldif_gid
= 999;
36 static uint32 ldif_uid
= 999;
39 static uint32_t g_index
= 0;
40 static uint32_t a_index
= 0;
42 /* Structure for mapping accounts to groups */
43 /* Array element is the group rid */
44 typedef struct _groupmap
{
51 typedef struct _accountmap
{
56 struct samsync_ldif_context
{
58 ACCOUNTMAP
*accountmap
;
60 const char *add_template
;
61 const char *mod_template
;
72 Returns the substring from src between the first occurrence of
73 the char "front" and the first occurence of the char "back".
74 Mallocs the return string which must be freed. Not for use
75 with wide character strings.
77 static char *sstring_sub(const char *src
, char front
, char back
)
79 char *temp1
, *temp2
, *temp3
;
82 temp1
= strchr(src
, front
);
83 if (temp1
== NULL
) return NULL
;
84 temp2
= strchr(src
, back
);
85 if (temp2
== NULL
) return NULL
;
87 if (len
<= 0) return NULL
;
88 temp3
= (char*)SMB_MALLOC(len
);
90 DEBUG(1,("Malloc failure in sstring_sub\n"));
93 memcpy(temp3
, temp1
+1, len
-1);
98 /****************************************************************
99 ****************************************************************/
101 static NTSTATUS
populate_ldap_for_ldif(const char *sid
,
103 const char *builtin_sid
,
106 const char *user_suffix
, *group_suffix
, *machine_suffix
, *idmap_suffix
;
107 char *user_attr
=NULL
, *group_attr
=NULL
;
111 /* Get the suffix attribute */
112 suffix_attr
= sstring_sub(suffix
, '=', ',');
113 if (suffix_attr
== NULL
) {
114 len
= strlen(suffix
);
115 suffix_attr
= (char*)SMB_MALLOC(len
+1);
117 return NT_STATUS_NO_MEMORY
;
119 memcpy(suffix_attr
, suffix
, len
);
120 suffix_attr
[len
] = '\0';
124 fprintf(add_fd
, "# %s\n", suffix
);
125 fprintf(add_fd
, "dn: %s\n", suffix
);
126 fprintf(add_fd
, "objectClass: dcObject\n");
127 fprintf(add_fd
, "objectClass: organization\n");
128 fprintf(add_fd
, "o: %s\n", suffix_attr
);
129 fprintf(add_fd
, "dc: %s\n", suffix_attr
);
130 fprintf(add_fd
, "\n");
133 user_suffix
= lp_ldap_user_suffix();
134 if (user_suffix
== NULL
) {
135 SAFE_FREE(suffix_attr
);
136 return NT_STATUS_NO_MEMORY
;
138 /* If it exists and is distinct from other containers,
139 Write the Users entity */
140 if (*user_suffix
&& strcmp(user_suffix
, suffix
)) {
141 user_attr
= sstring_sub(lp_ldap_user_suffix(), '=', ',');
142 fprintf(add_fd
, "# %s\n", user_suffix
);
143 fprintf(add_fd
, "dn: %s\n", user_suffix
);
144 fprintf(add_fd
, "objectClass: organizationalUnit\n");
145 fprintf(add_fd
, "ou: %s\n", user_attr
);
146 fprintf(add_fd
, "\n");
151 group_suffix
= lp_ldap_group_suffix();
152 if (group_suffix
== NULL
) {
153 SAFE_FREE(suffix_attr
);
154 SAFE_FREE(user_attr
);
155 return NT_STATUS_NO_MEMORY
;
157 /* If it exists and is distinct from other containers,
158 Write the Groups entity */
159 if (*group_suffix
&& strcmp(group_suffix
, suffix
)) {
160 group_attr
= sstring_sub(lp_ldap_group_suffix(), '=', ',');
161 fprintf(add_fd
, "# %s\n", group_suffix
);
162 fprintf(add_fd
, "dn: %s\n", group_suffix
);
163 fprintf(add_fd
, "objectClass: organizationalUnit\n");
164 fprintf(add_fd
, "ou: %s\n", group_attr
);
165 fprintf(add_fd
, "\n");
169 /* If it exists and is distinct from other containers,
170 Write the Computers entity */
171 machine_suffix
= lp_ldap_machine_suffix();
172 if (machine_suffix
== NULL
) {
173 SAFE_FREE(suffix_attr
);
174 SAFE_FREE(user_attr
);
175 SAFE_FREE(group_attr
);
176 return NT_STATUS_NO_MEMORY
;
178 if (*machine_suffix
&& strcmp(machine_suffix
, user_suffix
) &&
179 strcmp(machine_suffix
, suffix
)) {
180 char *machine_ou
= NULL
;
181 fprintf(add_fd
, "# %s\n", machine_suffix
);
182 fprintf(add_fd
, "dn: %s\n", machine_suffix
);
183 fprintf(add_fd
, "objectClass: organizationalUnit\n");
184 /* this isn't totally correct as it assumes that
185 there _must_ be an ou. just fixing memleak now. jmcd */
186 machine_ou
= sstring_sub(lp_ldap_machine_suffix(), '=', ',');
187 fprintf(add_fd
, "ou: %s\n", machine_ou
);
188 SAFE_FREE(machine_ou
);
189 fprintf(add_fd
, "\n");
193 /* If it exists and is distinct from other containers,
194 Write the IdMap entity */
195 idmap_suffix
= lp_ldap_idmap_suffix();
196 if (idmap_suffix
== NULL
) {
197 SAFE_FREE(suffix_attr
);
198 SAFE_FREE(user_attr
);
199 SAFE_FREE(group_attr
);
200 return NT_STATUS_NO_MEMORY
;
203 strcmp(idmap_suffix
, user_suffix
) &&
204 strcmp(idmap_suffix
, suffix
)) {
206 fprintf(add_fd
, "# %s\n", idmap_suffix
);
207 fprintf(add_fd
, "dn: %s\n", idmap_suffix
);
208 fprintf(add_fd
, "ObjectClass: organizationalUnit\n");
209 s
= sstring_sub(lp_ldap_idmap_suffix(), '=', ',');
210 fprintf(add_fd
, "ou: %s\n", s
);
212 fprintf(add_fd
, "\n");
216 /* Write the domain entity */
217 fprintf(add_fd
, "# %s, %s\n", lp_workgroup(), suffix
);
218 fprintf(add_fd
, "dn: sambaDomainName=%s,%s\n", lp_workgroup(),
220 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_DOMINFO
);
221 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_IDPOOL
);
222 fprintf(add_fd
, "sambaDomainName: %s\n", lp_workgroup());
223 fprintf(add_fd
, "sambaSID: %s\n", sid
);
224 fprintf(add_fd
, "uidNumber: %d\n", ++ldif_uid
);
225 fprintf(add_fd
, "gidNumber: %d\n", ++ldif_gid
);
226 fprintf(add_fd
, "\n");
229 /* Write the Domain Admins entity */
230 fprintf(add_fd
, "# Domain Admins, %s, %s\n", group_attr
,
232 fprintf(add_fd
, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr
,
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 Admins\n");
237 fprintf(add_fd
, "memberUid: Administrator\n");
238 fprintf(add_fd
, "description: Netbios Domain Administrators\n");
239 fprintf(add_fd
, "gidNumber: 512\n");
240 fprintf(add_fd
, "sambaSID: %s-512\n", sid
);
241 fprintf(add_fd
, "sambaGroupType: 2\n");
242 fprintf(add_fd
, "displayName: Domain Admins\n");
243 fprintf(add_fd
, "\n");
246 /* Write the Domain Users entity */
247 fprintf(add_fd
, "# Domain Users, %s, %s\n", group_attr
,
249 fprintf(add_fd
, "dn: cn=Domain Users,ou=%s,%s\n", group_attr
,
251 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
252 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
253 fprintf(add_fd
, "cn: Domain Users\n");
254 fprintf(add_fd
, "description: Netbios Domain Users\n");
255 fprintf(add_fd
, "gidNumber: 513\n");
256 fprintf(add_fd
, "sambaSID: %s-513\n", sid
);
257 fprintf(add_fd
, "sambaGroupType: 2\n");
258 fprintf(add_fd
, "displayName: Domain Users\n");
259 fprintf(add_fd
, "\n");
262 /* Write the Domain Guests entity */
263 fprintf(add_fd
, "# Domain Guests, %s, %s\n", group_attr
,
265 fprintf(add_fd
, "dn: cn=Domain Guests,ou=%s,%s\n", group_attr
,
267 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
268 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
269 fprintf(add_fd
, "cn: Domain Guests\n");
270 fprintf(add_fd
, "description: Netbios Domain Guests\n");
271 fprintf(add_fd
, "gidNumber: 514\n");
272 fprintf(add_fd
, "sambaSID: %s-514\n", sid
);
273 fprintf(add_fd
, "sambaGroupType: 2\n");
274 fprintf(add_fd
, "displayName: Domain Guests\n");
275 fprintf(add_fd
, "\n");
278 /* Write the Domain Computers entity */
279 fprintf(add_fd
, "# Domain Computers, %s, %s\n", group_attr
,
281 fprintf(add_fd
, "dn: cn=Domain Computers,ou=%s,%s\n",
283 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
284 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
285 fprintf(add_fd
, "gidNumber: 515\n");
286 fprintf(add_fd
, "cn: Domain Computers\n");
287 fprintf(add_fd
, "description: Netbios Domain Computers accounts\n");
288 fprintf(add_fd
, "sambaSID: %s-515\n", sid
);
289 fprintf(add_fd
, "sambaGroupType: 2\n");
290 fprintf(add_fd
, "displayName: Domain Computers\n");
291 fprintf(add_fd
, "\n");
294 /* Write the Admininistrators Groups entity */
295 fprintf(add_fd
, "# Administrators, %s, %s\n", group_attr
,
297 fprintf(add_fd
, "dn: cn=Administrators,ou=%s,%s\n", group_attr
,
299 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
300 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
301 fprintf(add_fd
, "gidNumber: 544\n");
302 fprintf(add_fd
, "cn: Administrators\n");
303 fprintf(add_fd
, "description: Netbios Domain Members can fully administer the computer/sambaDomainName\n");
304 fprintf(add_fd
, "sambaSID: %s-544\n", builtin_sid
);
305 fprintf(add_fd
, "sambaGroupType: 5\n");
306 fprintf(add_fd
, "displayName: Administrators\n");
307 fprintf(add_fd
, "\n");
309 /* Write the Print Operator entity */
310 fprintf(add_fd
, "# Print Operators, %s, %s\n", group_attr
,
312 fprintf(add_fd
, "dn: cn=Print Operators,ou=%s,%s\n",
314 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
315 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
316 fprintf(add_fd
, "gidNumber: 550\n");
317 fprintf(add_fd
, "cn: Print Operators\n");
318 fprintf(add_fd
, "description: Netbios Domain Print Operators\n");
319 fprintf(add_fd
, "sambaSID: %s-550\n", builtin_sid
);
320 fprintf(add_fd
, "sambaGroupType: 5\n");
321 fprintf(add_fd
, "displayName: Print Operators\n");
322 fprintf(add_fd
, "\n");
325 /* Write the Backup Operators entity */
326 fprintf(add_fd
, "# Backup Operators, %s, %s\n", group_attr
,
328 fprintf(add_fd
, "dn: cn=Backup Operators,ou=%s,%s\n",
330 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
331 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
332 fprintf(add_fd
, "gidNumber: 551\n");
333 fprintf(add_fd
, "cn: Backup Operators\n");
334 fprintf(add_fd
, "description: Netbios Domain Members can bypass file security to back up files\n");
335 fprintf(add_fd
, "sambaSID: %s-551\n", builtin_sid
);
336 fprintf(add_fd
, "sambaGroupType: 5\n");
337 fprintf(add_fd
, "displayName: Backup Operators\n");
338 fprintf(add_fd
, "\n");
341 /* Write the Replicators entity */
342 fprintf(add_fd
, "# Replicators, %s, %s\n", group_attr
, suffix
);
343 fprintf(add_fd
, "dn: cn=Replicators,ou=%s,%s\n", group_attr
,
345 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
346 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
347 fprintf(add_fd
, "gidNumber: 552\n");
348 fprintf(add_fd
, "cn: Replicators\n");
349 fprintf(add_fd
, "description: Netbios Domain Supports file replication in a sambaDomainName\n");
350 fprintf(add_fd
, "sambaSID: %s-552\n", builtin_sid
);
351 fprintf(add_fd
, "sambaGroupType: 5\n");
352 fprintf(add_fd
, "displayName: Replicators\n");
353 fprintf(add_fd
, "\n");
356 /* Deallocate memory, and return */
357 SAFE_FREE(suffix_attr
);
358 SAFE_FREE(user_attr
);
359 SAFE_FREE(group_attr
);
363 /****************************************************************
364 ****************************************************************/
366 static NTSTATUS
map_populate_groups(TALLOC_CTX
*mem_ctx
,
368 ACCOUNTMAP
*accountmap
,
371 const char *builtin_sid
)
373 char *group_attr
= sstring_sub(lp_ldap_group_suffix(), '=', ',');
375 /* Map the groups created by populate_ldap_for_ldif */
376 groupmap
[0].rid
= 512;
377 groupmap
[0].gidNumber
= 512;
378 groupmap
[0].sambaSID
= talloc_asprintf(mem_ctx
, "%s-512", sid
);
379 groupmap
[0].group_dn
= talloc_asprintf(mem_ctx
,
380 "cn=Domain Admins,ou=%s,%s", group_attr
, suffix
);
381 if (groupmap
[0].sambaSID
== NULL
|| groupmap
[0].group_dn
== NULL
) {
385 accountmap
[0].rid
= 512;
386 accountmap
[0].cn
= talloc_strdup(mem_ctx
, "Domain Admins");
387 if (accountmap
[0].cn
== NULL
) {
391 groupmap
[1].rid
= 513;
392 groupmap
[1].gidNumber
= 513;
393 groupmap
[1].sambaSID
= talloc_asprintf(mem_ctx
, "%s-513", sid
);
394 groupmap
[1].group_dn
= talloc_asprintf(mem_ctx
,
395 "cn=Domain Users,ou=%s,%s", group_attr
, suffix
);
396 if (groupmap
[1].sambaSID
== NULL
|| groupmap
[1].group_dn
== NULL
) {
400 accountmap
[1].rid
= 513;
401 accountmap
[1].cn
= talloc_strdup(mem_ctx
, "Domain Users");
402 if (accountmap
[1].cn
== NULL
) {
406 groupmap
[2].rid
= 514;
407 groupmap
[2].gidNumber
= 514;
408 groupmap
[2].sambaSID
= talloc_asprintf(mem_ctx
, "%s-514", sid
);
409 groupmap
[2].group_dn
= talloc_asprintf(mem_ctx
,
410 "cn=Domain Guests,ou=%s,%s", group_attr
, suffix
);
411 if (groupmap
[2].sambaSID
== NULL
|| groupmap
[2].group_dn
== NULL
) {
415 accountmap
[2].rid
= 514;
416 accountmap
[2].cn
= talloc_strdup(mem_ctx
, "Domain Guests");
417 if (accountmap
[2].cn
== NULL
) {
421 groupmap
[3].rid
= 515;
422 groupmap
[3].gidNumber
= 515;
423 groupmap
[3].sambaSID
= talloc_asprintf(mem_ctx
, "%s-515", sid
);
424 groupmap
[3].group_dn
= talloc_asprintf(mem_ctx
,
425 "cn=Domain Computers,ou=%s,%s", group_attr
, suffix
);
426 if (groupmap
[3].sambaSID
== NULL
|| groupmap
[3].group_dn
== NULL
) {
430 accountmap
[3].rid
= 515;
431 accountmap
[3].cn
= talloc_strdup(mem_ctx
, "Domain Computers");
432 if (accountmap
[3].cn
== NULL
) {
436 groupmap
[4].rid
= 544;
437 groupmap
[4].gidNumber
= 544;
438 groupmap
[4].sambaSID
= talloc_asprintf(mem_ctx
, "%s-544", builtin_sid
);
439 groupmap
[4].group_dn
= talloc_asprintf(mem_ctx
,
440 "cn=Administrators,ou=%s,%s", group_attr
, suffix
);
441 if (groupmap
[4].sambaSID
== NULL
|| groupmap
[4].group_dn
== NULL
) {
445 accountmap
[4].rid
= 515;
446 accountmap
[4].cn
= talloc_strdup(mem_ctx
, "Administrators");
447 if (accountmap
[4].cn
== NULL
) {
451 groupmap
[5].rid
= 550;
452 groupmap
[5].gidNumber
= 550;
453 groupmap
[5].sambaSID
= talloc_asprintf(mem_ctx
, "%s-550", builtin_sid
);
454 groupmap
[5].group_dn
= talloc_asprintf(mem_ctx
,
455 "cn=Print Operators,ou=%s,%s", group_attr
, suffix
);
456 if (groupmap
[5].sambaSID
== NULL
|| groupmap
[5].group_dn
== NULL
) {
460 accountmap
[5].rid
= 550;
461 accountmap
[5].cn
= talloc_strdup(mem_ctx
, "Print Operators");
462 if (accountmap
[5].cn
== NULL
) {
466 groupmap
[6].rid
= 551;
467 groupmap
[6].gidNumber
= 551;
468 groupmap
[6].sambaSID
= talloc_asprintf(mem_ctx
, "%s-551", builtin_sid
);
469 groupmap
[6].group_dn
= talloc_asprintf(mem_ctx
,
470 "cn=Backup Operators,ou=%s,%s", group_attr
, suffix
);
471 if (groupmap
[6].sambaSID
== NULL
|| groupmap
[6].group_dn
== NULL
) {
475 accountmap
[6].rid
= 551;
476 accountmap
[6].cn
= talloc_strdup(mem_ctx
, "Backup Operators");
477 if (accountmap
[6].cn
== NULL
) {
481 groupmap
[7].rid
= 552;
482 groupmap
[7].gidNumber
= 552;
483 groupmap
[7].sambaSID
= talloc_asprintf(mem_ctx
, "%s-552", builtin_sid
);
484 groupmap
[7].group_dn
= talloc_asprintf(mem_ctx
,
485 "cn=Replicators,ou=%s,%s", group_attr
, suffix
);
486 if (groupmap
[7].sambaSID
== NULL
|| groupmap
[7].group_dn
== NULL
) {
490 accountmap
[7].rid
= 551;
491 accountmap
[7].cn
= talloc_strdup(mem_ctx
, "Replicators");
492 if (accountmap
[7].cn
== NULL
) {
496 SAFE_FREE(group_attr
);
502 SAFE_FREE(group_attr
);
503 return NT_STATUS_NO_MEMORY
;
507 * This is a crap routine, but I think it's the quickest way to solve the
508 * UTF8->base64 problem.
511 static int fprintf_attr(FILE *add_fd
, const char *attr_name
,
512 const char *fmt
, ...)
515 char *value
, *p
, *base64
;
516 DATA_BLOB base64_blob
;
517 bool do_base64
= false;
521 value
= talloc_vasprintf(NULL
, fmt
, ap
);
524 SMB_ASSERT(value
!= NULL
);
526 for (p
=value
; *p
; p
++) {
534 bool only_whitespace
= true;
535 for (p
=value
; *p
; p
++) {
537 * I know that this not multibyte safe, but we break
538 * on the first non-whitespace character anyway.
541 only_whitespace
= false;
545 if (only_whitespace
) {
551 res
= fprintf(add_fd
, "%s: %s\n", attr_name
, value
);
556 base64_blob
.data
= (unsigned char *)value
;
557 base64_blob
.length
= strlen(value
);
559 base64
= base64_encode_data_blob(value
, base64_blob
);
560 SMB_ASSERT(base64
!= NULL
);
562 res
= fprintf(add_fd
, "%s:: %s\n", attr_name
, base64
);
567 /****************************************************************
568 ****************************************************************/
570 static NTSTATUS
fetch_group_info_to_ldif(TALLOC_CTX
*mem_ctx
,
571 struct netr_DELTA_GROUP
*r
,
577 const char *groupname
= r
->group_name
.string
;
578 uint32 grouptype
= 0, g_rid
= 0;
579 char *group_attr
= sstring_sub(lp_ldap_group_suffix(), '=', ',');
581 /* Set up the group type (always 2 for group info) */
584 /* These groups are entered by populate_ldap_for_ldif */
585 if (strcmp(groupname
, "Domain Admins") == 0 ||
586 strcmp(groupname
, "Domain Users") == 0 ||
587 strcmp(groupname
, "Domain Guests") == 0 ||
588 strcmp(groupname
, "Domain Computers") == 0 ||
589 strcmp(groupname
, "Administrators") == 0 ||
590 strcmp(groupname
, "Print Operators") == 0 ||
591 strcmp(groupname
, "Backup Operators") == 0 ||
592 strcmp(groupname
, "Replicators") == 0) {
593 SAFE_FREE(group_attr
);
596 /* Increment the gid for the new group */
600 /* Map the group rid, gid, and dn */
602 groupmap
->rid
= g_rid
;
603 groupmap
->gidNumber
= ldif_gid
;
604 groupmap
->sambaSID
= talloc_asprintf(mem_ctx
, "%s-%d", sid
, g_rid
);
605 groupmap
->group_dn
= talloc_asprintf(mem_ctx
,
606 "cn=%s,ou=%s,%s", groupname
, group_attr
, suffix
);
607 if (groupmap
->sambaSID
== NULL
|| groupmap
->group_dn
== NULL
) {
608 SAFE_FREE(group_attr
);
609 return NT_STATUS_NO_MEMORY
;
612 /* Write the data to the temporary add ldif file */
613 fprintf(add_fd
, "# %s, %s, %s\n", groupname
, group_attr
,
615 fprintf_attr(add_fd
, "dn", "cn=%s,ou=%s,%s", groupname
, group_attr
,
617 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
618 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
619 fprintf_attr(add_fd
, "cn", "%s", groupname
);
620 fprintf(add_fd
, "gidNumber: %d\n", ldif_gid
);
621 fprintf(add_fd
, "sambaSID: %s\n", groupmap
->sambaSID
);
622 fprintf(add_fd
, "sambaGroupType: %d\n", grouptype
);
623 fprintf_attr(add_fd
, "displayName", "%s", groupname
);
624 fprintf(add_fd
, "\n");
627 SAFE_FREE(group_attr
);
632 /****************************************************************
633 ****************************************************************/
635 static NTSTATUS
fetch_account_info_to_ldif(TALLOC_CTX
*mem_ctx
,
636 struct netr_DELTA_USER
*r
,
638 ACCOUNTMAP
*accountmap
,
644 fstring username
, logonscript
, homedrive
, homepath
= "", homedir
= "";
645 fstring hex_nt_passwd
, hex_lm_passwd
;
646 fstring description
, profilepath
, fullname
, sambaSID
;
647 char *flags
, *user_rdn
;
649 const char* nopasswd
= "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
651 uint32 rid
= 0, group_rid
= 0, gidNumber
= 0;
655 memset(zero_buf
, '\0', sizeof(zero_buf
));
657 /* Get the username */
658 fstrcpy(username
, r
->account_name
.string
);
663 /* Map the rid and username for group member info later */
664 accountmap
->rid
= rid
;
665 accountmap
->cn
= talloc_strdup(mem_ctx
, username
);
666 NT_STATUS_HAVE_NO_MEMORY(accountmap
->cn
);
668 /* Get the home directory */
669 if (r
->acct_flags
& ACB_NORMAL
) {
670 fstrcpy(homedir
, r
->home_directory
.string
);
672 snprintf(homedir
, sizeof(homedir
), "/home/%s", username
);
674 snprintf(homedir
, sizeof(homedir
), "/nobodyshomedir");
676 ou
= lp_ldap_user_suffix();
678 ou
= lp_ldap_machine_suffix();
679 snprintf(homedir
, sizeof(homedir
), "/machinehomedir");
682 /* Get the logon script */
683 fstrcpy(logonscript
, r
->logon_script
.string
);
685 /* Get the home drive */
686 fstrcpy(homedrive
, r
->home_drive
.string
);
688 /* Get the home path */
689 fstrcpy(homepath
, r
->home_directory
.string
);
691 /* Get the description */
692 fstrcpy(description
, r
->description
.string
);
694 /* Get the display name */
695 fstrcpy(fullname
, r
->full_name
.string
);
697 /* Get the profile path */
698 fstrcpy(profilepath
, r
->profile_path
.string
);
700 /* Get lm and nt password data */
701 if (memcmp(r
->lmpassword
.hash
, zero_buf
, 16) != 0) {
702 pdb_sethexpwd(hex_lm_passwd
, r
->lmpassword
.hash
, r
->acct_flags
);
704 pdb_sethexpwd(hex_lm_passwd
, NULL
, 0);
706 if (memcmp(r
->ntpassword
.hash
, zero_buf
, 16) != 0) {
707 pdb_sethexpwd(hex_nt_passwd
, r
->ntpassword
.hash
, r
->acct_flags
);
709 pdb_sethexpwd(hex_nt_passwd
, NULL
, 0);
711 unix_time
= nt_time_to_unix(r
->last_password_change
);
713 /* Increment the uid for the new user */
716 /* Set up group id and sambaSID for the user */
717 group_rid
= r
->primary_gid
;
718 for (i
=0; i
<alloced
; i
++) {
719 if (groupmap
[i
].rid
== group_rid
) break;
722 DEBUG(1, ("Could not find rid %d in groupmap array\n",
724 return NT_STATUS_UNSUCCESSFUL
;
726 gidNumber
= groupmap
[i
].gidNumber
;
727 ret
= snprintf(sambaSID
, sizeof(sambaSID
), "%s", groupmap
[i
].sambaSID
);
728 if (ret
< 0 || ret
== sizeof(sambaSID
)) {
729 return NT_STATUS_UNSUCCESSFUL
;
732 /* Set up sambaAcctFlags */
733 flags
= pdb_encode_acct_ctrl(r
->acct_flags
,
734 NEW_PW_FORMAT_SPACE_PADDED_LEN
);
736 /* Add the user to the temporary add ldif file */
737 /* this isn't quite right...we can't assume there's just OU=. jmcd */
738 user_rdn
= sstring_sub(ou
, '=', ',');
739 fprintf(add_fd
, "# %s, %s, %s\n", username
, user_rdn
, suffix
);
740 fprintf_attr(add_fd
, "dn", "uid=%s,ou=%s,%s", username
, user_rdn
,
743 fprintf(add_fd
, "ObjectClass: top\n");
744 fprintf(add_fd
, "objectClass: inetOrgPerson\n");
745 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT
);
746 fprintf(add_fd
, "objectClass: shadowAccount\n");
747 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT
);
748 fprintf_attr(add_fd
, "cn", "%s", username
);
749 fprintf_attr(add_fd
, "sn", "%s", username
);
750 fprintf_attr(add_fd
, "uid", "%s", username
);
751 fprintf(add_fd
, "uidNumber: %d\n", ldif_uid
);
752 fprintf(add_fd
, "gidNumber: %d\n", gidNumber
);
753 fprintf_attr(add_fd
, "homeDirectory", "%s", homedir
);
755 fprintf_attr(add_fd
, "sambaHomePath", "%s", homepath
);
757 fprintf_attr(add_fd
, "sambaHomeDrive", "%s", homedrive
);
759 fprintf_attr(add_fd
, "sambaLogonScript", "%s", logonscript
);
760 fprintf(add_fd
, "loginShell: %s\n",
761 ((r
->acct_flags
& ACB_NORMAL
) ?
762 "/bin/bash" : "/bin/false"));
763 fprintf(add_fd
, "gecos: System User\n");
765 fprintf_attr(add_fd
, "description", "%s", description
);
766 fprintf(add_fd
, "sambaSID: %s-%d\n", sid
, rid
);
767 fprintf(add_fd
, "sambaPrimaryGroupSID: %s\n", sambaSID
);
769 fprintf_attr(add_fd
, "displayName", "%s", fullname
);
771 fprintf_attr(add_fd
, "sambaProfilePath", "%s", profilepath
);
772 if (strcmp(nopasswd
, hex_lm_passwd
) != 0)
773 fprintf(add_fd
, "sambaLMPassword: %s\n", hex_lm_passwd
);
774 if (strcmp(nopasswd
, hex_nt_passwd
) != 0)
775 fprintf(add_fd
, "sambaNTPassword: %s\n", hex_nt_passwd
);
776 fprintf(add_fd
, "sambaPwdLastSet: %d\n", (int)unix_time
);
777 fprintf(add_fd
, "sambaAcctFlags: %s\n", flags
);
778 fprintf(add_fd
, "\n");
785 /****************************************************************
786 ****************************************************************/
788 static NTSTATUS
fetch_alias_info_to_ldif(TALLOC_CTX
*mem_ctx
,
789 struct netr_DELTA_ALIAS
*r
,
794 enum netr_SamDatabaseID database_id
)
796 fstring aliasname
, description
;
797 uint32 grouptype
= 0, g_rid
= 0;
798 char *group_attr
= sstring_sub(lp_ldap_group_suffix(), '=', ',');
800 /* Get the alias name */
801 fstrcpy(aliasname
, r
->alias_name
.string
);
803 /* Get the alias description */
804 fstrcpy(description
, r
->description
.string
);
806 /* Set up the group type */
807 switch (database_id
) {
808 case SAM_DATABASE_DOMAIN
:
811 case SAM_DATABASE_BUILTIN
:
820 These groups are entered by populate_ldap_for_ldif
821 Note that populate creates a group called Relicators,
822 but NT returns a group called Replicator
824 if (strcmp(aliasname
, "Domain Admins") == 0 ||
825 strcmp(aliasname
, "Domain Users") == 0 ||
826 strcmp(aliasname
, "Domain Guests") == 0 ||
827 strcmp(aliasname
, "Domain Computers") == 0 ||
828 strcmp(aliasname
, "Administrators") == 0 ||
829 strcmp(aliasname
, "Print Operators") == 0 ||
830 strcmp(aliasname
, "Backup Operators") == 0 ||
831 strcmp(aliasname
, "Replicator") == 0) {
832 SAFE_FREE(group_attr
);
835 /* Increment the gid for the new group */
839 /* Map the group rid and gid */
841 groupmap
->gidNumber
= ldif_gid
;
842 groupmap
->sambaSID
= talloc_asprintf(mem_ctx
, "%s-%d", sid
, g_rid
);
843 if (groupmap
->sambaSID
== NULL
) {
844 SAFE_FREE(group_attr
);
845 return NT_STATUS_NO_MEMORY
;
848 /* Write the data to the temporary add ldif file */
849 fprintf(add_fd
, "# %s, %s, %s\n", aliasname
, group_attr
,
851 fprintf_attr(add_fd
, "dn", "cn=%s,ou=%s,%s", aliasname
, group_attr
,
853 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
854 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
855 fprintf(add_fd
, "cn: %s\n", aliasname
);
856 fprintf(add_fd
, "gidNumber: %d\n", ldif_gid
);
857 fprintf(add_fd
, "sambaSID: %s\n", groupmap
->sambaSID
);
858 fprintf(add_fd
, "sambaGroupType: %d\n", grouptype
);
859 fprintf_attr(add_fd
, "displayName", "%s", aliasname
);
861 fprintf_attr(add_fd
, "description", "%s", description
);
862 fprintf(add_fd
, "\n");
865 SAFE_FREE(group_attr
);
870 /****************************************************************
871 ****************************************************************/
873 static NTSTATUS
fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER
*r
,
876 ACCOUNTMAP
*accountmap
,
877 FILE *mod_fd
, int alloced
)
880 uint32 group_rid
= 0, rid
= 0;
883 /* Get the dn for the group */
884 if (r
->num_rids
> 0) {
886 for (j
=0; j
<alloced
; j
++) {
887 if (groupmap
[j
].rid
== group_rid
) break;
890 DEBUG(1, ("Could not find rid %d in groupmap array\n",
892 return NT_STATUS_UNSUCCESSFUL
;
894 snprintf(group_dn
, sizeof(group_dn
), "%s", groupmap
[j
].group_dn
);
895 fprintf(mod_fd
, "dn: %s\n", group_dn
);
897 /* Get the cn for each member */
898 for (i
=0; i
< r
->num_rids
; i
++) {
900 for (k
=0; k
<alloced
; k
++) {
901 if (accountmap
[k
].rid
== rid
) break;
904 DEBUG(1, ("Could not find rid %d in "
905 "accountmap array\n", rid
));
906 return NT_STATUS_UNSUCCESSFUL
;
908 fprintf(mod_fd
, "memberUid: %s\n", accountmap
[k
].cn
);
910 fprintf(mod_fd
, "\n");
918 /****************************************************************
919 ****************************************************************/
921 static NTSTATUS
ldif_init_context(TALLOC_CTX
*mem_ctx
,
922 enum netr_SamDatabaseID database_id
,
923 const char *ldif_filename
,
924 const char *domain_sid_str
,
925 struct samsync_ldif_context
**ctx
)
927 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
928 struct samsync_ldif_context
*r
;
929 const char *add_template
= "/tmp/add.ldif.XXXXXX";
930 const char *mod_template
= "/tmp/mod.ldif.XXXXXX";
931 const char *builtin_sid
= "S-1-5-32";
933 /* Get other smb.conf data */
934 if (!(lp_workgroup()) || !*(lp_workgroup())) {
935 DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
939 /* Get the ldap suffix */
940 if (!(lp_ldap_suffix()) || !*(lp_ldap_suffix())) {
941 DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
945 if (*ctx
&& (*ctx
)->initialized
) {
949 r
= talloc_zero(mem_ctx
, struct samsync_ldif_context
);
950 NT_STATUS_HAVE_NO_MEMORY(r
);
952 /* Get the ldap suffix */
953 r
->suffix
= lp_ldap_suffix();
955 /* Ensure we have an output file */
957 r
->ldif_file
= fopen(ldif_filename
, "a");
959 r
->ldif_file
= stdout
;
963 fprintf(stderr
, "Could not open %s\n", ldif_filename
);
964 DEBUG(1, ("Could not open %s\n", ldif_filename
));
965 status
= NT_STATUS_UNSUCCESSFUL
;
969 r
->add_template
= talloc_strdup(mem_ctx
, add_template
);
970 r
->mod_template
= talloc_strdup(mem_ctx
, mod_template
);
971 if (!r
->add_template
|| !r
->mod_template
) {
972 status
= NT_STATUS_NO_MEMORY
;
976 r
->add_name
= talloc_strdup(mem_ctx
, add_template
);
977 r
->module_name
= talloc_strdup(mem_ctx
, mod_template
);
978 if (!r
->add_name
|| !r
->module_name
) {
979 status
= NT_STATUS_NO_MEMORY
;
983 /* Open the add and mod ldif files */
984 if (!(r
->add_file
= fdopen(mkstemp(r
->add_name
),"w"))) {
985 DEBUG(1, ("Could not open %s\n", r
->add_name
));
986 status
= NT_STATUS_UNSUCCESSFUL
;
989 if (!(r
->mod_file
= fdopen(mkstemp(r
->module_name
),"w"))) {
990 DEBUG(1, ("Could not open %s\n", r
->module_name
));
991 status
= NT_STATUS_UNSUCCESSFUL
;
995 /* Allocate initial memory for groupmap and accountmap arrays */
996 r
->groupmap
= talloc_zero_array(mem_ctx
, GROUPMAP
, 8);
997 r
->accountmap
= talloc_zero_array(mem_ctx
, ACCOUNTMAP
, 8);
998 if (r
->groupmap
== NULL
|| r
->accountmap
== NULL
) {
999 DEBUG(1,("GROUPMAP talloc failed\n"));
1000 status
= NT_STATUS_NO_MEMORY
;
1004 /* Remember how many we malloced */
1007 /* Initial database population */
1008 if (database_id
== SAM_DATABASE_DOMAIN
) {
1010 status
= populate_ldap_for_ldif(domain_sid_str
,
1014 if (!NT_STATUS_IS_OK(status
)) {
1018 status
= map_populate_groups(mem_ctx
,
1024 if (!NT_STATUS_IS_OK(status
)) {
1029 r
->initialized
= true;
1033 return NT_STATUS_OK
;
1039 /****************************************************************
1040 ****************************************************************/
1042 static void ldif_free_context(struct samsync_ldif_context
*r
)
1048 /* Close and delete the ldif files */
1050 fclose(r
->add_file
);
1053 if ((r
->add_name
!= NULL
) &&
1054 strcmp(r
->add_name
, r
->add_template
) && (unlink(r
->add_name
))) {
1055 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1056 r
->add_name
, strerror(errno
)));
1060 fclose(r
->mod_file
);
1063 if ((r
->module_name
!= NULL
) &&
1064 strcmp(r
->module_name
, r
->mod_template
) && (unlink(r
->module_name
))) {
1065 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1066 r
->module_name
, strerror(errno
)));
1069 if (r
->ldif_file
&& (r
->ldif_file
!= stdout
)) {
1070 fclose(r
->ldif_file
);
1076 /****************************************************************
1077 ****************************************************************/
1079 static void ldif_write_output(enum netr_SamDatabaseID database_id
,
1080 struct samsync_ldif_context
*l
)
1082 /* Write ldif data to the user's file */
1083 if (database_id
== SAM_DATABASE_DOMAIN
) {
1084 fprintf(l
->ldif_file
,
1085 "# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
1086 fprintf(l
->ldif_file
,
1087 "# =================================\n\n");
1088 fflush(l
->ldif_file
);
1089 } else if (database_id
== SAM_DATABASE_BUILTIN
) {
1090 fprintf(l
->ldif_file
,
1091 "# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
1092 fprintf(l
->ldif_file
,
1093 "# ==================================\n\n");
1094 fflush(l
->ldif_file
);
1096 fseek(l
->add_file
, 0, SEEK_SET
);
1097 transfer_file(fileno(l
->add_file
), fileno(l
->ldif_file
), (size_t) -1);
1099 if (database_id
== SAM_DATABASE_DOMAIN
) {
1100 fprintf(l
->ldif_file
,
1101 "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
1102 fprintf(l
->ldif_file
,
1103 "# ====================================\n\n");
1104 fflush(l
->ldif_file
);
1105 } else if (database_id
== SAM_DATABASE_BUILTIN
) {
1106 fprintf(l
->ldif_file
,
1107 "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
1108 fprintf(l
->ldif_file
,
1109 "# =====================================\n\n");
1110 fflush(l
->ldif_file
);
1112 fseek(l
->mod_file
, 0, SEEK_SET
);
1113 transfer_file(fileno(l
->mod_file
), fileno(l
->ldif_file
), (size_t) -1);
1116 /****************************************************************
1117 ****************************************************************/
1119 static NTSTATUS
fetch_sam_entry_ldif(TALLOC_CTX
*mem_ctx
,
1120 enum netr_SamDatabaseID database_id
,
1121 struct netr_DELTA_ENUM
*r
,
1122 struct samsync_context
*ctx
,
1123 uint32_t *a_index_p
,
1124 uint32_t *g_index_p
)
1126 union netr_DELTA_UNION u
= r
->delta_union
;
1127 union netr_DELTA_ID_UNION id
= r
->delta_id_union
;
1128 struct samsync_ldif_context
*l
=
1129 talloc_get_type_abort(ctx
->private_data
, struct samsync_ldif_context
);
1131 switch (r
->delta_type
) {
1132 case NETR_DELTA_DOMAIN
:
1135 case NETR_DELTA_GROUP
:
1136 fetch_group_info_to_ldif(mem_ctx
,
1138 &l
->groupmap
[*g_index_p
],
1140 ctx
->domain_sid_str
,
1145 case NETR_DELTA_USER
:
1146 fetch_account_info_to_ldif(mem_ctx
,
1149 &l
->accountmap
[*a_index_p
],
1151 ctx
->domain_sid_str
,
1157 case NETR_DELTA_ALIAS
:
1158 fetch_alias_info_to_ldif(mem_ctx
,
1160 &l
->groupmap
[*g_index_p
],
1162 ctx
->domain_sid_str
,
1168 case NETR_DELTA_GROUP_MEMBER
:
1169 fetch_groupmem_info_to_ldif(u
.group_member
,
1177 case NETR_DELTA_ALIAS_MEMBER
:
1178 case NETR_DELTA_POLICY
:
1179 case NETR_DELTA_ACCOUNT
:
1180 case NETR_DELTA_TRUSTED_DOMAIN
:
1181 case NETR_DELTA_SECRET
:
1182 case NETR_DELTA_RENAME_GROUP
:
1183 case NETR_DELTA_RENAME_USER
:
1184 case NETR_DELTA_RENAME_ALIAS
:
1185 case NETR_DELTA_DELETE_GROUP
:
1186 case NETR_DELTA_DELETE_USER
:
1187 case NETR_DELTA_MODIFY_COUNT
:
1190 } /* end of switch */
1192 return NT_STATUS_OK
;
1195 /****************************************************************
1196 ****************************************************************/
1198 static NTSTATUS
ldif_realloc_maps(TALLOC_CTX
*mem_ctx
,
1199 struct samsync_ldif_context
*l
,
1200 uint32_t num_entries
)
1202 /* Re-allocate memory for groupmap and accountmap arrays */
1203 l
->groupmap
= talloc_realloc(mem_ctx
,
1206 num_entries
+ l
->num_alloced
);
1208 l
->accountmap
= talloc_realloc(mem_ctx
,
1211 num_entries
+ l
->num_alloced
);
1213 if (l
->groupmap
== NULL
|| l
->accountmap
== NULL
) {
1214 DEBUG(1,("GROUPMAP talloc failed\n"));
1215 return NT_STATUS_NO_MEMORY
;
1218 /* Initialize the new records */
1219 memset(&(l
->groupmap
[l
->num_alloced
]), 0,
1220 sizeof(GROUPMAP
) * num_entries
);
1221 memset(&(l
->accountmap
[l
->num_alloced
]), 0,
1222 sizeof(ACCOUNTMAP
) * num_entries
);
1224 /* Remember how many we alloced this time */
1225 l
->num_alloced
+= num_entries
;
1227 return NT_STATUS_OK
;
1230 /****************************************************************
1231 ****************************************************************/
1233 static NTSTATUS
init_ldif(TALLOC_CTX
*mem_ctx
,
1234 struct samsync_context
*ctx
,
1235 enum netr_SamDatabaseID database_id
,
1236 uint64_t *sequence_num
)
1239 struct samsync_ldif_context
*ldif_ctx
=
1240 (struct samsync_ldif_context
*)ctx
->private_data
;
1242 status
= ldif_init_context(mem_ctx
,
1244 ctx
->output_filename
,
1245 ctx
->domain_sid_str
,
1247 if (!NT_STATUS_IS_OK(status
)) {
1251 ctx
->private_data
= ldif_ctx
;
1253 return NT_STATUS_OK
;
1256 /****************************************************************
1257 ****************************************************************/
1259 static NTSTATUS
fetch_sam_entries_ldif(TALLOC_CTX
*mem_ctx
,
1260 enum netr_SamDatabaseID database_id
,
1261 struct netr_DELTA_ENUM_ARRAY
*r
,
1262 uint64_t *sequence_num
,
1263 struct samsync_context
*ctx
)
1267 struct samsync_ldif_context
*ldif_ctx
=
1268 (struct samsync_ldif_context
*)ctx
->private_data
;
1270 status
= ldif_realloc_maps(mem_ctx
, ldif_ctx
, r
->num_deltas
);
1271 if (!NT_STATUS_IS_OK(status
)) {
1275 for (i
= 0; i
< r
->num_deltas
; i
++) {
1276 status
= fetch_sam_entry_ldif(mem_ctx
, database_id
,
1277 &r
->delta_enum
[i
], ctx
,
1278 &a_index
, &g_index
);
1279 if (!NT_STATUS_IS_OK(status
)) {
1284 return NT_STATUS_OK
;
1287 ldif_free_context(ldif_ctx
);
1288 ctx
->private_data
= NULL
;
1293 /****************************************************************
1294 ****************************************************************/
1296 static NTSTATUS
close_ldif(TALLOC_CTX
*mem_ctx
,
1297 struct samsync_context
*ctx
,
1298 enum netr_SamDatabaseID database_id
,
1299 uint64_t sequence_num
)
1301 struct samsync_ldif_context
*ldif_ctx
=
1302 (struct samsync_ldif_context
*)ctx
->private_data
;
1304 /* This was the last query */
1305 ldif_write_output(database_id
, ldif_ctx
);
1306 if (ldif_ctx
->ldif_file
!= stdout
) {
1307 ctx
->result_message
= talloc_asprintf(ctx
,
1308 "Vampired %d accounts and %d groups to %s",
1309 a_index
, g_index
, ctx
->output_filename
);
1312 ldif_free_context(ldif_ctx
);
1313 ctx
->private_data
= NULL
;
1315 return NT_STATUS_OK
;
1318 #else /* HAVE_LDAP */
1320 static NTSTATUS
init_ldif(TALLOC_CTX
*mem_ctx
,
1321 struct samsync_context
*ctx
,
1322 enum netr_SamDatabaseID database_id
,
1323 uint64_t *sequence_num
)
1325 return NT_STATUS_NOT_SUPPORTED
;
1328 static NTSTATUS
fetch_sam_entries_ldif(TALLOC_CTX
*mem_ctx
,
1329 enum netr_SamDatabaseID database_id
,
1330 struct netr_DELTA_ENUM_ARRAY
*r
,
1331 uint64_t *sequence_num
,
1332 struct samsync_context
*ctx
)
1334 return NT_STATUS_NOT_SUPPORTED
;
1337 static NTSTATUS
close_ldif(TALLOC_CTX
*mem_ctx
,
1338 struct samsync_context
*ctx
,
1339 enum netr_SamDatabaseID database_id
,
1340 uint64_t sequence_num
)
1342 return NT_STATUS_NOT_SUPPORTED
;
1347 const struct samsync_ops libnet_samsync_ldif_ops
= {
1348 .startup
= init_ldif
,
1349 .process_objects
= fetch_sam_entries_ldif
,
1350 .finish
= close_ldif
,