add version, domain and workstation fields

Add version support from jh125486
Add workstation and domain support from jh125486
Enable to extract domain from username
This commit is contained in:
Dan
2018-04-12 18:05:24 +01:00
committed by GitHub
parent c92175d540
commit df1f808002
3 changed files with 84 additions and 19 deletions

View File

@@ -3,29 +3,61 @@ package ntlmssp
import ( import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"errors"
"strings"
) )
const expMsgBodyLen = 40
type negotiateMessageFields struct { type negotiateMessageFields struct {
messageHeader messageHeader
NegotiateFlags negotiateFlags NegotiateFlags negotiateFlags
Domain varField
Workstation varField
Version
} }
var defaultFlags = negotiateFlagNTLMSSPNEGOTIATETARGETINFO |
negotiateFlagNTLMSSPNEGOTIATE56 |
negotiateFlagNTLMSSPNEGOTIATE128 |
negotiateFlagNTLMSSPNEGOTIATEUNICODE
//NewNegotiateMessage creates a new NEGOTIATE message with the //NewNegotiateMessage creates a new NEGOTIATE message with the
//flags that this package supports. //flags that this package supports.
func NewNegotiateMessage() []byte { func NewNegotiateMessage(domainName, workstationName string) ([]byte, error) {
m := negotiateMessageFields{ payloadOffset := expMsgBodyLen
messageHeader: newMessageHeader(1), flags := defaultFlags
if domainName != "" {
flags |= negotiateFlagNTLMSSPNEGOTIATEOEMDOMAINSUPPLIED
} }
m.NegotiateFlags = negotiateFlagNTLMSSPREQUESTTARGET | if workstationName != "" {
negotiateFlagNTLMSSPNEGOTIATENTLM | flags |= negotiateFlagNTLMSSPNEGOTIATEOEMWORKSTATIONSUPPLIED
negotiateFlagNTLMSSPNEGOTIATEALWAYSSIGN | }
negotiateFlagNTLMSSPNEGOTIATEUNICODE
msg := negotiateMessageFields{
messageHeader: newMessageHeader(1),
NegotiateFlags: flags,
Domain: newVarField(&payloadOffset, len(domainName)),
Workstation: newVarField(&payloadOffset, len(workstationName)),
Version: DefaultVersion(),
}
b := bytes.Buffer{} b := bytes.Buffer{}
err := binary.Write(&b, binary.LittleEndian, &m) if err := binary.Write(&b, binary.LittleEndian, &msg); err != nil {
if err != nil { return nil, err
panic(err)
} }
return b.Bytes() if b.Len() != expMsgBodyLen {
return nil, errors.New("incorrect body length")
}
payload := strings.ToUpper(domainName + workstationName)
if _, err := b.WriteString(payload); err != nil {
return nil, err
}
return b.Bytes(), nil
} }

View File

@@ -6,6 +6,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strings"
) )
//Negotiator is a http.Roundtripper decorator that automatically //Negotiator is a http.Roundtripper decorator that automatically
@@ -76,8 +77,20 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
return nil, err return nil, err
} }
// parse domain name from username
domain := ""
if strings.Contains(u, "\\") {
u_components := strings.Split(u, "\\")
domain = u_components[0]
u = u_components[1]
}
// send negotiate // send negotiate
negotiateMessage := NewNegotiateMessage() negotiateMessage, err := NewNegotiateMessage(domain, "")
if err != nil {
return nil, err
}
if resauth.IsNTLM() { if resauth.IsNTLM() {
req.Header.Set("Authorization", "NTLM "+base64.StdEncoding.EncodeToString(negotiateMessage)) req.Header.Set("Authorization", "NTLM "+base64.StdEncoding.EncodeToString(negotiateMessage))
} else { } else {

20
version.go Normal file
View File

@@ -0,0 +1,20 @@
package ntlmssp
// Version is a struct representing https://msdn.microsoft.com/en-us/library/cc236654.aspx
type Version struct {
ProductMajorVersion uint8
ProductMinorVersion uint8
ProductBuild uint16
_ [3]byte
NTLMRevisionCurrent uint8
}
// DefaultVersion returns a Version with "sensible" defaults (Windows 7)
func DefaultVersion() Version {
return Version{
ProductMajorVersion: 6,
ProductMinorVersion: 1,
ProductBuild: 7601,
NTLMRevisionCurrent: 15,
}
}