Main Page   Namespace List   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

fksec::sid Class Reference

The sid class mimics an NT SID object (Security Identifier). More...

#include <sid.h>

Collaboration diagram for fksec::sid:

Collaboration graph
[legend]
List of all members.

Public Types

enum  SidType {
  stWellKnown,
  stLocal,
  stDomain,
  stForeign
}
 The SidType enumeration, used by LookupSidType(), provides values which identify a SID as local or remote. More...


Public Methods

 sid ()
 construct *this as an empty sid object. More...

 sid ( const sid &s )
 construct *this as a copy of another sid object. More...

 sid ( const PSID s )
 Construct *this as a copy of a SID. More...

 sid ( const TCHAR *name )
 Construct *this by interpreting a string SID or looking a name up in the accounts database. More...

 sid ( SID_IDENTIFIER_AUTHORITY newsia, DWORD nSubAuths, DWORD subAuth0 = 0, DWORD subAuth1 = 0, DWORD subAuth2 = 0, DWORD subAuth3 = 0, DWORD subAuth4 = 0, DWORD subAuth5 = 0, DWORD subAuth6 = 0, DWORD subAuth7 = 0 )
 construct *this from bits and pieces. More...

 sid ( unsigned __int64 newsia, DWORD nSubAuths, DWORD subAuth0 = 0, DWORD subAuth1 = 0, DWORD subAuth2 = 0, DWORD subAuth3 = 0, DWORD subAuth4 = 0, DWORD subAuth5 = 0, DWORD subAuth6 = 0, DWORD subAuth7 = 0 )
 construct *this from different bits and pieces. More...

virtual ~sid ()
 clean up *this. More...

const sid& operator= ( const sid &s )
 set *this to a copy of a sid, including the valid/invalid state. More...

const sid& operator= ( const PSID s )
 set *this to a copy of a SID. More...

const sid& operator= ( const TCHAR *name )
 set *this to a SID derived from interpreting a string SID or looking a name up in the accounts database. More...

 operator const PSID () const
 return a pointer to an NT-formatted SID. More...

bool operator< ( const sid &r ) const
 compares two sid objects for less-than. More...

bool operator== ( const sid &r ) const
 compares two sid objects for equality. More...

bool operator!= ( const sid &r ) const
 compares two sid objects for inequality. More...

bool EqualPrefix ( const sid &r ) const
 compares the prefixes of two sid objects for equality. More...

DWORD GetLength () const
 computes the number of bytes needed to store *this as an NT SID. More...

__int64 GetSidIdentifierAuthority () const
 returns the SID_IDENTIFIER_AUTHORITY value as a 64-bit integer. More...

void RemoveLastRid ()
 truncates *this by removing the last subauthority value. More...

void AppendSubAuthority ( DWORD rid )
 appends a RID to the end of this sid. More...

void SetSubAuthority ( DWORD index, DWORD rid )
 sets a new value for an existing RID. More...

DWORD GetSubAuthority ( DWORD index ) const
 returns a specified subauthority value. More...

DWORD GetSubAuthorityCount () const
 returns the current subauthority count. More...

bool IsValid () const
 tests *this for validity. More...

fkstr ConvertToStringSid () const
 returns the string representation of *this. More...

void StoreSid ( PSID ps, DWORD size ) const
 stores a SID into a client-provided buffer. More...

void ConvertFromStringSid ( const TCHAR *stringsid )
 sets *this to the SID represented by a stringified SID. More...

void LookupName ( const TCHAR *server, const TCHAR *name )
 sets *this to the SID of an account looked up on a server. More...

void LookupSid ( const TCHAR *server, fkstr &name, fkstr &domain, SID_NAME_USE &snu ) const
 retrieves the account name and domain for the sid. More...

SidType LookupSidType ()
 determines the server on which the SID resides. More...

SidList MemberOf ( bool bIncludeGlobal, bool bIncludeLocal, bool bIncludeIndirect, const TCHAR *server = NULL )
 retrieves the list of groups that this user is a member of. More...

SidList Members ( const TCHAR *server = NULL )
 retrieves all the members of this group. More...


Static Public Methods

const TCHAR* SnuToText ( SID_NAME_USE snu )
 translates SID_NAME_USE to text description. More...


Static Public Attributes

constant SIDs outside NT AUTHORITY
const sid sidNull
 S-1-0-0 null SID. More...

const sid sidWorld
 S-1-1-0 World (Everyone). More...

const sid sidLocal
 S 1-2-0 Local. More...

const sid sidCreatorOwner
 S-1-3-0 Creator Owner. More...

const sid sidCreatorGroup
 S-1-3-1 Creator Group. More...

const sid sidCreatorOwnerServer
 S-1-3-2 Creator Owner Server. More...

const sid sidCreatorGroupServer
 S-1-3-3 Creator Group Server. More...

constant SIDs in the NT AUTHORITY domain
const sid sidNtAuthority
 S-1-5- prefix for built-in accounts and groups. More...

const sid sidDialup
 S-1-5-1 Dialup users. More...

const sid sidNetwork
 S-1-5-2 Network logons. More...

const sid sidBatch
 S-1-5-3 Batch logons. More...

const sid sidInteractive
 S-1-5-4 Interactive logons. More...

const sid sidLogon
 S-1-5-5- prefix for logon session SIDs, requires two more RIDs. More...

const sid sidService
 S-1-5-6 Service logons. More...

const sid sidAnonymousLogon
 S-1-5-7 Anonymous (null session). More...

const sid sidProxy
 S-1-5-8 Logon by proxy. More...

const sid sidServerLogon
 S-1-5-9 DC account. More...

const sid sidSelf
 S-1-5-10 Self (current caller). More...

const sid sidAuthenticated
 S-1-5-11 Authenticated users (as opposed to World). More...

const sid sidRestricted
 S-1-5-12 Indicates a restricted token. More...

const sid sidTerminalServer
 S-1-5-13 Token from Terminal Server. More...

const sid sidLocalSystem
 S-1-5-18 LocalSystem (NT AUTHORITY\SYSTEM). More...

functions returning semi-constant SIDs in an account domain
const sid sidNonUnique
 S-1-5-21- prefix for domains, domain accounts, etc. More...

constant SIDs in the built-in domain
const sid sidBuiltin
 S-1-5-32 built-in domain. More...

const sid sidLocalAdministrator
 S-1-5-32-500 local admin account. More...

const sid sidLocalGuest
 S-1-5-32-501 local guest account. More...

const sid sidLocalAdministrators
 S-1-5-32-544 Administrators. More...

const sid sidLocalUsers
 S-1-5-32-545 Users. More...

const sid sidLocalGuests
 S-1-5-32-546 Guests. More...

const sid sidLocalPowerUsers
 S-1-5-32-547 Power Users. More...

const sid sidLocalAccountOperators
 S-1-5-32-548 Account Operators. More...

const sid sidLocalSystemOperators
 S-1-5-32-549 System Operators. More...

const sid sidLocalPrintOperators
 S-1-5-32-550 Print Server Operators. More...

const sid sidLocalBackupOperators
 S-1-5-32-551 Backup Operators. More...

const sid sidLocalReplicator
 S-1-5-32-552 File replicator account. More...

const sid sidLocalRasServers
 S-1-5-32-553 Ras servers. More...

const sid sidLocalPreW3KCompAccess
 S-1-5-32-554 SID used to validate Net*() access from NT4 machines. More...


Private Methods

void Init ()
 initializes all members of a sid object to zero and sets its state to invalid. More...

void ClearPSID () const
 sets psid to NULL and havePSID to false. More...

void ReleasePSID () const
 releases psid memory, if any, and sets psid to NULL and havePSID to false. More...

bool CvsGetUInt64 ( const TCHAR *&str, unsigned __int64 &r )
 reads and converts a "-<uint64>" string. More...

PSID MakePSID () const
 generates a PSID from *this. More...


Private Attributes

bool isValid
 isValid remains false until a valid SID can be built. More...

SID_IDENTIFIER_AUTHORITY sia
 sia contains the sid's SID_IDENTIFIER_AUTHORITY value. More...

DWORD subAuthCount
 subAuthCount gives the current number of subauthorities in *this. More...

DWORD subAuth [SID_MAX_SUB_AUTHORITIES]
 subAuth[] contains the list of subauthorities. More...

bool havePSID
 havePSID indicates whether psid is valid and points to an NT-formatted SID reflecting the contents of *this. More...

PSID psid
 psid points to a new()ed chunk of memory which holds an NT-formatted SID representing *this. More...


Friends

fkostreamoperator<< ( fkostream &o, const sid &s )
 Inserts a textual representation, suitable for debugging, into an output stream.


Detailed Description

The sid class mimics an NT SID object (Security Identifier).

SIDs are strings of numbers that uniquely (one hopes) identify an entity within a certain context. Their major features are an "authority" which is basically the subsystem or general area issuing a SID, and a series of DWORDs (RIDs) which, in a hierarchical manner, narrow down to a single entry. Here, for example, is my SID when I log on as Administrator, expressed as a string:

    S-1-5-21-484763869-764733703-1202660629-500

All users in my domain would have an identical SID, except for the last value. This last value is technically just one of 5 RIDs that are present, but in practice we call the last RID "the RID," and what goes before it is the "prefix." Here, the prefix is at the same time a domain SID, because it identifies the domain in which user 500 lives, and a domain SID that is part of a complete, larger SID is often called a "domain prefix."

An object of class sid encapsulates just such a SID and happily converts between NT-formatted SIDs, user/group/domain/… names, and the textual representation above, which is what you can see in the HKEY_USERS key of your registry, too. It also provides a const PSID conversion operator so you can plug an sid into any place where you would normally use a const PSID.

A note on the validity of sid instances

A sid object may, at any time, be in an invalid state, or in a valid one. Without going into details, it becomes valid as soon as it has an sia (SID_IDENTIFIER_AUTHORITY) value and at least one RID. Using an invalid sid object anywhere is very likely to reward you with an exception, so make sure of your exception handling.

Author(s):
Simon Fell <simon@zaks.demon.co.uk> , Felix Kasza <felixk@mvps.org> , see http://mvps.org/security/fksec.html

Definition at line 62 of file sid.h.


Member Enumeration Documentation

enum fksec::sid::SidType
 

The SidType enumeration, used by LookupSidType(), provides values which identify a SID as local or remote.

Enumeration values:
stWellKnown   refers to SIDs which are always local and which do not belong to any account domain. Examples are the SIDs for Everyone, LocalSystem.
stLocal   refers to SIDs residing in the local machine's accounts database -- local users and local groups, mostly.
stDomain   is used for accounts which reside in the domain controller's accounts database, including domain users and global groups.
stForeign   is the tag for SIDs whose domain prefix does not match the local prefixes, and for which no domain can be identified.

Definition at line 66 of file sid.h.

00067         {
00071             stWellKnown,
00074             stLocal,
00078             stDomain,
00081             stForeign
00082         }


Constructor & Destructor Documentation

fksec::sid::sid ( )
 

construct *this as an empty sid object.

The initial state of *this is invalid.

Exceptions:
none  

Definition at line 23 of file sid.cpp.

00024 {
00025     Init();
00026     ClearPSID();
00027 }

fksec::sid::sid ( const sid & s )
 

construct *this as a copy of another sid object.

*this becomes a copy of the argument, including its valid state.

Parameters:
s   the sid to copy
Exceptions:
none  

Definition at line 33 of file sid.cpp.

00034 {
00035     Init();
00036     ClearPSID();
00037     isValid = s.isValid;
00038     if ( isValid )
00039     {
00040         sia = s.sia;
00041         subAuthCount = s.subAuthCount;
00042         memcpy( subAuth, s.subAuth, sizeof subAuth );
00043     }
00044 }

fksec::sid::sid ( const PSID s )
 

Construct *this as a copy of a SID.

Parses the SID and stashes its contents in *this. Note that the sid class does not wrap the PSID; you can free the PSID after this function returns.

Parameters:
s   pointer to the NT-formatted SID to copy into *this
Exceptions:
none  

Definition at line 52 of file sid.cpp.

00053 {
00054     DWORD i;
00055 
00056     Init();
00057     ClearPSID();
00058     if ( IsValidSid( s ) )
00059     {
00060         isValid = true;
00061         sia = *::GetSidIdentifierAuthority( s );
00062         subAuthCount = (DWORD) *GetSidSubAuthorityCount( s );
00063         if ( subAuthCount < lenof( subAuth ) )
00064         {
00065             for ( i = 0; i < subAuthCount; ++ i )
00066                 subAuth[i] = *GetSidSubAuthority( s, i );
00067         }
00068         else
00069             throw NEWEX( errTooManySubAuths, "sid::sid( PSID ): more than SID_MAX_SUB_AUTHORITIES subauthorities in the SID" );
00070     }
00071     else
00072         throw NEWEX( errInvalidSid, "sid::sid( PSID ): invalid SID passed in" );
00073 }

fksec::sid::sid ( const TCHAR * name )
 

Construct *this by interpreting a string SID or looking a name up in the accounts database.

The ctor first tries to parse the string as a text-SID ("S-1-5-..."); if that fails, it calls LookupAccountName() with server == NULL (i.e., it asks the local machine to find the name). If this works, the SID is stored in *this.

Parameters:
name   a pointer to a null-terminted string naming either a valid account like felixk, MVPS\\felixk, or felixk@nt.mvps.org, or a SID in string form, such as S-1-5-18
Exceptions:
errNoMemory  
errInvalidSid   (both from LookupName())

Definition at line 85 of file sid.cpp.

00086 {
00087     Init();
00088     ClearPSID();
00089 
00090     try { ConvertFromStringSid( name ); }
00091     catch ( ex *e )
00092     {
00093         if ( e->GetErr() != errInvalidSid )
00094         {
00095             e->FKSECADDHOP( "sid::sid( name )" );
00096             throw;
00097         }
00098 
00099         // not a string SID, so let's try something else
00100         delete e;
00101         try { LookupName( /* server */ 0, name ); }
00102         RETHROWEX( "sid::sid( name )" )
00103     }
00104 }

fksec::sid::sid ( SID_IDENTIFIER_AUTHORITY newsia,
DWORD nSubAuths,
DWORD subAuth0 = 0,
DWORD subAuth1 = 0,
DWORD subAuth2 = 0,
DWORD subAuth3 = 0,
DWORD subAuth4 = 0,
DWORD subAuth5 = 0,
DWORD subAuth6 = 0,
DWORD subAuth7 = 0 )
 

construct *this from bits and pieces.

This ctor works in a manner similar to AllocateAndInitializeSid(), except that it allocates no memory.

Parameters:
newsia   a SID_IDENTIFIER_AUTHORITY value (struct { byte[6] })
nSubAuths   number of the following subauthorities that are valid and should be used
subAuthN   the Nth subauthority value
Exceptions:
none  

Definition at line 113 of file sid.cpp.

00117 {
00118     Init();
00119     ClearPSID();
00120     sia = newsia;
00121     subAuthCount = nSubAuths;
00122     subAuth[0] = subAuth0;
00123     subAuth[1] = subAuth1;
00124     subAuth[2] = subAuth2;
00125     subAuth[3] = subAuth3;
00126     subAuth[4] = subAuth4;
00127     subAuth[5] = subAuth5;
00128     subAuth[6] = subAuth6;
00129     subAuth[7] = subAuth7;
00130     isValid = true;
00131 }

fksec::sid::sid ( unsigned __int64 newsia,
DWORD nSubAuths,
DWORD subAuth0 = 0,
DWORD subAuth1 = 0,
DWORD subAuth2 = 0,
DWORD subAuth3 = 0,
DWORD subAuth4 = 0,
DWORD subAuth5 = 0,
DWORD subAuth6 = 0,
DWORD subAuth7 = 0 )
 

construct *this from different bits and pieces.

This ctor works in a manner similar to AllocateAndInitializeSid(), except that it allocates no memory, and that it uses a different format for the newsia argument.

Parameters:
newsia   a SID_IDENTIFIER_AUTHORITY value (expressed as an unsigned __int64)
nSubAuths   number of the following subauthorities that are valid and should be used
subAuthN   the Nth subauthority value
Exceptions:
none  

Definition at line 141 of file sid.cpp.

00145 {
00146     int i;
00147     Init();
00148     ClearPSID();
00149     // why so complicated? because sia's byte ordering is machine-independent,
00150     // while __int64 is not.  This code is endian-safe.
00151     for ( i = lenof( sia.Value ) - 1; i >= 0; -- i )
00152     {
00153         sia.Value[i] = newsia % 256UI64;
00154         newsia /= 256UI64;
00155     }
00156     subAuthCount = nSubAuths;
00157     subAuth[0] = subAuth0;
00158     subAuth[1] = subAuth1;
00159     subAuth[2] = subAuth2;
00160     subAuth[3] = subAuth3;
00161     subAuth[4] = subAuth4;
00162     subAuth[5] = subAuth5;
00163     subAuth[6] = subAuth6;
00164     subAuth[7] = subAuth7;
00165     isValid = true;
00166 }

fksec::sid::~sid ( ) [virtual]
 

clean up *this.

The dtor releases any internal buffers (like the one that the object may have used for providing PSID conversion).

Exceptions:
none  

Definition at line 172 of file sid.cpp.

00173 {
00174     ReleasePSID();
00175 }


Member Function Documentation

void fksec::sid::AppendSubAuthority ( DWORD rid )
 

appends a RID to the end of this sid.

Given a domain SID and a user RID (some NetGroup*() functions return just those), this method can be used to build a full SID for the user (or group).

Parameters:
rid   the RID (subauthority value) to append to sid
Exceptions:
errInvalidSid  
errTooManySubAuths  

Definition at line 483 of file sid.cpp.

00484 {
00485     if ( ! isValid )
00486         throw NEWEX( errInvalidSid, "sid::AppendSubAuthority(): invalid SID" );
00487 
00488     if ( subAuthCount >= SID_MAX_SUB_AUTHORITIES )
00489         throw NEWEX( errTooManySubAuths, "sid::AppendSubAuthority(): already SID_MAX_SUB_AUTHORITIES in the SID" );
00490 
00491     ReleasePSID();
00492     subAuth[subAuthCount] = rid;
00493     ++ subAuthCount;
00494 }

void fksec::sid::ClearPSID ( ) const [private]
 

sets psid to NULL and havePSID to false.

This method does not release memory allocated for psid. Use with care.

Exceptions:
none  

Definition at line 1193 of file sid.cpp.

01194 {
01195     havePSID = false;
01196     psid = 0;
01197 }

void fksec::sid::ConvertFromStringSid ( const TCHAR * stringsid )
 

sets *this to the SID represented by a stringified SID.

This method is the complement to ConvertToStringSid(). It attempts to parse the format produced by that function and, if successful, sets *this to the parsed SID. If unsuccessful, an exception is raised, and the state of *this is unchanged.

Parameters:
stringsid   a pointer to a null-terminated string representing a SID, such as S-1-5-18
Exceptions:
errInvalidSid  

Definition at line 687 of file sid.cpp.

00688 {
00689     // a string SID has the form
00690     // S-rev-sia-rid-rid...
00691     DWORD i;
00692     unsigned __int64 r;
00693     SID_IDENTIFIER_AUTHORITY tempsia = { 0 };
00694     DWORD rids[SID_MAX_SUB_AUTHORITIES];
00695 
00696     if ( stringsid == 0 )
00697         throw NEWEX( errInvalidSid, "sid::ConvertFromStringSid(): invalid SID (NULL)" );
00698 
00699     if ( *stringsid != _T( 's' ) && *stringsid != _T( 'S' ) )
00700         throw NEWEX( errInvalidSid, "sid::ConvertFromStringSid(): invalid SID (first char not 'S')" );
00701 
00702     ++ stringsid; // skip 'S'
00703 
00704     if ( ! CvsGetUInt64( stringsid, r ) )
00705         throw NEWEX( errInvalidSid, "sid::ConvertFromStringSid(): invalid SID (cannot parse revision)" );
00706     if ( r != SID_REVISION )
00707         throw NEWEX( errInvalidSid, "sid::ConvertFromStringSid(): invalid SID (revision != SID_REVISION)" );
00708 
00709     if ( ! CvsGetUInt64( stringsid, r ) )
00710         throw NEWEX( errInvalidSid, "sid::ConvertFromStringSid(): invalid SID (cannot parse SIA)" );
00711     if ( r == 0 || r > 0xffffffffffffUI64 )
00712         throw NEWEX( errInvalidSid, "sid::ConvertFromStringSid(): invalid SID (SIA out of range)" );
00713     // SIA is stored high-byte first; to avoid machine dependency,
00714     // we fill it byte for byte
00715     for ( i = 0; i < lenof( tempsia.Value ); ++ i )
00716     {
00717         tempsia.Value[lenof( tempsia.Value ) - i - 1] = (byte) ( r & 0xff );
00718         r >>= 8;
00719     }
00720 
00721     for ( i = 0; i < SID_MAX_SUB_AUTHORITIES; ++ i )
00722     {
00723         if ( ! CvsGetUInt64( stringsid, r ) )
00724             break;
00725         if ( r > 0xffffffffUI64 )
00726             throw NEWEX( errInvalidSid, "sid::ConvertFromStringSid(): invalid SID (RID out of range)" );
00727         rids[i] = (DWORD) r;
00728     }
00729     // we ran out of array space, or the SID was finished.
00730     // in either case, stringsid should point to a '\0'.
00731 
00732     if ( *stringsid != _T( '\0' ) )
00733         throw NEWEX( errInvalidSid, "sid::ConvertFromStringSid(): invalid SID (cannot parse RID, or trailing garbage in string)" );
00734 
00735     // we have a complete SID. Stash it.
00736     ReleasePSID();
00737     Init();
00738     sia = tempsia;
00739     subAuthCount = i;
00740     memcpy( subAuth, rids, subAuthCount * sizeof rids[0] );
00741     isValid = true;
00742 }

fkstr fksec::sid::ConvertToStringSid ( ) const
 

returns the string representation of *this.

Produces a string representation of the sid object's contents in the same format as NT5's ConvertSidToStringSid(), but does not rely on running under NT5.

If the sid is not currently valid, the returned string has the value "*invalid*". No exceptions are thrown.

Returns:
an instance of fkstr (which maps to std::string or std::wstring, depending on the UNICODE setting) containing the stringified sid.
Exceptions:
none  

Definition at line 619 of file sid.cpp.

00620 {
00621     // S-rev- + SIA + subauthlen*maxsubauth + terminator
00622     TCHAR buf[15 + 12 + 12*SID_MAX_SUB_AUTHORITIES + 1];
00623     TCHAR *p = &buf[0];
00624     DWORD i;
00625 
00626     // Validate the binary SID.
00627 
00628     if ( ! IsValid() )
00629         return fkstr( _T( "*invalid*" ) );
00630 
00631     p += _sntprintf( p, &buf[lenof( buf )] - p, _T( "S-%lu-" ), SID_REVISION );
00632 
00633     if ( ( sia.Value[0] != 0 ) || ( sia.Value[1] != 0 ) )
00634         p += _sntprintf( p, &buf[lenof( buf )] - p, _T( "0x%02hx%02hx%02hx%02hx%02hx%02hx" ),
00635             (USHORT) sia.Value[0], (USHORT) sia.Value[1],
00636             (USHORT) sia.Value[2], (USHORT) sia.Value[3],
00637             (USHORT) sia.Value[4], (USHORT) sia.Value[5] );
00638     else
00639         p += _sntprintf( p, &buf[lenof( buf )] - p, _T( "%lu" ),
00640             (ULONG) ( sia.Value[5]       ) + (ULONG) ( sia.Value[4] << 8  ) +
00641             (ULONG) ( sia.Value[3] << 16 ) + (ULONG) ( sia.Value[2] << 24 ) );
00642 
00643     // Add SID subauthorities to the string.
00644 
00645     for ( i = 0; i < subAuthCount; ++ i )
00646         p += _sntprintf( p, &buf[lenof( buf )] - p, _T( "-%lu" ), subAuth[i] );
00647 
00648     return fkstr( buf );
00649 }

bool fksec::sid::CvsGetUInt64 ( const TCHAR *& str,
unsigned __int64 & r ) [private]
 

reads and converts a "-<uint64>" string.

CvsGetUInt64() expects str to point at a string consisting of a hyphen and a number. The number itself may be decimal (default), octal (if there is a leading zero), or hex (leading zero followed by a lower- or uppercase 'x'). The method advances str past the characters it has successfully read.

The return value is false if either the input string's syntax does not match the method's expectations, or if the number (or the part following the base-prefix, if any) has no convertible digits. Otherwise, the return value is true, and the unsigned __int64 reference r stores the result.

Parameters:
str   reference to a pointer to the string to be converted. After conversion, the pointer will be advanced to reflect the converted characters.
r   a reference to an unsigned __int64 in which to store the conversion result
Return values:
true   if a number was successfully converted, in which case str points at the first unconverted character, and r holds the result
false   if a syntax error was encountered.
Exceptions:
none  

Definition at line 1233 of file sid.cpp.

01234 {
01235     DWORD base = 10, d;
01236     const TCHAR *startOfNumber;
01237     static byte value[256] = { 0 };
01238 
01239     if ( str == 0 || *str != _T( '-' ) )
01240         return false;
01241 
01242     if ( value[0] == 0 ) // array not yet initialized
01243     {
01244         memset( value, '\xff', sizeof value );
01245         for ( d = '0'; d <= '9'; ++ d )
01246             value[d] = (byte) d - '0';
01247         for ( d = 'A'; d <= 'F'; ++ d )
01248             value[d | 0x20] = value[d] = (byte) d - '7';
01249     }
01250 
01251     r = 0;
01252     ++ str;
01253     if ( *str == _T( '0' ) )
01254     {
01255         base = 8;
01256         ++ str;
01257         if ( *str == _T( 'x' ) || *str == _T( 'X' ) )
01258         {
01259             base = 16;
01260             ++ str;
01261         }
01262     }
01263 
01264     startOfNumber = str;
01265     for ( ; ; )
01266     {
01267         d = value[(DWORD) (byte) *str]; // would hate to have an o-o-b index
01268         if ( d >= base )
01269             break;
01270         r = r * base + (unsigned __int64) d;
01271         ++ str;
01272     }
01273 
01274     // no digits converted?
01275     // if base != 10, we have seen a leading zero ... which, in this case,
01276     // was not a base prefix but the entire number. Not an error!
01277     if ( str == startOfNumber && base == 10 )
01278         return false;
01279 
01280     return true;
01281 }

bool fksec::sid::EqualPrefix ( const sid & r ) const
 

compares the prefixes of two sid objects for equality.

Compares the prefix of *this with the prefix of r and returns the result.

The method considers two SIDs (and sids) to be equal if and only if they have the same authority value, subauthority count, and subauthority lists, except for the last subauthority value, which is ignored in both sid objects.

Parameters:
r   the right-hand side sid for the comparison
Return values:
true   if the sids have the same prefix.
false   if the sids do not have the same prefix
Exceptions:
errInvalidSid  

Definition at line 415 of file sid.cpp.

00416 {
00417     DWORD i;
00418 
00419     if ( ! isValid || ! r.isValid )
00420         throw NEWEX( errInvalidSid, "sid::EqualPrefix(): invalid SID" );
00421 
00422     if ( subAuthCount != r.subAuthCount || 0 != memcmp( &sia, &r.sia, sizeof( sia ) ) )
00423         return false;
00424 
00425     for ( i = 0; i < subAuthCount - 1; ++ i )
00426         if ( subAuth[i] != r.subAuth[i] )
00427             return false;
00428 
00429     return true;
00430 }

DWORD fksec::sid::GetLength ( ) const
 

computes the number of bytes needed to store *this as an NT SID.

Returns:
the number of bytes required for *this as an NT SID
Exceptions:
none  

Definition at line 438 of file sid.cpp.

00439 {
00440     return ::GetSidLengthRequired( (byte) subAuthCount );
00441 }

__int64 fksec::sid::GetSidIdentifierAuthority ( ) const
 

returns the SID_IDENTIFIER_AUTHORITY value as a 64-bit integer.

Returns:
the integer equivalent of the SIA, with proper byte ordering
Exceptions:
none  

Definition at line 446 of file sid.cpp.

00447 {
00448     unsigned __int64 r;
00449 
00450     // SIA is stored high byte first; we avoid platform
00451     // dependency by processing it byte for byte
00452     r = ( ( (unsigned __int64) sia.Value[0] ) << 40 ) |
00453         ( ( (unsigned __int64) sia.Value[1] ) << 32 ) |
00454         ( ( (unsigned __int64) sia.Value[2] ) << 24 ) |
00455         ( ( (unsigned __int64) sia.Value[3] ) << 16 ) |
00456         ( ( (unsigned __int64) sia.Value[4] ) <<  8 ) |
00457         ( ( (unsigned __int64) sia.Value[5] )       );
00458 
00459     return (__int64) r;
00460 }

DWORD fksec::sid::GetSubAuthority ( DWORD index ) const
 

returns a specified subauthority value.

Note that subauthority index values range from 0 through GetSubAuthorityCount() - 1.

Parameters:
index   the zero-based index of the RID to be retrieved
Returns:
a DWORD with the indexth subauthority value
Exceptions:
errInvalidSid  
errInvalidSubAuthIndex  

Definition at line 524 of file sid.cpp.

00525 {
00526     if ( ! isValid )
00527         throw NEWEX( errInvalidSid, "sid::GetSubAuthority(): invalid SID" );
00528 
00529     if ( index >= subAuthCount )
00530         throw NEWEX( errInvalidSubAuthIndex,
00531             "sid::GetSubAuthority(): invalid subauthority index" );
00532 
00533     return subAuth[index];
00534 }

DWORD fksec::sid::GetSubAuthorityCount ( ) const
 

returns the current subauthority count.

Returns:
a DWORD with the sid's current subauthority count
Exceptions:
errInvalidSid  

Definition at line 539 of file sid.cpp.

00540 {
00541     if ( ! isValid )
00542         throw NEWEX( errInvalidSid, "sid::GetSubAuthorityCount(): invalid SID" );
00543 
00544     return subAuthCount;
00545 }

void fksec::sid::Init ( ) [private]
 

initializes all members of a sid object to zero and sets its state to invalid.

\excption none

Definition at line 1181 of file sid.cpp.

01182 {
01183     isValid = false;
01184     memset( &sia, '\0', sizeof sia );
01185     subAuthCount = 0;
01186     memset( subAuth, '\0', sizeof subAuth );
01187 }

bool fksec::sid::IsValid ( ) const
 

tests *this for validity.

If the sid is initialized, it builds an NT SID and runs it through IsValidSid(). If both tests are met, the sid is considered valid. This function is guaranteed to never throw an exception.

Return values:
true   if the sid is valid
false   if the sid is not initialized or does not pass IsValidSid()
Exceptions:
none  

Definition at line 554 of file sid.cpp.

00555 {
00556     PSID p;
00557 
00558     if ( ! isValid )
00559         return false;
00560 
00561     try { p = MakePSID(); }
00562     catch ( ex *e )
00563     {
00564         delete e;
00565         return false;
00566     }
00567 
00568     if ( p == 0 )
00569         return false;
00570 
00571     return !! IsValidSid( p );
00572 }

void fksec::sid::LookupName ( const TCHAR * server,
const TCHAR * name )
 

sets *this to the SID of an account looked up on a server.

LookupName() uses LookupAccountName to query the named server (local machine if server is NULL or points to an empty string) for the SID of the account named. If successful, *this is set to this SID, else an exception is raised.

Parameters:
server   pointer to a null-terminated string containing the server name to perform the lookup on. If server is NULL or an empty string, the local computer is used
name   pointer to a null-terminated string containing the account name to look up, like felixk, MVPS\\felixk, or felixk@nt.mvps.org
Exceptions:
errNoMemory  
errInvalidSid  

Definition at line 756 of file sid.cpp.

00757 {
00758     PSID ps;
00759     DWORD pslen, domlen;
00760     SID_NAME_USE snu;
00761     TCHAR domain[256];
00762 
00763     domlen = lenof( domain );
00764     pslen = GetSidLengthRequired( SID_MAX_SUB_AUTHORITIES );
00765     ps = new byte[pslen];
00766     if ( ps == 0 )
00767         throw NEWEX( errNoMemory, "sid::LookupName(): no memory for SID buffer" );
00768 
00769     ReleasePSID();
00770     if ( ::LookupAccountName( server, name, ps, &pslen, domain, &domlen, &snu ) )
00771         *this = ps;
00772     else
00773     {
00774         delete [] ps;
00775         throw NEWEX32( errInvalidSid, "sid::LookupName(): failed, see GetErrWin32()", GetLastError() );
00776     }
00777 
00778     delete [] ps;
00779 }

void fksec::sid::LookupSid ( const TCHAR * server,
fkstr & name,
fkstr & domain,
SID_NAME_USE & snu ) const
 

retrieves the account name and domain for the sid.

This method uses LookupAccountSid() to query the named server (local machine if server == NULL or points to an empty string) for the name and domain of the account represented by the sid.

Parameters:
server   pointer to a null-terminated string containing the server name to perform the lookup on. If server is NULL or an empty string, the local computer is used
name   writable reference to an fkstr to receive the account name represented by *this
domain   writable reference to an fkstr to receive the domain of the account name represented by *this
anu   writable reference to a SID_NAME_USE enum variable to receive the type of the account represented by *this
Returns:
no direct return; side effects: name, domain, snu changed if successful.
Exceptions:
errInvalidSid  
errNoMemory  

Definition at line 798 of file sid.cpp.

00799 {
00800     PSID ps;
00801     DWORD rc, tempnamelen, tempdomainlen;
00802     TCHAR *tempname = 0, *tempdomain = 0;
00803 
00804     try { ps = MakePSID(); }
00805     RETHROWEX( "sid::lookupSid(): cannot generate NT-formatted SID" );
00806 
00807     if ( ps == 0 )
00808         throw NEWEX( errNoMemory, "sid::LookupSid(): no memory for SID buffer" );
00809 
00810     rc = 0; // assume all is well
00811     tempnamelen = tempdomainlen = 256;
00812     tempname = new TCHAR[tempnamelen];
00813     tempdomain = new TCHAR[tempdomainlen];
00814     if ( ! ::LookupAccountSid( server, ps, tempname, &tempnamelen,
00815         tempdomain, &tempdomainlen, &snu ) )
00816     {
00817         // it failed == buffers too small?
00818         rc = GetLastError();
00819         delete [] tempname;
00820         delete [] tempdomain;
00821         if ( rc == ERROR_INSUFFICIENT_BUFFER )
00822         {
00823             tempname = new TCHAR[tempnamelen];
00824             tempdomain = new TCHAR[tempdomainlen];
00825             if ( ! ::LookupAccountSid( server, ps, tempname, &tempnamelen,
00826                 tempdomain, &tempdomainlen, &snu ) )
00827             {
00828                 delete [] tempname;
00829                 delete [] tempdomain;
00830                 throw NEWEX32( errInvalidSid, "sid::LookupSid(): LookupAccountSid() failed, see GetErrWin32()", GetLastError() );
00831             }
00832         }
00833         else
00834             throw NEWEX32( errInvalidSid, "sid::LookupSid(): LookupAccountSid() failed, see GetErrWin32()", rc );
00835     }
00836 
00837     name = tempname;
00838     domain = tempdomain;
00839 
00840     delete [] tempname;
00841     delete [] tempdomain;
00842 }

SidType fksec::sid::LookupSidType ( )
 

determines the server on which the SID resides.

This method finds out whether the SID is in the local SAM, whether it comes from the domain that this machine is a server of, or whether it is a "special" SID such as the ones in the BUILTIN domain.

Returns:
a sid::SidType enumeration value representing the SID status.
Exceptions:
errInvalidSid  
errNoPrefixSid  
errTooManySubauths   (from AppendSubAuthority() only)

Definition at line 854 of file sid.cpp.

00855 {
00856     const SID_IDENTIFIER_AUTHORITY sec_nt_auth = SECURITY_NT_AUTHORITY;
00857     DWORD rc;
00858     byte *buf = 0;
00859 
00860     byte buf2[SID_MAX_SUB_AUTHORITIES * sizeof DWORD + sizeof SID_IDENTIFIER_AUTHORITY + sizeof DWORD];
00861     TCHAR refdom[256], dom[256];
00862     SID_NAME_USE snu;
00863     wchar_t *ws;
00864     sid temp;
00865     DWORD sidsize = sizeof buf2, refdomsize = lenof( refdom );
00866 
00867     if ( ! IsValid() )
00868         throw NEWEX( errInvalidSid, "sid::LookupSidType(): invalid SID" );
00869 
00870     if ( memcmp( &sia, &sec_nt_auth, sizeof sia ) != 0 )
00871         return stWellKnown;
00872 
00873     // for SECURITY_NT_AUTHORITY, we need to look at the first RID, too.
00874     if ( GetSubAuthorityCount() < 1 )
00875         throw NEWEX( errInvalidSid, "sid::LookupSidType(): invalid SID" );
00876 
00877     // local account?
00878     if ( GetSubAuthority( 0 ) == SECURITY_BUILTIN_DOMAIN_RID )
00879         return stWellKnown;
00880 
00881     // domain account?
00882     if ( GetSubAuthority( 0 ) == SECURITY_NT_NON_UNIQUE )
00883     {
00884         rc = NetUserModalsGet( 0, 2, &buf );
00885         if ( rc != ERROR_SUCCESS )
00886             throw NEWEX32( errNoPrefixSid, "sid::LookupSidType(): can't get local domain prefix", rc );
00887 
00888         try {
00889             if ( ( (USER_MODALS_INFO_2 *) buf )->usrmod2_domain_id == 0 )
00890                 throw NEWEX( errNoPrefixSid, "sid::LookupSidType(): NUMG() returned a NULL PSID. Feh!" );
00891 
00892             temp = ( (USER_MODALS_INFO_2 *) buf )->usrmod2_domain_id;
00893             NetApiBufferFree( buf );
00894             buf = 0;
00895             temp.AppendSubAuthority( 0 );
00896             if ( EqualPrefix( temp ) )
00897                 return stLocal;
00898             else
00899             {
00900                 // it's not local; now check if the SID belongs to the domain
00901                 // that we are a member of (if we are, that is).
00902 
00903                 // first, find the domain name
00904                 rc = NetWkstaGetInfo( 0, 100, &buf );
00905                 if ( rc != ERROR_SUCCESS )
00906                     throw NEWEX32( errNoPrefixSid, "sid::LookupSidType(): cannot get member domain name", rc );
00907 
00908                 // so, are we a domain member in the first place?
00909                 ws = (wchar_t *) ( (WKSTA_INFO_100 *) buf )->wki100_langroup;
00910                 if ( ws == 0 || ws[0] == L'\0' )
00911                 {
00912                     NetApiBufferFree( buf );
00913                     return stForeign;
00914                 }
00915 
00916 #ifdef UNICODE
00917                 wcscpy( dom, ws );
00918 #else
00919                 wcstombs( dom, ws, sizeof dom );
00920 #endif
00921                 NetApiBufferFree( buf );
00922                 buf = 0;
00923 
00924                 // now, get the domain SID
00925                 if ( ! LookupAccountName( 0, dom, buf2, &sidsize, refdom, &refdomsize, &snu ) )
00926                     throw NEWEX32( errNoPrefixSid, "sid::LookupSidType(): cannot get member domain SID", GetLastError() );
00927 
00928                 try {
00929                     temp = buf2;
00930                     temp.AppendSubAuthority( 0 );
00931                     if ( EqualPrefix( temp ) )
00932                         return stDomain;
00933                     else
00934                         return stForeign;
00935                 }
00936                 RETHROWEX( "sid::LookupSidType(): compare to domain acct prefix failed" )
00937             }
00938         }
00939         catch ( ex *e )
00940         {
00941             e->FKSECADDHOP( "sid::LookupSidType(): compare to machine acct prefix failed" );
00942             if ( buf != 0 )
00943                 NetApiBufferFree( buf );
00944             throw;
00945         }
00946     }
00947 
00948     return stWellKnown;
00949 }

PSID fksec::sid::MakePSID ( ) const [private]
 

generates a PSID from *this.

MakePSID() takes no action if havePSID is already true. If havePSID is false, the method allocates a buffer for a SID and fills it with the SID components in *this. The member psid is set to the address of the buffer, and havePSID is set to true.

Returns:
the value of psid, pointing to the SID.
Exceptions:
errInvalidSid  
errNoMemory  

Definition at line 1292 of file sid.cpp.

01293 {
01294     if ( ! isValid )
01295         throw NEWEX( errInvalidSid, "sid::MakePSID(): invalid SID" );
01296 
01297     if ( ! havePSID )
01298     {
01299         DWORD i;
01300 
01301         psid = (PSID) new byte[GetLength()];
01302         if ( psid == 0 )
01303             throw NEWEX( errNoMemory, "sid::MakePSID(): no memory for SID buffer" );
01304 
01305         if ( InitializeSid( psid, &sia, (byte) subAuthCount ) )
01306             for ( i = 0; i < subAuthCount; ++ i )
01307                 *GetSidSubAuthority( psid, i ) = subAuth[i];
01308         else
01309         {
01310             delete [] (byte *) psid;
01311             psid = 0;
01312             throw NEWEX( errInvalidSid, "sid::MakePSID(): invalid SID" );
01313         }
01314 
01315         havePSID = true;
01316     }
01317 
01318     return psid;
01319 }

SidList fksec::sid::MemberOf ( bool bIncludeGlobal,
bool bIncludeLocal,
bool bIncludeIndirect,
const TCHAR * server = NULL )
 

retrieves the list of groups that this user is a member of.

This method uses NetUserGetGroups & NetUserGetLocalGroups to retrieve the list of groups that this user is a member of. The server to perform this check on can optionally be specified (by default it is the local machine), the server must be specified in UNC format, and remember to escape the \'s (e.g. _T("\\\\someServer"). Note that the Net* Functions are Unicode only; if this code is built as ANSI it will perform the relevant conversions required, but obviously building the Unicode version is recommended.

Parameters:
bIncludeGlobal   controls whether the domain global groups are queried.
bIncludeLocal   controls whether the server local groups are queried.
bIncludeIndirect   for local groups, if this is specified, the list includes any groups that the user is an indirect member (by virtual of being a member of a global group, which is a member of a local group)
server   specify the UNC name of the server to run the query against.
Returns:
a SidList of the groups.
Exceptions:
errInvalidSid  
errNoMemory  
errNetApi32  

Definition at line 970 of file sid.cpp.

00971 {
00972     SidList list ;
00973     fkstr name, domain ;
00974     SID_NAME_USE snu ; 
00975     DWORD cRead, cTotal ;
00976     NET_API_STATUS rc = NERR_Success ;
00977     try {
00978         LookupSid( server, name, domain, snu );
00979     }
00980     RETHROWEX("sid::MemberOf(): sid::LookupSid() failed")
00981     
00982 #ifdef _UNICODE
00983         LPCWSTR szName = name.c_str() ;
00984         LPCWSTR szServer = server ;
00985 #else
00986         // the Net* API is UNICODE only, so for ANSI builds, we need to mess around with W2A & A2W conversions
00987         std::auto_ptr<WCHAR> swName ( Ansi2Unicode(name.c_str()) ) ;
00988         LPCWSTR szName = swName.get() ;
00989         LPCWSTR szServer = NULL ;
00990         std::auto_ptr<WCHAR> swServer ;
00991         if ( server )
00992         {
00993             swServer = Ansi2Unicode(server) ;
00994             szServer = swServer.get() ;
00995         }
00996         static const int CONV_BUFF_LEN = UNCLEN + GNLEN + 2 ;
00997         char szConvBuffer[CONV_BUFF_LEN] ;
00998 #endif
00999 
01000     if ( bIncludeGlobal )
01001     {
01002         GROUP_USERS_INFO_0 * buf = 0 ;
01003         rc = ::NetUserGetGroups( szServer, szName, 0, (BYTE **)&buf, MAX_PREFERRED_LENGTH, &cRead, &cTotal ) ;
01004         if ( NERR_Success == rc )
01005         {
01006             list.reserve(cTotal) ;
01007             sid s ;
01008             while ( cRead-- )
01009             {
01010                 // arrrghh, the PSID constructor / assignment operator, means the compiler won't pick an ANSI/UNICODE mismatch here
01011                 #ifdef _UNICODE
01012                     s = buf[cRead].grui0_name ;
01013                 #else
01014                     WideCharToMultiByte ( CP_ACP, 0 , buf[cRead].grui0_name, -1, szConvBuffer, CONV_BUFF_LEN, NULL, NULL ) ;
01015                     s = szConvBuffer ;
01016                 #endif
01017                 list.push_back(s) ;
01018             }
01019             NetApiBufferFree(buf) ;
01020             buf = 0 ;
01021         }
01022         else
01023             throw NEWEX32( errNetApi32, "sid::MemberOf(): NetUserGetGroups() failed, see GetErrWin32()", rc ) ;
01024     }
01025 
01026     if ( bIncludeLocal )
01027     {
01028         LOCALGROUP_USERS_INFO_0 * buf = 0 ;
01029         rc = ::NetUserGetLocalGroups(szServer, szName, 0, bIncludeIndirect ? LG_INCLUDE_INDIRECT : 0, (BYTE **)&buf, MAX_PREFERRED_LENGTH, &cRead, &cTotal ) ;
01030         if ( NERR_Success == rc )
01031         {
01032             list.reserve(list.size() + cTotal ) ;
01033             sid s ;
01034             while ( cRead-- )
01035             {
01036                 #ifdef _UNICODE
01037                     s = buf[cRead].lgrui0_name ;
01038                 #else
01039                     WideCharToMultiByte ( CP_ACP, 0 , buf[cRead].lgrui0_name, -1, szConvBuffer, CONV_BUFF_LEN, NULL, NULL ) ;
01040                     s = szConvBuffer ;
01041                 #endif
01042                 list.push_back(s);
01043             }
01044             NetApiBufferFree(buf) ;
01045             buf = 0 ;
01046         }
01047         else
01048             throw NEWEX32 ( errNetApi32, "sid::MemberOf(): NetUserGetLocalGroups() failed, see GetErrWin32()", rc ) ;
01049     }
01050     return list ;
01051 }

SidList fksec::sid::Members ( const TCHAR * server = NULL )
 

retrieves all the members of this group.

This method uses NetLocalGroupGetMembers or NetGroupGetUsers to retrieve the list of members for this group. The server to perform this check on can optionally be specified (by default it is the local machine), the server must be specified in UNC format, and remember to escape the \'s (e.g. _T("\\\\someServer"). Note that the Net* Functions are Unicode only; if this code is built as ANSI it will perform the relevant conversions required, but obviously building the Unicode version is recommended.

Parameters:
server   specify the UNC name of the server to run the query against.
Returns:
a SidList of the group members
Exceptions:
errInvalidSid  
errNoMemory  
errNetApi32  

Definition at line 1067 of file sid.cpp.

01068 {
01069     SidList list ;
01070     fkstr name, domain ;
01071     SID_NAME_USE snu ; 
01072     DWORD cRead, cTotal ;
01073     NET_API_STATUS rc = NERR_Success ;
01074     BYTE * buf = 0 ;
01075     try {
01076         LookupSid( server, name, domain, snu );
01077     }
01078     RETHROWEX("sid::MemberOf(): sid::LookupSid() failed")
01079 
01080 #ifdef _UNICODE
01081         LPCWSTR szName = name.c_str() ;
01082         LPCWSTR szServer = server ;
01083 #else
01084         // the Net* API is UNICODE only 
01085         std::auto_ptr<WCHAR> swName = Ansi2Unicode(name.c_str()) ;
01086         LPCWSTR szName = swName.get() ;
01087         std::auto_ptr<WCHAR> swServer ;
01088         LPCWSTR szServer = NULL ;
01089         if ( server )
01090         {
01091             swServer = Ansi2Unicode(server) ;
01092             szServer = swServer.get() ;
01093         }
01094         static const int CONV_BUFF_LEN = UNCLEN + GNLEN + 2 ;
01095         char szConvBuffer[CONV_BUFF_LEN] ;
01096 #endif
01097 
01098     if ( SidTypeAlias == snu )
01099     {
01100         LOCALGROUP_MEMBERS_INFO_0 * buf = 0 ;
01101         rc = ::NetLocalGroupGetMembers ( szServer, szName, 0, (BYTE **)&buf, MAX_PREFERRED_LENGTH, &cRead, &cTotal, NULL ) ;
01102         if ( NERR_Success == rc )
01103         {
01104             list.reserve(cTotal) ;
01105             while ( cRead-- )
01106                 list.push_back(buf[cRead].lgrmi0_sid) ;
01107         }
01108         else
01109             throw NEWEX32 ( errNetApi32, "sid::Members(): NetLocalGroupGetMembers failed, see GetErrWin32()", rc) ;
01110     }
01111     else
01112     {
01113         GROUP_USERS_INFO_0  * buf = 0 ;
01114         rc = ::NetGroupGetUsers ( szServer, szName, 0, (BYTE **)&buf, MAX_PREFERRED_LENGTH, &cRead, &cTotal, NULL ) ;
01115         if ( NERR_Success == rc ) 
01116         {
01117             list.reserve(list.size() + cTotal) ;
01118             sid s ;
01119             while ( cRead-- )
01120             {
01121                 #ifdef _UNICODE
01122                     s = buf[cRead].grui0_name ;
01123                 #else
01124                     WideCharToMultiByte ( CP_ACP, 0 , buf[cRead].grui0_name, -1, szConvBuffer, CONV_BUFF_LEN, NULL, NULL ) ;
01125                     s = szConvBuffer ;                  
01126                 #endif
01127                 list.push_back(s) ;
01128             }
01129             NetApiBufferFree(buf) ;
01130             buf = 0 ;
01131         }
01132         else
01133             throw NEWEX32 ( errNetApi32, "sid::Members(): NetGroupGetUsers() failed, see GetErrWin32()", rc ) ;
01134     }
01135 
01136     return list ;
01137 }

void fksec::sid::ReleasePSID ( ) const [private]
 

releases psid memory, if any, and sets psid to NULL and havePSID to false.

Exceptions:
none  

Definition at line 1201 of file sid.cpp.

01202 {
01203     if ( havePSID )
01204     {
01205         delete [] (byte *) psid;
01206         psid = 0;
01207         havePSID = false;
01208     }
01209 }

void fksec::sid::RemoveLastRid ( )
 

truncates *this by removing the last subauthority value.

One of the uses for this method is getting a domain SID from a user or group SID.

Exceptions:
errInvalidSid  

Definition at line 466 of file sid.cpp.

00467 {
00468     if ( ! isValid || subAuthCount == 0 )
00469         throw NEWEX( errInvalidSid, "sid::RemoveLastRid(): invalid SID" );
00470 
00471     ReleasePSID();
00472     -- subAuthCount;
00473     subAuth[subAuthCount] = 0;
00474 }

void fksec::sid::SetSubAuthority ( DWORD index,
DWORD rid )
 

sets a new value for an existing RID.

Note that subauthority index values range from 0 through GetSubAuthorityCount() - 1. This method can not be used to lengthen or truncate a sid.

Parameters:
index   the zero-based index of the RID to be changed
rid   the new value to be set for that RID
Exceptions:
errInvalidSid  
errInvalidSubAuthIndex  

Definition at line 504 of file sid.cpp.

00505 {
00506     if ( ! isValid )
00507         throw NEWEX( errInvalidSid, "sid::SetSubAuthority(): invalid SID" );
00508 
00509     if ( index >= subAuthCount )
00510         throw NEWEX( errInvalidSubAuthIndex,
00511             "sid::SetSubAuthority(): invalid subauthority index" );
00512 
00513     ReleasePSID();
00514     subAuth[index] = rid;
00515 }

const TCHAR * fksec::sid::SnuToText ( SID_NAME_USE snu ) [static]
 

translates SID_NAME_USE to text description.

SnuToText() looks up a short textual representation for the SID_NAME_USE argument value. This method does not return localized strings.

Parameters:
snu   the SID_NAME_USE value for which a name is sought
Returns:
a const TCHAR* to the description string, or to the string "*SNU?*" if the argument is an unknown SID_NAME_USE value.
Exceptions:
none  

Definition at line 582 of file sid.cpp.

00583 {
00584     static TCHAR *snuText[16] = { 0 };
00585     static const TCHAR *badSnuText = _T( "*SNU?*" );
00586     static bool snuTextInitialized = false;
00587 
00588     if ( ! snuTextInitialized )
00589     {
00590         snuTextInitialized = true;
00591         snuText[SidTypeUser]            = _T( "user" );
00592         snuText[SidTypeGroup]           = _T( "group" );
00593         snuText[SidTypeDomain]          = _T( "domain" );
00594         snuText[SidTypeAlias]           = _T( "alias" );
00595         snuText[SidTypeWellKnownGroup]  = _T( "well-known group" );
00596         snuText[SidTypeDeletedAccount]  = _T( "deleted" );
00597         snuText[SidTypeInvalid]         = _T( "invalid" );
00598         snuText[SidTypeUnknown]         = _T( "unknown" );
00599         snuText[SidTypeComputer]        = _T( "computer" );
00600     }
00601 
00602     if ( snu < (SID_NAME_USE) 1 || snu > lenof( snuText ) || snuText[snu] == 0 )
00603         return badSnuText;
00604 
00605     return snuText[snu];
00606 }

void fksec::sid::StoreSid ( PSID ps,
DWORD size ) const
 

stores a SID into a client-provided buffer.

StoreSid() fills a client-allocated buffer with the NT-formatted SID corresponding to *this' contents, unless size is less than needed; in that case, an exception is raised.

Parameters:
ps   points to the (caller-allocated) buffer in which to place the NT-formatted SID
size   is the size, in bytes, of the buffer provided by the caller
Exceptions:
errInvalidSid  
errBufferTooSmall  

Definition at line 659 of file sid.cpp.

00660 {
00661     DWORD i;
00662 
00663     if ( ! isValid )
00664         throw NEWEX( errInvalidSid, "sid::StoreSid(): invalid SID" );
00665 
00666     i = GetLength();
00667     if ( size < i )
00668         throw new ex( _T( __FILE__ ), __LINE__, errBufferTooSmall,
00669             _T( "sid::StoreSid(): provided buffer is too small, ex::GetData() gives required size" ), 0, i );
00670 
00671     if ( InitializeSid( ps, &sia, (byte) subAuthCount ) )
00672         for ( i = 0; i < subAuthCount; ++ i )
00673             *GetSidSubAuthority( ps, i ) = subAuth[i];
00674     else
00675         throw NEWEX32( errInvalidSid,
00676             "sid::StoreSid(): InitializeSid() failed, see GetErrWin32()", GetLastError() );
00677 }

fksec::sid::operator const PSID ( ) const
 

return a pointer to an NT-formatted SID.

Creates an NT-formatted SID in storage internal to the object, and returns a pointer to that memory. The returned pointer is only guaranteed to be valid until the next method is invoked on the object.

Note: a PSID is essentially a typedef for a void*. This may lead to conversions where you do not want them.

Returns:
a const pointer to SID (PSID) which is typedef-ed as a const pointer to void.
Exceptions:
errInvalidSid  
errNoMemory  

Definition at line 288 of file sid.cpp.

00289 {
00290     if ( ! isValid )
00291         throw NEWEX( errInvalidSid, "sid::operator const PSID(): invalid SID" );
00292 
00293     try { MakePSID(); }
00294     RETHROWEX( "sid::operator const PSID(): MakePSID() failed" )
00295 
00296     return psid;
00297 }

bool fksec::sid::operator!= ( const sid & r ) const
 

compares two sid objects for inequality.

Compares *this with r and returns the result.

The != operator considers two SIDs(and sids) to be equal if and only if they have the same authority value, subauthority count, and subauthority lists.

Parameters:
r   the right-hand side sid for the comparison
Return values:
true   if *this is not equal to r.
false   if *this is equal to r.
Exceptions:
errInvalidSid  

Definition at line 387 of file sid.cpp.

00388 {
00389     DWORD i;
00390 
00391     if ( ! isValid || ! r.isValid )
00392         throw NEWEX( errInvalidSid, "sid::operator!=( sid ): invalid SID" );
00393 
00394     if ( subAuthCount != r.subAuthCount || 0 != memcmp( &sia, &r.sia, sizeof( sia ) ) )
00395         return true;
00396 
00397     for ( i = 0; i < subAuthCount; ++ i )
00398         if ( subAuth[i] != r.subAuth[i] )
00399             return true;
00400 
00401     return false;
00402 }

bool fksec::sid::operator< ( const sid & r ) const
 

compares two sid objects for less-than.

Compares *this with r and returns the result.

The < operator compares by the following arbitrary ordering: If this has less subauthorities than r, *this is smaller. If *this has more subauthorities than r, r is smaller. Else, if the numerical value of this->sia is less than r.sia, *this is smaller; if this->sia is higher than r.sia, r is smaller. If, after this, the subauthority count and the SIA have proved equal, the lists of subauthorities are compared left to right. The relation between the first two unequal subauthorities determines the final result. If no unequal subauthorities exist, the SIDs are equal, and the result is false (since "==" implies "not <").

Parameters:
r   the right-hand side sid for the comparison
Return values:
true   if *this is "less" than r.
false   if *this is not "less" than r.
Exceptions:
errInvalidSid  

Definition at line 319 of file sid.cpp.

00320 {
00321     DWORD i;
00322     __int64 tsia, rsia;
00323 
00324     if ( ! isValid || ! r.isValid )
00325         throw NEWEX( errInvalidSid, "sid::operator<( sid ): invalid SID" );
00326 
00327     tsia = GetSidIdentifierAuthority();
00328     rsia = r.GetSidIdentifierAuthority();
00329     if ( tsia < rsia )
00330         return true;
00331     if ( tsia > rsia )
00332         return false;
00333 
00334     if ( subAuthCount < r.subAuthCount )
00335         return true;
00336     if ( subAuthCount > r.subAuthCount )
00337         return false;
00338 
00339     for ( i = 0; i < subAuthCount; ++ i )
00340     {
00341         if ( subAuth[i] < r.subAuth[i] )
00342             return true;
00343         if ( subAuth[i] > r.subAuth[i] )
00344             return false;
00345     }
00346 
00347     return false;
00348 }

const sid & fksec::sid::operator= ( const TCHAR * name )
 

set *this to a SID derived from interpreting a string SID or looking a name up in the accounts database.

The operator first tries to parse the string as a text-SID ("S-1-5-..."); if that fails, it calls LookupAccountName() with server == NULL (i.e., it asks the local machine to find the name). If this works, the SID is stored in *this.

Parameters:
name   a pointer to a null-terminted string naming either a valid account like felixk, MVPS\\felixk, or felixk@nt.mvps.org, or a SID in string form, such as S-1-5-18
Returns:
a const reference to *this.
Exceptions:
errNoMemory  
errInvalidSid   (both from LookupName())

Definition at line 248 of file sid.cpp.

00249 {
00250     ReleasePSID();
00251     Init();
00252 
00253     try { ConvertFromStringSid( name ); }
00254     catch ( ex *e )
00255     {
00256         if ( e->GetErr() != errInvalidSid )
00257         {
00258             e->FKSECADDHOP( "sid::operator=(TCHAR*)" );
00259             throw;
00260         }
00261 
00262         // invalid SID, let's try something different
00263         delete e;
00264 
00265         try { LookupName( /* server */ 0, name ); }
00266         RETHROWEX( "sid::operator=(TCHAR*)" )
00267     }
00268 
00269 
00270     return *this;
00271 }

const sid & fksec::sid::operator= ( const PSID s )
 

set *this to a copy of a SID.

Parses the SID and stashes its contents in *this. Note that the sid class does not wrap the PSID; you can free the PSID after this function returns.

Parameters:
s   a pointer to an NT-formatted SID
Returns:
a const reference to *this.
Exceptions:
none  

Definition at line 208 of file sid.cpp.

00209 {
00210     DWORD i;
00211 
00212     if ( havePSID && psid == s )
00213         return *this;
00214 
00215     ReleasePSID();
00216     Init();
00217     if ( ::IsValidSid( s ) )
00218     {
00219         isValid = true;
00220         sia = *::GetSidIdentifierAuthority( s );
00221         subAuthCount = (DWORD) *::GetSidSubAuthorityCount( s );
00222         if ( subAuthCount < lenof( subAuth ) )
00223         {
00224             for ( i = 0; i < subAuthCount; ++ i )
00225                 subAuth[i] = *::GetSidSubAuthority( s, i );
00226         }
00227         else
00228             throw NEWEX( errTooManySubAuths,
00229                 "sid::operator=( PSID ): more than SID_MAX_SUB_AUTHORITIES subauthorities in the SID" );
00230     }
00231     else
00232         throw NEWEX( errInvalidSid, "sid::operator=( PSID ): invalid SID passed in" );
00233 
00234     return *this;
00235 }

const sid & fksec::sid::operator= ( const sid & s )
 

set *this to a copy of a sid, including the valid/invalid state.

Parameters:
s   the sid to crib from
Returns:
a const reference to *this
Exceptions:
none  

Definition at line 184 of file sid.cpp.

00185 {
00186     if ( this != &s )
00187     {
00188         ReleasePSID();
00189         isValid = s.isValid;
00190         if ( isValid )
00191         {
00192             sia = s.sia;
00193             subAuthCount = s.subAuthCount;
00194             memcpy( subAuth, s.subAuth, sizeof subAuth );
00195         }
00196     }
00197 
00198     return *this;
00199 }

bool fksec::sid::operator== ( const sid & r ) const
 

compares two sid objects for equality.

Compares *this with r and returns the result.

The == operator considers two SIDs(and sids) to be equal if and only if they have the same authority value, subauthority count, and subauthority lists.

Parameters:
r   the right-hand side sid for the comparison
Return values:
true   if *this is equal to r.
false   if *this is not equal to r.
Exceptions:
errInvalidSid  

Definition at line 360 of file sid.cpp.

00361 {
00362     DWORD i;
00363 
00364     if ( ! isValid || ! r.isValid )
00365         throw NEWEX( errInvalidSid, "sid::operator==( sid ): invalid SID" );
00366 
00367     if ( subAuthCount != r.subAuthCount || 0 != memcmp( &sia, &r.sia, sizeof( sia ) ) )
00368         return false;
00369 
00370     for ( i = 0; i < subAuthCount; ++ i )
00371         if ( subAuth[i] != r.subAuth[i] )
00372             return false;
00373 
00374     return true;
00375 }


Friends And Related Function Documentation

fkostream & operator<< ( fkostream & o,
const sid & s ) [friend]
 

Inserts a textual representation, suitable for debugging, into an output stream.


Member Data Documentation

bool fksec::sid::havePSID [mutable, private]
 

havePSID indicates whether psid is valid and points to an NT-formatted SID reflecting the contents of *this.

If havePSID is false, psid is invalid, even if non-NULL. Do not rely on whether psid is NULL or not!

See also:
MakePSID() , ReleasePSID()

Definition at line 241 of file sid.h.

bool fksec::sid::isValid [private]
 

isValid remains false until a valid SID can be built.

Definition at line 221 of file sid.h.

PSID fksec::sid::psid [mutable, private]
 

psid points to a new()ed chunk of memory which holds an NT-formatted SID representing *this.

If havePSID is false, psid is not to be relied on!

Definition at line 245 of file sid.h.

SID_IDENTIFIER_AUTHORITY fksec::sid::sia [mutable, private]
 

sia contains the sid's SID_IDENTIFIER_AUTHORITY value.

sia is mutable because InitializeSid() wants a non-const pointer. Feh!

Definition at line 228 of file sid.h.

const sid fksec::sid::sidAnonymousLogon [static]
 

S-1-5-7 Anonymous (null session).

Definition at line 285 of file sid.h.

const sid fksec::sid::sidAuthenticated [static]
 

S-1-5-11 Authenticated users (as opposed to World).

Definition at line 293 of file sid.h.

const sid fksec::sid::sidBatch [static]
 

S-1-5-3 Batch logons.

Definition at line 277 of file sid.h.

const sid fksec::sid::sidBuiltin [static]
 

S-1-5-32 built-in domain.

Definition at line 312 of file sid.h.

const sid fksec::sid::sidCreatorGroup [static]
 

S-1-3-1 Creator Group.

Definition at line 261 of file sid.h.

const sid fksec::sid::sidCreatorGroupServer [static]
 

S-1-3-3 Creator Group Server.

Definition at line 265 of file sid.h.

const sid fksec::sid::sidCreatorOwner [static]
 

S-1-3-0 Creator Owner.

Definition at line 259 of file sid.h.

const sid fksec::sid::sidCreatorOwnerServer [static]
 

S-1-3-2 Creator Owner Server.

Definition at line 263 of file sid.h.

const sid fksec::sid::sidDialup [static]
 

S-1-5-1 Dialup users.

Definition at line 273 of file sid.h.

const sid fksec::sid::sidInteractive [static]
 

S-1-5-4 Interactive logons.

Definition at line 279 of file sid.h.

const sid fksec::sid::sidLocal [static]
 

S 1-2-0 Local.

Definition at line 257 of file sid.h.

const sid fksec::sid::sidLocalAccountOperators [static]
 

S-1-5-32-548 Account Operators.

Definition at line 326 of file sid.h.

const sid fksec::sid::sidLocalAdministrator [static]
 

S-1-5-32-500 local admin account.

Definition at line 314 of file sid.h.

const sid fksec::sid::sidLocalAdministrators [static]
 

S-1-5-32-544 Administrators.

Definition at line 318 of file sid.h.

const sid fksec::sid::sidLocalBackupOperators [static]
 

S-1-5-32-551 Backup Operators.

Definition at line 332 of file sid.h.

const sid fksec::sid::sidLocalGuest [static]
 

S-1-5-32-501 local guest account.

Definition at line 316 of file sid.h.

const sid fksec::sid::sidLocalGuests [static]
 

S-1-5-32-546 Guests.

Definition at line 322 of file sid.h.

const sid fksec::sid::sidLocalPowerUsers [static]
 

S-1-5-32-547 Power Users.

Definition at line 324 of file sid.h.

const sid fksec::sid::sidLocalPreW3KCompAccess [static]
 

S-1-5-32-554 SID used to validate Net*() access from NT4 machines.

Definition at line 338 of file sid.h.

const sid fksec::sid::sidLocalPrintOperators [static]
 

S-1-5-32-550 Print Server Operators.

Definition at line 330 of file sid.h.

const sid fksec::sid::sidLocalRasServers [static]
 

S-1-5-32-553 Ras servers.

Definition at line 336 of file sid.h.

const sid fksec::sid::sidLocalReplicator [static]
 

S-1-5-32-552 File replicator account.

Definition at line 334 of file sid.h.

const sid fksec::sid::sidLocalSystem [static]
 

S-1-5-18 LocalSystem (NT AUTHORITY\SYSTEM).

Definition at line 299 of file sid.h.

const sid fksec::sid::sidLocalSystemOperators [static]
 

S-1-5-32-549 System Operators.

Definition at line 328 of file sid.h.

const sid fksec::sid::sidLocalUsers [static]
 

S-1-5-32-545 Users.

Definition at line 320 of file sid.h.

const sid fksec::sid::sidLogon [static]
 

S-1-5-5- prefix for logon session SIDs, requires two more RIDs.

Definition at line 281 of file sid.h.

const sid fksec::sid::sidNetwork [static]
 

S-1-5-2 Network logons.

Definition at line 275 of file sid.h.

const sid fksec::sid::sidNonUnique [static]
 

S-1-5-21- prefix for domains, domain accounts, etc.

Todo:
Add sid::GetDomainFooSid() functions to return domain-SID-dependent well-known SIDs.

Definition at line 306 of file sid.h.

const sid fksec::sid::sidNtAuthority [static]
 

S-1-5- prefix for built-in accounts and groups.

Definition at line 271 of file sid.h.

const sid fksec::sid::sidNull [static]
 

S-1-0-0 null SID.

Definition at line 253 of file sid.h.

const sid fksec::sid::sidProxy [static]
 

S-1-5-8 Logon by proxy.

Definition at line 287 of file sid.h.

const sid fksec::sid::sidRestricted [static]
 

S-1-5-12 Indicates a restricted token.

Definition at line 295 of file sid.h.

const sid fksec::sid::sidSelf [static]
 

S-1-5-10 Self (current caller).

Definition at line 291 of file sid.h.

const sid fksec::sid::sidServerLogon [static]
 

S-1-5-9 DC account.

Definition at line 289 of file sid.h.

const sid fksec::sid::sidService [static]
 

S-1-5-6 Service logons.

Definition at line 283 of file sid.h.

const sid fksec::sid::sidTerminalServer [static]
 

S-1-5-13 Token from Terminal Server.

Definition at line 297 of file sid.h.

const sid fksec::sid::sidWorld [static]
 

S-1-1-0 World (Everyone).

Definition at line 255 of file sid.h.

DWORD fksec::sid::subAuth[SID_MAX_SUB_AUTHORITIES] [private]
 

subAuth[] contains the list of subauthorities.

Definition at line 234 of file sid.h.

DWORD fksec::sid::subAuthCount [private]
 

subAuthCount gives the current number of subauthorities in *this.

Definition at line 231 of file sid.h.


The documentation for this class was generated from the following files:
Generated at Mon Oct 16 06:14:23 2000 for fksec by doxygen1.2.2 written by Dimitri van Heesch, © 1997-2000