net_vampire: restructure internal code more.
[vlendec/samba-autobuild/.git] / source3 / utils / net_rpc_samsync.c
1 /*
2    Unix SMB/CIFS implementation.
3    dump the remote SAM using rpc samsync operations
4
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.
11
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.
16
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.
21
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/>.
24 */
25
26 #include "includes.h"
27 #include "utils/net.h"
28
29 /* uid's and gid's for writing deltas to ldif */
30 static uint32 ldif_gid = 999;
31 static uint32 ldif_uid = 999;
32
33 static void display_group_mem_info(uint32_t rid,
34                                    struct netr_DELTA_GROUP_MEMBER *r)
35 {
36         int i;
37         d_printf("Group mem %u: ", rid);
38         for (i=0; i< r->num_rids; i++) {
39                 d_printf("%u ", r->rids[i]);
40         }
41         d_printf("\n");
42 }
43
44 static void display_alias_info(uint32_t rid,
45                                struct netr_DELTA_ALIAS *r)
46 {
47         d_printf("Alias '%s' ", r->alias_name.string);
48         d_printf("desc='%s' rid=%u\n", r->description.string, r->rid);
49 }
50
51 static void display_alias_mem(uint32_t rid,
52                               struct netr_DELTA_ALIAS_MEMBER *r)
53 {
54         int i;
55         d_printf("Alias rid %u: ", rid);
56         for (i=0; i< r->sids.num_sids; i++) {
57                 d_printf("%s ", sid_string_tos(r->sids.sids[i].sid));
58         }
59         d_printf("\n");
60 }
61
62 static void display_account_info(uint32_t rid,
63                                  struct netr_DELTA_USER *r)
64 {
65         fstring hex_nt_passwd, hex_lm_passwd;
66         uchar lm_passwd[16], nt_passwd[16];
67         static uchar zero_buf[16];
68
69         /* Decode hashes from password hash (if they are not NULL) */
70
71         if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
72                 sam_pwd_hash(r->rid, r->lmpassword.hash, lm_passwd, 0);
73                 pdb_sethexpwd(hex_lm_passwd, lm_passwd, r->acct_flags);
74         } else {
75                 pdb_sethexpwd(hex_lm_passwd, NULL, 0);
76         }
77
78         if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
79                 sam_pwd_hash(r->rid, r->ntpassword.hash, nt_passwd, 0);
80                 pdb_sethexpwd(hex_nt_passwd, nt_passwd, r->acct_flags);
81         } else {
82                 pdb_sethexpwd(hex_nt_passwd, NULL, 0);
83         }
84
85         printf("%s:%d:%s:%s:%s:LCT-0\n",
86                 r->account_name.string,
87                 r->rid, hex_lm_passwd, hex_nt_passwd,
88                 pdb_encode_acct_ctrl(r->acct_flags, NEW_PW_FORMAT_SPACE_PADDED_LEN));
89 }
90
91 static time_t uint64s_nt_time_to_unix_abs(const uint64 *src)
92 {
93         NTTIME nttime;
94         nttime = *src;
95         return nt_time_to_unix_abs(&nttime);
96 }
97
98 static NTSTATUS pull_netr_AcctLockStr(TALLOC_CTX *mem_ctx,
99                                       struct lsa_BinaryString *r,
100                                       struct netr_AcctLockStr **str_p)
101 {
102         struct netr_AcctLockStr *str;
103         enum ndr_err_code ndr_err;
104         DATA_BLOB blob;
105
106         if (!mem_ctx || !r || !str_p) {
107                 return NT_STATUS_INVALID_PARAMETER;
108         }
109
110         *str_p = NULL;
111
112         str = TALLOC_ZERO_P(mem_ctx, struct netr_AcctLockStr);
113         if (!str) {
114                 return NT_STATUS_NO_MEMORY;
115         }
116
117         blob = data_blob_const(r->array, r->length);
118
119         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, str,
120                        (ndr_pull_flags_fn_t)ndr_pull_netr_AcctLockStr);
121         data_blob_free(&blob);
122
123         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
124                 return ndr_map_error2ntstatus(ndr_err);
125         }
126
127         *str_p = str;
128
129         return NT_STATUS_OK;
130 }
131
132 static void display_domain_info(struct netr_DELTA_DOMAIN *r)
133 {
134         time_t u_logout;
135         struct netr_AcctLockStr *lockstr = NULL;
136         NTSTATUS status;
137         TALLOC_CTX *mem_ctx = talloc_tos();
138
139         status = pull_netr_AcctLockStr(mem_ctx, &r->account_lockout,
140                                        &lockstr);
141         if (!NT_STATUS_IS_OK(status)) {
142                 d_printf("failed to pull account lockout string: %s\n",
143                         nt_errstr(status));
144         }
145
146         u_logout = uint64s_nt_time_to_unix_abs((const uint64 *)&r->force_logoff_time);
147
148         d_printf("Domain name: %s\n", r->domain_name.string);
149
150         d_printf("Minimal Password Length: %d\n", r->min_password_length);
151         d_printf("Password History Length: %d\n", r->password_history_length);
152
153         d_printf("Force Logoff: %d\n", (int)u_logout);
154
155         d_printf("Max Password Age: %s\n", display_time(r->max_password_age));
156         d_printf("Min Password Age: %s\n", display_time(r->min_password_age));
157
158         if (lockstr) {
159                 d_printf("Lockout Time: %s\n", display_time((NTTIME)lockstr->lockout_duration));
160                 d_printf("Lockout Reset Time: %s\n", display_time((NTTIME)lockstr->reset_count));
161                 d_printf("Bad Attempt Lockout: %d\n", lockstr->bad_attempt_lockout);
162         }
163
164         d_printf("User must logon to change password: %d\n", r->logon_to_chgpass);
165 }
166
167 static void display_group_info(uint32_t rid, struct netr_DELTA_GROUP *r)
168 {
169         d_printf("Group '%s' ", r->group_name.string);
170         d_printf("desc='%s', rid=%u\n", r->description.string, rid);
171 }
172
173 static NTSTATUS display_sam_entry(TALLOC_CTX *mem_ctx,
174                                   enum netr_SamDatabaseID database_id,
175                                   struct netr_DELTA_ENUM *r,
176                                   NTSTATUS status,
177                                   struct samsync_context *ctx)
178 {
179         union netr_DELTA_UNION u = r->delta_union;
180         union netr_DELTA_ID_UNION id = r->delta_id_union;
181
182         switch (r->delta_type) {
183         case NETR_DELTA_DOMAIN:
184                 display_domain_info(u.domain);
185                 break;
186         case NETR_DELTA_GROUP:
187                 display_group_info(id.rid, u.group);
188                 break;
189 #if 0
190         case NETR_DELTA_DELETE_GROUP:
191                 printf("Delete Group: %d\n",
192                         u.delete_account.unknown);
193                 break;
194         case NETR_DELTA_RENAME_GROUP:
195                 printf("Rename Group: %s -> %s\n",
196                         u.rename_group->OldName.string,
197                         u.rename_group->NewName.string);
198                 break;
199 #endif
200         case NETR_DELTA_USER:
201                 display_account_info(id.rid, u.user);
202                 break;
203 #if 0
204         case NETR_DELTA_DELETE_USER:
205                 printf("Delete User: %d\n",
206                         id.rid);
207                 break;
208         case NETR_DELTA_RENAME_USER:
209                 printf("Rename user: %s -> %s\n",
210                         u.rename_user->OldName.string,
211                         u.rename_user->NewName.string);
212                 break;
213 #endif
214         case NETR_DELTA_GROUP_MEMBER:
215                 display_group_mem_info(id.rid, u.group_member);
216                 break;
217         case NETR_DELTA_ALIAS:
218                 display_alias_info(id.rid, u.alias);
219                 break;
220 #if 0
221         case NETR_DELTA_DELETE_ALIAS:
222                 printf("Delete Alias: %d\n",
223                         id.rid);
224                 break;
225         case NETR_DELTA_RENAME_ALIAS:
226                 printf("Rename alias: %s -> %s\n",
227                         u.rename_alias->OldName.string,
228                         u.rename_alias->NewName.string);
229                 break;
230 #endif
231         case NETR_DELTA_ALIAS_MEMBER:
232                 display_alias_mem(id.rid, u.alias_member);
233                 break;
234 #if 0
235         case NETR_DELTA_POLICY:
236                 printf("Policy\n");
237                 break;
238         case NETR_DELTA_TRUSTED_DOMAIN:
239                 printf("Trusted Domain: %s\n",
240                         u.trusted_domain->domain_name.string);
241                 break;
242         case NETR_DELTA_DELETE_TRUST:
243                 printf("Delete Trust: %d\n",
244                         u.delete_trust.unknown);
245                 break;
246         case NETR_DELTA_ACCOUNT:
247                 printf("Account\n");
248                 break;
249         case NETR_DELTA_DELETE_ACCOUNT:
250                 printf("Delete Account: %d\n",
251                         u.delete_account.unknown);
252                 break;
253         case NETR_DELTA_SECRET:
254                 printf("Secret\n");
255                 break;
256         case NETR_DELTA_DELETE_SECRET:
257                 printf("Delete Secret: %d\n",
258                         u.delete_secret.unknown);
259                 break;
260         case NETR_DELTA_DELETE_GROUP2:
261                 printf("Delete Group2: %s\n",
262                         u.delete_group->account_name);
263                 break;
264         case NETR_DELTA_DELETE_USER2:
265                 printf("Delete User2: %s\n",
266                         u.delete_user->account_name);
267                 break;
268         case NETR_DELTA_MODIFY_COUNT:
269                 printf("sam sequence update: 0x%016llx\n",
270                         (unsigned long long) *u.modified_count);
271                 break;
272 #endif
273         /* The following types are recognised but not handled */
274         case NETR_DELTA_RENAME_GROUP:
275                 d_printf("NETR_DELTA_RENAME_GROUP not handled\n");
276                 break;
277         case NETR_DELTA_RENAME_USER:
278                 d_printf("NETR_DELTA_RENAME_USER not handled\n");
279                 break;
280         case NETR_DELTA_RENAME_ALIAS:
281                 d_printf("NETR_DELTA_RENAME_ALIAS not handled\n");
282                 break;
283         case NETR_DELTA_POLICY:
284                 d_printf("NETR_DELTA_POLICY not handled\n");
285                 break;
286         case NETR_DELTA_TRUSTED_DOMAIN:
287                 d_printf("NETR_DELTA_TRUSTED_DOMAIN not handled\n");
288                 break;
289         case NETR_DELTA_ACCOUNT:
290                 d_printf("NETR_DELTA_ACCOUNT not handled\n");
291                 break;
292         case NETR_DELTA_SECRET:
293                 d_printf("NETR_DELTA_SECRET not handled\n");
294                 break;
295         case NETR_DELTA_DELETE_GROUP:
296                 d_printf("NETR_DELTA_DELETE_GROUP not handled\n");
297                 break;
298         case NETR_DELTA_DELETE_USER:
299                 d_printf("NETR_DELTA_DELETE_USER not handled\n");
300                 break;
301         case NETR_DELTA_MODIFY_COUNT:
302                 d_printf("NETR_DELTA_MODIFY_COUNT not handled\n");
303                 break;
304         case NETR_DELTA_DELETE_ALIAS:
305                 d_printf("NETR_DELTA_DELETE_ALIAS not handled\n");
306                 break;
307         case NETR_DELTA_DELETE_TRUST:
308                 d_printf("NETR_DELTA_DELETE_TRUST not handled\n");
309                 break;
310         case NETR_DELTA_DELETE_ACCOUNT:
311                 d_printf("NETR_DELTA_DELETE_ACCOUNT not handled\n");
312                 break;
313         case NETR_DELTA_DELETE_SECRET:
314                 d_printf("NETR_DELTA_DELETE_SECRET not handled\n");
315                 break;
316         case NETR_DELTA_DELETE_GROUP2:
317                 d_printf("NETR_DELTA_DELETE_GROUP2 not handled\n");
318                 break;
319         case NETR_DELTA_DELETE_USER2:
320                 d_printf("NETR_DELTA_DELETE_USER2 not handled\n");
321                 break;
322         default:
323                 printf("unknown delta type 0x%02x\n",
324                         r->delta_type);
325                 break;
326         }
327
328         return NT_STATUS_OK;
329 }
330
331 static NTSTATUS display_sam_entries(TALLOC_CTX *mem_ctx,
332                                     enum netr_SamDatabaseID database_id,
333                                     struct netr_DELTA_ENUM_ARRAY *r,
334                                     NTSTATUS status,
335                                     struct samsync_context *ctx)
336 {
337         int i;
338
339         for (i = 0; i < r->num_deltas; i++) {
340                 display_sam_entry(mem_ctx, database_id, &r->delta_enum[i], status, ctx);
341         }
342
343         return NT_STATUS_OK;
344 }
345
346 typedef NTSTATUS (*samsync_fn_t)(TALLOC_CTX *,
347                                  enum netr_SamDatabaseID,
348                                  struct netr_DELTA_ENUM_ARRAY *,
349                                  NTSTATUS,
350                                  struct samsync_context *);
351
352 static NTSTATUS process_database(struct rpc_pipe_client *pipe_hnd,
353                                  enum netr_SamDatabaseID database_id,
354                                  samsync_fn_t callback_fn,
355                                  struct samsync_context *ctx)
356 {
357         NTSTATUS result;
358         TALLOC_CTX *mem_ctx;
359         const char *logon_server = pipe_hnd->desthost;
360         const char *computername = global_myname();
361         struct netr_Authenticator credential;
362         struct netr_Authenticator return_authenticator;
363         uint16_t restart_state = 0;
364         uint32_t sync_context = 0;
365         DATA_BLOB session_key;
366         const char *action = NULL;
367
368         ZERO_STRUCT(return_authenticator);
369
370         if (!(mem_ctx = talloc_init("process_database"))) {
371                 return NT_STATUS_NO_MEMORY;
372         }
373
374         switch (ctx->mode) {
375                 case NET_SAMSYNC_MODE_DUMP:
376                         action = "Dumping (to stdout)";
377                         break;
378                 case NET_SAMSYNC_MODE_FETCH_PASSDB:
379                         action = "Fetching (to passdb)";
380                         break;
381                 case NET_SAMSYNC_MODE_FETCH_LDIF:
382                         action = "Fetching (to ldif)";
383                         break;
384                 default:
385                         action = "Unknown";
386                         break;
387         }
388
389         switch (database_id) {
390         case SAM_DATABASE_DOMAIN:
391                 d_fprintf(stderr, "%s DOMAIN database\n", action);
392                 break;
393         case SAM_DATABASE_BUILTIN:
394                 d_fprintf(stderr, "%s BUILTIN database\n", action);
395                 break;
396         case SAM_DATABASE_PRIVS:
397                 d_fprintf(stderr, "%s PRIVS databases\n", action);
398                 break;
399         default:
400                 d_fprintf(stderr, "%s unknown database type %u\n",
401                         action, database_id);
402                 break;
403         }
404
405         do {
406                 struct netr_DELTA_ENUM_ARRAY *delta_enum_array = NULL;
407
408                 netlogon_creds_client_step(pipe_hnd->dc, &credential);
409
410                 result = rpccli_netr_DatabaseSync2(pipe_hnd, mem_ctx,
411                                                    logon_server,
412                                                    computername,
413                                                    &credential,
414                                                    &return_authenticator,
415                                                    database_id,
416                                                    restart_state,
417                                                    &sync_context,
418                                                    &delta_enum_array,
419                                                    0xffff);
420                 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) {
421                         return result;
422                 }
423
424                 /* Check returned credentials. */
425                 if (!netlogon_creds_client_check(pipe_hnd->dc,
426                                                  &return_authenticator.cred)) {
427                         DEBUG(0,("credentials chain check failed\n"));
428                         return NT_STATUS_ACCESS_DENIED;
429                 }
430
431                 if (NT_STATUS_IS_ERR(result)) {
432                         break;
433                 }
434
435                 session_key = data_blob_const(pipe_hnd->dc->sess_key, 16);
436
437                 samsync_fix_delta_array(mem_ctx,
438                                         &session_key,
439                                         true,
440                                         database_id,
441                                         delta_enum_array);
442
443                 /* Process results */
444                 callback_fn(mem_ctx, database_id, delta_enum_array, result, ctx);
445
446                 TALLOC_FREE(delta_enum_array);
447
448                 /* Increment sync_context */
449                 sync_context += 1;
450
451         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
452
453         talloc_destroy(mem_ctx);
454
455         return result;
456 }
457
458 /* dump sam database via samsync rpc calls */
459 NTSTATUS rpc_samdump_internals(struct net_context *c,
460                                 const DOM_SID *domain_sid,
461                                 const char *domain_name,
462                                 struct cli_state *cli,
463                                 struct rpc_pipe_client *pipe_hnd,
464                                 TALLOC_CTX *mem_ctx,
465                                 int argc,
466                                 const char **argv)
467 {
468         struct samsync_context *ctx;
469
470         ctx = TALLOC_ZERO_P(mem_ctx, struct samsync_context);
471         NT_STATUS_HAVE_NO_MEMORY(ctx);
472
473         ctx->mode = NET_SAMSYNC_MODE_DUMP;
474         ctx->domain_sid = domain_sid;
475
476         process_database(pipe_hnd, SAM_DATABASE_DOMAIN,
477                          display_sam_entries, ctx);
478
479         process_database(pipe_hnd, SAM_DATABASE_BUILTIN,
480                          display_sam_entries, ctx);
481
482         process_database(pipe_hnd, SAM_DATABASE_PRIVS,
483                          display_sam_entries, ctx);
484
485         return NT_STATUS_OK;
486 }
487
488 /* Convert a struct samu_DELTA to a struct samu. */
489 #define STRING_CHANGED (old_string && !new_string) ||\
490                     (!old_string && new_string) ||\
491                 (old_string && new_string && (strcmp(old_string, new_string) != 0))
492
493 #define STRING_CHANGED_NC(s1,s2) ((s1) && !(s2)) ||\
494                     (!(s1) && (s2)) ||\
495                 ((s1) && (s2) && (strcmp((s1), (s2)) != 0))
496
497 static NTSTATUS sam_account_from_delta(struct samu *account,
498                                        struct netr_DELTA_USER *r)
499 {
500         const char *old_string, *new_string;
501         time_t unix_time, stored_time;
502         uchar lm_passwd[16], nt_passwd[16];
503         static uchar zero_buf[16];
504
505         /* Username, fullname, home dir, dir drive, logon script, acct
506            desc, workstations, profile. */
507
508         if (r->account_name.string) {
509                 old_string = pdb_get_nt_username(account);
510                 new_string = r->account_name.string;
511
512                 if (STRING_CHANGED) {
513                         pdb_set_nt_username(account, new_string, PDB_CHANGED);
514                 }
515
516                 /* Unix username is the same - for sanity */
517                 old_string = pdb_get_username( account );
518                 if (STRING_CHANGED) {
519                         pdb_set_username(account, new_string, PDB_CHANGED);
520                 }
521         }
522
523         if (r->full_name.string) {
524                 old_string = pdb_get_fullname(account);
525                 new_string = r->full_name.string;
526
527                 if (STRING_CHANGED)
528                         pdb_set_fullname(account, new_string, PDB_CHANGED);
529         }
530
531         if (r->home_directory.string) {
532                 old_string = pdb_get_homedir(account);
533                 new_string = r->home_directory.string;
534
535                 if (STRING_CHANGED)
536                         pdb_set_homedir(account, new_string, PDB_CHANGED);
537         }
538
539         if (r->home_drive.string) {
540                 old_string = pdb_get_dir_drive(account);
541                 new_string = r->home_drive.string;
542
543                 if (STRING_CHANGED)
544                         pdb_set_dir_drive(account, new_string, PDB_CHANGED);
545         }
546
547         if (r->logon_script.string) {
548                 old_string = pdb_get_logon_script(account);
549                 new_string = r->logon_script.string;
550
551                 if (STRING_CHANGED)
552                         pdb_set_logon_script(account, new_string, PDB_CHANGED);
553         }
554
555         if (r->description.string) {
556                 old_string = pdb_get_acct_desc(account);
557                 new_string = r->description.string;
558
559                 if (STRING_CHANGED)
560                         pdb_set_acct_desc(account, new_string, PDB_CHANGED);
561         }
562
563         if (r->workstations.string) {
564                 old_string = pdb_get_workstations(account);
565                 new_string = r->workstations.string;
566
567                 if (STRING_CHANGED)
568                         pdb_set_workstations(account, new_string, PDB_CHANGED);
569         }
570
571         if (r->profile_path.string) {
572                 old_string = pdb_get_profile_path(account);
573                 new_string = r->profile_path.string;
574
575                 if (STRING_CHANGED)
576                         pdb_set_profile_path(account, new_string, PDB_CHANGED);
577         }
578
579         if (r->parameters.string) {
580                 DATA_BLOB mung;
581                 char *newstr;
582                 old_string = pdb_get_munged_dial(account);
583                 mung.length = r->parameters.length;
584                 mung.data = (uint8 *) r->parameters.string;
585                 newstr = (mung.length == 0) ? NULL :
586                         base64_encode_data_blob(talloc_tos(), mung);
587
588                 if (STRING_CHANGED_NC(old_string, newstr))
589                         pdb_set_munged_dial(account, newstr, PDB_CHANGED);
590                 TALLOC_FREE(newstr);
591         }
592
593         /* User and group sid */
594         if (pdb_get_user_rid(account) != r->rid)
595                 pdb_set_user_sid_from_rid(account, r->rid, PDB_CHANGED);
596         if (pdb_get_group_rid(account) != r->primary_gid)
597                 pdb_set_group_sid_from_rid(account, r->primary_gid, PDB_CHANGED);
598
599         /* Logon and password information */
600         if (!nt_time_is_zero(&r->last_logon)) {
601                 unix_time = nt_time_to_unix(r->last_logon);
602                 stored_time = pdb_get_logon_time(account);
603                 if (stored_time != unix_time)
604                         pdb_set_logon_time(account, unix_time, PDB_CHANGED);
605         }
606
607         if (!nt_time_is_zero(&r->last_logoff)) {
608                 unix_time = nt_time_to_unix(r->last_logoff);
609                 stored_time = pdb_get_logoff_time(account);
610                 if (stored_time != unix_time)
611                         pdb_set_logoff_time(account, unix_time,PDB_CHANGED);
612         }
613
614         /* Logon Divs */
615         if (pdb_get_logon_divs(account) != r->logon_hours.units_per_week)
616                 pdb_set_logon_divs(account, r->logon_hours.units_per_week, PDB_CHANGED);
617
618 #if 0
619         /* no idea what to do with this one - gd */
620         /* Max Logon Hours */
621         if (delta->unknown1 != pdb_get_unknown_6(account)) {
622                 pdb_set_unknown_6(account, delta->unknown1, PDB_CHANGED);
623         }
624 #endif
625         /* Logon Hours Len */
626         if (r->logon_hours.units_per_week/8 != pdb_get_hours_len(account)) {
627                 pdb_set_hours_len(account, r->logon_hours.units_per_week/8, PDB_CHANGED);
628         }
629
630         /* Logon Hours */
631         if (r->logon_hours.bits) {
632                 char oldstr[44], newstr[44];
633                 pdb_sethexhours(oldstr, pdb_get_hours(account));
634                 pdb_sethexhours(newstr, r->logon_hours.bits);
635                 if (!strequal(oldstr, newstr))
636                         pdb_set_hours(account, r->logon_hours.bits, PDB_CHANGED);
637         }
638
639         if (pdb_get_bad_password_count(account) != r->bad_password_count)
640                 pdb_set_bad_password_count(account, r->bad_password_count, PDB_CHANGED);
641
642         if (pdb_get_logon_count(account) != r->logon_count)
643                 pdb_set_logon_count(account, r->logon_count, PDB_CHANGED);
644
645         if (!nt_time_is_zero(&r->last_password_change)) {
646                 unix_time = nt_time_to_unix(r->last_password_change);
647                 stored_time = pdb_get_pass_last_set_time(account);
648                 if (stored_time != unix_time)
649                         pdb_set_pass_last_set_time(account, unix_time, PDB_CHANGED);
650         } else {
651                 /* no last set time, make it now */
652                 pdb_set_pass_last_set_time(account, time(NULL), PDB_CHANGED);
653         }
654
655         if (!nt_time_is_zero(&r->acct_expiry)) {
656                 unix_time = nt_time_to_unix(r->acct_expiry);
657                 stored_time = pdb_get_kickoff_time(account);
658                 if (stored_time != unix_time)
659                         pdb_set_kickoff_time(account, unix_time, PDB_CHANGED);
660         }
661
662         /* Decode hashes from password hash
663            Note that win2000 may send us all zeros for the hashes if it doesn't
664            think this channel is secure enough - don't set the passwords at all
665            in that case
666         */
667         if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
668                 sam_pwd_hash(r->rid, r->ntpassword.hash, lm_passwd, 0);
669                 pdb_set_lanman_passwd(account, lm_passwd, PDB_CHANGED);
670         }
671
672         if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
673                 sam_pwd_hash(r->rid, r->lmpassword.hash, nt_passwd, 0);
674                 pdb_set_nt_passwd(account, nt_passwd, PDB_CHANGED);
675         }
676
677         /* TODO: account expiry time */
678
679         pdb_set_acct_ctrl(account, r->acct_flags, PDB_CHANGED);
680
681         pdb_set_domain(account, lp_workgroup(), PDB_CHANGED);
682
683         return NT_STATUS_OK;
684 }
685
686 static NTSTATUS fetch_account_info(uint32_t rid,
687                                    struct netr_DELTA_USER *r)
688 {
689
690         NTSTATUS nt_ret = NT_STATUS_UNSUCCESSFUL;
691         fstring account;
692         char *add_script = NULL;
693         struct samu *sam_account=NULL;
694         GROUP_MAP map;
695         struct group *grp;
696         DOM_SID user_sid;
697         DOM_SID group_sid;
698         struct passwd *passwd;
699         fstring sid_string;
700
701         fstrcpy(account, r->account_name.string);
702         d_printf("Creating account: %s\n", account);
703
704         if ( !(sam_account = samu_new( NULL )) ) {
705                 return NT_STATUS_NO_MEMORY;
706         }
707
708         if (!(passwd = Get_Pwnam_alloc(sam_account, account))) {
709                 /* Create appropriate user */
710                 if (r->acct_flags & ACB_NORMAL) {
711                         add_script = talloc_strdup(sam_account,
712                                         lp_adduser_script());
713                 } else if ( (r->acct_flags & ACB_WSTRUST) ||
714                             (r->acct_flags & ACB_SVRTRUST) ||
715                             (r->acct_flags & ACB_DOMTRUST) ) {
716                         add_script = talloc_strdup(sam_account,
717                                         lp_addmachine_script());
718                 } else {
719                         DEBUG(1, ("Unknown user type: %s\n",
720                                   pdb_encode_acct_ctrl(r->acct_flags, NEW_PW_FORMAT_SPACE_PADDED_LEN)));
721                         nt_ret = NT_STATUS_UNSUCCESSFUL;
722                         goto done;
723                 }
724                 if (!add_script) {
725                         nt_ret = NT_STATUS_NO_MEMORY;
726                         goto done;
727                 }
728                 if (*add_script) {
729                         int add_ret;
730                         add_script = talloc_all_string_sub(sam_account,
731                                         add_script,
732                                         "%u",
733                                         account);
734                         if (!add_script) {
735                                 nt_ret = NT_STATUS_NO_MEMORY;
736                                 goto done;
737                         }
738                         add_ret = smbrun(add_script,NULL);
739                         DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' "
740                                  "gave %d\n", add_script, add_ret));
741                         if (add_ret == 0) {
742                                 smb_nscd_flush_user_cache();
743                         }
744                 }
745
746                 /* try and find the possible unix account again */
747                 if ( !(passwd = Get_Pwnam_alloc(sam_account, account)) ) {
748                         d_fprintf(stderr, "Could not create posix account info for '%s'\n", account);
749                         nt_ret = NT_STATUS_NO_SUCH_USER;
750                         goto done;
751                 }
752         }
753
754         sid_copy(&user_sid, get_global_sam_sid());
755         sid_append_rid(&user_sid, r->rid);
756
757         DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n",
758                   sid_to_fstring(sid_string, &user_sid), account));
759         if (!pdb_getsampwsid(sam_account, &user_sid)) {
760                 sam_account_from_delta(sam_account, r);
761                 DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n",
762                           sid_to_fstring(sid_string, &user_sid),
763                           pdb_get_username(sam_account)));
764                 if (!NT_STATUS_IS_OK(pdb_add_sam_account(sam_account))) {
765                         DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
766                                   account));
767                         return NT_STATUS_ACCESS_DENIED;
768                 }
769         } else {
770                 sam_account_from_delta(sam_account, r);
771                 DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n",
772                           sid_to_fstring(sid_string, &user_sid),
773                           pdb_get_username(sam_account)));
774                 if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_account))) {
775                         DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
776                                   account));
777                         TALLOC_FREE(sam_account);
778                         return NT_STATUS_ACCESS_DENIED;
779                 }
780         }
781
782         if (pdb_get_group_sid(sam_account) == NULL) {
783                 return NT_STATUS_UNSUCCESSFUL;
784         }
785
786         group_sid = *pdb_get_group_sid(sam_account);
787
788         if (!pdb_getgrsid(&map, group_sid)) {
789                 DEBUG(0, ("Primary group of %s has no mapping!\n",
790                           pdb_get_username(sam_account)));
791         } else {
792                 if (map.gid != passwd->pw_gid) {
793                         if (!(grp = getgrgid(map.gid))) {
794                                 DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n",
795                                           (unsigned long)map.gid, pdb_get_username(sam_account), sid_string_tos(&group_sid)));
796                         } else {
797                                 smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account));
798                         }
799                 }
800         }
801
802         if ( !passwd ) {
803                 DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n",
804                         pdb_get_username(sam_account)));
805         }
806
807  done:
808         TALLOC_FREE(sam_account);
809         return nt_ret;
810 }
811
812 static NTSTATUS fetch_group_info(uint32_t rid,
813                                  struct netr_DELTA_GROUP *r)
814 {
815         fstring name;
816         fstring comment;
817         struct group *grp = NULL;
818         DOM_SID group_sid;
819         fstring sid_string;
820         GROUP_MAP map;
821         bool insert = true;
822
823         fstrcpy(name, r->group_name.string);
824         fstrcpy(comment, r->description.string);
825
826         /* add the group to the mapping table */
827         sid_copy(&group_sid, get_global_sam_sid());
828         sid_append_rid(&group_sid, rid);
829         sid_to_fstring(sid_string, &group_sid);
830
831         if (pdb_getgrsid(&map, group_sid)) {
832                 if ( map.gid != -1 )
833                         grp = getgrgid(map.gid);
834                 insert = false;
835         }
836
837         if (grp == NULL) {
838                 gid_t gid;
839
840                 /* No group found from mapping, find it from its name. */
841                 if ((grp = getgrnam(name)) == NULL) {
842
843                         /* No appropriate group found, create one */
844
845                         d_printf("Creating unix group: '%s'\n", name);
846
847                         if (smb_create_group(name, &gid) != 0)
848                                 return NT_STATUS_ACCESS_DENIED;
849
850                         if ((grp = getgrnam(name)) == NULL)
851                                 return NT_STATUS_ACCESS_DENIED;
852                 }
853         }
854
855         map.gid = grp->gr_gid;
856         map.sid = group_sid;
857         map.sid_name_use = SID_NAME_DOM_GRP;
858         fstrcpy(map.nt_name, name);
859         if (r->description.string) {
860                 fstrcpy(map.comment, comment);
861         } else {
862                 fstrcpy(map.comment, "");
863         }
864
865         if (insert)
866                 pdb_add_group_mapping_entry(&map);
867         else
868                 pdb_update_group_mapping_entry(&map);
869
870         return NT_STATUS_OK;
871 }
872
873 static NTSTATUS fetch_group_mem_info(uint32_t rid,
874                                      struct netr_DELTA_GROUP_MEMBER *r)
875 {
876         int i;
877         TALLOC_CTX *t = NULL;
878         char **nt_members = NULL;
879         char **unix_members;
880         DOM_SID group_sid;
881         GROUP_MAP map;
882         struct group *grp;
883
884         if (r->num_rids == 0) {
885                 return NT_STATUS_OK;
886         }
887
888         sid_copy(&group_sid, get_global_sam_sid());
889         sid_append_rid(&group_sid, rid);
890
891         if (!get_domain_group_from_sid(group_sid, &map)) {
892                 DEBUG(0, ("Could not find global group %d\n", rid));
893                 return NT_STATUS_NO_SUCH_GROUP;
894         }
895
896         if (!(grp = getgrgid(map.gid))) {
897                 DEBUG(0, ("Could not find unix group %lu\n", (unsigned long)map.gid));
898                 return NT_STATUS_NO_SUCH_GROUP;
899         }
900
901         d_printf("Group members of %s: ", grp->gr_name);
902
903         if (!(t = talloc_init("fetch_group_mem_info"))) {
904                 DEBUG(0, ("could not talloc_init\n"));
905                 return NT_STATUS_NO_MEMORY;
906         }
907
908         if (r->num_rids) {
909                 if ((nt_members = TALLOC_ZERO_ARRAY(t, char *, r->num_rids)) == NULL) {
910                         DEBUG(0, ("talloc failed\n"));
911                         talloc_free(t);
912                         return NT_STATUS_NO_MEMORY;
913                 }
914         } else {
915                 nt_members = NULL;
916         }
917
918         for (i=0; i < r->num_rids; i++) {
919                 struct samu *member = NULL;
920                 DOM_SID member_sid;
921
922                 if ( !(member = samu_new(t)) ) {
923                         talloc_destroy(t);
924                         return NT_STATUS_NO_MEMORY;
925                 }
926
927                 sid_copy(&member_sid, get_global_sam_sid());
928                 sid_append_rid(&member_sid, r->rids[i]);
929
930                 if (!pdb_getsampwsid(member, &member_sid)) {
931                         DEBUG(1, ("Found bogus group member: %d (member_sid=%s group=%s)\n",
932                                   r->rids[i], sid_string_tos(&member_sid), grp->gr_name));
933                         TALLOC_FREE(member);
934                         continue;
935                 }
936
937                 if (pdb_get_group_rid(member) == rid) {
938                         d_printf("%s(primary),", pdb_get_username(member));
939                         TALLOC_FREE(member);
940                         continue;
941                 }
942
943                 d_printf("%s,", pdb_get_username(member));
944                 nt_members[i] = talloc_strdup(t, pdb_get_username(member));
945                 TALLOC_FREE(member);
946         }
947
948         d_printf("\n");
949
950         unix_members = grp->gr_mem;
951
952         while (*unix_members) {
953                 bool is_nt_member = false;
954                 for (i=0; i < r->num_rids; i++) {
955                         if (nt_members[i] == NULL) {
956                                 /* This was a primary group */
957                                 continue;
958                         }
959
960                         if (strcmp(*unix_members, nt_members[i]) == 0) {
961                                 is_nt_member = true;
962                                 break;
963                         }
964                 }
965                 if (!is_nt_member) {
966                         /* We look at a unix group member that is not
967                            an nt group member. So, remove it. NT is
968                            boss here. */
969                         smb_delete_user_group(grp->gr_name, *unix_members);
970                 }
971                 unix_members += 1;
972         }
973
974         for (i=0; i < r->num_rids; i++) {
975                 bool is_unix_member = false;
976
977                 if (nt_members[i] == NULL) {
978                         /* This was the primary group */
979                         continue;
980                 }
981
982                 unix_members = grp->gr_mem;
983
984                 while (*unix_members) {
985                         if (strcmp(*unix_members, nt_members[i]) == 0) {
986                                 is_unix_member = true;
987                                 break;
988                         }
989                         unix_members += 1;
990                 }
991
992                 if (!is_unix_member) {
993                         /* We look at a nt group member that is not a
994                            unix group member currently. So, add the nt
995                            group member. */
996                         smb_add_user_group(grp->gr_name, nt_members[i]);
997                 }
998         }
999
1000         talloc_destroy(t);
1001         return NT_STATUS_OK;
1002 }
1003
1004 static NTSTATUS fetch_alias_info(uint32_t rid,
1005                                  struct netr_DELTA_ALIAS *r,
1006                                  const DOM_SID *dom_sid)
1007 {
1008         fstring name;
1009         fstring comment;
1010         struct group *grp = NULL;
1011         DOM_SID alias_sid;
1012         fstring sid_string;
1013         GROUP_MAP map;
1014         bool insert = true;
1015
1016         fstrcpy(name, r->alias_name.string);
1017         fstrcpy(comment, r->description.string);
1018
1019         /* Find out whether the group is already mapped */
1020         sid_copy(&alias_sid, dom_sid);
1021         sid_append_rid(&alias_sid, rid);
1022         sid_to_fstring(sid_string, &alias_sid);
1023
1024         if (pdb_getgrsid(&map, alias_sid)) {
1025                 grp = getgrgid(map.gid);
1026                 insert = false;
1027         }
1028
1029         if (grp == NULL) {
1030                 gid_t gid;
1031
1032                 /* No group found from mapping, find it from its name. */
1033                 if ((grp = getgrnam(name)) == NULL) {
1034                         /* No appropriate group found, create one */
1035                         d_printf("Creating unix group: '%s'\n", name);
1036                         if (smb_create_group(name, &gid) != 0)
1037                                 return NT_STATUS_ACCESS_DENIED;
1038                         if ((grp = getgrgid(gid)) == NULL)
1039                                 return NT_STATUS_ACCESS_DENIED;
1040                 }
1041         }
1042
1043         map.gid = grp->gr_gid;
1044         map.sid = alias_sid;
1045
1046         if (sid_equal(dom_sid, &global_sid_Builtin))
1047                 map.sid_name_use = SID_NAME_WKN_GRP;
1048         else
1049                 map.sid_name_use = SID_NAME_ALIAS;
1050
1051         fstrcpy(map.nt_name, name);
1052         fstrcpy(map.comment, comment);
1053
1054         if (insert)
1055                 pdb_add_group_mapping_entry(&map);
1056         else
1057                 pdb_update_group_mapping_entry(&map);
1058
1059         return NT_STATUS_OK;
1060 }
1061
1062 static NTSTATUS fetch_alias_mem(uint32_t rid,
1063                                 struct netr_DELTA_ALIAS_MEMBER *r,
1064                                 const DOM_SID *dom_sid)
1065 {
1066         return NT_STATUS_OK;
1067 }
1068
1069 static NTSTATUS fetch_domain_info(uint32_t rid,
1070                                   struct netr_DELTA_DOMAIN *r)
1071 {
1072         time_t u_max_age, u_min_age, u_logout;
1073         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
1074         const char *domname;
1075         struct netr_AcctLockStr *lockstr = NULL;
1076         NTSTATUS status;
1077         TALLOC_CTX *mem_ctx = talloc_tos();
1078
1079         status = pull_netr_AcctLockStr(mem_ctx, &r->account_lockout,
1080                                        &lockstr);
1081         if (!NT_STATUS_IS_OK(status)) {
1082                 d_printf("failed to pull account lockout string: %s\n",
1083                         nt_errstr(status));
1084         }
1085
1086         u_max_age = uint64s_nt_time_to_unix_abs((uint64 *)&r->max_password_age);
1087         u_min_age = uint64s_nt_time_to_unix_abs((uint64 *)&r->min_password_age);
1088         u_logout = uint64s_nt_time_to_unix_abs((uint64 *)&r->force_logoff_time);
1089
1090         domname = r->domain_name.string;
1091         if (!domname) {
1092                 return NT_STATUS_NO_MEMORY;
1093         }
1094
1095         /* we don't handle BUILTIN account policies */
1096         if (!strequal(domname, get_global_sam_name())) {
1097                 printf("skipping SAM_DOMAIN_INFO delta for '%s' (is not my domain)\n", domname);
1098                 return NT_STATUS_OK;
1099         }
1100
1101
1102         if (!pdb_set_account_policy(AP_PASSWORD_HISTORY,
1103                                     r->password_history_length))
1104                 return nt_status;
1105
1106         if (!pdb_set_account_policy(AP_MIN_PASSWORD_LEN,
1107                                     r->min_password_length))
1108                 return nt_status;
1109
1110         if (!pdb_set_account_policy(AP_MAX_PASSWORD_AGE, (uint32)u_max_age))
1111                 return nt_status;
1112
1113         if (!pdb_set_account_policy(AP_MIN_PASSWORD_AGE, (uint32)u_min_age))
1114                 return nt_status;
1115
1116         if (!pdb_set_account_policy(AP_TIME_TO_LOGOUT, (uint32)u_logout))
1117                 return nt_status;
1118
1119         if (lockstr) {
1120                 time_t u_lockoutreset, u_lockouttime;
1121
1122                 u_lockoutreset = uint64s_nt_time_to_unix_abs(&lockstr->reset_count);
1123                 u_lockouttime = uint64s_nt_time_to_unix_abs((uint64_t *)&lockstr->lockout_duration);
1124
1125                 if (!pdb_set_account_policy(AP_BAD_ATTEMPT_LOCKOUT,
1126                                             lockstr->bad_attempt_lockout))
1127                         return nt_status;
1128
1129                 if (!pdb_set_account_policy(AP_RESET_COUNT_TIME, (uint32_t)u_lockoutreset/60))
1130                         return nt_status;
1131
1132                 if (u_lockouttime != -1)
1133                         u_lockouttime /= 60;
1134
1135                 if (!pdb_set_account_policy(AP_LOCK_ACCOUNT_DURATION, (uint32_t)u_lockouttime))
1136                         return nt_status;
1137         }
1138
1139         if (!pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS,
1140                                     r->logon_to_chgpass))
1141                 return nt_status;
1142
1143         return NT_STATUS_OK;
1144 }
1145
1146 static NTSTATUS fetch_sam_entry(TALLOC_CTX *mem_ctx,
1147                                 enum netr_SamDatabaseID database_id,
1148                                 struct netr_DELTA_ENUM *r,
1149                                 struct samsync_context *ctx)
1150 {
1151         switch(r->delta_type) {
1152         case NETR_DELTA_USER:
1153                 fetch_account_info(r->delta_id_union.rid,
1154                                    r->delta_union.user);
1155                 break;
1156         case NETR_DELTA_GROUP:
1157                 fetch_group_info(r->delta_id_union.rid,
1158                                  r->delta_union.group);
1159                 break;
1160         case NETR_DELTA_GROUP_MEMBER:
1161                 fetch_group_mem_info(r->delta_id_union.rid,
1162                                      r->delta_union.group_member);
1163                 break;
1164         case NETR_DELTA_ALIAS:
1165                 fetch_alias_info(r->delta_id_union.rid,
1166                                  r->delta_union.alias,
1167                                  ctx->domain_sid);
1168                 break;
1169         case NETR_DELTA_ALIAS_MEMBER:
1170                 fetch_alias_mem(r->delta_id_union.rid,
1171                                 r->delta_union.alias_member,
1172                                 ctx->domain_sid);
1173                 break;
1174         case NETR_DELTA_DOMAIN:
1175                 fetch_domain_info(r->delta_id_union.rid,
1176                                   r->delta_union.domain);
1177                 break;
1178         /* The following types are recognised but not handled */
1179         case NETR_DELTA_RENAME_GROUP:
1180                 d_printf("NETR_DELTA_RENAME_GROUP not handled\n");
1181                 break;
1182         case NETR_DELTA_RENAME_USER:
1183                 d_printf("NETR_DELTA_RENAME_USER not handled\n");
1184                 break;
1185         case NETR_DELTA_RENAME_ALIAS:
1186                 d_printf("NETR_DELTA_RENAME_ALIAS not handled\n");
1187                 break;
1188         case NETR_DELTA_POLICY:
1189                 d_printf("NETR_DELTA_POLICY not handled\n");
1190                 break;
1191         case NETR_DELTA_TRUSTED_DOMAIN:
1192                 d_printf("NETR_DELTA_TRUSTED_DOMAIN not handled\n");
1193                 break;
1194         case NETR_DELTA_ACCOUNT:
1195                 d_printf("NETR_DELTA_ACCOUNT not handled\n");
1196                 break;
1197         case NETR_DELTA_SECRET:
1198                 d_printf("NETR_DELTA_SECRET not handled\n");
1199                 break;
1200         case NETR_DELTA_DELETE_GROUP:
1201                 d_printf("NETR_DELTA_DELETE_GROUP not handled\n");
1202                 break;
1203         case NETR_DELTA_DELETE_USER:
1204                 d_printf("NETR_DELTA_DELETE_USER not handled\n");
1205                 break;
1206         case NETR_DELTA_MODIFY_COUNT:
1207                 d_printf("NETR_DELTA_MODIFY_COUNT not handled\n");
1208                 break;
1209         case NETR_DELTA_DELETE_ALIAS:
1210                 d_printf("NETR_DELTA_DELETE_ALIAS not handled\n");
1211                 break;
1212         case NETR_DELTA_DELETE_TRUST:
1213                 d_printf("NETR_DELTA_DELETE_TRUST not handled\n");
1214                 break;
1215         case NETR_DELTA_DELETE_ACCOUNT:
1216                 d_printf("NETR_DELTA_DELETE_ACCOUNT not handled\n");
1217                 break;
1218         case NETR_DELTA_DELETE_SECRET:
1219                 d_printf("NETR_DELTA_DELETE_SECRET not handled\n");
1220                 break;
1221         case NETR_DELTA_DELETE_GROUP2:
1222                 d_printf("NETR_DELTA_DELETE_GROUP2 not handled\n");
1223                 break;
1224         case NETR_DELTA_DELETE_USER2:
1225                 d_printf("NETR_DELTA_DELETE_USER2 not handled\n");
1226                 break;
1227         default:
1228                 d_printf("Unknown delta record type %d\n", r->delta_type);
1229                 break;
1230         }
1231
1232         return NT_STATUS_OK;
1233 }
1234
1235 static NTSTATUS fetch_sam_entries(TALLOC_CTX *mem_ctx,
1236                                   enum netr_SamDatabaseID database_id,
1237                                   struct netr_DELTA_ENUM_ARRAY *r,
1238                                   NTSTATUS status,
1239                                   struct samsync_context *ctx)
1240 {
1241         int i;
1242
1243         for (i = 0; i < r->num_deltas; i++) {
1244                 fetch_sam_entry(mem_ctx, database_id, &r->delta_enum[i], ctx);
1245         }
1246
1247         return NT_STATUS_OK;
1248 }
1249
1250 /****************************************************************
1251 ****************************************************************/
1252
1253 static NTSTATUS populate_ldap_for_ldif(const char *sid,
1254                                        const char *suffix,
1255                                        const char *builtin_sid,
1256                                        FILE *add_fd)
1257 {
1258         const char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix;
1259         char *user_attr=NULL, *group_attr=NULL;
1260         char *suffix_attr;
1261         int len;
1262
1263         /* Get the suffix attribute */
1264         suffix_attr = sstring_sub(suffix, '=', ',');
1265         if (suffix_attr == NULL) {
1266                 len = strlen(suffix);
1267                 suffix_attr = (char*)SMB_MALLOC(len+1);
1268                 memcpy(suffix_attr, suffix, len);
1269                 suffix_attr[len] = '\0';
1270         }
1271
1272         /* Write the base */
1273         fprintf(add_fd, "# %s\n", suffix);
1274         fprintf(add_fd, "dn: %s\n", suffix);
1275         fprintf(add_fd, "objectClass: dcObject\n");
1276         fprintf(add_fd, "objectClass: organization\n");
1277         fprintf(add_fd, "o: %s\n", suffix_attr);
1278         fprintf(add_fd, "dc: %s\n", suffix_attr);
1279         fprintf(add_fd, "\n");
1280         fflush(add_fd);
1281
1282         user_suffix = lp_ldap_user_suffix();
1283         if (user_suffix == NULL) {
1284                 SAFE_FREE(suffix_attr);
1285                 return NT_STATUS_NO_MEMORY;
1286         }
1287         /* If it exists and is distinct from other containers,
1288            Write the Users entity */
1289         if (*user_suffix && strcmp(user_suffix, suffix)) {
1290                 user_attr = sstring_sub(lp_ldap_user_suffix(), '=', ',');
1291                 fprintf(add_fd, "# %s\n", user_suffix);
1292                 fprintf(add_fd, "dn: %s\n", user_suffix);
1293                 fprintf(add_fd, "objectClass: organizationalUnit\n");
1294                 fprintf(add_fd, "ou: %s\n", user_attr);
1295                 fprintf(add_fd, "\n");
1296                 fflush(add_fd);
1297         }
1298
1299
1300         group_suffix = lp_ldap_group_suffix();
1301         if (group_suffix == NULL) {
1302                 SAFE_FREE(suffix_attr);
1303                 SAFE_FREE(user_attr);
1304                 return NT_STATUS_NO_MEMORY;
1305         }
1306         /* If it exists and is distinct from other containers,
1307            Write the Groups entity */
1308         if (*group_suffix && strcmp(group_suffix, suffix)) {
1309                 group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
1310                 fprintf(add_fd, "# %s\n", group_suffix);
1311                 fprintf(add_fd, "dn: %s\n", group_suffix);
1312                 fprintf(add_fd, "objectClass: organizationalUnit\n");
1313                 fprintf(add_fd, "ou: %s\n", group_attr);
1314                 fprintf(add_fd, "\n");
1315                 fflush(add_fd);
1316         }
1317
1318         /* If it exists and is distinct from other containers,
1319            Write the Computers entity */
1320         machine_suffix = lp_ldap_machine_suffix();
1321         if (machine_suffix == NULL) {
1322                 SAFE_FREE(suffix_attr);
1323                 SAFE_FREE(user_attr);
1324                 SAFE_FREE(group_attr);
1325                 return NT_STATUS_NO_MEMORY;
1326         }
1327         if (*machine_suffix && strcmp(machine_suffix, user_suffix) &&
1328             strcmp(machine_suffix, suffix)) {
1329                 char *machine_ou = NULL;
1330                 fprintf(add_fd, "# %s\n", machine_suffix);
1331                 fprintf(add_fd, "dn: %s\n", machine_suffix);
1332                 fprintf(add_fd, "objectClass: organizationalUnit\n");
1333                 /* this isn't totally correct as it assumes that
1334                    there _must_ be an ou. just fixing memleak now. jmcd */
1335                 machine_ou = sstring_sub(lp_ldap_machine_suffix(), '=', ',');
1336                 fprintf(add_fd, "ou: %s\n", machine_ou);
1337                 SAFE_FREE(machine_ou);
1338                 fprintf(add_fd, "\n");
1339                 fflush(add_fd);
1340         }
1341
1342         /* If it exists and is distinct from other containers,
1343            Write the IdMap entity */
1344         idmap_suffix = lp_ldap_idmap_suffix();
1345         if (idmap_suffix == NULL) {
1346                 SAFE_FREE(suffix_attr);
1347                 SAFE_FREE(user_attr);
1348                 SAFE_FREE(group_attr);
1349                 return NT_STATUS_NO_MEMORY;
1350         }
1351         if (*idmap_suffix &&
1352             strcmp(idmap_suffix, user_suffix) &&
1353             strcmp(idmap_suffix, suffix)) {
1354                 char *s;
1355                 fprintf(add_fd, "# %s\n", idmap_suffix);
1356                 fprintf(add_fd, "dn: %s\n", idmap_suffix);
1357                 fprintf(add_fd, "ObjectClass: organizationalUnit\n");
1358                 s = sstring_sub(lp_ldap_idmap_suffix(), '=', ',');
1359                 fprintf(add_fd, "ou: %s\n", s);
1360                 SAFE_FREE(s);
1361                 fprintf(add_fd, "\n");
1362                 fflush(add_fd);
1363         }
1364
1365         /* Write the domain entity */
1366         fprintf(add_fd, "# %s, %s\n", lp_workgroup(), suffix);
1367         fprintf(add_fd, "dn: sambaDomainName=%s,%s\n", lp_workgroup(),
1368                 suffix);
1369         fprintf(add_fd, "objectClass: sambaDomain\n");
1370         fprintf(add_fd, "objectClass: sambaUnixIdPool\n");
1371         fprintf(add_fd, "sambaDomainName: %s\n", lp_workgroup());
1372         fprintf(add_fd, "sambaSID: %s\n", sid);
1373         fprintf(add_fd, "uidNumber: %d\n", ++ldif_uid);
1374         fprintf(add_fd, "gidNumber: %d\n", ++ldif_gid);
1375         fprintf(add_fd, "\n");
1376         fflush(add_fd);
1377
1378         /* Write the Domain Admins entity */
1379         fprintf(add_fd, "# Domain Admins, %s, %s\n", group_attr,
1380                 suffix);
1381         fprintf(add_fd, "dn: cn=Domain Admins,ou=%s,%s\n", group_attr,
1382                 suffix);
1383         fprintf(add_fd, "objectClass: posixGroup\n");
1384         fprintf(add_fd, "objectClass: sambaGroupMapping\n");
1385         fprintf(add_fd, "cn: Domain Admins\n");
1386         fprintf(add_fd, "memberUid: Administrator\n");
1387         fprintf(add_fd, "description: Netbios Domain Administrators\n");
1388         fprintf(add_fd, "gidNumber: 512\n");
1389         fprintf(add_fd, "sambaSID: %s-512\n", sid);
1390         fprintf(add_fd, "sambaGroupType: 2\n");
1391         fprintf(add_fd, "displayName: Domain Admins\n");
1392         fprintf(add_fd, "\n");
1393         fflush(add_fd);
1394
1395         /* Write the Domain Users entity */
1396         fprintf(add_fd, "# Domain Users, %s, %s\n", group_attr,
1397                 suffix);
1398         fprintf(add_fd, "dn: cn=Domain Users,ou=%s,%s\n", group_attr,
1399                 suffix);
1400         fprintf(add_fd, "objectClass: posixGroup\n");
1401         fprintf(add_fd, "objectClass: sambaGroupMapping\n");
1402         fprintf(add_fd, "cn: Domain Users\n");
1403         fprintf(add_fd, "description: Netbios Domain Users\n");
1404         fprintf(add_fd, "gidNumber: 513\n");
1405         fprintf(add_fd, "sambaSID: %s-513\n", sid);
1406         fprintf(add_fd, "sambaGroupType: 2\n");
1407         fprintf(add_fd, "displayName: Domain Users\n");
1408         fprintf(add_fd, "\n");
1409         fflush(add_fd);
1410
1411         /* Write the Domain Guests entity */
1412         fprintf(add_fd, "# Domain Guests, %s, %s\n", group_attr,
1413                 suffix);
1414         fprintf(add_fd, "dn: cn=Domain Guests,ou=%s,%s\n", group_attr,
1415                 suffix);
1416         fprintf(add_fd, "objectClass: posixGroup\n");
1417         fprintf(add_fd, "objectClass: sambaGroupMapping\n");
1418         fprintf(add_fd, "cn: Domain Guests\n");
1419         fprintf(add_fd, "description: Netbios Domain Guests\n");
1420         fprintf(add_fd, "gidNumber: 514\n");
1421         fprintf(add_fd, "sambaSID: %s-514\n", sid);
1422         fprintf(add_fd, "sambaGroupType: 2\n");
1423         fprintf(add_fd, "displayName: Domain Guests\n");
1424         fprintf(add_fd, "\n");
1425         fflush(add_fd);
1426
1427         /* Write the Domain Computers entity */
1428         fprintf(add_fd, "# Domain Computers, %s, %s\n", group_attr,
1429                 suffix);
1430         fprintf(add_fd, "dn: cn=Domain Computers,ou=%s,%s\n",
1431                 group_attr, suffix);
1432         fprintf(add_fd, "objectClass: posixGroup\n");
1433         fprintf(add_fd, "objectClass: sambaGroupMapping\n");
1434         fprintf(add_fd, "gidNumber: 515\n");
1435         fprintf(add_fd, "cn: Domain Computers\n");
1436         fprintf(add_fd, "description: Netbios Domain Computers accounts\n");
1437         fprintf(add_fd, "sambaSID: %s-515\n", sid);
1438         fprintf(add_fd, "sambaGroupType: 2\n");
1439         fprintf(add_fd, "displayName: Domain Computers\n");
1440         fprintf(add_fd, "\n");
1441         fflush(add_fd);
1442
1443         /* Write the Admininistrators Groups entity */
1444         fprintf(add_fd, "# Administrators, %s, %s\n", group_attr,
1445                 suffix);
1446         fprintf(add_fd, "dn: cn=Administrators,ou=%s,%s\n", group_attr,
1447                 suffix);
1448         fprintf(add_fd, "objectClass: posixGroup\n");
1449         fprintf(add_fd, "objectClass: sambaGroupMapping\n");
1450         fprintf(add_fd, "gidNumber: 544\n");
1451         fprintf(add_fd, "cn: Administrators\n");
1452         fprintf(add_fd, "description: Netbios Domain Members can fully administer the computer/sambaDomainName\n");
1453         fprintf(add_fd, "sambaSID: %s-544\n", builtin_sid);
1454         fprintf(add_fd, "sambaGroupType: 5\n");
1455         fprintf(add_fd, "displayName: Administrators\n");
1456         fprintf(add_fd, "\n");
1457
1458         /* Write the Print Operator entity */
1459         fprintf(add_fd, "# Print Operators, %s, %s\n", group_attr,
1460                 suffix);
1461         fprintf(add_fd, "dn: cn=Print Operators,ou=%s,%s\n",
1462                 group_attr, suffix);
1463         fprintf(add_fd, "objectClass: posixGroup\n");
1464         fprintf(add_fd, "objectClass: sambaGroupMapping\n");
1465         fprintf(add_fd, "gidNumber: 550\n");
1466         fprintf(add_fd, "cn: Print Operators\n");
1467         fprintf(add_fd, "description: Netbios Domain Print Operators\n");
1468         fprintf(add_fd, "sambaSID: %s-550\n", builtin_sid);
1469         fprintf(add_fd, "sambaGroupType: 5\n");
1470         fprintf(add_fd, "displayName: Print Operators\n");
1471         fprintf(add_fd, "\n");
1472         fflush(add_fd);
1473
1474         /* Write the Backup Operators entity */
1475         fprintf(add_fd, "# Backup Operators, %s, %s\n", group_attr,
1476                 suffix);
1477         fprintf(add_fd, "dn: cn=Backup Operators,ou=%s,%s\n",
1478                 group_attr, suffix);
1479         fprintf(add_fd, "objectClass: posixGroup\n");
1480         fprintf(add_fd, "objectClass: sambaGroupMapping\n");
1481         fprintf(add_fd, "gidNumber: 551\n");
1482         fprintf(add_fd, "cn: Backup Operators\n");
1483         fprintf(add_fd, "description: Netbios Domain Members can bypass file security to back up files\n");
1484         fprintf(add_fd, "sambaSID: %s-551\n", builtin_sid);
1485         fprintf(add_fd, "sambaGroupType: 5\n");
1486         fprintf(add_fd, "displayName: Backup Operators\n");
1487         fprintf(add_fd, "\n");
1488         fflush(add_fd);
1489
1490         /* Write the Replicators entity */
1491         fprintf(add_fd, "# Replicators, %s, %s\n", group_attr, suffix);
1492         fprintf(add_fd, "dn: cn=Replicators,ou=%s,%s\n", group_attr,
1493                 suffix);
1494         fprintf(add_fd, "objectClass: posixGroup\n");
1495         fprintf(add_fd, "objectClass: sambaGroupMapping\n");
1496         fprintf(add_fd, "gidNumber: 552\n");
1497         fprintf(add_fd, "cn: Replicators\n");
1498         fprintf(add_fd, "description: Netbios Domain Supports file replication in a sambaDomainName\n");
1499         fprintf(add_fd, "sambaSID: %s-552\n", builtin_sid);
1500         fprintf(add_fd, "sambaGroupType: 5\n");
1501         fprintf(add_fd, "displayName: Replicators\n");
1502         fprintf(add_fd, "\n");
1503         fflush(add_fd);
1504
1505         /* Deallocate memory, and return */
1506         SAFE_FREE(suffix_attr);
1507         SAFE_FREE(user_attr);
1508         SAFE_FREE(group_attr);
1509         return NT_STATUS_OK;
1510 }
1511
1512 /****************************************************************
1513 ****************************************************************/
1514
1515 static NTSTATUS map_populate_groups(TALLOC_CTX *mem_ctx,
1516                                     GROUPMAP *groupmap,
1517                                     ACCOUNTMAP *accountmap,
1518                                     const char *sid,
1519                                     const char *suffix,
1520                                     const char *builtin_sid)
1521 {
1522         char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
1523
1524         /* Map the groups created by populate_ldap_for_ldif */
1525         groupmap[0].rid         = 512;
1526         groupmap[0].gidNumber   = 512;
1527         groupmap[0].sambaSID    = talloc_asprintf(mem_ctx, "%s-512", sid);
1528         groupmap[0].group_dn    = talloc_asprintf(mem_ctx,
1529                 "cn=Domain Admins,ou=%s,%s", group_attr, suffix);
1530         NT_STATUS_HAVE_NO_MEMORY(groupmap[0].sambaSID);
1531         NT_STATUS_HAVE_NO_MEMORY(groupmap[0].group_dn);
1532
1533         accountmap[0].rid       = 512;
1534         accountmap[0].cn        = talloc_strdup(mem_ctx, "Domain Admins");
1535         NT_STATUS_HAVE_NO_MEMORY(accountmap[0].cn);
1536
1537         groupmap[1].rid         = 513;
1538         groupmap[1].gidNumber   = 513;
1539         groupmap[1].sambaSID    = talloc_asprintf(mem_ctx, "%s-513", sid);
1540         groupmap[1].group_dn    = talloc_asprintf(mem_ctx,
1541                 "cn=Domain Users,ou=%s,%s", group_attr, suffix);
1542         NT_STATUS_HAVE_NO_MEMORY(groupmap[1].sambaSID);
1543         NT_STATUS_HAVE_NO_MEMORY(groupmap[1].group_dn);
1544
1545         accountmap[1].rid       = 513;
1546         accountmap[1].cn        = talloc_strdup(mem_ctx, "Domain Users");
1547         NT_STATUS_HAVE_NO_MEMORY(accountmap[1].cn);
1548
1549         groupmap[2].rid         = 514;
1550         groupmap[2].gidNumber   = 514;
1551         groupmap[2].sambaSID    = talloc_asprintf(mem_ctx, "%s-514", sid);
1552         groupmap[2].group_dn    = talloc_asprintf(mem_ctx,
1553                 "cn=Domain Guests,ou=%s,%s", group_attr, suffix);
1554         NT_STATUS_HAVE_NO_MEMORY(groupmap[2].sambaSID);
1555         NT_STATUS_HAVE_NO_MEMORY(groupmap[2].group_dn);
1556
1557         accountmap[2].rid       = 514;
1558         accountmap[2].cn        = talloc_strdup(mem_ctx, "Domain Guests");
1559         NT_STATUS_HAVE_NO_MEMORY(accountmap[2].cn);
1560
1561         groupmap[3].rid         = 515;
1562         groupmap[3].gidNumber   = 515;
1563         groupmap[3].sambaSID    = talloc_asprintf(mem_ctx, "%s-515", sid);
1564         groupmap[3].group_dn    = talloc_asprintf(mem_ctx,
1565                 "cn=Domain Computers,ou=%s,%s", group_attr, suffix);
1566         NT_STATUS_HAVE_NO_MEMORY(groupmap[3].sambaSID);
1567         NT_STATUS_HAVE_NO_MEMORY(groupmap[3].group_dn);
1568
1569         accountmap[3].rid       = 515;
1570         accountmap[3].cn        = talloc_strdup(mem_ctx, "Domain Computers");
1571         NT_STATUS_HAVE_NO_MEMORY(accountmap[3].cn);
1572
1573         groupmap[4].rid         = 544;
1574         groupmap[4].gidNumber   = 544;
1575         groupmap[4].sambaSID    = talloc_asprintf(mem_ctx, "%s-544", builtin_sid);
1576         groupmap[4].group_dn    = talloc_asprintf(mem_ctx,
1577                 "cn=Administrators,ou=%s,%s", group_attr, suffix);
1578         NT_STATUS_HAVE_NO_MEMORY(groupmap[4].sambaSID);
1579         NT_STATUS_HAVE_NO_MEMORY(groupmap[4].group_dn);
1580
1581         accountmap[4].rid       = 515;
1582         accountmap[4].cn        = talloc_strdup(mem_ctx, "Administrators");
1583         NT_STATUS_HAVE_NO_MEMORY(accountmap[4].cn);
1584
1585         groupmap[5].rid         = 550;
1586         groupmap[5].gidNumber   = 550;
1587         groupmap[5].sambaSID    = talloc_asprintf(mem_ctx, "%s-550", builtin_sid);
1588         groupmap[5].group_dn    = talloc_asprintf(mem_ctx,
1589                 "cn=Print Operators,ou=%s,%s", group_attr, suffix);
1590         NT_STATUS_HAVE_NO_MEMORY(groupmap[5].sambaSID);
1591         NT_STATUS_HAVE_NO_MEMORY(groupmap[5].group_dn);
1592
1593         accountmap[5].rid       = 550;
1594         accountmap[5].cn        = talloc_strdup(mem_ctx, "Print Operators");
1595         NT_STATUS_HAVE_NO_MEMORY(accountmap[5].cn);
1596
1597         groupmap[6].rid         = 551;
1598         groupmap[6].gidNumber   = 551;
1599         groupmap[6].sambaSID    = talloc_asprintf(mem_ctx, "%s-551", builtin_sid);
1600         groupmap[6].group_dn    = talloc_asprintf(mem_ctx,
1601                 "cn=Backup Operators,ou=%s,%s", group_attr, suffix);
1602         NT_STATUS_HAVE_NO_MEMORY(groupmap[6].sambaSID);
1603         NT_STATUS_HAVE_NO_MEMORY(groupmap[6].group_dn);
1604
1605         accountmap[6].rid       = 551;
1606         accountmap[6].cn        = talloc_strdup(mem_ctx, "Backup Operators");
1607         NT_STATUS_HAVE_NO_MEMORY(accountmap[6].cn);
1608
1609         groupmap[7].rid         = 552;
1610         groupmap[7].gidNumber   = 552;
1611         groupmap[7].sambaSID    = talloc_asprintf(mem_ctx, "%s-552", builtin_sid);
1612         groupmap[7].group_dn    = talloc_asprintf(mem_ctx,
1613                 "cn=Replicators,ou=%s,%s", group_attr, suffix);
1614         NT_STATUS_HAVE_NO_MEMORY(groupmap[7].sambaSID);
1615         NT_STATUS_HAVE_NO_MEMORY(groupmap[7].group_dn);
1616
1617         accountmap[7].rid       = 551;
1618         accountmap[7].cn        = talloc_strdup(mem_ctx, "Replicators");
1619         NT_STATUS_HAVE_NO_MEMORY(accountmap[7].cn);
1620
1621         SAFE_FREE(group_attr);
1622
1623         return NT_STATUS_OK;
1624 }
1625
1626 /*
1627  * This is a crap routine, but I think it's the quickest way to solve the
1628  * UTF8->base64 problem.
1629  */
1630
1631 static int fprintf_attr(FILE *add_fd, const char *attr_name,
1632                         const char *fmt, ...)
1633 {
1634         va_list ap;
1635         char *value, *p, *base64;
1636         DATA_BLOB base64_blob;
1637         bool do_base64 = false;
1638         int res;
1639
1640         va_start(ap, fmt);
1641         value = talloc_vasprintf(NULL, fmt, ap);
1642         va_end(ap);
1643
1644         SMB_ASSERT(value != NULL);
1645
1646         for (p=value; *p; p++) {
1647                 if (*p & 0x80) {
1648                         do_base64 = true;
1649                         break;
1650                 }
1651         }
1652
1653         if (!do_base64) {
1654                 bool only_whitespace = true;
1655                 for (p=value; *p; p++) {
1656                         /*
1657                          * I know that this not multibyte safe, but we break
1658                          * on the first non-whitespace character anyway.
1659                          */
1660                         if (!isspace(*p)) {
1661                                 only_whitespace = false;
1662                                 break;
1663                         }
1664                 }
1665                 if (only_whitespace) {
1666                         do_base64 = true;
1667                 }
1668         }
1669
1670         if (!do_base64) {
1671                 res = fprintf(add_fd, "%s: %s\n", attr_name, value);
1672                 TALLOC_FREE(value);
1673                 return res;
1674         }
1675
1676         base64_blob.data = (unsigned char *)value;
1677         base64_blob.length = strlen(value);
1678
1679         base64 = base64_encode_data_blob(value, base64_blob);
1680         SMB_ASSERT(base64 != NULL);
1681
1682         res = fprintf(add_fd, "%s:: %s\n", attr_name, base64);
1683         TALLOC_FREE(value);
1684         return res;
1685 }
1686
1687 /****************************************************************
1688 ****************************************************************/
1689
1690 static NTSTATUS fetch_group_info_to_ldif(TALLOC_CTX *mem_ctx,
1691                                          struct netr_DELTA_GROUP *r,
1692                                          GROUPMAP *groupmap,
1693                                          FILE *add_fd,
1694                                          const char *sid,
1695                                          const char *suffix)
1696 {
1697         const char *groupname = r->group_name.string;
1698         uint32 grouptype = 0, g_rid = 0;
1699         char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
1700
1701         /* Set up the group type (always 2 for group info) */
1702         grouptype = 2;
1703
1704         /* These groups are entered by populate_ldap_for_ldif */
1705         if (strcmp(groupname, "Domain Admins") == 0 ||
1706             strcmp(groupname, "Domain Users") == 0 ||
1707             strcmp(groupname, "Domain Guests") == 0 ||
1708             strcmp(groupname, "Domain Computers") == 0 ||
1709             strcmp(groupname, "Administrators") == 0 ||
1710             strcmp(groupname, "Print Operators") == 0 ||
1711             strcmp(groupname, "Backup Operators") == 0 ||
1712             strcmp(groupname, "Replicators") == 0) {
1713                 SAFE_FREE(group_attr);
1714                 return NT_STATUS_OK;
1715         } else {
1716                 /* Increment the gid for the new group */
1717                 ldif_gid++;
1718         }
1719
1720         /* Map the group rid, gid, and dn */
1721         g_rid = r->rid;
1722         groupmap->rid = g_rid;
1723         groupmap->gidNumber = ldif_gid;
1724         groupmap->sambaSID      = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
1725         groupmap->group_dn      = talloc_asprintf(mem_ctx,
1726              "cn=%s,ou=%s,%s", groupname, group_attr, suffix);
1727         NT_STATUS_HAVE_NO_MEMORY(groupmap->sambaSID);
1728         NT_STATUS_HAVE_NO_MEMORY(groupmap->group_dn);
1729
1730         /* Write the data to the temporary add ldif file */
1731         fprintf(add_fd, "# %s, %s, %s\n", groupname, group_attr,
1732                 suffix);
1733         fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", groupname, group_attr,
1734                      suffix);
1735         fprintf(add_fd, "objectClass: posixGroup\n");
1736         fprintf(add_fd, "objectClass: sambaGroupMapping\n");
1737         fprintf_attr(add_fd, "cn", "%s", groupname);
1738         fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
1739         fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
1740         fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
1741         fprintf_attr(add_fd, "displayName", "%s", groupname);
1742         fprintf(add_fd, "\n");
1743         fflush(add_fd);
1744
1745         SAFE_FREE(group_attr);
1746         /* Return */
1747         return NT_STATUS_OK;
1748 }
1749
1750 /****************************************************************
1751 ****************************************************************/
1752
1753 static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx,
1754                                            struct netr_DELTA_USER *r,
1755                                            GROUPMAP *groupmap,
1756                                            ACCOUNTMAP *accountmap,
1757                                            FILE *add_fd,
1758                                            const char *sid,
1759                                            const char *suffix,
1760                                            int alloced)
1761 {
1762         fstring username, logonscript, homedrive, homepath = "", homedir = "";
1763         fstring hex_nt_passwd, hex_lm_passwd;
1764         fstring description, profilepath, fullname, sambaSID;
1765         uchar lm_passwd[16], nt_passwd[16];
1766         char *flags, *user_rdn;
1767         const char *ou;
1768         const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
1769         static uchar zero_buf[16];
1770         uint32 rid = 0, group_rid = 0, gidNumber = 0;
1771         time_t unix_time;
1772         int i;
1773
1774         /* Get the username */
1775         fstrcpy(username, r->account_name.string);
1776
1777         /* Get the rid */
1778         rid = r->rid;
1779
1780         /* Map the rid and username for group member info later */
1781         accountmap->rid = rid;
1782         accountmap->cn = talloc_strdup(mem_ctx, username);
1783         NT_STATUS_HAVE_NO_MEMORY(accountmap->cn);
1784
1785         /* Get the home directory */
1786         if (r->acct_flags & ACB_NORMAL) {
1787                 fstrcpy(homedir, r->home_directory.string);
1788                 if (!*homedir) {
1789                         snprintf(homedir, sizeof(homedir), "/home/%s", username);
1790                 } else {
1791                         snprintf(homedir, sizeof(homedir), "/nobodyshomedir");
1792                 }
1793                 ou = lp_ldap_user_suffix();
1794         } else {
1795                 ou = lp_ldap_machine_suffix();
1796                 snprintf(homedir, sizeof(homedir), "/machinehomedir");
1797         }
1798
1799         /* Get the logon script */
1800         fstrcpy(logonscript, r->logon_script.string);
1801
1802         /* Get the home drive */
1803         fstrcpy(homedrive, r->home_drive.string);
1804
1805         /* Get the home path */
1806         fstrcpy(homepath, r->home_directory.string);
1807
1808         /* Get the description */
1809         fstrcpy(description, r->description.string);
1810
1811         /* Get the display name */
1812         fstrcpy(fullname, r->full_name.string);
1813
1814         /* Get the profile path */
1815         fstrcpy(profilepath, r->profile_path.string);
1816
1817         /* Get lm and nt password data */
1818         if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
1819                 sam_pwd_hash(r->rid, r->lmpassword.hash, lm_passwd, 0);
1820                 pdb_sethexpwd(hex_lm_passwd, lm_passwd, r->acct_flags);
1821         } else {
1822                 pdb_sethexpwd(hex_lm_passwd, NULL, 0);
1823         }
1824         if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
1825                 sam_pwd_hash(r->rid, r->ntpassword.hash, nt_passwd, 0);
1826                 pdb_sethexpwd(hex_nt_passwd, nt_passwd, r->acct_flags);
1827         } else {
1828                 pdb_sethexpwd(hex_nt_passwd, NULL, 0);
1829         }
1830         unix_time = nt_time_to_unix(r->last_password_change);
1831
1832         /* Increment the uid for the new user */
1833         ldif_uid++;
1834
1835         /* Set up group id and sambaSID for the user */
1836         group_rid = r->primary_gid;
1837         for (i=0; i<alloced; i++) {
1838                 if (groupmap[i].rid == group_rid) break;
1839         }
1840         if (i == alloced){
1841                 DEBUG(1, ("Could not find rid %d in groupmap array\n",
1842                           group_rid));
1843                 return NT_STATUS_UNSUCCESSFUL;
1844         }
1845         gidNumber = groupmap[i].gidNumber;
1846         snprintf(sambaSID, sizeof(sambaSID), groupmap[i].sambaSID);
1847
1848         /* Set up sambaAcctFlags */
1849         flags = pdb_encode_acct_ctrl(r->acct_flags,
1850                                      NEW_PW_FORMAT_SPACE_PADDED_LEN);
1851
1852         /* Add the user to the temporary add ldif file */
1853         /* this isn't quite right...we can't assume there's just OU=. jmcd */
1854         user_rdn = sstring_sub(ou, '=', ',');
1855         fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
1856         fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
1857                      suffix);
1858         SAFE_FREE(user_rdn);
1859         fprintf(add_fd, "ObjectClass: top\n");
1860         fprintf(add_fd, "objectClass: inetOrgPerson\n");
1861         fprintf(add_fd, "objectClass: posixAccount\n");
1862         fprintf(add_fd, "objectClass: shadowAccount\n");
1863         fprintf(add_fd, "objectClass: sambaSamAccount\n");
1864         fprintf_attr(add_fd, "cn", "%s", username);
1865         fprintf_attr(add_fd, "sn", "%s", username);
1866         fprintf_attr(add_fd, "uid", "%s", username);
1867         fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
1868         fprintf(add_fd, "gidNumber: %d\n", gidNumber);
1869         fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
1870         if (*homepath)
1871                 fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
1872         if (*homedrive)
1873                 fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
1874         if (*logonscript)
1875                 fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
1876         fprintf(add_fd, "loginShell: %s\n",
1877                 ((r->acct_flags & ACB_NORMAL) ?
1878                  "/bin/bash" : "/bin/false"));
1879         fprintf(add_fd, "gecos: System User\n");
1880         if (*description)
1881                 fprintf_attr(add_fd, "description", "%s", description);
1882         fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
1883         fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
1884         if(*fullname)
1885                 fprintf_attr(add_fd, "displayName", "%s", fullname);
1886         if(*profilepath)
1887                 fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
1888         if (strcmp(nopasswd, hex_lm_passwd) != 0)
1889                 fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
1890         if (strcmp(nopasswd, hex_nt_passwd) != 0)
1891                 fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd);
1892         fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time);
1893         fprintf(add_fd, "sambaAcctFlags: %s\n", flags);
1894         fprintf(add_fd, "\n");
1895         fflush(add_fd);
1896
1897         /* Return */
1898         return NT_STATUS_OK;
1899 }
1900
1901 /****************************************************************
1902 ****************************************************************/
1903
1904 static NTSTATUS fetch_alias_info_to_ldif(TALLOC_CTX *mem_ctx,
1905                                          struct netr_DELTA_ALIAS *r,
1906                                          GROUPMAP *groupmap,
1907                                          FILE *add_fd,
1908                                          const char *sid,
1909                                          const char *suffix,
1910                                          enum netr_SamDatabaseID database_id)
1911 {
1912         fstring aliasname, description;
1913         uint32 grouptype = 0, g_rid = 0;
1914         char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
1915
1916         /* Get the alias name */
1917         fstrcpy(aliasname, r->alias_name.string);
1918
1919         /* Get the alias description */
1920         fstrcpy(description, r->description.string);
1921
1922         /* Set up the group type */
1923         switch (database_id) {
1924         case SAM_DATABASE_DOMAIN:
1925                 grouptype = 4;
1926                 break;
1927         case SAM_DATABASE_BUILTIN:
1928                 grouptype = 5;
1929                 break;
1930         default:
1931                 grouptype = 4;
1932                 break;
1933         }
1934
1935         /*
1936           These groups are entered by populate_ldap_for_ldif
1937           Note that populate creates a group called Relicators,
1938           but NT returns a group called Replicator
1939         */
1940         if (strcmp(aliasname, "Domain Admins") == 0 ||
1941             strcmp(aliasname, "Domain Users") == 0 ||
1942             strcmp(aliasname, "Domain Guests") == 0 ||
1943             strcmp(aliasname, "Domain Computers") == 0 ||
1944             strcmp(aliasname, "Administrators") == 0 ||
1945             strcmp(aliasname, "Print Operators") == 0 ||
1946             strcmp(aliasname, "Backup Operators") == 0 ||
1947             strcmp(aliasname, "Replicator") == 0) {
1948                 SAFE_FREE(group_attr);
1949                 return NT_STATUS_OK;
1950         } else {
1951                 /* Increment the gid for the new group */
1952                 ldif_gid++;
1953         }
1954
1955         /* Map the group rid and gid */
1956         g_rid = r->rid;
1957         groupmap->gidNumber = ldif_gid;
1958         groupmap->sambaSID = talloc_asprintf(mem_ctx, "%s-%d", sid, g_rid);
1959         NT_STATUS_HAVE_NO_MEMORY(groupmap->sambaSID);
1960
1961         /* Write the data to the temporary add ldif file */
1962         fprintf(add_fd, "# %s, %s, %s\n", aliasname, group_attr,
1963                 suffix);
1964         fprintf_attr(add_fd, "dn", "cn=%s,ou=%s,%s", aliasname, group_attr,
1965                      suffix);
1966         fprintf(add_fd, "objectClass: posixGroup\n");
1967         fprintf(add_fd, "objectClass: sambaGroupMapping\n");
1968         fprintf(add_fd, "cn: %s\n", aliasname);
1969         fprintf(add_fd, "gidNumber: %d\n", ldif_gid);
1970         fprintf(add_fd, "sambaSID: %s\n", groupmap->sambaSID);
1971         fprintf(add_fd, "sambaGroupType: %d\n", grouptype);
1972         fprintf_attr(add_fd, "displayName", "%s", aliasname);
1973         if (description[0])
1974                 fprintf_attr(add_fd, "description", "%s", description);
1975         fprintf(add_fd, "\n");
1976         fflush(add_fd);
1977
1978         SAFE_FREE(group_attr);
1979         /* Return */
1980         return NT_STATUS_OK;
1981 }
1982
1983 /****************************************************************
1984 ****************************************************************/
1985
1986 static NTSTATUS fetch_groupmem_info_to_ldif(struct netr_DELTA_GROUP_MEMBER *r,
1987                                             uint32_t id_rid,
1988                                             GROUPMAP *groupmap,
1989                                             ACCOUNTMAP *accountmap,
1990                                             FILE *mod_fd, int alloced)
1991 {
1992         fstring group_dn;
1993         uint32 group_rid = 0, rid = 0;
1994         int i, j, k;
1995
1996         /* Get the dn for the group */
1997         if (r->num_rids > 0) {
1998                 group_rid = id_rid;
1999                 for (j=0; j<alloced; j++) {
2000                         if (groupmap[j].rid == group_rid) break;
2001                 }
2002                 if (j == alloced){
2003                         DEBUG(1, ("Could not find rid %d in groupmap array\n",
2004                                   group_rid));
2005                         return NT_STATUS_UNSUCCESSFUL;
2006                 }
2007                 snprintf(group_dn, sizeof(group_dn), "%s", groupmap[j].group_dn);
2008                 fprintf(mod_fd, "dn: %s\n", group_dn);
2009
2010                 /* Get the cn for each member */
2011                 for (i=0; i < r->num_rids; i++) {
2012                         rid = r->rids[i];
2013                         for (k=0; k<alloced; k++) {
2014                                 if (accountmap[k].rid == rid) break;
2015                         }
2016                         if (k == alloced){
2017                                 DEBUG(1, ("Could not find rid %d in "
2018                                           "accountmap array\n", rid));
2019                                 return NT_STATUS_UNSUCCESSFUL;
2020                         }
2021                         fprintf(mod_fd, "memberUid: %s\n", accountmap[k].cn);
2022                 }
2023                 fprintf(mod_fd, "\n");
2024         }
2025         fflush(mod_fd);
2026
2027         /* Return */
2028         return NT_STATUS_OK;
2029 }
2030
2031 /****************************************************************
2032 ****************************************************************/
2033
2034 static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx,
2035                                   struct samsync_context *ctx,
2036                                   enum netr_SamDatabaseID database_id)
2037 {
2038         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
2039         struct samsync_ldif_context *r;
2040         const char *add_template = "/tmp/add.ldif.XXXXXX";
2041         const char *mod_template = "/tmp/mod.ldif.XXXXXX";
2042         const char *builtin_sid = "S-1-5-32";
2043
2044         if (ctx->ldif && ctx->ldif->initialized) {
2045                 return NT_STATUS_OK;
2046         }
2047
2048         r = TALLOC_ZERO_P(mem_ctx, struct samsync_ldif_context);
2049         NT_STATUS_HAVE_NO_MEMORY(r);
2050
2051         /* Get other smb.conf data */
2052         if (!(lp_workgroup()) || !*(lp_workgroup())) {
2053                 DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
2054                 exit(1);
2055         }
2056
2057         /* Get the ldap suffix */
2058         r->suffix = lp_ldap_suffix();
2059         if (r->suffix == NULL || strcmp(r->suffix, "") == 0) {
2060                 DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
2061                 exit(1);
2062         }
2063
2064         /* Get the sid */
2065         ctx->domain_sid_str = sid_string_talloc(mem_ctx, ctx->domain_sid);
2066         NT_STATUS_HAVE_NO_MEMORY(ctx->domain_sid_str);
2067
2068         /* Ensure we have an output file */
2069         if (ctx->ldif_filename) {
2070                 r->ldif_file = fopen(ctx->ldif_filename, "a");
2071         } else {
2072                 r->ldif_file = stdout;
2073         }
2074
2075         if (!r->ldif_file) {
2076                 fprintf(stderr, "Could not open %s\n", ctx->ldif_filename);
2077                 DEBUG(1, ("Could not open %s\n", ctx->ldif_filename));
2078                 status = NT_STATUS_UNSUCCESSFUL;
2079                 goto done;
2080         }
2081
2082         r->add_template = talloc_strdup(mem_ctx, add_template);
2083         r->mod_template = talloc_strdup(mem_ctx, mod_template);
2084         if (!r->add_template || !r->mod_template) {
2085                 status = NT_STATUS_NO_MEMORY;
2086                 goto done;
2087         }
2088
2089         r->add_name = talloc_strdup(mem_ctx, add_template);
2090         r->mod_name = talloc_strdup(mem_ctx, mod_template);
2091         if (!r->add_name || !r->mod_name) {
2092                 status = NT_STATUS_NO_MEMORY;
2093                 goto done;
2094         }
2095
2096         /* Open the add and mod ldif files */
2097         if (!(r->add_file = fdopen(smb_mkstemp(r->add_name),"w"))) {
2098                 DEBUG(1, ("Could not open %s\n", r->add_name));
2099                 status = NT_STATUS_UNSUCCESSFUL;
2100                 goto done;
2101         }
2102         if (!(r->mod_file = fdopen(smb_mkstemp(r->mod_name),"w"))) {
2103                 DEBUG(1, ("Could not open %s\n", r->mod_name));
2104                 status = NT_STATUS_UNSUCCESSFUL;
2105                 goto done;
2106         }
2107
2108         /* Allocate initial memory for groupmap and accountmap arrays */
2109         r->groupmap = TALLOC_ZERO_ARRAY(mem_ctx, GROUPMAP, 8);
2110         r->accountmap = TALLOC_ZERO_ARRAY(mem_ctx, ACCOUNTMAP, 8);
2111         if (r->groupmap == NULL || r->accountmap == NULL) {
2112                 DEBUG(1,("GROUPMAP talloc failed\n"));
2113                 status = NT_STATUS_NO_MEMORY;
2114                 goto done;
2115         }
2116
2117         /* Remember how many we malloced */
2118         r->num_alloced = 8;
2119
2120         /* Initial database population */
2121         if (database_id == SAM_DATABASE_DOMAIN) {
2122
2123                 status = populate_ldap_for_ldif(ctx->domain_sid_str,
2124                                                 r->suffix,
2125                                                 builtin_sid,
2126                                                 r->add_file);
2127                 if (!NT_STATUS_IS_OK(status)) {
2128                         goto done;
2129                 }
2130
2131                 status = map_populate_groups(mem_ctx,
2132                                              r->groupmap,
2133                                              r->accountmap,
2134                                              ctx->domain_sid_str,
2135                                              r->suffix,
2136                                              builtin_sid);
2137                 if (!NT_STATUS_IS_OK(status)) {
2138                         goto done;
2139                 }
2140         }
2141
2142         r->initialized = true;
2143
2144         ctx->ldif = r;
2145
2146         return NT_STATUS_OK;
2147  done:
2148         TALLOC_FREE(r);
2149         return status;
2150 }
2151
2152 /****************************************************************
2153 ****************************************************************/
2154
2155 static void ldif_free_context(struct samsync_ldif_context *r)
2156 {
2157         if (!r) {
2158                 return;
2159         }
2160
2161         /* Close and delete the ldif files */
2162         if (r->add_file) {
2163                 fclose(r->add_file);
2164         }
2165
2166         if ((r->add_name != NULL) &&
2167             strcmp(r->add_name, r->add_template) && (unlink(r->add_name))) {
2168                 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
2169                          r->add_name, strerror(errno)));
2170         }
2171
2172         if (r->mod_file) {
2173                 fclose(r->mod_file);
2174         }
2175
2176         if ((r->mod_name != NULL) &&
2177             strcmp(r->mod_name, r->mod_template) && (unlink(r->mod_name))) {
2178                 DEBUG(1,("unlink(%s) failed, error was (%s)\n",
2179                          r->mod_name, strerror(errno)));
2180         }
2181
2182         if (r->ldif_file && (r->ldif_file != stdout)) {
2183                 fclose(r->ldif_file);
2184         }
2185
2186         TALLOC_FREE(r);
2187 }
2188
2189 /****************************************************************
2190 ****************************************************************/
2191
2192 static void ldif_write_output(enum netr_SamDatabaseID database_id,
2193                               struct samsync_context *ctx)
2194 {
2195         struct samsync_ldif_context *l = ctx->ldif;
2196
2197         /* Write ldif data to the user's file */
2198         if (database_id == SAM_DATABASE_DOMAIN) {
2199                 fprintf(l->ldif_file,
2200                         "# SAM_DATABASE_DOMAIN: ADD ENTITIES\n");
2201                 fprintf(l->ldif_file,
2202                         "# =================================\n\n");
2203                 fflush(l->ldif_file);
2204         } else if (database_id == SAM_DATABASE_BUILTIN) {
2205                 fprintf(l->ldif_file,
2206                         "# SAM_DATABASE_BUILTIN: ADD ENTITIES\n");
2207                 fprintf(l->ldif_file,
2208                         "# ==================================\n\n");
2209                 fflush(l->ldif_file);
2210         }
2211         fseek(l->add_file, 0, SEEK_SET);
2212         transfer_file(fileno(l->add_file), fileno(l->ldif_file), (size_t) -1);
2213
2214         if (database_id == SAM_DATABASE_DOMAIN) {
2215                 fprintf(l->ldif_file,
2216                         "# SAM_DATABASE_DOMAIN: MODIFY ENTITIES\n");
2217                 fprintf(l->ldif_file,
2218                         "# ====================================\n\n");
2219                 fflush(l->ldif_file);
2220         } else if (database_id == SAM_DATABASE_BUILTIN) {
2221                 fprintf(l->ldif_file,
2222                         "# SAM_DATABASE_BUILTIN: MODIFY ENTITIES\n");
2223                 fprintf(l->ldif_file,
2224                         "# =====================================\n\n");
2225                 fflush(l->ldif_file);
2226         }
2227         fseek(l->mod_file, 0, SEEK_SET);
2228         transfer_file(fileno(l->mod_file), fileno(l->ldif_file), (size_t) -1);
2229 }
2230
2231 /****************************************************************
2232 ****************************************************************/
2233
2234 static NTSTATUS fetch_sam_entry_ldif(TALLOC_CTX *mem_ctx,
2235                                      enum netr_SamDatabaseID database_id,
2236                                      struct netr_DELTA_ENUM *r,
2237                                      struct samsync_context *ctx,
2238                                      uint32_t *a_index,
2239                                      uint32_t *g_index)
2240 {
2241         union netr_DELTA_UNION u = r->delta_union;
2242         union netr_DELTA_ID_UNION id = r->delta_id_union;
2243         struct samsync_ldif_context *l = ctx->ldif;
2244
2245         switch (r->delta_type) {
2246                 case NETR_DELTA_DOMAIN:
2247                         break;
2248
2249                 case NETR_DELTA_GROUP:
2250                         fetch_group_info_to_ldif(mem_ctx,
2251                                                  u.group,
2252                                                  &l->groupmap[*g_index],
2253                                                  l->add_file,
2254                                                  ctx->domain_sid_str,
2255                                                  l->suffix);
2256                         (*g_index)++;
2257                         break;
2258
2259                 case NETR_DELTA_USER:
2260                         fetch_account_info_to_ldif(mem_ctx,
2261                                                    u.user,
2262                                                    l->groupmap,
2263                                                    &l->accountmap[*a_index],
2264                                                    l->add_file,
2265                                                    ctx->domain_sid_str,
2266                                                    l->suffix,
2267                                                    l->num_alloced);
2268                         (*a_index)++;
2269                         break;
2270
2271                 case NETR_DELTA_ALIAS:
2272                         fetch_alias_info_to_ldif(mem_ctx,
2273                                                  u.alias,
2274                                                  &l->groupmap[*g_index],
2275                                                  l->add_file,
2276                                                  ctx->domain_sid_str,
2277                                                  l->suffix,
2278                                                  database_id);
2279                         (*g_index)++;
2280                         break;
2281
2282                 case NETR_DELTA_GROUP_MEMBER:
2283                         fetch_groupmem_info_to_ldif(u.group_member,
2284                                                     id.rid,
2285                                                     l->groupmap,
2286                                                     l->accountmap,
2287                                                     l->mod_file,
2288                                                     l->num_alloced);
2289                         break;
2290
2291                 case NETR_DELTA_ALIAS_MEMBER:
2292                 case NETR_DELTA_POLICY:
2293                 case NETR_DELTA_ACCOUNT:
2294                 case NETR_DELTA_TRUSTED_DOMAIN:
2295                 case NETR_DELTA_SECRET:
2296                 case NETR_DELTA_RENAME_GROUP:
2297                 case NETR_DELTA_RENAME_USER:
2298                 case NETR_DELTA_RENAME_ALIAS:
2299                 case NETR_DELTA_DELETE_GROUP:
2300                 case NETR_DELTA_DELETE_USER:
2301                 case NETR_DELTA_MODIFY_COUNT:
2302                 default:
2303                         break;
2304         } /* end of switch */
2305
2306         return NT_STATUS_OK;
2307 }
2308
2309 /****************************************************************
2310 ****************************************************************/
2311
2312 static NTSTATUS ldif_realloc_maps(TALLOC_CTX *mem_ctx,
2313                                   struct samsync_context *ctx,
2314                                   uint32_t num_entries)
2315 {
2316         struct samsync_ldif_context *l = ctx->ldif;
2317
2318         if (!l) {
2319                 return NT_STATUS_INVALID_PARAMETER;
2320         }
2321
2322         /* Re-allocate memory for groupmap and accountmap arrays */
2323         l->groupmap = TALLOC_REALLOC_ARRAY(mem_ctx,
2324                                            l->groupmap,
2325                                            GROUPMAP,
2326                                            num_entries + l->num_alloced);
2327
2328         l->accountmap = TALLOC_REALLOC_ARRAY(mem_ctx,
2329                                              l->accountmap,
2330                                              ACCOUNTMAP,
2331                                              num_entries + l->num_alloced);
2332
2333         if (l->groupmap == NULL || l->accountmap == NULL) {
2334                 DEBUG(1,("GROUPMAP talloc failed\n"));
2335                 return NT_STATUS_NO_MEMORY;
2336         }
2337
2338         /* Initialize the new records */
2339         memset(&(l->groupmap[l->num_alloced]), 0,
2340                sizeof(GROUPMAP) * num_entries);
2341         memset(&(l->accountmap[l->num_alloced]), 0,
2342                sizeof(ACCOUNTMAP) * num_entries);
2343
2344         /* Remember how many we alloced this time */
2345         l->num_alloced += num_entries;
2346
2347         return NT_STATUS_OK;
2348 }
2349
2350 /****************************************************************
2351 ****************************************************************/
2352
2353 static NTSTATUS fetch_sam_entries_ldif(TALLOC_CTX *mem_ctx,
2354                                        enum netr_SamDatabaseID database_id,
2355                                        struct netr_DELTA_ENUM_ARRAY *r,
2356                                        NTSTATUS result,
2357                                        struct samsync_context *ctx)
2358 {
2359         NTSTATUS status;
2360         int i;
2361         uint32_t g_index = 0, a_index = 0;
2362
2363         status = ldif_init_context(mem_ctx, ctx, database_id);
2364         if (!NT_STATUS_IS_OK(status)) {
2365                 goto failed;
2366         }
2367
2368         status = ldif_realloc_maps(mem_ctx, ctx, r->num_deltas);
2369         if (!NT_STATUS_IS_OK(status)) {
2370                 goto failed;
2371         }
2372
2373         for (i = 0; i < r->num_deltas; i++) {
2374                 status = fetch_sam_entry_ldif(mem_ctx, database_id,
2375                                               &r->delta_enum[i], ctx,
2376                                               &g_index, &a_index);
2377                 if (!NT_STATUS_IS_OK(status)) {
2378                         goto failed;
2379                 }
2380         }
2381
2382         /* This was the last query */
2383         if (NT_STATUS_IS_OK(result)) {
2384                 ldif_write_output(database_id, ctx);
2385                 ldif_free_context(ctx->ldif);
2386                 ctx->ldif = NULL;
2387         }
2388
2389         return NT_STATUS_OK;
2390
2391  failed:
2392         ldif_free_context(ctx->ldif);
2393
2394         return status;
2395 }
2396
2397 /**
2398  * Basic usage function for 'net rpc vampire'
2399  *
2400  * @param c     A net_context structure
2401  * @param argc  Standard main() style argc
2402  * @param argc  Standard main() style argv.  Initial components are already
2403  *              stripped
2404  **/
2405
2406 int rpc_vampire_usage(struct net_context *c, int argc, const char **argv)
2407 {
2408         d_printf("net rpc vampire [ldif [<ldif-filename>] [options]\n"
2409                  "\t to pull accounts from a remote PDC where we are a BDC\n"
2410                  "\t\t no args puts accounts in local passdb from smb.conf\n"
2411                  "\t\t ldif - put accounts in ldif format (file defaults to "
2412                  "/tmp/tmp.ldif\n");
2413
2414         net_common_flags_usage(c, argc, argv);
2415         return -1;
2416 }
2417
2418
2419 /* dump sam database via samsync rpc calls */
2420 NTSTATUS rpc_vampire_internals(struct net_context *c,
2421                                 const DOM_SID *domain_sid,
2422                                 const char *domain_name,
2423                                 struct cli_state *cli,
2424                                 struct rpc_pipe_client *pipe_hnd,
2425                                 TALLOC_CTX *mem_ctx,
2426                                 int argc,
2427                                 const char **argv)
2428 {
2429         NTSTATUS result;
2430         fstring my_dom_sid_str;
2431         fstring rem_dom_sid_str;
2432         struct samsync_context *ctx;
2433         samsync_fn_t *fn;
2434
2435         ctx = TALLOC_ZERO_P(mem_ctx, struct samsync_context);
2436         NT_STATUS_HAVE_NO_MEMORY(ctx);
2437
2438         if (!sid_equal(domain_sid, get_global_sam_sid())) {
2439                 d_printf("Cannot import users from %s at this time, "
2440                          "as the current domain:\n\t%s: %s\nconflicts "
2441                          "with the remote domain\n\t%s: %s\n"
2442                          "Perhaps you need to set: \n\n\tsecurity=user\n\t"
2443                          "workgroup=%s\n\n in your smb.conf?\n",
2444                          domain_name,
2445                          get_global_sam_name(),
2446                          sid_to_fstring(my_dom_sid_str,
2447                                         get_global_sam_sid()),
2448                          domain_name, sid_to_fstring(rem_dom_sid_str,
2449                                                      domain_sid),
2450                          domain_name);
2451                 return NT_STATUS_UNSUCCESSFUL;
2452         }
2453
2454         if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) {
2455                 ctx->mode = NET_SAMSYNC_MODE_FETCH_LDIF;
2456                 ctx->ldif_filename = argv[1];
2457                 fn = (samsync_fn_t *)fetch_sam_entries_ldif;
2458         } else {
2459                 ctx->mode = NET_SAMSYNC_MODE_FETCH_PASSDB;
2460                 fn = (samsync_fn_t *)fetch_sam_entries;
2461         }
2462
2463         /* fetch domain */
2464         ctx->domain_sid = domain_sid;
2465         result = process_database(pipe_hnd, SAM_DATABASE_DOMAIN,
2466                                   (samsync_fn_t)fn, ctx);
2467         if (!NT_STATUS_IS_OK(result)) {
2468                 d_fprintf(stderr, "Failed to fetch domain database: %s\n",
2469                           nt_errstr(result));
2470                 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED))
2471                         d_fprintf(stderr, "Perhaps %s is a Windows 2000 "
2472                                   "native mode domain?\n", domain_name);
2473                 goto fail;
2474         }
2475
2476         /* fetch builtin */
2477         ctx->domain_sid = &global_sid_Builtin;
2478         result = process_database(pipe_hnd, SAM_DATABASE_BUILTIN,
2479                                   (samsync_fn_t)fn, ctx);
2480         if (!NT_STATUS_IS_OK(result)) {
2481                 d_fprintf(stderr, "Failed to fetch builtin database: %s\n",
2482                           nt_errstr(result));
2483                 goto fail;
2484         }
2485
2486         /* Currently we crash on PRIVS somewhere in unmarshalling */
2487         /* Dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds); */
2488
2489  fail:
2490         return result;
2491 }