func (c *ClientContext) EncryptMessage(msg []byte, qop, seqno uint32) ([]byte, error) {
	return common.EncryptMessage(c.sctxt, msg, qop, seqno)
}
EncryptMessage uses the established client context to encrypt a message
using the provided quality of protection flags and sequence number.
It returns the signature token in addition to any error.
IMPORTANT: the input msg parameter is updated in place by the low-level windows api
so must be copied if the initial content should not be modified.
package negotiate
import (
	"errors"
	"syscall"
	"time"
	"unsafe"
	"github.com/alexbrainman/sspi"
	"github.com/alexbrainman/sspi/internal/common"
)
var PackageInfo *sspi.PackageInfo
func init() {
	var err error
	PackageInfo, err = sspi.QueryPackageInfo(sspi.NEGOSSP_NAME)
	if err != nil {
		panic("failed to fetch Negotiate package info: " + err.Error())
	}
}
func acquireCredentials(principalName string, creduse uint32, ai *sspi.SEC_WINNT_AUTH_IDENTITY) (*sspi.Credentials, error) {
	c, err := sspi.AcquireCredentials(principalName, sspi.NEGOSSP_NAME, creduse, (*byte)(unsafe.Pointer(ai)))
	if err != nil {
		return nil, err
	}
	return c, nil
}
func AcquireCurrentUserCredentials() (*sspi.Credentials, error) {
	return acquireCredentials("", sspi.SECPKG_CRED_OUTBOUND, nil)
}
func AcquireUserCredentials(domain, username, password string) (*sspi.Credentials, error) {
	ai, err := common.BuildAuthIdentity(domain, username, password)
	if err != nil {
		return nil, err
	}
	return acquireCredentials("", sspi.SECPKG_CRED_OUTBOUND, ai)
}
func AcquireServerCredentials(principalName string) (*sspi.Credentials, error) {
	return acquireCredentials(principalName, sspi.SECPKG_CRED_INBOUND, nil)
}
type ClientContext struct {
	sctxt      *sspi.Context
	targetName *uint16
}
func NewClientContext(cred *sspi.Credentials, targetName string) (cc *ClientContext, outputToken []byte, err error) {
	return NewClientContextWithFlags(cred, targetName, sspi.ISC_REQ_CONNECTION)
}
func NewClientContextWithFlags(cred *sspi.Credentials, targetName string, flags uint32) (cc *ClientContext, outputToken []byte, err error) {
	var tname *uint16
	if len(targetName) > 0 {
		p, err2 := syscall.UTF16FromString(targetName)
		if err2 != nil {
			return nil, nil, err2
		}
		if len(p) > 0 {
			tname = &p[0]
		}
	}
	otoken := make([]byte, PackageInfo.MaxToken)
	c := sspi.NewClientContext(cred, flags)
	authCompleted, n, err2 := common.UpdateContext(c, otoken, nil, tname)
	if err2 != nil {
		return nil, nil, err2
	}
	if authCompleted {
		c.Release()
		return nil, nil, errors.New("negotiate authentication should not be completed yet")
	}
	if n == 0 {
		c.Release()
		return nil, nil, errors.New("negotiate token should not be empty")
	}
	otoken = otoken[:n]
	return &ClientContext{sctxt: c, targetName: tname}, otoken, nil
}
func (c *ClientContext) Release() error {
	if c == nil {
		return nil
	}
	return c.sctxt.Release()
}
func (c *ClientContext) Expiry() time.Time {
	return c.sctxt.Expiry()
}
func (c *ClientContext) Update(token []byte) (authCompleted bool, outputToken []byte, err error) {
	otoken := make([]byte, PackageInfo.MaxToken)
	authDone, n, err2 := common.UpdateContext(c.sctxt, otoken, token, c.targetName)
	if err2 != nil {
		return false, nil, err2
	}
	if n == 0 && !authDone {
		return false, nil, errors.New("negotiate token should not be empty")
	}
	otoken = otoken[:n]
	return authDone, otoken, nil
}
func (c *ClientContext) Sizes() (uint32, uint32, uint32, uint32, error) {
	return c.sctxt.Sizes()
}
func (c *ClientContext) MakeSignature(msg []byte, qop, seqno uint32) ([]byte, error) {
	return common.MakeSignature(c.sctxt, msg, qop, seqno)
}
func (c *ClientContext) VerifySignature(msg, token []byte, seqno uint32) (uint32, error) {
	return common.VerifySignature(c.sctxt, msg, token, seqno)
}