437 lines
15 KiB
C++
437 lines
15 KiB
C++
/*++
|
||
|
||
Copyright (c) 1998 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
digestui.cxx
|
||
|
||
Abstract:
|
||
|
||
Authentication UI for digest sspi package.
|
||
|
||
Author:
|
||
|
||
Adriaan Canter (adriaanc) 01-Aug-1998
|
||
|
||
History
|
||
|
||
Sudeep Bharati (sudeepb) 24-Sep-1998
|
||
Added support for ms specific header additions for Trustmarks
|
||
Added support for Passport specific header additions for custom text,
|
||
Trustmarks support and Register me button. Passport specific support
|
||
also adds some rules on the typed in username.
|
||
|
||
Adriaan Canter (adriaanc) 16-Dec-1998
|
||
Expunged all Passport code.
|
||
|
||
--*/
|
||
#include "include.hxx"
|
||
#include "resource.h"
|
||
#include "exdisp.h"
|
||
|
||
HANDLE hDigest;
|
||
|
||
// BUGBUG - DISABLE DROP DOWN IF NO CREDS.
|
||
//--------------------------------------------------------------------
|
||
// DigestErrorDlg
|
||
//--------------------------------------------------------------------
|
||
DWORD DigestErrorDlg(LPSTR szCtx, LPSTR szHost, LPSTR szRealm,
|
||
LPSTR szUser, LPSTR szNonce, LPSTR szCNonce, CCredInfo *pInfoIn,
|
||
CCredInfo **ppInfoOut, HWND hWnd)
|
||
{
|
||
INT nResult = 0;
|
||
DWORD dwError = ERROR_SUCCESS;
|
||
LPTSTR lpRes;
|
||
DigestDlgParams DlgPrms;
|
||
|
||
// Parameters to be passed to DigestAuthDialogProc.
|
||
DlgPrms.szCtx = szCtx;
|
||
DlgPrms.szHost = szHost;
|
||
DlgPrms.szRealm = szRealm;
|
||
DlgPrms.szUser = szUser;
|
||
DlgPrms.szNonce = szNonce;
|
||
DlgPrms.szCNonce = szCNonce;
|
||
DlgPrms.pInfoIn = pInfoIn;
|
||
|
||
|
||
LPARAM lpParam = (LPARAM) &DlgPrms;
|
||
if (WaitForSingleObject (hDigest, INFINITE) != WAIT_OBJECT_0) {
|
||
dwError = ERROR_NOT_READY;
|
||
goto quit;
|
||
}
|
||
|
||
lpRes = MAKEINTRESOURCE(IDD_DIGEST);
|
||
|
||
|
||
nResult = (INT)DialogBoxParam(g_hModule,
|
||
lpRes,
|
||
hWnd,
|
||
DigestAuthDialogProc,
|
||
(LPARAM) lpParam);
|
||
|
||
|
||
if (nResult == FALSE || nResult == -1)
|
||
{
|
||
dwError = ERROR_CANCELLED;
|
||
*ppInfoOut = NULL;
|
||
goto quit;
|
||
}
|
||
|
||
// *ppInfoOut points to a CCredInfo created in the
|
||
// DigestAuthDialog proc.
|
||
*ppInfoOut = DlgPrms.pInfoOut;
|
||
|
||
quit:
|
||
// delete DlgPrms.szCtx; biaow: we should NOT delete here; the caller will take care of this
|
||
return dwError;
|
||
}
|
||
|
||
|
||
|
||
//--------------------------------------------------------------------
|
||
// DigestAuthDialogProc
|
||
//--------------------------------------------------------------------
|
||
INT_PTR CALLBACK DigestAuthDialogProc(HWND hwnd, UINT msg,
|
||
WPARAM wparam, LPARAM lparam)
|
||
{
|
||
static CCredInfo *pList = NULL;
|
||
static HWND hCtrlText,hCtrlVerify;
|
||
|
||
PDigestDlgParams pDlgPrms;
|
||
USHORT len;
|
||
LPSTR p,q;
|
||
|
||
CHAR szUser[MAX_USERNAME_LEN + 1];
|
||
CHAR szPass[MAX_PASSWORD_LEN + 1];
|
||
|
||
BOOL fCreated = FALSE;
|
||
BOOL fPersisted = FALSE;
|
||
|
||
BSTR bstr;
|
||
CHAR szTextTemp [MAX_LOGIN_TEXT];
|
||
CHAR szText [MAX_LOGIN_TEXT];
|
||
|
||
switch (msg)
|
||
{
|
||
// Dialog is being initialized.
|
||
case WM_INITDIALOG:
|
||
{
|
||
ReleaseMutex (hDigest);
|
||
|
||
// pDlgPrms->pInfoIn can be NULL or point
|
||
// to one or more CCredInfo structs.
|
||
pDlgPrms = (DigestDlgParams *) lparam;
|
||
DIGEST_ASSERT(pDlgPrms);
|
||
|
||
SetWindowLongPtr(hwnd, DWLP_USER, lparam);
|
||
|
||
SetForegroundWindow(hwnd);
|
||
|
||
// Take Care of Host field
|
||
|
||
hCtrlText = GetDlgItem (hwnd, IDD_LOGIN_TEXT1);
|
||
len = (USHORT)GetWindowText (hCtrlText,szTextTemp,MAX_LOGIN_TEXT);
|
||
if (len == 0) {
|
||
DIGEST_ASSERT(FALSE);
|
||
EndDialog (hwnd, FALSE);
|
||
return TRUE;
|
||
}
|
||
if ((p = strchr (szTextTemp, '%')) == NULL) {
|
||
DIGEST_ASSERT(FALSE);
|
||
EndDialog (hwnd, FALSE);
|
||
return TRUE;
|
||
}
|
||
*p++ = '\0';
|
||
strcpy (szText, szTextTemp);
|
||
if (pDlgPrms->szHost)
|
||
strcat (szText,pDlgPrms->szHost);
|
||
else {
|
||
if (len = (USHORT)LoadString (g_hModule,IDS_STRING_UDOMAIN,
|
||
szUser,MAX_USERNAME_LEN))
|
||
strcat (szText,szUser);
|
||
}
|
||
strcat (szText, p);
|
||
if (!SetWindowText (hCtrlText,szText)) {
|
||
DIGEST_ASSERT(FALSE);
|
||
EndDialog (hwnd, FALSE);
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
// Take care of Realm and Hint fields. Remember Passport has
|
||
// hard coded text for this second line.
|
||
hCtrlText = GetDlgItem (hwnd, IDD_LOGIN_TEXT2);
|
||
len = (USHORT)GetWindowText (hCtrlText,szTextTemp,MAX_LOGIN_TEXT);
|
||
if (len == 0) {
|
||
DIGEST_ASSERT(FALSE);
|
||
EndDialog (hwnd, FALSE);
|
||
return TRUE;
|
||
}
|
||
if ((p = strchr (szTextTemp, '%')) == NULL) {
|
||
DIGEST_ASSERT(FALSE);
|
||
EndDialog (hwnd, FALSE);
|
||
return TRUE;
|
||
}
|
||
*p++ = '\0';
|
||
strcpy (szText, szTextTemp);
|
||
if (pDlgPrms->szRealm)
|
||
{
|
||
DWORD dwAvailBuf = MAX_LOGIN_TEXT - strlen(szText);
|
||
strncpy(szText + strlen(szText), pDlgPrms->szRealm, dwAvailBuf - 1);
|
||
szText[MAX_LOGIN_TEXT - 1] = 0;
|
||
// strcat (szText,pDlgPrms->szRealm);
|
||
}
|
||
else {
|
||
if (len = (USHORT)LoadString (g_hModule,IDS_STRING_UREALM,
|
||
szUser,MAX_USERNAME_LEN))
|
||
strcat (szText,szUser);
|
||
}
|
||
|
||
strcat (szText,p);
|
||
|
||
if (!SetWindowText (hCtrlText,szText)) {
|
||
DIGEST_ASSERT(FALSE);
|
||
EndDialog (hwnd, FALSE);
|
||
return TRUE;
|
||
}
|
||
|
||
// Determine if credential persistence is available.
|
||
if (g_dwCredPersistAvail == CRED_PERSIST_UNKNOWN)
|
||
g_dwCredPersistAvail = InetInitCredentialPersist();
|
||
|
||
// If credential persist not available, hide checkbox.
|
||
if (g_dwCredPersistAvail == CRED_PERSIST_NOT_AVAIL)
|
||
ShowWindow(GetDlgItem(hwnd, IDC_SAVE_PASSWORD), SW_HIDE);
|
||
|
||
|
||
// Find any persisted credential.
|
||
if (g_dwCredPersistAvail
|
||
&& ((InetGetCachedCredentials(pDlgPrms->szCtx, pDlgPrms->szRealm,
|
||
szUser, szPass) == ERROR_SUCCESS)))
|
||
{
|
||
// Retrieved a set of credentials. If a username was passed
|
||
// in check to see that the persisted username matches.
|
||
if (!pDlgPrms->szUser || !strcmp(pDlgPrms->szUser, szUser))
|
||
{
|
||
// No username passed in or usernames match.
|
||
// Create a CCredInfo and insert it into head of list.
|
||
pList = new CCredInfo(pDlgPrms->szHost, pDlgPrms->szRealm, szUser, szPass,
|
||
pDlgPrms->szNonce, pDlgPrms->szCNonce);
|
||
if (!pList || pList->dwStatus != ERROR_SUCCESS)
|
||
{
|
||
DIGEST_ASSERT(FALSE);
|
||
return FALSE;
|
||
}
|
||
// Insert it at the beginning of the list.
|
||
pList->pNext = pDlgPrms->pInfoIn;
|
||
if (pDlgPrms->pInfoIn)
|
||
pDlgPrms->pInfoIn->pPrev = pList;
|
||
|
||
fPersisted = TRUE;
|
||
fCreated = TRUE;
|
||
}
|
||
}
|
||
|
||
// If we did not retrieve a persisted credential, check to see
|
||
// if we need to create a dummy credential.
|
||
if (!fPersisted)
|
||
{
|
||
// Create a dummy credential if a username was passed in
|
||
// but a credential was not retrieved from memory.
|
||
if (pDlgPrms->szUser && !pDlgPrms->pInfoIn)
|
||
{
|
||
pList = new CCredInfo(pDlgPrms->szHost, pDlgPrms->szRealm, pDlgPrms->szUser, NULL,
|
||
pDlgPrms->szNonce, pDlgPrms->szCNonce);
|
||
fCreated = TRUE;
|
||
}
|
||
else
|
||
{
|
||
// Otherwise, just point to the creds
|
||
// retrieved from memory.
|
||
pList = pDlgPrms->pInfoIn;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
// A persisted credential was created and inserted
|
||
// into the beginning of the list. The list may
|
||
// contain a CCredInfo with a matching user.
|
||
// remove any (at most one) duplicate entry.
|
||
CCredInfo *pCur;
|
||
pCur = pList->pNext;
|
||
while (pCur)
|
||
{
|
||
if (!strcmp(pCur->szUser, pList->szUser))
|
||
{
|
||
pCur->pPrev->pNext = pCur->pNext;
|
||
if (pCur->pNext)
|
||
pCur->pNext->pPrev = pCur->pPrev;
|
||
|
||
break;
|
||
}
|
||
pCur = pCur->pNext;
|
||
}
|
||
}
|
||
|
||
// The list is now in the correct format:
|
||
// 1) pList may be NULL
|
||
// 2) pList may have a dummy credential for username with no password.
|
||
// 3) pList may have one credential for username with password.
|
||
// 4) pList may have one or more credentials for different usernames.
|
||
|
||
// Limit drop-down if no items in list.
|
||
if (!pList)
|
||
{
|
||
SendMessage(GetDlgItem(hwnd, IDC_COMBO1), CB_ADDSTRING, 0, (LPARAM) (LPCSTR) "");
|
||
}
|
||
|
||
// Populate the combo box with the list contents.
|
||
CCredInfo *pCur;
|
||
pCur = pList;
|
||
while (pCur)
|
||
{
|
||
SendMessage(GetDlgItem(hwnd, IDC_COMBO1), CB_ADDSTRING, 0, (LPARAM) (LPCSTR) pCur->szUser);
|
||
pCur = pCur->pNext;
|
||
}
|
||
|
||
// If the first item in the combo box was created (user given or persisted)
|
||
// set it as the default and set it's password in the password control.
|
||
// Indicate if credentials are from persisted store.
|
||
|
||
// Default to 0th item.
|
||
SendMessage(GetDlgItem(hwnd, IDC_COMBO1), CB_SETCURSEL, 0, 0);
|
||
|
||
// Set password field if extant.
|
||
if (pList)
|
||
SetWindowText (GetDlgItem(hwnd,IDC_PASSWORD_FIELD), pList->szPass);
|
||
|
||
// Indicate if credentials from persisted store.
|
||
if (fPersisted)
|
||
CheckDlgButton(hwnd, IDC_SAVE_PASSWORD, BST_CHECKED);
|
||
|
||
SetFocus(GetDlgItem(hwnd, IDC_COMBO1));
|
||
|
||
// Return FALSE since we are always setting the keyboard focus.
|
||
return FALSE;
|
||
}
|
||
|
||
// WM comands from action on dialog.
|
||
case WM_COMMAND:
|
||
{
|
||
WORD wID = LOWORD(wparam);
|
||
WORD wNotificationCode = HIWORD(wparam);
|
||
HWND hWndCtrl = (HWND) lparam;
|
||
|
||
pDlgPrms = (DigestDlgParams*) GetWindowLongPtr(hwnd, DWLP_USER);
|
||
DIGEST_ASSERT(pDlgPrms);
|
||
|
||
// User has selected something on the combo-box.
|
||
switch(wNotificationCode)
|
||
{
|
||
// User has selected a drop-down item.
|
||
case CBN_SELCHANGE:
|
||
{
|
||
// Get the index of the selected item.
|
||
DWORD nIndex;
|
||
nIndex = (DWORD)SendMessage(GetDlgItem(hwnd, IDC_COMBO1), CB_GETCURSEL, 0, 0);
|
||
if (nIndex == -1)
|
||
{
|
||
SendMessage(GetDlgItem(hwnd, IDC_COMBO1), CB_SETCURSEL, 0, 0);
|
||
return FALSE;
|
||
}
|
||
|
||
// Point to the indexed CCredInfo entry
|
||
CCredInfo *pCur;
|
||
pCur = pList;
|
||
for (DWORD i = 0; i < nIndex ; i++)
|
||
pCur = pCur->pNext;
|
||
|
||
// Set password of the indexed CCredInfo struct.
|
||
SetWindowText (GetDlgItem(hwnd,IDC_PASSWORD_FIELD), pCur ? pCur->szPass : "");
|
||
|
||
// User may have selected username with persisted credentials.
|
||
if (g_dwCredPersistAvail)
|
||
{
|
||
// If selected CCredInfo has a user with persisted credentials
|
||
if ((InetGetCachedCredentials(pDlgPrms->szCtx, pDlgPrms->szRealm,
|
||
szUser, szPass) == ERROR_SUCCESS)
|
||
&& !strcmp(pCur->szUser, szUser))
|
||
{
|
||
// Indicate that this user has persisted creds for the realm.
|
||
CheckDlgButton(hwnd, IDC_SAVE_PASSWORD, BST_CHECKED);
|
||
}
|
||
else
|
||
{
|
||
// Otherwise Indicate that this user does not have persisted
|
||
// creds for the realm.
|
||
CheckDlgButton(hwnd, IDC_SAVE_PASSWORD, BST_UNCHECKED);
|
||
}
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
// User has clicked OK or Cancel button.
|
||
switch (wID)
|
||
{
|
||
case IDOK:
|
||
{
|
||
CCredInfo *pOut;
|
||
|
||
// User has clicked on OK button.
|
||
|
||
// Get the username and password into the output CCredInfo.
|
||
GetWindowText(GetDlgItem(hwnd,IDC_COMBO1), szUser, MAX_USERNAME_LEN);
|
||
GetWindowText(GetDlgItem(hwnd,IDC_PASSWORD_FIELD), szPass, MAX_PASSWORD_LEN);
|
||
|
||
|
||
// If save box checked, persist credentials.
|
||
if (IsDlgButtonChecked(hwnd, IDC_SAVE_PASSWORD) == BST_CHECKED)
|
||
{
|
||
InetSetCachedCredentials(pDlgPrms->szCtx, pDlgPrms->szRealm,
|
||
szUser, szPass);
|
||
}
|
||
else
|
||
{
|
||
// Otherwise the button is not checked. Check to see if we should
|
||
// remove the credentials from persisted store.
|
||
if (g_dwCredPersistAvail)
|
||
{
|
||
// If current and original credentials are for same user,
|
||
// remove the credentials.
|
||
CHAR szUserPersist[MAX_USERNAME_LEN], szPassPersist[MAX_PASSWORD_LEN];
|
||
if ((InetGetCachedCredentials(pDlgPrms->szCtx, pDlgPrms->szRealm,
|
||
szUserPersist, szPassPersist) == ERROR_SUCCESS)
|
||
&& !strcmp(szUser, szUserPersist))
|
||
{
|
||
InetRemoveCachedCredentials(pDlgPrms->szCtx, pDlgPrms->szRealm);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Allocate a new CCredInfo struct to return.
|
||
pOut = new CCredInfo(pDlgPrms->szHost, pDlgPrms->szRealm, szUser, szPass,
|
||
pDlgPrms->szNonce, pDlgPrms->szCNonce);
|
||
if (!pOut)
|
||
{
|
||
DIGEST_ASSERT(FALSE);
|
||
}
|
||
pDlgPrms->pInfoOut = pOut;
|
||
EndDialog(hwnd, TRUE);
|
||
break;
|
||
}
|
||
case IDCANCEL:
|
||
{
|
||
// User has canceled dialog - no action.
|
||
EndDialog(hwnd, FALSE);
|
||
break;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
}
|
||
return FALSE;
|
||
}
|
||
|