155 lines
5.1 KiB
Go
155 lines
5.1 KiB
Go
//Copyright 2013 Thomson Reuters Global Resources. All Rights Reserved. Proprietary and confidential information of TRGR. Disclosure, use, or reproduction without written authorization of TRGR is prohibited.
|
|
|
|
package ntlm
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
)
|
|
|
|
// NTLMv1
|
|
// ******
|
|
type NtlmV1Response struct {
|
|
// 24 byte array
|
|
Response []byte
|
|
}
|
|
|
|
func (n *NtlmV1Response) String() string {
|
|
return fmt.Sprintf("NtlmV1Response: %s", hex.EncodeToString(n.Response))
|
|
}
|
|
|
|
func ReadNtlmV1Response(bytes []byte) (*NtlmV1Response, error) {
|
|
r := new(NtlmV1Response)
|
|
r.Response = bytes[0:24]
|
|
return r, nil
|
|
}
|
|
|
|
// *** NTLMv2
|
|
// The NTLMv2_CLIENT_CHALLENGE structure defines the client challenge in the AUTHENTICATE_MESSAGE.
|
|
// This structure is used only when NTLM v2 authentication is configured.
|
|
type NtlmV2ClientChallenge struct {
|
|
// An 8-bit unsigned char that contains the current version of the challenge response type.
|
|
// This field MUST be 0x01.
|
|
RespType byte
|
|
// An 8-bit unsigned char that contains the maximum supported version of the challenge response type.
|
|
// This field MUST be 0x01.
|
|
HiRespType byte
|
|
// A 16-bit unsigned integer that SHOULD be 0x0000 and MUST be ignored on receipt.
|
|
Reserved1 uint16
|
|
// A 32-bit unsigned integer that SHOULD be 0x00000000 and MUST be ignored on receipt.
|
|
Reserved2 uint32
|
|
// A 64-bit unsigned integer that contains the current system time, represented as the number of 100 nanosecond
|
|
// ticks elapsed since midnight of January 1, 1601 (UTC).
|
|
TimeStamp []byte
|
|
// An 8-byte array of unsigned char that contains the client's ClientChallenge (section 3.1.5.1.2).
|
|
ChallengeFromClient []byte
|
|
// A 32-bit unsigned integer that SHOULD be 0x00000000 and MUST be ignored on receipt.
|
|
Reserved3 uint32
|
|
AvPairs *AvPairs
|
|
}
|
|
|
|
func (n *NtlmV2ClientChallenge) String() string {
|
|
var buffer bytes.Buffer
|
|
|
|
buffer.WriteString("NTLM v2 ClientChallenge\n")
|
|
buffer.WriteString(fmt.Sprintf("Timestamp: %s\n", hex.EncodeToString(n.TimeStamp)))
|
|
buffer.WriteString(fmt.Sprintf("ChallengeFromClient: %s\n", hex.EncodeToString(n.ChallengeFromClient)))
|
|
buffer.WriteString("AvPairs\n")
|
|
buffer.WriteString(n.AvPairs.String())
|
|
|
|
return buffer.String()
|
|
}
|
|
|
|
// The NTLMv2_RESPONSE structure defines the NTLMv2 authentication NtChallengeResponse in the AUTHENTICATE_MESSAGE.
|
|
// This response is used only when NTLMv2 authentication is configured.
|
|
type NtlmV2Response struct {
|
|
// A 16-byte array of unsigned char that contains the client's NT challenge- response as defined in section 3.3.2.
|
|
// Response corresponds to the NTProofStr variable from section 3.3.2.
|
|
Response []byte
|
|
// A variable-length byte array that contains the ClientChallenge as defined in section 3.3.2.
|
|
// ChallengeFromClient corresponds to the temp variable from section 3.3.2.
|
|
NtlmV2ClientChallenge *NtlmV2ClientChallenge
|
|
}
|
|
|
|
func (n *NtlmV2Response) String() string {
|
|
var buffer bytes.Buffer
|
|
|
|
buffer.WriteString("NTLM v2 Response\n")
|
|
buffer.WriteString(fmt.Sprintf("Response: %s\n", hex.EncodeToString(n.Response)))
|
|
buffer.WriteString(n.NtlmV2ClientChallenge.String())
|
|
|
|
return buffer.String()
|
|
}
|
|
|
|
func ReadNtlmV2Response(bytes []byte) (*NtlmV2Response, error) {
|
|
r := new(NtlmV2Response)
|
|
r.Response = bytes[0:16]
|
|
r.NtlmV2ClientChallenge = new(NtlmV2ClientChallenge)
|
|
c := r.NtlmV2ClientChallenge
|
|
c.RespType = bytes[16]
|
|
c.HiRespType = bytes[17]
|
|
|
|
if c.RespType != 1 || c.HiRespType != 1 {
|
|
return nil, errors.New("Does not contain a valid NTLM v2 client challenge - could be NTLMv1.")
|
|
}
|
|
|
|
// Ignoring - 2 bytes reserved
|
|
// c.Reserved1
|
|
// Ignoring - 4 bytes reserved
|
|
// c.Reserved2
|
|
c.TimeStamp = bytes[24:32]
|
|
c.ChallengeFromClient = bytes[32:40]
|
|
// Ignoring - 4 bytes reserved
|
|
// c.Reserved3
|
|
c.AvPairs = ReadAvPairs(bytes[44:])
|
|
return r, nil
|
|
}
|
|
|
|
// LMv1
|
|
// ****
|
|
type LmV1Response struct {
|
|
// 24 bytes
|
|
Response []byte
|
|
}
|
|
|
|
func ReadLmV1Response(bytes []byte) *LmV1Response {
|
|
r := new(LmV1Response)
|
|
r.Response = bytes[0:24]
|
|
return r
|
|
}
|
|
|
|
func (l *LmV1Response) String() string {
|
|
return fmt.Sprintf("LmV1Response: %s", hex.EncodeToString(l.Response))
|
|
}
|
|
|
|
// *** LMv2
|
|
type LmV2Response struct {
|
|
// A 16-byte array of unsigned char that contains the client's LM challenge-response.
|
|
// This is the portion of the LmChallengeResponse field to which the HMAC_MD5 algorithm
|
|
/// has been applied, as defined in section 3.3.2. Specifically, Response corresponds
|
|
// to the result of applying the HMAC_MD5 algorithm, using the key ResponseKeyLM, to a
|
|
// message consisting of the concatenation of the ResponseKeyLM, ServerChallenge and ClientChallenge.
|
|
Response []byte
|
|
// An 8-byte array of unsigned char that contains the client's ClientChallenge, as defined in section 3.1.5.1.2.
|
|
ChallengeFromClient []byte
|
|
}
|
|
|
|
func ReadLmV2Response(bytes []byte) *LmV2Response {
|
|
r := new(LmV2Response)
|
|
r.Response = bytes[0:16]
|
|
r.ChallengeFromClient = bytes[16:24]
|
|
return r
|
|
}
|
|
|
|
func (l *LmV2Response) String() string {
|
|
var buffer bytes.Buffer
|
|
|
|
buffer.WriteString("LM v2 Response\n")
|
|
buffer.WriteString(fmt.Sprintf("Response: %s\n", hex.EncodeToString(l.Response)))
|
|
buffer.WriteString(fmt.Sprintf("ChallengeFromClient: %s\n", hex.EncodeToString(l.ChallengeFromClient)))
|
|
|
|
return buffer.String()
|
|
}
|