|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Introduction
Overview
Figure 1.
Winlogon handles interface functions that are independent of authentication policy. The GINA is a replaceable DLL component that is loaded by Winlogon. The GINA implements the authentication policy of the interactive logon model, and is expected to perform all identification and authentication user interactions. For example, replacement GINA DLLs can implement smart card, retinal-scan, or other authentication mechanisms in place of the standard Windows NT/Windows 2000 user name and password authentication. Network provider DLL is not used in our case. SecurityEach client requires a security key at the time of setup. This key should be the same for a group of PCs. Several groups can exist but user can login only on the same group. If there is only one group (all PCs use the same key) everyone can login to every PC. The security key is kept with Windows. This key is required while creating the authentication disk. Every disk contains Windows user information and this is checked using Local Security Authority (LSA) of Windows. The User.Info FileThe Authentication ProcessWhen the computer boots up, the Winlogon initializes and negotiates with GINA. The GINA shows a dialog box and waits for the user to insert his/ her mobile disk (Figure 2).
Figure 2.
When a removable device is inserted into or replaced from a computer, a system wide ImplementationThe application has four parts:
Now let me give a short description for each of them. Custom GINAThis is the heart of the project. It is used by Windows to interact with the user to manage a user session. It is a DLL with predefined functions. We make our GINA implementation to be used with mobile disk. Here I show the int WINAPI WlxLoggedOutSAS (
PVOID pWlxContext,
DWORD dwSasType,
PLUID pAuthenticationId,
PSID pLogonSid,
PDWORD pdwOptions,
PHANDLE phToken,
PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
PVOID * pProfile)
{
if(MY_SAS_TYPE!=dwSasType)
return WLX_SAS_ACTION_NONE;
PGINA_CONTEXT pgContext = (PGINA_CONTEXT) pWlxContext;
int ret = pgContext->pWlxFuncs->WlxDialogBox(pgContext->hWlx,
pgContext->hDllInstance,
(LPWSTR)MAKEINTRESOURCE(IDD_INSERT_CARD_NOTICE_DIALOG),
NULL,
DisplaySASNoticeDlgProc
);
if(ret==IDCANCEL)
{
return WLX_SAS_ACTION_SHUTDOWN;
}
if (ret != IDC_LOGON_BUTTON)
{
return WLX_SAS_ACTION_NONE;
}
TOKEN_STATISTICS userStats;
TOKEN_GROUPS * pGroups;
DWORD cbStats;
if (!phToken)
return WLX_SAS_ACTION_NONE;
while(1)
{
if (!LogonUser(g_lpUserName,
g_lpDomain,
g_lpPassword,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
phToken))
{
//Logon failed. Give user a chance to update his disk
ret = pgContext->pWlxFuncs->WlxDialogBox(pgContext->hWlx,
pgContext->hDllInstance,
(LPWSTR)MAKEINTRESOURCE(IDD_WIN_LOGON_DIALOG),
NULL,
UpdateWindowsUserDlgProc
);
if (ret != IDOK)
{
return WLX_SAS_ACTION_NONE;
}
}
else
break;
}
pgContext->hUserToken=*phToken;
// Pass back null profile and options.
*pdwOptions = 0;
*pProfile =NULL;
// Get the authenticationid from the user token.
if (!GetTokenInformation(*phToken,
TokenStatistics,
(PVOID) &userStats,
sizeof(TOKEN_STATISTICS),
&cbStats)
)
{
return WLX_SAS_ACTION_NONE;
}
else
{
*pAuthenticationId = userStats.AuthenticationId;
}
DWORD size,i;
pGroups = (TOKEN_GROUPS *)LocalAlloc(LMEM_FIXED, 1024);
GetTokenInformation(*phToken,
TokenGroups,
pGroups,
1024,
&size);
if (size > 1024)
{
pGroups = (TOKEN_GROUPS *)LocalReAlloc(pGroups, LMEM_FIXED, size);
GetTokenInformation(*phToken,
TokenGroups,
pGroups,
size,
&size);
}
for (i = 0; i < pGroups->GroupCount ; i++)
{
if ((pGroups->Groups[i].Attributes & SE_GROUP_LOGON_ID) ==
SE_GROUP_LOGON_ID)
{
CopySid(GetLengthSid(pLogonSid),
pLogonSid,
pGroups->Groups[i].Sid );
break;
}
}
LocalFree(pGroups);
pMprNotifyInfo->pszUserName=DupMbToWsString(g_lpUserName);
pMprNotifyInfo->pszDomain=DupMbToWsString(g_lpDomain);
pMprNotifyInfo->pszPassword=DupMbToWsString(g_lpPassword);
pMprNotifyInfo->pszOldPassword = NULL;
return WLX_SAS_ACTION_LOGON;
}
The dialog procedure is as follows: int CALLBACK DisplaySASNoticeDlgProc(
HWND hDlg,
UINT Message,
WPARAM wParam,
LPARAM lParam)
{
PDEV_BROADCAST_HDR pheadBC;
PDEV_BROADCAST_VOLUME pVol;
HWND hMsg=GetDlgItem(hDlg,IDC_STATUS_STATIC);
CUserInfo ui;
int drv;
char lpPath[255];
switch (Message)
{
case WM_DEVICECHANGE:
Sleep(2000);
pheadBC=(PDEV_BROADCAST_HDR)lParam;
if(wParam==DBT_DEVICEARRIVAL && pheadBC->dbch_devicetype==DBT_DEVTYP_VOLUME)
{
pVol=(PDEV_BROADCAST_VOLUME)lParam;
drv=ui.ValidDiskPresent();
lpPath[255];
if(drv)
{
sprintf(lpPath,"%c:\\%s",'A'+drv,DISK_FILE_NAME);
USER_INFO user_info=ui.LoadUserInfo(lpPath);
user_info=ui.Decode(user_info);
strcpy(g_lpUserName,user_info.lpWindowsUser);
strcpy(g_lpPassword,user_info.lpWindowsPassword);
if(strlen(user_info.lpDomain))
strcpy(g_lpDomain,user_info.lpDomain);
else
{
strcpy(g_lpDomain,".");
}
g_nLoginType=user_info.dwLogonType;
EndDialog(hDlg, ID_LOGON_SUCCESS);
}
}
break;
}
return(FALSE);
}
Device Monitor ApplicationThis application is used to monitor the mobile disk. If the user removes a mobile disk, the system sends LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message)
{
case WM_DEVICECHANGE:
if(wParam==DBT_DEVICEREMOVECOMPLETE)
{
if(!g_bLogoutOnDiskRemove) break;
//MessageBox(0,"Device Removed",0,0);
if(!g_UserInfo.ValidDiskPresent())
ExitWindows(EWX_LOGOFF,EWX_FORCEIFHUNG);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
We need to check if a valid disk is still present on system to make sure the actual logon disk is removed. BOOL CUserInfo::ValidDiskPresent()
{
TCHAR drive[10], lpPath[100];
DWORD dwDrives=GetLogicalDrives();
for(int i=2;i<26;i++)
{
int bit=(int)pow((double)2,i);
if(dwDrives&bit)
{
sprintf(drive,"%c:",'A'+i);
if(FIND_DRIVE_TYPE==GetDriveType(drive))
{
sprintf(lpPath,"%c:\\%s",'A'+i,DISK_FILE_NAME);
if(!PathFileExists(lpPath))continue;
USER_INFO user_info=LoadUserInfo(lpPath);
user_info=Decode(user_info);
if(CheckDisk(user_info,i))
return i;
}
}
}
return 0;
}
The KeyGen ApplicationThis application is used to generate userinfo file on mobile disk. It takes input from the user. It shows a combo box of all users to select from. To enumerate users in a combo box, we use the following function. void CSelectUserDlg::EnumUsers()
{
LPUSER_INFO_0 pBuf = NULL;
LPUSER_INFO_0 pTmpBuf;
DWORD dwLevel = 0;
DWORD dwPrefMaxLen = -1;
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD dwResumeHandle = 0;
DWORD i;
DWORD dwTotalCount = 0;
NET_API_STATUS nStatus;
char *pmbbuf = (char *)malloc( 100 );
// Call the NetUserEnum function, specifying level 0;
// enumerate global user account types only.
//
do // begin do
{
nStatus = NetUserEnum((LPCWSTR)pszServerName,
dwLevel,
FILTER_NORMAL_ACCOUNT, // global/domain users
(LPBYTE*)&pBuf,
dwPrefMaxLen,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
{
if ((pTmpBuf = pBuf) != NULL)
{
for (i = 0; (i < dwEntriesRead); i++)
{
if (pTmpBuf == NULL)
{
return;
}
wcstombs( pmbbuf, pTmpBuf->usri0_name, 99 );
m_UsersCombo.AddString((char *)pmbbuf);
pTmpBuf++;
dwTotalCount++;
}
}
}
if (pBuf != NULL)
{
NetApiBufferFree(pBuf);
pBuf = NULL;
}
}
while (nStatus == ERROR_MORE_DATA); // end do
if (pBuf != NULL)
NetApiBufferFree(pBuf);
}
The Setup ApplicationIt stores both previous applications (excluding InstallationUse setup.exe to install on the client PC. Please be careful while entering the security key. If this key is wrong, you may not logon to Windows locally even if you are the administrator. Create Logon DiskUse UninstallLogon to an administrator account and use setup.exe to uninstall
| ||||||||||||||||||||