Unix to Windows Porting Dictionary for HPC

RSS

Links

Function List

setuid


Unix

header files: unistd.h, sys/types.h

int setuid (uid_t uid);
int seteuid (uid_t euid);
int setreuid (uid_t ruid, uid_t euid);

Windows

header file: Winbase.h

BOOL LogonUser(
 __in      LPTSTR lpszUsername,
 __in_opt  LPTSTR lpszDomain,
 __in      LPTSTR lpszPassword,
 __in      DWORD dwLogonType,
 __in      DWORD dwLogonProvider,
 __out     PHANDLE phToken
);

BOOL WINAPI ImpersonateLoggedOnUser(
 __in  HANDLE hToken
);

BOOL WINAPI CreateRestrictedToken(
 __in      HANDLE ExistingTokenHandle,
 __in      DWORD Flags,
 __in      DWORD DisableSidCount,
 __in_opt  PSID_AND_ATTRIBUTES SidsToDisable,
 __in      DWORD DeletePrivilegeCount,
 __in_opt  PLUID_AND_ATTRIBUTES PrivilegesToDelete,
 __in      DWORD RestrictedSidCount,
 __in_opt  PSID_AND_ATTRIBUTES SidsToRestrict,
 __out     PHANDLE NewTokenHandle
);

BOOL WINAPI CreateProcessAsUser(
 __in_opt     HANDLE hToken,
 __in_opt     LPCTSTR lpApplicationName,
 __inout_opt  LPTSTR lpCommandLine,
 __in_opt     LPSECURITY_ATTRIBUTES lpProcessAttributes,
 __in_opt     LPSECURITY_ATTRIBUTES lpThreadAttributes,
 __in         BOOL bInheritHandles,
 __in         DWORD dwCreationFlags,
 __in_opt     LPVOID lpEnvironment,
 __in_opt     LPCTSTR lpCurrentDirectory,
 __in         LPSTARTUPINFO lpStartupInfo,
 __out        LPPROCESS_INFORMATION lpProcessInformation
);

BOOL WINAPI RevertToSelf(void);

BOOL WINAPI SetThreadToken(
 __in_opt  PHANDLE Thread,
 __in_opt  HANDLE Token
);

BOOL WINAPI ImpersonateSelf(
 __in  SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
);
      

Purpose

The purpose of the setuid(), seteuid() functions is to set the real and effective user ID of the current process on a Unix or Unix-like system. The setreuid() function can set both the real and effective user ID at the same time. Implicit is the setting of the saved user ID when these functions are used so that a process can revert back to the original user ID at a later time.

Discussion

On Unix systems some of the security checks are done as a comparison to the real and/or effective user ID of a process. These security checks may allow access to certain resources and/or privileges. When the security check is not validated then the process will be denied certain actions. The results of using these functions affects the security of the entire process (including any threads).

On Windows systems the security paradigm is constructed differently than on Unix or Unix-like systems, however there is enough direct analogy for modifying the source code to perform very similarly. The Windows security model using Access Control Lists (ACL's) can determine whether access should be allowed or denied (explicitly or implicitly). The identity of the user that the process or thread is running in stored in security tokens that will be examined when appropriate. The security token for a process overall can be different than for a specific thread. In fact, each thread of the program can be running with a different user identity.

While running a program with the threads having a different user identity is somewhat analogous to Unix's effective ID great care must be taken when threads will be running with different identities. Such threads should not request actions or information from other threads with different identities, nor should a thread provide actions or information to other threads of a different identity. Such behavior can be security dangerous because it steps around the Windows system security.

You may wish to modify or convert your source code to use Windows function calls to affect either the entire process or threads.

To enact changing the user identity a new security token must be created or duplicated. This token may be modified from the original if duplicated. A new token does not necessarily immediately become active.

A new token can be created with the LogonUser() provided the password of the new user identity is known. A similar function is CreateProcessAsUser() where a new process is started with a different user identity. Another option is to use the CreateRestrictedToken() to duplicate the existing security token for a process with modifications (restriction) to limit or make ineffective entries existing in the token's ACL.

When you have the new token you can activate it with the ImpersonateLoggedOnUser() function call. The impersonation will continue until either the process exits, another ImpersonateLoggedOnUser() is performed or the RevertToSelf() function is called. The ImpersonateLoggedOnUser() function affects the entire process. The RevertToSelf() function affects the entire process.

To affect on a particular thread of a process a token can be applied to a thread using the SetThreadToken() function. The token being used must be created with TOKEN_IMPERSONATE access rights. A thread may return to its original token with the ImpersonateSelf() so that other threads will not be affected by the change as will happen if RevertToSelf() is called.

An impersonation token can be created when LOGON32_LOGON_NETWORK flag is specified as the logon type to the appropriates functions.

The RevertToSelf() and ImpersonateSelf() functions are similar to using the saved user ID's on a Unix system.

On Unix systems if the initial user that the process is running as has "root" powers then the process can switch to any other user ID without restriction. On Windows systems the switching between users requires the use of the password of the new user ID to be successful. Handling this paradigm shift is beyond this dictionary entry.

Example of Use in Windows

BOOL rez;
char username[]="candy@mydomain", passwd[]="jellybean";
HANDLE TokHandle;

rez = LogonUser(username, NULL, passwd, LOGON32_LOGON_NETWORK,
               LOGON32_Provider_DEFAULT, &TokHandle);

if (!rez) {
       printf("could not create token\n");
       return(1);
}

rez = ImpersonateLoggedOnUser(TokHandle);

if (rez) {
       printf("impersonation is successful\n");

       /* do your actions here */

       rez = RevertToSelf();
       if (rez) {
        printf("reverted token back to original\n");
       }
        return(0);
}
else {
       printf("impersonation was not successful\n");
       return(1);
}

    

More Information

blog comments powered by Disqus
Valid HTML 4.01 Transitional Valid CSS!