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
if (groupmap[0].sambaSID == NULL || groupmap[0].group_dn == NULL) {
352
accountmap[0].rid = 512;
353
accountmap[0].cn = talloc_strdup(mem_ctx, "Domain Admins");
354
if (accountmap[0].cn == NULL) {
358
groupmap[1].rid = 513;
359
groupmap[1].gidNumber = 513;
360
groupmap[1].sambaSID = talloc_asprintf(mem_ctx, "%s-513", sid);
361
groupmap[1].group_dn = talloc_asprintf(mem_ctx,
362
"cn=Domain Users,ou=%s,%s", group_attr, suffix);
363
if (groupmap[1].sambaSID == NULL || groupmap[1].group_dn == NULL) {
367
accountmap[1].rid = 513;
368
accountmap[1].cn = talloc_strdup(mem_ctx, "Domain Users");
369
if (accountmap[1].cn == NULL) {
373
groupmap[2].rid = 514;
374
groupmap[2].gidNumber = 514;
375
groupmap[2].sambaSID = talloc_asprintf(mem_ctx, "%s-514", sid);
376
groupmap[2].group_dn = talloc_asprintf(mem_ctx,
377
"cn=Domain Guests,ou=%s,%s", group_attr, suffix);
378
if (groupmap[2].sambaSID == NULL || groupmap[2].group_dn == NULL) {
382
accountmap[2].rid = 514;
383
accountmap[2].cn = talloc_strdup(mem_ctx, "Domain Guests");
384
if (accountmap[2].cn == NULL) {
388
groupmap[3].rid = 515;
389
groupmap[3].gidNumber = 515;
390
groupmap[3].sambaSID = talloc_asprintf(mem_ctx, "%s-515", sid);
391
groupmap[3].group_dn = talloc_asprintf(mem_ctx,
392
"cn=Domain Computers,ou=%s,%s", group_attr, suffix);
393
if (groupmap[3].sambaSID == NULL || groupmap[3].group_dn == NULL) {
397
accountmap[3].rid = 515;
398
accountmap[3].cn = talloc_strdup(mem_ctx, "Domain Computers");
399
if (accountmap[3].cn == NULL) {
403
groupmap[4].rid = 544;
404
groupmap[4].gidNumber = 544;
405
groupmap[4].sambaSID = talloc_asprintf(mem_ctx, "%s-544", builtin_sid);
406
groupmap[4].group_dn = talloc_asprintf(mem_ctx,
407
"cn=Administrators,ou=%s,%s", group_attr, suffix);
408
if (groupmap[4].sambaSID == NULL || groupmap[4].group_dn == NULL) {
412
accountmap[4].rid = 515;
413
accountmap[4].cn = talloc_strdup(mem_ctx, "Administrators");
414
if (accountmap[4].cn == NULL) {
418
groupmap[5].rid = 550;
419
groupmap[5].gidNumber = 550;
420
groupmap[5].sambaSID = talloc_asprintf(mem_ctx, "%s-550", builtin_sid);
421
groupmap[5].group_dn = talloc_asprintf(mem_ctx,
422
"cn=Print Operators,ou=%s,%s", group_attr, suffix);
423
if (groupmap[5].sambaSID == NULL || groupmap[5].group_dn == NULL) {
427
accountmap[5].rid = 550;
428
accountmap[5].cn = talloc_strdup(mem_ctx, "Print Operators");
429
if (accountmap[5].cn == NULL) {
433
groupmap[6].rid = 551;
434
groupmap[6].gidNumber = 551;
435
groupmap[6].sambaSID = talloc_asprintf(mem_ctx, "%s-551", builtin_sid);
436
groupmap[6].group_dn = talloc_asprintf(mem_ctx,
437
"cn=Backup Operators,ou=%s,%s", group_attr, suffix);
438
if (groupmap[6].sambaSID == NULL || groupmap[6].group_dn == NULL) {
442
accountmap[6].rid = 551;
443
accountmap[6].cn = talloc_strdup(mem_ctx, "Backup Operators");
444
if (accountmap[6].cn == NULL) {
448
groupmap[7].rid = 552;
449
groupmap[7].gidNumber = 552;
450
groupmap[7].sambaSID = talloc_asprintf(mem_ctx, "%s-552", builtin_sid);
451
groupmap[7].group_dn = talloc_asprintf(mem_ctx,
452
"cn=Replicators,ou=%s,%s", group_attr, suffix);
453
if (groupmap[7].sambaSID == NULL || groupmap[7].group_dn == NULL) {
457
accountmap[7].rid = 551;
458
accountmap[7].cn = talloc_strdup(mem_ctx, "Replicators");
459
if (accountmap[7].cn == NULL) {
463
SAFE_FREE(group_attr);
469
SAFE_FREE(group_attr);
470
return NT_STATUS_NO_MEMORY;
474
* This is a crap routine, but I think it's the quickest way to solve the
475
* UTF8->base64 problem.
478
static int fprintf_attr(FILE *add_fd, const char *attr_name,
479
const char *fmt, ...)
482
char *value, *p, *base64;
483
DATA_BLOB base64_blob;
484
bool do_base64 = false;
488
value = talloc_vasprintf(NULL, fmt, ap);
491
SMB_ASSERT(value != NULL);
493
for (p=value; *p; p++) {
501
bool only_whitespace = true;
502
for (p=value; *p; p++) {
504
* I know that this not multibyte safe, but we break
505
* on the first non-whitespace character anyway.
508
only_whitespace = false;
512
if (only_whitespace) {
518
res = fprintf(add_fd, "%s: %s\n", attr_name, value);
523
base64_blob.data = (unsigned char *)value;
524
base64_blob.length = strlen(value);
526
base64 = base64_encode_data_blob(value, base64_blob);
527
SMB_ASSERT(base64 != NULL);
529
res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
534
/****************************************************************
535
****************************************************************/
537
static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx,
538
struct netr_DELTA_GROUP *r,
544
const char *groupname = r->group_name.string;
545
uint32 grouptype = 0, g_rid = 0;
546
char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
548
/* Set up the group type (always 2 for group info) */
551
/* These groups are entered by populate_ldap_for_ldif */
552
if (strcmp(groupname, "Domain Admins") == 0 ||
553
strcmp(groupname, "Domain Users") == 0 ||
554
strcmp(groupname, "Domain Guests") == 0 ||
555
strcmp(groupname, "Domain Computers") == 0 ||
556
strcmp(groupname, "Administrators") == 0 ||
557
strcmp(groupname, "Print Operators") == 0 ||
558
strcmp(groupname, "Backup Operators") == 0 ||
559
strcmp(groupname, "Replicators") == 0) {
560
SAFE_FREE(group_attr);
563
/* Increment the gid for the new group */
567
/* Map the group rid, gid, and dn */
569
groupmap->rid = g_rid;
570
groupmap->gidNumber = ldif_gid;
571
groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
572
groupmap->group_dn = talloc_asprintf(mem_ctx,
573
"cn=%s,ou=%s,%s", groupname, group_attr, suffix);
574
if (groupmap->sambaSID == NULL || groupmap->group_dn == NULL) {
575
SAFE_FREE(group_attr);
576
return NT_STATUS_NO_MEMORY;
579
/* Write the data to the temporary add ldif file */
580
fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr,
582
fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", groupname, group_attr,
584
fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
585
fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
586
fprintf_attr(add_fd, "cn", "%s", groupname);
587
fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
588
fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
589
fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
590
fprintf_attr(add_fd, "displayName", "%s", groupname);
591
fprintf(add_fd, "\n");
594
SAFE_FREE(group_attr);
599
/****************************************************************
600
****************************************************************/
602
static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx,
603
struct netr_DELTA_USER *r,
605
ACCOUNTMAP *accountmap,
611
fstring username, logonscript, homedrive, homepath = "", homedir = "";
612
fstring hex_nt_passwd, hex_lm_passwd;
613
fstring description, profilepath, fullname, sambaSID;
614
char *flags, *user_rdn;
616
const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
618
uint32 rid = 0, group_rid = 0, gidNumber = 0;
622
memset(zero_buf, '\0', sizeof(zero_buf));
624
/* Get the username */
625
fstrcpy(username, r->account_name.string);
630
/* Map the rid and username for group member info later */
631
accountmap->rid = rid;
632
accountmap->cn = talloc_strdup(mem_ctx, username);
633
NT_STATUS_HAVE_NO_MEMORY(accountmap->cn);
635
/* Get the home directory */
636
if (r->acct_flags & ACB_NORMAL) {
637
fstrcpy(homedir, r->home_directory.string);
639
snprintf(homedir, sizeof(homedir), "/home/%s", username);
641
snprintf(homedir, sizeof(homedir), "/nobodyshomedir");
643
ou = lp_ldap_user_suffix();
645
ou = lp_ldap_machine_suffix();
646
snprintf(homedir, sizeof(homedir), "/machinehomedir");
649
/* Get the logon script */
650
fstrcpy(logonscript, r->logon_script.string);
652
/* Get the home drive */
653
fstrcpy(homedrive, r->home_drive.string);
655
/* Get the home path */
656
fstrcpy(homepath, r->home_directory.string);
658
/* Get the description */
659
fstrcpy(description, r->description.string);
661
/* Get the display name */
662
fstrcpy(fullname, r->full_name.string);
664
/* Get the profile path */
665
fstrcpy(profilepath, r->profile_path.string);
667
/* Get lm and nt password data */
668
if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
669
pdb_sethexpwd(hex_lm_passwd, r->lmpassword.hash, r->acct_flags);
671
pdb_sethexpwd(hex_lm_passwd, NULL, 0);
673
if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
674
pdb_sethexpwd(hex_nt_passwd, r->ntpassword.hash, r->acct_flags);
676
pdb_sethexpwd(hex_nt_passwd, NULL, 0);
678
unix_time = nt_time_to_unix(r->last_password_change);
680
/* Increment the uid for the new user */
683
/* Set up group id and sambaSID for the user */
684
group_rid = r->primary_gid;
685
for (i=0; i<alloced; i++) {
686
if (groupmap[i].rid == group_rid) break;
689
DEBUG(1, ("Could not find rid %d in groupmap array\n",
691
return NT_STATUS_UNSUCCESSFUL;
693
gidNumber = groupmap[i].gidNumber;
694
ret = snprintf(sambaSID, sizeof(sambaSID), "%s", groupmap[i].sambaSID);
695
if (ret < 0 || ret == sizeof(sambaSID)) {
696
return NT_STATUS_UNSUCCESSFUL;
699
/* Set up sambaAcctFlags */
700
flags = pdb_encode_acct_ctrl(r->acct_flags,
701
NEW_PW_FORMAT_SPACE_PADDED_LEN);
703
/* Add the user to the temporary add ldif file */
704
/* this isn't quite right...we can't assume there's just OU=. jmcd */
705
user_rdn = sstring_sub(ou, '=', ',');
706
fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
707
fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
710
fprintf(add_fd, "ObjectClass: top\n");
711
fprintf(add_fd, "objectClass: inetOrgPerson\n");
712
fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT);
713
fprintf(add_fd, "objectClass: shadowAccount\n");
714
fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT);
715
fprintf_attr(add_fd, "cn", "%s", username);
716
fprintf_attr(add_fd, "sn", "%s", username);
717
fprintf_attr(add_fd, "uid", "%s", username);
718
fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
719
fprintf(add_fd, "gidNumber: %d\n", gidNumber);
720
fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
722
fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
724
fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
726
fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
727
fprintf(add_fd, "loginShell: %s\n",
728
((r->acct_flags & ACB_NORMAL) ?
729
"/bin/bash" : "/bin/false"));
730
fprintf(add_fd, "gecos: System User\n");
732
fprintf_attr(add_fd, "description", "%s", description);
733
fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
734
fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
736
fprintf_attr(add_fd, "displayName", "%s", fullname);
738
fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
739
if (strcmp(nopasswd, hex_lm_passwd) != 0)
740
fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
741
if (strcmp(nopasswd, hex_nt_passwd) != 0)
742
fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd);
743
fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time);
744
fprintf(add_fd, "sambaAcctFlags: %s\n", flags);
745
fprintf(add_fd, "\n");
752
/****************************************************************
753
****************************************************************/
755
static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx,
756
struct netr_DELTA_ALIAS *r,
761
enum netr_SamDatabaseID database_id)
763
fstring aliasname, description;
764
uint32 grouptype = 0, g_rid = 0;
765
char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
767
/* Get the alias name */
768
fstrcpy(aliasname, r->alias_name.string);
770
/* Get the alias description */
771
fstrcpy(description, r->description.string);
773
/* Set up the group type */
774
switch (database_id) {
775
case SAM_DATABASE_DOMAIN:
778
case SAM_DATABASE_BUILTIN:
787
These groups are entered by populate_ldap_for_ldif
788
Note that populate creates a group called Relicators,
789
but NT returns a group called Replicator
791
if (strcmp(aliasname, "Domain Admins") == 0 ||
792
strcmp(aliasname, "Domain Users") == 0 ||
793
strcmp(aliasname, "Domain Guests") == 0 ||
794
strcmp(aliasname, "Domain Computers") == 0 ||
795
strcmp(aliasname, "Administrators") == 0 ||
796
strcmp(aliasname, "Print Operators") == 0 ||
797
strcmp(aliasname, "Backup Operators") == 0 ||
798
strcmp(aliasname, "Replicator") == 0) {
799
SAFE_FREE(group_attr);
802
/* Increment the gid for the new group */
806
/* Map the group rid and gid */
808
groupmap->gidNumber = ldif_gid;
809
groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
810
if (groupmap->sambaSID == NULL) {
811
SAFE_FREE(group_attr);
812
return NT_STATUS_NO_MEMORY;
815
/* Write the data to the temporary add ldif file */
816
fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr,
818
fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", aliasname, group_attr,
820
fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXGROUP);
821
fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_GROUPMAP);
822
fprintf(add_fd, "cn: %s\n", aliasname);
823
fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
824
fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
825
fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
826
fprintf_attr(add_fd, "displayName", "%s", aliasname);
828
fprintf_attr(add_fd, "description", "%s", description);
829
fprintf(add_fd, "\n");
832
SAFE_FREE(group_attr);
837
/****************************************************************
838
****************************************************************/
840
static NTSTATUS fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER *r,
843
ACCOUNTMAP *accountmap,
844
FILE *mod_fd, int alloced)
847
uint32 group_rid = 0, rid = 0;
850
/* Get the dn for the group */
851
if (r->num_rids > 0) {
853
for (j=0; j<alloced; j++) {
854
if (groupmap[j].rid == group_rid) break;
857
DEBUG(1, ("Could not find rid %d in groupmap array\n",
859
return NT_STATUS_UNSUCCESSFUL;
861
snprintf(group_dn, sizeof(group_dn), "%s", groupmap[j].group_dn);
862
fprintf(mod_fd, "dn: %s\n", group_dn);
864
/* Get the cn for each member */
865
for (i=0; i < r->num_rids; i++) {
867
for (k=0; k<alloced; k++) {
868
if (accountmap[k].rid == rid) break;
871
DEBUG(1, ("Could not find rid %d in "
872
"accountmap array\n", rid));
873
return NT_STATUS_UNSUCCESSFUL;
875
fprintf(mod_fd, "memberUid: %s\n", accountmap[k].cn);
877
fprintf(mod_fd, "\n");
885
/****************************************************************
886
****************************************************************/
888
static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx,
889
enum netr_SamDatabaseID database_id,
890
const char *ldif_filename,
891
const char *domain_sid_str,
892
struct samsync_ldif_context **ctx)
894
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
895
struct samsync_ldif_context *r;
896
const char *add_template = "/tmp/add.ldif.XXXXXX";
897
const char *mod_template = "/tmp/mod.ldif.XXXXXX";
898
const char *builtin_sid = "S-1-5-32";
900
/* Get other smb.conf data */
901
if (!(lp_workgroup()) || !*(lp_workgroup())) {
902
DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
906
/* Get the ldap suffix */
907
if (!(lp_ldap_suffix()) || !*(lp_ldap_suffix())) {
908
DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
912
if (*ctx && (*ctx)->initialized) {
916
r = TALLOC_ZERO_P(mem_ctx, struct samsync_ldif_context);
917
NT_STATUS_HAVE_NO_MEMORY(r);
919
/* Get the ldap suffix */
920
r->suffix = lp_ldap_suffix();
922
/* Ensure we have an output file */
924
r->ldif_file = fopen(ldif_filename, "a");
926
r->ldif_file = stdout;
930
fprintf(stderr, "Could not open %s\n", ldif_filename);
931
DEBUG(1, ("Could not open %s\n", ldif_filename));
932
status = NT_STATUS_UNSUCCESSFUL;
936
r->add_template = talloc_strdup(mem_ctx, add_template);
937
r->mod_template = talloc_strdup(mem_ctx, mod_template);
938
if (!r->add_template || !r->mod_template) {
939
status = NT_STATUS_NO_MEMORY;
943
r->add_name = talloc_strdup(mem_ctx, add_template);
944
r->mod_name = talloc_strdup(mem_ctx, mod_template);
945
if (!r->add_name || !r->mod_name) {
946
status = NT_STATUS_NO_MEMORY;
950
/* Open the add and mod ldif files */
951
if (!(r->add_file = fdopen(smb_mkstemp(r->add_name),"w"))) {
952
DEBUG(1, ("Could not open %s\n", r->add_name));
953
status = NT_STATUS_UNSUCCESSFUL;
956
if (!(r->mod_file = fdopen(smb_mkstemp(r->mod_name),"w"))) {
957
DEBUG(1, ("Could not open %s\n", r->mod_name));
958
status = NT_STATUS_UNSUCCESSFUL;
962
/* Allocate initial memory for groupmap and accountmap arrays */
963
r->groupmap = TALLOC_ZERO_ARRAY(mem_ctx, GROUPMAP, 8);
964
r->accountmap = TALLOC_ZERO_ARRAY(mem_ctx, ACCOUNTMAP, 8);
965
if (r->groupmap == NULL || r->accountmap == NULL) {
966
DEBUG(1,("GROUPMAP talloc failed\n"));
967
status = NT_STATUS_NO_MEMORY;
971
/* Remember how many we malloced */
974
/* Initial database population */
975
if (database_id == SAM_DATABASE_DOMAIN) {
977
status = populate_ldap_for_ldif(domain_sid_str,
981
if (!NT_STATUS_IS_OK(status)) {
985
status = map_populate_groups(mem_ctx,
991
if (!NT_STATUS_IS_OK(status)) {
996
r->initialized = true;
1000
return NT_STATUS_OK;
1006
/****************************************************************
1007
****************************************************************/
1009
static void ldif_free_context(struct samsync_ldif_context *r)
1015
/* Close and delete the ldif files */
1017
fclose(r->add_file);
1020
if ((r->add_name != NULL) &&
1021
strcmp(r->add_name, r->add_template) && (unlink(r->add_name))) {
1022
DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1023
r->add_name, strerror(errno)));
1027
fclose(r->mod_file);
1030
if ((r->mod_name != NULL) &&
1031
strcmp(r->mod_name, r->mod_template) && (unlink(r->mod_name))) {
1032
DEBUG(1,("unlink(%s) failed, error was (%s)\n",
1033
r->mod_name, strerror(errno)));
1036
if (r->ldif_file && (r->ldif_file != stdout)) {
1037
fclose(r->ldif_file);
1043
/****************************************************************
1044
****************************************************************/
1046
static void ldif_write_output(enum netr_SamDatabaseID database_id,
1047
struct samsync_ldif_context *l)
1049
/* Write ldif data to the user's file */
1050
if (database_id == SAM_DATABASE_DOMAIN) {
1051
fprintf(l->ldif_file,
1052
"# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
1053
fprintf(l->ldif_file,
1054
"# =================================\n\n");
1055
fflush(l->ldif_file);
1056
} else if (database_id == SAM_DATABASE_BUILTIN) {
1057
fprintf(l->ldif_file,
1058
"# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
1059
fprintf(l->ldif_file,
1060
"# ==================================\n\n");
1061
fflush(l->ldif_file);
1063
fseek(l->add_file, 0, SEEK_SET);
1064
transfer_file(fileno(l->add_file), fileno(l->ldif_file), (size_t) -1);
1066
if (database_id == SAM_DATABASE_DOMAIN) {
1067
fprintf(l->ldif_file,
1068
"# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
1069
fprintf(l->ldif_file,
1070
"# ====================================\n\n");
1071
fflush(l->ldif_file);
1072
} else if (database_id == SAM_DATABASE_BUILTIN) {
1073
fprintf(l->ldif_file,
1074
"# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
1075
fprintf(l->ldif_file,
1076
"# =====================================\n\n");
1077
fflush(l->ldif_file);
1079
fseek(l->mod_file, 0, SEEK_SET);
1080
transfer_file(fileno(l->mod_file), fileno(l->ldif_file), (size_t) -1);
1083
/****************************************************************
1084
****************************************************************/
1086
static NTSTATUS fetch_sam_entry_ldif(TALLOC_CTX *mem_ctx,
1087
enum netr_SamDatabaseID database_id,
1088
struct netr_DELTA_ENUM *r,
1089
struct samsync_context *ctx,
1090
uint32_t *a_index_p,
1091
uint32_t *g_index_p)
1093
union netr_DELTA_UNION u = r->delta_union;
1094
union netr_DELTA_ID_UNION id = r->delta_id_union;
1095
struct samsync_ldif_context *l =
1096
talloc_get_type_abort(ctx->private_data, struct samsync_ldif_context);
1098
switch (r->delta_type) {
1099
case NETR_DELTA_DOMAIN:
1102
case NETR_DELTA_GROUP:
1103
fetch_group_info_to_ldif(mem_ctx,
1105
&l->groupmap[*g_index_p],
1107
ctx->domain_sid_str,
1112
case NETR_DELTA_USER:
1113
fetch_account_info_to_ldif(mem_ctx,
1116
&l->accountmap[*a_index_p],
1118
ctx->domain_sid_str,
1124
case NETR_DELTA_ALIAS:
1125
fetch_alias_info_to_ldif(mem_ctx,
1127
&l->groupmap[*g_index_p],
1129
ctx->domain_sid_str,
1135
case NETR_DELTA_GROUP_MEMBER:
1136
fetch_groupmem_info_to_ldif(u.group_member,
1144
case NETR_DELTA_ALIAS_MEMBER:
1145
case NETR_DELTA_POLICY:
1146
case NETR_DELTA_ACCOUNT:
1147
case NETR_DELTA_TRUSTED_DOMAIN:
1148
case NETR_DELTA_SECRET:
1149
case NETR_DELTA_RENAME_GROUP:
1150
case NETR_DELTA_RENAME_USER:
1151
case NETR_DELTA_RENAME_ALIAS:
1152
case NETR_DELTA_DELETE_GROUP:
1153
case NETR_DELTA_DELETE_USER:
1154
case NETR_DELTA_MODIFY_COUNT:
1157
} /* end of switch */
1159
return NT_STATUS_OK;
1162
/****************************************************************
1163
****************************************************************/
1165
static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx,
1166
struct samsync_ldif_context *l,
1167
uint32_t num_entries)
1169
/* Re-allocate memory for groupmap and accountmap arrays */
1170
l->groupmap = TALLOC_REALLOC_ARRAY(mem_ctx,
1173
num_entries + l->num_alloced);
1175
l->accountmap = TALLOC_REALLOC_ARRAY(mem_ctx,
1178
num_entries + l->num_alloced);
1180
if (l->groupmap == NULL || l->accountmap == NULL) {
1181
DEBUG(1,("GROUPMAP talloc failed\n"));
1182
return NT_STATUS_NO_MEMORY;
1185
/* Initialize the new records */
1186
memset(&(l->groupmap[l->num_alloced]), 0,
1187
sizeof(GROUPMAP) * num_entries);
1188
memset(&(l->accountmap[l->num_alloced]), 0,
1189
sizeof(ACCOUNTMAP) * num_entries);
1191
/* Remember how many we alloced this time */
1192
l->num_alloced += num_entries;
1194
return NT_STATUS_OK;
1197
/****************************************************************
1198
****************************************************************/
1200
static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
1201
struct samsync_context *ctx,
1202
enum netr_SamDatabaseID database_id,
1203
uint64_t *sequence_num)
1206
struct samsync_ldif_context *ldif_ctx =
1207
(struct samsync_ldif_context *)ctx->private_data;
1209
status = ldif_init_context(mem_ctx,
1211
ctx->output_filename,
1212
ctx->domain_sid_str,
1214
if (!NT_STATUS_IS_OK(status)) {
1218
ctx->private_data = ldif_ctx;
1220
return NT_STATUS_OK;
1223
/****************************************************************
1224
****************************************************************/
1226
static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
1227
enum netr_SamDatabaseID database_id,
1228
struct netr_DELTA_ENUM_ARRAY *r,
1229
uint64_t *sequence_num,
1230
struct samsync_context *ctx)
1234
struct samsync_ldif_context *ldif_ctx =
1235
(struct samsync_ldif_context *)ctx->private_data;
1237
status = ldif_realloc_maps(mem_ctx, ldif_ctx, r->num_deltas);
1238
if (!NT_STATUS_IS_OK(status)) {
1242
for (i = 0; i < r->num_deltas; i++) {
1243
status = fetch_sam_entry_ldif(mem_ctx, database_id,
1244
&r->delta_enum[i], ctx,
1245
&a_index, &g_index);
1246
if (!NT_STATUS_IS_OK(status)) {
1251
return NT_STATUS_OK;
1254
ldif_free_context(ldif_ctx);
1255
ctx->private_data = NULL;
1260
/****************************************************************
1261
****************************************************************/
1263
static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
1264
struct samsync_context *ctx,
1265
enum netr_SamDatabaseID database_id,
1266
uint64_t sequence_num)
1268
struct samsync_ldif_context *ldif_ctx =
1269
(struct samsync_ldif_context *)ctx->private_data;
1271
/* This was the last query */
1272
ldif_write_output(database_id, ldif_ctx);
1273
if (ldif_ctx->ldif_file != stdout) {
1274
ctx->result_message = talloc_asprintf(ctx,
1275
"Vampired %d accounts and %d groups to %s",
1276
a_index, g_index, ctx->output_filename);
1279
ldif_free_context(ldif_ctx);
1280
ctx->private_data = NULL;
1282
return NT_STATUS_OK;
1285
#else /* HAVE_LDAP */
1287
static NTSTATUS init_ldif(TALLOC_CTX *mem_ctx,
1288
struct samsync_context *ctx,
1289
enum netr_SamDatabaseID database_id,
1290
uint64_t *sequence_num)
1292
return NT_STATUS_NOT_SUPPORTED;
1295
static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
1296
enum netr_SamDatabaseID database_id,
1297
struct netr_DELTA_ENUM_ARRAY *r,
1298
uint64_t *sequence_num,
1299
struct samsync_context *ctx)
1301
return NT_STATUS_NOT_SUPPORTED;
1304
static NTSTATUS close_ldif(TALLOC_CTX *mem_ctx,
1305
struct samsync_context *ctx,
1306
enum netr_SamDatabaseID database_id,
1307
uint64_t sequence_num)
1309
return NT_STATUS_NOT_SUPPORTED;
1314
const struct samsync_ops libnet_samsync_ldif_ops = {
1315
.startup = init_ldif,
1316
.process_objects = fetch_sam_entries_ldif,
1317
.finish = close_ldif,