r7882: Looks like a large patch - but what it actually does is make Samba
[samba.git] / source / 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    Modified by Volker Lendecke 2002
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "utils/net.h"
26
27 static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g)
28 {
29         int i;
30         d_printf("Group mem %u: ", rid);
31         for (i=0;i<g->num_members;i++) {
32                 d_printf("%u ", g->rids[i]);
33         }
34         d_printf("\n");
35 }
36
37
38 static const char *display_time(NTTIME *nttime)
39 {
40         static fstring string;
41
42         float high;
43         float low;
44         int sec;
45         int days, hours, mins, secs;
46         int offset = 1;
47
48         if (nttime->high==0 && nttime->low==0)
49                 return "Now";
50
51         if (nttime->high==0x80000000 && nttime->low==0)
52                 return "Never";
53
54         high = 65536;   
55         high = high/10000;
56         high = high*65536;
57         high = high/1000;
58         high = high * (~nttime->high);
59
60         low = ~nttime->low;     
61         low = low/(1000*1000*10);
62
63         sec=high+low;
64         sec+=offset;
65
66         days=sec/(60*60*24);
67         hours=(sec - (days*60*60*24)) / (60*60);
68         mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60;
69         secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60);
70
71         fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs);
72         return (string);
73 }
74
75
76 static void display_alias_info(uint32 rid, SAM_ALIAS_INFO *a)
77 {
78         d_printf("Alias '%s' ", unistr2_static(&a->uni_als_name));
79         d_printf("desc='%s' rid=%u\n", unistr2_static(&a->uni_als_desc), a->als_rid);
80 }
81
82 static void display_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *a)
83 {
84         int i;
85         d_printf("Alias rid %u: ", rid);
86         for (i=0;i<a->num_members;i++) {
87                 d_printf("%s ", sid_string_static(&a->sids[i].sid));
88         }
89         d_printf("\n");
90 }
91
92 static void display_account_info(uint32 rid, SAM_ACCOUNT_INFO *a)
93 {
94         fstring hex_nt_passwd, hex_lm_passwd;
95         uchar lm_passwd[16], nt_passwd[16];
96         static uchar zero_buf[16];
97
98         /* Decode hashes from password hash (if they are not NULL) */
99         
100         if (memcmp(a->pass.buf_lm_pwd, zero_buf, 16) != 0) {
101                 sam_pwd_hash(a->user_rid, a->pass.buf_lm_pwd, lm_passwd, 0);
102                 pdb_sethexpwd(hex_lm_passwd, lm_passwd, a->acb_info);
103         } else {
104                 pdb_sethexpwd(hex_lm_passwd, NULL, 0);
105         }
106
107         if (memcmp(a->pass.buf_nt_pwd, zero_buf, 16) != 0) {
108                 sam_pwd_hash(a->user_rid, a->pass.buf_nt_pwd, nt_passwd, 0);
109                 pdb_sethexpwd(hex_nt_passwd, nt_passwd, a->acb_info);
110         } else {
111                 pdb_sethexpwd(hex_nt_passwd, NULL, 0);
112         }
113         
114         printf("%s:%d:%s:%s:%s:LCT-0\n", unistr2_static(&a->uni_acct_name),
115                a->user_rid, hex_lm_passwd, hex_nt_passwd,
116                pdb_encode_acct_ctrl(a->acb_info, NEW_PW_FORMAT_SPACE_PADDED_LEN));
117 }
118
119 static void display_domain_info(SAM_DOMAIN_INFO *a)
120 {
121         time_t u_logout;
122
123         u_logout = nt_time_to_unix_abs((NTTIME *)&a->force_logoff);
124
125         d_printf("Domain name: %s\n", unistr2_static(&a->uni_dom_name));
126
127         d_printf("Minimal Password Length: %d\n", a->min_pwd_len);
128         d_printf("Password History Length: %d\n", a->pwd_history_len);
129
130         d_printf("Force Logoff: %d\n", (int)u_logout);
131
132         d_printf("Max Password Age: %s\n", display_time((NTTIME *)&a->max_pwd_age));
133         d_printf("Min Password Age: %s\n", display_time((NTTIME *)&a->min_pwd_age));
134
135         d_printf("Lockout Time: %s\n", display_time((NTTIME *)&a->account_lockout.lockout_duration));
136         d_printf("Lockout Reset Time: %s\n", display_time((NTTIME *)&a->account_lockout.reset_count));
137
138         d_printf("Bad Attempt Lockout: %d\n", a->account_lockout.bad_attempt_lockout);
139         d_printf("User must logon to change password: %d\n", a->logon_chgpass);
140 }
141
142 static void display_group_info(uint32 rid, SAM_GROUP_INFO *a)
143 {
144         d_printf("Group '%s' ", unistr2_static(&a->uni_grp_name));
145         d_printf("desc='%s', rid=%u\n", unistr2_static(&a->uni_grp_desc), rid);
146 }
147
148 static void display_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta)
149 {
150         switch (hdr_delta->type) {
151         case SAM_DELTA_ACCOUNT_INFO:
152                 display_account_info(hdr_delta->target_rid, &delta->account_info);
153                 break;
154         case SAM_DELTA_GROUP_MEM:
155                 display_group_mem_info(hdr_delta->target_rid, &delta->grp_mem_info);
156                 break;
157         case SAM_DELTA_ALIAS_INFO:
158                 display_alias_info(hdr_delta->target_rid, &delta->alias_info);
159                 break;
160         case SAM_DELTA_ALIAS_MEM:
161                 display_alias_mem(hdr_delta->target_rid, &delta->als_mem_info);
162                 break;
163         case SAM_DELTA_DOMAIN_INFO:
164                 display_domain_info(&delta->domain_info);
165                 break;
166         case SAM_DELTA_GROUP_INFO:
167                 display_group_info(hdr_delta->target_rid, &delta->group_info);
168                 break;
169                 /* The following types are recognised but not handled */
170         case SAM_DELTA_RENAME_GROUP:
171                 d_printf("SAM_DELTA_RENAME_GROUP not handled\n");
172                 break;
173         case SAM_DELTA_RENAME_USER:
174                 d_printf("SAM_DELTA_RENAME_USER not handled\n");
175                 break;
176         case SAM_DELTA_RENAME_ALIAS:
177                 d_printf("SAM_DELTA_RENAME_ALIAS not handled\n");
178                 break;
179         case SAM_DELTA_POLICY_INFO:
180                 d_printf("SAM_DELTA_POLICY_INFO not handled\n");
181                 break;
182         case SAM_DELTA_TRUST_DOMS:
183                 d_printf("SAM_DELTA_TRUST_DOMS not handled\n");
184                 break;
185         case SAM_DELTA_PRIVS_INFO:
186                 d_printf("SAM_DELTA_PRIVS_INFO not handled\n");
187                 break;
188         case SAM_DELTA_SECRET_INFO:
189                 d_printf("SAM_DELTA_SECRET_INFO not handled\n");
190                 break;
191         case SAM_DELTA_DELETE_GROUP:
192                 d_printf("SAM_DELTA_DELETE_GROUP not handled\n");
193                 break;
194         case SAM_DELTA_DELETE_USER:
195                 d_printf("SAM_DELTA_DELETE_USER not handled\n");
196                 break;
197         case SAM_DELTA_MODIFIED_COUNT:
198                 d_printf("SAM_DELTA_MODIFIED_COUNT not handled\n");
199                 break;
200         default:
201                 d_printf("Unknown delta record type %d\n", hdr_delta->type);
202                 break;
203         }
204 }
205
206
207 static void dump_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds)
208 {
209         unsigned sync_context = 0;
210         NTSTATUS result;
211         int i;
212         TALLOC_CTX *mem_ctx;
213         SAM_DELTA_HDR *hdr_deltas;
214         SAM_DELTA_CTR *deltas;
215         uint32 num_deltas;
216
217         if (!(mem_ctx = talloc_init("dump_database"))) {
218                 return;
219         }
220
221         switch( db_type ) {
222         case SAM_DATABASE_DOMAIN:
223                 d_printf("Dumping DOMAIN database\n");
224                 break;
225         case SAM_DATABASE_BUILTIN:
226                 d_printf("Dumping BUILTIN database\n");
227                 break;
228         case SAM_DATABASE_PRIVS:
229                 d_printf("Dumping PRIVS databases\n");
230                 break;
231         default:
232                 d_printf("Dumping unknown database type %u\n", db_type );
233                 break;
234         }
235
236         do {
237                 result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds, db_type,
238                                                sync_context,
239                                                &num_deltas, &hdr_deltas, &deltas);
240                 if (NT_STATUS_IS_ERR(result))
241                         break;
242
243                 clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), ret_creds);
244                 for (i = 0; i < num_deltas; i++) {
245                         display_sam_entry(&hdr_deltas[i], &deltas[i]);
246                 }
247                 sync_context += 1;
248         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
249
250         talloc_destroy(mem_ctx);
251 }
252
253 /* dump sam database via samsync rpc calls */
254 NTSTATUS rpc_samdump_internals(const DOM_SID *domain_sid, 
255                                const char *domain_name, 
256                                struct cli_state *cli, TALLOC_CTX *mem_ctx, 
257                                int argc, const char **argv) 
258 {
259         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
260         uchar trust_password[16];
261         DOM_CRED ret_creds;
262         uint32 sec_channel;
263
264         ZERO_STRUCT(ret_creds);
265
266         fstrcpy(cli->domain, domain_name);
267
268         if (!secrets_fetch_trust_account_password(domain_name,
269                                                   trust_password,
270                                                   NULL, &sec_channel)) {
271                 DEBUG(0,("Could not fetch trust account password\n"));
272                 goto fail;
273         }
274
275         if (!NT_STATUS_IS_OK(nt_status = cli_nt_establish_netlogon(cli, sec_channel,
276                                                                    trust_password))) {
277                 DEBUG(0,("Error connecting to NETLOGON pipe\n"));
278                 goto fail;
279         }
280
281         dump_database(cli, SAM_DATABASE_DOMAIN, &ret_creds);
282         dump_database(cli, SAM_DATABASE_BUILTIN, &ret_creds);
283         dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds);
284
285         nt_status = NT_STATUS_OK;
286
287 fail:
288         cli_nt_session_close(cli);
289         return nt_status;
290 }
291
292 /* Convert a SAM_ACCOUNT_DELTA to a SAM_ACCOUNT. */
293 #define STRING_CHANGED (old_string && !new_string) ||\
294                     (!old_string && new_string) ||\
295                 (old_string && new_string && (strcmp(old_string, new_string) != 0))
296
297 static NTSTATUS
298 sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta)
299 {
300         const char *old_string, *new_string;
301         time_t unix_time, stored_time;
302         uchar lm_passwd[16], nt_passwd[16];
303         static uchar zero_buf[16];
304
305         /* Username, fullname, home dir, dir drive, logon script, acct
306            desc, workstations, profile. */
307
308         if (delta->hdr_acct_name.buffer) {
309                 old_string = pdb_get_nt_username(account);
310                 new_string = unistr2_static(&delta->uni_acct_name);
311
312                 if (STRING_CHANGED) {
313                         pdb_set_nt_username(account, new_string, PDB_CHANGED);
314               
315                 }
316          
317                 /* Unix username is the same - for sanity */
318                 old_string = pdb_get_username( account );
319                 if (STRING_CHANGED) {
320                         pdb_set_username(account, new_string, PDB_CHANGED);
321                 }
322         }
323
324         if (delta->hdr_full_name.buffer) {
325                 old_string = pdb_get_fullname(account);
326                 new_string = unistr2_static(&delta->uni_full_name);
327
328                 if (STRING_CHANGED)
329                         pdb_set_fullname(account, new_string, PDB_CHANGED);
330         }
331
332         if (delta->hdr_home_dir.buffer) {
333                 old_string = pdb_get_homedir(account);
334                 new_string = unistr2_static(&delta->uni_home_dir);
335
336                 if (STRING_CHANGED)
337                         pdb_set_homedir(account, new_string, PDB_CHANGED);
338         }
339
340         if (delta->hdr_dir_drive.buffer) {
341                 old_string = pdb_get_dir_drive(account);
342                 new_string = unistr2_static(&delta->uni_dir_drive);
343
344                 if (STRING_CHANGED)
345                         pdb_set_dir_drive(account, new_string, PDB_CHANGED);
346         }
347
348         if (delta->hdr_logon_script.buffer) {
349                 old_string = pdb_get_logon_script(account);
350                 new_string = unistr2_static(&delta->uni_logon_script);
351
352                 if (STRING_CHANGED)
353                         pdb_set_logon_script(account, new_string, PDB_CHANGED);
354         }
355
356         if (delta->hdr_acct_desc.buffer) {
357                 old_string = pdb_get_acct_desc(account);
358                 new_string = unistr2_static(&delta->uni_acct_desc);
359
360                 if (STRING_CHANGED)
361                         pdb_set_acct_desc(account, new_string, PDB_CHANGED);
362         }
363
364         if (delta->hdr_workstations.buffer) {
365                 old_string = pdb_get_workstations(account);
366                 new_string = unistr2_static(&delta->uni_workstations);
367
368                 if (STRING_CHANGED)
369                         pdb_set_workstations(account, new_string, PDB_CHANGED);
370         }
371
372         if (delta->hdr_profile.buffer) {
373                 old_string = pdb_get_profile_path(account);
374                 new_string = unistr2_static(&delta->uni_profile);
375
376                 if (STRING_CHANGED)
377                         pdb_set_profile_path(account, new_string, PDB_CHANGED);
378         }
379
380         if (delta->hdr_parameters.buffer) {
381                 DATA_BLOB mung;
382                 old_string = pdb_get_munged_dial(account);
383                 mung.length = delta->hdr_parameters.uni_str_len;
384                 mung.data = (uint8 *) delta->uni_parameters.buffer;
385                 new_string = (mung.length == 0) ? NULL : base64_encode_data_blob(mung);
386
387                 if (STRING_CHANGED)
388                         pdb_set_munged_dial(account, new_string, PDB_CHANGED);
389         }
390
391         /* User and group sid */
392         if (pdb_get_user_rid(account) != delta->user_rid)
393                 pdb_set_user_sid_from_rid(account, delta->user_rid, PDB_CHANGED);
394         if (pdb_get_group_rid(account) != delta->group_rid)
395                 pdb_set_group_sid_from_rid(account, delta->group_rid, PDB_CHANGED);
396
397         /* Logon and password information */
398         if (!nt_time_is_zero(&delta->logon_time)) {
399                 unix_time = nt_time_to_unix(&delta->logon_time);
400                 stored_time = pdb_get_logon_time(account);
401                 if (stored_time != unix_time)
402                         pdb_set_logon_time(account, unix_time, PDB_CHANGED);
403         }
404
405         if (!nt_time_is_zero(&delta->logoff_time)) {
406                 unix_time = nt_time_to_unix(&delta->logoff_time);
407                 stored_time = pdb_get_logoff_time(account);
408                 if (stored_time != unix_time)
409                         pdb_set_logoff_time(account, unix_time,PDB_CHANGED);
410         }
411
412         /* Logon Divs */
413         if (pdb_get_logon_divs(account) != delta->logon_divs)
414                 pdb_set_logon_divs(account, delta->logon_divs, PDB_CHANGED);
415
416         /* Max Logon Hours */
417         if (delta->unknown1 != pdb_get_unknown_6(account)) {
418                 pdb_set_unknown_6(account, delta->unknown1, PDB_CHANGED);
419         }
420
421         /* Logon Hours Len */
422         if (delta->buf_logon_hrs.buf_len != pdb_get_hours_len(account)) {
423                 pdb_set_hours_len(account, delta->buf_logon_hrs.buf_len, PDB_CHANGED);
424         }
425
426         /* Logon Hours */
427         if (delta->buf_logon_hrs.buffer) {
428                 pstring oldstr, newstr;
429                 pdb_sethexhours(oldstr, pdb_get_hours(account));
430                 pdb_sethexhours(newstr, delta->buf_logon_hrs.buffer);
431                 if (!strequal(oldstr, newstr))
432                         pdb_set_hours(account, (const char *)delta->buf_logon_hrs.buffer, PDB_CHANGED);
433         }
434
435         if (pdb_get_bad_password_count(account) != delta->bad_pwd_count)
436                 pdb_set_bad_password_count(account, delta->bad_pwd_count, PDB_CHANGED);
437
438         if (pdb_get_logon_count(account) != delta->logon_count)
439                 pdb_set_logon_count(account, delta->logon_count, PDB_CHANGED);
440
441         if (!nt_time_is_zero(&delta->pwd_last_set_time)) {
442                 unix_time = nt_time_to_unix(&delta->pwd_last_set_time);
443                 stored_time = pdb_get_pass_last_set_time(account);
444                 if (stored_time != unix_time)
445                         pdb_set_pass_last_set_time(account, unix_time, PDB_CHANGED);
446         } else {
447                 /* no last set time, make it now */
448                 pdb_set_pass_last_set_time(account, time(NULL), PDB_CHANGED);
449         }
450
451 #if 0
452 /*      No kickoff time in the delta? */
453         if (!nt_time_is_zero(&delta->kickoff_time)) {
454                 unix_time = nt_time_to_unix(&delta->kickoff_time);
455                 stored_time = pdb_get_kickoff_time(account);
456                 if (stored_time != unix_time)
457                         pdb_set_kickoff_time(account, unix_time, PDB_CHANGED);
458         }
459 #endif
460
461         /* Decode hashes from password hash 
462            Note that win2000 may send us all zeros for the hashes if it doesn't 
463            think this channel is secure enough - don't set the passwords at all
464            in that case
465         */
466         if (memcmp(delta->pass.buf_lm_pwd, zero_buf, 16) != 0) {
467                 sam_pwd_hash(delta->user_rid, delta->pass.buf_lm_pwd, lm_passwd, 0);
468                 pdb_set_lanman_passwd(account, lm_passwd, PDB_CHANGED);
469         }
470
471         if (memcmp(delta->pass.buf_nt_pwd, zero_buf, 16) != 0) {
472                 sam_pwd_hash(delta->user_rid, delta->pass.buf_nt_pwd, nt_passwd, 0);
473                 pdb_set_nt_passwd(account, nt_passwd, PDB_CHANGED);
474         }
475
476         /* TODO: account expiry time */
477
478         if (pdb_get_acct_ctrl(account) != delta->acb_info)
479                 pdb_set_acct_ctrl(account, delta->acb_info, PDB_CHANGED);
480
481         pdb_set_domain(account, lp_workgroup(), PDB_CHANGED);
482
483         return NT_STATUS_OK;
484 }
485
486 static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
487 {
488         NTSTATUS nt_ret;
489         fstring account;
490         pstring add_script;
491         SAM_ACCOUNT *sam_account=NULL;
492         GROUP_MAP map;
493         struct group *grp;
494         DOM_SID user_sid;
495         DOM_SID group_sid;
496         struct passwd *passwd;
497         fstring sid_string;
498
499         fstrcpy(account, unistr2_static(&delta->uni_acct_name));
500         d_printf("Creating account: %s\n", account);
501
502         if (!NT_STATUS_IS_OK(nt_ret = pdb_init_sam(&sam_account)))
503                 return nt_ret;
504
505         if (!(passwd = Get_Pwnam(account))) {
506                 /* Create appropriate user */
507                 if (delta->acb_info & ACB_NORMAL) {
508                         pstrcpy(add_script, lp_adduser_script());
509                 } else if ( (delta->acb_info & ACB_WSTRUST) ||
510                             (delta->acb_info & ACB_SVRTRUST) ||
511                             (delta->acb_info & ACB_DOMTRUST) ) {
512                         pstrcpy(add_script, lp_addmachine_script());
513                 } else {
514                         DEBUG(1, ("Unknown user type: %s\n",
515                                   pdb_encode_acct_ctrl(delta->acb_info, NEW_PW_FORMAT_SPACE_PADDED_LEN)));
516                         nt_ret = NT_STATUS_UNSUCCESSFUL;
517                         goto done;
518                 }
519                 if (*add_script) {
520                         int add_ret;
521                         all_string_sub(add_script, "%u", account,
522                                        sizeof(account));
523                         add_ret = smbrun(add_script,NULL);
524                         DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' "
525                                  "gave %d\n", add_script, add_ret));
526                 } 
527                 
528                 /* try and find the possible unix account again */
529                 if ( !(passwd = Get_Pwnam(account)) ) {
530                         d_printf("Could not create posix account info for '%s'\n", account);
531                         nt_ret = NT_STATUS_NO_SUCH_USER;
532                         goto done;
533                 }
534         }
535         
536         sid_copy(&user_sid, get_global_sam_sid());
537         sid_append_rid(&user_sid, delta->user_rid);
538
539         DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n", sid_to_string(sid_string, &user_sid), account));
540         if (!pdb_getsampwsid(sam_account, &user_sid)) {
541                 sam_account_from_delta(sam_account, delta);
542                 DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n", 
543                           sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account)));
544                 if (!pdb_add_sam_account(sam_account)) {
545                         DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
546                                   account));
547                         return NT_STATUS_ACCESS_DENIED; 
548                 }
549         } else {
550                 sam_account_from_delta(sam_account, delta);
551                 DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n", 
552                           sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account)));
553                 if (!pdb_update_sam_account(sam_account)) {
554                         DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
555                                   account));
556                         pdb_free_sam(&sam_account);
557                         return NT_STATUS_ACCESS_DENIED; 
558                 }
559         }
560
561         group_sid = *pdb_get_group_sid(sam_account);
562
563         if (!pdb_getgrsid(&map, group_sid)) {
564                 DEBUG(0, ("Primary group of %s has no mapping!\n",
565                           pdb_get_username(sam_account)));
566         } else {
567                 if (map.gid != passwd->pw_gid) {
568                         if (!(grp = getgrgid(map.gid))) {
569                                 DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n", 
570                                           (unsigned long)map.gid, pdb_get_username(sam_account), sid_string_static(&group_sid)));
571                         } else {
572                                 smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account));
573                         }
574                 }
575         }       
576
577         if ( !passwd ) {
578                 DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n", 
579                         pdb_get_username(sam_account)));
580         }
581
582  done:
583         pdb_free_sam(&sam_account);
584         return nt_ret;
585 }
586
587 static NTSTATUS
588 fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta)
589 {
590         fstring name;
591         fstring comment;
592         struct group *grp = NULL;
593         DOM_SID group_sid;
594         fstring sid_string;
595         GROUP_MAP map;
596         BOOL insert = True;
597
598         unistr2_to_ascii(name, &delta->uni_grp_name, sizeof(name)-1);
599         unistr2_to_ascii(comment, &delta->uni_grp_desc, sizeof(comment)-1);
600
601         /* add the group to the mapping table */
602         sid_copy(&group_sid, get_global_sam_sid());
603         sid_append_rid(&group_sid, rid);
604         sid_to_string(sid_string, &group_sid);
605
606         if (pdb_getgrsid(&map, group_sid)) {
607                 if ( map.gid != -1 )
608                         grp = getgrgid(map.gid);
609                 insert = False;
610         }
611
612         if (grp == NULL) {
613                 gid_t gid;
614
615                 /* No group found from mapping, find it from its name. */
616                 if ((grp = getgrnam(name)) == NULL) {
617                 
618                         /* No appropriate group found, create one */
619                         
620                         d_printf("Creating unix group: '%s'\n", name);
621                         
622                         if (smb_create_group(name, &gid) != 0)
623                                 return NT_STATUS_ACCESS_DENIED;
624                                 
625                         if ((grp = getgrnam(name)) == NULL)
626                                 return NT_STATUS_ACCESS_DENIED;
627                 }
628         }
629
630         map.gid = grp->gr_gid;
631         map.sid = group_sid;
632         map.sid_name_use = SID_NAME_DOM_GRP;
633         fstrcpy(map.nt_name, name);
634         if (delta->hdr_grp_desc.buffer) {
635                 fstrcpy(map.comment, comment);
636         } else {
637                 fstrcpy(map.comment, "");
638         }
639
640         if (insert)
641                 pdb_add_group_mapping_entry(&map);
642         else
643                 pdb_update_group_mapping_entry(&map);
644
645         return NT_STATUS_OK;
646 }
647
648 static NTSTATUS
649 fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta)
650 {
651         int i;
652         TALLOC_CTX *t = NULL;
653         char **nt_members = NULL;
654         char **unix_members;
655         DOM_SID group_sid;
656         GROUP_MAP map;
657         struct group *grp;
658
659         if (delta->num_members == 0) {
660                 return NT_STATUS_OK;
661         }
662
663         sid_copy(&group_sid, get_global_sam_sid());
664         sid_append_rid(&group_sid, rid);
665
666         if (!get_domain_group_from_sid(group_sid, &map)) {
667                 DEBUG(0, ("Could not find global group %d\n", rid));
668                 return NT_STATUS_NO_SUCH_GROUP;
669         }
670
671         if (!(grp = getgrgid(map.gid))) {
672                 DEBUG(0, ("Could not find unix group %lu\n", (unsigned long)map.gid));
673                 return NT_STATUS_NO_SUCH_GROUP;
674         }
675
676         d_printf("Group members of %s: ", grp->gr_name);
677
678         if (!(t = talloc_init("fetch_group_mem_info"))) {
679                 DEBUG(0, ("could not talloc_init\n"));
680                 return NT_STATUS_NO_MEMORY;
681         }
682
683         nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members);
684
685         for (i=0; i<delta->num_members; i++) {
686                 NTSTATUS nt_status;
687                 SAM_ACCOUNT *member = NULL;
688                 DOM_SID member_sid;
689
690                 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) {
691                         talloc_destroy(t);
692                         return nt_status;
693                 }
694
695                 sid_copy(&member_sid, get_global_sam_sid());
696                 sid_append_rid(&member_sid, delta->rids[i]);
697
698                 if (!pdb_getsampwsid(member, &member_sid)) {
699                         DEBUG(1, ("Found bogus group member: %d (member_sid=%s group=%s)\n",
700                                   delta->rids[i], sid_string_static(&member_sid), grp->gr_name));
701                         pdb_free_sam(&member);
702                         continue;
703                 }
704
705                 if (pdb_get_group_rid(member) == rid) {
706                         d_printf("%s(primary),", pdb_get_username(member));
707                         pdb_free_sam(&member);
708                         continue;
709                 }
710                 
711                 d_printf("%s,", pdb_get_username(member));
712                 nt_members[i] = talloc_strdup(t, pdb_get_username(member));
713                 pdb_free_sam(&member);
714         }
715
716         d_printf("\n");
717
718         unix_members = grp->gr_mem;
719
720         while (*unix_members) {
721                 BOOL is_nt_member = False;
722                 for (i=0; i<delta->num_members; i++) {
723                         if (nt_members[i] == NULL) {
724                                 /* This was a primary group */
725                                 continue;
726                         }
727
728                         if (strcmp(*unix_members, nt_members[i]) == 0) {
729                                 is_nt_member = True;
730                                 break;
731                         }
732                 }
733                 if (!is_nt_member) {
734                         /* We look at a unix group member that is not
735                            an nt group member. So, remove it. NT is
736                            boss here. */
737                         smb_delete_user_group(grp->gr_name, *unix_members);
738                 }
739                 unix_members += 1;
740         }
741
742         for (i=0; i<delta->num_members; i++) {
743                 BOOL is_unix_member = False;
744
745                 if (nt_members[i] == NULL) {
746                         /* This was the primary group */
747                         continue;
748                 }
749
750                 unix_members = grp->gr_mem;
751
752                 while (*unix_members) {
753                         if (strcmp(*unix_members, nt_members[i]) == 0) {
754                                 is_unix_member = True;
755                                 break;
756                         }
757                         unix_members += 1;
758                 }
759
760                 if (!is_unix_member) {
761                         /* We look at a nt group member that is not a
762                            unix group member currently. So, add the nt
763                            group member. */
764                         smb_add_user_group(grp->gr_name, nt_members[i]);
765                 }
766         }
767         
768         talloc_destroy(t);
769         return NT_STATUS_OK;
770 }
771
772 static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta,
773                                  DOM_SID dom_sid)
774 {
775         fstring name;
776         fstring comment;
777         struct group *grp = NULL;
778         DOM_SID alias_sid;
779         fstring sid_string;
780         GROUP_MAP map;
781         BOOL insert = True;
782
783         unistr2_to_ascii(name, &delta->uni_als_name, sizeof(name)-1);
784         unistr2_to_ascii(comment, &delta->uni_als_desc, sizeof(comment)-1);
785
786         /* Find out whether the group is already mapped */
787         sid_copy(&alias_sid, &dom_sid);
788         sid_append_rid(&alias_sid, rid);
789         sid_to_string(sid_string, &alias_sid);
790
791         if (pdb_getgrsid(&map, alias_sid)) {
792                 grp = getgrgid(map.gid);
793                 insert = False;
794         }
795
796         if (grp == NULL) {
797                 gid_t gid;
798
799                 /* No group found from mapping, find it from its name. */
800                 if ((grp = getgrnam(name)) == NULL) {
801                         /* No appropriate group found, create one */
802                         d_printf("Creating unix group: '%s'\n", name);
803                         if (smb_create_group(name, &gid) != 0)
804                                 return NT_STATUS_ACCESS_DENIED;
805                         if ((grp = getgrgid(gid)) == NULL)
806                                 return NT_STATUS_ACCESS_DENIED;
807                 }
808         }
809
810         map.gid = grp->gr_gid;
811         map.sid = alias_sid;
812
813         if (sid_equal(&dom_sid, &global_sid_Builtin))
814                 map.sid_name_use = SID_NAME_WKN_GRP;
815         else
816                 map.sid_name_use = SID_NAME_ALIAS;
817
818         fstrcpy(map.nt_name, name);
819         fstrcpy(map.comment, comment);
820
821         if (insert)
822                 pdb_add_group_mapping_entry(&map);
823         else
824                 pdb_update_group_mapping_entry(&map);
825
826         return NT_STATUS_OK;
827 }
828
829 static NTSTATUS
830 fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid)
831 {
832 #if 0   /* 
833          * commented out right now after talking to Volker.  Can't
834          * do much with the membership but seemed a shame to waste
835          * somewhat working code.  Needs testing because the membership
836          * that shows up surprises me.  Also can't do much with groups
837          * in groups (e.g. Domain Admins being a member of Adminsitrators).
838          * --jerry
839          */
840         
841         int i;
842         TALLOC_CTX *t = NULL;
843         char **nt_members = NULL;
844         char **unix_members;
845         DOM_SID group_sid;
846         GROUP_MAP map;
847         struct group *grp;
848         enum SID_NAME_USE sid_type;
849
850         if (delta->num_members == 0) {
851                 return NT_STATUS_OK;
852         }
853
854         sid_copy(&group_sid, &dom_sid);
855         sid_append_rid(&group_sid, rid);
856
857         if (sid_equal(&dom_sid, &global_sid_Builtin)) {
858                 sid_type = SID_NAME_WKN_GRP;
859                 if (!get_builtin_group_from_sid(&group_sid, &map, False)) {
860                         DEBUG(0, ("Could not find builtin group %s\n", sid_string_static(&group_sid)));
861                         return NT_STATUS_NO_SUCH_GROUP;
862                 }
863         } else {
864                 sid_type = SID_NAME_ALIAS;
865                 if (!get_local_group_from_sid(&group_sid, &map, False)) {
866                         DEBUG(0, ("Could not find local group %s\n", sid_string_static(&group_sid)));
867                         return NT_STATUS_NO_SUCH_GROUP;
868                 }
869         }       
870
871         if (!(grp = getgrgid(map.gid))) {
872                 DEBUG(0, ("Could not find unix group %d\n", map.gid));
873                 return NT_STATUS_NO_SUCH_GROUP;
874         }
875
876         d_printf("Group members of %s: ", grp->gr_name);
877
878         if (!(t = talloc_init("fetch_group_mem_info"))) {
879                 DEBUG(0, ("could not talloc_init\n"));
880                 return NT_STATUS_NO_MEMORY;
881         }
882
883         nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members);
884
885         for (i=0; i<delta->num_members; i++) {
886                 NTSTATUS nt_status;
887                 SAM_ACCOUNT *member = NULL;
888                 DOM_SID member_sid;
889
890                 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) {
891                         talloc_destroy(t);
892                         return nt_status;
893                 }
894
895                 sid_copy(&member_sid, &delta->sids[i].sid);
896
897                 if (!pdb_getsampwsid(member, &member_sid)) {
898                         DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
899                                   sid_string_static(&member_sid), grp->gr_name));
900                         pdb_free_sam(&member);
901                         continue;
902                 }
903
904                 if (pdb_get_group_rid(member) == rid) {
905                         d_printf("%s(primary),", pdb_get_username(member));
906                         pdb_free_sam(&member);
907                         continue;
908                 }
909                 
910                 d_printf("%s,", pdb_get_username(member));
911                 nt_members[i] = talloc_strdup(t, pdb_get_username(member));
912                 pdb_free_sam(&member);
913         }
914
915         d_printf("\n");
916
917         unix_members = grp->gr_mem;
918
919         while (*unix_members) {
920                 BOOL is_nt_member = False;
921                 for (i=0; i<delta->num_members; i++) {
922                         if (nt_members[i] == NULL) {
923                                 /* This was a primary group */
924                                 continue;
925                         }
926
927                         if (strcmp(*unix_members, nt_members[i]) == 0) {
928                                 is_nt_member = True;
929                                 break;
930                         }
931                 }
932                 if (!is_nt_member) {
933                         /* We look at a unix group member that is not
934                            an nt group member. So, remove it. NT is
935                            boss here. */
936                         smb_delete_user_group(grp->gr_name, *unix_members);
937                 }
938                 unix_members += 1;
939         }
940
941         for (i=0; i<delta->num_members; i++) {
942                 BOOL is_unix_member = False;
943
944                 if (nt_members[i] == NULL) {
945                         /* This was the primary group */
946                         continue;
947                 }
948
949                 unix_members = grp->gr_mem;
950
951                 while (*unix_members) {
952                         if (strcmp(*unix_members, nt_members[i]) == 0) {
953                                 is_unix_member = True;
954                                 break;
955                         }
956                         unix_members += 1;
957                 }
958
959                 if (!is_unix_member) {
960                         /* We look at a nt group member that is not a
961                            unix group member currently. So, add the nt
962                            group member. */
963                         smb_add_user_group(grp->gr_name, nt_members[i]);
964                 }
965         }
966         
967         talloc_destroy(t);
968
969 #endif  /* end of fetch_alias_mem() */
970
971         return NT_STATUS_OK;
972 }
973
974 static NTSTATUS fetch_domain_info(uint32 rid, SAM_DOMAIN_INFO *delta)
975 {
976         time_t u_max_age, u_min_age, u_logout, u_lockoutreset, u_lockouttime;
977         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
978         pstring domname;
979
980         u_max_age = nt_time_to_unix_abs((NTTIME *)&delta->max_pwd_age);
981         u_min_age = nt_time_to_unix_abs((NTTIME *)&delta->min_pwd_age);
982         u_logout = nt_time_to_unix_abs((NTTIME *)&delta->force_logoff);
983         u_lockoutreset = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.reset_count);
984         u_lockouttime = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.lockout_duration);
985
986         unistr2_to_ascii(domname, &delta->uni_dom_name, sizeof(domname) - 1);
987
988         /* we don't handle BUILTIN account policies */  
989         if (!strequal(domname, get_global_sam_name())) {
990                 printf("skipping SAM_DOMAIN_INFO delta for '%s' (is not my domain)\n", domname);
991                 return NT_STATUS_OK;
992         }
993
994
995         if (!account_policy_set(AP_PASSWORD_HISTORY, delta->pwd_history_len))
996                 return nt_status;
997
998         if (!account_policy_set(AP_MIN_PASSWORD_LEN, delta->min_pwd_len))
999                 return nt_status;
1000
1001         if (!account_policy_set(AP_MAX_PASSWORD_AGE, (uint32)u_max_age))
1002                 return nt_status;
1003
1004         if (!account_policy_set(AP_MIN_PASSWORD_AGE, (uint32)u_min_age))
1005                 return nt_status;
1006
1007         if (!account_policy_set(AP_TIME_TO_LOGOUT, (uint32)u_logout))
1008                 return nt_status;
1009
1010         if (!account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, delta->account_lockout.bad_attempt_lockout))
1011                 return nt_status;
1012
1013         if (!account_policy_set(AP_RESET_COUNT_TIME, (uint32)u_lockoutreset/60))
1014                 return nt_status;
1015
1016         if (u_lockouttime != -1)
1017                 u_lockouttime /= 60;
1018
1019         if (!account_policy_set(AP_LOCK_ACCOUNT_DURATION, (uint32)u_lockouttime))
1020                 return nt_status;
1021
1022         if (!account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, delta->logon_chgpass))
1023                 return nt_status;
1024
1025         return NT_STATUS_OK;
1026 }
1027
1028
1029 static void
1030 fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta,
1031                 DOM_SID dom_sid)
1032 {
1033         switch(hdr_delta->type) {
1034         case SAM_DELTA_ACCOUNT_INFO:
1035                 fetch_account_info(hdr_delta->target_rid,
1036                                    &delta->account_info);
1037                 break;
1038         case SAM_DELTA_GROUP_INFO:
1039                 fetch_group_info(hdr_delta->target_rid,
1040                                  &delta->group_info);
1041                 break;
1042         case SAM_DELTA_GROUP_MEM:
1043                 fetch_group_mem_info(hdr_delta->target_rid,
1044                                      &delta->grp_mem_info);
1045                 break;
1046         case SAM_DELTA_ALIAS_INFO:
1047                 fetch_alias_info(hdr_delta->target_rid,
1048                                  &delta->alias_info, dom_sid);
1049                 break;
1050         case SAM_DELTA_ALIAS_MEM:
1051                 fetch_alias_mem(hdr_delta->target_rid,
1052                                 &delta->als_mem_info, dom_sid);
1053                 break;
1054         case SAM_DELTA_DOMAIN_INFO:
1055                 fetch_domain_info(hdr_delta->target_rid,
1056                                 &delta->domain_info);
1057                 break;
1058         /* The following types are recognised but not handled */
1059         case SAM_DELTA_RENAME_GROUP:
1060                 d_printf("SAM_DELTA_RENAME_GROUP not handled\n");
1061                 break;
1062         case SAM_DELTA_RENAME_USER:
1063                 d_printf("SAM_DELTA_RENAME_USER not handled\n");
1064                 break;
1065         case SAM_DELTA_RENAME_ALIAS:
1066                 d_printf("SAM_DELTA_RENAME_ALIAS not handled\n");
1067                 break;
1068         case SAM_DELTA_POLICY_INFO:
1069                 d_printf("SAM_DELTA_POLICY_INFO not handled\n");
1070                 break;
1071         case SAM_DELTA_TRUST_DOMS:
1072                 d_printf("SAM_DELTA_TRUST_DOMS not handled\n");
1073                 break;
1074         case SAM_DELTA_PRIVS_INFO:
1075                 d_printf("SAM_DELTA_PRIVS_INFO not handled\n");
1076                 break;
1077         case SAM_DELTA_SECRET_INFO:
1078                 d_printf("SAM_DELTA_SECRET_INFO not handled\n");
1079                 break;
1080         case SAM_DELTA_DELETE_GROUP:
1081                 d_printf("SAM_DELTA_DELETE_GROUP not handled\n");
1082                 break;
1083         case SAM_DELTA_DELETE_USER:
1084                 d_printf("SAM_DELTA_DELETE_USER not handled\n");
1085                 break;
1086         case SAM_DELTA_MODIFIED_COUNT:
1087                 d_printf("SAM_DELTA_MODIFIED_COUNT not handled\n");
1088                 break;
1089         default:
1090                 d_printf("Unknown delta record type %d\n", hdr_delta->type);
1091                 break;
1092         }
1093 }
1094
1095 static NTSTATUS
1096 fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds,
1097                DOM_SID dom_sid)
1098 {
1099         unsigned sync_context = 0;
1100         NTSTATUS result;
1101         int i;
1102         TALLOC_CTX *mem_ctx;
1103         SAM_DELTA_HDR *hdr_deltas;
1104         SAM_DELTA_CTR *deltas;
1105         uint32 num_deltas;
1106
1107         if (!(mem_ctx = talloc_init("fetch_database")))
1108                 return NT_STATUS_NO_MEMORY;
1109
1110         switch( db_type ) {
1111         case SAM_DATABASE_DOMAIN:
1112                 d_printf("Fetching DOMAIN database\n");
1113                 break;
1114         case SAM_DATABASE_BUILTIN:
1115                 d_printf("Fetching BUILTIN database\n");
1116                 break;
1117         case SAM_DATABASE_PRIVS:
1118                 d_printf("Fetching PRIVS databases\n");
1119                 break;
1120         default:
1121                 d_printf("Fetching unknown database type %u\n", db_type );
1122                 break;
1123         }
1124
1125         do {
1126                 result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds,
1127                                                db_type, sync_context,
1128                                                &num_deltas,
1129                                                &hdr_deltas, &deltas);
1130
1131                 if (NT_STATUS_IS_OK(result) ||
1132                     NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1133
1134                         clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred),
1135                                              ret_creds);
1136
1137                         for (i = 0; i < num_deltas; i++) {
1138                                 fetch_sam_entry(&hdr_deltas[i], &deltas[i], dom_sid);
1139                         }
1140                 } else
1141                         return result;
1142
1143                 sync_context += 1;
1144         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1145
1146         talloc_destroy(mem_ctx);
1147
1148         return result;
1149 }
1150
1151 /* dump sam database via samsync rpc calls */
1152 NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, 
1153                                const char *domain_name, 
1154                                struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1155                                int argc, const char **argv) 
1156 {
1157         NTSTATUS result;
1158         uchar trust_password[16];
1159         DOM_CRED ret_creds;
1160         fstring my_dom_sid_str;
1161         fstring rem_dom_sid_str;
1162         uint32 sec_channel;
1163
1164         ZERO_STRUCT(ret_creds);
1165
1166         if (!sid_equal(domain_sid, get_global_sam_sid())) {
1167                 d_printf("Cannot import users from %s at this time, "
1168                          "as the current domain:\n\t%s: %s\nconflicts "
1169                          "with the remote domain\n\t%s: %s\n"
1170                          "Perhaps you need to set: \n\n\tsecurity=user\n\tworkgroup=%s\n\n in your smb.conf?\n",
1171                          domain_name,
1172                          get_global_sam_name(), sid_to_string(my_dom_sid_str, 
1173                                                               get_global_sam_sid()),
1174                          domain_name, sid_to_string(rem_dom_sid_str, domain_sid),
1175                          domain_name);
1176                 return NT_STATUS_UNSUCCESSFUL;
1177         }
1178
1179         fstrcpy(cli->domain, domain_name);
1180
1181         if (!secrets_fetch_trust_account_password(domain_name,
1182                                                   trust_password, NULL,
1183                                                   &sec_channel)) {
1184                 result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1185                 d_printf("Could not retrieve domain trust secret\n");
1186                 goto fail;
1187         }
1188         
1189         result = cli_nt_establish_netlogon(cli, sec_channel, trust_password);
1190
1191         if (!NT_STATUS_IS_OK(result)) {
1192                 d_printf("Failed to setup BDC creds\n");
1193                 goto fail;
1194         }
1195
1196         result = fetch_database(cli, SAM_DATABASE_DOMAIN, &ret_creds, *domain_sid);
1197
1198         if (!NT_STATUS_IS_OK(result)) {
1199                 d_printf("Failed to fetch domain database: %s\n",
1200                          nt_errstr(result));
1201                 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED))
1202                         d_printf("Perhaps %s is a Windows 2000 native mode "
1203                                  "domain?\n", domain_name);
1204                 goto fail;
1205         }
1206
1207         result = fetch_database(cli, SAM_DATABASE_BUILTIN, &ret_creds, 
1208                                 global_sid_Builtin);
1209
1210         if (!NT_STATUS_IS_OK(result)) {
1211                 d_printf("Failed to fetch builtin database: %s\n",
1212                          nt_errstr(result));
1213                 goto fail;
1214         }
1215
1216         /* Currently we crash on PRIVS somewhere in unmarshalling */
1217         /* Dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds); */
1218
1219 fail:
1220         return result;
1221 }