windows-nt/Source/XPSP1/NT/inetsrv/iis/ui/admin/certwiz/netutil.cpp
2020-09-26 16:20:57 +08:00

298 lines
7.3 KiB
C++

//
// NetUtil.cpp
//
#include "stdafx.h"
#include <lm.h>
#include "NetUtil.h"
#include <wincrypt.h>
#include <certrpc.h>
#include <certcli.h>
#include <malloc.h>
#define LEVEL_1 1
#define LEVEL_2 2
BOOL GetCurrentUserFullName(CString& name)
{
BOOL bRes = FALSE;
NET_API_STATUS nas;
WKSTA_USER_INFO_1 * pWksInfo = NULL;
if (NERR_Success == (nas = NetWkstaUserGetInfo(NULL,
LEVEL_1, (BYTE **)&pWksInfo)))
{
USER_INFO_2 * pUserInfo = NULL;
CString strServerName = _T("\\\\");
ASSERT(pWksInfo->wkui1_logon_server[0] != 0);
strServerName += pWksInfo->wkui1_logon_server;
if (NERR_Success == (nas = NetUserGetInfo(
(LPCWSTR)strServerName,
(LPCWSTR)pWksInfo->wkui1_username,
LEVEL_2,
(BYTE **)&pUserInfo)))
{
name = pUserInfo->usri2_full_name;
if (pUserInfo != NULL)
NetApiBufferFree(pUserInfo);
bRes = TRUE;
}
if (pWksInfo != NULL)
NetApiBufferFree(pWksInfo);
}
return bRes;
}
#if 0
/*********************************** Direct Cert Request *********************************/
typedef struct _RPC_BINDING_LIST
{
LPTSTR pszProtSeq;
LPTSTR pszEndpoint;
} RPC_BINDING_LIST;
RPC_BINDING_LIST g_BindingList[] =
{
{_T("ncacn_ip_tcp"), NULL},
{_T("ncacn_np"), _T("\\pipe\\cert")}
};
DWORD g_BindingListSize = sizeof(g_BindingList)/sizeof(g_BindingList[0]);
typedef struct _RPC_ATHN_LIST
{
DWORD dwAuthnLevel;
DWORD dwAuthnService;
} RPC_ATHN_LIST;
RPC_ATHN_LIST g_AthnList[] =
{
{ RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, RPC_C_AUTHN_GSS_NEGOTIATE},
{ RPC_C_AUTHN_LEVEL_NONE, RPC_C_AUTHN_NONE }
};
DWORD g_AthnListSize = sizeof(g_AthnList)/sizeof(g_AthnList[0]);
//-----------------------------------------------------------------------
//
// RetrivePKCS7FromCA
//
//------------------------------------------------------------------------
HRESULT
RetrievePKCS7FromCA(CString& strCALocation,
CString& strCAName,
LPWSTR pwszRequestString,
CRYPT_DATA_BLOB * pPKCS10Blob,
CRYPT_DATA_BLOB * pPKCS7Blob,
DWORD * pdwStatus,
BOOL bRenew)
{
HRESULT hr = E_FAIL;
UINT id = 0;
DWORD dwDisposition = 0;
DWORD dwErr = 0;
DWORD dwStatus = 0;
RPC_STATUS rpcStatus = 0;
CERTTRANSBLOB tbRequest = {0, NULL};
CERTTRANSBLOB tbCert = {0, NULL};
CERTTRANSBLOB tbCertChain = {0, NULL};
CERTTRANSBLOB tbAttrib = {0, NULL};
CERTTRANSBLOB tbDispositionMessage = {0, NULL};
LPTSTR szStringBinding = NULL;
RPC_BINDING_HANDLE hCARPCBinding = NULL;
LPTSTR pszCAPrinceName = NULL;
//input checking
if (!pPKCS10Blob || !pPKCS7Blob)
return E_INVALIDARG;
for (DWORD i = 0; i < g_BindingListSize; i++)
{
if (RPC_S_OK != RpcNetworkIsProtseqValid(g_BindingList[i].pszProtSeq))
continue;
rpcStatus = RpcStringBindingCompose(NULL,
g_BindingList[i].pszProtSeq,
(LPTSTR)(LPCTSTR)strCALocation,
g_BindingList[i].pszEndpoint,
NULL,
&szStringBinding);
if(rpcStatus != RPC_S_OK)
continue;
rpcStatus = RpcBindingFromStringBinding(szStringBinding, &hCARPCBinding);
if (szStringBinding)
RpcStringFree(&szStringBinding);
if (rpcStatus != RPC_S_OK)
continue;
rpcStatus = RpcEpResolveBinding(hCARPCBinding, ICertPassage_v0_0_c_ifspec);
if (rpcStatus == RPC_S_OK)
break;
}
if (rpcStatus != RPC_S_OK)
{
dwStatus = WIZ_CERT_REQUEST_STATUS_CONNECTION_FAILED;
hr = E_FAIL;
goto CLEANUP;
}
//add the attribute to the request
if (pwszRequestString)
{
tbAttrib.cb = (wcslen(pwszRequestString) + 1) * sizeof(WCHAR);
tbAttrib.pb = (BYTE *)pwszRequestString;
}
//submit the request
tbRequest.cb = pPKCS10Blob->cbData;
tbRequest.pb = pPKCS10Blob->pbData;
//set the RPC connect as the SNEGO connect, which can authenticate
//a machine if supported by the system
//do not need to check the return value since not supported by NT4/Win9x
for (i = 0; i < g_AthnListSize; i++)
{
pszCAPrinceName = NULL;
if (g_AthnList[i].dwAuthnService != RPC_C_AUTHN_NONE)
{
dwErr = RpcMgmtInqServerPrincNameA(hCARPCBinding,
g_AthnList[i].dwAuthnService,
(PBYTE *)&pszCAPrinceName);
if (dwErr == RPC_S_UNKNOWN_AUTHN_SERVICE)
continue;
}
dwErr = RpcBindingSetAuthInfo(hCARPCBinding,
pszCAPrinceName,
g_AthnList[i].dwAuthnLevel,
g_AthnList[i].dwAuthnService,
NULL,
RPC_C_AUTHZ_NONE);
if (pszCAPrinceName)
RpcStringFree(&pszCAPrinceName);
if (dwErr == RPC_S_UNKNOWN_AUTHN_SERVICE)
continue;
if (dwErr != RPC_S_OK)
break;
//determine the format flag
DWORD dwFlags = CR_IN_BINARY | bRenew ? CR_IN_PKCS7 : CR_IN_PKCS10;
DWORD dwRequestId = 0;
__try
{
dwErr = CertServerRequest(
hCARPCBinding,
dwFlags,
strCAName,
&dwRequestId,
&dwDisposition,
&tbAttrib,
&tbRequest,
&tbCertChain,
&tbCert,
&tbDispositionMessage);
}
__except(dwErr = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
{
}
if (dwErr != RPC_S_UNKNOWN_AUTHN_SERVICE)
break;
}
if ( dwErr == RPC_S_UNKNOWN_AUTHN_SERVICE
|| dwErr == RPC_S_SERVER_UNAVAILABLE
|| dwErr == RPC_S_SERVER_TOO_BUSY
)
{
// We tried all of our auth services, but just couldn't connect
dwStatus = WIZ_CERT_REQUEST_STATUS_CONNECTION_FAILED;
hr = E_FAIL;
goto CLEANUP;
}
//get the return code
hr = HRESULT_FROM_WIN32(dwErr);
//we want to detect the case when hr is S_OK and the
//request is denied. In this case, dwDispotion
//is the REAL hresult code.
if (hr == S_OK)
{
if(FAILED(dwDisposition))
{
hr = dwDisposition;
dwDisposition = CR_DISP_DENIED;
}
}
else
{
dwDisposition=CR_DISP_ERROR;
}
//map the dwDisposition
switch (dwDisposition)
{
case CR_DISP_DENIED:
dwStatus = WIZ_CERT_REQUEST_STATUS_REQUEST_DENIED;
if (!FAILED(hr))
hr = E_FAIL;
break;
case CR_DISP_ISSUED:
dwStatus = WIZ_CERT_REQUEST_STATUS_CERT_ISSUED;
break;
case CR_DISP_ISSUED_OUT_OF_BAND:
dwStatus = WIZ_CERT_REQUEST_STATUS_ISSUED_SEPARATELY;
break;
case CR_DISP_UNDER_SUBMISSION:
dwStatus = WIZ_CERT_REQUEST_STATUS_UNDER_SUBMISSION;
break;
//we should never get CR_DISP_INCOMPLETE or CR_DISP_REVOKED
//case CR_DISP_INCOMPLETE:
//case CR_DISP_REVOKED:
case CR_DISP_ERROR:
default:
dwStatus = WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
if (!FAILED(hr))
hr=E_FAIL;
break;
}
if (hr != S_OK)
goto CLEANUP;
//copy the PKCS7 blob
pPKCS7Blob->cbData = tbCertChain.cb;
pPKCS7Blob->pbData = new BYTE[tbCertChain.cb];
if (NULL == pPKCS7Blob->pbData)
{
hr = E_OUTOFMEMORY;
dwStatus = WIZ_CERT_REQUEST_STATUS_INSTALL_FAILED;
goto CLEANUP;
}
memcpy(pPKCS7Blob->pbData,tbCertChain.pb,tbCertChain.cb);
hr = S_OK;
CLEANUP:
if (pdwStatus)
*pdwStatus = dwStatus;
if (tbCert.pb)
CoTaskMemFree(tbCert.pb);
if (tbCertChain.pb)
CoTaskMemFree(tbCertChain.pb);
if (tbDispositionMessage.pb)
CoTaskMemFree(tbDispositionMessage.pb);
if (hCARPCBinding)
RpcBindingFree(&hCARPCBinding);
return hr;
}
#endif