|
|
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: rpc.cpp
//
// Contents: Cert Server RPC
//
// History: 03-Sep-96 larrys created
//
//---------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#include <stdio.h>
#include <accctrl.h>
#include "certrpc.h"
#include "certacl.h"
#include "cscom.h"
#include "resource.h"
#define __dwFILE__ __dwFILE_CERTSRV_RPC_CPP__
RPC_BINDING_VECTOR *pvBindings = NULL;
char *pszProtSeqNp = "ncacn_np";
char *pszProtSeqTcp = "ncacn_ip_tcp";
typedef struct _CS_RPC_ATHN_LIST { DWORD dwAuthnLevel; DWORD dwPrinceNameService; DWORD dwAuthnService; } CS_RPC_ATHN_LIST ;
CS_RPC_ATHN_LIST g_acsAthnList[] = { { RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_GSS_NEGOTIATE, RPC_C_AUTHN_GSS_NEGOTIATE }, { RPC_C_AUTHN_LEVEL_NONE, RPC_C_AUTHN_NONE, RPC_C_AUTHN_NONE } };
DWORD g_ccsAthnList = sizeof(g_acsAthnList)/sizeof(g_acsAthnList[0]);
HRESULT RPCInit(VOID) { char *pszEndpoint = "\\pipe\\cert";
LPSTR pszPrincName = NULL; HRESULT hr; DWORD i;
if (RPC_S_OK == RpcNetworkIsProtseqValidA((unsigned char *) pszProtSeqNp)) { hr = RpcServerUseProtseqEpA( (unsigned char *) pszProtSeqNp, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, (unsigned char *) pszEndpoint, NULL); _JumpIfError(hr, error, "RpcServerUseProtseqEpA"); }
if (RPC_S_OK == RpcNetworkIsProtseqValidA((unsigned char *) pszProtSeqTcp)) {
hr = RpcServerUseProtseqA( (unsigned char *) pszProtSeqTcp, RPC_C_PROTSEQ_MAX_REQS_DEFAULT, NULL); if ((HRESULT) ERROR_OUTOFMEMORY == hr) { OSVERSIONINFO ovi;
ovi.dwOSVersionInfoSize = sizeof(ovi); if (GetVersionEx(&ovi) && VER_PLATFORM_WIN32_NT == ovi.dwPlatformId && 4 >= ovi.dwMajorVersion) { hr = S_OK; // Ignore IP failure
} } _JumpIfError(hr, error, "RpcServerUseProtseqA"); }
hr = RpcServerInqBindings(&pvBindings); _JumpIfError(hr, error, "RpcServerInqBindings");
hr = RpcServerRegisterIf(s_ICertPassage_v0_0_s_ifspec, NULL, NULL); _JumpIfError(hr, error, "RpcServerRegisterIf");
// Register Authentication Services
for (i = 0; i < g_ccsAthnList; i++) {
pszPrincName = NULL; if (g_acsAthnList[i].dwPrinceNameService != RPC_C_AUTHN_NONE) { hr = RpcServerInqDefaultPrincNameA( g_acsAthnList[i].dwPrinceNameService, (BYTE **) &pszPrincName); if (hr != RPC_S_OK) { continue; } }
hr = RpcServerRegisterAuthInfoA( (BYTE *) pszPrincName, g_acsAthnList[i].dwAuthnService, 0, 0); if(hr == RPC_S_UNKNOWN_AUTHN_SERVICE) { continue; } if(hr != RPC_S_OK) { break; } }
if (hr != RPC_S_UNKNOWN_AUTHN_SERVICE) { _JumpIfError(hr, error, "RpcServerRegisterAuthInfoA"); }
hr = RpcEpRegister(s_ICertPassage_v0_0_s_ifspec, pvBindings, NULL, NULL); _JumpIfError(hr, error, "RpcEpRegister");
// Listen, but don't wait...
hr = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); _JumpIfError(hr, error, "RpcServerListen");
error: if (NULL != pszPrincName) { RpcStringFreeA((BYTE **) &pszPrincName); } return(hr); }
HRESULT RPCTeardown(VOID) { HRESULT hr; // tear down, don't wait for calls to complete
hr = RpcServerUnregisterIf(s_ICertPassage_v0_0_s_ifspec, NULL, FALSE); _JumpIfError(hr, error, "RpcServerUnregisterIf");
// We have no good way of knowing if all RPC requests are done, so let it
// leak on shutdown.
// RPC_STATUS RPC_ENTRY RpcMgmtWaitServerListen(VOID); ??
hr = S_OK;
error: return(hr); }
HRESULT SetTransBlobString( CERTTRANSBLOB const *pctb, WCHAR const **ppwsz) { HRESULT hr;
if (NULL != pctb->pb && 0 != pctb->cb) { *ppwsz = (WCHAR const *) pctb->pb;
// use lstrlen here for protection against non-zero terminated bufs!
// lstrlen will catch AV's and return error
if ((lstrlen(*ppwsz) + 1) * sizeof(WCHAR) != pctb->cb) { hr = E_INVALIDARG; _JumpIfError(hr, error, "Bad TransBlob string"); } } hr = S_OK;
error: return(hr); }
/* server prototype */ DWORD s_CertServerRequest( /* [in] */ handle_t h, /* [in] */ DWORD dwFlags, /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority, /* [ref][out][in] */ DWORD __RPC_FAR *pdwRequestId, /* [out] */ DWORD __RPC_FAR *pdwDisposition, /* [ref][in] */ CERTTRANSBLOB const __RPC_FAR *pctbAttribs, /* [ref][in] */ CERTTRANSBLOB const __RPC_FAR *pctbRequest, /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbCertChain, /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbEncodedCert, /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbDispositionMessage) { HRESULT hr = S_OK; DWORD OpRequest; WCHAR const *pwszAttributes = NULL; WCHAR const *pwszSerialNumber = NULL; CERTTRANSBLOB ctbEmpty = { 0, NULL }; CERTTRANSBLOB const *pctbSerial = &ctbEmpty; WCHAR *pwszUserName = NULL; DWORD dwComContextIndex = MAXDWORD; CERTSRV_COM_CONTEXT ComContext; CERTSRV_RESULT_CONTEXT ResultContext; DWORD State = 0;
ZeroMemory(&ComContext, sizeof(ComContext)); ZeroMemory(&ResultContext, sizeof(ResultContext));
DBGPRINT(( DBG_SS_CERTSRV, "s_CertServerRequest(tid=%d)\n", GetCurrentThreadId()));
hr = CertSrvEnterServer(&State); _JumpIfError(hr, error, "CertSrvEnterServer");
hr = CheckAuthorityName(pwszAuthority); _JumpIfError(hr, error, "No authority name");
hr = RegisterComContext(&ComContext, &dwComContextIndex); _JumpIfError(hr, error, "RegisterComContext");
OpRequest = CR_IN_RETRIEVE; if (NULL != pctbRequest->pb) { *pdwRequestId = 0; OpRequest = CR_IN_NEW; } else { // RetrievePending by SerialNumber in pctbAttribs
pctbSerial = pctbAttribs; pctbAttribs = &ctbEmpty; } *pdwDisposition = CR_DISP_ERROR;
__try { hr = CheckCertSrvAccess( pwszAuthority, h, CA_ACCESS_ENROLL, &ComContext.fInRequestGroup, &ComContext.hAccessToken); _LeaveIfError(hr, "CheckCertSrvAccess"); } __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr, "Exception"); } _JumpIfError(hr, error, "CheckCertSrvAccess");
hr = SetTransBlobString(pctbAttribs, &pwszAttributes); _JumpIfError(hr, error, "SetTransBlobString");
hr = SetTransBlobString(pctbSerial, &pwszSerialNumber); _JumpIfError(hr, error, "SetTransBlobString");
ResultContext.pdwRequestId = pdwRequestId; ResultContext.pdwDisposition = pdwDisposition; ResultContext.pctbDispositionMessage = pctbDispositionMessage; ResultContext.pctbCert = pctbEncodedCert; if (CR_IN_FULLRESPONSE & dwFlags) { ResultContext.pctbFullResponse = pctbCertChain; } else { ResultContext.pctbCertChain = pctbCertChain; }
__try { hr = GetClientUserName( h, &pwszUserName, CR_IN_NEW == OpRequest && IsEnterpriseCA(g_CAType)? &ComContext.pwszUserDN : NULL); _LeaveIfError(hr, "GetClientUserName");
hr = CoreProcessRequest( OpRequest | (dwFlags & CR_IN_FORMATMASK), pwszUserName, pctbRequest->cb, // cbRequest
pctbRequest->pb, // pbRequest
pwszAttributes, pwszSerialNumber, dwComContextIndex, *pdwRequestId, &ResultContext); // Allocates returned memory
} __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { } _JumpIfError(hr, error, "CoreProcessRequest");
// Post-processing
pctbDispositionMessage->cb = 0; if (NULL != pctbDispositionMessage->pb) { pctbDispositionMessage->cb = (wcslen((WCHAR *) pctbDispositionMessage->pb) + 1) * sizeof(WCHAR); }
error: ReleaseResult(&ResultContext); if (NULL != pwszUserName) { LocalFree(pwszUserName); } if (NULL != ComContext.hAccessToken) { HRESULT hr2;
// closehandle can throw
__try { CloseHandle(ComContext.hAccessToken); } __except(hr2 = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER) { _PrintError(hr2, "Exception"); if (S_OK == hr) { hr = hr2; } } } if (MAXDWORD != dwComContextIndex) { if (NULL != ComContext.pwszUserDN) { LocalFree(ComContext.pwszUserDN); } UnregisterComContext(&ComContext, dwComContextIndex); } CertSrvExitServer(State); CSASSERT(S_OK == hr || FAILED(hr)); return(hr); }
//+--------------------------------------------------------------------------
// MIDL_user_allocate -- Allocates memory for RPC operations.
//
// Parameters:
// cb - # of bytes to allocate
//
// Returns:
// Memory allocated, or NULL if not enough memory.
//---------------------------------------------------------------------------
void __RPC_FAR * __RPC_USER MIDL_user_allocate( IN size_t cb) { return(CoTaskMemAlloc(cb)); }
//+--------------------------------------------------------------------------
// MIDL_user_free -- Free memory allocated via MIDL_user_allocate.
//
// Parameters:
// pvBuffer - The buffer to free.
//
// Returns:
// None.
//---------------------------------------------------------------------------
void __RPC_USER MIDL_user_free( IN void __RPC_FAR *pb) { CoTaskMemFree(pb); }
|