/*****************************************************************//**                  Microsoft Windows 2000                     **//**           Copyright (C) Microsoft Corp., 1991-1998          **//*****************************************************************//*****************************************************************//**                       Microsoft Windows                     **//**           Copyright (C) Microsoft Corp., 1991-1995          **//*****************************************************************//*****************************************************************//**               Microsoft Windows for Workgroups              **//**           Copyright (C) Microsoft Corp., 1991-1992          **//*****************************************************************//********************************************************************//**                     Microsoft LAN Manager                      **//**               Copyright(c) Microsoft Corp., 1987-1991          **//********************************************************************/#include <stdlib.h>#include <stdio.h>#include <string.h>#include "USRPWST3.h"// ---------------------------------------------------------------------------//		¥ EncryptStdBlock()// ---------------------------------------------------------------------------//	Routine Description:////    Takes a block key encrypts the standard text block with it.//    The resulting encrypted block is returned.//    This is a One-Way-Function - the key cannot be recovered from the//    encrypted data block.////	Arguments:////    BlockKey - The key to use to encrypt the standard text block.////    CypherBlock - The encrypted data is returned here////	Return Values:////    TRUE - The encryption was successful.//           The result is in CypherBlock////    FALSE - Something failed. The CypherBlock is undefined.bool EncryptStdBlock(    		IN 	PBLOCK_KEY 		BlockKey,    		OUT PCYPHER_BLOCK 	CypherBlock	 ){    unsigned 	Result;    char 		StdEncrPwd[] = "KGS!@#$%";    Result = DES_ECB_LM((DWORD)ENCR_KEY,                        (const char *)BlockKey,                        (unsigned char *)StdEncrPwd,                        (unsigned char *)CypherBlock                       );    if (Result == CRYPT_OK) {        return(TRUE);    } else {        return(FALSE);    }}// ---------------------------------------------------------------------------//		¥ CalculateLmOwfPassword()// ---------------------------------------------------------------------------//	Routine Description:////    Takes the passed LmPassword and performs a one-way-function on it.//    The current implementation does this by using the password as a key//    to encrypt a known block of text.////	Arguments:////    LmPassword - The password to perform the one-way-function on.////    LmOwfPassword - The hashed password is returned here////	Return Values:////    BOOL - The function was completed successfully. The hashed//                     password is in LmOwfPassword.////    FALSE - Something failed. The LmOwfPassword is undefined.bool CalculateLmOwfPassword(    		IN 		PLM_PASSWORD 		LmPassword,    		OUT 	PLM_OWF_PASSWORD 	LmOwfPassword ){    bool        Status;    BLOCK_KEY   Key[2];    PCHAR       pKey;    // Copy the password into our key buffer and zero pad to fill the 2 keys    pKey = (PCHAR)(&Key[0]);    while (*LmPassword && (pKey < (PCHAR)(&Key[2]))) {        *pKey++ = *LmPassword++;    }    while (pKey < (PCHAR)(&Key[2])) {        *pKey++ = 0;    }    // Use the keys to encrypt the standard text    Status = EncryptStdBlock(&Key[0], &(LmOwfPassword->data[0]));    if (!Status) {        return(Status);    }	//*****************************************************	//BUGBUG: Alignment work-around needed for 68K, may not	//work under PowerPC!	//*****************************************************	PBLOCK_KEY pK = (PBLOCK_KEY)(((PUCHAR)&Key[1])-1);    Status = EncryptStdBlock(pK /*&Key[1]*/, &(LmOwfPassword->data[1]));    //    // clear our copy of the cleartext password    //    pKey = (PCHAR)(&Key[0]);    while (pKey < (PCHAR)(&Key[2])) {        *pKey++ = 0;    }    return(Status);}// ---------------------------------------------------------------------------//		¥ EncryptBlock()// ---------------------------------------------------------------------------//	Routine Description:////    Takes a block of data and encrypts it with a key producing//    an encrypted block of data.////	Arguments:////    ClearBlock - The block of data that is to be encrypted.////    BlockKey - The key to use to encrypt data////    CypherBlock - Encrypted data is returned here////	Return Values:////    TRUE - The data was encrypted successfully. The encrypted//                     data block is in CypherBlock////    FALSE - Something failed. The CypherBlock is undefined.bool EncryptBlock(    	IN 	PCLEAR_BLOCK 	ClearBlock,    	IN 	PBLOCK_KEY 		BlockKey,    	OUT PCYPHER_BLOCK 	CypherBlock ){    unsigned Result;    Result = DES_ECB_LM(ENCR_KEY,                        (const char *)BlockKey,                        (unsigned char *)ClearBlock,                        (unsigned char *)CypherBlock                       );    if (Result == CRYPT_OK) {        return(TRUE);    } else {        return(FALSE);    }}// ---------------------------------------------------------------------------//		¥ EncryptLmOwfPwdWithLmOwfPwd()// ---------------------------------------------------------------------------//	Routine Description:////    Encrypts one OwfPassword with another////	Arguments:////    DataLmOwfPassword - OwfPassword to be encrypted////    KeyLmOwfPassword - OwfPassword to be used as a key to the encryption////    EncryptedLmOwfPassword - The encrypted OwfPassword is returned here.////	Return Values:////    TRUE - The function completed successfully. The encrypted//                     OwfPassword is in EncryptedLmOwfPassword////    FALSE - Something failed. The EncryptedLmOwfPassword is undefined.bool EncryptLmOwfPwdWithLmOwfPwd(    	IN 	PLM_OWF_PASSWORD 			DataLmOwfPassword,    	IN 	PLM_OWF_PASSWORD 			KeyLmOwfPassword,   		OUT PENCRYPTED_LM_OWF_PASSWORD 	EncryptedLmOwfPassword ){    bool    Status;    Status = EncryptBlock(  (PCLEAR_BLOCK)&(DataLmOwfPassword->data[0]),                            &(((PBLOCK_KEY)(KeyLmOwfPassword->data))[0]),                            &(EncryptedLmOwfPassword->data[0]));            if (!Status) {        return(Status);    }        //    //*****************************************    //****WILL PROBABLY BREAK UNDER POWERPC****    //****This is necessary on Mac68K**********    //****WILL PROBABLY BREAK UNDER POWERPC****    //    PBLOCK_KEY pK = (PBLOCK_KEY)&(KeyLmOwfPassword->data[1]);    //pK++;        //    //Notice the "-1" in the second parameter, this is necessary to position the     //ptr at byte 7 in the FIRST parameter of the struct.    //    Status = EncryptBlock(  (PCLEAR_BLOCK)&(DataLmOwfPassword->data[1]),                            (PBLOCK_KEY)(((PUCHAR)pK)-1),                            &(EncryptedLmOwfPassword->data[1]));    //    //*****************************************    //        return(Status);}// ---------------------------------------------------------------------------//		¥ SampEncryptLmPasswords()// ---------------------------------------------------------------------------//Routine Description:////    Encrypts the cleartext passwords into the form that is sent over//    the network.  Before computing the OWF passwords, the cleartext forms//    are upper cased, then OEMed (the order is significant).  The cleartext//    password to be sent is OEMed only.////Arguments:////Return Value:DWORD SampEncryptLmPasswords(	    LPSTR OldUpcasePassword,	    LPSTR NewUpcasePassword,	    LPSTR NewPassword,	    PSAMPR_ENCRYPTED_USER_PASSWORD NewEncryptedWithOldLm,	    PENCRYPTED_NT_OWF_PASSWORD OldLmOwfEncryptedWithNewLm ){    LM_OWF_PASSWORD OldLmOwfPassword;    LM_OWF_PASSWORD NewLmOwfPassword;    PSAMPR_USER_PASSWORD NewLm = (PSAMPR_USER_PASSWORD) NewEncryptedWithOldLm;    struct RC4_KEYSTRUCT Rc4Key;    bool Status;        memset(&Rc4Key, 0, sizeof(RC4_KEYSTRUCT));    //    // Calculate the LM OWF passwords    //    Status = CalculateLmOwfPassword(                OldUpcasePassword,                &OldLmOwfPassword                );        if (Status)    {        Status = CalculateLmOwfPassword(                    NewUpcasePassword,                    &NewLmOwfPassword                    );    }    //    // Calculate the encrypted old passwords    //    if (Status)    {        Status = EncryptLmOwfPwdWithLmOwfPwd(                    &OldLmOwfPassword,                    &NewLmOwfPassword,                    OldLmOwfEncryptedWithNewLm                    );    }        //    // Calculate the encrypted new passwords    //    if (Status)    {        //        // Compute the encrypted new password with LM key.        //        rc4_key(            &Rc4Key,            (DWORD)LM_OWF_PASSWORD_LENGTH,            (PUCHAR)&OldLmOwfPassword            );                    memcpy(            ((PUCHAR) NewLm->Buffer) + (SAM_MAX_PASSWORD_LENGTH * sizeof(WCHAR)) - strlen(NewPassword),            NewPassword,            strlen(NewPassword)            );        	//****************************************************    	//BUGBUG: We must swap the significant bytes on Mac68K    	//****************************************************        NewLm->Length = strlen(NewPassword);		NewLm->Length = ntoh(NewLm->Length);	        rc4(&Rc4Key,            sizeof(SAMPR_USER_PASSWORD),            (PUCHAR) NewLm->Buffer            );    }    if (Status)    {        return(ERROR_SUCCESS);    }    else return(ERROR_INVALID_FUNCTION);}