|
|
//
// 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
|