457 lines
11 KiB
C
457 lines
11 KiB
C
|
//+---------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
// Copyright (C) Microsoft Corporation, 1992 - 1996.
|
||
|
//
|
||
|
// File: ras.c
|
||
|
//
|
||
|
// Contents:
|
||
|
//
|
||
|
// Classes:
|
||
|
//
|
||
|
// Functions:
|
||
|
//
|
||
|
// History: 2-09-96 RichardW Created
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#include "msgina.h"
|
||
|
#include <wchar.h>
|
||
|
#include <wincrypt.h>
|
||
|
#include <sclogon.h>
|
||
|
#include <raserror.h>
|
||
|
|
||
|
#define NP_Nbf 0x1
|
||
|
#define NP_Ipx 0x2
|
||
|
#define NP_Ip 0x4
|
||
|
|
||
|
HANDLE hRasApi ;
|
||
|
|
||
|
VOID WINAPI
|
||
|
MyRasCallback(
|
||
|
IN DWORD_PTR dwCallbackId,
|
||
|
IN DWORD dwEventCode,
|
||
|
IN LPWSTR pszEntry,
|
||
|
IN LPVOID pEventArgs )
|
||
|
|
||
|
/* RasPhonebookDlg callback. 'DwCallbackId' is the ID provided in
|
||
|
** parameters to RasPhonebookDlg. 'DwEventCode' indicates the
|
||
|
** RASPBDEVENT_* event that has occurred. 'PszEntry' is the name of the
|
||
|
** entry on which the event occurred. 'PEventArgs' is the event-specific
|
||
|
** parameter block passed to us during RasPhonebookDlg callback.
|
||
|
*/
|
||
|
{
|
||
|
RASNOUSERW* pInfo;
|
||
|
PGLOBALS pGlobals;
|
||
|
|
||
|
DebugLog((DEB_TRACE, "RasCallback: %#x, %#x, %ws, %#x\n",
|
||
|
dwCallbackId, dwEventCode, pszEntry, pEventArgs ));
|
||
|
|
||
|
|
||
|
/* Fill in information about the not yet logged on user.
|
||
|
*/
|
||
|
pInfo = (RASNOUSERW* )pEventArgs;
|
||
|
pGlobals = (PGLOBALS) dwCallbackId;
|
||
|
|
||
|
|
||
|
if (dwEventCode == RASPBDEVENT_NoUserEdit)
|
||
|
{
|
||
|
if (pInfo->szUserName[0])
|
||
|
{
|
||
|
wcscpy( pGlobals->UserName, pInfo->szUserName );
|
||
|
}
|
||
|
|
||
|
if (pInfo->szPassword[0])
|
||
|
{
|
||
|
wcscpy( pGlobals->Password, pInfo->szPassword );
|
||
|
RtlInitUnicodeString( &pGlobals->PasswordString, pGlobals->Password );
|
||
|
|
||
|
pGlobals->Seed = 0;
|
||
|
|
||
|
HidePassword( &pGlobals->Seed, &pGlobals->PasswordString );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else if (dwEventCode == RASPBDEVENT_NoUser)
|
||
|
|
||
|
{
|
||
|
|
||
|
ZeroMemory( pInfo, sizeof( RASNOUSERW ) );
|
||
|
|
||
|
pInfo->dwTimeoutMs = 2 * 60 * 1000;
|
||
|
pInfo->dwSize = sizeof( RASNOUSERW );
|
||
|
wcsncpy( pInfo->szUserName, pGlobals->UserName, UNLEN );
|
||
|
wcsncpy( pInfo->szDomain, pGlobals->Domain, DNLEN );
|
||
|
|
||
|
RevealPassword( &pGlobals->PasswordString );
|
||
|
wcsncpy( pInfo->szPassword, pGlobals->Password, PWLEN );
|
||
|
|
||
|
HidePassword( &pGlobals->Seed, &pGlobals->PasswordString );
|
||
|
|
||
|
}
|
||
|
|
||
|
if( pGlobals->SmartCardLogon
|
||
|
&& (NULL != pInfo))
|
||
|
{
|
||
|
pInfo->dwFlags |= RASNOUSER_SmartCard;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
GetRasDialOutProtocols(
|
||
|
void )
|
||
|
|
||
|
/* Returns a bit field containing NP_<protocol> flags for the installed
|
||
|
** PPP protocols. The term "installed" here includes enabling in RAS
|
||
|
** Setup.
|
||
|
*/
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Since after the connections checkin, RAS is always installed
|
||
|
// and there is no way to uninstall it, all we need to check here
|
||
|
// is if there are protocols installed that can be used by RAS to
|
||
|
// dial out. By default any protocol installed is available for RAS
|
||
|
// to dial out on. This can be overridden from the phonebook entry.
|
||
|
//
|
||
|
|
||
|
static const TCHAR c_szRegKeyIp[] =
|
||
|
TEXT("SYSTEM\\CurrentControlSet\\Services\\Tcpip");
|
||
|
|
||
|
static const TCHAR c_szRegKeyIpx[] =
|
||
|
TEXT("SYSTEM\\CurrentControlSet\\Services\\NwlnkIpx");
|
||
|
|
||
|
static const TCHAR c_szRegKeyNbf[] =
|
||
|
TEXT("SYSTEM\\CurrentControlSet\\Services\\Nbf");
|
||
|
|
||
|
struct PROTOCOL_INFO
|
||
|
{
|
||
|
DWORD dwFlag;
|
||
|
LPCTSTR pszRegkey;
|
||
|
};
|
||
|
|
||
|
static const struct PROTOCOL_INFO c_aProtocolInfo[] =
|
||
|
{
|
||
|
{
|
||
|
NP_Ip,
|
||
|
c_szRegKeyIp,
|
||
|
},
|
||
|
|
||
|
{
|
||
|
NP_Ipx,
|
||
|
c_szRegKeyIpx,
|
||
|
},
|
||
|
|
||
|
{
|
||
|
NP_Nbf,
|
||
|
c_szRegKeyNbf,
|
||
|
},
|
||
|
};
|
||
|
|
||
|
DWORD dwfInstalledProtocols = 0;
|
||
|
DWORD dwNumProtocols = sizeof(c_aProtocolInfo)/sizeof(c_aProtocolInfo[0]);
|
||
|
DWORD i;
|
||
|
HKEY hkey;
|
||
|
|
||
|
|
||
|
DebugLog(( DEB_TRACE, "GetRasDialOutProtocols...\n" ));
|
||
|
|
||
|
for(i = 0; i < dwNumProtocols; i++)
|
||
|
{
|
||
|
if(0 == RegOpenKey(HKEY_LOCAL_MACHINE,
|
||
|
c_aProtocolInfo[i].pszRegkey,
|
||
|
&hkey))
|
||
|
{
|
||
|
dwfInstalledProtocols |= c_aProtocolInfo[i].dwFlag;
|
||
|
RegCloseKey(hkey);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DebugLog(( DEB_TRACE, "GetRasDialOutProtocols: dwfInstalledProtocols=0x%x\n",
|
||
|
dwfInstalledProtocols));
|
||
|
|
||
|
return dwfInstalledProtocols;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
PopupRasPhonebookDlg(
|
||
|
IN HWND hwndOwner,
|
||
|
IN PGLOBALS pGlobals,
|
||
|
OUT BOOL* pfTimedOut
|
||
|
)
|
||
|
|
||
|
/* Popup the RAS common phonebook dialog to let user establish connection.
|
||
|
** 'HwndOwner' is the window to own the RAS dialog or NULL if none. '*PfTimedOut' is
|
||
|
** set TRUE if the dialog timed out, false otherwise.
|
||
|
**
|
||
|
** Returns true if user made a connection, false if not, i.e. an error
|
||
|
** occurred, RAS is not installed or user could not or chose not to
|
||
|
** connect.
|
||
|
*/
|
||
|
{
|
||
|
BOOL fConnected;
|
||
|
RASPBDLG info;
|
||
|
DWORD Protocols;
|
||
|
PUCHAR pvScData = NULL;
|
||
|
|
||
|
struct EAPINFO
|
||
|
{
|
||
|
DWORD dwSizeofEapInfo;
|
||
|
PBYTE pbEapInfo;
|
||
|
DWORD dwSizeofPINInfo;
|
||
|
PBYTE pbPINInfo;
|
||
|
};
|
||
|
|
||
|
struct EAPINFO eapinfo;
|
||
|
struct EAPINFO *pEapInfo = NULL;
|
||
|
|
||
|
*pfTimedOut = FALSE;
|
||
|
|
||
|
Protocols = GetRasDialOutProtocols();
|
||
|
if (Protocols == 0)
|
||
|
{
|
||
|
return( FALSE );
|
||
|
}
|
||
|
|
||
|
if(pGlobals->SmartCardLogon)
|
||
|
{
|
||
|
PULONG pulScData;
|
||
|
|
||
|
struct FLAT_UNICODE_STRING
|
||
|
{
|
||
|
USHORT Length;
|
||
|
USHORT MaximumLength;
|
||
|
BYTE abdata[1];
|
||
|
};
|
||
|
|
||
|
struct FLAT_UNICODE_STRING *pFlatUnicodeString;
|
||
|
PWLX_SC_NOTIFICATION_INFO ScInfo = NULL ;
|
||
|
|
||
|
//
|
||
|
// Get the set of strings indicating the reader and CSP
|
||
|
// to be used for the smart card. We will pass this info
|
||
|
// down to RAS.
|
||
|
//
|
||
|
pWlxFuncs->WlxGetOption( pGlobals->hGlobalWlx,
|
||
|
WLX_OPTION_SMART_CARD_INFO,
|
||
|
(ULONG_PTR *) &ScInfo);
|
||
|
|
||
|
if ( !ScInfo )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Validate the SC info against some common user
|
||
|
// errors
|
||
|
//
|
||
|
|
||
|
if ( ( ScInfo->pszReader ) &&
|
||
|
( ScInfo->pszCard == NULL ) )
|
||
|
{
|
||
|
//
|
||
|
// The card could not be read. Might not be
|
||
|
// inserted correctly.
|
||
|
//
|
||
|
LocalFree(ScInfo);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( ( ScInfo->pszReader ) &&
|
||
|
( ScInfo->pszCryptoProvider == NULL ) )
|
||
|
{
|
||
|
//
|
||
|
// Got a card, but the CSP for it could not be
|
||
|
// found.
|
||
|
//
|
||
|
LocalFree(ScInfo);
|
||
|
return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
pvScData = ScBuildLogonInfo(ScInfo->pszCard,
|
||
|
ScInfo->pszReader,
|
||
|
ScInfo->pszContainer,
|
||
|
ScInfo->pszCryptoProvider );
|
||
|
|
||
|
LocalFree(ScInfo);
|
||
|
|
||
|
if ( ! pvScData )
|
||
|
{
|
||
|
return FALSE ;
|
||
|
}
|
||
|
|
||
|
|
||
|
pulScData = (PULONG) pvScData;
|
||
|
|
||
|
ZeroMemory(&eapinfo, sizeof(struct EAPINFO));
|
||
|
|
||
|
eapinfo.dwSizeofEapInfo = *pulScData;
|
||
|
eapinfo.pbEapInfo = (BYTE *) pvScData;
|
||
|
|
||
|
eapinfo.dwSizeofPINInfo = sizeof(UNICODE_STRING) +
|
||
|
(sizeof(TCHAR) *
|
||
|
(1 + lstrlen(pGlobals->PasswordString.Buffer)));
|
||
|
|
||
|
//
|
||
|
// Flatten out the unicode string.
|
||
|
//
|
||
|
pFlatUnicodeString = LocalAlloc(LPTR, eapinfo.dwSizeofPINInfo);
|
||
|
|
||
|
if(NULL == pFlatUnicodeString)
|
||
|
{
|
||
|
if(NULL != pvScData)
|
||
|
{
|
||
|
LocalFree(pvScData);
|
||
|
}
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
pFlatUnicodeString->Length = pGlobals->PasswordString.Length;
|
||
|
pFlatUnicodeString->MaximumLength = pGlobals->PasswordString.MaximumLength;
|
||
|
|
||
|
lstrcpy((LPTSTR) pFlatUnicodeString->abdata,
|
||
|
(LPTSTR) pGlobals->PasswordString.Buffer);
|
||
|
|
||
|
|
||
|
eapinfo.pbPINInfo = (BYTE *) pFlatUnicodeString;
|
||
|
pEapInfo = &eapinfo;
|
||
|
}
|
||
|
|
||
|
ZeroMemory( &info, sizeof(info) );
|
||
|
info.dwSize = sizeof(info);
|
||
|
info.hwndOwner = hwndOwner;
|
||
|
info.dwFlags = RASPBDFLAG_NoUser;
|
||
|
info.pCallback = MyRasCallback;
|
||
|
info.dwCallbackId = (ULONG_PTR) pGlobals;
|
||
|
info.reserved2 = (ULONG_PTR) pEapInfo;
|
||
|
|
||
|
fConnected = RasPhonebookDlg( NULL, NULL, &info );
|
||
|
if (info.dwError == STATUS_TIMEOUT)
|
||
|
*pfTimedOut = TRUE;
|
||
|
|
||
|
if( (pEapInfo)
|
||
|
&& (pEapInfo->pbPINInfo))
|
||
|
{
|
||
|
LocalFree(pEapInfo->pbPINInfo);
|
||
|
}
|
||
|
|
||
|
if(NULL != pvScData)
|
||
|
{
|
||
|
LocalFree(pvScData);
|
||
|
}
|
||
|
|
||
|
return fConnected;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
IsRASServiceRunning()
|
||
|
{
|
||
|
BOOL bRet = FALSE; // assume the service is not running
|
||
|
SC_HANDLE hServiceMgr;
|
||
|
|
||
|
hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
|
||
|
|
||
|
if (hServiceMgr != NULL)
|
||
|
{
|
||
|
SC_HANDLE hService = OpenService(hServiceMgr, TEXT("RASMAN"), SERVICE_QUERY_STATUS);
|
||
|
|
||
|
if (hService != NULL)
|
||
|
{
|
||
|
SERVICE_STATUS status;
|
||
|
|
||
|
if (QueryServiceStatus(hService, &status) &&
|
||
|
(status.dwCurrentState == SERVICE_RUNNING))
|
||
|
{
|
||
|
// the RAS service is running
|
||
|
bRet = TRUE;
|
||
|
}
|
||
|
|
||
|
CloseServiceHandle(hService);
|
||
|
}
|
||
|
|
||
|
CloseServiceHandle(hServiceMgr);
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
// we need to treat RAS connections made by the system luid as created by the user.
|
||
|
// this allows us to "do the right thing" when a connection is made from the C-A-D dialog
|
||
|
// before any user is logged in
|
||
|
__inline BOOL IsEqualOrSystemLuid(PLUID pLuid, PLUID pUserLuid)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
static LUID luidSystem = SYSTEM_LUID;
|
||
|
|
||
|
if (RtlEqualLuid(pLuid, pUserLuid) || RtlEqualLuid(pLuid, &luidSystem))
|
||
|
{
|
||
|
// return true if pLuid matches the users luid or the system luid
|
||
|
bRet = TRUE;
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
HangupRasConnections(
|
||
|
PGLOBALS pGlobals
|
||
|
)
|
||
|
{
|
||
|
DWORD dwError;
|
||
|
RASCONN rasconn;
|
||
|
RASCONN* prc;
|
||
|
DWORD cbSize;
|
||
|
DWORD cConnections;
|
||
|
HLOCAL pBuffToFree = NULL;
|
||
|
|
||
|
if (!IsRASServiceRunning())
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
prc = &rasconn;
|
||
|
prc->dwSize = sizeof(RASCONN);
|
||
|
cbSize = sizeof(RASCONN);
|
||
|
|
||
|
dwError = RasEnumConnections(prc, &cbSize, &cConnections);
|
||
|
|
||
|
if (dwError == ERROR_BUFFER_TOO_SMALL)
|
||
|
{
|
||
|
pBuffToFree = LocalAlloc(LPTR, cbSize);
|
||
|
|
||
|
prc = (RASCONN*)pBuffToFree;
|
||
|
if (prc)
|
||
|
{
|
||
|
prc->dwSize = sizeof(RASCONN);
|
||
|
|
||
|
dwError = RasEnumConnections(prc, &cbSize, &cConnections);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwError == ERROR_SUCCESS)
|
||
|
{
|
||
|
UINT i;
|
||
|
|
||
|
for (i = 0; i < cConnections; i++)
|
||
|
{
|
||
|
if (IsEqualOrSystemLuid(&prc[i].luid, &pGlobals->LogonId))
|
||
|
{
|
||
|
RasHangUp(prc[i].hrasconn);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (pBuffToFree)
|
||
|
{
|
||
|
LocalFree(pBuffToFree);
|
||
|
}
|
||
|
|
||
|
return (dwError == ERROR_SUCCESS);
|
||
|
}
|
||
|
|