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"
31 /* uid's and gid's for writing deltas to ldif */
32 static uint32 ldif_gid
= 999;
33 static uint32 ldif_uid
= 999;
36 static uint32_t g_index
= 0;
37 static uint32_t a_index
= 0;
39 /* Structure for mapping accounts to groups */
40 /* Array element is the group rid */
41 typedef struct _groupmap
{
48 typedef struct _accountmap
{
53 struct samsync_ldif_context
{
55 ACCOUNTMAP
*accountmap
;
57 const char *add_template
;
58 const char *mod_template
;
68 /****************************************************************
69 ****************************************************************/
71 static NTSTATUS
populate_ldap_for_ldif(const char *sid
,
73 const char *builtin_sid
,
76 const char *user_suffix
, *group_suffix
, *machine_suffix
, *idmap_suffix
;
77 char *user_attr
=NULL
, *group_attr
=NULL
;
81 /* Get the suffix attribute */
82 suffix_attr
= sstring_sub(suffix
, '=', ',');
83 if (suffix_attr
== NULL
) {
85 suffix_attr
= (char*)SMB_MALLOC(len
+1);
86 memcpy(suffix_attr
, suffix
, len
);
87 suffix_attr
[len
] = '\0';
91 fprintf(add_fd
, "# %s\n", suffix
);
92 fprintf(add_fd
, "dn: %s\n", suffix
);
93 fprintf(add_fd
, "objectClass: dcObject\n");
94 fprintf(add_fd
, "objectClass: organization\n");
95 fprintf(add_fd
, "o: %s\n", suffix_attr
);
96 fprintf(add_fd
, "dc: %s\n", suffix_attr
);
97 fprintf(add_fd
, "\n");
100 user_suffix
= lp_ldap_user_suffix();
101 if (user_suffix
== NULL
) {
102 SAFE_FREE(suffix_attr
);
103 return NT_STATUS_NO_MEMORY
;
105 /* If it exists and is distinct from other containers,
106 Write the Users entity */
107 if (*user_suffix
&& strcmp(user_suffix
, suffix
)) {
108 user_attr
= sstring_sub(lp_ldap_user_suffix(), '=', ',');
109 fprintf(add_fd
, "# %s\n", user_suffix
);
110 fprintf(add_fd
, "dn: %s\n", user_suffix
);
111 fprintf(add_fd
, "objectClass: organizationalUnit\n");
112 fprintf(add_fd
, "ou: %s\n", user_attr
);
113 fprintf(add_fd
, "\n");
118 group_suffix
= lp_ldap_group_suffix();
119 if (group_suffix
== NULL
) {
120 SAFE_FREE(suffix_attr
);
121 SAFE_FREE(user_attr
);
122 return NT_STATUS_NO_MEMORY
;
124 /* If it exists and is distinct from other containers,
125 Write the Groups entity */
126 if (*group_suffix
&& strcmp(group_suffix
, suffix
)) {
127 group_attr
= sstring_sub(lp_ldap_group_suffix(), '=', ',');
128 fprintf(add_fd
, "# %s\n", group_suffix
);
129 fprintf(add_fd
, "dn: %s\n", group_suffix
);
130 fprintf(add_fd
, "objectClass: organizationalUnit\n");
131 fprintf(add_fd
, "ou: %s\n", group_attr
);
132 fprintf(add_fd
, "\n");
136 /* If it exists and is distinct from other containers,
137 Write the Computers entity */
138 machine_suffix
= lp_ldap_machine_suffix();
139 if (machine_suffix
== NULL
) {
140 SAFE_FREE(suffix_attr
);
141 SAFE_FREE(user_attr
);
142 SAFE_FREE(group_attr
);
143 return NT_STATUS_NO_MEMORY
;
145 if (*machine_suffix
&& strcmp(machine_suffix
, user_suffix
) &&
146 strcmp(machine_suffix
, suffix
)) {
147 char *machine_ou
= NULL
;
148 fprintf(add_fd
, "# %s\n", machine_suffix
);
149 fprintf(add_fd
, "dn: %s\n", machine_suffix
);
150 fprintf(add_fd
, "objectClass: organizationalUnit\n");
151 /* this isn't totally correct as it assumes that
152 there _must_ be an ou. just fixing memleak now. jmcd */
153 machine_ou
= sstring_sub(lp_ldap_machine_suffix(), '=', ',');
154 fprintf(add_fd
, "ou: %s\n", machine_ou
);
155 SAFE_FREE(machine_ou
);
156 fprintf(add_fd
, "\n");
160 /* If it exists and is distinct from other containers,
161 Write the IdMap entity */
162 idmap_suffix
= lp_ldap_idmap_suffix();
163 if (idmap_suffix
== NULL
) {
164 SAFE_FREE(suffix_attr
);
165 SAFE_FREE(user_attr
);
166 SAFE_FREE(group_attr
);
167 return NT_STATUS_NO_MEMORY
;
170 strcmp(idmap_suffix
, user_suffix
) &&
171 strcmp(idmap_suffix
, suffix
)) {
173 fprintf(add_fd
, "# %s\n", idmap_suffix
);
174 fprintf(add_fd
, "dn: %s\n", idmap_suffix
);
175 fprintf(add_fd
, "ObjectClass: organizationalUnit\n");
176 s
= sstring_sub(lp_ldap_idmap_suffix(), '=', ',');
177 fprintf(add_fd
, "ou: %s\n", s
);
179 fprintf(add_fd
, "\n");
183 /* Write the domain entity */
184 fprintf(add_fd
, "# %s, %s\n", lp_workgroup(), suffix
);
185 fprintf(add_fd
, "dn: sambaDomainName=%s,%s\n", lp_workgroup(),
187 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_DOMINFO
);
188 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_IDPOOL
);
189 fprintf(add_fd
, "sambaDomainName: %s\n", lp_workgroup());
190 fprintf(add_fd
, "sambaSID: %s\n", sid
);
191 fprintf(add_fd
, "uidNumber: %d\n", ++ldif_uid
);
192 fprintf(add_fd
, "gidNumber: %d\n", ++ldif_gid
);
193 fprintf(add_fd
, "\n");
196 /* Write the Domain Admins entity */
197 fprintf(add_fd
, "# Domain Admins, %s, %s\n", group_attr
,
199 fprintf(add_fd
, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr
,
201 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
202 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
203 fprintf(add_fd
, "cn: Domain Admins\n");
204 fprintf(add_fd
, "memberUid: Administrator\n");
205 fprintf(add_fd
, "description: Netbios Domain Administrators\n");
206 fprintf(add_fd
, "gidNumber: 512\n");
207 fprintf(add_fd
, "sambaSID: %s-512\n", sid
);
208 fprintf(add_fd
, "sambaGroupType: 2\n");
209 fprintf(add_fd
, "displayName: Domain Admins\n");
210 fprintf(add_fd
, "\n");
213 /* Write the Domain Users entity */
214 fprintf(add_fd
, "# Domain Users, %s, %s\n", group_attr
,
216 fprintf(add_fd
, "dn: cn=Domain Users,ou=%s,%s\n", group_attr
,
218 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
219 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
220 fprintf(add_fd
, "cn: Domain Users\n");
221 fprintf(add_fd
, "description: Netbios Domain Users\n");
222 fprintf(add_fd
, "gidNumber: 513\n");
223 fprintf(add_fd
, "sambaSID: %s-513\n", sid
);
224 fprintf(add_fd
, "sambaGroupType: 2\n");
225 fprintf(add_fd
, "displayName: Domain Users\n");
226 fprintf(add_fd
, "\n");
229 /* Write the Domain Guests entity */
230 fprintf(add_fd
, "# Domain Guests, %s, %s\n", group_attr
,
232 fprintf(add_fd
, "dn: cn=Domain Guests,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 Guests\n");
237 fprintf(add_fd
, "description: Netbios Domain Guests\n");
238 fprintf(add_fd
, "gidNumber: 514\n");
239 fprintf(add_fd
, "sambaSID: %s-514\n", sid
);
240 fprintf(add_fd
, "sambaGroupType: 2\n");
241 fprintf(add_fd
, "displayName: Domain Guests\n");
242 fprintf(add_fd
, "\n");
245 /* Write the Domain Computers entity */
246 fprintf(add_fd
, "# Domain Computers, %s, %s\n", group_attr
,
248 fprintf(add_fd
, "dn: cn=Domain Computers,ou=%s,%s\n",
250 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
251 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
252 fprintf(add_fd
, "gidNumber: 515\n");
253 fprintf(add_fd
, "cn: Domain Computers\n");
254 fprintf(add_fd
, "description: Netbios Domain Computers accounts\n");
255 fprintf(add_fd
, "sambaSID: %s-515\n", sid
);
256 fprintf(add_fd
, "sambaGroupType: 2\n");
257 fprintf(add_fd
, "displayName: Domain Computers\n");
258 fprintf(add_fd
, "\n");
261 /* Write the Admininistrators Groups entity */
262 fprintf(add_fd
, "# Administrators, %s, %s\n", group_attr
,
264 fprintf(add_fd
, "dn: cn=Administrators,ou=%s,%s\n", group_attr
,
266 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
267 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
268 fprintf(add_fd
, "gidNumber: 544\n");
269 fprintf(add_fd
, "cn: Administrators\n");
270 fprintf(add_fd
, "description: Netbios Domain Members can fully administer the computer/sambaDomainName\n");
271 fprintf(add_fd
, "sambaSID: %s-544\n", builtin_sid
);
272 fprintf(add_fd
, "sambaGroupType: 5\n");
273 fprintf(add_fd
, "displayName: Administrators\n");
274 fprintf(add_fd
, "\n");
276 /* Write the Print Operator entity */
277 fprintf(add_fd
, "# Print Operators, %s, %s\n", group_attr
,
279 fprintf(add_fd
, "dn: cn=Print Operators,ou=%s,%s\n",
281 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
282 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
283 fprintf(add_fd
, "gidNumber: 550\n");
284 fprintf(add_fd
, "cn: Print Operators\n");
285 fprintf(add_fd
, "description: Netbios Domain Print Operators\n");
286 fprintf(add_fd
, "sambaSID: %s-550\n", builtin_sid
);
287 fprintf(add_fd
, "sambaGroupType: 5\n");
288 fprintf(add_fd
, "displayName: Print Operators\n");
289 fprintf(add_fd
, "\n");
292 /* Write the Backup Operators entity */
293 fprintf(add_fd
, "# Backup Operators, %s, %s\n", group_attr
,
295 fprintf(add_fd
, "dn: cn=Backup Operators,ou=%s,%s\n",
297 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
298 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
299 fprintf(add_fd
, "gidNumber: 551\n");
300 fprintf(add_fd
, "cn: Backup Operators\n");
301 fprintf(add_fd
, "description: Netbios Domain Members can bypass file security to back up files\n");
302 fprintf(add_fd
, "sambaSID: %s-551\n", builtin_sid
);
303 fprintf(add_fd
, "sambaGroupType: 5\n");
304 fprintf(add_fd
, "displayName: Backup Operators\n");
305 fprintf(add_fd
, "\n");
308 /* Write the Replicators entity */
309 fprintf(add_fd
, "# Replicators, %s, %s\n", group_attr
, suffix
);
310 fprintf(add_fd
, "dn: cn=Replicators,ou=%s,%s\n", group_attr
,
312 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
313 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
314 fprintf(add_fd
, "gidNumber: 552\n");
315 fprintf(add_fd
, "cn: Replicators\n");
316 fprintf(add_fd
, "description: Netbios Domain Supports file replication in a sambaDomainName\n");
317 fprintf(add_fd
, "sambaSID: %s-552\n", builtin_sid
);
318 fprintf(add_fd
, "sambaGroupType: 5\n");
319 fprintf(add_fd
, "displayName: Replicators\n");
320 fprintf(add_fd
, "\n");
323 /* Deallocate memory, and return */
324 SAFE_FREE(suffix_attr
);
325 SAFE_FREE(user_attr
);
326 SAFE_FREE(group_attr
);
330 /****************************************************************
331 ****************************************************************/
333 static NTSTATUS
map_populate_groups(TALLOC_CTX
*mem_ctx
,
335 ACCOUNTMAP
*accountmap
,
338 const char *builtin_sid
)
340 char *group_attr
= sstring_sub(lp_ldap_group_suffix(), '=', ',');
342 /* Map the groups created by populate_ldap_for_ldif */
343 groupmap
[0].rid
= 512;
344 groupmap
[0].gidNumber
= 512;
345 groupmap
[0].sambaSID
= talloc_asprintf(mem_ctx
, "%s-512", sid
);
346 groupmap
[0].group_dn
= talloc_asprintf(mem_ctx
,
347 "cn=Domain Admins,ou=%s,%s", group_attr
, suffix
);
348 NT_STATUS_HAVE_NO_MEMORY(groupmap
[0].sambaSID
);
349 NT_STATUS_HAVE_NO_MEMORY(groupmap
[0].group_dn
);
351 accountmap
[0].rid
= 512;
352 accountmap
[0].cn
= talloc_strdup(mem_ctx
, "Domain Admins");
353 NT_STATUS_HAVE_NO_MEMORY(accountmap
[0].cn
);
355 groupmap
[1].rid
= 513;
356 groupmap
[1].gidNumber
= 513;
357 groupmap
[1].sambaSID
= talloc_asprintf(mem_ctx
, "%s-513", sid
);
358 groupmap
[1].group_dn
= talloc_asprintf(mem_ctx
,
359 "cn=Domain Users,ou=%s,%s", group_attr
, suffix
);
360 NT_STATUS_HAVE_NO_MEMORY(groupmap
[1].sambaSID
);
361 NT_STATUS_HAVE_NO_MEMORY(groupmap
[1].group_dn
);
363 accountmap
[1].rid
= 513;
364 accountmap
[1].cn
= talloc_strdup(mem_ctx
, "Domain Users");
365 NT_STATUS_HAVE_NO_MEMORY(accountmap
[1].cn
);
367 groupmap
[2].rid
= 514;
368 groupmap
[2].gidNumber
= 514;
369 groupmap
[2].sambaSID
= talloc_asprintf(mem_ctx
, "%s-514", sid
);
370 groupmap
[2].group_dn
= talloc_asprintf(mem_ctx
,
371 "cn=Domain Guests,ou=%s,%s", group_attr
, suffix
);
372 NT_STATUS_HAVE_NO_MEMORY(groupmap
[2].sambaSID
);
373 NT_STATUS_HAVE_NO_MEMORY(groupmap
[2].group_dn
);
375 accountmap
[2].rid
= 514;
376 accountmap
[2].cn
= talloc_strdup(mem_ctx
, "Domain Guests");
377 NT_STATUS_HAVE_NO_MEMORY(accountmap
[2].cn
);
379 groupmap
[3].rid
= 515;
380 groupmap
[3].gidNumber
= 515;
381 groupmap
[3].sambaSID
= talloc_asprintf(mem_ctx
, "%s-515", sid
);
382 groupmap
[3].group_dn
= talloc_asprintf(mem_ctx
,
383 "cn=Domain Computers,ou=%s,%s", group_attr
, suffix
);
384 NT_STATUS_HAVE_NO_MEMORY(groupmap
[3].sambaSID
);
385 NT_STATUS_HAVE_NO_MEMORY(groupmap
[3].group_dn
);
387 accountmap
[3].rid
= 515;
388 accountmap
[3].cn
= talloc_strdup(mem_ctx
, "Domain Computers");
389 NT_STATUS_HAVE_NO_MEMORY(accountmap
[3].cn
);
391 groupmap
[4].rid
= 544;
392 groupmap
[4].gidNumber
= 544;
393 groupmap
[4].sambaSID
= talloc_asprintf(mem_ctx
, "%s-544", builtin_sid
);
394 groupmap
[4].group_dn
= talloc_asprintf(mem_ctx
,
395 "cn=Administrators,ou=%s,%s", group_attr
, suffix
);
396 NT_STATUS_HAVE_NO_MEMORY(groupmap
[4].sambaSID
);
397 NT_STATUS_HAVE_NO_MEMORY(groupmap
[4].group_dn
);
399 accountmap
[4].rid
= 515;
400 accountmap
[4].cn
= talloc_strdup(mem_ctx
, "Administrators");
401 NT_STATUS_HAVE_NO_MEMORY(accountmap
[4].cn
);
403 groupmap
[5].rid
= 550;
404 groupmap
[5].gidNumber
= 550;
405 groupmap
[5].sambaSID
= talloc_asprintf(mem_ctx
, "%s-550", builtin_sid
);
406 groupmap
[5].group_dn
= talloc_asprintf(mem_ctx
,
407 "cn=Print Operators,ou=%s,%s", group_attr
, suffix
);
408 NT_STATUS_HAVE_NO_MEMORY(groupmap
[5].sambaSID
);
409 NT_STATUS_HAVE_NO_MEMORY(groupmap
[5].group_dn
);
411 accountmap
[5].rid
= 550;
412 accountmap
[5].cn
= talloc_strdup(mem_ctx
, "Print Operators");
413 NT_STATUS_HAVE_NO_MEMORY(accountmap
[5].cn
);
415 groupmap
[6].rid
= 551;
416 groupmap
[6].gidNumber
= 551;
417 groupmap
[6].sambaSID
= talloc_asprintf(mem_ctx
, "%s-551", builtin_sid
);
418 groupmap
[6].group_dn
= talloc_asprintf(mem_ctx
,
419 "cn=Backup Operators,ou=%s,%s", group_attr
, suffix
);
420 NT_STATUS_HAVE_NO_MEMORY(groupmap
[6].sambaSID
);
421 NT_STATUS_HAVE_NO_MEMORY(groupmap
[6].group_dn
);
423 accountmap
[6].rid
= 551;
424 accountmap
[6].cn
= talloc_strdup(mem_ctx
, "Backup Operators");
425 NT_STATUS_HAVE_NO_MEMORY(accountmap
[6].cn
);
427 groupmap
[7].rid
= 552;
428 groupmap
[7].gidNumber
= 552;
429 groupmap
[7].sambaSID
= talloc_asprintf(mem_ctx
, "%s-552", builtin_sid
);
430 groupmap
[7].group_dn
= talloc_asprintf(mem_ctx
,
431 "cn=Replicators,ou=%s,%s", group_attr
, suffix
);
432 NT_STATUS_HAVE_NO_MEMORY(groupmap
[7].sambaSID
);
433 NT_STATUS_HAVE_NO_MEMORY(groupmap
[7].group_dn
);
435 accountmap
[7].rid
= 551;
436 accountmap
[7].cn
= talloc_strdup(mem_ctx
, "Replicators");
437 NT_STATUS_HAVE_NO_MEMORY(accountmap
[7].cn
);
439 SAFE_FREE(group_attr
);
445 * This is a crap routine, but I think it's the quickest way to solve the
446 * UTF8->base64 problem.
449 static int fprintf_attr(FILE *add_fd
, const char *attr_name
,
450 const char *fmt
, ...)
453 char *value
, *p
, *base64
;
454 DATA_BLOB base64_blob
;
455 bool do_base64
= false;
459 value
= talloc_vasprintf(NULL
, fmt
, ap
);
462 SMB_ASSERT(value
!= NULL
);
464 for (p
=value
; *p
; p
++) {
472 bool only_whitespace
= true;
473 for (p
=value
; *p
; p
++) {
475 * I know that this not multibyte safe, but we break
476 * on the first non-whitespace character anyway.
479 only_whitespace
= false;
483 if (only_whitespace
) {
489 res
= fprintf(add_fd
, "%s: %s\n", attr_name
, value
);
494 base64_blob
.data
= (unsigned char *)value
;
495 base64_blob
.length
= strlen(value
);
497 base64
= base64_encode_data_blob(value
, base64_blob
);
498 SMB_ASSERT(base64
!= NULL
);
500 res
= fprintf(add_fd
, "%s:: %s\n", attr_name
, base64
);
505 /****************************************************************
506 ****************************************************************/
508 static NTSTATUS
fetch_group_info_to_ldif(TALLOC_CTX
*mem_ctx
,
509 struct netr_DELTA_GROUP
*r
,
515 const char *groupname
= r
->group_name
.string
;
516 uint32 grouptype
= 0, g_rid
= 0;
517 char *group_attr
= sstring_sub(lp_ldap_group_suffix(), '=', ',');
519 /* Set up the group type (always 2 for group info) */
522 /* These groups are entered by populate_ldap_for_ldif */
523 if (strcmp(groupname
, "Domain Admins") == 0 ||
524 strcmp(groupname
, "Domain Users") == 0 ||
525 strcmp(groupname
, "Domain Guests") == 0 ||
526 strcmp(groupname
, "Domain Computers") == 0 ||
527 strcmp(groupname
, "Administrators") == 0 ||
528 strcmp(groupname
, "Print Operators") == 0 ||
529 strcmp(groupname
, "Backup Operators") == 0 ||
530 strcmp(groupname
, "Replicators") == 0) {
531 SAFE_FREE(group_attr
);
534 /* Increment the gid for the new group */
538 /* Map the group rid, gid, and dn */
540 groupmap
->rid
= g_rid
;
541 groupmap
->gidNumber
= ldif_gid
;
542 groupmap
->sambaSID
= talloc_asprintf(mem_ctx
, "%s-%d", sid
, g_rid
);
543 groupmap
->group_dn
= talloc_asprintf(mem_ctx
,
544 "cn=%s,ou=%s,%s", groupname
, group_attr
, suffix
);
545 NT_STATUS_HAVE_NO_MEMORY(groupmap
->sambaSID
);
546 NT_STATUS_HAVE_NO_MEMORY(groupmap
->group_dn
);
548 /* Write the data to the temporary add ldif file */
549 fprintf(add_fd
, "# %s, %s, %s\n", groupname
, group_attr
,
551 fprintf_attr(add_fd
, "dn", "cn=%s,ou=%s,%s", groupname
, group_attr
,
553 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
554 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
555 fprintf_attr(add_fd
, "cn", "%s", groupname
);
556 fprintf(add_fd
, "gidNumber: %d\n", ldif_gid
);
557 fprintf(add_fd
, "sambaSID: %s\n", groupmap
->sambaSID
);
558 fprintf(add_fd
, "sambaGroupType: %d\n", grouptype
);
559 fprintf_attr(add_fd
, "displayName", "%s", groupname
);
560 fprintf(add_fd
, "\n");
563 SAFE_FREE(group_attr
);
568 /****************************************************************
569 ****************************************************************/
571 static NTSTATUS
fetch_account_info_to_ldif(TALLOC_CTX
*mem_ctx
,
572 struct netr_DELTA_USER
*r
,
574 ACCOUNTMAP
*accountmap
,
580 fstring username
, logonscript
, homedrive
, homepath
= "", homedir
= "";
581 fstring hex_nt_passwd
, hex_lm_passwd
;
582 fstring description
, profilepath
, fullname
, sambaSID
;
583 char *flags
, *user_rdn
;
585 const char* nopasswd
= "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
587 uint32 rid
= 0, group_rid
= 0, gidNumber
= 0;
591 memset(zero_buf
, '\0', sizeof(zero_buf
));
593 /* Get the username */
594 fstrcpy(username
, r
->account_name
.string
);
599 /* Map the rid and username for group member info later */
600 accountmap
->rid
= rid
;
601 accountmap
->cn
= talloc_strdup(mem_ctx
, username
);
602 NT_STATUS_HAVE_NO_MEMORY(accountmap
->cn
);
604 /* Get the home directory */
605 if (r
->acct_flags
& ACB_NORMAL
) {
606 fstrcpy(homedir
, r
->home_directory
.string
);
608 snprintf(homedir
, sizeof(homedir
), "/home/%s", username
);
610 snprintf(homedir
, sizeof(homedir
), "/nobodyshomedir");
612 ou
= lp_ldap_user_suffix();
614 ou
= lp_ldap_machine_suffix();
615 snprintf(homedir
, sizeof(homedir
), "/machinehomedir");
618 /* Get the logon script */
619 fstrcpy(logonscript
, r
->logon_script
.string
);
621 /* Get the home drive */
622 fstrcpy(homedrive
, r
->home_drive
.string
);
624 /* Get the home path */
625 fstrcpy(homepath
, r
->home_directory
.string
);
627 /* Get the description */
628 fstrcpy(description
, r
->description
.string
);
630 /* Get the display name */
631 fstrcpy(fullname
, r
->full_name
.string
);
633 /* Get the profile path */
634 fstrcpy(profilepath
, r
->profile_path
.string
);
636 /* Get lm and nt password data */
637 if (memcmp(r
->lmpassword
.hash
, zero_buf
, 16) != 0) {
638 pdb_sethexpwd(hex_lm_passwd
, r
->lmpassword
.hash
, r
->acct_flags
);
640 pdb_sethexpwd(hex_lm_passwd
, NULL
, 0);
642 if (memcmp(r
->ntpassword
.hash
, zero_buf
, 16) != 0) {
643 pdb_sethexpwd(hex_nt_passwd
, r
->ntpassword
.hash
, r
->acct_flags
);
645 pdb_sethexpwd(hex_nt_passwd
, NULL
, 0);
647 unix_time
= nt_time_to_unix(r
->last_password_change
);
649 /* Increment the uid for the new user */
652 /* Set up group id and sambaSID for the user */
653 group_rid
= r
->primary_gid
;
654 for (i
=0; i
<alloced
; i
++) {
655 if (groupmap
[i
].rid
== group_rid
) break;
658 DEBUG(1, ("Could not find rid %d in groupmap array\n",
660 return NT_STATUS_UNSUCCESSFUL
;
662 gidNumber
= groupmap
[i
].gidNumber
;
663 ret
= snprintf(sambaSID
, sizeof(sambaSID
), "%s", groupmap
[i
].sambaSID
);
664 if (ret
< 0 || ret
== sizeof(sambaSID
)) {
665 return NT_STATUS_UNSUCCESSFUL
;
668 /* Set up sambaAcctFlags */
669 flags
= pdb_encode_acct_ctrl(r
->acct_flags
,
670 NEW_PW_FORMAT_SPACE_PADDED_LEN
);
672 /* Add the user to the temporary add ldif file */
673 /* this isn't quite right...we can't assume there's just OU=. jmcd */
674 user_rdn
= sstring_sub(ou
, '=', ',');
675 fprintf(add_fd
, "# %s, %s, %s\n", username
, user_rdn
, suffix
);
676 fprintf_attr(add_fd
, "dn", "uid=%s,ou=%s,%s", username
, user_rdn
,
679 fprintf(add_fd
, "ObjectClass: top\n");
680 fprintf(add_fd
, "objectClass: inetOrgPerson\n");
681 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT
);
682 fprintf(add_fd
, "objectClass: shadowAccount\n");
683 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT
);
684 fprintf_attr(add_fd
, "cn", "%s", username
);
685 fprintf_attr(add_fd
, "sn", "%s", username
);
686 fprintf_attr(add_fd
, "uid", "%s", username
);
687 fprintf(add_fd
, "uidNumber: %d\n", ldif_uid
);
688 fprintf(add_fd
, "gidNumber: %d\n", gidNumber
);
689 fprintf_attr(add_fd
, "homeDirectory", "%s", homedir
);
691 fprintf_attr(add_fd
, "sambaHomePath", "%s", homepath
);
693 fprintf_attr(add_fd
, "sambaHomeDrive", "%s", homedrive
);
695 fprintf_attr(add_fd
, "sambaLogonScript", "%s", logonscript
);
696 fprintf(add_fd
, "loginShell: %s\n",
697 ((r
->acct_flags
& ACB_NORMAL
) ?
698 "/bin/bash" : "/bin/false"));
699 fprintf(add_fd
, "gecos: System User\n");
701 fprintf_attr(add_fd
, "description", "%s", description
);
702 fprintf(add_fd
, "sambaSID: %s-%d\n", sid
, rid
);
703 fprintf(add_fd
, "sambaPrimaryGroupSID: %s\n", sambaSID
);
705 fprintf_attr(add_fd
, "displayName", "%s", fullname
);
707 fprintf_attr(add_fd
, "sambaProfilePath", "%s", profilepath
);
708 if (strcmp(nopasswd
, hex_lm_passwd
) != 0)
709 fprintf(add_fd
, "sambaLMPassword: %s\n", hex_lm_passwd
);
710 if (strcmp(nopasswd
, hex_nt_passwd
) != 0)
711 fprintf(add_fd
, "sambaNTPassword: %s\n", hex_nt_passwd
);
712 fprintf(add_fd
, "sambaPwdLastSet: %d\n", (int)unix_time
);
713 fprintf(add_fd
, "sambaAcctFlags: %s\n", flags
);
714 fprintf(add_fd
, "\n");
721 /****************************************************************
722 ****************************************************************/
724 static NTSTATUS
fetch_alias_info_to_ldif(TALLOC_CTX
*mem_ctx
,
725 struct netr_DELTA_ALIAS
*r
,
730 enum netr_SamDatabaseID database_id
)
732 fstring aliasname
, description
;
733 uint32 grouptype
= 0, g_rid
= 0;
734 char *group_attr
= sstring_sub(lp_ldap_group_suffix(), '=', ',');
736 /* Get the alias name */
737 fstrcpy(aliasname
, r
->alias_name
.string
);
739 /* Get the alias description */
740 fstrcpy(description
, r
->description
.string
);
742 /* Set up the group type */
743 switch (database_id
) {
744 case SAM_DATABASE_DOMAIN
:
747 case SAM_DATABASE_BUILTIN
:
756 These groups are entered by populate_ldap_for_ldif
757 Note that populate creates a group called Relicators,
758 but NT returns a group called Replicator
760 if (strcmp(aliasname
, "Domain Admins") == 0 ||
761 strcmp(aliasname
, "Domain Users") == 0 ||
762 strcmp(aliasname
, "Domain Guests") == 0 ||
763 strcmp(aliasname
, "Domain Computers") == 0 ||
764 strcmp(aliasname
, "Administrators") == 0 ||
765 strcmp(aliasname
, "Print Operators") == 0 ||
766 strcmp(aliasname
, "Backup Operators") == 0 ||
767 strcmp(aliasname
, "Replicator") == 0) {
768 SAFE_FREE(group_attr
);
771 /* Increment the gid for the new group */
775 /* Map the group rid and gid */
777 groupmap
->gidNumber
= ldif_gid
;
778 groupmap
->sambaSID
= talloc_asprintf(mem_ctx
, "%s-%d", sid
, g_rid
);
779 if (groupmap
->sambaSID
== NULL
) {
780 SAFE_FREE(group_attr
);
781 return NT_STATUS_NO_MEMORY
;
784 /* Write the data to the temporary add ldif file */
785 fprintf(add_fd
, "# %s, %s, %s\n", aliasname
, group_attr
,
787 fprintf_attr(add_fd
, "dn", "cn=%s,ou=%s,%s", aliasname
, group_attr
,
789 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP
);
790 fprintf(add_fd
, "objectClass: %s\n", LDAP_OBJ_GROUPMAP
);
791 fprintf(add_fd
, "cn: %s\n", aliasname
);
792 fprintf(add_fd
, "gidNumber: %d\n", ldif_gid
);
793 fprintf(add_fd
, "sambaSID: %s\n", groupmap
->sambaSID
);
794 fprintf(add_fd
, "sambaGroupType: %d\n", grouptype
);
795 fprintf_attr(add_fd
, "displayName", "%s", aliasname
);
797 fprintf_attr(add_fd
, "description", "%s", description
);
798 fprintf(add_fd
, "\n");
801 SAFE_FREE(group_attr
);
806 /****************************************************************
807 ****************************************************************/
809 static NTSTATUS
fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER
*r
,
812 ACCOUNTMAP
*accountmap
,
813 FILE *mod_fd
, int alloced
)
816 uint32 group_rid
= 0, rid
= 0;
819 /* Get the dn for the group */
820 if (r
->num_rids
> 0) {
822 for (j
=0; j
<alloced
; j
++) {
823 if (groupmap
[j
].rid
== group_rid
) break;
826 DEBUG(1, ("Could not find rid %d in groupmap array\n",
828 return NT_STATUS_UNSUCCESSFUL
;
830 snprintf(group_dn
, sizeof(group_dn
), "%s", groupmap
[j
].group_dn
);
831 fprintf(mod_fd
, "dn: %s\n", group_dn
);
833 /* Get the cn for each member */
834 for (i
=0; i
< r
->num_rids
; i
++) {
836 for (k
=0; k
<alloced
; k
++) {
837 if (accountmap
[k
].rid
== rid
) break;
840 DEBUG(1, ("Could not find rid %d in "
841 "accountmap array\n", rid
));
842 return NT_STATUS_UNSUCCESSFUL
;
844 fprintf(mod_fd
, "memberUid: %s\n", accountmap
[k
].cn
);
846 fprintf(mod_fd
, "\n");
854 /****************************************************************
855 ****************************************************************/
857 static NTSTATUS
ldif_init_context(TALLOC_CTX
*mem_ctx
,
858 enum netr_SamDatabaseID database_id
,
859 const char *ldif_filename
,
860 const char *domain_sid_str
,
861 struct samsync_ldif_context
**ctx
)
863 NTSTATUS status
= NT_STATUS_UNSUCCESSFUL
;
864 struct samsync_ldif_context
*r
;
865 const char *add_template
= "/tmp/add.ldif.XXXXXX";
866 const char *mod_template
= "/tmp/mod.ldif.XXXXXX";
867 const char *builtin_sid
= "S-1-5-32";
869 /* Get other smb.conf data */
870 if (!(lp_workgroup()) || !*(lp_workgroup())) {
871 DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
875 /* Get the ldap suffix */
876 if (!(lp_ldap_suffix()) || !*(lp_ldap_suffix())) {
877 DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
881 if (*ctx
&& (*ctx
)->initialized
) {
885 r
= TALLOC_ZERO_P(mem_ctx
, struct samsync_ldif_context
);
886 NT_STATUS_HAVE_NO_MEMORY(r
);
888 /* Get the ldap suffix */
889 r
->suffix
= lp_ldap_suffix();
891 /* Ensure we have an output file */
893 r
->ldif_file
= fopen(ldif_filename
, "a");
895 r
->ldif_file
= stdout
;
899 fprintf(stderr
, "Could not open %s\n", ldif_filename
);
900 DEBUG(1, ("Could not open %s\n", ldif_filename
));
901 status
= NT_STATUS_UNSUCCESSFUL
;
905 r
->add_template
= talloc_strdup(mem_ctx
, add_template
);
906 r
->mod_template
= talloc_strdup(mem_ctx
, mod_template
);
907 if (!r
->add_template
|| !r
->mod_template
) {
908 status
= NT_STATUS_NO_MEMORY
;
912 r
->add_name
= talloc_strdup(mem_ctx
, add_template
);
913 r
->mod_name
= talloc_strdup(mem_ctx
, mod_template
);
914 if (!r
->add_name
|| !r
->mod_name
) {
915 status
= NT_STATUS_NO_MEMORY
;
919 /* Open the add and mod ldif files */
920 if (!(r
->add_file
= fdopen(smb_mkstemp(r
->add_name
),"w"))) {
921 DEBUG(1, ("Could not open %s\n", r
->add_name
));
922 status
= NT_STATUS_UNSUCCESSFUL
;
925 if (!(r
->mod_file
= fdopen(smb_mkstemp(r
->mod_name
),"w"))) {
926 DEBUG(1, ("Could not open %s\n", r
->mod_name
));
927 status
= NT_STATUS_UNSUCCESSFUL
;
931 /* Allocate initial memory for groupmap and accountmap arrays */
932 r
->groupmap
= TALLOC_ZERO_ARRAY(mem_ctx
, GROUPMAP
, 8);
933 r
->accountmap
= TALLOC_ZERO_ARRAY(mem_ctx
, ACCOUNTMAP
, 8);
934 if (r
->groupmap
== NULL
|| r
->accountmap
== NULL
) {
935 DEBUG(1,("GROUPMAP talloc failed\n"));
936 status
= NT_STATUS_NO_MEMORY
;
940 /* Remember how many we malloced */
943 /* Initial database population */
944 if (database_id
== SAM_DATABASE_DOMAIN
) {
946 status
= populate_ldap_for_ldif(domain_sid_str
,
950 if (!NT_STATUS_IS_OK(status
)) {
954 status
= map_populate_groups(mem_ctx
,
960 if (!NT_STATUS_IS_OK(status
)) {
965 r
->initialized
= true;
975 /****************************************************************
976 ****************************************************************/
978 static void ldif_free_context(struct samsync_ldif_context
*r
)
984 /* Close and delete the ldif files */
989 if ((r
->add_name
!= NULL
) &&
990 strcmp(r
->add_name
, r
->add_template
) && (unlink(r
->add_name
))) {
991 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
992 r
->add_name
, strerror(errno
)));
999 if ((r
->mod_name
!= NULL
) &&
1000 strcmp(r
->mod_name
, r
->mod_template
) && (unlink(r
->mod_name
))) {
1001 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1002 r
->mod_name
, strerror(errno
)));
1005 if (r
->ldif_file
&& (r
->ldif_file
!= stdout
)) {
1006 fclose(r
->ldif_file
);
1012 /****************************************************************
1013 ****************************************************************/
1015 static void ldif_write_output(enum netr_SamDatabaseID database_id
,
1016 struct samsync_ldif_context
*l
)
1018 /* Write ldif data to the user's file */
1019 if (database_id
== SAM_DATABASE_DOMAIN
) {
1020 fprintf(l
->ldif_file
,
1021 "# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
1022 fprintf(l
->ldif_file
,
1023 "# =================================\n\n");
1024 fflush(l
->ldif_file
);
1025 } else if (database_id
== SAM_DATABASE_BUILTIN
) {
1026 fprintf(l
->ldif_file
,
1027 "# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
1028 fprintf(l
->ldif_file
,
1029 "# ==================================\n\n");
1030 fflush(l
->ldif_file
);
1032 fseek(l
->add_file
, 0, SEEK_SET
);
1033 transfer_file(fileno(l
->add_file
), fileno(l
->ldif_file
), (size_t) -1);
1035 if (database_id
== SAM_DATABASE_DOMAIN
) {
1036 fprintf(l
->ldif_file
,
1037 "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
1038 fprintf(l
->ldif_file
,
1039 "# ====================================\n\n");
1040 fflush(l
->ldif_file
);
1041 } else if (database_id
== SAM_DATABASE_BUILTIN
) {
1042 fprintf(l
->ldif_file
,
1043 "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
1044 fprintf(l
->ldif_file
,
1045 "# =====================================\n\n");
1046 fflush(l
->ldif_file
);
1048 fseek(l
->mod_file
, 0, SEEK_SET
);
1049 transfer_file(fileno(l
->mod_file
), fileno(l
->ldif_file
), (size_t) -1);
1052 /****************************************************************
1053 ****************************************************************/
1055 static NTSTATUS
fetch_sam_entry_ldif(TALLOC_CTX
*mem_ctx
,
1056 enum netr_SamDatabaseID database_id
,
1057 struct netr_DELTA_ENUM
*r
,
1058 struct samsync_context
*ctx
,
1059 uint32_t *a_index_p
,
1060 uint32_t *g_index_p
)
1062 union netr_DELTA_UNION u
= r
->delta_union
;
1063 union netr_DELTA_ID_UNION id
= r
->delta_id_union
;
1064 struct samsync_ldif_context
*l
=
1065 talloc_get_type_abort(ctx
->private_data
, struct samsync_ldif_context
);
1067 switch (r
->delta_type
) {
1068 case NETR_DELTA_DOMAIN
:
1071 case NETR_DELTA_GROUP
:
1072 fetch_group_info_to_ldif(mem_ctx
,
1074 &l
->groupmap
[*g_index_p
],
1076 ctx
->domain_sid_str
,
1081 case NETR_DELTA_USER
:
1082 fetch_account_info_to_ldif(mem_ctx
,
1085 &l
->accountmap
[*a_index_p
],
1087 ctx
->domain_sid_str
,
1093 case NETR_DELTA_ALIAS
:
1094 fetch_alias_info_to_ldif(mem_ctx
,
1096 &l
->groupmap
[*g_index_p
],
1098 ctx
->domain_sid_str
,
1104 case NETR_DELTA_GROUP_MEMBER
:
1105 fetch_groupmem_info_to_ldif(u
.group_member
,
1113 case NETR_DELTA_ALIAS_MEMBER
:
1114 case NETR_DELTA_POLICY
:
1115 case NETR_DELTA_ACCOUNT
:
1116 case NETR_DELTA_TRUSTED_DOMAIN
:
1117 case NETR_DELTA_SECRET
:
1118 case NETR_DELTA_RENAME_GROUP
:
1119 case NETR_DELTA_RENAME_USER
:
1120 case NETR_DELTA_RENAME_ALIAS
:
1121 case NETR_DELTA_DELETE_GROUP
:
1122 case NETR_DELTA_DELETE_USER
:
1123 case NETR_DELTA_MODIFY_COUNT
:
1126 } /* end of switch */
1128 return NT_STATUS_OK
;
1131 /****************************************************************
1132 ****************************************************************/
1134 static NTSTATUS
ldif_realloc_maps(TALLOC_CTX
*mem_ctx
,
1135 struct samsync_ldif_context
*l
,
1136 uint32_t num_entries
)
1138 /* Re-allocate memory for groupmap and accountmap arrays */
1139 l
->groupmap
= TALLOC_REALLOC_ARRAY(mem_ctx
,
1142 num_entries
+ l
->num_alloced
);
1144 l
->accountmap
= TALLOC_REALLOC_ARRAY(mem_ctx
,
1147 num_entries
+ l
->num_alloced
);
1149 if (l
->groupmap
== NULL
|| l
->accountmap
== NULL
) {
1150 DEBUG(1,("GROUPMAP talloc failed\n"));
1151 return NT_STATUS_NO_MEMORY
;
1154 /* Initialize the new records */
1155 memset(&(l
->groupmap
[l
->num_alloced
]), 0,
1156 sizeof(GROUPMAP
) * num_entries
);
1157 memset(&(l
->accountmap
[l
->num_alloced
]), 0,
1158 sizeof(ACCOUNTMAP
) * num_entries
);
1160 /* Remember how many we alloced this time */
1161 l
->num_alloced
+= num_entries
;
1163 return NT_STATUS_OK
;
1166 /****************************************************************
1167 ****************************************************************/
1169 static NTSTATUS
init_ldif(TALLOC_CTX
*mem_ctx
,
1170 struct samsync_context
*ctx
,
1171 enum netr_SamDatabaseID database_id
,
1172 uint64_t *sequence_num
)
1175 struct samsync_ldif_context
*ldif_ctx
=
1176 (struct samsync_ldif_context
*)ctx
->private_data
;
1178 status
= ldif_init_context(mem_ctx
,
1180 ctx
->output_filename
,
1181 ctx
->domain_sid_str
,
1183 if (!NT_STATUS_IS_OK(status
)) {
1187 ctx
->private_data
= ldif_ctx
;
1189 return NT_STATUS_OK
;
1192 /****************************************************************
1193 ****************************************************************/
1195 static NTSTATUS
fetch_sam_entries_ldif(TALLOC_CTX
*mem_ctx
,
1196 enum netr_SamDatabaseID database_id
,
1197 struct netr_DELTA_ENUM_ARRAY
*r
,
1198 uint64_t *sequence_num
,
1199 struct samsync_context
*ctx
)
1203 struct samsync_ldif_context
*ldif_ctx
=
1204 (struct samsync_ldif_context
*)ctx
->private_data
;
1206 status
= ldif_realloc_maps(mem_ctx
, ldif_ctx
, r
->num_deltas
);
1207 if (!NT_STATUS_IS_OK(status
)) {
1211 for (i
= 0; i
< r
->num_deltas
; i
++) {
1212 status
= fetch_sam_entry_ldif(mem_ctx
, database_id
,
1213 &r
->delta_enum
[i
], ctx
,
1214 &a_index
, &g_index
);
1215 if (!NT_STATUS_IS_OK(status
)) {
1220 return NT_STATUS_OK
;
1223 ldif_free_context(ldif_ctx
);
1224 ctx
->private_data
= NULL
;
1229 /****************************************************************
1230 ****************************************************************/
1232 static NTSTATUS
close_ldif(TALLOC_CTX
*mem_ctx
,
1233 struct samsync_context
*ctx
,
1234 enum netr_SamDatabaseID database_id
,
1235 uint64_t sequence_num
)
1237 struct samsync_ldif_context
*ldif_ctx
=
1238 (struct samsync_ldif_context
*)ctx
->private_data
;
1240 /* This was the last query */
1241 ldif_write_output(database_id
, ldif_ctx
);
1242 if (ldif_ctx
->ldif_file
!= stdout
) {
1243 ctx
->result_message
= talloc_asprintf(ctx
,
1244 "Vampired %d accounts and %d groups to %s",
1245 a_index
, g_index
, ctx
->output_filename
);
1248 ldif_free_context(ldif_ctx
);
1249 ctx
->private_data
= NULL
;
1251 return NT_STATUS_OK
;
1254 #else /* HAVE_LDAP */
1256 static NTSTATUS
init_ldif(TALLOC_CTX
*mem_ctx
,
1257 struct samsync_context
*ctx
,
1258 enum netr_SamDatabaseID database_id
,
1259 uint64_t *sequence_num
)
1261 return NT_STATUS_NOT_SUPPORTED
;
1264 static NTSTATUS
fetch_sam_entries_ldif(TALLOC_CTX
*mem_ctx
,
1265 enum netr_SamDatabaseID database_id
,
1266 struct netr_DELTA_ENUM_ARRAY
*r
,
1267 uint64_t *sequence_num
,
1268 struct samsync_context
*ctx
)
1270 return NT_STATUS_NOT_SUPPORTED
;
1273 static NTSTATUS
close_ldif(TALLOC_CTX
*mem_ctx
,
1274 struct samsync_context
*ctx
,
1275 enum netr_SamDatabaseID database_id
,
1276 uint64_t sequence_num
)
1278 return NT_STATUS_NOT_SUPPORTED
;
1283 const struct samsync_ops libnet_samsync_ldif_ops
= {
1284 .startup
= init_ldif
,
1285 .process_objects
= fetch_sam_entries_ldif
,
1286 .finish
= close_ldif
,