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