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:
@@ -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
|
||||||
}
|
|
||||||
|
|
||||||
m.NegotiateFlags = negotiateFlagNTLMSSPREQUESTTARGET |
|
if domainName != "" {
|
||||||
negotiateFlagNTLMSSPNEGOTIATENTLM |
|
flags |= negotiateFlagNTLMSSPNEGOTIATEOEMDOMAINSUPPLIED
|
||||||
negotiateFlagNTLMSSPNEGOTIATEALWAYSSIGN |
|
}
|
||||||
negotiateFlagNTLMSSPNEGOTIATEUNICODE
|
|
||||||
|
|
||||||
b := bytes.Buffer{}
|
if workstationName != "" {
|
||||||
err := binary.Write(&b, binary.LittleEndian, &m)
|
flags |= negotiateFlagNTLMSSPNEGOTIATEOEMWORKSTATIONSUPPLIED
|
||||||
if err != nil {
|
}
|
||||||
panic(err)
|
|
||||||
}
|
msg := negotiateMessageFields{
|
||||||
return b.Bytes()
|
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
|
||||||
}
|
}
|
||||||
|
@@ -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,9 +77,21 @@ func (l Negotiator) RoundTrip(req *http.Request) (res *http.Response, err error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// send negotiate
|
// parse domain name from username
|
||||||
negotiateMessage := NewNegotiateMessage()
|
domain := ""
|
||||||
if resauth.IsNTLM() {
|
|
||||||
|
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))
|
req.Header.Set("Authorization", "NTLM "+base64.StdEncoding.EncodeToString(negotiateMessage))
|
||||||
} else {
|
} else {
|
||||||
req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(negotiateMessage))
|
req.Header.Set("Authorization", "Negotiate "+base64.StdEncoding.EncodeToString(negotiateMessage))
|
||||||
|
20
version.go
Normal file
20
version.go
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user