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 (
"bytes"
"encoding/binary"
"errors"
"strings"
)
const expMsgBodyLen = 40
type negotiateMessageFields struct {
messageHeader
NegotiateFlags negotiateFlags
messageHeader
NegotiateFlags negotiateFlags
Domain varField
Workstation varField
Version
}
var defaultFlags = negotiateFlagNTLMSSPNEGOTIATETARGETINFO |
negotiateFlagNTLMSSPNEGOTIATE56 |
negotiateFlagNTLMSSPNEGOTIATE128 |
negotiateFlagNTLMSSPNEGOTIATEUNICODE
//NewNegotiateMessage creates a new NEGOTIATE message with the
//flags that this package supports.
func NewNegotiateMessage() []byte {
m := negotiateMessageFields{
messageHeader: newMessageHeader(1),
}
func NewNegotiateMessage(domainName, workstationName string) ([]byte, error) {
payloadOffset := expMsgBodyLen
flags := defaultFlags
m.NegotiateFlags = negotiateFlagNTLMSSPREQUESTTARGET |
negotiateFlagNTLMSSPNEGOTIATENTLM |
negotiateFlagNTLMSSPNEGOTIATEALWAYSSIGN |
negotiateFlagNTLMSSPNEGOTIATEUNICODE
if domainName != "" {
flags |= negotiateFlagNTLMSSPNEGOTIATEOEMDOMAINSUPPLIED
}
b := bytes.Buffer{}
err := binary.Write(&b, binary.LittleEndian, &m)
if err != nil {
panic(err)
}
return b.Bytes()
if workstationName != "" {
flags |= negotiateFlagNTLMSSPNEGOTIATEOEMWORKSTATIONSUPPLIED
}
msg := negotiateMessageFields{
messageHeader: newMessageHeader(1),
NegotiateFlags: flags,
Domain: newVarField(&payloadOffset, len(domainName)),
Workstation: newVarField(&payloadOffset, len(workstationName)),
Version: DefaultVersion(),
}
b := bytes.Buffer{}
if err := binary.Write(&b, binary.LittleEndian, &msg); err != nil {
return nil, err
}
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/ioutil"
"net/http"
"strings"
)
//Negotiator is a http.Roundtripper decorator that automatically
@@ -76,9 +77,21 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
return nil, err
}
// send negotiate
negotiateMessage := NewNegotiateMessage()
if resauth.IsNTLM() {
// 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
negotiateMessage, err := NewNegotiateMessage(domain, "")
if err != nil {
return nil, err
}
if resauth.IsNTLM() {
req.Header.Set("Authorization", "NTLM "+base64.StdEncoding.EncodeToString(negotiateMessage))
} else {
req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(negotiateMessage))

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,
}
}