/* Copyright (c) 1993, Microsoft Corporation, all rights reserved ** ** raschap.h ** Remote Access PPP Challenge Handshake Authentication Protocol ** ** 11/05/93 Steve Cobb */ #ifndef _RASCHAP_H_ #define _RASCHAP_H_ #include "md5.h" #include #define TRACE_RASCHAP (0x00010000|TRACE_USE_MASK|TRACE_USE_MSEC|TRACE_USE_DATE) #define TRACE(a) TracePrintfExA(g_dwTraceIdChap,TRACE_RASCHAP,a ) #define TRACE1(a,b) TracePrintfExA(g_dwTraceIdChap,TRACE_RASCHAP,a,b ) #define TRACE2(a,b,c) TracePrintfExA(g_dwTraceIdChap,TRACE_RASCHAP,a,b,c ) #define TRACE3(a,b,c,d) TracePrintfExA(g_dwTraceIdChap,TRACE_RASCHAP,a,b,c,d ) #define DUMPW(X,Y) TraceDumpExA(g_dwTraceIdChap,1,(LPBYTE)X,Y,4,1,NULL) #define DUMPB(X,Y) TraceDumpExA(g_dwTraceIdChap,1,(LPBYTE)X,Y,1,1,NULL) //General macros #define GEN_RAND_ENCODE_SEED ((CHAR) ( 1 + rand() % 250 )) /* CHAP packet codes from CHAP spec except ChangePw. */ #define CHAPCODE_Challenge 1 #define CHAPCODE_Response 2 #define CHAPCODE_Success 3 #define CHAPCODE_Failure 4 #define CHAPCODE_ChangePw1 5 #define CHAPCODE_ChangePw2 6 #define CHAPCODE_ChangePw3 7 #define MAXCHAPCODE 7 /* Returned by receive buffer parsing routines that discover the packet is ** corrupt, usually because the length fields don't make sense. */ #define ERRORBADPACKET (DWORD )-1 /* Maximum challenge and response lengths. */ #define MAXCHALLENGELEN 255 #define MSRESPONSELEN (LM_RESPONSE_LENGTH + NT_RESPONSE_LENGTH + 1) #define MD5RESPONSELEN MD5_LEN #define MAXRESPONSELEN max( MSRESPONSELEN, MD5RESPONSELEN ) #define MAXINFOLEN 1500 /* Defines states within the CHAP protocol. */ #define CHAPSTATE enum tagCHAPSTATE CHAPSTATE { CS_Initial, CS_WaitForChallenge, CS_ChallengeSent, CS_ResponseSent, CS_Retry, CS_ChangePw, CS_ChangePw1, CS_ChangePw2, CS_ChangePw1Sent, CS_ChangePw2Sent, CS_WaitForAuthenticationToComplete1, CS_WaitForAuthenticationToComplete2, CS_Done }; /* Defines the change password version 1 (NT 3.5) response data buffer. */ #define CHANGEPW1 struct tagCHANGEPW1 CHANGEPW1 { BYTE abEncryptedLmOwfOldPw[ ENCRYPTED_LM_OWF_PASSWORD_LENGTH ]; BYTE abEncryptedLmOwfNewPw[ ENCRYPTED_LM_OWF_PASSWORD_LENGTH ]; BYTE abEncryptedNtOwfOldPw[ ENCRYPTED_NT_OWF_PASSWORD_LENGTH ]; BYTE abEncryptedNtOwfNewPw[ ENCRYPTED_NT_OWF_PASSWORD_LENGTH ]; BYTE abPasswordLength[ 2 ]; BYTE abFlags[ 2 ]; }; /* CHANGEPW1.abFlags bit definitions. */ #define CPW1F_UseNtResponse 0x00000001 /* Define the change password version 2 (NT 3.51) response data buffer. */ #define CHANGEPW2 struct tagCHANGEPW2 CHANGEPW2 { BYTE abNewEncryptedWithOldNtOwf[ sizeof(SAMPR_ENCRYPTED_USER_PASSWORD) ]; BYTE abOldNtOwfEncryptedWithNewNtOwf[ ENCRYPTED_NT_OWF_PASSWORD_LENGTH ]; BYTE abNewEncryptedWithOldLmOwf[ sizeof(SAMPR_ENCRYPTED_USER_PASSWORD) ]; BYTE abOldLmOwfEncryptedWithNewNtOwf[ ENCRYPTED_NT_OWF_PASSWORD_LENGTH ]; BYTE abLmResponse[ LM_RESPONSE_LENGTH ]; BYTE abNtResponse[ NT_RESPONSE_LENGTH ]; BYTE abFlags[ 2 ]; }; /* CHANGEPW2.abFlags bit definitions. */ #define CPW2F_UseNtResponse 0x00000001 #define CPW2F_LmPasswordPresent 0x00000002 /* Define the change password for new MS-CHAP */ #define CHANGEPW3 struct tagCHANGEPW3 CHANGEPW3 { BYTE abEncryptedPassword[ 516 ]; BYTE abEncryptedHash[ 16 ]; BYTE abPeerChallenge[ 24 ]; BYTE abNTResponse[ 24 ]; BYTE abFlags[ 2 ]; }; /* Union for storage effieciency (never need both formats at same time). */ #define CHANGEPW union tagCHANGEPW CHANGEPW { /* This dummy field is included so the MIPS compiler will align the ** structure on a DWORD boundary. Normally, MIPS does not force alignment ** if the structure contains only BYTEs or BYTE arrays. This protects us ** from alignment faults should SAM or LSA interpret the byte arrays as ** containing some necessarily aligned type, though currently they do not. */ DWORD dwAlign; CHANGEPW1 v1; CHANGEPW2 v2; CHANGEPW3 v3; }; /* Defines the WorkBuf stored for us by the PPP engine. */ #define CHAPWB struct tagCHAPWB CHAPWB { /* CHAP encryption method negotiated (MD5 or Microsoft extended). Note ** that server does not support MD5. */ BYTE bAlgorithm; /* True if role is server, false if client. */ BOOL fServer; /* The port handle on which the protocol is active. */ HPORT hport; /* Number of authentication attempts left before we shut down. (Microsoft ** extended CHAP only) */ DWORD dwTriesLeft; /* Client's credentials. */ CHAR szUserName[ UNLEN + DNLEN + 2 ]; CHAR szOldPassword[ PWLEN + 1 ]; CHAR szPassword[ PWLEN + 1 ]; CHAR szDomain[ DNLEN + 1 ]; /* The LUID is a logon ID required by LSA to determine the response. It ** must be determined in calling app's context and is therefore passed ** down. (client only) */ LUID Luid; /* The challenge sent or received in the Challenge Packet and the length ** in bytes of same. Note that LUID above keeps this DWORD aligned. */ BYTE abChallenge[ MAXCHALLENGELEN ]; BYTE cbChallenge; BYTE abComputedChallenge[ MAXCHALLENGELEN ]; /* Indicates whether a new challenge was provided in the last Failure ** packet. (client only) */ BOOL fNewChallengeProvided; /* The response sent or received in the Response packet and the length in ** bytes of same. Note the BOOL above keeps this DWORD aligned. */ BYTE abResponse[ MAXRESPONSELEN ]; BYTE cbResponse; /* The change password response sent or received in the ChangePw or ** ChangePw2 packets. */ CHANGEPW changepw; /* The LM and user session keys retrieved when credentials are successfully ** authenticated. */ LM_SESSION_KEY keyLm; USER_SESSION_KEY keyUser; /* This flag indicates that the session key has been calculated ** from the password or retrieved from LSA. */ BOOL fSessionKeysObtained; /* On the client, this contains the pointer to the MPPE keys. On the server ** this field is not used. */ RAS_AUTH_ATTRIBUTE * pMPPEKeys; /* The current state in the CHAP protocol. */ CHAPSTATE state; /* Sequencing ID expected on next packet received on this port and the ** value to send on the next outgoing packet. */ BYTE bIdExpected; BYTE bIdToSend; /* The final result, used to duplicate the original response in subsequent ** response packets. This is per CHAP spec to cover lost Success/Failure ** case without allowing malicious client to discover alternative ** identities under the covers during a connection. (applies to server ** only) */ PPPAP_RESULT result; HPORT hPort; DWORD dwInitialPacketId; DWORD fConfigInfo; RAS_AUTH_ATTRIBUTE * pAttributesFromAuthenticator; // // Used to send authentication request to backend server // RAS_AUTH_ATTRIBUTE * pUserAttributes; // CHAR chSeed; //Seed for encoding password. // // Data Blob information for password // DATA_BLOB DBPassword; // // Data Blob information for oldpassword // DATA_BLOB DBOldPassword; }; /* Prototypes. */ DWORD ChapInit( IN BOOL fInitialize ); DWORD ChapSMakeMessage( CHAPWB*, PPP_CONFIG*, PPP_CONFIG*, DWORD, PPPAP_RESULT*, PPPAP_INPUT* ); DWORD MakeAuthenticationRequestAttributes( IN CHAPWB* pwb, IN BOOL fMSChap, IN BYTE bAlgorithm, IN CHAR* szUserName, IN BYTE* pbChallenge, IN DWORD cbChallenge, IN BYTE* pbResponse, IN DWORD cbResponse, IN BYTE bId ); DWORD GetErrorCodeFromAttributes( IN CHAPWB* pwb ); DWORD LoadChapHelperFunctions( VOID ); DWORD ChapCMakeMessage( CHAPWB*, PPP_CONFIG*, PPP_CONFIG*, DWORD, PPPAP_RESULT*, PPPAP_INPUT* ); DWORD ChapBegin( VOID**, VOID* ); DWORD ChapEnd( VOID* ); DWORD ChapMakeMessage( VOID*, PPP_CONFIG*, PPP_CONFIG*, DWORD, PPPAP_RESULT*, PPPAP_INPUT* ); DWORD GetChallengeFromChallenge( CHAPWB*, PPP_CONFIG* ); DWORD MakeChangePw1Message( CHAPWB*, PPP_CONFIG*, DWORD ); DWORD MakeChangePw2Message( CHAPWB*, PPP_CONFIG*, DWORD ); DWORD MakeChangePw3Message( CHAPWB*, PPP_CONFIG*, DWORD, BOOL ); DWORD GetCredentialsFromResponse( PPP_CONFIG*, BYTE, CHAR*, BYTE* ); DWORD GetInfoFromChangePw1( PPP_CONFIG*, CHANGEPW1* ); DWORD GetInfoFromChangePw2( PPP_CONFIG*, CHANGEPW2*, BYTE* ); DWORD GetInfoFromChangePw3( PPP_CONFIG*, CHANGEPW3*, BYTE* ); VOID GetInfoFromFailure( CHAPWB*, PPP_CONFIG*, DWORD*, BOOL*, DWORD* ); BYTE HexCharValue( CHAR ); DWORD MakeChallengeMessage( CHAPWB*, PPP_CONFIG*, DWORD ); DWORD MakeResponseMessage( CHAPWB*, PPP_CONFIG*, DWORD, BOOL ); VOID ChapMakeResultMessage( CHAPWB*, DWORD, BOOL, PPP_CONFIG*, DWORD ); DWORD StoreCredentials( CHAPWB*, PPPAP_INPUT* ); DWORD ChapChangeNotification( VOID ); DWORD GetChallenge( OUT PBYTE pChallenge ); VOID EndLSA( VOID ); DWORD InitLSA( VOID ); DWORD MakeChangePasswordV1RequestAttributes( IN CHAPWB* pwb, IN BYTE bId, IN PCHAR pchIdentity, IN PBYTE Challenge, IN PENCRYPTED_LM_OWF_PASSWORD pEncryptedLmOwfOldPassword, IN PENCRYPTED_LM_OWF_PASSWORD pEncryptedLmOwfNewPassword, IN PENCRYPTED_NT_OWF_PASSWORD pEncryptedNtOwfOldPassword, IN PENCRYPTED_NT_OWF_PASSWORD pEncryptedNtOwfNewPassword, IN WORD LenPassword, IN WORD wFlags, IN DWORD cbChallenge, IN BYTE * pbChallenge ); DWORD MakeChangePasswordV2RequestAttributes( IN CHAPWB* pwb, IN BYTE bId, IN CHAR* pchIdentity, IN SAMPR_ENCRYPTED_USER_PASSWORD* pNewEncryptedWithOldNtOwf, IN ENCRYPTED_NT_OWF_PASSWORD* pOldNtOwfEncryptedWithNewNtOwf, IN SAMPR_ENCRYPTED_USER_PASSWORD* pNewEncryptedWithOldLmOwf, IN ENCRYPTED_NT_OWF_PASSWORD* pOldLmOwfEncryptedWithNewNtOwf, IN DWORD cbChallenge, IN BYTE * pbChallenge, IN BYTE * pbResponse, IN WORD wFlags ); DWORD MakeChangePasswordV3RequestAttributes( IN CHAPWB* pwb, IN BYTE bId, IN CHAR* pchIdentity, IN CHANGEPW3* pchangepw3, IN DWORD cbChallenge, IN BYTE * pbChallenge ); DWORD GetEncryptedPasswordsForChangePassword2( IN CHAR* pszOldPassword, IN CHAR* pszNewPassword, OUT SAMPR_ENCRYPTED_USER_PASSWORD* pNewEncryptedWithOldNtOwf, OUT ENCRYPTED_NT_OWF_PASSWORD* pOldNtOwfEncryptedWithNewNtOwf, OUT SAMPR_ENCRYPTED_USER_PASSWORD* pNewEncryptedWithOldLmOwf, OUT ENCRYPTED_NT_OWF_PASSWORD* pOldLmOwfEncryptedWithNewNtOwf, OUT BOOLEAN* pfLmPresent ); /* Globals. */ #ifdef RASCHAPGLOBALS #define GLOBALS #define EXTERN #else #define EXTERN extern #endif EXTERN DWORD g_dwTraceIdChap #ifdef GLOBALS = INVALID_TRACEID; #endif ; EXTERN DWORD g_dwRefCount #ifdef GLOBALS = 0; #endif ; EXTERN HANDLE g_hLsa #ifdef GLOBALS = INVALID_HANDLE_VALUE; #endif ; EXTERN CHAR szComputerName[CNLEN+1]; #undef EXTERN #undef GLOBALS #endif // _RASCHAP_H_