How to get the SID and User Name of the user utilising my service in C++

旧巷老猫 提交于 2021-02-18 18:14:21

问题


I am attempting to create a service that will essentially act as a local web server. In theory users will use a REST API by visiting URIs through localhost in a browser i.e. http://localhost:2017/path/to/function/call will connect to the service and execute a function.

My question is how do I get the SID and User Name of the account that called the service?

I have implemented a couple of solutions but they return the SID and User Name of the service and not the user using it.

OJSon* UnifiedStreamingService::getUserDetails()
{

    OJSon* result = OJSon::create();
    if(result)
    {
        /*
        HANDLE hToken = NULL;
        ULONG id = WTSGetActiveConsoleSessionId();

        BOOL bRet = WTSQueryUserToken(id, &hToken);
        if (bRet == false)
        {
            DWORD error = GetLastError();
            printf("ERROR: %d", error);
        }
        */
        HANDLE hToken = NULL;
        if ( ! OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &hToken ) ) 
        {
            //_tprintf( _T("OpenProcessToken failed. GetLastError returned: %d\n"), GetLastError());
            return NULL;
        }

        // Get the size of the memory buffer needed for the SID
        DWORD dwBufferSize = 0;
        if ( ! GetTokenInformation( hToken, TokenUser, NULL, 0, &dwBufferSize ) && ( GetLastError() != ERROR_INSUFFICIENT_BUFFER ) )
        {
            //_tprintf( _T("GetTokenInformation failed. GetLastError returned: %d\n"), GetLastError());
            // Cleanup
            CloseHandle( hToken );
            hToken = NULL;

            return NULL;
        }
        // Allocate buffer for user token data
        std::vector<BYTE> buffer;
        buffer.resize( dwBufferSize );
        PTOKEN_USER pTokenUser = reinterpret_cast<PTOKEN_USER>( &buffer[0] );
        // Retrieve the token information in a TOKEN_USER structure
        if ( ! GetTokenInformation( 
                 hToken, 
                 TokenUser, 
                 pTokenUser, 
                 dwBufferSize,
                 &dwBufferSize)) 
        {
            //_tprintf( _T("2 GetTokenInformation failed. GetLastError returned: %d\n"), GetLastError());
            // Cleanup
            CloseHandle( hToken );
            hToken = NULL;

            return NULL;
        }
        // Check if SID is valid
        if ( ! IsValidSid( pTokenUser->User.Sid ) ) 
        {
            //_tprintf( _T("The owner SID is invalid.\n") );
            // Cleanup
            CloseHandle(hToken);
            hToken = NULL;

            return NULL;
        }
        // add the name
        OString* name = lookupAccountSid(pTokenUser->User.Sid);
        if(name)
        {
            result->setKey(&OString("name"), name);
            SAFEDELETE(name);
        }
        // add the SID
        OString* sid = convertSidToString(pTokenUser->User.Sid);
        if(sid)
        {
            result->setKey(&OString("SID"), sid);
            SAFEDELETE(sid);
        }
        // Cleanup
        CloseHandle(hToken);
        hToken = NULL;

    }
    return result;
}

OString* UnifiedStreamingService::convertSidToString(PSID pSID)
{
    OString* result = NULL;

    if(pSID)
    {
        // Get string corresponding to SID
        LPTSTR pszSID = NULL;
        if ( ! ConvertSidToStringSid( pSID, &pszSID ) )
        {
            return NULL;
        }
        result = new OString(pszSID);
        // Release buffer allocated by ConvertSidToStringSid API
        LocalFree( pszSID );
        pszSID = NULL;
    }

    return result;
}

OString* UnifiedStreamingService::lookupAccountSid(PSID pSID)
{
DWORD dwSize = 256;
DWORD dwResult = 0;
SID_NAME_USE SidType;
LPTSTR lpName = new TCHAR[dwSize];
LPWSTR lpDomain = new TCHAR[dwSize];
OString* result = NULL;

    if( !LookupAccountSid( NULL, pSID, lpName, &dwSize, lpDomain, &dwSize, &SidType ) ) 
    {
        dwResult = GetLastError();
        return NULL;
    }

    OString* pDomain = new OString(lpDomain);
    OString* pName = new OString(lpName);
    if(pDomain && pName)
    {
        result = OString::createByFormat(&OString("%s\\%s"), pDomain, pName);

        SAFEDELETE(pDomain);
        SAFEDELETE(pName);
    }

    delete[] lpDomain;
    delete[] lpName;

    return result;
}

回答1:


The task can be accomplished by using WTSGetActiveConsoleSessionId and WTSQueryUserToken to get user token and then getting SID with GetTokenInformation. The additional requirement is the service is running under Local System account which grants SE_TCB_NAME privelege (== SeTcbPrivilege). SE_TCB_NAME required by WTSQueryUserToken. Note that the other accounts usually have no SE_TCB_NAME privelege!



来源:https://stackoverflow.com/questions/42483572/how-to-get-the-sid-and-user-name-of-the-user-utilising-my-service-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!