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
27 KiB
1 lines
27 KiB
// ===========================================================================
// UAMMain.cp © 1997-2001 Microsoft Corp. All rights reserved.
// ===========================================================================
// Main unit for Microsoft User Authentication Method.
//
// Notes:
// --------------------------------------------------------------------------
//
// Version History:
// ===========================================================================
// Version 5.0.8:
// 04.26.01 MJC - Code cleanup. Combined UAMNetwork and UAMDSNetwork into
// one file (UAMNetwork.c & UAMNetwork.h)
// - UAM_ChangePasswordV2(): Now check for zero length old
// and new passwords before upper casing.
// - Now use common LM hash code for login and changepassword v2.
// - Zero password buffers when done with them (security fix).
// - Now clear password field when login error occurs.
// 05.01.01 - Fixed bug where over-long user names could be pasted
// into username field.
// - Can now tab out of user name field when name is max length.
// - Now clear password when failure occurs in UAM_LoginMSUAM().
// 07.02.01 - Fixed bug where password was being cleared in UAM_LoginContinue()
// before I saved it to the keychain.
// 10.18.01 - Completed MacOS X v1.0 UAM.
// - Support added for NTLMv2 auth and change password.
// Version 1.0.1:
// 01.21.02 - Fix: Keychain passwords couldn't exceed 8 bytes.
// - Fix: Close session after attempted login w/bad password.
// - Fix: Now conform to Apple's Aqua UI guidelines.
// - Now check buffer length for all string copies.
// Version 1.0.2:
// 02.18.02 - User can now choose to allow only strong authentication.
// - Added preference file support for above change.
// - Finally moved OSX builds to CodeWarrior!
// 03.01.02 - Many changes for security push
//
// Version 1.0.3:
// 05.31.02 - Fixed bug where we weren't dealing with all the new
// AFP URL type (eg. afp://username:password@server/share).
// ===========================================================================
#include "UAMMain.h"
#include "UAMDebug.h"
#include "UAMUtils.h"
#include "UAMDialogs.h"
#include "UAMNetwork.h"
#include "UAMDLOGUtils.h"
#include "UAMKeychain.h"
#include "UAMPswdField.h"
#include "UAMPrefs.h"
//
//Global variables are declared here
//
Str32 gServerName;
Str64 gUserName;
Boolean gContextInited;
Boolean gGuestLogon;
Boolean gSupportsChngPwd;
DialogPtr gDialog;
Str32 gAFPVersion;
long gSupportedUAMs;
ModalFilterUPP gPwdDialogFilter;
UserItemUPP gLineItem;
Str32 gUAMVersionString;
Str32 gZoneName;
UInt32 gExpirationTime = 0;
struct sockaddr* gServerAddress = NULL;
EventCallbackPtr gEventCallbackUPP = NULL;
Boolean gTriedKeychain = false;
extern UAM_PREFERENCES gUAMPreferences;
#pragma export on
// ---------------------------------------------------------------------------
// ¥ main()
// ---------------------------------------------------------------------------
// This is the main entry point for our UAM. This function is passed a
// pointer to a UAMArgs struct. This struct contains the function selector,
// call-backs, and many other things we need to do our stuff.
EXTERN_API( OSStatus ) UAMMain(UAMArgs *inUAMArgs)
{
OSStatus theResult = noErr;
switch(inUAMArgs->command)
{
case kUAMOpen:
theResult = MS_UAMOpen(inUAMArgs);
break;
case kUAMClose:
MS_UAMClose();
break;
case kUAMPWDlog:
theResult = MS_UAMPwdDialog(inUAMArgs);
break;
case kUAMLogin:
theResult = UAM_UAMLogin(inUAMArgs);
break;
case kUAMVSDlog:
break;
case kUAMChgPass:
case kUAMChgPassDlg:
DbgPrint_((DBGBUFF, "Change password dialog must be implemented"));
theResult = kNotForUs;
break;
default:
//
//If we get here then we were asked to handle a routine that
//we don't support. Return the appropriate error code.
//
DbgPrint_((DBGBUFF, "Unsupported function selector in MSUAM main() (%d)", inUAMArgs->command));
theResult = kNotForUs;
break;
}
return(theResult);
}
#pragma export off
// ---------------------------------------------------------------------------
// ¥ MS_UAMOpen()
// ---------------------------------------------------------------------------
// This is called by the device package. It is not a required function but
// we use it to initialize our UAM code. Note that when we encounter an
// error we don't make an effort to clean up. Instead we return userCanceledErr
// in which case our UAMClose function will be called by AppleShare Client.
OSStatus MS_UAMOpen(UAMArgs *inUAMArgs)
{
short theUAMConfig = 0;
DbgPrint_((DBGBUFF, "MS_UAMOpen() enter..."));
//
//Get the name of the server we want to log into.
//
UAM_PStrCopy(inUAMArgs->Opt.open.objectName, gServerName, sizeof(gServerName));
//
//Copy the zone name for. If it's NULL, then we
//don't have a zone name.
//
if (inUAMArgs->Opt.open.zoneName != NULL)
{
//
//01.16.02: Pass maximum length to string copy routine.
//
UAM_PStrCopy(inUAMArgs->Opt.open.zoneName, gZoneName, sizeof(gZoneName));
}
else
{
DbgPrint_((DBGBUFF, "No AppleTalk zone name passed to UAM"));
gZoneName[0] = 0;
}
gContextInited = false; //Been through PwdDialog before?
gGuestLogon = false; //Is guest our logon choice?
gDialog = NULL; //So we can see if we really got it.
gPwdDialogFilter = NULL;
gLineItem = NULL;
gAFPVersion[0] = 0;
gUserName[0] = 0;
gServerAddress = inUAMArgs->Opt.open.srvrAddress;
gEventCallbackUPP = inUAMArgs->callbacks->EventCallbackUPP;
gTriedKeychain = false;
//
//Get the MSUAM preferences from the prefs file.
//
ZeroMemory(&gUAMPreferences, sizeof(UAM_PREFERENCES));
UAM_RetrieveUAMPreferenceData(&gUAMPreferences);
UAM_KCInitialize(inUAMArgs);
gPwdDialogFilter = NewModalFilterUPP((ModalFilterUPP)MS_PwdDialogFilter);
gLineItem = NewUserItemUPP((UserItemUPP)UAM_FrameDialogItem);
//
//Get the AFP version and the default user name. This function finds
//a match which is the highest AFP version supported by both the client
//and server.
//
UAM_GetAFPVersionString(
inUAMArgs->Opt.open.srvrInfo,
inUAMArgs->callbacks,
gAFPVersion,
gUserName );
//
//gUserName can be null, we just capture here during debugging to
//ensure we're getting the name properly.
//
Assert_(PSTR_LENGTH(gUserName) != 0);
Assert_(PSTR_LENGTH(gAFPVersion) != 0);
if (PSTR_LENGTH(gAFPVersion) == 0)
{
//
//No AFPVersion, no logon...
//
UAM_ReportError(uamErr_NoAFPVersion);
return(userCanceledErr);
}
gSupportsChngPwd = ((inUAMArgs->Opt.open.srvrInfo->fFlags & kSupportsChngPswd) != 0);
//
//Get the list of supported UAMs from a utility routine. This data
//is necessary in the password dialog code.
//
UAM_GetSupportedUAMS(
inUAMArgs,
gAFPVersion,
&gSupportedUAMs
);
//
//We should never get here if the following is false, but we
//check just to be on the safe side.
//
if ( ((gSupportedUAMs & kMSUAMSupported) == 0) &&
((gSupportedUAMs & kMSUAM_V2_Supported) == 0) )
{
Assert_(0);
UAM_ReportError(afpBadUAM);
return(userCanceledErr);
}
UAM_VersionString(gUAMVersionString);
//
//Set the maximum allowed password length. This may be changed and reset
//later by the change password UI.
//
UAM_SetMaximumPasswordLength(false);
//
//This is how we tell AppleShare what our UAM supports. We have
//our own password dialog, we support change password, and we
//use our own change password dialog.
//
theUAMConfig |= BIT_0; //Custom login dialog
theUAMConfig |= BIT_2; //We support change password
theUAMConfig |= BIT_3; //Custom change password dialog
inUAMArgs->result = theUAMConfig;
return(noErr);
}
// ---------------------------------------------------------------------------
// ¥ MS_UAMClose()
// ---------------------------------------------------------------------------
// Like UAMOpen, UAMClose has no specific purpose as defined by the device
// manager. We use it to clean up our allocated storage and globals.
void MS_UAMClose(void)
{
DbgPrint_((DBGBUFF, "MS_UAMClose() enter..."));
//
//Release memory allocated for the password edit stuff.
//
UAM_CleanupPasswordFieldItems();
if (gDialog != NULL)
{
//
//If we put up our login dialog, get rid of it.
//
DisposeDialog(gDialog);
}
if (gPwdDialogFilter) DisposeRoutineDescriptor(gPwdDialogFilter);
if (gLineItem) DisposeRoutineDescriptor(gLineItem);
}
// ---------------------------------------------------------------------------
// ¥ MS_TestTextEntryLength()
// ---------------------------------------------------------------------------
// We don't allow entries in the login dialog to be of any length. This
// function tests the length of the entered text in an edit field. It will
// modify the event record appropriately to inhibit processing of the
// keystroke if it will take the field over the limit.
Boolean MS_TestTextEntryLength(
DialogPtr inDialog,
EventRecord* inEvent,
short inItem,
short inMaxLengthAllowed
)
{
Str255 theString;
Boolean theResult = false;
if (GetDialogKeyboardFocusItem(inDialog) == inItem)
{
UAM_GetDialogEditText(inDialog, inItem, theString);
if (PSTR_LENGTH(theString) >= inMaxLengthAllowed)
{
SysBeep(1);
inEvent->what = nullEvent;
inEvent->message = 0;
theResult = true;
//
//If the string length is currently too long, then
//we have to chop off the end of the string to the
//proper length.
//
if (PSTR_LENGTH(theString) > inMaxLengthAllowed)
{
//
//Easy way out, pascal style strings have length
//byte in front. Just adjust it.
//
theString[0] = inMaxLengthAllowed;
//
//Now set the text in the edit field with the new string.
//
UAM_SetDialogEditText(inDialog, inItem, theString);
}
}
}
return(theResult);
}
// ---------------------------------------------------------------------------
// ¥ MS_PwdDialogFilter()
// ---------------------------------------------------------------------------
// Filter function for the password dialog. We have this so we can capture
// command keys and keep length requirements for the user name in the login
// dialog.
pascal Boolean MS_PwdDialogFilter(DialogRef inDialog, EventRecord *inEvent, short *inItem)
{
short theCode;
Str255 theString;
Boolean theResult = false;
SInt16 theMaxUserNameLength;
//
//For MS2.0 and 3.0 we allow 64 character passwords. 32 characters
//for Microsoft V1.0.
//
theMaxUserNameLength = (gSupportedUAMs & (kMSUAM_V2_Supported | kMSUAM_V3_Supported)) ?
UAM_USERNAMELEN_V3 : UAM_USERNAMELEN;
if ((inEvent->what == keyDown) || (inEvent->what == autoKey))
{
theCode = (inEvent->message & charCodeMask);
//
//04.30.01: Don't allow cmd selections when autoKey'ing.
//
if ((inEvent->modifiers & cmdKey) && (inEvent->what != autoKey))
{
switch(theCode)
{
case 'g':
case 'G':
*inItem = DITEM_GuestRadio;
theResult = true;
break;
case 'r':
case 'R':
*inItem = DITEM_RegRadio;
theResult = true;
break;
case 's':
case 'S':
*inItem = DITEM_ChangePwd;
theResult = true;
break;
case 'a':
case 'A':
*inItem = DITEM_Keychain;
theResult = true;
break;
//
//Handle edit commands from the user. We don't allow any
//editing commands in the password field. This mimicks
//Apple's own UAM's.
//
case 'c':
case 'C':
case 'v':
case 'V':
case 'x':
case 'X':
theResult = true;
break;
default:
break;
}
}
else
{
//
//Don't allow more than UAM_USERNAMELEN maximum characters in edit field.
//
if (GetDialogKeyboardFocusItem(inDialog) == DITEM_UserName)
{
UAM_GetDialogEditText(inDialog, DITEM_UserName, theString);
switch(theCode)
{
case UAMKey_BackDel:
case UAMKey_Left:
case UAMKey_Right:
case UAMKey_Return:
case UAMKey_Enter:
case UAMKey_Escape:
case UAMKey_Tab:
break;
default:
if (PSTR_LENGTH(theString) >= theMaxUserNameLength)
{
SysBeep(1);
inEvent->what = nullEvent;
theResult = true;
}
break;
}
}
}
}
else
{
if (gEventCallbackUPP)
{
//
//If we're not handling the event ourselves, then call the
//event callback which gives AS and the Chooser a chance
//to update it's windows, etc.
//
#ifndef UAM_TARGET_CARBON
CallUniversalProc(gEventCallbackUPP, kEventCallbackProcInfo, inEvent);
#else
gEventCallbackUPP(inEvent);
#endif
}
}
if (theResult == FALSE)
{
theResult = StdFilterProc(inDialog , inEvent, inItem);
}
return(theResult);
}
// ---------------------------------------------------------------------------
// ¥ MS_UAMPwdDialog()
// ---------------------------------------------------------------------------
// This is where we put up our password dialog. The buffers pointed to by
// 'inUserName' and 'inPassword' end up getting passed directly to the
// UAMLogin function.
//
// The buffer passed for the user name and password is 64 bytes long. Don't
// use more than that!
OSStatus MS_UAMPwdDialog(UAMArgs *inUAMArgs)
{
short theItem, x;
Str255 theStr;
OSStatus theError = noErr;
Boolean theLoop = true;
DbgPrint_((DBGBUFF, "MS_UAMPwdDialog() enter..."));
Assert_(gPwdDialogFilter != NULL);
Assert_(gLineItem != NULL);
//
//Determine which user name to use, the default or the
//one supplied by the client (if any). gUserName is filled
//in originally during the UAMOpen call.
//
if (PSTR_LENGTH(inUAMArgs->Opt.pwDlg.userName) != 0)
{
//
//01.16.02: Pass maximum length to string copy routine.
//
UAM_PStrCopy(inUAMArgs->Opt.pwDlg.userName, gUserName, sizeof(gUserName));
}
//
//If we already tried the keychain and failed, we don't want
//to try again or we'll loop forever. Give the user a chance
//to enter the correct name and password.
//
//NOTE: We check to see if the cmd key is down, if it is, then
//we bypass the keychain stuff alltogether. Maybe the user wants
//to change his password!?!?!
//
if ((gTriedKeychain == false) && (UAM_KCAvailable()) && (!UAM_KeyDown(KEY_Command)))
{
gTriedKeychain = true;
if ( (PSTR_LENGTH(inUAMArgs->Opt.pwDlg.userName) != 0) &&
(strlen((char*)inUAMArgs->Opt.pwDlg.password) != 0) )
{
//
//We were supplied a username and password by the AFP
//client. This means the user clicked a keychain entry.
//
goto exit;
}
else
{
DbgPrint_((DBGBUFF, "Checking keychain for stored credentials..."));
theError = UAM_KCFindAppleSharePassword(
gUserName,
inUAMArgs->Opt.pwDlg.password,
gServerName,
NULL
);
if (theError == noErr)
{
DbgPrint_((DBGBUFF, "Credentials found in the keychain!"));
//
//Fill in the user name for the UAMArgs.
//
if (PSTR_LENGTH(inUAMArgs->Opt.pwDlg.userName) == 0)
{
UAM_PStrCopy(gUserName, inUAMArgs->Opt.pwDlg.userName);
}
//
//The password must always passed back in UAMArgs as a C string.
//
_p2cstr(inUAMArgs->Opt.pwDlg.password);
//
//A password was found so try to logon.
//
goto exit;
}
else if ( (theError != errKCItemNotFound) &&
(theError != userCanceledErr) )
{
//
//Only report "real" errors.
//
UAM_ReportError(theError);
}
else
{
DbgPrint_((DBGBUFF, "No credentials found in the keychain!"));
}
}
}
else if ((UAM_KCAvailable()) && (UAM_KeyDown(KEY_Command)))
{
//
//If the user is holding the cmd key down, then we don't want to
//try the keychain the next time through either.
//
gTriedKeychain = true;
}
//
//Display the server name in the dialog title text
//which is located at the top of the dialog. This must be
//done even if we've been here before.
//
ParamText(gServerName, NULL, NULL, NULL);
//
//If we haven't been through here before, then we need to do
//all the prep work.
//
if (!gContextInited)
{
gDialog = GetNewDialog(DLOG_Login, NULL, (WindowPtr)-1);
if (gDialog == NULL)
{
DbgPrint_((DBGBUFF, "Failed to get logon dialog resource!"));
//
//If we couldn't get the dialog, then we're either out
//of memory or the resource couldn't be found.
//
theError = MemError();
if (theError == noErr)
theError = ResError();
if (theError == noErr)
theError = resNotFound;
UAM_ReportError(theError);
return(userCanceledErr);
}
//
//Setup our custom user item that displays the divider line at the
//top of the dialog window.
//
UAM_SetupDialogUserItem(gDialog, DITEM_Line, gLineItem, userItem);
//
//Set up the default user name and password (if any). If a user name
//exists, then make the password field the active field ready for input.
//
//
//If we've not been here before, then we want to use the user name
//entered in the Sharing Setup Control Panel (or Chooser).
//
if (PSTR_LENGTH(gUserName) != 0)
{
UAM_SetDialogEditText(gDialog, DITEM_UserName, gUserName);
UAM_MakeEditItemFocus(gDialog, DITEM_UserName);
}
else
{
UAM_HiliteDialogControlItem(gDialog, 1, 255);
}
//
//Initialize the password edit control so it behaves properly.
//
UAM_InitializeDialogPasswordItem(gDialog, DITEM_Password);
//
//Now we set up the guest and registered user radio buttons and the
//change password button as determined by UAM_GetServerInfo().
//
if (!gSupportsChngPwd)
{
//
//Change password is not supported by the server for this user. We
//gray out the button to make it unselectable.
//
UAM_HiliteDialogControlItem(gDialog, DITEM_ChangePwd, 255);
}
if (!(gSupportedUAMs & kGuestSupported))
{
//
//No guest support, we don't need the guest radio button.
//
UAM_HiliteDialogControlItem(gDialog, DITEM_GuestRadio, 255);
}
//
//Set the initial radio for the default/current login method.
//
if (gGuestLogon)
{
UAM_SetDialogControlValue(gDialog, DITEM_GuestRadio, 1);
UAM_SetDialogControlValue(gDialog, DITEM_RegRadio, 0);
UAM_HiliteDialogControlItem(gDialog, DITEM_ChangePwd, 255);
for (x = DITEM_FirstHideItem; x <= DITEM_LastHideItem; x++) {
HideDialogItem(gDialog, x);
}
UAM_HiliteDialogControlItem(gDialog, 1, 0);
}
else {
UAM_SetDialogControlValue(gDialog, DITEM_RegRadio, 1);
}
//
//If the client is not allowed to save password for this server,
//then we gray out the keychain checkbox.
//
if (UAM_KCAvailable() == false)
{
UAM_HiliteDialogControlItem(gDialog, DITEM_Keychain, 255);
}
else if (gTriedKeychain)
{
UAM_SetPasswordText(gDialog, DITEM_Password, "\p");
UAM_MakePasswordItemFocusItem(gDialog, DITEM_Password);
}
//
//Set the encryption type checkbox to the proper value.
//
if (gUAMPreferences.flags & UAM_PREFS_REQUIRE_STRONG_ENCRYPTION)
{
UAM_SetDialogControlValue(gDialog, DITEM_StrongEncryption, 1);
}
SetDialogDefaultItem(gDialog, DITEM_OK);
SetDialogCancelItem(gDialog, DITEM_Cancel);
//
//This flag lets up know that we've initialized our login dialog
//and that we don't need to do it again when/if we come here again.
//
gContextInited = true;
SetPortDialogPort(gDialog);
ShowWindow(GetDialogWindow(gDialog));
}
else
{
UAM_SetDialogEditText(gDialog, DITEM_UserName, gUserName);
UAM_SetPasswordText(gDialog, DITEM_Password, "\p");
//
//Hilite the password selection.
//
UAM_MakePasswordItemFocusItem(gDialog, DITEM_Password);
}
do
{
ModalDialog(gPwdDialogFilter, &theItem);
switch(theItem)
{
case DITEM_OK:
gGuestLogon = (UAM_GetDialogControlValue(gDialog, DITEM_GuestRadio) != 0);
theError = noErr;
theLoop = false;
if (gGuestLogon)
{
inUAMArgs->Opt.pwDlg.userName[0] = 0;
inUAMArgs->Opt.pwDlg.password[0] = 0;
}
else
{
UAM_GetPasswordText( gDialog,
DITEM_Password,
inUAMArgs->Opt.pwDlg.password );
UAM_GetDialogEditText( gDialog,
DITEM_UserName,
inUAMArgs->Opt.pwDlg.userName );
//
//Don't allow blank passwords for 2 reasons:
//
// 1. It is not secure and user can use Apple UAM for this.
// 2. This covers a security hole that is generated after changing
// passwords on these servers using Apple's clear text UAM.
//
if (PSTR_LENGTH(inUAMArgs->Opt.pwDlg.password) == 0)
{
UAM_StandardAlert(
uamErr_PasswordMessage,
uamErr_NoBlankPasswordsAllowed,
NULL
);
//
//Continue the login dialog loop so the user can make changes.
//
theLoop = true;
}
//
//The password must always be in C style string form.
//
_p2cstr(inUAMArgs->Opt.pwDlg.password);
}
//
//Only save the preferences if the user hits "Connect".
//
UAM_SaveUAMPreferenceData(&gUAMPreferences);
break;
case DITEM_Cancel:
//
//VERSION 5.0: To force cancellation, we pass userCanceledError(-128)
//back to the Chooser. The old UAM would pass back dsForcedQuit which
//is the wrong value. This would cause an error dialog when cancelling.
//
DbgPrint_((DBGBUFF, "Cancel selected in login dialog."));
theError = userCanceledError;
theLoop = false;
break;
case DITEM_GuestRadio:
//
//Set up the controls in the dialog for guest login. We don't
//need the user name and password items, so hide them from
//the user. We must explicitly enable the 'OK' button since
//it may have been disabled by the gate stuff.
//
if (UAM_IsDialogControlActive(gDialog, DITEM_GuestRadio))
{
UAM_SetDialogControlValue(gDialog, DITEM_GuestRadio, 1);
UAM_SetDialogControlValue(gDialog, DITEM_RegRadio, 0);
for (x = DITEM_FirstHideItem; x <= DITEM_LastHideItem; x++) {
HideDialogItem(gDialog, x);
}
}
break;
case DITEM_RegRadio:
//
//Now we need all the items back that were hidden above, make
//them visible.
//
if (UAM_GetDialogControlValue(gDialog, DITEM_RegRadio) <= 0)
{
UAM_SetDialogControlValue(gDialog, DITEM_GuestRadio, 0);
UAM_SetDialogControlValue(gDialog, DITEM_RegRadio, 1);
for (x = DITEM_FirstHideItem; x <= DITEM_LastHideItem; x++) {
ShowDialogItem(gDialog, x);
}
UAM_GetDialogEditText(gDialog, DITEM_UserName, theStr);
UAM_MakeEditItemFocus(gDialog, DITEM_UserName);
if ((gSupportsChngPwd) && (theStr[0] != 0)) {
UAM_HiliteDialogControlItem(gDialog, DITEM_ChangePwd, 0);
}
}
break;
case DITEM_ChangePwd:
UAM_GetPasswordText( gDialog,
DITEM_Password,
inUAMArgs->Opt.pwDlg.password );
UAM_GetDialogEditText( gDialog,
DITEM_UserName,
inUAMArgs->Opt.pwDlg.userName );
theError = UAM_ChangePwd(inUAMArgs);
switch(theError)
{
case CHNGPSWD_USER_CANCELED:
break;
case CHNGPSWD_UPDATE_KEYCHAIN:
//
//We need to re-add the keychain item with the
//correct password. Flag it by checking the box.
//
UAM_SetDialogControlValue(gDialog, DITEM_Keychain, 1);
//
//Just fall on through and handle the normal case.
//
case CHNGPSWD_NOERR:
//
//Set the password field and buffer with the new password in case
//we end back here later.
//
UAM_SetPasswordText(gDialog, DITEM_Password, inUAMArgs->Opt.pwDlg.password);
//
//The password must always be in C style string form.
//
_p2cstr(inUAMArgs->Opt.pwDlg.password);
theError = noErr;
theLoop = false;
break;
default:
UAM_ReportError(theError);
//
//Make sure in debug that the password field is cleared in
//an error condition.
//
Assert_(PSTR_LENGTH(inUAMArgs->Opt.pwDlg.password) == 0);
//
//We do this here so we clear the password field like we should
//do whenever there is a failure.
//
UAM_SetPasswordText(gDialog, DITEM_Password, "\p");
//
//Because we use ParamText() we must manually force an update
//of the dialog or things won't redraw properly.
//
#ifndef UAM_TARGET_CARBON
InvalRect(&gDialog->portRect);
#endif
break;
}
//
//Must reset our user's name since UAM_ChangePwd() uses ParamText()
//to set some strings of it's own.
//
ParamText(gServerName, NULL, NULL, NULL);
break;
case DITEM_Keychain:
UAM_ToggleDialogControl(gDialog, DITEM_Keychain);
break;
case DITEM_StrongEncryption:
//
//Update the required encryption dynamically.
//
UAM_ToggleDialogControl(gDialog, DITEM_StrongEncryption);
if (UAM_GetDialogControlValue(gDialog, DITEM_StrongEncryption) > 0)
{
gUAMPreferences.flags |= UAM_PREFS_REQUIRE_STRONG_ENCRYPTION;
}
else
{
gUAMPreferences.flags &= ~UAM_PREFS_REQUIRE_STRONG_ENCRYPTION;
UAM_StandardAlert(
uamErr_WARNINGMessage,
uamErr_UsingWeakAuthentication,
NULL
);
}
break;
default:
break;
}
}while(theLoop);
exit:
DbgPrint_((DBGBUFF, "Exit MS_UAMPwdDialog() return code = %d", (int)theError));
return(theError);
}
|