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.
 
 
 
 
 
 

424 lines
14 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
CHGPSW.CPP
Abstract:
Handler for the CHANGE button on the properties dialog,
used to change the user's domain password.
Author:
990917 johnhaw Created.
georgema 000310 updated
georgema 000501 used to be EXE, changed to CPL
Comments:
Environment:
WinXP
Revision History:
--*/
// test/dev switch variables
#include "switches.h"
//////////////////////////////////////////////////////////////////////////////
//
// Include files
//
#include <stdlib.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winbase.h>
#include <lmaccess.h>
#include <lmerr.h>
#include <scuisupp.h>
#include <wincrui.h>
#include <comctrlp.h>
#include <tchar.h>
#include <shfusion.h>
#include "switches.h"
#include "Dlg.h"
#include "Res.h"
#include "KRDlg.h"
#include "keymgr.h"
#include "testaudit.h"
#include "pswutil.h"
//////////////////////////////////////////////////////////////////////////////
//
// C_ChangePasswordDlg
//
// Constructor.
//
// parameters:
// hwndParent parent window for the dialog (may be NULL)
// hInstance instance handle of the parent window (may be NULL)
// lIDD dialog template id
// pfnDlgProc pointer to the function that will process messages for
// the dialog. if it is NULL, the default dialog proc
// will be used.
//
// returns:
// Nothing.
//
//////////////////////////////////////////////////////////////////////////////
C_ChangePasswordDlg::C_ChangePasswordDlg(
HWND hwndParent,
HINSTANCE hInstance,
LONG lIDD,
DLGPROC pfnDlgProc // = NULL
)
: C_Dlg(hwndParent, hInstance, lIDD, pfnDlgProc)
{
m_hInst = hInstance;
} // C_ChangePasswordDlg::C_ChangePasswordDlg
//////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
// Dialog control and data initialization.
//
// parameters:
// hwndDlg window handle of the dialog box
// hwndFocus window handle of the control that will receive focus
//
// returns:
// TRUE if the system should set the default keyboard focus
// FALSE if the keyboard focus is set by this app
//
//////////////////////////////////////////////////////////////////////////////
BOOL
C_ChangePasswordDlg::OnInitDialog(
HWND hwndDlg,
HWND hwndFocus
)
{
// To economize on memory, szMsg buffer is sized considerably longer than the MAX_STRING_SIZE
// that would be expected for its normal use for short messages. In one instance, it is being
// used to hold a username (line 139). It is, therefore considerably longer than otherwise needed.
// This size mismatch is benignly not reflected in code which uses counted string functions to
// copy/cat into this buffer. This is the result of the buffer length having been changed after
// the surrounding code was originally written.
TCHAR szMsg[CRED_MAX_USERNAME_LENGTH + 1];
TCHAR szTitle[MAX_STRING_SIZE + 1];
CREDENTIAL *pOldCred = NULL;
BOOL bResult;
TCHAR *pC;
C_Dlg::OnInitDialog(hwndDlg, hwndFocus);
SetFocus (GetDlgItem ( hwndDlg, IDC_OLD_PASSWORD));
m_hDlg = hwndDlg;
// read the currently selected credential, read the cred to get the username,
// extract the domain, and set the text to show the affected domain.
bResult = CredRead(g_szTargetName,CRED_TYPE_DOMAIN_PASSWORD,0,&pOldCred);
if (bResult != TRUE)
{
LoadString ( m_hInst, IDS_PSWFAILED, szMsg, MAX_STRING_SIZE );
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
EndDialog(IDOK);
return TRUE;
}
// Get the domain and user names from the username string in the credential
// handle domain\user, domain.etc.etc\user, [email protected]
_tcsncpy(m_szFullUsername,pOldCred->UserName,UNLEN + UNLEN + 1 + 1 );
m_szFullUsername[UNLEN + UNLEN + 1] = 0;
_tcsncpy(szMsg,pOldCred->UserName,CRED_MAX_USERNAME_LENGTH); // scratch buff
szMsg[CRED_MAX_USERNAME_LENGTH] = 0;
pC = _tcschr(szMsg,((TCHAR)'\\'));
if (NULL != pC)
{
// name is format domain\something
*pC = 0;
_tcsncpy(m_szDomain,szMsg,UNLEN);
m_szDomain[UNLEN - 1] = 0;
_tcsncpy(m_szUsername, (pC + 1), UNLEN);
m_szUsername[UNLEN - 1] = 0;
}
else
{
// see if name@something
pC = _tcschr(szMsg,((TCHAR)'@'));
if (NULL == pC)
{
LoadString ( m_hInst, IDS_DOMAINFAILED, szMsg, CRED_MAX_USERNAME_LENGTH);
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
if (pOldCred) CredFree(pOldCred);
return TRUE; // don't call EndDialog()
}
*pC = 0;
_tcsncpy(m_szDomain,(pC + 1),UNLEN);
m_szDomain[UNLEN - 1] = 0;
_tcsncpy(m_szUsername, szMsg,UNLEN);
m_szUsername[UNLEN - 1] = 0;
}
if (pOldCred) CredFree(pOldCred);
if (0 != LoadString(g_hInstance,IDS_CPLABEL,szTitle,MAX_STRING_SIZE))
{
INT iLen = MAX_STRING_SIZE - _tcslen(szTitle);
if (iLen > 0)
{
// this will change your password for the domain <appendedname>
// GMBUG: this may localize inconsistently. Should use positional
// parameters.
_tcsncat(szTitle,m_szDomain,iLen);
szTitle[MAX_STRING_SIZE - 1] = 0;
}
SetDlgItemText(m_hwnd,IDC_CPLABEL,szTitle);
}
return TRUE;
} // C_ChangePasswordDlg::OnInitDialog
//////////////////////////////////////////////////////////////////////////////
//
// OnCommand
//
// Route WM_COMMAND message to appropriate handlers.
//
// parameters:
// wNotifyCode code describing action that has occured
// wSenderId id of the control sending the message, if the message
// is from a dialog
// hwndSender window handle of the window sending the message if the
// message is not from a dialog
//
// returns:
// TRUE if the message was processed completely
// FALSE if Windows is to process the message
//
//////////////////////////////////////////////////////////////////////////////
BOOL
C_ChangePasswordDlg::OnCommand(
WORD wNotifyCode,
WORD wSenderId,
HWND hwndSender
)
{
// Was the message handled?
//
BOOL fHandled = FALSE;
switch (wSenderId)
{
case IDOK:
if (BN_CLICKED == wNotifyCode)
{
OnOK( );
fHandled = TRUE;
}
break;
case IDCANCEL:
if (BN_CLICKED == wNotifyCode)
{
EndDialog(IDCANCEL);
fHandled = TRUE;
}
break;
} // switch
return fHandled;
} // C_ChangePasswordDlg::OnCommand
////////////////////////////////////////////////////////////////////////////
//
// OnOK
//
// Validate user name, synthesize computer name, and destroy dialog.
//
// parameters:
// None.
//
// returns:
// Nothing.
//
//////////////////////////////////////////////////////////////////////////////
void
C_ChangePasswordDlg::OnOK( )
{
TCHAR szMsg[CRED_MAX_USERNAME_LENGTH];
TCHAR szTitle[MAX_STRING_SIZE];
ULONG Error = 0;
BOOL bResult;
ASSERT(::IsWindow(m_hwnd));
// get old and new passwords from the dialog box
GetDlgItemText ( m_hDlg, IDC_OLD_PASSWORD, m_szOldPassword, PWLEN );
GetDlgItemText ( m_hDlg, IDC_NEW_PASSWORD, m_szNewPassword, PWLEN );
GetDlgItemText ( m_hDlg, IDC_CONFIRM_PASSWORD, m_szConfirmPassword, PWLEN );
if ( wcslen ( m_szOldPassword ) == 0 && wcslen ( m_szNewPassword ) ==0 && wcslen (m_szConfirmPassword) == 0 )
{
// must have something filled in
return;
}
else if ( wcscmp ( m_szNewPassword, m_szConfirmPassword) != 0 )
{
LoadString ( m_hInst, IDS_NEWPASSWORDNOTCONFIRMED, szMsg, CRED_MAX_USERNAME_LENGTH );
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
return; // don't call EndDialog()
}
else
{
HCURSOR hCursor, hOldCursor;
hOldCursor = NULL;
hCursor = ::LoadCursor ( m_hInst, IDC_WAIT );
if ( hCursor )
{
hOldCursor = ::SetCursor ( hCursor );
}
// let's try changing it
// The targetname is not used. Only the domain name the username, and
// old/new passwords are used
#ifdef LOUDLY
OutputDebugString(L"Changing password on the domain :");
OutputDebugString(m_szDomain);
OutputDebugString(L" for ");
OutputDebugString(m_szUsername);
OutputDebugString(L" to ");
OutputDebugString(m_szNewPassword);
OutputDebugString(L"\n");
#endif
// gm: pass full username and crack it in NetUserChangePasswordEy, so that routine can
// decide whether we are facing a Kerberos domain
Error = NetUserChangePasswordEy ( NULL, m_szFullUsername, m_szOldPassword, m_szNewPassword );
if ( hOldCursor )
::SetCursor ( hOldCursor );
}
if ( Error == NERR_Success )
{
#ifdef LOUDLY
OutputDebugString(L"Remote password set succeeded\n");
#endif
// Store the new credential in the keyring. It will overlay
// a previous version if present
// Note that the user must have knowledge of and actually type in
// the old password as well as the new password. If the user
// elects to update only the local cache, the old password
// information is not actually used.
// CredWriteDomainCredentials() is used
// m_szDomain holds the domain name
// m_szUsername holds the username
// m_szNewPassword holds the password
CREDENTIAL stCredential;
UINT cbPassword;
memcpy((void *)&stCredential,(void *)g_pExistingCred,sizeof(CREDENTIAL));
// password length does not include zero term
cbPassword = _tcslen(m_szNewPassword) * sizeof(TCHAR);
// Form the domain\username composite username
stCredential.Type = CRED_TYPE_DOMAIN_PASSWORD;
stCredential.TargetName = g_szTargetName;
stCredential.CredentialBlob = (unsigned char *)m_szNewPassword;
stCredential.CredentialBlobSize = cbPassword;
stCredential.UserName = m_szFullUsername;
stCredential.Persist = g_dwPersist;
bResult = CredWrite(&stCredential,0);
if (bResult)
{
LoadString ( m_hInst, IDS_DOMAINCHANGE, szMsg, CRED_MAX_USERNAME_LENGTH );
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
}
else
{
LoadString ( m_hInst, IDS_LOCALFAILED, szMsg, CRED_MAX_USERNAME_LENGTH );
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
}
// BUGBUG - what to do if the local update operation fails?
// This is not a very big failure, as the first prompt would
// ripple through all domain\username matching creds on the
// keyring and update them later. You're pretty much stuck
// here, since the domain probably will not let you reset the
// psw to the old value.
}
else
{
// Attempt to be specific about failure to change the psw on the
// remote system
#ifdef LOUDLY
OutputDebugString(L"Remote password set failed\n");
#endif
if (Error == ERROR_INVALID_PASSWORD)
{
LoadString ( m_hInst, IDS_CP_INVPSW, szMsg, CRED_MAX_USERNAME_LENGTH );
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
}
else if (Error == NERR_UserNotFound)
{
LoadString ( m_hInst, IDS_CP_NOUSER, szMsg, CRED_MAX_USERNAME_LENGTH );
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
}
else if (Error == NERR_PasswordTooShort)
{
LoadString ( m_hInst, IDS_CP_BADPSW, szMsg, CRED_MAX_USERNAME_LENGTH );
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
}
else if (Error == NERR_InvalidComputer)
{
LoadString ( m_hInst, IDS_CP_NOSVR, szMsg, CRED_MAX_USERNAME_LENGTH );
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
}
else if (Error == NERR_NotPrimary)
{
LoadString ( m_hInst, IDS_CP_NOTALLOWED, szMsg, CRED_MAX_USERNAME_LENGTH );
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
}
else
{
// Reaching here signifies a failure to set the remote domain
// password for more general reasons
LoadString ( m_hInst, IDS_DOMAINFAILED, szMsg, CRED_MAX_USERNAME_LENGTH );
LoadString ( m_hInst, IDS_APP_NAME, szTitle, MAX_STRING_SIZE );
MessageBox ( m_hDlg, szMsg, szTitle, MB_OK );
}
}
// clean any psw buffers, release the old cred, and go.
SecureZeroMemory(m_szOldPassword,sizeof(m_szOldPassword));
SecureZeroMemory(m_szNewPassword,sizeof(m_szNewPassword));
SecureZeroMemory(m_szConfirmPassword,sizeof(m_szConfirmPassword));
EndDialog(IDOK);
} // C_ChangePasswordDlg::OnOK
//
///// End of file: krDlg.cpp ///////////////////////////////////////////////