first pass at updating head branch to be to be the same as the SAMBA_2_0 branch
[bbaumbach/samba-autobuild/.git] / source3 / passdb / sampassdb.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Password and authentication handling
5    Copyright (C) Jeremy Allison 1996-1998
6    Copyright (C) Luke Kenneth Casson Leighton 1996-1998
7       
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "nterr.h"
25
26 extern int DEBUGLEVEL;
27 extern DOM_SID global_sam_sid;
28
29 /*
30  * NOTE. All these functions are abstracted into a structure
31  * that points to the correct function for the selected database. JRA.
32  *
33  * NOTE.  for the get/mod/add functions, there are two sets of functions.
34  * one supports struct sam_passwd, the other supports struct smb_passwd.
35  * for speed optimisation it is best to support both these sets.
36  * 
37  * it is, however, optional to support one set but not the other: there
38  * is conversion-capability built in to passdb.c, and run-time error
39  * detection for when neither are supported.
40  * 
41  * password database writers are recommended to implement the sam_passwd
42  * functions in a first pass, as struct sam_passwd contains more
43  * information, needed by the NT Domain support.
44  * 
45  * an API writer is expected to create either one set (struct smb_passwd) or
46  * the other (struct sam_passwd) OR both, and optionally also to write display
47  * info routines * (struct sam_disp_info).  functions which the API writer
48  * chooses NOT to write must be wrapped in conversion functions (pwdb_x_to_y)
49  * such that API users can call any function and still get valid results.
50  *
51  * the password API does NOT fill in the gaps if you set an API function
52  * to NULL: it will deliberately attempt to call the NULL function.
53  *
54  */
55
56 static struct sam_passdb_ops *pwdb_ops;
57
58 /***************************************************************
59  Initialise the password db operations.
60 ***************************************************************/
61
62 BOOL initialise_sam_password_db(void)
63 {
64   if (pwdb_ops)
65   {
66     return True;
67   }
68
69 #ifdef WITH_NISPLUS
70   pwdb_ops =  nisplus_initialise_sam_password_db();
71 #elif defined(WITH_LDAP)
72   pwdb_ops = ldap_initialise_sam_password_db();
73 #elif defined(HAVE_MYSQL_H) && defined(WITH_MYSQLSAM)
74   pwdb_ops = mysql_initialise_sam_password_db();
75 #elif defined(USE_SMBPASS_DB)
76   pwdb_ops = file_initialise_sam_password_db();
77 #endif 
78
79   return (pwdb_ops != NULL);
80 }
81
82 /*
83  * Functions that return/manipulate a struct sam_passwd.
84  */
85
86 /***************************************************************
87  Start to enumerate the smb or sam passwd list. Returns a void pointer
88  to ensure no modification outside this module.
89
90  Note that currently it is being assumed that a pointer returned
91  from this function may be used to enumerate struct sam_passwd
92  entries as well as struct smb_passwd entries. This may need
93  to change. JRA.
94
95 ****************************************************************/
96
97 void *startsam21pwent(BOOL update)
98 {
99   return pwdb_ops->startsam21pwent(update);
100 }
101
102 /***************************************************************
103  End enumeration of the sam passwd list.
104
105  Note that currently it is being assumed that a pointer returned
106  from this function may be used to enumerate struct sam_passwd
107  entries as well as struct smb_passwd entries. This may need
108  to change. JRA.
109
110 ****************************************************************/
111
112 void endsam21pwent(void *vp)
113 {
114   pwdb_ops->endsam21pwent(vp);
115 }
116
117 /*************************************************************************
118  Routine to return the next entry in the smb passwd list.
119  *************************************************************************/
120
121 struct sam_passwd *getsam21pwent(void *vp)
122 {
123         return pwdb_sam_map_names(pwdb_ops->getsam21pwent(vp));
124 }
125
126 /************************************************************************
127  Routine to search the smb passwd file for an entry matching the username.
128  and then modify its password entry. We can't use the startsampwent()/
129  getsampwent()/endsampwent() interfaces here as we depend on looking
130  in the actual file to decide how much room we have to write data.
131  override = False, normal
132  override = True, override XXXXXXXX'd out password or NO PASS
133 ************************************************************************/
134
135 BOOL mod_sam21pwd_entry(struct sam_passwd* pwd, BOOL override)
136 {
137         struct sam_passwd *mapped;
138
139         DEBUG(10,("mod_sam21pwd_entry: unix user %s rid %d\n", 
140                 pwd->unix_name, pwd->user_rid));
141
142         mapped = pwdb_sam_map_names(pwd);
143         if (mapped != NULL)
144         {
145                 return pwdb_ops->mod_sam21pwd_entry(mapped, override);
146         }
147         return False;
148 }
149
150 /************************************************************************
151  Utility function to search sam passwd by name.  use this if your database
152  does not have search facilities.
153 *************************************************************************/
154
155 struct sam_passwd *iterate_getsam21pwntnam(const char *ntname)
156 {
157         fstring nt_name;
158         struct sam_passwd *pwd = NULL;
159         void *fp = NULL;
160
161         DEBUG(10, ("search by name: %s\n", ntname));
162
163         fstrcpy(nt_name, ntname);
164
165         /* Open the smb password database - not for update. */
166         fp = startsmbpwent(False);
167
168         if (fp == NULL)
169         {
170                 DEBUG(0, ("unable to open sam password database.\n"));
171                 return NULL;
172         }
173
174         while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->nt_name, nt_name))
175         {
176                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->nt_name, pwd->user_rid));
177         }
178
179         if (pwd != NULL)
180         {
181                 DEBUG(10, ("found by name: %s\n", nt_name));
182         }
183
184         endsmbpwent(fp);
185         return pwd;
186 }
187
188 /************************************************************************
189  Utility function to search sam passwd by rid.  use this if your database
190  does not have search facilities.
191
192  search capability by both rid and uid are needed as the rid <-> uid
193  mapping may be non-monotonic.  
194
195 *************************************************************************/
196
197 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
198 {
199         struct sam_passwd *pwd = NULL;
200         void *fp = NULL;
201
202         DEBUG(10, ("search by rid: %x\n", rid));
203
204         /* Open the smb password file - not for update. */
205         fp = startsmbpwent(False);
206
207         if (fp == NULL)
208         {
209                 DEBUG(0, ("unable to open sam password database.\n"));
210                 return NULL;
211         }
212
213         while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
214         {
215                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->nt_name, pwd->user_rid));
216         }
217
218         if (pwd != NULL)
219         {
220                 DEBUG(10, ("found by user_rid: %x\n", rid));
221         }
222
223         endsmbpwent(fp);
224         return pwd;
225 }
226
227 /************************************************************************
228  Utility function to search sam passwd by uid.  use this if your database
229  does not have search facilities.
230
231  search capability by both rid and uid are needed as the rid <-> uid
232  mapping may be non-monotonic.  
233
234 *************************************************************************/
235
236 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
237 {
238         struct sam_passwd *pwd = NULL;
239         void *fp = NULL;
240
241         DEBUG(10, ("search by uid: %x\n", (int)uid));
242
243         /* Open the smb password file - not for update. */
244         fp = startsmbpwent(False);
245
246         if (fp == NULL)
247         {
248                 DEBUG(0, ("unable to open sam password database.\n"));
249                 return NULL;
250         }
251
252         while ((pwd = getsam21pwent(fp)) != NULL && pwd->unix_uid != uid)
253         {
254         }
255
256         if (pwd != NULL)
257         {
258                 DEBUG(10, ("found by unix_uid: %x\n", (int)uid));
259         }
260
261         endsmbpwent(fp);
262         return pwd;
263 }
264
265 /*************************************************************************
266  Routine to return a display info structure, by rid
267  *************************************************************************/
268 struct sam_disp_info *getsamdisprid(uint32 rid)
269 {
270         return pwdb_ops->getsamdisprid(rid);
271 }
272
273 /************************************************************************
274  Routine to search sam passwd by name.
275 *************************************************************************/
276
277 struct sam_passwd *getsam21pwntnam(const char *name)
278 {
279         return pwdb_sam_map_names(pwdb_ops->getsam21pwntnam(name));
280 }
281
282 /************************************************************************
283  Routine to search sam passwd by rid.  
284 *************************************************************************/
285
286 struct sam_passwd *getsam21pwrid(uint32 rid)
287 {
288         return pwdb_sam_map_names(pwdb_ops->getsam21pwrid(rid));
289 }
290
291
292 /**********************************************************
293  **********************************************************
294
295  utility routines which are likely to be useful to all password
296  databases
297
298  **********************************************************
299  **********************************************************/
300
301 /*************************************************************
302  initialises a struct sam_disp_info.
303  **************************************************************/
304
305 static void pwdb_init_dispinfo(struct sam_disp_info *user)
306 {
307         if (user == NULL) return;
308         bzero(user, sizeof(*user));
309         user->user_rid = 0xffffffff;
310 }
311
312 /*************************************************************
313  initialises a struct sam_passwd.
314  **************************************************************/
315 void pwdb_init_sam(struct sam_passwd *user)
316 {
317         if (user == NULL) return;
318         bzero(user, sizeof(*user));
319
320         init_nt_time(&user->logon_time);
321         init_nt_time(&user->logoff_time);
322         init_nt_time(&user->kickoff_time);
323         init_nt_time(&user->pass_last_set_time);
324         init_nt_time(&user->pass_can_change_time);
325         init_nt_time(&user->pass_must_change_time);
326
327         user->unix_uid = (uid_t)-1;
328         user->unix_gid = (gid_t)-1;
329         user->user_rid  = 0xffffffff;
330         user->group_rid = 0xffffffff;
331 }
332
333 /*************************************************************************
334  Routine to return the next entry in the sam passwd list.
335  *************************************************************************/
336
337 struct sam_disp_info *pwdb_sam_to_dispinfo(struct sam_passwd *user)
338 {
339         static struct sam_disp_info disp_info;
340
341         if (user == NULL) return NULL;
342
343         pwdb_init_dispinfo(&disp_info);
344
345         disp_info.nt_name   = user->nt_name;
346         disp_info.full_name = user->full_name;
347         disp_info.user_rid  = user->user_rid;
348
349         return &disp_info;
350 }
351
352 static void select_name(fstring *string, char **name, const UNISTR2 *from)
353 {
354         if (from->buffer != 0)
355         {
356                 unistr2_to_ascii(*string, from, sizeof(*string));
357                 *name = *string;
358         }
359 }
360
361 /*************************************************************
362  copies a sam passwd.
363  **************************************************************/
364 void copy_id23_to_sam_passwd(struct sam_passwd *to, const SAM_USER_INFO_23 *from)
365 {
366         static fstring nt_name;
367         static fstring full_name;
368         static fstring home_dir;
369         static fstring dir_drive;
370         static fstring logon_script;
371         static fstring profile_path;
372         static fstring acct_desc;
373         static fstring workstations;
374         static fstring unknown_str;
375         static fstring munged_dial;
376
377         if (from == NULL || to == NULL) return;
378
379         to->logon_time = from->logon_time;
380         to->logoff_time = from->logoff_time;
381         to->kickoff_time = from->kickoff_time;
382         to->pass_last_set_time = from->pass_last_set_time;
383         to->pass_can_change_time = from->pass_can_change_time;
384         to->pass_must_change_time = from->pass_must_change_time;
385
386         select_name(&nt_name     , &to->nt_name     , &from->uni_user_name   );
387         select_name(&full_name   , &to->full_name   , &from->uni_full_name   );
388         select_name(&home_dir    , &to->home_dir    , &from->uni_home_dir    );
389         select_name(&dir_drive   , &to->dir_drive   , &from->uni_dir_drive   );
390         select_name(&logon_script, &to->logon_script, &from->uni_logon_script);
391         select_name(&profile_path, &to->profile_path, &from->uni_profile_path);
392         select_name(&acct_desc   , &to->acct_desc   , &from->uni_acct_desc   );
393         select_name(&workstations, &to->workstations, &from->uni_workstations);
394         select_name(&unknown_str , &to->unknown_str , &from->uni_unknown_str );
395         select_name(&munged_dial , &to->munged_dial , &from->uni_munged_dial );
396
397         to->unix_uid = (uid_t)-1;
398         to->unix_gid = (gid_t)-1;
399         to->user_rid = from->user_rid;
400         to->group_rid = from->group_rid;
401
402         to->smb_passwd = NULL;
403         to->smb_nt_passwd = NULL;
404
405         to->acct_ctrl = from->acb_info;
406         to->unknown_3 = from->unknown_3;
407
408         to->logon_divs = from->logon_divs;
409         to->hours_len = from->logon_hrs.len;
410         memcpy(to->hours, from->logon_hrs.hours, MAX_HOURS_LEN);
411
412         to->unknown_5 = from->unknown_5;
413         to->unknown_6 = from->unknown_6;
414 }
415
416
417 /*************************************************************
418  copies a sam passwd.
419  **************************************************************/
420 void copy_sam_passwd(struct sam_passwd *to, const struct sam_passwd *from)
421 {
422         static fstring nt_name;
423         static fstring unix_name;
424         static fstring full_name;
425         static fstring home_dir;
426         static fstring dir_drive;
427         static fstring logon_script;
428         static fstring profile_path;
429         static fstring acct_desc;
430         static fstring workstations;
431         static fstring unknown_str;
432         static fstring munged_dial;
433
434         if (from == NULL || to == NULL) return;
435
436         memcpy(to, from, sizeof(*from));
437
438         if (from->nt_name != NULL)
439         {
440                 fstrcpy(nt_name  , from->nt_name);
441                 to->nt_name = nt_name;
442         }
443         else if (to->nt_name != NULL)
444         {
445                 fstrcpy(nt_name  , to->nt_name);
446                 to->nt_name = nt_name;
447         }
448
449         if (from->unix_name != NULL)
450         {
451                 fstrcpy(unix_name, from->unix_name);
452                 to->unix_name = unix_name;
453         }
454         else if (to->unix_name != NULL)
455         {
456                 fstrcpy(unix_name, to->unix_name);
457                 to->unix_name = unix_name;
458         }
459
460         if (from->full_name != NULL)
461         {
462                 fstrcpy(full_name, from->full_name);
463                 to->full_name = full_name;
464         }
465         else if (to->full_name != NULL)
466         {
467                 fstrcpy(full_name, to->full_name);
468                 to->full_name = full_name;
469         }
470
471         if (from->home_dir != NULL)
472         {
473                 fstrcpy(home_dir  , from->home_dir);
474                 to->home_dir = home_dir;
475         }
476         else if (to->home_dir != NULL)
477         {
478                 fstrcpy(home_dir  , to->home_dir);
479                 to->home_dir = home_dir;
480         }
481
482         if (from->dir_drive != NULL)
483         {
484                 fstrcpy(dir_drive  , from->dir_drive);
485                 to->dir_drive = dir_drive;
486         }
487         else if (to->dir_drive != NULL)
488         {
489                 fstrcpy(dir_drive  , to->dir_drive);
490                 to->dir_drive = dir_drive;
491         }
492
493         if (from->logon_script != NULL)
494         {
495                 fstrcpy(logon_script  , from->logon_script);
496                 to->logon_script = logon_script;
497         }
498         else if (to->logon_script != NULL)
499         {
500                 fstrcpy(logon_script  , to->logon_script);
501                 to->logon_script = logon_script;
502         }
503
504         if (from->profile_path != NULL)
505         {
506                 fstrcpy(profile_path  , from->profile_path);
507                 to->profile_path = profile_path;
508         }
509         else if (to->profile_path != NULL)
510         {
511                 fstrcpy(profile_path  , to->profile_path);
512                 to->profile_path = profile_path;
513         }
514
515         if (from->acct_desc != NULL)
516         {
517                 fstrcpy(acct_desc  , from->acct_desc);
518                 to->acct_desc = acct_desc;
519         }
520         else if (to->acct_desc != NULL)
521         {
522                 fstrcpy(acct_desc  , to->acct_desc);
523                 to->acct_desc = acct_desc;
524         }
525
526         if (from->workstations != NULL)
527         {
528                 fstrcpy(workstations  , from->workstations);
529                 to->workstations = workstations;
530         }
531         else if (to->workstations != NULL)
532         {
533                 fstrcpy(workstations  , to->workstations);
534                 to->workstations = workstations;
535         }
536
537         if (from->unknown_str != NULL)
538         {
539                 fstrcpy(unknown_str  , from->unknown_str);
540                 to->unknown_str = unknown_str;
541         }
542         else if (to->unknown_str != NULL)
543         {
544                 fstrcpy(unknown_str  , to->unknown_str);
545                 to->unknown_str = unknown_str;
546         }
547
548         if (from->munged_dial != NULL)
549         {
550                 fstrcpy(munged_dial  , from->munged_dial);
551                 to->munged_dial = munged_dial;
552         }
553         else if (to->munged_dial != NULL)
554         {
555                 fstrcpy(munged_dial  , to->munged_dial);
556                 to->munged_dial = munged_dial;
557         }
558 }
559
560
561 /*************************************************************
562  converts a sam_passwd structure to a smb_passwd structure.
563  **************************************************************/
564 struct smb_passwd *pwdb_sam_to_smb(struct sam_passwd *user)
565 {
566         static struct smb_passwd pw_buf;
567         static fstring nt_name;
568         static fstring unix_name;
569
570         if (user == NULL) return NULL;
571
572         pwdb_init_smb(&pw_buf);
573
574         if (user->nt_name != NULL)
575         {
576                 fstrcpy(nt_name  , user->nt_name);
577                 pw_buf.nt_name = nt_name;
578         }
579         if (user->unix_name != NULL)
580         {
581                 fstrcpy(unix_name, user->unix_name);
582                 pw_buf.unix_name = unix_name;
583         }
584         pw_buf.unix_uid           = user->unix_uid;
585         pw_buf.user_rid           = user->user_rid;
586         pw_buf.smb_passwd         = user->smb_passwd;
587         pw_buf.smb_nt_passwd      = user->smb_nt_passwd;
588         pw_buf.acct_ctrl          = user->acct_ctrl;
589         pw_buf.pass_last_set_time = nt_time_to_unix(&user->pass_last_set_time);
590
591         return &pw_buf;
592 }
593
594
595 /*************************************************************
596  converts a smb_passwd structure to a sam_passwd structure.
597  **************************************************************/
598
599 struct sam_passwd *pwdb_smb_to_sam(struct smb_passwd *user)
600 {
601         static struct sam_passwd pw_buf;
602         struct passwd *pass=NULL;
603         static fstring nt_name;
604         static fstring unix_name;
605         static pstring unix_gecos;
606
607         if (user == NULL) return NULL;
608
609         pwdb_init_sam(&pw_buf);
610
611         if (user->nt_name != NULL)
612         {
613                 fstrcpy(nt_name  , user->nt_name);
614                 pw_buf.nt_name = nt_name;
615         }
616         if (user->unix_name != NULL)
617         {
618                 fstrcpy(unix_name, user->unix_name);
619                 pw_buf.unix_name = unix_name;
620         }
621         pw_buf.unix_uid           = user->unix_uid;
622         pw_buf.user_rid           = user->user_rid;
623         pw_buf.smb_passwd         = user->smb_passwd;
624         pw_buf.smb_nt_passwd      = user->smb_nt_passwd;
625         pw_buf.acct_ctrl          = user->acct_ctrl;
626                 
627         pass = hashed_getpwnam(unix_name);
628         if (pass != NULL)
629         {
630                 pstrcpy(unix_gecos, pass->pw_gecos);
631                 pw_buf.full_name=unix_gecos;
632         }
633
634         if ( user->pass_last_set_time != (time_t)-1 )
635         {
636                 unix_to_nt_time(&pw_buf.pass_last_set_time, user->pass_last_set_time);
637                 unix_to_nt_time(&pw_buf.pass_can_change_time, user->pass_last_set_time);
638         }
639
640         return &pw_buf;
641 }
642
643 static BOOL trust_account_warning_done = False;
644
645 /*************************************************************
646  fills in missing details.  one set of details _must_ exist.
647  **************************************************************/
648 struct sam_passwd *pwdb_sam_map_names(struct sam_passwd *sam)
649 {
650         DOM_NAME_MAP gmep;
651         BOOL found = False;
652         DOM_SID sid;
653         static fstring unix_name;
654         static fstring nt_name;
655
656         /*
657          * name details
658          */
659
660         if (sam == NULL)
661         {
662                 DEBUG(10,("pwdb_sam_map_names: NULL\n"));
663                 return NULL;
664         }
665
666         DEBUG(10,("pwdb_sam_map_names: unix %s nt %s unix %d nt%d\n",
667                    sam->unix_name != NULL ? sam->unix_name : "NULL",
668                    sam->nt_name   != NULL ? sam->nt_name   : "NULL",
669                    sam->unix_uid, sam->user_rid));
670
671         if (!found && sam->unix_name != NULL)
672         {
673                 found = lookupsmbpwnam(sam->unix_name, &gmep);
674         }
675         if (!found && sam->unix_uid  != (uid_t)-1)
676         {
677                 found = lookupsmbpwuid(sam->unix_uid , &gmep);
678         }
679         if (!found && sam->user_rid != 0xffffffff)
680         {
681                 sid_copy(&sid, &global_sam_sid);
682                 sid_append_rid(&sid, sam->user_rid);
683                 found = lookupsmbpwsid  (&sid        , &gmep);
684         }
685         if (!found && sam->nt_name  != NULL)
686         {
687                 found = lookupsmbpwntnam(sam->nt_name, &gmep);
688         }
689
690         if (!found)
691         {
692                 return NULL;
693         }
694
695         if (!sid_front_equal(&global_sam_sid, &gmep.sid))
696         {
697                 return NULL;
698         }
699
700         fstrcpy(unix_name, gmep.unix_name);
701         fstrcpy(nt_name  , gmep.nt_name  );
702         if (sam->unix_name == NULL      ) sam->unix_name = unix_name;
703         if (sam->nt_name   == NULL      ) sam->nt_name   = nt_name  ;
704         if (sam->unix_uid  == (uid_t)-1 ) sam->unix_uid  = (uid_t)gmep.unix_id;
705         if (sam->user_rid  == 0xffffffff) sid_split_rid(&gmep.sid, &sam->user_rid);
706
707         DEBUG(10,("pwdb_sam_map_name: found unix user %s nt %s uid %d rid 0x%x\n",
708                    sam->unix_name, sam->nt_name, sam->unix_uid, sam->user_rid));
709
710         /*
711          * group details
712          */
713
714         found = False;
715
716         if (sam->unix_gid != (gid_t)-1 && sam->group_rid != 0xffffffff)
717         {
718                 return sam;
719         }
720
721         if (sam->unix_gid == (gid_t)-1 && sam->group_rid == 0xffffffff)
722         {
723                 struct passwd *pass = hashed_getpwnam(unix_name);
724                 if (pass != NULL)
725                 {
726                         sam->unix_gid = pass->pw_gid;
727                 }
728                 else
729                 {
730                         DEBUG(0,("pwdb_sam_map_names: no unix password entry for %s\n",
731                                   unix_name));
732                 }
733         }
734
735         if (!found && sam->unix_gid  != (gid_t)-1)
736         {
737                 found = lookupsmbgrpgid(sam->unix_gid , &gmep);
738         }
739         if (!found && sam->group_rid != 0xffffffff)
740         {
741                 sid_copy(&sid, &global_sam_sid);
742                 sid_append_rid(&sid, sam->group_rid);
743                 found = lookupsmbgrpsid(&sid        , &gmep);
744         }
745
746         if (!found)
747         {
748                 if (IS_BITS_SET_SOME(sam->acct_ctrl, ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST))
749                 {
750                         if (!trust_account_warning_done)
751                         {
752                                 trust_account_warning_done = True;
753                                 DEBUG(0, ("\
754 pwdb_sam_map_names: your unix password database appears to have difficulties\n\
755 resolving trust account %s, probably because it ends in a '$'.\n\
756 you will get this warning only once (for all trust accounts)\n", unix_name));
757                         }
758                         /*
759                          * oh, dear.
760                          */
761                         if (sam->unix_gid != (gid_t)-1)
762                         {
763                                 sam->unix_gid = (gid_t)-1;
764                         }
765                         sam->group_rid = DOMAIN_GROUP_RID_USERS;
766
767                         return sam;
768                 }
769                 else
770                 {
771                         DEBUG(0, ("pwdb_sam_map_names: could not find Primary Group for %s\n",
772                                    unix_name));
773                         return NULL;
774                 }
775         }
776
777         if (!sid_front_equal(&global_sam_sid, &gmep.sid))
778         {
779                 fstring sid_str;
780                 sid_to_string(sid_str, &gmep.sid);
781                 DEBUG(0,("UNIX User %s Primary Group is in the wrong domain! %s\n",
782                           sam->unix_name, sid_str));
783                 return NULL;
784         }
785
786         if (sam->unix_gid  == (gid_t)-1 ) sam->unix_gid  = (gid_t)gmep.unix_id;
787         if (sam->group_rid == 0xffffffff) sid_split_rid(&gmep.sid, &sam->group_rid);
788
789         DEBUG(10,("pwdb_sam_map_name: found gid %d and group rid 0x%x for unix user %s\n",
790                    sam->unix_gid, sam->group_rid, sam->unix_name));
791
792         return sam;
793 }