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.
588 lines
14 KiB
588 lines
14 KiB
/* Copyright (c) 1992, Microsoft Corporation, all rights reserved
|
|
**
|
|
** util.c
|
|
** Remote Access External APIs
|
|
** Utility routines
|
|
**
|
|
** 10/12/92 Steve Cobb
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <debug.h> // Trace and assert
|
|
#include <rasman.h>
|
|
#include <rasapip.h>
|
|
#include <pbk.h>
|
|
|
|
#define EAP_CUSTOM_KEY 0x43424431
|
|
|
|
typedef struct _EAP_CUSTOM_DATA
|
|
{
|
|
DWORD dwSignature;
|
|
DWORD dwCustomAuthKey;
|
|
DWORD dwSize;
|
|
BYTE abdata[1];
|
|
} EAP_CUSTOM_DATA;
|
|
|
|
|
|
BOOL IsRouterPhonebook(LPCTSTR pszPhonebook)
|
|
{
|
|
const TCHAR *psz;
|
|
|
|
BOOL fRouter = FALSE;
|
|
|
|
if(NULL == pszPhonebook)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
psz = pszPhonebook + lstrlen(pszPhonebook);
|
|
|
|
//
|
|
// Seek back to the beginning of the filename
|
|
//
|
|
while(psz != pszPhonebook)
|
|
{
|
|
if(TEXT('\\') == *psz)
|
|
{
|
|
break;
|
|
}
|
|
|
|
psz--;
|
|
}
|
|
|
|
if(TEXT('\\') == *psz)
|
|
{
|
|
psz += 1;
|
|
}
|
|
|
|
TRACE1("IsRouterPhonebook: pbk=%ws", psz);
|
|
|
|
//For whistler 524726
|
|
fRouter = ( CSTR_EQUAL == CompareString(
|
|
LOCALE_INVARIANT,
|
|
NORM_IGNORECASE,
|
|
TEXT("router.pbk"),
|
|
-1,
|
|
psz,
|
|
-1
|
|
)
|
|
);
|
|
|
|
|
|
done:
|
|
|
|
return fRouter;
|
|
}
|
|
|
|
BOOL
|
|
DwIsDefaultConnection(
|
|
IN PWCHAR pszEntryName)
|
|
{
|
|
DWORD dwErr = NO_ERROR, dwCb = 0, dwCount = 1;
|
|
RASAUTODIALENTRYW adEntry;
|
|
INT iCmp;
|
|
|
|
// Validate parameters
|
|
//
|
|
if (!pszEntryName)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// Initialze
|
|
//
|
|
ZeroMemory(&adEntry, sizeof(adEntry));
|
|
dwCb = adEntry.dwSize = sizeof(adEntry);
|
|
|
|
dwErr = RasGetAutodialAddressW(
|
|
NULL,
|
|
NULL,
|
|
&adEntry,
|
|
&dwCb,
|
|
&dwCount);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
iCmp = _wcsnicmp(
|
|
adEntry.szEntry,
|
|
pszEntryName,
|
|
sizeof(adEntry.szEntry) / sizeof(WCHAR));
|
|
|
|
return (0 == iCmp);
|
|
}
|
|
|
|
DWORD
|
|
DwPbentryToDetails(
|
|
IN PBENTRY* pEntry,
|
|
IN LPCWSTR pszPhonebookPath,
|
|
IN BOOL fIsAllUsersPbk,
|
|
OUT RASENUMENTRYDETAILS* pDetails)
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
DTLNODE *pdtlnode;
|
|
PBLINK *pLink;
|
|
|
|
pDetails->dwSize = sizeof(RASENUMENTRYDETAILS);
|
|
pDetails->dwType = pEntry->dwType;
|
|
|
|
pDetails->fShowMonitorIconInTaskBar =
|
|
pEntry->fShowMonitorIconInTaskBar;
|
|
|
|
if(pEntry->pGuid)
|
|
{
|
|
pDetails->guidId = *pEntry->pGuid;
|
|
}
|
|
|
|
//For .Net 587396
|
|
lstrcpynW(pDetails->szEntryName,
|
|
pEntry->pszEntryName,
|
|
RASAPIP_MAX_ENTRY_NAME+1);
|
|
|
|
pDetails->dwFlags = (fIsAllUsersPbk) ? REN_AllUsers : REN_User;
|
|
|
|
if(pszPhonebookPath)
|
|
{
|
|
lstrcpynW(pDetails->szPhonebookPath,
|
|
pszPhonebookPath,
|
|
MAX_PATH + 1);
|
|
}
|
|
else
|
|
{
|
|
pDetails->szPhonebookPath[0] = L'\0';
|
|
}
|
|
|
|
//
|
|
// Get the devicename associated with the first
|
|
// link in the list of entries associated with
|
|
// this entry
|
|
//
|
|
pDetails->szDeviceName[0] = TEXT('\0');
|
|
pDetails->szPhoneNumber[0] = TEXT('\0');
|
|
|
|
pdtlnode = (DTLNODE *)
|
|
DtlGetFirstNode(pEntry->pdtllistLinks);
|
|
|
|
if(pdtlnode)
|
|
{
|
|
pLink = (PBLINK *) DtlGetData(pdtlnode);
|
|
|
|
if( (NULL != pLink)
|
|
&& (pLink->pbport.pszDevice))
|
|
{
|
|
pDetails->rdt = RdtFromPbdt(
|
|
pLink->pbport.pbdevicetype,
|
|
pLink->pbport.dwFlags);
|
|
|
|
if(RAS_DEVICE_CLASS(pDetails->rdt) == RDT_Tunnel)
|
|
{
|
|
(void) DwGetVpnDeviceName(
|
|
pEntry->dwVpnStrategy,
|
|
pLink->pbport.pszDevice,
|
|
pDetails->szDeviceName);
|
|
}
|
|
else
|
|
{
|
|
lstrcpy(pDetails->szDeviceName,
|
|
pLink->pbport.pszDevice);
|
|
}
|
|
}
|
|
|
|
// XP 351412
|
|
//
|
|
// Populate the phone number as well
|
|
//
|
|
if( (NULL != pLink)
|
|
&& (pLink->pdtllistPhones))
|
|
{
|
|
DTLNODE* pnodeNum = DtlGetFirstNode(pLink->pdtllistPhones);
|
|
PBPHONE* pPhone = NULL;
|
|
|
|
if (NULL != pnodeNum)
|
|
{
|
|
pPhone = DtlGetData(pnodeNum);
|
|
if ((NULL != pPhone) && (NULL != pPhone->pszPhoneNumber))
|
|
{
|
|
lstrcpyn(
|
|
pDetails->szPhoneNumber,
|
|
pPhone->pszPhoneNumber,
|
|
RAS_MaxPhoneNumber);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Mark whether this is the default connection
|
|
// XP 286752
|
|
//
|
|
if (DwIsDefaultConnection(pEntry->pszEntryName))
|
|
{
|
|
pDetails->dwFlagsPriv |= REED_F_Default;
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DwSendRasNotification(
|
|
IN RASEVENTTYPE Type,
|
|
IN PBENTRY* pEntry,
|
|
IN LPCTSTR pszPhonebookPath,
|
|
IN HANDLE hData) // Extra Type-specific info
|
|
{
|
|
RASEVENT RasEvent;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
|
|
ZeroMemory((PBYTE) &RasEvent, sizeof(RASEVENT));
|
|
|
|
RasEvent.Type = Type;
|
|
|
|
//
|
|
// Ignore the notification if this is a router interface
|
|
//
|
|
if(IsRouterPhonebook(pszPhonebookPath))
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
switch(Type)
|
|
{
|
|
case ENTRY_ADDED:
|
|
case ENTRY_MODIFIED:
|
|
case ENTRY_AUTODIAL:
|
|
{
|
|
BOOL fAllUsers = TRUE;
|
|
|
|
if (NULL != pszPhonebookPath)
|
|
{
|
|
fAllUsers = IsPublicPhonebook(pszPhonebookPath);
|
|
}
|
|
|
|
DwPbentryToDetails(
|
|
pEntry,
|
|
pszPhonebookPath,
|
|
fAllUsers,
|
|
&(RasEvent.Details)
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case ENTRY_DELETED:
|
|
case ENTRY_RENAMED:
|
|
{
|
|
if(NULL != pEntry->pGuid)
|
|
{
|
|
RasEvent.guidId = *pEntry->pGuid;
|
|
}
|
|
|
|
if(ENTRY_RENAMED == Type)
|
|
{
|
|
lstrcpy(RasEvent.pszwNewName,
|
|
pEntry->pszEntryName);
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
#if DBG
|
|
ASSERT(FALSE);
|
|
#endif
|
|
goto done;
|
|
}
|
|
|
|
}
|
|
|
|
dwErr = RasSendNotification(&RasEvent);
|
|
|
|
done:
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
DwGetCustomAuthData(PBENTRY *pEntry,
|
|
DWORD *pcbCustomAuthData,
|
|
PBYTE *ppCustomAuthData)
|
|
{
|
|
DWORD retcode = SUCCESS;
|
|
DWORD cbOffset = 0;
|
|
EAP_CUSTOM_DATA *pCustomData = NULL;
|
|
|
|
ASSERT(NULL != pcbCustomAuthData);
|
|
ASSERT(NULL != ppCustomAuthData);
|
|
ASSERT(NULL != pEntry);
|
|
|
|
*pcbCustomAuthData = 0;
|
|
*ppCustomAuthData = NULL;
|
|
|
|
//
|
|
// first check to see if we understand the format of the
|
|
// eap blob stored in the phonebook
|
|
//
|
|
if(NULL == pEntry->pCustomAuthData)
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
if( (sizeof(DWORD) > pEntry->cbCustomAuthData)
|
|
|| ((*((DWORD *) pEntry->pCustomAuthData)) != EAP_CUSTOM_KEY))
|
|
{
|
|
Free(pEntry->pCustomAuthData);
|
|
pEntry->pCustomAuthData = NULL;
|
|
pEntry->cbCustomAuthData = 0;
|
|
|
|
goto done;
|
|
}
|
|
|
|
//
|
|
// Loop through the blob and return the blob corresponding
|
|
// to the eap type of the entry
|
|
//
|
|
while(cbOffset < pEntry->cbCustomAuthData)
|
|
{
|
|
pCustomData = (EAP_CUSTOM_DATA *)
|
|
((PBYTE) pEntry->pCustomAuthData + cbOffset);
|
|
|
|
if( (sizeof(DWORD) > (pEntry->cbCustomAuthData - cbOffset))
|
|
|| ((*((DWORD *) pEntry->pCustomAuthData)) != EAP_CUSTOM_KEY))
|
|
{
|
|
//
|
|
// The data is corrupt. Blow away the data.
|
|
// should we return an error?
|
|
//
|
|
Free(pEntry->pCustomAuthData);
|
|
pEntry->pCustomAuthData = NULL;
|
|
pEntry->cbCustomAuthData = 0;
|
|
|
|
TRACE("GetCustomAuthdata: data is corrupt");
|
|
|
|
goto done;
|
|
}
|
|
|
|
if(pCustomData->dwCustomAuthKey == pEntry->dwCustomAuthKey)
|
|
{
|
|
break;
|
|
}
|
|
|
|
cbOffset += sizeof(EAP_CUSTOM_DATA) + pCustomData->dwSize;
|
|
}
|
|
|
|
if(cbOffset < pEntry->cbCustomAuthData)
|
|
{
|
|
*pcbCustomAuthData = pCustomData->dwSize;
|
|
*ppCustomAuthData = pCustomData->abdata;
|
|
}
|
|
|
|
done:
|
|
return retcode;
|
|
}
|
|
|
|
DWORD
|
|
DwSetCustomAuthData(PBENTRY *pEntry,
|
|
DWORD cbCustomAuthData,
|
|
PBYTE pCustomAuthData)
|
|
{
|
|
DWORD retcode = SUCCESS;
|
|
DWORD cbOffset = 0;
|
|
EAP_CUSTOM_DATA *pCustomData = NULL;
|
|
DWORD dwSize;
|
|
PBYTE pNewCustomAuthData;
|
|
|
|
ASSERT(NULL != pEntry);
|
|
|
|
if(NULL != pEntry->pCustomAuthData)
|
|
{
|
|
if( (sizeof(DWORD) > pEntry->cbCustomAuthData)
|
|
|| ((*((DWORD *) pEntry->pCustomAuthData)) != EAP_CUSTOM_KEY))
|
|
{
|
|
Free(pEntry->pCustomAuthData);
|
|
pEntry->pCustomAuthData = NULL;
|
|
pEntry->cbCustomAuthData = 0;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Find the old Eap Data
|
|
//
|
|
while(cbOffset < pEntry->cbCustomAuthData)
|
|
{
|
|
pCustomData = (EAP_CUSTOM_DATA *)
|
|
((PBYTE)pEntry->pCustomAuthData + cbOffset);
|
|
|
|
if( (sizeof(DWORD) > (pEntry->cbCustomAuthData - cbOffset))
|
|
|| ((*((DWORD *) pEntry->pCustomAuthData)) != EAP_CUSTOM_KEY))
|
|
{
|
|
//
|
|
// The data is corrupt. Blow away the data.
|
|
// should we return an error?
|
|
//
|
|
Free(pEntry->pCustomAuthData);
|
|
pEntry->pCustomAuthData = NULL;
|
|
pEntry->cbCustomAuthData = 0;
|
|
|
|
TRACE("SetCustomAuthData: data is corrupt!");
|
|
|
|
break;
|
|
}
|
|
|
|
if(pCustomData->dwCustomAuthKey == pEntry->dwCustomAuthKey)
|
|
{
|
|
break;
|
|
}
|
|
|
|
cbOffset += (sizeof(EAP_CUSTOM_DATA) + pCustomData->dwSize);
|
|
}
|
|
|
|
//
|
|
// Prefast warning
|
|
//
|
|
if( (NULL != pCustomData)
|
|
&& (cbOffset < pEntry->cbCustomAuthData))
|
|
{
|
|
dwSize = sizeof(EAP_CUSTOM_DATA) + pCustomData->dwSize;
|
|
|
|
ASSERT(pEntry->cbCustomAuthData >= (cbOffset + dwSize));
|
|
|
|
MoveMemory(pEntry->pCustomAuthData + cbOffset,
|
|
pEntry->pCustomAuthData
|
|
+ cbOffset + dwSize,
|
|
pEntry->cbCustomAuthData - cbOffset - dwSize);
|
|
|
|
pEntry->cbCustomAuthData -= dwSize;
|
|
}
|
|
|
|
if(0 == pEntry->cbCustomAuthData)
|
|
{
|
|
Free0(pEntry->pCustomAuthData);
|
|
pEntry->pCustomAuthData = NULL;
|
|
}
|
|
|
|
if( (0 == cbCustomAuthData)
|
|
|| (NULL == pCustomAuthData))
|
|
{
|
|
goto done;
|
|
}
|
|
|
|
dwSize = cbCustomAuthData
|
|
+ pEntry->cbCustomAuthData
|
|
+ sizeof(EAP_CUSTOM_DATA);
|
|
|
|
pNewCustomAuthData = Malloc(dwSize);
|
|
|
|
if(NULL == pNewCustomAuthData)
|
|
{
|
|
retcode = E_OUTOFMEMORY;
|
|
goto done;
|
|
}
|
|
|
|
ZeroMemory(pNewCustomAuthData, dwSize);
|
|
|
|
CopyMemory(pNewCustomAuthData,
|
|
pEntry->pCustomAuthData,
|
|
pEntry->cbCustomAuthData);
|
|
|
|
pCustomData = (EAP_CUSTOM_DATA *) (pNewCustomAuthData
|
|
+ pEntry->cbCustomAuthData);
|
|
|
|
pCustomData->dwSignature = EAP_CUSTOM_KEY;
|
|
pCustomData->dwCustomAuthKey = pEntry->dwCustomAuthKey;
|
|
pCustomData->dwSize = cbCustomAuthData;
|
|
CopyMemory(pCustomData->abdata,
|
|
pCustomAuthData,
|
|
cbCustomAuthData);
|
|
|
|
pEntry->cbCustomAuthData = dwSize;
|
|
|
|
if(NULL != pEntry->pCustomAuthData)
|
|
{
|
|
Free(pEntry->pCustomAuthData);
|
|
}
|
|
|
|
pEntry->pCustomAuthData = pNewCustomAuthData;
|
|
|
|
done:
|
|
return retcode;
|
|
}
|
|
|
|
DWORD
|
|
DwGetVpnDeviceName(
|
|
DWORD dwVpnStrategy,
|
|
WCHAR *pszDeviceDefault,
|
|
WCHAR *pszDeviceName)
|
|
{
|
|
DWORD dwErr = ERROR_SUCCESS, dwType;
|
|
CHAR szDeviceName[MAX_DEVICE_NAME];
|
|
|
|
// Figure out the device name we're interested in
|
|
// discovering.
|
|
//
|
|
dwType = RDT_Tunnel_L2tp;
|
|
switch (dwVpnStrategy)
|
|
{
|
|
case VS_Default:
|
|
case VS_L2tpFirst:
|
|
case VS_L2tpOnly:
|
|
dwType = RDT_Tunnel_L2tp;
|
|
break;
|
|
|
|
case VS_PptpFirst:
|
|
case VS_PptpOnly:
|
|
dwType = RDT_Tunnel_Pptp;
|
|
break;
|
|
}
|
|
|
|
TRACE1("RasGetDeviceName(rdt=%d)...", dwType);
|
|
|
|
dwErr = RasGetDeviceNameW(
|
|
dwType,
|
|
pszDeviceName);
|
|
|
|
TRACE1("RasGetDeviceName. 0x%x", dwErr);
|
|
|
|
if(ERROR_SUCCESS != dwErr)
|
|
{
|
|
dwErr = ERROR_SUCCESS;
|
|
|
|
// We can't determine from rasman -- use the phonebook
|
|
// value if possible
|
|
//
|
|
if (NULL != pszDeviceDefault)
|
|
{
|
|
lstrcpyn(
|
|
pszDeviceName,
|
|
pszDeviceDefault,
|
|
RASAPIP_MAX_DEVICE_NAME);
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
BOOL
|
|
IsServerOS ( )
|
|
{
|
|
BOOL fServerOS = TRUE; //Default
|
|
//Check to see if the OS is server - Data Center, Server, Advanced Server
|
|
|
|
OSVERSIONINFOEX stOsvEx;
|
|
ZeroMemory( &stOsvEx, sizeof(stOsvEx) );
|
|
stOsvEx.dwOSVersionInfoSize = sizeof(stOsvEx);
|
|
GetVersionEx((LPOSVERSIONINFO)&stOsvEx);
|
|
if ( stOsvEx.wProductType == VER_NT_WORKSTATION )
|
|
fServerOS = FALSE;
|
|
return fServerOS;
|
|
|
|
}
|
|
|