package  ntlm 
 
import  ( 
	"bytes"  
	"crypto/rc4"  
	"errors"  
 
	"github.com/hirochachacha/go-smb2/internal/utf16le"  
) 
 
type  Session  struct  { 
	isClientSide bool  
 
	user string  
 
	negotiateFlags     uint32  
	exportedSessionKey []byte  
	clientSigningKey   []byte  
	serverSigningKey   []byte  
 
	clientHandle *rc4 .Cipher  
	serverHandle *rc4 .Cipher  
 
	infoMap map [uint16 ][]byte  
} 
 
func  (s  *Session ) User () string  { 
	return  s .user  
} 
 
func  (s  *Session ) SessionKey () []byte  { 
	return  s .exportedSessionKey  
} 
 
type  InfoMap  struct  { 
	NbComputerName  string  
	NbDomainName    string  
	DnsComputerName string  
	DnsDomainName   string  
	DnsTreeName     string  
	 
 
 
 
 
} 
 
 
func  (s  *Session ) InfoMap () *InfoMap  { 
	return  &InfoMap { 
		NbComputerName :  utf16le .DecodeToString (s .infoMap [MsvAvNbComputerName ]), 
		NbDomainName :    utf16le .DecodeToString (s .infoMap [MsvAvNbDomainName ]), 
		DnsComputerName : utf16le .DecodeToString (s .infoMap [MsvAvDnsComputerName ]), 
		DnsDomainName :   utf16le .DecodeToString (s .infoMap [MsvAvDnsDomainName ]), 
		DnsTreeName :     utf16le .DecodeToString (s .infoMap [MsvAvDnsTreeName ]), 
		 
	} 
} 
 
func  (s  *Session ) Overhead () int  { 
	return  16  
} 
 
func  (s  *Session ) Sum (plaintext  []byte , seqNum  uint32 ) ([]byte , uint32 ) { 
	if  s .negotiateFlags &NTLMSSP_NEGOTIATE_SIGN  == 0  { 
		return  nil , 0  
	} 
 
	if  s .isClientSide  { 
		return  mac (nil , s .negotiateFlags , s .clientHandle , s .clientSigningKey , seqNum , plaintext ) 
	} 
	return  mac (nil , s .negotiateFlags , s .serverHandle , s .serverSigningKey , seqNum , plaintext ) 
} 
 
func  (s  *Session ) CheckSum (sum , plaintext  []byte , seqNum  uint32 ) (bool , uint32 ) { 
	if  s .negotiateFlags &NTLMSSP_NEGOTIATE_SIGN  == 0  { 
		if  sum  == nil  { 
			return  true , 0  
		} 
		return  false , 0  
	} 
 
	if  s .isClientSide  { 
		ret , seqNum  := mac (nil , s .negotiateFlags , s .serverHandle , s .serverSigningKey , seqNum , plaintext ) 
		if  !bytes .Equal (sum , ret ) { 
			return  false , 0  
		} 
		return  true , seqNum  
	} 
	ret , seqNum  := mac (nil , s .negotiateFlags , s .clientHandle , s .clientSigningKey , seqNum , plaintext ) 
	if  !bytes .Equal (sum , ret ) { 
		return  false , 0  
	} 
	return  true , seqNum  
} 
 
func  (s  *Session ) Seal (dst , plaintext  []byte , seqNum  uint32 ) ([]byte , uint32 ) { 
	ret , ciphertext  := sliceForAppend (dst , len (plaintext )+16 ) 
 
	switch  { 
	case  s .negotiateFlags &NTLMSSP_NEGOTIATE_SEAL  != 0 : 
		s .clientHandle .XORKeyStream (ciphertext [16 :], plaintext ) 
 
		if  s .isClientSide  { 
			_, seqNum  = mac (ciphertext [:0 ], s .negotiateFlags , s .clientHandle , s .clientSigningKey , seqNum , plaintext ) 
		} else  { 
			_, seqNum  = mac (ciphertext [:0 ], s .negotiateFlags , s .serverHandle , s .serverSigningKey , seqNum , plaintext ) 
		} 
	case  s .negotiateFlags &NTLMSSP_NEGOTIATE_SIGN  != 0 : 
		copy (ciphertext [16 :], plaintext ) 
 
		if  s .isClientSide  { 
			_, seqNum  = mac (ciphertext [:0 ], s .negotiateFlags , s .clientHandle , s .clientSigningKey , seqNum , plaintext ) 
		} else  { 
			_, seqNum  = mac (ciphertext [:0 ], s .negotiateFlags , s .serverHandle , s .serverSigningKey , seqNum , plaintext ) 
		} 
	} 
 
	return  ret , seqNum  
} 
 
func  (s  *Session ) Unseal (dst , ciphertext  []byte , seqNum  uint32 ) ([]byte , uint32 , error ) { 
	ret , plaintext  := sliceForAppend (dst , len (ciphertext )-16 ) 
 
	switch  { 
	case  s .negotiateFlags &NTLMSSP_NEGOTIATE_SEAL  != 0 : 
		s .serverHandle .XORKeyStream (plaintext , ciphertext [16 :]) 
 
		var  sum  []byte  
 
		if  s .isClientSide  { 
			sum , seqNum  = mac (nil , s .negotiateFlags , s .serverHandle , s .serverSigningKey , seqNum , plaintext ) 
		} else  { 
			sum , seqNum  = mac (nil , s .negotiateFlags , s .clientHandle , s .clientSigningKey , seqNum , plaintext ) 
		} 
		if  !bytes .Equal (ciphertext [:16 ], sum ) { 
			return  nil , 0 , errors .New ("signature mismatch" ) 
		} 
	case  s .negotiateFlags &NTLMSSP_NEGOTIATE_SIGN  != 0 : 
		copy (plaintext , ciphertext [16 :]) 
 
		var  sum  []byte  
 
		if  s .isClientSide  { 
			sum , seqNum  = mac (nil , s .negotiateFlags , s .serverHandle , s .serverSigningKey , seqNum , plaintext ) 
		} else  { 
			sum , seqNum  = mac (nil , s .negotiateFlags , s .clientHandle , s .clientSigningKey , seqNum , plaintext ) 
		} 
		if  !bytes .Equal (ciphertext [:16 ], sum ) { 
			return  nil , 0 , errors .New ("signature mismatch" ) 
		} 
	default : 
		copy (plaintext , ciphertext [16 :]) 
		for  _ , s  := range  ciphertext [:16 ] { 
			if  s  != 0x0  { 
				return  nil , 0 , errors .New ("signature mismatch" ) 
			} 
		} 
	} 
 
	return  ret , seqNum , nil  
} 
  
The pages are generated with Golds   v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds  is a Go 101  project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1  (reachable from the left QR code) to get the latest news of Golds .