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.
1 lines
14 KiB
1 lines
14 KiB
// ===========================================================================
// UAMDialogs.c © 1997 Microsoft Corp. All rights reserved.
// ===========================================================================
// General dialog utilities used by the Microsoft User Authentication Method.
//
// ===========================================================================
#include <macstrsafe.h>
#include "UAMDebug.h"
#include "UAMDialogs.h"
#include "UAMUtils.h"
#include "UAMNetwork.h"
#include "UAMDLOGUtils.h"
#include "UAMKeychain.h"
#include "UAMPswdField.h"
#include "UAMPrefs.h"
#ifndef UAM_TARGET_CARBON
extern ModalFilterUPP gDialogFilter;
#endif
extern Str32 gServerName;
extern UserItemUPP gLineItem;
extern long gSupportedUAMs;
extern UAM_PREFERENCES gUAMPreferences;
SInt16 gNumPasswordEntryErrors = 0;
// ---------------------------------------------------------------------------
// ¥ UAM_ReportError()
// ---------------------------------------------------------------------------
// Reports an error to the user by displaying an alert box.
//
void UAM_ReportError(OSStatus inError)
{
UAM_StandardAlert(uamErr_ErrorMessageString, inError, NULL);
}
// ---------------------------------------------------------------------------
// ¥ UAM_StandardAlert()
// ---------------------------------------------------------------------------
// Puts up a standard alert box for reporting errors and other items to the
// user.
//
// The routine looks for resources of type 'STR ' to get the strings
// associated with the message and explanations.
//
void UAM_StandardAlert(SInt16 inMessageID, SInt32 inExplanation, SInt16* outSelectedItem)
{
StringHandle theMessage = NULL;
StringHandle theExplanation = NULL;
SInt16 theSelectedItem;
#ifdef UAM_TARGET_CARBON
AlertStdAlertParamRec theAlertRec;
SysBeep(1);
theAlertRec.movable = TRUE;
theAlertRec.helpButton = FALSE;
theAlertRec.filterProc = NULL;
theAlertRec.defaultText = (UInt8*)kAlertDefaultOKText;
theAlertRec.cancelText = NULL;
theAlertRec.otherText = NULL;
theAlertRec.defaultButton = kAlertStdAlertOKButton;
theAlertRec.position = kWindowAlertPositionMainScreen;
//
//If the caller is looking for the button the user selected, then we
//assume that the user wants a cancel button.
//
if (outSelectedItem != NULL)
{
theAlertRec.cancelButton = kAlertStdAlertCancelButton;
}
else
{
theAlertRec.cancelButton = 0;
}
#endif //UAM_TARGET_CARBON
InitCursor();
if (outSelectedItem != NULL)
{
*outSelectedItem = 0;
}
theMessage = GetString(inMessageID);
if (theMessage != NULL)
{
HLock((Handle)theMessage);
theExplanation = GetString(inExplanation);
if (theExplanation == NULL)
{
//
//We didn't find an error string corresponding to this error, so
//put up a general error message.
//
theExplanation = GetString(uamErr_DefaultExplanation);
}
if (theExplanation != NULL)
{
HLock((Handle)theExplanation);
#ifdef UAM_TARGET_CARBON
StandardAlert(
kAlertStopAlert,
*theMessage,
*theExplanation,
&theAlertRec,
&theSelectedItem
);
#else
ParamText(NULL, NULL, *theMessage, *theExplanation);
theSelectedItem = StopAlert((outSelectedItem == NULL) ? ALRT_Error : ALRT_Error2, NULL);
#endif
if (outSelectedItem != NULL)
{
*outSelectedItem = theSelectedItem;
}
HUnlock((Handle)theExplanation);
ReleaseResource((Handle)theExplanation);
}
HUnlock((Handle)theMessage);
ReleaseResource((Handle)theMessage);
}
}
// ---------------------------------------------------------------------------
// ¥ UAM_ChangePwdDialogFilter()
// ---------------------------------------------------------------------------
// Dialog filter for the change password dialog.
//
pascal Boolean UAM_ChangePwdDialogFilter(DialogRef inDialog, EventRecord *inEvent, SInt16 *inItem)
{
Boolean theResult = FALSE;
SInt16 theCode;
if ((inEvent->what == keyDown) || (inEvent->what == autoKey))
{
theCode = (inEvent->message & charCodeMask);
if ((inEvent->modifiers & cmdKey) && (inEvent->what != autoKey))
{
switch(theCode)
{
//
//Don't allow users to cut/copy or paste their passwords.
//
case 'c':
case 'C':
case 'v':
case 'V':
case 'x':
case 'X':
theResult = TRUE;
break;
default:
break;
}
}
else if ((inEvent->modifiers & optionKey) || (inEvent->modifiers & controlKey))
{
//
//We do not allow the use of extended or control characters. This is because
//there is no way to map them over to the windows code page.
//
//
//If the user tried to use extended chars more than once, we
//put up a dialog telling them they are not allowed.
//
gNumPasswordEntryErrors++;
if (gNumPasswordEntryErrors >= MAX_PASSWORD_ENTRY_ERRORS)
{
UAM_StandardAlert(
uamErr_PasswordMessage,
uamErr_ExtendedCharsNotAllowed,
NULL
);
gNumPasswordEntryErrors = 0;
}
else {
SysBeep(1);
}
theResult = TRUE;
}
else
{
switch(theCode)
{
case UAMKey_Escape:
*inItem = DITEM_Cancel;
theResult = TRUE;
break;
case UAMKey_Enter:
case UAMKey_Return:
*inItem = DITEM_OK;
theResult = TRUE;
break;
default:
break;
}
}
}
#ifdef UAM_TARGET_CARBON
if (theResult == FALSE)
{
theResult = StdFilterProc(inDialog , inEvent, inItem);
}
#endif
return(theResult);
}
// ---------------------------------------------------------------------------
// ¥ UAM_ChangePwd()
// ---------------------------------------------------------------------------
// Puts up and handles the change password dialog and calls the appropriate
// routines to change the password.
//
// Unless there is an error, we'll usually return one of:
//
// #define CHNGPSWD_UPDATE_KEYCHAIN 1000
// #define CHNGPSWD_USER_CANCELED 1001
// #define CHNGPSWD_NOERR noErr
#define DITEM_Icon 3
#define DITEM_OldPassword 6
#define DITEM_NewPassword 8
#define DITEM_VerifyPwd 10
#define DITEM_LineItem 11
OSStatus UAM_ChangePwd(UAMArgs *inUAMArgs)
{
GrafPtr theSavePort;
short theItem;
Str255 theNewPwd, theVerPwd;
CursHandle theCursor;
OSStatus theError = noErr;
DialogRef theDialog = NULL;
Boolean theDoLoop = true;
KCItemRef theKCItemRef = NULL;
ModalFilterUPP theFilter = NULL;
Assert_(gLineItem != NULL);
theFilter = NewModalFilterUPP(&UAM_ChangePwdDialogFilter);
if (theFilter == NULL)
{
//
//Bad problems if we couldn't allocate a little ol upp!
//
return(-108);
}
GetPort(&theSavePort);
ParamText(inUAMArgs->Opt.pwDlg.userName, gServerName, NULL, NULL);
#ifdef UAM_TARGET_CARBON
theDialog = GetNewDialog(DLOG_ChangePwd, NULL, (WindowPtr)-1);
#else
theDialog = UAM_NewDialog(DLOG_ChangePwd, true);
#endif
if (theDialog == NULL)
{
UAM_ReportError(resNotFound);
return(resNotFound);
}
//
//Set up the line at the top of the dialog.
//
UAM_SetupDialogUserItem(theDialog, DITEM_LineItem, gLineItem, userItem);
//
//Initialize the 3 password edit fields.
//
UAM_InitializeDialogPasswordItem(theDialog, DITEM_OldPassword);
UAM_InitializeDialogPasswordItem(theDialog, DITEM_NewPassword);
UAM_InitializeDialogPasswordItem(theDialog, DITEM_VerifyPwd);
if (inUAMArgs->Opt.pwDlg.password[0] != 0)
{
UAM_SetPasswordText(
theDialog,
DITEM_OldPassword,
inUAMArgs->Opt.pwDlg.password );
UAM_MakePasswordItemFocusItem(theDialog, DITEM_NewPassword);
}
else {
UAM_MakePasswordItemFocusItem(theDialog, DITEM_OldPassword);
}
#ifdef UAM_TARGET_CARBON
SetPortDialogPort(theDialog);
ShowWindow(GetDialogWindow(theDialog));
BringToFront(GetDialogWindow(theDialog));
#else
UAM_SetCustomFilterProc(theDialog, theFilter);
#endif
//
//Tell the password key filter the maximum password length to allow.
//
UAM_SetMaximumPasswordLength(true);
do
{
ModalDialog(
#ifdef UAM_TARGET_CARBON
theFilter,
#else
gDialogFilter,
#endif
&theItem);
switch(theItem)
{
case 1:
UAM_GetPasswordText(theDialog, DITEM_NewPassword, theNewPwd);
UAM_GetPasswordText(theDialog, DITEM_VerifyPwd, theVerPwd);
UAM_GetPasswordText(theDialog, DITEM_OldPassword, inUAMArgs->Opt.pwDlg.password);
//
//Ensure the new and verified password are equal. If not, present an
//error to the user and give 'em a chance to correct the problem.
//
if (!EqualString(theNewPwd, theVerPwd, true, true))
{
UAM_ReportError(afpNTNewPasswordMismatchErr);
UAM_SetPasswordText(theDialog, DITEM_NewPassword, "\p");
UAM_SetPasswordText(theDialog, DITEM_VerifyPwd, "\p");
UAM_MakePasswordItemFocusItem(theDialog, DITEM_NewPassword);
break;
}
//
//Let the user know they may wait a while for the operation to
//complete.
//
theCursor = GetCursor(watchCursor);
if (theCursor) {
SetCursor(*theCursor);
}
//
//Make sure the user is not trying to enter in a blank or null
//password for the old or new password.
//
if ((PSTR_LENGTH(inUAMArgs->Opt.auth.password) == 0) || (PSTR_LENGTH(theNewPwd) == 0))
{
UAM_StandardAlert(
uamErr_PasswordMessage,
uamErr_NoBlankPasswordsAllowed,
NULL
);
break;
}
//
//Determine which change password method we're using. We use v1 for
//NT4.0 and older servers and v2 for Windows2000 and v3 for .NET.
//
if (gSupportedUAMs & kMSUAM_V3_Supported)
{
DbgPrint_((DBGBUFF, "CHANGE PSWD: using UAM_ChangePasswordV3()"));
theError = UAM_ChangePasswordForMS30(inUAMArgs, theNewPwd);
}
else if (gSupportedUAMs & kMSUAM_V2_Supported)
{
DbgPrint_((DBGBUFF, "CHANGE PSWD: using UAM_ChangePasswordV2()"));
theError = UAM_ChangePasswordForMS20(inUAMArgs, theNewPwd);
}
else
{
//
//Check and see if the user wants to allow this weak authentication
//to take place.
//
if (gUAMPreferences.flags & UAM_PREFS_REQUIRE_STRONG_ENCRYPTION)
{
//
//Nope, the auth strength is too weak for the user to
//stomach. Exit gracefully.
//
UAM_StandardAlert(
uamErr_AuthenticationMessage,
uamErr_AuthTooWeak,
NULL
);
return(userCanceledErr);
}
DbgPrint_((DBGBUFF, "CHANGE PSWD: using UAM_ChangePasswordV1()"));
theError = UAM_ChangePasswordForMS10(inUAMArgs, theNewPwd);
}
if (theError == noErr)
{
if (UAM_KCAvailable())
{
//
//See if a keychain existed for the user name.
//If so, delete it.
//
if (UAM_KCFindAppleSharePassword(
inUAMArgs->Opt.pwDlg.userName,
inUAMArgs->Opt.pwDlg.password,
gServerName,
&theKCItemRef) == noErr)
{
theError = KCDeleteItem(theKCItemRef);
if ((theError != noErr) && (theError != userCanceledErr))
{
DbgPrint_((DBGBUFF, "KCDeleteItem() failed (%d)", (int)theError));
UAM_ReportError(theError);
}
else if (theError == noErr)
{
//
//This is how we tell the main login routine to
//re-enter the password into the keychain.
//
theError = CHNGPSWD_UPDATE_KEYCHAIN;
}
KCReleaseItem(&theKCItemRef);
}
}
//
//If we changed the password successfully, then store the
//new password in the arguments struct.
//
UAM_PStrCopy(theNewPwd, inUAMArgs->Opt.pwDlg.password);
}
theDoLoop = false;
break;
case 2:
theError = CHNGPSWD_USER_CANCELED;
theDoLoop = false;
break;
default:
break;
}
}while(theDoLoop);
DisposeDialog(theDialog);
SetPort(theSavePort);
DisposeRoutineDescriptor(theFilter);
//
//Reset the maximum password length for non-password changing ops.
//
UAM_SetMaximumPasswordLength(false);
return(theError);
}
// ---------------------------------------------------------------------------
// ¥ UAM_ChangePasswordNotificationDlg()
// ---------------------------------------------------------------------------
// Put up an about dialog.
void UAM_ChangePasswordNotificationDlg(Int16 inDaysTillExpiration)
{
Str255 theDaysStr;
NumToString(inDaysTillExpiration, theDaysStr);
ParamText(theDaysStr, NULL, NULL, NULL);
UAM_StandardAlert(uamErr_PasswordExpirationMessage, uamErr_PasswordExpirationExplanation, NULL);
}
|