2025-11-28 00:35:46 +09:00

255 lines
8.0 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
#include "Utils.h"
#include "VpnConnection.h"
#define EAP_TLS 13 // Smartcard or other certificate (TLS)
#define EAP_PEAP 25 // PEAP
#define EAP_MSCHAPv2 26 // EAP Mschapv2
#define RDT_Tunnel_Pptp (0x8)
#define RDT_Tunnel_L2tp (0x9)
#define RDT_Tunnel_Sstp (0xe)
#define RDT_Tunnel_Ikev2 (0xf)
//********************************************************************************************
// Function: EnumerateVpnConnections
//
// Description: Enumarates and displays all the VPN connections connected to the Remote access server.
//
//********************************************************************************************
VOID EnumerateVpnConnections(
_In_opt_ LPWSTR serverName
)
{
DWORD status = ERROR_SUCCESS;
MPR_SERVER_HANDLE serverHandleAdmin = NULL;
HANDLE serverHandleConfig = NULL;
RAS_CONNECTION_4* vpnConnectionList = NULL;
DWORD entriesRead = 0;
DWORD totalEntries = 0;
DWORD resumeHandle = 0;
wprintf(L"---------------------------------------------------------\n\n");
wprintf(L"Executing EnumerateVpnConnections on '%s'\n", (serverName == NULL) ? L"Current machine" : serverName);
status = RemoteAccessServerConenct(serverName, &serverHandleAdmin, &serverHandleConfig);
if ((ERROR_SUCCESS != status) ||
(NULL == serverHandleAdmin))
{
wprintf(L"RemoteAccessServerConenct failed. \
The RemoteAccess service might be stopped - Try after starting the RemoteAccess service.\n");
DisplayError(status);
goto Done;
}
status = g_pMprAdminConnectionEnum(serverHandleAdmin, // hRasServer
4, // dwLevel
(LPBYTE *) &vpnConnectionList, // lplpbBuffer
0xffffffff, // dwPrefMaxLen
&entriesRead, // lpdwEntriesRead
&totalEntries, // lpdwTotalEntries
&resumeHandle); // lpdwResumeHandle
if (ERROR_SUCCESS != status)
{
wprintf(L"MprAdminConnectionEnum failed.\n");
DisplayError(status);
goto Done;
}
if (0 == entriesRead)
{
wprintf(L"No VPN clients are connected to the server at this moment.\n");
}
else
{
wprintf(L"%u VPN clients are connected to the server at this moment.\n", entriesRead);
}
for (DWORD index = 0; index < entriesRead; index++)
{
wprintf(L"Connection - %u\n", (index + 1));
PrintVPNConnectionDetails(&(vpnConnectionList[index]));
}
Done:
if (vpnConnectionList)
{
g_pMprAdminBufferFree(vpnConnectionList);
}
RemoteAccessServerDisconenct(serverHandleAdmin, serverHandleConfig);
if (status != ERROR_SUCCESS)
{
wprintf(L"EnumerateVpnConnections failed\n");
DisplayError(status);
}
wprintf(L"---------------------------------------------------------\n\n");
}
//********************************************************************************************
// Function: PrintVPNConnectionDetails
//
// Description: Prints various fields of the speficied RAS_CONNECTION_4 structure in string format
//
//********************************************************************************************
VOID PrintVPNConnectionDetails(
_In_ RAS_CONNECTION_4* vpnConnection
)
{
wprintf(L"\t Connection Start time: ");
PrintFileTime(&(vpnConnection->connectionStartTime));
wprintf(L"\n");
// Username
//
wprintf(L"\t Remote username: ");
if (0 != vpnConnection->wszLogonDomain[0])
{
// Domain name is specified
//
wprintf(L"%s\\%s\n", vpnConnection->wszLogonDomain, vpnConnection->wszUserName);
}
else if (0 != vpnConnection->wszUserName[0])
{
wprintf(L"%s\n", vpnConnection->wszUserName);
}
else
wprintf(L"UnKnown\n");
wprintf(L"\t Interface type: ");
PrintInterfaceType(vpnConnection->dwInterfaceType);
wprintf(L"\n");
// print tunnel type
//
wprintf(L"\t VPN type: ");
switch (vpnConnection->dwDeviceType)
{
case RDT_Tunnel_Pptp:
wprintf(L"PPTP\n");
break;
case RDT_Tunnel_L2tp:
wprintf(L"L2TP\n");
break;
case RDT_Tunnel_Sstp:
wprintf(L"SSTP\n");
break;
case RDT_Tunnel_Ikev2:
wprintf(L"IKEv2\n");
break;
default:
wprintf(L"UnKnown\n");
}
// Authentication method
//
wprintf(L"\t Authentication method: ");
PrintAuthMethod(&(vpnConnection->ProjectionInfo));
wprintf(L"\n");
wprintf(L"\t Total bytes Received: %I64u\n", vpnConnection->ullBytesRcved);
wprintf(L"\t Total bytes Transmitted: %I64u\n", vpnConnection->ullBytesXmited);
}
//********************************************************************************************
// Function: PrintAuthMethod
//
// Description: Retrieve the authentication method from the speficied PROJECTION_INFO2 structure
// and prints it in string format
//
//********************************************************************************************
VOID PrintAuthMethod(
_In_ PROJECTION_INFO2* projectionInfo
)
{
DWORD authProtocol = 0;
DWORD eapTypeID = 0;
DWORD embeddedEapTypeID = 0;
DWORD authenticationData = 0;
if (projectionInfo->projectionInfoType == MPRAPI_IKEV2_PROJECTION_INFO_TYPE)
{
// This is an IKEv2 tunnel.
//
authProtocol = projectionInfo->Ikev2ProjectionInfo.dwAuthenticationProtocol;
eapTypeID = projectionInfo->Ikev2ProjectionInfo.dwEapTypeId;
embeddedEapTypeID = projectionInfo->Ikev2ProjectionInfo.dwEmbeddedEAPTypeId;
}
else
{
// This is a PPP based tunnell.
//
authProtocol = projectionInfo->PppProjectionInfo.dwAuthenticationProtocol;
eapTypeID = projectionInfo->PppProjectionInfo.dwEapTypeId;
embeddedEapTypeID = projectionInfo->PppProjectionInfo.dwEmbeddedEAPTypeId;
authenticationData = projectionInfo->PppProjectionInfo.dwAuthenticationData;
}
if ((authProtocol != PPP_LCP_EAP) &&
(authProtocol != MPRAPI_IKEV2_AUTH_USING_EAP))
{
// if auth protocol is not EAP, the auth protocol ID is same as the auth method used
//
switch (authProtocol)
{
case PPP_LCP_PAP:
wprintf(L"PAP");
break;
case MPRAPI_IKEV2_AUTH_USING_CERT:
wprintf(L"Machine Certificate");
break;
case PPP_LCP_CHAP:
if (authenticationData == PPP_LCP_CHAP_MSV2)
wprintf(L"MS-CHAPv2");
else
wprintf(L"CHAP");
break;
default:
wprintf(L"UnKnown(%u)", authProtocol);
}
}
else
{
// In case of EAP auth protocol, get the auth method from the eap method type
//
switch (eapTypeID)
{
case EAP_TLS:
wprintf(L"EAP-TLS");
break;
case EAP_PEAP:
wprintf(L"EAP-PEAP");
break;
case EAP_MSCHAPv2:
wprintf(L"EAP-MSCHAPv2");
break;
default:
wprintf(L"EAP(MethodID: %u)", eapTypeID);
break;
}
// Get the inner auth method from the embedded eap method type
//
switch (embeddedEapTypeID)
{
case EAP_TLS:
wprintf(L" (Inner EAP method: EAP-TLS)");
break;
case EAP_MSCHAPv2:
wprintf(L" (Inner EAP method: EAP-MSCHAPv2)");
break;
}
}
}