You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
521 lines
16 KiB
521 lines
16 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
namedpipes.cxx
|
|
|
|
Abstract:
|
|
|
|
namedpipes
|
|
|
|
Author:
|
|
|
|
Larry Zhu (LZhu) January 1, 2002 Created
|
|
|
|
Environment:
|
|
|
|
User Mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "namedpipes.hxx"
|
|
|
|
PCTSTR g_pszPipeName = TEXT("pipetest");
|
|
|
|
|
|
HRESULT
|
|
GetClientImpToken(
|
|
IN ULONG ProcessId,
|
|
IN OPTIONAL PCWSTR pszS4uClientUpn,
|
|
IN OPTIONAL PCWSTR pszS4uClientRealm,
|
|
IN ULONG S4u2SelfFlags,
|
|
OUT HANDLE* phToken
|
|
)
|
|
{
|
|
THResult hRetval = S_OK;
|
|
|
|
UNICODE_STRING ClientUpn = {0};
|
|
UNICODE_STRING ClientRealm = {0};
|
|
UNICODE_STRING Password = {0}; // ignored
|
|
ULONG PackageId = 0;
|
|
HANDLE hLsa = NULL;
|
|
HANDLE hImpToken = NULL;
|
|
|
|
TPrivilege* pPriv = NULL;
|
|
|
|
*phToken = NULL;
|
|
|
|
if (ProcessId)
|
|
{
|
|
hRetval DBGCHK = GetProcessTokenByProcessId(ProcessId, &hImpToken);
|
|
}
|
|
else if (pszS4uClientRealm || pszS4uClientUpn)
|
|
{
|
|
RtlInitUnicodeString(&ClientRealm, pszS4uClientRealm);
|
|
RtlInitUnicodeString(&ClientUpn, pszS4uClientUpn);
|
|
|
|
pPriv = new TPrivilege(SE_TCB_PRIVILEGE, TRUE);
|
|
hRetval DBGCHK = pPriv ? pPriv->Validate() : E_OUTOFMEMORY;
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = GetLsaHandleAndPackageId(
|
|
MICROSOFT_KERBEROS_NAME_A,
|
|
&hLsa,
|
|
&PackageId
|
|
);
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = KrbLsaLogonUser(
|
|
hLsa,
|
|
PackageId,
|
|
Network, // this would cause S4u2self to be used
|
|
&ClientUpn,
|
|
&ClientRealm,
|
|
&Password, // ignored for s4u2self
|
|
S4u2SelfFlags, // Flags for s4u2self
|
|
&hImpToken
|
|
);
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
*phToken = hImpToken;
|
|
hImpToken = NULL;
|
|
}
|
|
|
|
if (hImpToken)
|
|
{
|
|
CloseHandle(hImpToken);
|
|
}
|
|
|
|
if (pPriv)
|
|
{
|
|
delete pPriv;
|
|
}
|
|
|
|
if (hLsa)
|
|
{
|
|
LsaDeregisterLogonProcess(hLsa);
|
|
}
|
|
|
|
return hRetval;
|
|
}
|
|
|
|
DWORD WINAPI ClientThread(IN PVOID pvParam)
|
|
{
|
|
THResult hRetval = S_OK;
|
|
|
|
CHAR Request[MAX_PATH] = {0};
|
|
CHAR Reply[MAX_PATH] = {0};
|
|
ULONG cbRead = 0;
|
|
ULONG cbWritten = 0;
|
|
HANDLE hToken = NULL;
|
|
TImpersonation* pImper = NULL;
|
|
HANDLE hPipe = INVALID_HANDLE_VALUE;
|
|
SECURITY_ATTRIBUTES sa = {0};
|
|
|
|
TClientThreadParam* pClientParam = (TClientThreadParam *) pvParam;
|
|
|
|
SspiPrint(SSPI_LOG, TEXT("ClientThread entering processid %#x, pszPipeName %s, pszS4uClientRealm %s, pszS4uClientUpn %s, S4u2SelfFlags %#x, FlagsAndAttributes %#x\n"),
|
|
pClientParam->ProcessId, pClientParam->pszPipeName, pClientParam->pszS4uClientRealm, pClientParam->pszS4uClientUpn, pClientParam->S4u2SelfFlags, pClientParam->FlagsAndAttributes);
|
|
|
|
memset(Request, 0xef, sizeof(Request) - 1);
|
|
|
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
sa.lpSecurityDescriptor = NULL; // default Dacl of caller
|
|
sa.bInheritHandle = TRUE;
|
|
|
|
hRetval DBGCHK = GetClientImpToken(
|
|
pClientParam->ProcessId,
|
|
pClientParam->pszS4uClientUpn,
|
|
pClientParam->pszS4uClientRealm,
|
|
pClientParam->S4u2SelfFlags,
|
|
&hToken
|
|
);
|
|
|
|
if (SUCCEEDED(hRetval) && hToken)
|
|
{
|
|
pImper = new TImpersonation(hToken);
|
|
hRetval DBGCHK = pImper ? pImper->Validate() : E_OUTOFMEMORY;
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
SspiPrint(SSPI_LOG, TEXT("ClientPipeName %s\n"), pClientParam->pszPipeName);
|
|
|
|
hRetval DBGCHK = WaitNamedPipe(
|
|
pClientParam->pszPipeName,
|
|
60000
|
|
) ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hPipe = CreateFile(
|
|
pClientParam->pszPipeName,
|
|
GENERIC_WRITE | GENERIC_READ,
|
|
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
|
&sa,
|
|
OPEN_EXISTING,
|
|
pClientParam->FlagsAndAttributes ? pClientParam->FlagsAndAttributes : (SECURITY_SQOS_PRESENT | SECURITY_IMPERSONATION),
|
|
NULL
|
|
);
|
|
hRetval DBGCHK = (INVALID_HANDLE_VALUE != hPipe) ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = WriteFile(
|
|
hPipe, // handle to pipe
|
|
Request, // buffer to write from
|
|
sizeof(Request) - 1, // number of bytes to write
|
|
&cbWritten, // number of bytes written
|
|
NULL // not overlapped I/O
|
|
) ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = ReadFile(
|
|
hPipe, // handle to pipe
|
|
Reply, // buffer to receive data
|
|
sizeof(Reply), // size of buffer
|
|
&cbRead, // number of bytes read
|
|
NULL // not overlapped I/O
|
|
) ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
SspiPrintHex(SSPI_LOG, TEXT("Reply"), cbRead, Reply);
|
|
}
|
|
|
|
if (hToken)
|
|
{
|
|
CloseHandle(hToken);
|
|
}
|
|
|
|
if (hPipe != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(hPipe);
|
|
}
|
|
|
|
if (pImper)
|
|
{
|
|
delete pImper;
|
|
}
|
|
|
|
SspiPrint(SSPI_LOG, TEXT("ClientThread leaving %#x\n"), (HRESULT) hRetval);
|
|
|
|
return (HRESULT) hRetval;
|
|
}
|
|
|
|
DWORD WINAPI ServerWokerThread(IN PVOID pvParam)
|
|
{
|
|
THResult hRetval = S_OK;
|
|
|
|
CHAR Request[MAX_PATH] = {0};
|
|
CHAR Reply[MAX_PATH] = {0};
|
|
ULONG cbBytesRead = 0;
|
|
ULONG cbWritten = 0;
|
|
HANDLE hToken = NULL;
|
|
|
|
TServerWorkerThreadParam* pServerParam = (TServerWorkerThreadParam*) pvParam;
|
|
|
|
SspiPrint(SSPI_LOG, TEXT("ServerWokerThread entering ServerPipe is %p, pszCommandLine %s\n"), pServerParam->hPipe, pServerParam->pszCommandLine);
|
|
|
|
memset(Reply, 0xfe, sizeof(Reply) - 1);
|
|
|
|
hRetval DBGCHK = ImpersonateNamedPipeClient(pServerParam->hPipe) ? S_OK : GetLastErrorAsHResult();
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = ReadFile(
|
|
pServerParam->hPipe, // handle to pipe
|
|
Request, // buffer to receive data
|
|
sizeof(Request), // size of buffer
|
|
&cbBytesRead, // number of bytes read
|
|
NULL // not overlapped I/O
|
|
) ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
SspiPrintHex(SSPI_LOG, TEXT("Request"), cbBytesRead, Request);
|
|
|
|
hRetval DBGCHK = WriteFile(
|
|
pServerParam->hPipe, // handle to pipe
|
|
Reply, // buffer to write from
|
|
sizeof(Reply) - 1, // number of bytes to write
|
|
&cbWritten, // number of bytes written
|
|
NULL // not overlapped I/O
|
|
) ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval) && pServerParam->pszCommandLine)
|
|
{
|
|
hRetval DBGCHK = OpenThreadToken(
|
|
GetCurrentThread(),
|
|
MAXIMUM_ALLOWED,
|
|
TRUE,
|
|
&hToken
|
|
) ? S_OK : GetLastErrorAsHResult();
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = StartInteractiveClientProcessAsUser(
|
|
hToken,
|
|
pServerParam->pszCommandLine
|
|
);
|
|
}
|
|
}
|
|
|
|
RevertToSelf();
|
|
|
|
if (hToken)
|
|
{
|
|
CloseHandle(hToken);
|
|
}
|
|
|
|
FlushFileBuffers(pServerParam->hPipe);
|
|
DisconnectNamedPipe(pServerParam->hPipe);
|
|
CloseHandle(pServerParam->hPipe);
|
|
pServerParam->hPipe = INVALID_HANDLE_VALUE;
|
|
|
|
SspiPrint(SSPI_LOG, TEXT("ServerWokerThread leaving %#x\n"), (HRESULT) hRetval);
|
|
|
|
return (HRESULT) hRetval;
|
|
}
|
|
|
|
VOID
|
|
Usage(
|
|
IN PCTSTR pszProgram
|
|
)
|
|
{
|
|
SspiPrint(SSPI_ERROR,
|
|
TEXT("Usage: %s [-noclient] [-noserver] [-pipename <pipename>] [-application <application>]\n")
|
|
TEXT("[-s4uclientupn <clientupn>] [-s4uclientrealm <clientrealm>] [-s4u2selfflags <flags>]\n")
|
|
TEXT("[-clientprocessidtoimperonate <processid>] [-clientflagsandattributes <flagsandattributes>]\n"), pszProgram);
|
|
exit(-1);
|
|
}
|
|
|
|
VOID __cdecl
|
|
_tmain(
|
|
IN INT argc,
|
|
IN PTSTR argv[]
|
|
)
|
|
{
|
|
THResult hRetval = S_OK;
|
|
|
|
INT mark = 1;
|
|
|
|
BOOLEAN bStartClient = TRUE;
|
|
BOOLEAN bStartServer = TRUE;
|
|
|
|
PCTSTR pszPipeName = g_pszPipeName;
|
|
ULONG tid = 0;
|
|
HANDLE hClientThread = NULL;
|
|
HANDLE hServerWorkerThread = NULL;
|
|
TClientThreadParam ClientParam = {0};
|
|
TCHAR szClientPipeName[MAX_PATH] = {0};
|
|
TCHAR szServerPipeName[MAX_PATH] = {0};
|
|
PTSTR pszServerHost = NULL;
|
|
PTSTR pszCommandLine = NULL;
|
|
SECURITY_ATTRIBUTES sa = {0};
|
|
SECURITY_DESCRIPTOR sd = {0};
|
|
BYTE AclBuf[ 64 ] = {0};
|
|
DWORD cbAcl = sizeof(AclBuf);
|
|
PACL pAcl = (PACL)AclBuf;
|
|
|
|
argc--;
|
|
|
|
while (argc)
|
|
{
|
|
if (!lstrcmp(argv[mark], TEXT("-port")) && (argc > 1))
|
|
{
|
|
argc--; mark++;
|
|
pszPipeName = argv[mark];
|
|
argc--; mark++;
|
|
}
|
|
else if (!lstrcmp(argv[mark], TEXT("-application")) && (argc > 1))
|
|
{
|
|
argc--; mark++;
|
|
pszCommandLine = argv[mark];
|
|
argc--; mark++;
|
|
}
|
|
else if (!lstrcmp(argv[mark], TEXT("-su4clientupn")) && (argc > 1))
|
|
{
|
|
argc--; mark++;
|
|
ClientParam.pszS4uClientUpn = argv[mark];
|
|
argc--; mark++;
|
|
}
|
|
else if (!lstrcmp(argv[mark], TEXT("-clientflagsandattributes")) && (argc > 1))
|
|
{
|
|
argc--; mark++;
|
|
ClientParam.FlagsAndAttributes = lstrtol(argv[mark], NULL, 0);
|
|
argc--; mark++;
|
|
}
|
|
else if (!lstrcmp(argv[mark], TEXT("-su42selfflags")) && (argc > 1))
|
|
{
|
|
argc--; mark++;
|
|
ClientParam.S4u2SelfFlags = lstrtol(argv[mark], NULL, 0);
|
|
argc--; mark++;
|
|
}
|
|
else if (!lstrcmp(argv[mark], TEXT("-clientprocessidtoimperonate")) && (argc > 1))
|
|
{
|
|
argc--; mark++;
|
|
ClientParam.ProcessId = lstrtol(argv[mark], NULL, 0);
|
|
argc--; mark++;
|
|
}
|
|
else if (!lstrcmp(argv[mark], TEXT("-serverhost")) && (argc > 1))
|
|
{
|
|
argc--; mark++;
|
|
pszServerHost = argv[mark];
|
|
bStartServer = FALSE;
|
|
argc--; mark++;
|
|
}
|
|
else if (!lstrcmp(argv[mark], TEXT("-noclient")))
|
|
{
|
|
argc--; mark++;
|
|
bStartClient = FALSE;
|
|
}
|
|
else if (!lstrcmp(argv[mark],TEXT("-noserver")))
|
|
{
|
|
argc--; mark++;
|
|
bStartServer = FALSE;
|
|
}
|
|
else
|
|
{
|
|
Usage(argv[0]);
|
|
}
|
|
}
|
|
|
|
SspiLogOpen(TEXT("namedports.exe"), SSPI_LOG | SSPI_WARN | SSPI_ERROR);
|
|
|
|
if (bStartClient)
|
|
{
|
|
ClientParam.pszPipeName = szClientPipeName;
|
|
|
|
hRetval DBGCHK = _sntprintf(szClientPipeName, COUNTOF(szClientPipeName) - 1,
|
|
TEXT("\\\\%s\\pipe\\%s"),
|
|
pszServerHost ? pszServerHost : TEXT("."),
|
|
pszPipeName
|
|
) > 0 ? S_OK : E_INVALIDARG;
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval) && bStartServer)
|
|
{
|
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
sa.lpSecurityDescriptor = &sd;
|
|
sa.bInheritHandle = TRUE;
|
|
|
|
hRetval DBGCHK = BuildNamedPipeAcl(pAcl, &cbAcl) ? S_OK : GetLastErrorAsHResult();
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE) ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = _sntprintf(szServerPipeName, COUNTOF(szServerPipeName) - 1,
|
|
TEXT("\\\\.\\pipe\\%s"),
|
|
pszPipeName
|
|
) > 0 ? S_OK : E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval) && bStartClient)
|
|
{
|
|
hClientThread = CreateThread(NULL, 0, ClientThread, &ClientParam, 0, &tid);
|
|
hRetval DBGCHK = hClientThread ? S_OK : GetLastErrorAsHResult();
|
|
}
|
|
|
|
while (SUCCEEDED(hRetval) && bStartServer)
|
|
{
|
|
TServerWorkerThreadParam ServerParam = {0};
|
|
|
|
SspiPrint(SSPI_LOG, TEXT("Server waiting on pipe %s\n"), szServerPipeName);
|
|
|
|
ServerParam.pszCommandLine = pszCommandLine;
|
|
|
|
ServerParam.hPipe = CreateNamedPipe(
|
|
szServerPipeName,
|
|
PIPE_ACCESS_DUPLEX,
|
|
PIPE_TYPE_BYTE | PIPE_WAIT,
|
|
1,
|
|
4096, // output buffer size
|
|
4096, // input buffer size
|
|
NMPWAIT_USE_DEFAULT_WAIT, // timeout interval
|
|
&sa
|
|
);
|
|
hRetval DBGCHK = (ServerParam.hPipe != INVALID_HANDLE_VALUE) ? S_OK : GetLastErrorAsHResult();
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hRetval DBGCHK = ConnectNamedPipe(
|
|
ServerParam.hPipe,
|
|
NULL // no overlapped structure
|
|
) ? S_OK : GetLastErrorAsHResult();
|
|
if (FAILED(hRetval) && (ERROR_PIPE_CONNECTED == HRESULT_CODE(hRetval)))
|
|
{
|
|
hRetval DBGCHK = S_OK;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval))
|
|
{
|
|
hServerWorkerThread = CreateThread(NULL, 0, ServerWokerThread, &ServerParam, 0, &tid);
|
|
|
|
hRetval DBGCHK = hServerWorkerThread ? S_OK : GetLastErrorAsHResult();
|
|
|
|
if (FAILED(hRetval))
|
|
{
|
|
CloseHandle(ServerParam.hPipe);
|
|
ServerParam.hPipe = INVALID_HANDLE_VALUE;
|
|
}
|
|
else
|
|
{
|
|
(VOID) WaitForSingleObject(hServerWorkerThread, INFINITE);
|
|
}
|
|
|
|
if (hServerWorkerThread)
|
|
{
|
|
CloseHandle(hServerWorkerThread);
|
|
}
|
|
}
|
|
else if (ServerParam.hPipe != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(ServerParam.hPipe);
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hRetval) && hClientThread)
|
|
{
|
|
(VOID) WaitForSingleObject(hClientThread, INFINITE);
|
|
}
|
|
|
|
if (hClientThread)
|
|
{
|
|
CloseHandle(hClientThread);
|
|
}
|
|
|
|
SspiLogClose();
|
|
}
|
|
|