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