LsaLookupNames client call (first used as lookupnames command in rpcclient).
[samba.git] / source3 / passdb / passdb.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
28 /*
29  * NOTE. All these functions are abstracted into a structure
30  * that points to the correct function for the selected database. JRA.
31  *
32  * NOTE.  for the get/mod/add functions, there are two sets of functions.
33  * one supports struct sam_passwd, the other supports struct smb_passwd.
34  * for speed optimisation it is best to support both these sets.
35  * 
36  * it is, however, optional to support one set but not the other: there
37  * is conversion-capability built in to passdb.c, and run-time error
38  * detection for when neither are supported.
39  * 
40  * password database writers are recommended to implement the sam_passwd
41  * functions in a first pass, as struct sam_passwd contains more
42  * information, needed by the NT Domain support.
43  * 
44  * an API writer is expected to create either one set (struct smb_passwd) or
45  * the other (struct sam_passwd) OR both, and optionally also to write display
46  * info routines * (struct sam_disp_info).  functions which the API writer
47  * chooses NOT to write must be wrapped in conversion functions (pwdb_x_to_y)
48  * such that API users can call any function and still get valid results.
49  *
50  * the password API does NOT fill in the gaps if you set an API function
51  * to NULL: it will deliberately attempt to call the NULL function.
52  *
53  */
54
55 static struct passdb_ops *pwdb_ops;
56
57 /***************************************************************
58  Initialise the password db operations.
59 ***************************************************************/
60
61 BOOL initialise_password_db(void)
62 {
63   if (pwdb_ops)
64   {
65     return True;
66   }
67
68 #ifdef WITH_NISPLUS
69   pwdb_ops =  nisplus_initialise_password_db();
70 #elif defined(WITH_LDAP)
71   pwdb_ops = ldap_initialise_password_db();
72 #elif defined(USE_SMBPASS_DB)
73   pwdb_ops = file_initialise_password_db();
74 #endif 
75
76   return (pwdb_ops != NULL);
77 }
78
79 /*
80  * Functions that return/manipulate a struct smb_passwd.
81  */
82
83 /************************************************************************
84  Utility function to search smb passwd by rid.  
85 *************************************************************************/
86
87 struct smb_passwd *iterate_getsmbpwrid(uint32 user_rid)
88 {
89         return iterate_getsmbpwuid(pwdb_user_rid_to_uid(user_rid));
90 }
91
92 /************************************************************************
93  Utility function to search smb passwd by uid.  use this if your database
94  does not have search facilities.
95 *************************************************************************/
96
97 struct smb_passwd *iterate_getsmbpwuid(uid_t smb_userid)
98 {
99         struct smb_passwd *pwd = NULL;
100         void *fp = NULL;
101
102         DEBUG(10, ("search by smb_userid: %x\n", (int)smb_userid));
103
104         /* Open the smb password database - not for update. */
105         fp = startsmbpwent(False);
106
107         if (fp == NULL)
108         {
109                 DEBUG(0, ("unable to open smb password database.\n"));
110                 return NULL;
111         }
112
113         while ((pwd = getsmbpwent(fp)) != NULL && pwd->smb_userid != smb_userid)
114         {
115         }
116
117         if (pwd != NULL)
118         {
119                 DEBUG(10, ("found by smb_userid: %x\n", (int)smb_userid));
120         }
121
122         endsmbpwent(fp);
123         return pwd;
124 }
125
126 /************************************************************************
127  Utility function to search smb passwd by name.  use this if your database
128  does not have search facilities.
129 *************************************************************************/
130
131 struct smb_passwd *iterate_getsmbpwnam(char *name)
132 {
133         struct smb_passwd *pwd = NULL;
134         void *fp = NULL;
135
136         DEBUG(10, ("search by name: %s\n", name));
137
138         /* Open the sam password file - not for update. */
139         fp = startsmbpwent(False);
140
141         if (fp == NULL)
142         {
143                 DEBUG(0, ("unable to open smb password database.\n"));
144                 return NULL;
145         }
146
147         while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->smb_name, name))
148         {
149         }
150
151         if (pwd != NULL)
152         {
153                 DEBUG(10, ("found by name: %s\n", name));
154         }
155
156         endsmbpwent(fp);
157         return pwd;
158 }
159
160 /***************************************************************
161  Start to enumerate the smb or sam passwd list. Returns a void pointer
162  to ensure no modification outside this module.
163
164  Note that currently it is being assumed that a pointer returned
165  from this function may be used to enumerate struct sam_passwd
166  entries as well as struct smb_passwd entries. This may need
167  to change. JRA.
168
169 ****************************************************************/
170
171 void *startsmbpwent(BOOL update)
172 {
173   return pwdb_ops->startsmbpwent(update);
174 }
175
176 /***************************************************************
177  End enumeration of the smb or sam passwd list.
178
179  Note that currently it is being assumed that a pointer returned
180  from this function may be used to enumerate struct sam_passwd
181  entries as well as struct smb_passwd entries. This may need
182  to change. JRA.
183
184 ****************************************************************/
185
186 void endsmbpwent(void *vp)
187 {
188   pwdb_ops->endsmbpwent(vp);
189 }
190
191 /*************************************************************************
192  Routine to return the next entry in the smb passwd list.
193  *************************************************************************/
194
195 struct smb_passwd *getsmbpwent(void *vp)
196 {
197         return pwdb_ops->getsmbpwent(vp);
198 }
199
200 /************************************************************************
201  Routine to add an entry to the smb passwd file.
202 *************************************************************************/
203
204 BOOL add_smbpwd_entry(struct smb_passwd *newpwd)
205 {
206         return pwdb_ops->add_smbpwd_entry(newpwd);
207 }
208
209 /************************************************************************
210  Routine to search the smb passwd file for an entry matching the username.
211  and then modify its password entry. We can't use the startsampwent()/
212  getsampwent()/endsampwent() interfaces here as we depend on looking
213  in the actual file to decide how much room we have to write data.
214  override = False, normal
215  override = True, override XXXXXXXX'd out password or NO PASS
216 ************************************************************************/
217
218 BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
219 {
220         return pwdb_ops->mod_smbpwd_entry(pwd, override);
221 }
222
223 /************************************************************************
224  Routine to search smb passwd by name.
225 *************************************************************************/
226
227 struct smb_passwd *getsmbpwnam(char *name)
228 {
229         return pwdb_ops->getsmbpwnam(name);
230 }
231
232 /************************************************************************
233  Routine to search smb passwd by user rid.
234 *************************************************************************/
235
236 struct smb_passwd *getsmbpwrid(uint32 user_rid)
237 {
238         return pwdb_ops->getsmbpwrid(user_rid);
239 }
240
241 /************************************************************************
242  Routine to search smb passwd by uid.
243 *************************************************************************/
244
245 struct smb_passwd *getsmbpwuid(uid_t smb_userid)
246 {
247         return pwdb_ops->getsmbpwuid(smb_userid);
248 }
249
250 /*
251  * Functions that manupulate a struct sam_passwd.
252  */
253
254 /************************************************************************
255  Utility function to search sam passwd by name.  use this if your database
256  does not have search facilities.
257 *************************************************************************/
258
259 struct sam_passwd *iterate_getsam21pwnam(char *name)
260 {
261         struct sam_passwd *pwd = NULL;
262         void *fp = NULL;
263
264         DEBUG(10, ("search by name: %s\n", name));
265
266         /* Open the smb password database - not for update. */
267         fp = startsmbpwent(False);
268
269         if (fp == NULL)
270         {
271                 DEBUG(0, ("unable to open sam password database.\n"));
272                 return NULL;
273         }
274
275         while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name))
276         {
277                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
278         }
279
280         if (pwd != NULL)
281         {
282                 DEBUG(10, ("found by name: %s\n", name));
283         }
284
285         endsmbpwent(fp);
286         return pwd;
287 }
288
289 /************************************************************************
290  Utility function to search sam passwd by rid.  use this if your database
291  does not have search facilities.
292
293  search capability by both rid and uid are needed as the rid <-> uid
294  mapping may be non-monotonic.  
295
296 *************************************************************************/
297
298 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
299 {
300         struct sam_passwd *pwd = NULL;
301         void *fp = NULL;
302
303         DEBUG(10, ("search by rid: %x\n", rid));
304
305         /* Open the smb password file - not for update. */
306         fp = startsmbpwent(False);
307
308         if (fp == NULL)
309         {
310                 DEBUG(0, ("unable to open sam password database.\n"));
311                 return NULL;
312         }
313
314         while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
315         {
316                 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
317         }
318
319         if (pwd != NULL)
320         {
321                 DEBUG(10, ("found by user_rid: %x\n", rid));
322         }
323
324         endsmbpwent(fp);
325         return pwd;
326 }
327
328 /************************************************************************
329  Utility function to search sam passwd by uid.  use this if your database
330  does not have search facilities.
331
332  search capability by both rid and uid are needed as the rid <-> uid
333  mapping may be non-monotonic.  
334
335 *************************************************************************/
336
337 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
338 {
339         struct sam_passwd *pwd = NULL;
340         void *fp = NULL;
341
342         DEBUG(10, ("search by uid: %x\n", (int)uid));
343
344         /* Open the smb password file - not for update. */
345         fp = startsmbpwent(False);
346
347         if (fp == NULL)
348         {
349                 DEBUG(0, ("unable to open sam password database.\n"));
350                 return NULL;
351         }
352
353         while ((pwd = getsam21pwent(fp)) != NULL && pwd->smb_userid != uid)
354         {
355         }
356
357         if (pwd != NULL)
358         {
359                 DEBUG(10, ("found by smb_userid: %x\n", (int)uid));
360         }
361
362         endsmbpwent(fp);
363         return pwd;
364 }
365
366 /*************************************************************************
367  Routine to return a display info structure, by rid
368  *************************************************************************/
369 struct sam_disp_info *getsamdisprid(uint32 rid)
370 {
371         return pwdb_ops->getsamdisprid(rid);
372 }
373
374 /*************************************************************************
375  Routine to return the next entry in the sam passwd list.
376  *************************************************************************/
377
378 struct sam_passwd *getsam21pwent(void *vp)
379 {
380         return pwdb_ops->getsam21pwent(vp);
381 }
382
383
384 /************************************************************************
385  Routine to search sam passwd by name.
386 *************************************************************************/
387
388 struct sam_passwd *getsam21pwnam(char *name)
389 {
390         return pwdb_ops->getsam21pwnam(name);
391 }
392
393 /************************************************************************
394  Routine to search sam passwd by rid.  
395 *************************************************************************/
396
397 struct sam_passwd *getsam21pwrid(uint32 rid)
398 {
399         return pwdb_ops->getsam21pwrid(rid);
400 }
401
402
403 /**********************************************************
404  **********************************************************
405
406  utility routines which are likely to be useful to all password
407  databases
408
409  **********************************************************
410  **********************************************************/
411
412 /*************************************************************
413  initialises a struct sam_disp_info.
414  **************************************************************/
415
416 static void pwdb_init_dispinfo(struct sam_disp_info *user)
417 {
418         if (user == NULL) return;
419         bzero(user, sizeof(*user));
420 }
421
422 /*************************************************************
423  initialises a struct smb_passwd.
424  **************************************************************/
425
426 void pwdb_init_smb(struct smb_passwd *user)
427 {
428         if (user == NULL) return;
429         bzero(user, sizeof(*user));
430         user->pass_last_set_time    = (time_t)-1;
431 }
432
433 /*************************************************************
434  initialises a struct sam_passwd.
435  **************************************************************/
436 void pwdb_init_sam(struct sam_passwd *user)
437 {
438         if (user == NULL) return;
439         bzero(user, sizeof(*user));
440         user->logon_time            = (time_t)-1;
441         user->logoff_time           = (time_t)-1;
442         user->kickoff_time          = (time_t)-1;
443         user->pass_last_set_time    = (time_t)-1;
444         user->pass_can_change_time  = (time_t)-1;
445         user->pass_must_change_time = (time_t)-1;
446 }
447
448 /*************************************************************************
449  Routine to return the next entry in the sam passwd list.
450  *************************************************************************/
451
452 struct sam_disp_info *pwdb_sam_to_dispinfo(struct sam_passwd *user)
453 {
454         static struct sam_disp_info disp_info;
455
456         if (user == NULL) return NULL;
457
458         pwdb_init_dispinfo(&disp_info);
459
460         disp_info.smb_name  = user->smb_name;
461         disp_info.full_name = user->full_name;
462         disp_info.user_rid  = user->user_rid;
463
464         return &disp_info;
465 }
466
467 /*************************************************************
468  converts a sam_passwd structure to a smb_passwd structure.
469  **************************************************************/
470
471 struct smb_passwd *pwdb_sam_to_smb(struct sam_passwd *user)
472 {
473         static struct smb_passwd pw_buf;
474
475         if (user == NULL) return NULL;
476
477         pwdb_init_smb(&pw_buf);
478
479         pw_buf.smb_userid         = user->smb_userid;
480         pw_buf.smb_name           = user->smb_name;
481         pw_buf.smb_passwd         = user->smb_passwd;
482         pw_buf.smb_nt_passwd      = user->smb_nt_passwd;
483         pw_buf.acct_ctrl          = user->acct_ctrl;
484         pw_buf.pass_last_set_time = user->pass_last_set_time;
485
486         return &pw_buf;
487 }
488
489
490 /*************************************************************
491  converts a smb_passwd structure to a sam_passwd structure.
492  **************************************************************/
493
494 struct sam_passwd *pwdb_smb_to_sam(struct smb_passwd *user)
495 {
496         static struct sam_passwd pw_buf;
497
498         if (user == NULL) return NULL;
499
500         pwdb_init_sam(&pw_buf);
501
502         pw_buf.smb_userid         = user->smb_userid;
503         pw_buf.smb_name           = user->smb_name;
504         pw_buf.smb_passwd         = user->smb_passwd;
505         pw_buf.smb_nt_passwd      = user->smb_nt_passwd;
506         pw_buf.acct_ctrl          = user->acct_ctrl;
507         pw_buf.pass_last_set_time = user->pass_last_set_time;
508
509         return &pw_buf;
510 }
511
512 /**********************************************************
513  Encode the account control bits into a string.
514  length = length of string to encode into (including terminating
515  null). length *MUST BE MORE THAN 2* !
516  **********************************************************/
517
518 char *pwdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
519 {
520         static fstring acct_str;
521         size_t i = 0;
522
523         acct_str[i++] = '[';
524
525         if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
526         if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
527         if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
528         if (acct_ctrl & ACB_TEMPDUP  ) acct_str[i++] = 'T'; 
529         if (acct_ctrl & ACB_NORMAL   ) acct_str[i++] = 'U';
530         if (acct_ctrl & ACB_MNS      ) acct_str[i++] = 'M';
531         if (acct_ctrl & ACB_WSTRUST  ) acct_str[i++] = 'W';
532         if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
533         if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
534         if (acct_ctrl & ACB_PWNOEXP  ) acct_str[i++] = 'X';
535         if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
536
537         for ( ; i < length - 2 ; i++ )
538         {
539                 acct_str[i] = ' ';
540         }
541
542         i = length - 2;
543         acct_str[i++] = ']';
544         acct_str[i++] = '\0';
545
546         return acct_str;
547 }     
548
549 /**********************************************************
550  Decode the account control bits from a string.
551
552  this function breaks coding standards minimum line width of 80 chars.
553  reason: vertical line-up code clarity - all case statements fit into
554  15 lines, which is more important.
555  **********************************************************/
556
557 uint16 pwdb_decode_acct_ctrl(const char *p)
558 {
559         uint16 acct_ctrl = 0;
560         BOOL finished = False;
561
562         /*
563          * Check if the account type bits have been encoded after the
564          * NT password (in the form [NDHTUWSLXI]).
565          */
566
567         if (*p != '[') return 0;
568
569         for (p++; *p && !finished; p++)
570         {
571                 switch (*p)
572                 {
573                         case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
574                         case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
575                         case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
576                         case 'T': { acct_ctrl |= ACB_TEMPDUP  ; break; /* 'T'emp account. */ } 
577                         case 'U': { acct_ctrl |= ACB_NORMAL   ; break; /* 'U'ser account (normal). */ } 
578                         case 'M': { acct_ctrl |= ACB_MNS      ; break; /* 'M'NS logon user account. What is this ? */ } 
579                         case 'W': { acct_ctrl |= ACB_WSTRUST  ; break; /* 'W'orkstation account. */ } 
580                         case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ } 
581                         case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ } 
582                         case 'X': { acct_ctrl |= ACB_PWNOEXP  ; break; /* No 'X'piry on password */ } 
583                         case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
584                         case ' ': { break; }
585                         case ':':
586                         case '\n':
587                         case '\0': 
588                         case ']':
589                         default:  { finished = True; }
590                 }
591         }
592
593         return acct_ctrl;
594 }
595
596 /*******************************************************************
597  gets password-database-format time from a string.
598  ********************************************************************/
599
600 static time_t get_time_from_string(const char *p)
601 {
602         int i;
603
604         for (i = 0; i < 8; i++)
605         {
606                 if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF)))
607                 {
608                         break;
609                 }
610         }
611         if (i == 8)
612         {
613                 /*
614                  * p points at 8 characters of hex digits - 
615                  * read into a time_t as the seconds since
616                  * 1970 that the password was last changed.
617                  */
618                 return (time_t)strtol(p, NULL, 16);
619         }
620         return (time_t)-1;
621 }
622
623 /*******************************************************************
624  gets password last set time
625  ********************************************************************/
626
627 time_t pwdb_get_last_set_time(const char *p)
628 {
629         if (*p && StrnCaseCmp(p, "LCT-", 4))
630         {
631                 return get_time_from_string(p + 4);
632         }
633         return (time_t)-1;
634 }
635
636
637 /*******************************************************************
638  sets password-database-format time in a string.
639  ********************************************************************/
640 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
641 {
642         slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
643 }
644
645 /*******************************************************************
646  sets logon time
647  ********************************************************************/
648 void pwdb_set_logon_time(char *p, int max_len, time_t t)
649 {
650         set_time_in_string(p, max_len, "LNT", t);
651 }
652
653 /*******************************************************************
654  sets logoff time
655  ********************************************************************/
656 void pwdb_set_logoff_time(char *p, int max_len, time_t t)
657 {
658         set_time_in_string(p, max_len, "LOT", t);
659 }
660
661 /*******************************************************************
662  sets kickoff time
663  ********************************************************************/
664 void pwdb_set_kickoff_time(char *p, int max_len, time_t t)
665 {
666         set_time_in_string(p, max_len, "KOT", t);
667 }
668
669 /*******************************************************************
670  sets password can change time
671  ********************************************************************/
672 void pwdb_set_can_change_time(char *p, int max_len, time_t t)
673 {
674         set_time_in_string(p, max_len, "CCT", t);
675 }
676
677 /*******************************************************************
678  sets password last set time
679  ********************************************************************/
680 void pwdb_set_must_change_time(char *p, int max_len, time_t t)
681 {
682         set_time_in_string(p, max_len, "MCT", t);
683 }
684
685 /*******************************************************************
686  sets password last set time
687  ********************************************************************/
688 void pwdb_set_last_set_time(char *p, int max_len, time_t t)
689 {
690         set_time_in_string(p, max_len, "LCT", t);
691 }
692
693
694 /*************************************************************
695  Routine to set 32 hex password characters from a 16 byte array.
696 **************************************************************/
697 void pwdb_sethexpwd(char *p, char *pwd, uint16 acct_ctrl)
698 {
699         if (pwd != NULL)
700         {
701                 int i;
702                 for (i = 0; i < 16; i++)
703                 {
704                         slprintf(&p[i*2], 33, "%02X", pwd[i]);
705                 }
706         }
707         else
708         {
709                 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
710                 {
711                         safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
712                 }
713                 else
714                 {
715                         safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
716                 }
717         }
718 }
719
720 /*************************************************************
721  Routine to get the 32 hex characters and turn them
722  into a 16 byte array.
723 **************************************************************/
724 BOOL pwdb_gethexpwd(char *p, char *pwd)
725 {
726         return strhex_to_str(pwd, 32, p) == 16;
727 }
728
729 /*******************************************************************
730  converts UNIX uid to an NT User RID. NOTE: IS SOMETHING SPECIFIC TO SAMBA
731  ********************************************************************/
732 uid_t pwdb_user_rid_to_uid(uint32 user_rid)
733 {
734         uid_t uid = (uid_t)(((user_rid & (~RID_TYPE_USER))- 1000)/RID_MULTIPLIER);
735         return uid;
736 }
737
738 /*******************************************************************
739  converts UNIX uid to an NT User RID. NOTE: IS SOMETHING SPECIFIC TO SAMBA
740  ********************************************************************/
741 uint32 pwdb_uid_to_user_rid(uid_t uid)
742 {
743         uint32 user_rid = (((((uint32)uid)*RID_MULTIPLIER) + 1000) | RID_TYPE_USER);
744         return user_rid;
745 }
746
747 /*******************************************************************
748  converts NT Group RID to a UNIX uid. NOTE: IS SOMETHING SPECIFIC TO SAMBA
749  ********************************************************************/
750 uint32 pwdb_gid_to_group_rid(gid_t gid)
751 {
752         uint32 grp_rid = (((((uint32)gid)*RID_MULTIPLIER) + 1000) | RID_TYPE_GROUP);
753         return grp_rid;
754 }
755
756 /*******************************************************************
757  converts NT Group RID to a UNIX uid. NOTE: IS SOMETHING SPECIFIC TO SAMBA
758  ********************************************************************/
759 gid_t pwdb_group_rid_to_gid(uint32 group_rid)
760 {
761         gid_t gid = (gid_t)(((group_rid & (~RID_TYPE_GROUP))- 1000)/RID_MULTIPLIER);
762         return gid;
763 }
764
765 /*******************************************************************
766  converts UNIX gid to an NT Alias RID. NOTE: IS SOMETHING SPECIFIC TO SAMBA
767  ********************************************************************/
768 uint32 pwdb_gid_to_alias_rid(gid_t gid)
769 {
770         uint32 alias_rid = (((((uint32)gid)*RID_MULTIPLIER) + 1000) | RID_TYPE_ALIAS);
771         return alias_rid;
772 }
773
774 /*******************************************************************
775  converts NT Alias RID to a UNIX uid. NOTE: IS SOMETHING SPECIFIC TO SAMBA
776  ********************************************************************/
777 gid_t pwdb_alias_rid_to_gid(uint32 alias_rid)
778 {
779         gid_t gid = (gid_t)(((alias_rid & (~RID_TYPE_ALIAS))- 1000)/RID_MULTIPLIER);
780         return gid;
781 }
782
783 /*******************************************************************
784  Decides if a RID is a well known RID.
785  ********************************************************************/
786 static BOOL pwdb_rid_is_well_known(uint32 rid)
787 {
788         return (rid < 1000);
789 }
790
791 /*******************************************************************
792  determines a rid's type.  NOTE: THIS IS SOMETHING SPECIFIC TO SAMBA
793  ********************************************************************/
794 static uint32 pwdb_rid_type(uint32 rid)
795 {
796         /* lkcl i understand that NT attaches an enumeration to a RID
797          * such that it can be identified as either a user, group etc
798          * type: SID_ENUM_TYPE.
799          */
800         if (pwdb_rid_is_well_known(rid))
801         {
802                 /*
803                  * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
804                  * and DOMAIN_USER_RID_GUEST.
805                  */
806                 if (rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
807                 {
808                         return RID_TYPE_USER;
809                 }
810                 if (DOMAIN_GROUP_RID_ADMINS <= rid && rid <= DOMAIN_GROUP_RID_GUESTS)
811                 {
812                         return RID_TYPE_GROUP;
813                 }
814                 if (BUILTIN_ALIAS_RID_ADMINS <= rid && rid <= BUILTIN_ALIAS_RID_REPLICATOR)
815                 {
816                         return RID_TYPE_ALIAS;
817                 }
818         }
819         return (rid & RID_TYPE_MASK);
820 }
821
822 /*******************************************************************
823  checks whether rid is a user rid.  NOTE: THIS IS SOMETHING SPECIFIC TO SAMBA
824  ********************************************************************/
825 BOOL pwdb_rid_is_user(uint32 rid)
826 {
827         return pwdb_rid_type(rid) == RID_TYPE_USER;
828 }
829