|
|
//+-----------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (c) Microsoft Corporation 1992 - 1996
//
// File: auth.h
//
// Contents: include file for auth.cxx for NTDigest
//
//
// History: KDamour 15Mar00 Stolen from msv_sspi\global.h
//
//------------------------------------------------------------------------
#ifndef NTDIGEST_AUTH_H
#define NTDIGEST_AUTH_H
#include "nonce.h"
// Contains all of the pointers and lengths for directives used in
// calculating the digest access values. Usually the
// parameters point to an external buffer, pHTTPBuffer
enum DIGEST_TYPE { DIGEST_UNDEFINED, // Initial state
NO_DIGEST_SPECIFIED, DIGEST_CLIENT, DIGEST_SERVER, SASL_SERVER, SASL_CLIENT };
enum QOP_TYPE { QOP_UNDEFINED, // Initial state
NO_QOP_SPECIFIED, AUTH, AUTH_INT, AUTH_CONF }; typedef QOP_TYPE *PQOP_TYPE;
enum ALGORITHM_TYPE { ALGORITHM_UNDEFINED, // Initial state
NO_ALGORITHM_SPECIFIED, MD5, MD5_SESS };
enum CHARSET_TYPE { CHARSET_UNDEFINED, // Initial state
ISO_8859_1, UTF_8, // UTF-8 encoding
UTF_8_SUBSET // ISO_8859_1 subset in UTF-8
};
enum CIPHER_TYPE { CIPHER_UNDEFINED, CIPHER_3DES, CIPHER_DES, // 56bit key
CIPHER_RC4_40, CIPHER_RC4, // 128bit key
CIPHER_RC4_56 };
enum DIGESTMODE_TYPE { DIGESTMODE_UNDEFINED, DIGESTMODE_HTTP, DIGESTMODE_SASL };
enum NAMEFORMAT_TYPE { NAMEFORMAT_UNKNOWN, NAMEFORMAT_ACCOUNTNAME, NAMEFORMAT_UPN, NAMEFORMAT_NETBIOS };
// For list of supported protocols
// Pack supported cyphers into a WORD (2 bytes)
#define SUPPORT_3DES 0x0001
#define SUPPORT_DES 0x0002
#define SUPPORT_RC4_40 0x0004
#define SUPPORT_RC4 0x0008
#define SUPPORT_RC4_56 0x0010
// Strings for the challenge and challengeResponse
#define STR_CIPHER_3DES "3des"
#define STR_CIPHER_DES "des"
#define STR_CIPHER_RC4_40 "rc4-40"
#define STR_CIPHER_RC4 "rc4"
#define STR_CIPHER_RC4_56 "rc4-56"
#define WSTR_CIPHER_HMAC_MD5 L"HMAC_MD5"
#define WSTR_CIPHER_RC4 L"RC4"
#define WSTR_CIPHER_DES L"DES"
#define WSTR_CIPHER_3DES L"3DES"
typedef enum _eSignSealOp { eSign, // MakeSignature is calling
eVerify, // VerifySignature is calling
eSeal, // SealMessage is calling
eUnseal // UnsealMessage is calling
} eSignSealOp;
// Supplimental credentals stored in the DC (pre-calculated Digest Hashes
#define SUPPCREDS_VERSION 1
#define NUMPRECALC_HEADERS 9
#define TOTALPRECALC_HEADERS (NUMPRECALC_HEADERS + 1)
// Format in supplimental credentials
#define NAME_HEADER 0
#define NAME_ACCT 1
#define NAME_ACCT_DOWNCASE 2
#define NAME_ACCT_UPCASE 3
#define NAME_UPN 4
#define NAME_UPN_DOWNCASE 5
#define NAME_UPN_UPCASE 6
#define NAME_NT4 7
#define NAME_NT4_DOWNCASE 8
#define NAME_NT4_UPCASE 9
// Bit flags for Packed UserContext
#define USERCONTEXT_UPDATE 0x00000001
//
// value names used by MD5 authentication.
//
enum MD5_AUTH_NAME { MD5_AUTH_USERNAME = 0, MD5_AUTH_REALM, MD5_AUTH_NONCE, MD5_AUTH_CNONCE, MD5_AUTH_NC, MD5_AUTH_ALGORITHM, MD5_AUTH_QOP, MD5_AUTH_METHOD, MD5_AUTH_URI, MD5_AUTH_RESPONSE, MD5_AUTH_HENTITY, MD5_AUTH_AUTHZID, // for SASL
// Above this list are Marshalled to DC as BlobData
MD5_AUTH_DOMAIN, MD5_AUTH_STALE, MD5_AUTH_OPAQUE, MD5_AUTH_MAXBUF, MD5_AUTH_CHARSET, MD5_AUTH_CIPHER, MD5_AUTH_DIGESTURI, // for SASL mapped to MD5_AUTH_URI
MD5_AUTH_RSPAUTH, // verify server has auth data
MD5_AUTH_LAST };
// Structure to pass around that contains the parameters for the Digest Calculation
typedef struct _DIGEST_PARAMETER { DIGEST_TYPE typeDigest; ALGORITHM_TYPE typeAlgorithm; QOP_TYPE typeQOP; CIPHER_TYPE typeCipher; CHARSET_TYPE typeCharset; STRING refstrParam[MD5_AUTH_LAST]; // referenced - points to non-owned memory- do not free up these Strings
UNICODE_STRING ustrRealm; // extracted from the digest auth directive values
UNICODE_STRING ustrUsername; // extracted from the digest auth directive values
UNICODE_STRING ustrUri; // extracted from the digest auth directive values
// Results from DSCrackName
NAMEFORMAT_TYPE typeName; UNICODE_STRING ustrCrackedAccountName; // SAMAccount name from DSCrackName
UNICODE_STRING ustrCrackedDomain; // Domain from DSCrackName
STRING strUsernameEncoded; // contains a copy of the encoded string used in challengeresponse
STRING strRealmEncoded; // contains a copy of the realm
STRING strDirective[MD5_AUTH_LAST]; // NULL terminated strings that contain directive values
STRING strSessionKey; // String for Sessionkey (points to chSessionKey)
// STRINGS Alloced by DigestInit and Freed by DigestFree
STRING strResponse; // String for the BinHex Hashed Response
} DIGEST_PARAMETER, *PDIGEST_PARAMETER;
// Structure to extract MD5 hashes and passwords for user accounts
typedef struct _USER_CREDENTIALS { UNICODE_STRING ustrUsername; UNICODE_STRING ustrDomain; NAMEFORMAT_TYPE typeName;
// The following fields might be filled in
// Will check any precalculated hashes first and then try the password if available
BOOL fIsValidPasswd; // set true if password is valid
BOOL fIsValidDigestHash; // set true if hash is valid
BOOL fIsEncryptedPasswd; // set to TRUE is passwd encrypted
SHORT wHashSelected; // if hash valid, index to process
SHORT sHashTags[TOTALPRECALC_HEADERS]; // indicate which hashes match username format
UNICODE_STRING ustrPasswd; STRING strDigestHash;
} USER_CREDENTIALS, *PUSER_CREDENTIALS;
// Data to use GenericPassthrough to send to the DC for processing
// The server will create the data, BlobData, and it will be wraped for
// transport over GenericPassthrough to the DC. The DC will be presented
// with only the BlobData to process
// ALL directive-values have a NULL terminator attached to each directive
// ALL directive-values are UNQUOTED unq("X") -> X
// cbBlobSize has number of bytes to hold header and the string data
// cbCharValues has number of bytes to hold string data
// This way future revs can Version++, increase cbBlobSize, and append to message
//
// Data Format
//
// USHORT Version
// USHORT cbBlobSize
// USHORT DIGEST_TYPE
// USHORT cbCharValues
//
// CHAR[cbUserName+1] unq(username-value)
// CHAR[cbRealm+1] unq(realm-value)
// CHAR[cbNonce+1] unq(nonce-value)
// CHAR[cbCnonce+1] unq(cnonce-value)
// CHAR[cbNC+1] unq(nc-value)
// CHAR[cbAlgorithm+1] unq(algorithm-value)
// CHAR[cbQOP+1] unq(qop-value)
// CHAR[cbMethod+1] Method
// CHAR[cbURI+1] unq(digest-uri-value)
// CHAR[cbReqDigest+1] unq(request-digest)
// CHAR[cbHEntity+1] unq(H(entity-body)) * maybe NULL only for qop="auth"
// CHAR[cbAuthzId+1] unq(AuthzId-value)
//
//
#define DIGEST_BLOB_VERSION 1
#define DIGEST_BLOB_VALUES 12 // How many field-values are sent over
// Values for separators detweent field-values
#define COLONSTR ":"
#define COLONSTR_LEN 1
#define AUTHSTR "auth"
#define AUTHSTR_LEN 4
#define AUTHINTSTR "auth-int"
#define AUTHINTSTR_LEN 8
#define AUTHCONFSTR "auth-conf"
#define AUTHCONFSTR_LEN 9
#define MAX_AUTH_LENGTH AUTHCONFSTR_LEN
#define MD5STR "MD5"
#define MD5_SESSSTR "MD5-sess"
#define MD5_SESS_SASLSTR "md5-sess"
#define MD5_UTF8STR "utf-8"
#define URI_STR "uri"
#define DIGESTURI_STR "digest-uri"
// SASL paramters
#define AUTHENTICATESTR "AUTHENTICATE"
#define ZERO32STR "00000000000000000000000000000000"
#define SASL_C2S_SIGN_KEY "Digest session key to client-to-server signing key magic constant"
#define SASL_S2C_SIGN_KEY "Digest session key to server-to-client signing key magic constant"
#define SASL_C2S_SEAL_KEY "Digest H(A1) to client-to-server sealing key magic constant"
#define SASL_S2C_SEAL_KEY "Digest H(A1) to server-to-client sealing key magic constant"
// Number of characters in the NonceCount (hex digits)
#define NCNUM 8
#define NCFIRST "00000001"
// Overlay header for getting values in Generic Passthrough request
typedef struct _DIGEST_BLOB_REQUEST { ULONG MessageType; USHORT version; USHORT cbBlobSize; USHORT digest_type; USHORT qop_type; USHORT alg_type; USHORT charset_type; USHORT cbCharValues; USHORT name_format; USHORT usReserved1; ULONG ulReserved2; ULONG ulReserved3; ULONG64 pad1; char cCharValues; // dummy char to mark start of field-values
} DIGEST_BLOB_REQUEST, *PDIGEST_BLOB_REQUEST;
// Supported MesageTypes
#define VERIFY_DIGEST_MESSAGE 0x1a // No specific value is needed
#define VERIFY_DIGEST_MESSAGE_RESPONSE 0x0a // No specific value is needed
// The response for the GenericPassthrough call is the status of the Digest Authentication
// Note: This is a fixed length response header - Authdata length not static
typedef struct _DIGEST_BLOB_RESPONSE { ULONG MessageType; USHORT version; NTSTATUS Status; // Information on Success of Digest Auth
USHORT SessionKeyMaxLength; ULONG ulAuthDataSize; ULONG ulReserved1; ULONG ulReserved2; ULONG ulReserved3; char SessionKey[MD5_HASH_HEX_SIZE + 1]; ULONG64 pad1; char cAuthData; // Start of AuthData opaque data
// Place group info here for LogonUser
} DIGEST_BLOB_RESPONSE, *PDIGEST_BLOB_RESPONSE;
// SASL MAC block
// Total of 16 bytes per rfc2831 sect 2.3
// first 10 bytes of HMAC-MD5 [ RFC 2104]
// 2-byte message type number fixed to value 1 (0x0001)
// 4-byte sequence number
// NOTE: This is using WORD as a 2 byte value and DWORD as a 4 byte value!
#define HMAC_MD5_HASH_BYTESIZE 16 // MHAC-MD5 hash size per RFC 2104
#define SASL_MAC_HMAC_SIZE 10
#define SASL_MAC_MSG_SIZE 2
#define SASL_MAC_SEQ_SIZE 4
typedef struct _SASL_MAC_BLOCK { UCHAR hmacMD5[SASL_MAC_HMAC_SIZE]; WORD wMsgType; DWORD dwSeqNumber; } SASL_MAC_BLOCK, *PSASL_MAC_BLOCK;
// The SASL MAC Block is 16 bytes: RFC 2831 sect 2.4
#define MAC_BLOCK_SIZE sizeof(SASL_MAC_BLOCK)
#define MAX_PADDING 8 // max padding is currently 8 for DES
// Encode the Digest Access Parameters fields into a BYTE Buffer
NTSTATUS NTAPI BlobEncodeRequest(IN PDIGEST_PARAMETER pDigest, OUT BYTE **ppBuffer, OUT USHORT *cbBuffer);
// Decode the Digest Access Parameters fields from a BYTE Buffer
NTSTATUS NTAPI BlobDecodeRequest(IN BYTE *pBuffer, PDIGEST_PARAMETER pDigest);
// Free BYTE Buffer from BlobEncodeRequest
VOID NTAPI BlobFreeRequest(BYTE *pBuffer);
// Hash and Encode upto 7 STRINGS SOut = Hex(H(S1 ":" S2 ... ":" S7))
NTSTATUS NTAPI DigestHash7(IN PSTRING pS1, IN PSTRING pS2, IN PSTRING pS3, IN PSTRING pS4, IN PSTRING pS5, IN PSTRING pS6, IN PSTRING pS7, IN BOOL fHexOut, OUT PSTRING pSOut);
// Perform Digest Access Calculation
NTSTATUS NTAPI DigestCalculation(IN PDIGEST_PARAMETER pDigest, IN PUSER_CREDENTIALS pUserCreds);
// Simple checks for enough data for Digest calculation
NTSTATUS NTAPI DigestIsValid(IN PDIGEST_PARAMETER pDigest);
// Initialize the DIGEST_PARAMETER structure
NTSTATUS NTAPI DigestInit(IN PDIGEST_PARAMETER pDigest);
// Clear out the digest & free memory from Digest struct
NTSTATUS NTAPI DigestFree(IN PDIGEST_PARAMETER pDigest);
// Determine H(A1) for Digest Access
NTSTATUS NTAPI DigestCalcHA1(IN PDIGEST_PARAMETER pDigest, PUSER_CREDENTIALS pUserCreds);
// Perform Digest Access Calculation for ChallengeResponse
NTSTATUS NTAPI DigestCalcChalRsp(IN PDIGEST_PARAMETER pDigest, IN PUSER_CREDENTIALS pUserCreds, BOOL bIsChallenge);
// Processed parsed digest auth message and fill in string values
NTSTATUS NTAPI DigestDecodeDirectiveStrings(IN OUT PDIGEST_PARAMETER pDigest);
NTSTATUS PrecalcDigestHash( IN PUNICODE_STRING pustrUsername, IN PUNICODE_STRING pustrRealm, IN PUNICODE_STRING pustrPassword, OUT PCHAR pHexHash, IN OUT PUSHORT piHashSize);
NTSTATUS PrecalcForms( IN PUNICODE_STRING pustrUsername, IN PUNICODE_STRING pustrRealm, IN PUNICODE_STRING pustrPassword, OUT PCHAR pHexHash, IN OUT PUSHORT piHashSize);
#endif // NTDIGEST_AUTH_H
|