r6263: Get rid of generate_wellknown_sids, they are const static and initializable
[ira/wip.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 old, new;
429                 pdb_sethexhours(old, pdb_get_hours(account));
430                 pdb_sethexhours(new, delta->buf_logon_hrs.buffer);
431                 if (!strequal(old, new))
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                 } else {
527                         DEBUG(8,("fetch_account_info: no add user/machine script.  Asking winbindd\n"));
528                         
529                         /* don't need a RID allocated since the user already has a SID */
530                         if ( !winbind_create_user( account, NULL ) )
531                                 DEBUG(4,("fetch_account_info: winbind_create_user() failed\n"));
532                 }
533                 
534                 /* try and find the possible unix account again */
535                 if ( !(passwd = Get_Pwnam(account)) ) {
536                         d_printf("Could not create posix account info for '%s'\n", account);
537                         nt_ret = NT_STATUS_NO_SUCH_USER;
538                         goto done;
539                 }
540         }
541         
542         sid_copy(&user_sid, get_global_sam_sid());
543         sid_append_rid(&user_sid, delta->user_rid);
544
545         DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n", sid_to_string(sid_string, &user_sid), account));
546         if (!pdb_getsampwsid(sam_account, &user_sid)) {
547                 sam_account_from_delta(sam_account, delta);
548                 DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n", 
549                           sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account)));
550                 if (!pdb_add_sam_account(sam_account)) {
551                         DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n",
552                                   account));
553                         return NT_STATUS_ACCESS_DENIED; 
554                 }
555         } else {
556                 sam_account_from_delta(sam_account, delta);
557                 DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n", 
558                           sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account)));
559                 if (!pdb_update_sam_account(sam_account)) {
560                         DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
561                                   account));
562                         pdb_free_sam(&sam_account);
563                         return NT_STATUS_ACCESS_DENIED; 
564                 }
565         }
566
567         group_sid = *pdb_get_group_sid(sam_account);
568
569         if (!pdb_getgrsid(&map, group_sid)) {
570                 DEBUG(0, ("Primary group of %s has no mapping!\n",
571                           pdb_get_username(sam_account)));
572         } else {
573                 if (map.gid != passwd->pw_gid) {
574                         if (!(grp = getgrgid(map.gid))) {
575                                 DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n", 
576                                           (unsigned long)map.gid, pdb_get_username(sam_account), sid_string_static(&group_sid)));
577                         } else {
578                                 smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account));
579                         }
580                 }
581         }       
582
583         if ( !passwd ) {
584                 DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n", 
585                         pdb_get_username(sam_account)));
586         }
587
588  done:
589         pdb_free_sam(&sam_account);
590         return nt_ret;
591 }
592
593 static NTSTATUS
594 fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta)
595 {
596         fstring name;
597         fstring comment;
598         struct group *grp = NULL;
599         DOM_SID group_sid;
600         fstring sid_string;
601         GROUP_MAP map;
602         BOOL insert = True;
603
604         unistr2_to_ascii(name, &delta->uni_grp_name, sizeof(name)-1);
605         unistr2_to_ascii(comment, &delta->uni_grp_desc, sizeof(comment)-1);
606
607         /* add the group to the mapping table */
608         sid_copy(&group_sid, get_global_sam_sid());
609         sid_append_rid(&group_sid, rid);
610         sid_to_string(sid_string, &group_sid);
611
612         if (pdb_getgrsid(&map, group_sid)) {
613                 if ( map.gid != -1 )
614                         grp = getgrgid(map.gid);
615                 insert = False;
616         }
617
618         if (grp == NULL) {
619                 gid_t gid;
620
621                 /* No group found from mapping, find it from its name. */
622                 if ((grp = getgrnam(name)) == NULL) {
623                 
624                         /* No appropriate group found, create one */
625                         
626                         d_printf("Creating unix group: '%s'\n", name);
627                         
628                         if (smb_create_group(name, &gid) != 0)
629                                 return NT_STATUS_ACCESS_DENIED;
630                                 
631                         if ((grp = getgrnam(name)) == NULL)
632                                 return NT_STATUS_ACCESS_DENIED;
633                 }
634         }
635
636         map.gid = grp->gr_gid;
637         map.sid = group_sid;
638         map.sid_name_use = SID_NAME_DOM_GRP;
639         fstrcpy(map.nt_name, name);
640         if (delta->hdr_grp_desc.buffer) {
641                 fstrcpy(map.comment, comment);
642         } else {
643                 fstrcpy(map.comment, "");
644         }
645
646         if (insert)
647                 pdb_add_group_mapping_entry(&map);
648         else
649                 pdb_update_group_mapping_entry(&map);
650
651         return NT_STATUS_OK;
652 }
653
654 static NTSTATUS
655 fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta)
656 {
657         int i;
658         TALLOC_CTX *t = NULL;
659         char **nt_members = NULL;
660         char **unix_members;
661         DOM_SID group_sid;
662         GROUP_MAP map;
663         struct group *grp;
664
665         if (delta->num_members == 0) {
666                 return NT_STATUS_OK;
667         }
668
669         sid_copy(&group_sid, get_global_sam_sid());
670         sid_append_rid(&group_sid, rid);
671
672         if (!get_domain_group_from_sid(group_sid, &map)) {
673                 DEBUG(0, ("Could not find global group %d\n", rid));
674                 return NT_STATUS_NO_SUCH_GROUP;
675         }
676
677         if (!(grp = getgrgid(map.gid))) {
678                 DEBUG(0, ("Could not find unix group %lu\n", (unsigned long)map.gid));
679                 return NT_STATUS_NO_SUCH_GROUP;
680         }
681
682         d_printf("Group members of %s: ", grp->gr_name);
683
684         if (!(t = talloc_init("fetch_group_mem_info"))) {
685                 DEBUG(0, ("could not talloc_init\n"));
686                 return NT_STATUS_NO_MEMORY;
687         }
688
689         nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members);
690
691         for (i=0; i<delta->num_members; i++) {
692                 NTSTATUS nt_status;
693                 SAM_ACCOUNT *member = NULL;
694                 DOM_SID member_sid;
695
696                 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) {
697                         talloc_destroy(t);
698                         return nt_status;
699                 }
700
701                 sid_copy(&member_sid, get_global_sam_sid());
702                 sid_append_rid(&member_sid, delta->rids[i]);
703
704                 if (!pdb_getsampwsid(member, &member_sid)) {
705                         DEBUG(1, ("Found bogus group member: %d (member_sid=%s group=%s)\n",
706                                   delta->rids[i], sid_string_static(&member_sid), grp->gr_name));
707                         pdb_free_sam(&member);
708                         continue;
709                 }
710
711                 if (pdb_get_group_rid(member) == rid) {
712                         d_printf("%s(primary),", pdb_get_username(member));
713                         pdb_free_sam(&member);
714                         continue;
715                 }
716                 
717                 d_printf("%s,", pdb_get_username(member));
718                 nt_members[i] = talloc_strdup(t, pdb_get_username(member));
719                 pdb_free_sam(&member);
720         }
721
722         d_printf("\n");
723
724         unix_members = grp->gr_mem;
725
726         while (*unix_members) {
727                 BOOL is_nt_member = False;
728                 for (i=0; i<delta->num_members; i++) {
729                         if (nt_members[i] == NULL) {
730                                 /* This was a primary group */
731                                 continue;
732                         }
733
734                         if (strcmp(*unix_members, nt_members[i]) == 0) {
735                                 is_nt_member = True;
736                                 break;
737                         }
738                 }
739                 if (!is_nt_member) {
740                         /* We look at a unix group member that is not
741                            an nt group member. So, remove it. NT is
742                            boss here. */
743                         smb_delete_user_group(grp->gr_name, *unix_members);
744                 }
745                 unix_members += 1;
746         }
747
748         for (i=0; i<delta->num_members; i++) {
749                 BOOL is_unix_member = False;
750
751                 if (nt_members[i] == NULL) {
752                         /* This was the primary group */
753                         continue;
754                 }
755
756                 unix_members = grp->gr_mem;
757
758                 while (*unix_members) {
759                         if (strcmp(*unix_members, nt_members[i]) == 0) {
760                                 is_unix_member = True;
761                                 break;
762                         }
763                         unix_members += 1;
764                 }
765
766                 if (!is_unix_member) {
767                         /* We look at a nt group member that is not a
768                            unix group member currently. So, add the nt
769                            group member. */
770                         smb_add_user_group(grp->gr_name, nt_members[i]);
771                 }
772         }
773         
774         talloc_destroy(t);
775         return NT_STATUS_OK;
776 }
777
778 static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta,
779                                  DOM_SID dom_sid)
780 {
781         fstring name;
782         fstring comment;
783         struct group *grp = NULL;
784         DOM_SID alias_sid;
785         fstring sid_string;
786         GROUP_MAP map;
787         BOOL insert = True;
788
789         unistr2_to_ascii(name, &delta->uni_als_name, sizeof(name)-1);
790         unistr2_to_ascii(comment, &delta->uni_als_desc, sizeof(comment)-1);
791
792         /* Find out whether the group is already mapped */
793         sid_copy(&alias_sid, &dom_sid);
794         sid_append_rid(&alias_sid, rid);
795         sid_to_string(sid_string, &alias_sid);
796
797         if (pdb_getgrsid(&map, alias_sid)) {
798                 grp = getgrgid(map.gid);
799                 insert = False;
800         }
801
802         if (grp == NULL) {
803                 gid_t gid;
804
805                 /* No group found from mapping, find it from its name. */
806                 if ((grp = getgrnam(name)) == NULL) {
807                         /* No appropriate group found, create one */
808                         d_printf("Creating unix group: '%s'\n", name);
809                         if (smb_create_group(name, &gid) != 0)
810                                 return NT_STATUS_ACCESS_DENIED;
811                         if ((grp = getgrgid(gid)) == NULL)
812                                 return NT_STATUS_ACCESS_DENIED;
813                 }
814         }
815
816         map.gid = grp->gr_gid;
817         map.sid = alias_sid;
818
819         if (sid_equal(&dom_sid, &global_sid_Builtin))
820                 map.sid_name_use = SID_NAME_WKN_GRP;
821         else
822                 map.sid_name_use = SID_NAME_ALIAS;
823
824         fstrcpy(map.nt_name, name);
825         fstrcpy(map.comment, comment);
826
827         if (insert)
828                 pdb_add_group_mapping_entry(&map);
829         else
830                 pdb_update_group_mapping_entry(&map);
831
832         return NT_STATUS_OK;
833 }
834
835 static NTSTATUS
836 fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid)
837 {
838 #if 0   /* 
839          * commented out right now after talking to Volker.  Can't
840          * do much with the membership but seemed a shame to waste
841          * somewhat working code.  Needs testing because the membership
842          * that shows up surprises me.  Also can't do much with groups
843          * in groups (e.g. Domain Admins being a member of Adminsitrators).
844          * --jerry
845          */
846         
847         int i;
848         TALLOC_CTX *t = NULL;
849         char **nt_members = NULL;
850         char **unix_members;
851         DOM_SID group_sid;
852         GROUP_MAP map;
853         struct group *grp;
854         enum SID_NAME_USE sid_type;
855
856         if (delta->num_members == 0) {
857                 return NT_STATUS_OK;
858         }
859
860         sid_copy(&group_sid, &dom_sid);
861         sid_append_rid(&group_sid, rid);
862
863         if (sid_equal(&dom_sid, &global_sid_Builtin)) {
864                 sid_type = SID_NAME_WKN_GRP;
865                 if (!get_builtin_group_from_sid(&group_sid, &map, False)) {
866                         DEBUG(0, ("Could not find builtin group %s\n", sid_string_static(&group_sid)));
867                         return NT_STATUS_NO_SUCH_GROUP;
868                 }
869         } else {
870                 sid_type = SID_NAME_ALIAS;
871                 if (!get_local_group_from_sid(&group_sid, &map, False)) {
872                         DEBUG(0, ("Could not find local group %s\n", sid_string_static(&group_sid)));
873                         return NT_STATUS_NO_SUCH_GROUP;
874                 }
875         }       
876
877         if (!(grp = getgrgid(map.gid))) {
878                 DEBUG(0, ("Could not find unix group %d\n", map.gid));
879                 return NT_STATUS_NO_SUCH_GROUP;
880         }
881
882         d_printf("Group members of %s: ", grp->gr_name);
883
884         if (!(t = talloc_init("fetch_group_mem_info"))) {
885                 DEBUG(0, ("could not talloc_init\n"));
886                 return NT_STATUS_NO_MEMORY;
887         }
888
889         nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members);
890
891         for (i=0; i<delta->num_members; i++) {
892                 NTSTATUS nt_status;
893                 SAM_ACCOUNT *member = NULL;
894                 DOM_SID member_sid;
895
896                 if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) {
897                         talloc_destroy(t);
898                         return nt_status;
899                 }
900
901                 sid_copy(&member_sid, &delta->sids[i].sid);
902
903                 if (!pdb_getsampwsid(member, &member_sid)) {
904                         DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
905                                   sid_string_static(&member_sid), grp->gr_name));
906                         pdb_free_sam(&member);
907                         continue;
908                 }
909
910                 if (pdb_get_group_rid(member) == rid) {
911                         d_printf("%s(primary),", pdb_get_username(member));
912                         pdb_free_sam(&member);
913                         continue;
914                 }
915                 
916                 d_printf("%s,", pdb_get_username(member));
917                 nt_members[i] = talloc_strdup(t, pdb_get_username(member));
918                 pdb_free_sam(&member);
919         }
920
921         d_printf("\n");
922
923         unix_members = grp->gr_mem;
924
925         while (*unix_members) {
926                 BOOL is_nt_member = False;
927                 for (i=0; i<delta->num_members; i++) {
928                         if (nt_members[i] == NULL) {
929                                 /* This was a primary group */
930                                 continue;
931                         }
932
933                         if (strcmp(*unix_members, nt_members[i]) == 0) {
934                                 is_nt_member = True;
935                                 break;
936                         }
937                 }
938                 if (!is_nt_member) {
939                         /* We look at a unix group member that is not
940                            an nt group member. So, remove it. NT is
941                            boss here. */
942                         smb_delete_user_group(grp->gr_name, *unix_members);
943                 }
944                 unix_members += 1;
945         }
946
947         for (i=0; i<delta->num_members; i++) {
948                 BOOL is_unix_member = False;
949
950                 if (nt_members[i] == NULL) {
951                         /* This was the primary group */
952                         continue;
953                 }
954
955                 unix_members = grp->gr_mem;
956
957                 while (*unix_members) {
958                         if (strcmp(*unix_members, nt_members[i]) == 0) {
959                                 is_unix_member = True;
960                                 break;
961                         }
962                         unix_members += 1;
963                 }
964
965                 if (!is_unix_member) {
966                         /* We look at a nt group member that is not a
967                            unix group member currently. So, add the nt
968                            group member. */
969                         smb_add_user_group(grp->gr_name, nt_members[i]);
970                 }
971         }
972         
973         talloc_destroy(t);
974
975 #endif  /* end of fetch_alias_mem() */
976
977         return NT_STATUS_OK;
978 }
979
980 static NTSTATUS fetch_domain_info(uint32 rid, SAM_DOMAIN_INFO *delta)
981 {
982         time_t u_max_age, u_min_age, u_logout, u_lockoutreset, u_lockouttime;
983         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
984         pstring domname;
985
986         u_max_age = nt_time_to_unix_abs((NTTIME *)&delta->max_pwd_age);
987         u_min_age = nt_time_to_unix_abs((NTTIME *)&delta->min_pwd_age);
988         u_logout = nt_time_to_unix_abs((NTTIME *)&delta->force_logoff);
989         u_lockoutreset = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.reset_count);
990         u_lockouttime = nt_time_to_unix_abs((NTTIME *)&delta->account_lockout.lockout_duration);
991
992         unistr2_to_ascii(domname, &delta->uni_dom_name, sizeof(domname) - 1);
993
994         /* we don't handle BUILTIN account policies */  
995         if (!strequal(domname, get_global_sam_name())) {
996                 printf("skipping SAM_DOMAIN_INFO delta for '%s' (is not my domain)\n", domname);
997                 return NT_STATUS_OK;
998         }
999
1000
1001         if (!account_policy_set(AP_PASSWORD_HISTORY, delta->pwd_history_len))
1002                 return nt_status;
1003
1004         if (!account_policy_set(AP_MIN_PASSWORD_LEN, delta->min_pwd_len))
1005                 return nt_status;
1006
1007         if (!account_policy_set(AP_MAX_PASSWORD_AGE, (uint32)u_max_age))
1008                 return nt_status;
1009
1010         if (!account_policy_set(AP_MIN_PASSWORD_AGE, (uint32)u_min_age))
1011                 return nt_status;
1012
1013         if (!account_policy_set(AP_TIME_TO_LOGOUT, (uint32)u_logout))
1014                 return nt_status;
1015
1016         if (!account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, delta->account_lockout.bad_attempt_lockout))
1017                 return nt_status;
1018
1019         if (!account_policy_set(AP_RESET_COUNT_TIME, (uint32)u_lockoutreset/60))
1020                 return nt_status;
1021
1022         if (u_lockouttime != -1)
1023                 u_lockouttime /= 60;
1024
1025         if (!account_policy_set(AP_LOCK_ACCOUNT_DURATION, (uint32)u_lockouttime))
1026                 return nt_status;
1027
1028         if (!account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, delta->logon_chgpass))
1029                 return nt_status;
1030
1031         return NT_STATUS_OK;
1032 }
1033
1034
1035 static void
1036 fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta,
1037                 DOM_SID dom_sid)
1038 {
1039         switch(hdr_delta->type) {
1040         case SAM_DELTA_ACCOUNT_INFO:
1041                 fetch_account_info(hdr_delta->target_rid,
1042                                    &delta->account_info);
1043                 break;
1044         case SAM_DELTA_GROUP_INFO:
1045                 fetch_group_info(hdr_delta->target_rid,
1046                                  &delta->group_info);
1047                 break;
1048         case SAM_DELTA_GROUP_MEM:
1049                 fetch_group_mem_info(hdr_delta->target_rid,
1050                                      &delta->grp_mem_info);
1051                 break;
1052         case SAM_DELTA_ALIAS_INFO:
1053                 fetch_alias_info(hdr_delta->target_rid,
1054                                  &delta->alias_info, dom_sid);
1055                 break;
1056         case SAM_DELTA_ALIAS_MEM:
1057                 fetch_alias_mem(hdr_delta->target_rid,
1058                                 &delta->als_mem_info, dom_sid);
1059                 break;
1060         case SAM_DELTA_DOMAIN_INFO:
1061                 fetch_domain_info(hdr_delta->target_rid,
1062                                 &delta->domain_info);
1063                 break;
1064         /* The following types are recognised but not handled */
1065         case SAM_DELTA_RENAME_GROUP:
1066                 d_printf("SAM_DELTA_RENAME_GROUP not handled\n");
1067                 break;
1068         case SAM_DELTA_RENAME_USER:
1069                 d_printf("SAM_DELTA_RENAME_USER not handled\n");
1070                 break;
1071         case SAM_DELTA_RENAME_ALIAS:
1072                 d_printf("SAM_DELTA_RENAME_ALIAS not handled\n");
1073                 break;
1074         case SAM_DELTA_POLICY_INFO:
1075                 d_printf("SAM_DELTA_POLICY_INFO not handled\n");
1076                 break;
1077         case SAM_DELTA_TRUST_DOMS:
1078                 d_printf("SAM_DELTA_TRUST_DOMS not handled\n");
1079                 break;
1080         case SAM_DELTA_PRIVS_INFO:
1081                 d_printf("SAM_DELTA_PRIVS_INFO not handled\n");
1082                 break;
1083         case SAM_DELTA_SECRET_INFO:
1084                 d_printf("SAM_DELTA_SECRET_INFO not handled\n");
1085                 break;
1086         case SAM_DELTA_DELETE_GROUP:
1087                 d_printf("SAM_DELTA_DELETE_GROUP not handled\n");
1088                 break;
1089         case SAM_DELTA_DELETE_USER:
1090                 d_printf("SAM_DELTA_DELETE_USER not handled\n");
1091                 break;
1092         case SAM_DELTA_MODIFIED_COUNT:
1093                 d_printf("SAM_DELTA_MODIFIED_COUNT not handled\n");
1094                 break;
1095         default:
1096                 d_printf("Unknown delta record type %d\n", hdr_delta->type);
1097                 break;
1098         }
1099 }
1100
1101 static NTSTATUS
1102 fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds,
1103                DOM_SID dom_sid)
1104 {
1105         unsigned sync_context = 0;
1106         NTSTATUS result;
1107         int i;
1108         TALLOC_CTX *mem_ctx;
1109         SAM_DELTA_HDR *hdr_deltas;
1110         SAM_DELTA_CTR *deltas;
1111         uint32 num_deltas;
1112
1113         if (!(mem_ctx = talloc_init("fetch_database")))
1114                 return NT_STATUS_NO_MEMORY;
1115
1116         switch( db_type ) {
1117         case SAM_DATABASE_DOMAIN:
1118                 d_printf("Fetching DOMAIN database\n");
1119                 break;
1120         case SAM_DATABASE_BUILTIN:
1121                 d_printf("Fetching BUILTIN database\n");
1122                 break;
1123         case SAM_DATABASE_PRIVS:
1124                 d_printf("Fetching PRIVS databases\n");
1125                 break;
1126         default:
1127                 d_printf("Fetching unknown database type %u\n", db_type );
1128                 break;
1129         }
1130
1131         do {
1132                 result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds,
1133                                                db_type, sync_context,
1134                                                &num_deltas,
1135                                                &hdr_deltas, &deltas);
1136
1137                 if (NT_STATUS_IS_OK(result) ||
1138                     NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
1139
1140                         clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred),
1141                                              ret_creds);
1142
1143                         for (i = 0; i < num_deltas; i++) {
1144                                 fetch_sam_entry(&hdr_deltas[i], &deltas[i], dom_sid);
1145                         }
1146                 } else
1147                         return result;
1148
1149                 sync_context += 1;
1150         } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
1151
1152         talloc_destroy(mem_ctx);
1153
1154         return result;
1155 }
1156
1157 /* dump sam database via samsync rpc calls */
1158 NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, 
1159                                const char *domain_name, 
1160                                struct cli_state *cli, TALLOC_CTX *mem_ctx, 
1161                                int argc, const char **argv) 
1162 {
1163         NTSTATUS result;
1164         uchar trust_password[16];
1165         DOM_CRED ret_creds;
1166         fstring my_dom_sid_str;
1167         fstring rem_dom_sid_str;
1168         uint32 sec_channel;
1169
1170         ZERO_STRUCT(ret_creds);
1171
1172         if (!sid_equal(domain_sid, get_global_sam_sid())) {
1173                 d_printf("Cannot import users from %s at this time, "
1174                          "as the current domain:\n\t%s: %s\nconflicts "
1175                          "with the remote domain\n\t%s: %s\n"
1176                          "Perhaps you need to set: \n\n\tsecurity=user\n\tworkgroup=%s\n\n in your smb.conf?\n",
1177                          domain_name,
1178                          get_global_sam_name(), sid_to_string(my_dom_sid_str, 
1179                                                               get_global_sam_sid()),
1180                          domain_name, sid_to_string(rem_dom_sid_str, domain_sid),
1181                          domain_name);
1182                 return NT_STATUS_UNSUCCESSFUL;
1183         }
1184
1185         fstrcpy(cli->domain, domain_name);
1186
1187         if (!secrets_fetch_trust_account_password(domain_name,
1188                                                   trust_password, NULL,
1189                                                   &sec_channel)) {
1190                 result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1191                 d_printf("Could not retrieve domain trust secret\n");
1192                 goto fail;
1193         }
1194         
1195         result = cli_nt_establish_netlogon(cli, sec_channel, trust_password);
1196
1197         if (!NT_STATUS_IS_OK(result)) {
1198                 d_printf("Failed to setup BDC creds\n");
1199                 goto fail;
1200         }
1201
1202         result = fetch_database(cli, SAM_DATABASE_DOMAIN, &ret_creds, *domain_sid);
1203
1204         if (!NT_STATUS_IS_OK(result)) {
1205                 d_printf("Failed to fetch domain database: %s\n",
1206                          nt_errstr(result));
1207                 if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED))
1208                         d_printf("Perhaps %s is a Windows 2000 native mode "
1209                                  "domain?\n", domain_name);
1210                 goto fail;
1211         }
1212
1213         result = fetch_database(cli, SAM_DATABASE_BUILTIN, &ret_creds, 
1214                                 global_sid_Builtin);
1215
1216         if (!NT_STATUS_IS_OK(result)) {
1217                 d_printf("Failed to fetch builtin database: %s\n",
1218                          nt_errstr(result));
1219                 goto fail;
1220         }
1221
1222         /* Currently we crash on PRIVS somewhere in unmarshalling */
1223         /* Dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds); */
1224
1225 fail:
1226         return result;
1227 }