Re: How to grant Access on Files on a share drive?

From: Jeffrey Tan[MSFT] (v-jetan_at_online.microsoft.com)
Date: 11/18/05


Date: Fri, 18 Nov 2005 11:17:02 GMT

Hi jahrens,

For impersonation does not work on Win2000, I think this is because of the
requirement of LogonUser API. On Win2000, calling LogonUser API requires
SeTcbPrivilige, which is by default only given to SYSTEM account.

So, you should first assign SeTcbPrivilige to your current interactive user
account, then the impersonation will succeed without any problem.

To assign SeTcbPrivilige to certain user account, we have 2 ways:
1. Directly go to Administrative Tools-> Local Security Policy, then
navigate to "Local Policies"->"Local Rights Assignment". In right panel,
click "Act as part of the operating system Properties" and add your current
user account. At last, you must log-off and re-login to let this setting
take effect.
2. Use LSA API to do this programmatically, however, this still requires
log-off and re-login to let this setting take effect, code listed below:
#ifndef UNICODE
#define UNICODE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <Ntsecapi.h>

#ifndef STATUS_SUCCESS
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#endif

#ifdef _DEBUG
#define JASSERT(x) printf x
#else
#define JASSERT(x)
#endif

#define RET_OK 1
#define RET_ERR 2
#define RET_UKN 0

#define MAX_NAME_LEN 200
//////////////////////////////////////////////////////////////////////////

void
InitUnicodeString( OUT PLSA_UNICODE_STRING LsaUnicodeString, IN LPWSTR
pwszString)
{
        memset(LsaUnicodeString, 0, sizeof(LsaUnicodeString));

        LsaUnicodeString->Length = wcslen(pwszString) * sizeof(WCHAR);
        LsaUnicodeString->MaximumLength = LsaUnicodeString->Length +
sizeof(UNICODE_NULL);
        LsaUnicodeString->Buffer = pwszString;
}

//////////////////////////////////////////////////////////////////////////

LSA_HANDLE
WINAPI
OpenPolicy(DWORD DesiredAccess, LPWSTR ServerName)
{
        LSA_HANDLE PolicyHandle = NULL;
        LSA_OBJECT_ATTRIBUTES ObjectAttributes;
        LSA_UNICODE_STRING ServerNameString;
        NTSTATUS Status;

        memset(&ObjectAttributes, 0, sizeof(LSA_OBJECT_ATTRIBUTES));

        InitUnicodeString(&ServerNameString, ServerName);

        Status = LsaOpenPolicy( &ServerNameString,
                &ObjectAttributes,
                DesiredAccess,
                &PolicyHandle);
        if(Status != STATUS_SUCCESS)
        {
                JASSERT(("OpenPolicy->LsaOpenPolicy error %X\n", Status));
        }
        return PolicyHandle;
}

//////////////////////////////////////////////////////////////////////////

BOOL
WINAPI
GetAccountSid(LPTSTR AccountName,
                          PSID *Sid)
{
        PSID pSID = NULL;
        DWORD cbSid = 0;
        LPTSTR DomainName = NULL;
        DWORD cbDomainName = 0;
        SID_NAME_USE SIDNameUse;
        BOOL bDone = FALSE;

        __try
        {
                if(!LookupAccountName(NULL, // we only concertrate local machine.
                        AccountName,
                        pSID,
                        &cbSid,
                        DomainName,
                        &cbDomainName,
                        &SIDNameUse))
                {
                        pSID = (PSID)malloc(cbSid);
                        DomainName = (LPTSTR)malloc(cbDomainName * sizeof(TCHAR));
                        if(!pSID || !DomainName)
                        {
                                JASSERT(("Not enough memory! failed...\n"));
                                __leave;
                        }
                        if(!LookupAccountName(NULL,
                                AccountName,
                                pSID,
                                &cbSid,
                                DomainName,
                                &cbDomainName,
                                &SIDNameUse))
                        {
                                JASSERT(("Not enough memory! failed...\n"));
                                __leave;
                        }
                        bDone = TRUE;
                }
        }
        __finally
        {
                if(DomainName)
                        free(DomainName);
                if(!bDone && pSID)
                        free(pSID);
        }
        if(bDone)
                *Sid = pSID;

        return bDone;
}

//////////////////////////////////////////////////////////////////////////

BOOL
WINAPI
AdjustUserPolicy(LSA_HANDLE PolicyHandle,
                                 PSID pAccountSid,
                                 LPWSTR lpwSePrivilege,
                                 BOOL fRemove)
{
        LSA_UNICODE_STRING SePrivilegeString;
        NTSTATUS Status;

        InitUnicodeString(&SePrivilegeString, lpwSePrivilege);

        if(fRemove)
        {
                Status = LsaRemoveAccountRights(PolicyHandle,
                        pAccountSid,
                        FALSE,
                        &SePrivilegeString,
                        1);
        }
        else
        {
                Status = LsaAddAccountRights(PolicyHandle,
                        pAccountSid,
                        &SePrivilegeString,
                        1);
        }
        return (Status == STATUS_SUCCESS);
}

//////////////////////////////////////////////////////////////////////////

int main(int argc, char** argv)
{
        LSA_HANDLE PolicyHandle = NULL;
        PSID pSid = NULL;
        DWORD cbAccountName = MAX_NAME_LEN;
        TCHAR AccountName[MAX_NAME_LEN];
        TCHAR wComputerName[] = L"";
        int nRet = RET_ERR;

        __try
        {
                if(!GetUserName(AccountName, &cbAccountName))
                {
                        printf("ft..... How long are your name?\n");
                        __leave;
                }

                PolicyHandle = OpenPolicy(POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES,
wComputerName);
                if(!PolicyHandle)
                {
                        printf("OpenPolicy return NULL\n");
                        __leave;
                }

                if(!GetAccountSid(AccountName, &pSid))
                {
                        printf("GetAccountSid return false\n");
                        __leave;
                }

                if(!AdjustUserPolicy(PolicyHandle, pSid, SE_TCB_NAME, FALSE))
                {
                        printf("AdjustUserPolicy return false\n");
                        __leave;
                }
                getchar();
                nRet = RET_OK;
        }
        __finally
        {
                if(pSid)
                        free(pSid);
                if(PolicyHandle)
                        LsaClose(PolicyHandle);
        }

        return nRet;
}

After enabling SeTcbPrivilige, we should can do impersonation without any
problem, my impersonation code listed below:
HANDLE hTok;
BOOL fResult=LogonUser(TEXT("SecurityTest"), TEXT("."),
TEXT("Password01!"),
        LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hTok);
if(!fResult)
{
        printf("LogonUser failed with %d", GetLastError());
        return -1;
}

fResult=ImpersonateLoggedOnUser(hTok);
if(!fResult)
{
        printf("ImpersonateLoggedOnUser failed with %d", GetLastError());
        return -1;
}

fResult=CreateDirectory(TEXT("C:\\Security"), NULL);
if(!fResult)
{
        printf("CreateDirectory failed with %d", GetLastError());
        return -1;
}

fResult=RevertToSelf();
if(!fResult)
{
        printf("RevertToSelf failed with %d", GetLastError());
        return -1;
}
CloseHandle(hTok);

This works well on my test Win2k VPC. Hope it helps

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.



Relevant Pages

  • Re: Impersonation using WindowsIdentity( upn ) ctor
    ... Ok, now, what if I use the LogonUser API? ... the token returned by the API will either be an Impersonation ... Only accounts with with that privilege can create an ... By default, only the SYSTEM account ...
    (microsoft.public.dotnet.security)
  • Re: Impersonation using WindowsIdentity( upn ) ctor
    ... Ok, now, what if I use the LogonUser API? ... the token returned by the API will either be an Impersonation ... Only accounts with with that privilege can create an ... By default, only the SYSTEM account ...
    (microsoft.public.dotnet.framework.aspnet.security)
  • Re: Using windows auth and alternate credentials for sql server
    ... > The WindowsIdentity class is useful to represent a user. ... Get the security token of specific user with LogonUser API via PInvoke ... Undo the Impersonation ...
    (microsoft.public.dotnet.framework.windowsforms)