// ===========================================================================
//	UAMNetwork.c 				© 1997 Microsoft Corp. All rights reserved.
// ===========================================================================
//	Networking functions for use by Microsoft User Authentication Method.
// ===========================================================================

#include <Errors.h>
#include <AppleTalk.h>
#include <String.h>

#include "encrypt.h"
#include "UAMDebug.h"
#include "UAMMain.h"
#include "UAMNetwork.h"
#include "UAMUtils.h"
#include "UAMDialogs.h"

short					gSessionRefNum;
MSUAMLoginReplyBlock	gMSUAMReply;

extern Str32			gAFPVersion;


// ---------------------------------------------------------------------------
//		¥ UAM_GetSupportedUAMS()
// ---------------------------------------------------------------------------
//	Returns a bitmap containing the UAMs supported on the server.
//
//	->	inReplyInfo			Pointer to reply info supplied by ASPGetStatus() call.
//	<-	outSupportedUAMS	Bitmap containing supported UAMs:
//								- Clear Text Password (Apple)
//								- Guest (Apple and MS)
//								- Microsoft V1.0
//
//	As per Inside AppleTalk p.13-96, the supported UAM string variable list structure:
//
//		|-------------------|
//		|   Count of UAMs   |
//		|-------------------|
//		|					|
//		¥					¥
//		¥	 UAM Strings	¥
//		¥					¥
//		|					|
//		|-------------------|

void UAM_GetSupportedUAMS(ServerInfoReplyBlockP inReplyInfo, long *ioSupported)
{
	char			*theString;
	register short	theIndex;
	register short	theUAMCount;
	
	Assert_(inReplyInfo != NULL);
	Assert_(ioSupported != NULL);
	
	theString 	= ((char *)inReplyInfo) + inReplyInfo->supportedUAMOffset;
	theUAMCount	= *theString;
	
	//
	//The first byte is the UAM count, so we must increment past it.
	// 
	++theString;
	
	//
	//Initialize the return struct to all false.
	//
	*ioSupported = 0L;

	for (theIndex = theUAMCount; theIndex > 0; theIndex--, theString += theString[0] + 1)
	{
		if (EqualString(PSTR_ClearTextLogin, (StringPtr)theString, false, false))
		{
			*ioSupported |= kClearTxtSupported;
			continue;
		}
		
		if (EqualString(PSTR_GuestLogin, (StringPtr)theString, false, false))
		{
			*ioSupported |= kGuestSupported;
			continue;
		}
		
		if (EqualString(PSTR_EncryptedLogin1_0, (StringPtr)theString, false, false))
		{
			*ioSupported |= kMSUAMSupported;
			continue;
		}
		
		if (EqualString(PSTR_EncryptedLogin2_0, (StringPtr)theString, false, false))
		{
			*ioSupported |= kMSUAM_V2_Supported;
			continue;
		}
	}
}


// ---------------------------------------------------------------------------
//		¥ UAM_MapCharactersIntoHostSet()
// ---------------------------------------------------------------------------
//	Given a counted string, and a "host mapping table", do an in-place conversion
//	of that string into the host character set.  The table is construed to be
//	of length 255 - StartingExtendedCharValue chars long, and a character for
//	character conversion will be indicated for any chars in targetStr which 
//	are equal to or in excess of StartingExtendedCharValue.

Boolean UAM_MapCharactersIntoHostSet(char *szTarg, char *mappingTbl)
{
	unsigned char c;
		
	while (*szTarg)	
	{
		if ((unsigned char)*szTarg >= (unsigned char)kStartingExtendedCharValue)
		{
			c = *(mappingTbl+ (unsigned char)*szTarg - kStartingExtendedCharValue);
			if (c == kIllegalMappedExtChar) {
				DbgPrint_((DBGBUFF, "Illegal mapping character"));
				return(false);
			}
			else {
				*szTarg = c;
			}
		}
		
		szTarg++;
	}
			
	return(true);
}


// ---------------------------------------------------------------------------
//		¥ UAM_CryptEncrypt()
// ---------------------------------------------------------------------------
//	Call on methods in Encrypt.c to encrypt the password.

void UAM_CryptEncrypt(char *inClearPassword, char *inServerChallenge, char *outEncryptPW)
{
	unsigned char theCP[22];
				
	if (SetupUAMEncrypt())
	{
		OneWayFunction((unsigned char *)inClearPassword, theCP, UAM_CLRTXTPWDLEN);
		Encrypt((unsigned char *)inServerChallenge, theCP, (unsigned char *)outEncryptPW);

		CleanupUAMEncrypt();
	}
}


// ---------------------------------------------------------------------------
//		¥ UAM_DoublePasswordEncrypt()
// ---------------------------------------------------------------------------
//	Taken from the NT RtlXXX sources, this algorithm is designed to deal with the encryption
//	of two passwords, when the OneWayFunction of one is known on the target.  Specifically,
//	
//		for passwords x, y 
//	-- do a one way encryption of x  to Owf(x) -> result(0..15)
//	-- do a one way encryption of  y to Owf(x) -> result(16..31)

void UAM_DoublePasswordEncrypt(char *inCPPassword, char *inCPKeyPass, char *outDest)
{
	if (SetupUAMEncrypt())
	{
		OneWayFunction((unsigned char *)inCPPassword, (unsigned char *)outDest, UAM_CLRTXTPWDLEN);
		OneWayFunction((unsigned char *)inCPKeyPass, (unsigned char *)(outDest + kOneWayEncryptedArgSize), UAM_CLRTXTPWDLEN);
		
		CleanupUAMEncrypt();
	}
}