windows-nt/Source/XPSP1/NT/ds/security/gina/msgina/ras.c
2020-09-26 16:20:57 +08:00

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);
}