| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- package gss
- import (
- "encoding/asn1"
- "fmt"
- "log"
- "imuslab.com/smb/driver/mod/smb/encoder"
- )
- // https://www.rfc-editor.org/rfc/rfc4178.html#section-4.1
- type MechTypeOid string
- const SpnegoOid = "1.3.6.1.5.5.2"
- const NtLmSSPMechTypeOid MechTypeOid = "1.3.6.1.4.1.311.2.2.10"
- // const KRB5SSPMechTypeOid MechTypeOid = "1.3.6.1.5.2.5"
- const GssStateAcceptCompleted = 0
- const GssStateAcceptIncomplete = 1
- const GssStateReject = 2
- const GssStateRequestMic = 3
- type NegTokenInitData struct {
- MechTypes []asn1.ObjectIdentifier `asn1:"explicit,tag:0"`
- ReqFlags asn1.BitString `asn1:"explicit,optional,omitempty,tag:1"`
- MechToken []byte `asn1:"explicit,optional,omitempty,tag:2"`
- MechTokenMIC []byte `asn1:"explicit,optional,omitempty,tag:3"`
- }
- type NegTokenInit struct {
- OID asn1.ObjectIdentifier
- Data NegTokenInitData `asn1:"explicit"`
- }
- type NegState int
- const (
- Accept_completed NegState = 0
- Accept_incomplete NegState = 1
- Reject NegState = 2
- Request_mic NegState = 3
- )
- type NegTokenResp struct {
- NegResult asn1.Enumerated `asn1:"explicit,optional,omitempty,tag:0"` //NegState
- SupportedMech asn1.ObjectIdentifier `asn1:"explicit,optional,omitempty,tag:1"`
- ResponseToken []byte `asn1:"explicit,optional,omitempty,tag:2"`
- MechListMIC []byte `asn1:"explicit,optional,omitempty,tag:3"`
- }
- // gsswrapped used to force ASN1 encoding to include explicit sequence tags
- // Type does not fulfill the BinaryMarshallable interfce and is used only as a
- // helper to marshal a NegTokenResp
- type gsswrapped struct{ G interface{} }
- func NewNegTokenInit(MechType MechTypeOid) (*NegTokenInit, error) {
- oid, err := ObjectIDStrToInt(SpnegoOid)
- if err != nil {
- return &NegTokenInit{}, err
- }
- mechType, err := ObjectIDStrToInt(MechType)
- if err != nil {
- return &NegTokenInit{}, err
- }
- return &NegTokenInit{
- OID: oid,
- Data: NegTokenInitData{
- MechTypes: []asn1.ObjectIdentifier{mechType},
- ReqFlags: asn1.BitString{},
- MechToken: []byte{},
- MechTokenMIC: []byte{},
- },
- }, nil
- }
- func NewNegTokenResp() *NegTokenResp {
- return &NegTokenResp{}
- }
- var _ encoder.BinaryMarshallable = (*NegTokenInit)(nil)
- func (n *NegTokenInit) MarshalBinary(meta *encoder.Metadata) ([]byte, error) {
- buf, err := asn1.Marshal(*n)
- if err != nil {
- log.Panicln(err)
- return nil, err
- }
- // When marshalling struct, asn1 uses 30 (sequence) tag by default.
- // Override to set 60 (application) to remain consistent with GSS/SMB
- buf[0] = 0x60
- return buf, nil
- }
- func (n *NegTokenInit) UnmarshalBinary(buf []byte, meta *encoder.Metadata) (interface{}, error) {
- data := NegTokenInit{}
- if _, err := asn1.UnmarshalWithParams(buf, &data, "application"); err != nil {
- return nil, err
- }
- *n = data
- return nil, nil
- }
- var _ encoder.BinaryMarshallable = (*NegTokenInit)(nil)
- func (r *NegTokenResp) MarshalBinary(meta *encoder.Metadata) ([]byte, error) {
- // Oddities in Go's ASN1 package vs SMB encoding mean we have to wrap our
- // struct in another struct to ensure proper tags and lengths are added
- // to encoded data
- wrapped := &gsswrapped{*r}
- ans, _ := wrapped.MarshalBinary(meta)
- fmt.Println("MAR", meta, ans)
- //return wrapped.MarshalBinary(meta)
- ans, err := wrapped.MarshalBinary(meta)
- if len(ans) == 4 && ans[0] == 0xa1 && ans[1] == 0x02 && ans[2] == 0x30 && ans[3] == 00 {
- return []byte{0xa1, 0x07, 0x30, 0x05, 0xa0, 0x03, 0x0a, 0x01, 0x00}, nil
- }
- return ans, err
- //return []byte{0xa1, 0x07, 0x30, 0x05, 0xa0, 0x03, 0x0a, 0x01, 0x00}, nil
- }
- func (r *NegTokenResp) UnmarshalBinary(buf []byte, meta *encoder.Metadata) (interface{}, error) {
- data := NegTokenResp{}
- if _, err := asn1.UnmarshalWithParams(buf, &data, "explicit,tag:1"); err != nil {
- return nil, err
- }
- *r = data
- return nil, nil
- }
- func (g *gsswrapped) MarshalBinary(meta *encoder.Metadata) ([]byte, error) {
- buf, err := asn1.Marshal(*g)
- if err != nil {
- return nil, err
- }
- buf[0] = 0xa1
- return buf, nil
- }
|