Leaked source code of windows server 2003
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.
 
 
 
 
 
 

354 lines
11 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
ItgRasXp
File Name:
ItgRasXp.cpp
Abstract:
This is the entry point file for the ITG RAS Smartcard Support Applet. This app
prompts the user for his domain\username and password credentials, and uses
these to create a *Session credential that is used for NTLM authentication for
servers on the network which do not use Kerberos.
Author:
Environment:
Win32, C++
Revision History:
none
Notes:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <commdlg.h>
#include <commctrl.h>
#include <ole2.h>
#include <stdio.h>
#include <lmcons.h>
#include <wincred.h>
#include <wincrui.h>
#define SECURITY_WIN32
#include <security.h>
#include "testaudit.h"
#include "res.h"
BOOL gfSuccess = FALSE;
HINSTANCE ghInstance = NULL;
#if 0
#define TESTKEY L"Environment"
#else
#define TESTKEY L"Software\\Microsoft\\Connection Manager\\Worldwide Dial-Up RAS to MS Corp"
#endif
// see if name valid - check for common mistakes. At the moment, we merely insist that
// the user fill in both username and password, and that the username contains the '\'
// character, making it more likely that it is an approved domain\usernaem form.
BOOL CheckUsername(WCHAR *pszUsername,WCHAR *pszPassword)
{
ASSERT(pszUsername);
ASSERT(pszPassword);
if ((0 == wcslen(pszUsername)) || (0 == wcslen(pszPassword)))
{
CHECKPOINT(2,"Username and password not both filled in.");
MessageBox(NULL,L"Both username and password must be specified.",L"Error",MB_ICONHAND);
return FALSE;
}
if (NULL == wcschr(pszUsername,L'\\'))
{
CHECKPOINT(3,"Username not domain\\username.");
MessageBox(NULL,L"The username format must be \"domain\\username\".",L"Error",MB_ICONHAND);
return FALSE;
}
else return TRUE;
}
// Attempt to use the credentials that the user entered and return FALSE if they do not
// appear to be valid on the net. Show the user any errors that arise from trying to validate
// his credentials. In the event that validation is impossible owing to a network error or some
// other error not the fault of his credentials, save them anyway, though with a warning.
#define DEFAULTSERVER L"\\\\products\\public"
BOOL IsCredentialOK(WCHAR *pszUsername,WCHAR *pszPassword)
{
ASSERT(pszUsername);
ASSERT(pszPassword);
NETRESOURCE stNetResource;
WCHAR szServer[MAX_PATH + 1]; // to hold test host string from registry
BOOL fKeyFound = FALSE;
DWORD dwErr = 0;
DWORD dwSize = 0; // for return from open connection
DWORD dwResult = 0; // for return from open connection
HKEY hKey= NULL; // reg key rread
DWORD dwType; // reg key read return
DWORD dwDataSize = 0; // reg key read in/out
memset(&stNetResource,0,sizeof(NETRESOURCE));
// prepare the servername preset to the default
wcsncpy(szServer,DEFAULTSERVER,MAX_PATH);
// Look for server in registry HKCU. If found, use it to overwrite the default server
if ((!fKeyFound) && (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER,TESTKEY,0,KEY_READ,&hKey)))
{
if ((hKey) && (ERROR_SUCCESS == RegQueryValueEx(hKey,L"RAS Test Host",0,&dwType,(LPBYTE) NULL,&dwDataSize)))
{
// key value exists and is of size dwDataSize
WCHAR *pString = (WCHAR *) LocalAlloc(LMEM_FIXED,dwDataSize);
ASSERT(pString);
ASSERT(dwType == REG_SZ);
if (pString)
{
if (ERROR_SUCCESS == RegQueryValueEx(hKey,L"RAS Test Host",0,&dwType,(LPBYTE) pString,&dwDataSize))
{
CHECKPOINT(9,"Override server found in registry in HKCU");
wcsncpy(szServer,pString,dwDataSize / sizeof(WCHAR));
fKeyFound = TRUE;
}
LocalFree(pString);
}
}
RegCloseKey(hKey);
hKey = NULL;
}
// Look for server in registry HKLM.
if ((!fKeyFound) && (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,TESTKEY,0,KEY_READ,&hKey)))
{
if ((hKey) && (ERROR_SUCCESS == RegQueryValueEx(hKey,L"RAS Test Host",0,&dwType,(LPBYTE) NULL,&dwDataSize)))
{
// key value exists and is of size dwDataSize
WCHAR *pString = (WCHAR *) LocalAlloc(LMEM_FIXED,dwDataSize);
ASSERT(pString);
ASSERT(dwType == REG_SZ);
if (pString)
{
if (ERROR_SUCCESS == RegQueryValueEx(hKey,L"RAS Test Host",0,&dwType,(LPBYTE) pString,&dwDataSize))
{
CHECKPOINT(8,"Override server found in registry in HKLM");
wcsncpy(szServer,pString,dwDataSize / sizeof(WCHAR));
fKeyFound = TRUE;
}
LocalFree(pString);
}
}
RegCloseKey(hKey);
hKey = NULL;
}
#if TESTAUDIT
if (!fKeyFound) CHECKPOINT(10,"No override server found in registry");
#endif
stNetResource.dwType = RESOURCETYPE_DISK;
stNetResource.lpLocalName = NULL;
stNetResource.lpRemoteName = szServer;
stNetResource.lpProvider = NULL;
dwErr = WNetUseConnection( NULL,
&stNetResource,
pszPassword,
pszUsername,
0,
NULL, // lpAccessName
&dwSize, // size of lpAccessName buffer
&dwResult);
if (dwErr == S_OK)
{
// On successful connection, tear down the connection and return success
WNetCancelConnection2(szServer, 0, TRUE);
return TRUE;
}
// Errors are handled by presenting a message box. If the server was found and rejected
// the creds, don't save them - give the user a chance to correct. If the server was
// unavailable, save the creds anyway, but warn the user that they were unvalidated.
switch (dwErr)
{
case ERROR_ACCESS_DENIED:
case ERROR_INVALID_PASSWORD:
// announce that the password is no good
CHECKPOINT(7,"Reached the server, but the creds were no good");
MessageBox(NULL,L"The entered username and password are not correct",L"Error",MB_ICONHAND);
break;
case ERROR_NO_NET_OR_BAD_PATH:
case ERROR_NO_NETWORK:
case ERROR_EXTENDED_ERROR:
case ERROR_BAD_NET_NAME:
case ERROR_BAD_PROVIDER:
default:
CHECKPOINT(6,"Not able to validate - server unreachable");
MessageBox(NULL,L"Your username and password will be saved for this session, though they could not be verified. They may be incorrect.",L"Error",MB_ICONHAND);
return TRUE; // permit them to be saved anyway
// announce that we cannot validate, and let them save it anyway
break;
}
return FALSE;
}
// Store the user's entered credentials on the keyring as a session persisted *Session cred.
// Call IsCredentialOK() before storing. If the credentials don't appear correct, present
// a message box describing the error and leave the dialog up.
BOOL WriteDomainCreds(WCHAR *pszUsername,WCHAR *pszPassword)
{
CREDENTIAL cred;
if (!CheckUsername(pszUsername,pszPassword))
{
return FALSE;
}
if (!IsCredentialOK(pszUsername,pszPassword))
{
return FALSE;
}
memset(&cred,0,sizeof(CREDENTIAL));
cred.TargetName = CRED_SESSION_WILDCARD_NAME_W;
cred.UserName = pszUsername;
cred.CredentialBlob = (LPBYTE) pszPassword;
cred.CredentialBlobSize = (wcslen(pszPassword) * sizeof(WCHAR));
cred.Type = CRED_TYPE_DOMAIN_PASSWORD;
cred.Persist = CRED_PERSIST_SESSION;
return CredWrite(&cred,0);
}
INT_PTR CALLBACK DialogProc(
HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
INT_PTR ret;
HWND hwndCred = NULL;
switch (msg)
{
case WM_COMMAND:
// Button clicks.
switch(LOWORD(wparam))
{
case IDOK:
if (HIWORD(wparam) == BN_CLICKED)
{
WCHAR szUser[UNLEN + 1];
WCHAR szPass[PWLEN + 1];
szUser[0] = 0;
szPass[0] = 0;
HWND hCc = GetDlgItem(hwnd,IDC_CRED);
ASSERT(hCc);
Credential_GetUserName(hCc,szUser,UNLEN);
Credential_GetPassword(hCc,szPass,PWLEN);
// Get contents of the cred control controls and write the session cred
gfSuccess = WriteDomainCreds(szUser,szPass);
SecureZeroMemory(szPass,sizeof(szPass));
if (gfSuccess)
{
EndDialog(hwnd,IDOK);
}
}
break;
case IDCANCEL:
if (HIWORD(wparam) == BN_CLICKED)
{
CHECKPOINT(5,"Leave the dialog by cancel.");
// Exit doing nothing
EndDialog(hwnd,IDCANCEL);
}
break;
default:
break;
}
break;
default:
break;
}
//return DefWindowProc(hwnd, msg, wparam, lparam);
return FALSE;
}
int WINAPI WinMain (
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdParam,
int nCmdShow)
{
CHECKPOINTINIT;
ghInstance = hInstance;
//OleInitialize(NULL);
INITCOMMONCONTROLSEX stICC;
BOOL fICC;
stICC.dwSize = sizeof(INITCOMMONCONTROLSEX);
stICC.dwICC = ICC_WIN95_CLASSES | ICC_STANDARD_CLASSES;
fICC = InitCommonControlsEx(&stICC);
// Silent fail if there is no preexisting cert credential.
CREDENTIAL *pCred = NULL;
BOOL fOK = CredRead(L"*Session",CRED_TYPE_DOMAIN_CERTIFICATE,0,&pCred);
CredFree(pCred);
if (!fOK)
{
CHECKPOINT(1,"No preexisting certificate cred for *Session");
CHECKPOINTFINISH;
return 1;
}
// Gen up credui
if (!CredUIInitControls())
{
return 1;
}
// show the ui
INT_PTR iErr = DialogBoxParam(
hInstance,
MAKEINTRESOURCE(IDD_MAINDIALOG),
GetForegroundWindow(),
DialogProc,
NULL);
if (iErr != IDOK && iErr != IDCANCEL)
{
MessageBox(NULL,L"An error occurred saving credential information.",L"Error",MB_OK);
CHECKPOINTFINISH;
return 0;
}
else
{
CHECKPOINT(4,"Sucessfully saved a cred.");
CHECKPOINTFINISH;
return 1;
}
}