2 Unix SMB/Netbios implementation.
4 Password and authentication handling
5 Copyright (C) Jeremy Allison 1996-1998
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1998
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.
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.
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.
26 extern int DEBUGLEVEL;
29 * This is set on startup - it defines the SID for this
33 DOM_SID global_machine_sid;
36 * NOTE. All these functions are abstracted into a structure
37 * that points to the correct function for the selected database. JRA.
39 * NOTE. for the get/mod/add functions, there are two sets of functions.
40 * one supports struct sam_passwd, the other supports struct smb_passwd.
41 * for speed optimisation it is best to support both these sets.
43 * it is, however, optional to support one set but not the other: there
44 * is conversion-capability built in to passdb.c, and run-time error
45 * detection for when neither are supported.
47 * password database writers are recommended to implement the sam_passwd
48 * functions in a first pass, as struct sam_passwd contains more
49 * information, needed by the NT Domain support.
51 * a full example set of derivative functions are listed below. an API
52 * writer is expected to cut/paste these into their module, replace
53 * either one set (struct smb_passwd) or the other (struct sam_passwd)
54 * OR both, and optionally also to write display info routines
55 * (struct sam_disp_info). lkcl
59 static struct passdb_ops *pdb_ops;
61 /***************************************************************
62 Initialize the password db operations.
63 ***************************************************************/
65 BOOL initialize_password_db(void)
73 pdb_ops = nisplus_initialize_password_db();
74 #elif defined(WITH_LDAP)
75 pdb_ops = ldap_initialize_password_db();
77 pdb_ops = file_initialize_password_db();
80 return (pdb_ops != NULL);
84 * Functions that return/manipulate a struct smb_passwd.
87 /************************************************************************
88 Utility function to search smb passwd by uid. use this if your database
89 does not have search facilities.
90 *************************************************************************/
92 struct smb_passwd *iterate_getsmbpwuid(uid_t smb_userid)
94 struct smb_passwd *pwd = NULL;
97 DEBUG(10, ("search by smb_userid: %x\n", (int)smb_userid));
99 /* Open the smb password database - not for update. */
100 fp = startsmbpwent(False);
104 DEBUG(0, ("unable to open smb password database.\n"));
108 while ((pwd = getsmbpwent(fp)) != NULL && pwd->smb_userid != smb_userid)
113 DEBUG(10, ("found by smb_userid: %x\n", (int)smb_userid));
120 /************************************************************************
121 Utility function to search smb passwd by name. use this if your database
122 does not have search facilities.
123 *************************************************************************/
125 struct smb_passwd *iterate_getsmbpwnam(char *name)
127 struct smb_passwd *pwd = NULL;
130 DEBUG(10, ("search by name: %s\n", name));
132 /* Open the sam password file - not for update. */
133 fp = startsmbpwent(False);
137 DEBUG(0, ("unable to open smb password database.\n"));
141 while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->smb_name, name))
146 DEBUG(10, ("found by name: %s\n", name));
153 /***************************************************************
154 Start to enumerate the smb or sam passwd list. Returns a void pointer
155 to ensure no modification outside this module.
157 Note that currently it is being assumed that a pointer returned
158 from this function may be used to enumerate struct sam_passwd
159 entries as well as struct smb_passwd entries. This may need
162 ****************************************************************/
164 void *startsmbpwent(BOOL update)
166 return pdb_ops->startsmbpwent(update);
169 /***************************************************************
170 End enumeration of the smb or sam passwd list.
172 Note that currently it is being assumed that a pointer returned
173 from this function may be used to enumerate struct sam_passwd
174 entries as well as struct smb_passwd entries. This may need
177 ****************************************************************/
179 void endsmbpwent(void *vp)
181 pdb_ops->endsmbpwent(vp);
184 /*************************************************************************
185 Routine to return the next entry in the smb passwd list.
186 *************************************************************************/
188 struct smb_passwd *getsmbpwent(void *vp)
190 return pdb_ops->getsmbpwent(vp);
193 /************************************************************************
194 Routine to add an entry to the smb passwd file.
195 *************************************************************************/
197 BOOL add_smbpwd_entry(struct smb_passwd *newpwd)
199 return pdb_ops->add_smbpwd_entry(newpwd);
202 /************************************************************************
203 Routine to search the smb passwd file for an entry matching the username.
204 and then modify its password entry. We can't use the startsampwent()/
205 getsampwent()/endsampwent() interfaces here as we depend on looking
206 in the actual file to decide how much room we have to write data.
207 override = False, normal
208 override = True, override XXXXXXXX'd out password or NO PASS
209 ************************************************************************/
211 BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
213 return pdb_ops->mod_smbpwd_entry(pwd, override);
216 /************************************************************************
217 Routine to search smb passwd by name.
218 *************************************************************************/
220 struct smb_passwd *getsmbpwnam(char *name)
222 return pdb_ops->getsmbpwnam(name);
225 /************************************************************************
226 Routine to search smb passwd by uid.
227 *************************************************************************/
229 struct smb_passwd *getsmbpwuid(uid_t smb_userid)
231 return pdb_ops->getsmbpwuid(smb_userid);
235 * Functions that manupulate a struct sam_passwd.
238 /************************************************************************
239 Utility function to search sam passwd by name. use this if your database
240 does not have search facilities.
241 *************************************************************************/
243 struct sam_passwd *iterate_getsam21pwnam(char *name)
245 struct sam_passwd *pwd = NULL;
248 DEBUG(10, ("search by name: %s\n", name));
250 /* Open the smb password database - not for update. */
251 fp = startsmbpwent(False);
255 DEBUG(0, ("unable to open sam password database.\n"));
259 while ((pwd = getsam21pwent(fp)) != NULL && !strequal(pwd->smb_name, name))
261 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
266 DEBUG(10, ("found by name: %s\n", name));
273 /************************************************************************
274 Utility function to search sam passwd by rid. use this if your database
275 does not have search facilities.
277 search capability by both rid and uid are needed as the rid <-> uid
278 mapping may be non-monotonic.
280 *************************************************************************/
282 struct sam_passwd *iterate_getsam21pwrid(uint32 rid)
284 struct sam_passwd *pwd = NULL;
287 DEBUG(10, ("search by rid: %x\n", rid));
289 /* Open the smb password file - not for update. */
290 fp = startsmbpwent(False);
294 DEBUG(0, ("unable to open sam password database.\n"));
298 while ((pwd = getsam21pwent(fp)) != NULL && pwd->user_rid != rid)
300 DEBUG(10, ("iterate: %s 0x%x\n", pwd->smb_name, pwd->user_rid));
305 DEBUG(10, ("found by user_rid: %x\n", rid));
312 /************************************************************************
313 Utility function to search sam passwd by uid. use this if your database
314 does not have search facilities.
316 search capability by both rid and uid are needed as the rid <-> uid
317 mapping may be non-monotonic.
319 *************************************************************************/
321 struct sam_passwd *iterate_getsam21pwuid(uid_t uid)
323 struct sam_passwd *pwd = NULL;
326 DEBUG(10, ("search by uid: %x\n", (int)uid));
328 /* Open the smb password file - not for update. */
329 fp = startsmbpwent(False);
333 DEBUG(0, ("unable to open sam password database.\n"));
337 while ((pwd = getsam21pwent(fp)) != NULL && pwd->smb_userid != uid)
342 DEBUG(10, ("found by smb_userid: %x\n", (int)uid));
349 /*************************************************************************
350 Routine to return a display info structure, by rid
351 *************************************************************************/
352 struct sam_disp_info *getsamdisprid(uint32 rid)
354 return pdb_ops->getsamdisprid(rid);
357 /*************************************************************************
358 Routine to return the next entry in the sam passwd list.
359 *************************************************************************/
361 struct sam_passwd *getsam21pwent(void *vp)
363 return pdb_ops->getsam21pwent(vp);
367 /************************************************************************
368 Routine to search sam passwd by name.
369 *************************************************************************/
371 struct sam_passwd *getsam21pwnam(char *name)
373 return pdb_ops->getsam21pwnam(name);
376 /************************************************************************
377 Routine to search sam passwd by rid.
378 *************************************************************************/
380 struct sam_passwd *getsam21pwrid(uint32 rid)
382 return pdb_ops->getsam21pwrid(rid);
386 /**********************************************************
387 **********************************************************
389 utility routines which are likely to be useful to all password
392 **********************************************************
393 **********************************************************/
395 /*************************************************************
396 initialises a struct sam_disp_info.
397 **************************************************************/
399 static void pdb_init_dispinfo(struct sam_disp_info *user)
401 if (user == NULL) return;
402 bzero(user, sizeof(*user));
405 /*************************************************************
406 initialises a struct smb_passwd.
407 **************************************************************/
409 void pdb_init_smb(struct smb_passwd *user)
411 if (user == NULL) return;
412 bzero(user, sizeof(*user));
413 user->pass_last_set_time = (time_t)-1;
416 /*************************************************************
417 initialises a struct sam_passwd.
418 **************************************************************/
419 void pdb_init_sam(struct sam_passwd *user)
421 if (user == NULL) return;
422 bzero(user, sizeof(*user));
423 user->logon_time = (time_t)-1;
424 user->logoff_time = (time_t)-1;
425 user->kickoff_time = (time_t)-1;
426 user->pass_last_set_time = (time_t)-1;
427 user->pass_can_change_time = (time_t)-1;
428 user->pass_must_change_time = (time_t)-1;
431 /*************************************************************************
432 Routine to return the next entry in the sam passwd list.
433 *************************************************************************/
435 struct sam_disp_info *pdb_sam_to_dispinfo(struct sam_passwd *user)
437 static struct sam_disp_info disp_info;
439 if (user == NULL) return NULL;
441 pdb_init_dispinfo(&disp_info);
443 disp_info.smb_name = user->smb_name;
444 disp_info.full_name = user->full_name;
445 disp_info.user_rid = user->user_rid;
450 /*************************************************************
451 converts a sam_passwd structure to a smb_passwd structure.
452 **************************************************************/
454 struct smb_passwd *pdb_sam_to_smb(struct sam_passwd *user)
456 static struct smb_passwd pw_buf;
458 if (user == NULL) return NULL;
460 pdb_init_smb(&pw_buf);
462 pw_buf.smb_userid = user->smb_userid;
463 pw_buf.smb_name = user->smb_name;
464 pw_buf.smb_passwd = user->smb_passwd;
465 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
466 pw_buf.acct_ctrl = user->acct_ctrl;
467 pw_buf.pass_last_set_time = user->pass_last_set_time;
473 /*************************************************************
474 converts a smb_passwd structure to a sam_passwd structure.
475 **************************************************************/
477 struct sam_passwd *pdb_smb_to_sam(struct smb_passwd *user)
479 static struct sam_passwd pw_buf;
481 if (user == NULL) return NULL;
483 pdb_init_sam(&pw_buf);
485 pw_buf.smb_userid = user->smb_userid;
486 pw_buf.smb_name = user->smb_name;
487 pw_buf.smb_passwd = user->smb_passwd;
488 pw_buf.smb_nt_passwd = user->smb_nt_passwd;
489 pw_buf.acct_ctrl = user->acct_ctrl;
490 pw_buf.pass_last_set_time = user->pass_last_set_time;
495 /**********************************************************
496 Encode the account control bits into a string.
497 length = length of string to encode into (including terminating
498 null). length *MUST BE MORE THAN 2* !
499 **********************************************************/
501 char *pdb_encode_acct_ctrl(uint16 acct_ctrl, size_t length)
503 static fstring acct_str;
508 if (acct_ctrl & ACB_PWNOTREQ ) acct_str[i++] = 'N';
509 if (acct_ctrl & ACB_DISABLED ) acct_str[i++] = 'D';
510 if (acct_ctrl & ACB_HOMDIRREQ) acct_str[i++] = 'H';
511 if (acct_ctrl & ACB_TEMPDUP ) acct_str[i++] = 'T';
512 if (acct_ctrl & ACB_NORMAL ) acct_str[i++] = 'U';
513 if (acct_ctrl & ACB_MNS ) acct_str[i++] = 'M';
514 if (acct_ctrl & ACB_WSTRUST ) acct_str[i++] = 'W';
515 if (acct_ctrl & ACB_SVRTRUST ) acct_str[i++] = 'S';
516 if (acct_ctrl & ACB_AUTOLOCK ) acct_str[i++] = 'L';
517 if (acct_ctrl & ACB_PWNOEXP ) acct_str[i++] = 'X';
518 if (acct_ctrl & ACB_DOMTRUST ) acct_str[i++] = 'I';
520 for ( ; i < length - 2 ; i++ ) { acct_str[i] = ' '; }
524 acct_str[i++] = '\0';
529 /**********************************************************
530 Decode the account control bits from a string.
532 this function breaks coding standards minimum line width of 80 chars.
533 reason: vertical line-up code clarity - all case statements fit into
534 15 lines, which is more important.
535 **********************************************************/
537 uint16 pdb_decode_acct_ctrl(char *p)
539 uint16 acct_ctrl = 0;
540 BOOL finished = False;
543 * Check if the account type bits have been encoded after the
544 * NT password (in the form [NDHTUWSLXI]).
547 if (*p != '[') return 0;
549 for (p++; *p && !finished; p++)
553 case 'N': { acct_ctrl |= ACB_PWNOTREQ ; break; /* 'N'o password. */ }
554 case 'D': { acct_ctrl |= ACB_DISABLED ; break; /* 'D'isabled. */ }
555 case 'H': { acct_ctrl |= ACB_HOMDIRREQ; break; /* 'H'omedir required. */ }
556 case 'T': { acct_ctrl |= ACB_TEMPDUP ; break; /* 'T'emp account. */ }
557 case 'U': { acct_ctrl |= ACB_NORMAL ; break; /* 'U'ser account (normal). */ }
558 case 'M': { acct_ctrl |= ACB_MNS ; break; /* 'M'NS logon user account. What is this ? */ }
559 case 'W': { acct_ctrl |= ACB_WSTRUST ; break; /* 'W'orkstation account. */ }
560 case 'S': { acct_ctrl |= ACB_SVRTRUST ; break; /* 'S'erver account. */ }
561 case 'L': { acct_ctrl |= ACB_AUTOLOCK ; break; /* 'L'ocked account. */ }
562 case 'X': { acct_ctrl |= ACB_PWNOEXP ; break; /* No 'X'piry on password */ }
563 case 'I': { acct_ctrl |= ACB_DOMTRUST ; break; /* 'I'nterdomain trust account. */ }
569 default: { finished = True; }
576 /*******************************************************************
577 gets password-database-format time from a string.
578 ********************************************************************/
580 static time_t get_time_from_string(char *p)
584 for (i = 0; i < 8; i++)
586 if (p[i] == '\0' || !isxdigit((int)(p[i]&0xFF)))
592 * p points at 8 characters of hex digits -
593 * read into a time_t as the seconds since
594 * 1970 that the password was last changed.
596 return (time_t)strtol((char *)p, NULL, 16);
601 /*******************************************************************
602 gets password last set time
603 ********************************************************************/
605 time_t pdb_get_last_set_time(char *p)
607 if (*p && StrnCaseCmp((char *)p, "LCT-", 4))
609 return get_time_from_string(p + 4);
615 /*******************************************************************
616 sets password-database-format time in a string.
617 ********************************************************************/
618 static void set_time_in_string(char *p, int max_len, char *type, time_t t)
620 slprintf(p, max_len, ":%s-%08X:", type, (uint32)t);
623 /*******************************************************************
625 ********************************************************************/
626 void pdb_set_logon_time(char *p, int max_len, time_t t)
628 set_time_in_string(p, max_len, "LNT", t);
631 /*******************************************************************
633 ********************************************************************/
634 void pdb_set_logoff_time(char *p, int max_len, time_t t)
636 set_time_in_string(p, max_len, "LOT", t);
639 /*******************************************************************
641 ********************************************************************/
642 void pdb_set_kickoff_time(char *p, int max_len, time_t t)
644 set_time_in_string(p, max_len, "KOT", t);
647 /*******************************************************************
648 sets password can change time
649 ********************************************************************/
650 void pdb_set_can_change_time(char *p, int max_len, time_t t)
652 set_time_in_string(p, max_len, "CCT", t);
655 /*******************************************************************
656 sets password last set time
657 ********************************************************************/
658 void pdb_set_must_change_time(char *p, int max_len, time_t t)
660 set_time_in_string(p, max_len, "MCT", t);
663 /*******************************************************************
664 sets password last set time
665 ********************************************************************/
666 void pdb_set_last_set_time(char *p, int max_len, time_t t)
668 set_time_in_string(p, max_len, "LCT", t);
672 /*************************************************************
673 Routine to set 32 hex password characters from a 16 byte array.
674 **************************************************************/
675 void pdb_sethexpwd(char *p, char *pwd, uint16 acct_ctrl)
680 for (i = 0; i < 16; i++)
682 slprintf(&p[i*2], 33, "%02X", pwd[i]);
687 if (IS_BITS_SET_ALL(acct_ctrl, ACB_PWNOTREQ))
689 safe_strcpy(p, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX", 33);
693 safe_strcpy(p, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 33);
697 /*************************************************************
698 Routine to get the 32 hex characters and turn them
699 into a 16 byte array.
700 **************************************************************/
701 BOOL pdb_gethexpwd(char *p, char *pwd)
704 unsigned char lonybble, hinybble;
705 char *hexchars = "0123456789ABCDEF";
708 for (i = 0; i < 32; i += 2)
710 hinybble = toupper(p[i]);
711 lonybble = toupper(p[i + 1]);
713 p1 = strchr(hexchars, hinybble);
714 p2 = strchr(hexchars, lonybble);
721 hinybble = PTR_DIFF(p1, hexchars);
722 lonybble = PTR_DIFF(p2, hexchars);
724 pwd[i / 2] = (hinybble << 4) | lonybble;
729 /*******************************************************************
730 Group and User RID username mapping function
731 ********************************************************************/
733 BOOL pdb_name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid)
735 struct passwd *pw = Get_Pwnam(user_name, False);
737 if (u_rid == NULL || g_rid == NULL || user_name == NULL)
744 DEBUG(1,("Username %s is invalid on this system\n", user_name));
748 if (user_in_list(user_name, lp_domain_guest_users()))
750 *u_rid = DOMAIN_USER_RID_GUEST;
752 else if (user_in_list(user_name, lp_domain_admin_users()))
754 *u_rid = DOMAIN_USER_RID_ADMIN;
758 /* turn the unix UID into a Domain RID. this is what the posix
759 sub-system does (adds 1000 to the uid) */
760 *u_rid = pdb_uid_to_user_rid(pw->pw_uid);
763 /* absolutely no idea what to do about the unix GID to Domain RID mapping */
764 *g_rid = pdb_gid_to_group_rid(pw->pw_gid);
769 /****************************************************************************
770 Read the machine SID from a file.
771 ****************************************************************************/
773 static BOOL read_sid_from_file(int fd, char *sid_file)
777 memset(fline, '\0', sizeof(fline));
779 if(read(fd, fline, sizeof(fline) -1 ) < 0) {
780 DEBUG(0,("unable to read file %s. Error was %s\n",
781 sid_file, strerror(errno) ));
786 * Convert to the machine SID.
789 fline[sizeof(fline)-1] = '\0';
790 if(!string_to_sid( &global_machine_sid, fline)) {
791 DEBUG(0,("unable to generate machine SID.\n"));
798 /****************************************************************************
799 Generate the global machine sid. Look for the MACHINE.SID file first, if
800 not found then look in smb.conf and use it to create the MACHINE.SID file.
801 ****************************************************************************/
802 BOOL pdb_generate_machine_sid(void)
809 uchar raw_sid_data[12];
811 pstrcpy(sid_file, lp_smb_passwd_file());
812 p = strrchr(sid_file, '/');
817 if (!directory_exist(sid_file, NULL)) {
818 if (dos_mkdir(sid_file, 0700) != 0) {
819 DEBUG(0,("can't create private directory %s : %s\n",
820 sid_file, strerror(errno)));
825 pstrcat(sid_file, "MACHINE.SID");
827 if((fd = open(sid_file, O_RDWR | O_CREAT, 0644)) == -1) {
828 DEBUG(0,("unable to open or create file %s. Error was %s\n",
829 sid_file, strerror(errno) ));
834 * Check if the file contains data.
837 if(sys_fstat( fd, &st) < 0) {
838 DEBUG(0,("unable to stat file %s. Error was %s\n",
839 sid_file, strerror(errno) ));
846 * We have a valid SID - read it.
848 if(!read_sid_from_file( fd, sid_file)) {
849 DEBUG(0,("unable to read file %s. Error was %s\n",
850 sid_file, strerror(errno) ));
859 * The file contains no data - we may need to generate our
860 * own sid. Try the lp_domain_sid() first.
864 fstrcpy( sid_string, lp_domain_sid());
867 * Generate the new sid data & turn it into a string.
870 generate_random_buffer( raw_sid_data, 12, True);
872 fstrcpy( sid_string, "S-1-5-21");
873 for( i = 0; i < 3; i++) {
875 slprintf( tmp_string, sizeof(tmp_string) - 1, "-%u", IVAL(raw_sid_data, i*4));
876 fstrcat( sid_string, tmp_string);
880 fstrcat(sid_string, "\n");
883 * Ensure our new SID is valid.
886 if(!string_to_sid( &global_machine_sid, sid_string)) {
887 DEBUG(0,("unable to generate machine SID.\n"));
892 * Do an exclusive blocking lock on the file.
895 if(!do_file_lock( fd, 60, F_WRLCK)) {
896 DEBUG(0,("unable to lock file %s. Error was %s\n",
897 sid_file, strerror(errno) ));
903 * At this point we have a blocking lock on the SID
904 * file - check if in the meantime someone else wrote
905 * SID data into the file. If so - they were here first,
909 if(sys_fstat( fd, &st) < 0) {
910 DEBUG(0,("unable to stat file %s. Error was %s\n",
911 sid_file, strerror(errno) ));
918 * Unlock as soon as possible to reduce
919 * contention on the exclusive lock.
921 do_file_lock( fd, 60, F_UNLCK);
924 * We have a valid SID - read it.
927 if(!read_sid_from_file( fd, sid_file)) {
928 DEBUG(0,("unable to read file %s. Error was %s\n",
929 sid_file, strerror(errno) ));
938 * The file is still empty and we have an exlusive lock on it.
939 * Write out out SID data into the file.
942 if(fchmod(fd, 0644) < 0) {
943 DEBUG(0,("unable to set correct permissions on file %s. \
944 Error was %s\n", sid_file, strerror(errno) ));
949 if(write( fd, sid_string, strlen(sid_string)) != strlen(sid_string)) {
950 DEBUG(0,("unable to write file %s. Error was %s\n",
951 sid_file, strerror(errno) ));
960 do_file_lock( fd, 60, F_UNLCK);
965 /*******************************************************************
966 converts UNIX uid to an NT User RID.
967 ********************************************************************/
969 uint32 pdb_uid_to_user_rid(uid_t uid)
971 return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
974 /*******************************************************************
975 converts NT Group RID to a UNIX uid.
976 ********************************************************************/
978 uint32 pdb_gid_to_group_rid(gid_t gid)
980 return (((((uint32)gid)*RID_MULTIPLIER) + 1000) | GROUP_RID_TYPE);
983 /*******************************************************************
984 Decides if a RID is a well known RID.
985 ********************************************************************/
987 static BOOL pdb_rid_is_well_known(uint32 rid)
992 /*******************************************************************
993 Decides if a RID is a user or group RID.
994 ********************************************************************/
996 BOOL pdb_rid_is_user(uint32 rid)
998 /* lkcl i understand that NT attaches an enumeration to a RID
999 * such that it can be identified as either a user, group etc
1000 * type. there are 5 such categories, and they are documented.
1002 if(pdb_rid_is_well_known(rid)) {
1004 * The only well known user RIDs are DOMAIN_USER_RID_ADMIN
1005 * and DOMAIN_USER_RID_GUEST.
1007 if(rid == DOMAIN_USER_RID_ADMIN || rid == DOMAIN_USER_RID_GUEST)
1009 } else if((rid & RID_TYPE_MASK) == USER_RID_TYPE) {