github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/upstreamproxy/go-ntlm/ntlm/negotiate_flags.go (about)

     1  //Copyright 2013 Thomson Reuters Global Resources. BSD License please see License file for more information
     2  
     3  package ntlm
     4  
     5  // During NTLM authentication, each of the following flags is a possible value of the NegotiateFlags field of the NEGOTIATE_MESSAGE,
     6  // CHALLENGE_MESSAGE, and AUTHENTICATE_MESSAGE, unless otherwise noted. These flags define client or server NTLM capabilities
     7  // ssupported by the sender.
     8  
     9  import (
    10  	"bytes"
    11  	"fmt"
    12  	"reflect"
    13  )
    14  
    15  type NegotiateFlag uint32
    16  
    17  const (
    18  	// A (1 bit): If set, requests Unicode character set encoding. An alternate name for this field is NTLMSSP_NEGOTIATE_UNICODE.
    19  	NTLMSSP_NEGOTIATE_UNICODE NegotiateFlag = 1 << iota
    20  	// B (1 bit): If set, requests OEM character set encoding. An alternate name for this field is NTLM_NEGOTIATE_OEM. See bit A for details.
    21  	NTLM_NEGOTIATE_OEM
    22  	// The A and B bits are evaluated together as follows:
    23  	// A==1: The choice of character set encoding MUST be Unicode.
    24  	// A==0 and B==1: The choice of character set encoding MUST be OEM.
    25  	// A==0 and B==0: The protocol MUST return SEC_E_INVALID_TOKEN.
    26  	// C (1 bit): If set, a TargetName field of the CHALLENGE_MESSAGE (section 2.2.1.2) MUST be supplied. An alternate name for this field is NTLMSSP_REQUEST_TARGET.
    27  	NTLMSSP_REQUEST_TARGET
    28  	// r10 (1 bit): This bit is unused and MUST be zero.
    29  	NTLMSSP_R10
    30  	// D (1 bit): If set, requests session key negotiation for message signatures. If the client sends NTLMSSP_NEGOTIATE_SIGN to the server
    31  	// in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SIGN to the client in the CHALLENGE_MESSAGE. An alternate name
    32  	// for this field is NTLMSSP_NEGOTIATE_SIGN.
    33  	NTLMSSP_NEGOTIATE_SIGN
    34  	// E (1 bit): If set, requests session key negotiation for message confidentiality. If the client sends NTLMSSP_NEGOTIATE_SEAL
    35  	// to the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SEAL to the client in the CHALLENGE_MESSAGE.
    36  	// Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD always set NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128,
    37  	// if they are supported. An alternate name for this field is NTLMSSP_NEGOTIATE_SEAL.
    38  	NTLMSSP_NEGOTIATE_SEAL
    39  	// F (1 bit): If set, requests connectionless authentication. If NTLMSSP_NEGOTIATE_DATAGRAM is set, then NTLMSSP_NEGOTIATE_KEY_EXCH
    40  	// MUST always be set in the AUTHENTICATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate name for
    41  	// this field is NTLMSSP_NEGOTIATE_DATAGRAM.
    42  	NTLMSSP_NEGOTIATE_DATAGRAM
    43  	// G (1 bit): If set, requests LAN Manager (LM) session key computation. NTLMSSP_NEGOTIATE_LM_KEY and NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
    44  	// are mutually exclusive. If both NTLMSSP_NEGOTIATE_LM_KEY and NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are requested,
    45  	// NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be returned to the client. NTLM v2 authentication session key generation
    46  	// MUST be supported by both the client and the DC in order to be used, and extended session security signing and sealing requires
    47  	// support from the client and the server to be used. An alternate name for this field is NTLMSSP_NEGOTIATE_LM_KEY.
    48  	NTLMSSP_NEGOTIATE_LM_KEY
    49  	// r9 (1 bit): This bit is unused and MUST be zero.
    50  	NTLMSSP_R9
    51  	// H (1 bit): If set, requests usage of the NTLM v1 session security protocol. NTLMSSP_NEGOTIATE_NTLM MUST be set in the
    52  	// NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate name for this field is NTLMSSP_NEGOTIATE_NTLM.
    53  	NTLMSSP_NEGOTIATE_NTLM
    54  	// r8 (1 bit): This bit is unused and MUST be zero.
    55  	NTLMSSP_R8
    56  	// J (1 bit): If set, the connection SHOULD be anonymous.<26> r8 (1 bit): This bit is unused and SHOULD be zero.<27>
    57  	NTLMSSP_ANONYMOUS
    58  	// K (1 bit): If set, the domain name is provided (section 2.2.1.1).<25> An alternate name for this field is NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED.
    59  	NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
    60  	// L (1 bit): This flag indicates whether the Workstation field is present. If this flag is not set, the Workstation field
    61  	// MUST be ignored. If this flag is set, the length field of the Workstation field specifies whether the workstation name
    62  	// is nonempty or not.<24> An alternate name for this field is NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED.
    63  	NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED
    64  	// r7 (1 bit): This bit is unused and MUST be zero.
    65  	NTLMSSP_R7
    66  	// M (1 bit): If set, requests the presence of a signature block on all  NTLMSSP_NEGOTIATE_ALWAYS_SIGN MUST be
    67  	// set in the NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. NTLMSSP_NEGOTIATE_ALWAYS_SIGN is
    68  	// overridden by NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_SEAL, if they are supported. An alternate name for this field
    69  	// is NTLMSSP_NEGOTIATE_ALWAYS_SIGN.
    70  	NTLMSSP_NEGOTIATE_ALWAYS_SIGN
    71  	// N (1 bit): If set, TargetName MUST be a domain name. The data corresponding to this flag is provided by the server in the
    72  	// TargetName field of the CHALLENGE_MESSAGE. If set, then NTLMSSP_TARGET_TYPE_SERVER MUST NOT be set. This flag MUST be ignored
    73  	// in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field is NTLMSSP_TARGET_TYPE_DOMAIN.
    74  	NTLMSSP_TARGET_TYPE_DOMAIN
    75  	// O (1 bit): If set, TargetName MUST be a server name. The data corresponding to this flag is provided by the server in the
    76  	// TargetName field of the CHALLENGE_MESSAGE. If this bit is set, then NTLMSSP_TARGET_TYPE_DOMAIN MUST NOT be set. This flag MUST
    77  	// be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field is NTLMSSP_TARGET_TYPE_SERVER.
    78  	NTLMSSP_TARGET_TYPE_SERVER
    79  	// r6 (1 bit): This bit is unused and MUST be zero.
    80  	NTLMSSP_R6
    81  	// P (1 bit): If set, requests usage of the NTLM v2 session security. NTLM v2 session security is a misnomer because it is not
    82  	// NTLM v2. It is NTLM v1 using the extended session security that is also in NTLM v2. NTLMSSP_NEGOTIATE_LM_KEY and
    83  	// NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY and
    84  	// NTLMSSP_NEGOTIATE_LM_KEY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be returned to the client.
    85  	// NTLM v2 authentication session key generation MUST be supported by both the client and the DC in order to be used, and extended
    86  	// session security signing and sealing requires support from the client and the server in order to be used.<23> An alternate name
    87  	// for this field is NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY.
    88  	NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
    89  	// Q (1 bit): If set, requests an identify level token. An alternate name for this field is NTLMSSP_NEGOTIATE_IDENTIFY.
    90  	NTLMSSP_NEGOTIATE_IDENTIFY
    91  	// r5 (1 bit): This bit is unused and MUST be zero.
    92  	NTLMSSP_R5
    93  	// R (1 bit): If set, requests the usage of the LMOWF (section 3.3). An alternate name for this field is NTLMSSP_REQUEST_NON_NT_SESSION_KEY.
    94  	NTLMSSP_REQUEST_NON_NT_SESSION_KEY
    95  	// S (1 bit): If set, indicates that the TargetInfo fields in the CHALLENGE_MESSAGE (section 2.2.1.2) are populated. An alternate
    96  	// name for this field is NTLMSSP_NEGOTIATE_TARGET_INFO.
    97  	NTLMSSP_NEGOTIATE_TARGET_INFO
    98  	//  r4 (1 bit): This bit is unused and MUST be zero.
    99  	NTLMSSP_R4
   100  	// T (1 bit): If set, requests the protocol version number. The data corresponding to this flag is provided in the Version field of the
   101  	// NEGOTIATE_MESSAGE, the CHALLENGE_MESSAGE, and the AUTHENTICATE_MESSAGE.<22> An alternate name for this field is NTLMSSP_NEGOTIATE_VERSION.
   102  	NTLMSSP_NEGOTIATE_VERSION
   103  	// r3 (1 bit): This bit is unused and MUST be zero.
   104  	NTLMSSP_R3
   105  	// r2 (1 bit): This bit is unused and MUST be zero.
   106  	NTLMSSP_R2
   107  	// r1 (1 bit): This bit is unused and MUST be zero.
   108  	NTLMSSP_R1
   109  	// U (1 bit): If set, requests 128-bit session key negotiation. An alternate name for this field is NTLMSSP_NEGOTIATE_128. If the client
   110  	// sends NTLMSSP_NEGOTIATE_128 to the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_128 to the client in the
   111  	// CHALLENGE_MESSAGE only if the client sets NTLMSSP_NEGOTIATE_SEAL or NTLMSSP_NEGOTIATE_SIGN. Otherwise it is ignored. If both
   112  	// NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 are requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and
   113  	// NTLMSSP_NEGOTIATE_128 will both be returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set
   114  	// NTLMSSP_NEGOTIATE_128 if it is supported. An alternate name for this field is NTLMSSP_NEGOTIATE_128.<21>
   115  	NTLMSSP_NEGOTIATE_128
   116  	// V (1 bit): If set, requests an explicit key exchange. This capability SHOULD be used because it improves security for message integrity or
   117  	// confidentiality. See sections 3.2.5.1.2, 3.2.5.2.1, and 3.2.5.2.2 for details. An alternate name for this field is NTLMSSP_NEGOTIATE_KEY_EXCH.
   118  	NTLMSSP_NEGOTIATE_KEY_EXCH
   119  	// If set, requests 56-bit encryption. If the client sends NTLMSSP_NEGOTIATE_SEAL or NTLMSSP_NEGOTIATE_SIGN with NTLMSSP_NEGOTIATE_56 to the
   120  	// server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_56 to the client in the CHALLENGE_MESSAGE. Otherwise it is ignored.
   121  	// If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 are requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and
   122  	// NTLMSSP_NEGOTIATE_128 will both be returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_56
   123  	// if it is supported. An alternate name for this field is NTLMSSP_NEGOTIATE_56.
   124  	NTLMSSP_NEGOTIATE_56
   125  )
   126  
   127  func (f NegotiateFlag) Set(flags uint32) uint32 {
   128  	return flags | uint32(f)
   129  }
   130  
   131  func (f NegotiateFlag) IsSet(flags uint32) bool {
   132  	return (flags & uint32(f)) != 0
   133  }
   134  
   135  func (f NegotiateFlag) Unset(flags uint32) uint32 {
   136  	return flags &^ uint32(f)
   137  }
   138  
   139  func (f NegotiateFlag) String() string {
   140  	return reflect.TypeOf(f).Name()
   141  }
   142  
   143  func GetFlagName(flag NegotiateFlag) string {
   144  	nameMap := map[NegotiateFlag]string{
   145  		NTLMSSP_NEGOTIATE_56:                       "NTLMSSP_NEGOTIATE_56",
   146  		NTLMSSP_NEGOTIATE_KEY_EXCH:                 "NTLMSSP_NEGOTIATE_KEY_EXCH",
   147  		NTLMSSP_NEGOTIATE_128:                      "NTLMSSP_NEGOTIATE_128",
   148  		NTLMSSP_NEGOTIATE_VERSION:                  "NTLMSSP_NEGOTIATE_VERSION",
   149  		NTLMSSP_NEGOTIATE_TARGET_INFO:              "NTLMSSP_NEGOTIATE_TARGET_INFO",
   150  		NTLMSSP_REQUEST_NON_NT_SESSION_KEY:         "NTLMSSP_REQUEST_NON_NT_SESSION_KEY",
   151  		NTLMSSP_NEGOTIATE_IDENTIFY:                 "NTLMSSP_NEGOTIATE_IDENTIFY",
   152  		NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: "NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY",
   153  		NTLMSSP_TARGET_TYPE_SERVER:                 "NTLMSSP_TARGET_TYPE_SERVER",
   154  		NTLMSSP_TARGET_TYPE_DOMAIN:                 "NTLMSSP_TARGET_TYPE_DOMAIN",
   155  		NTLMSSP_NEGOTIATE_ALWAYS_SIGN:              "NTLMSSP_NEGOTIATE_ALWAYS_SIGN",
   156  		NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED: "NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED",
   157  		NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED:      "NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED",
   158  		NTLMSSP_ANONYMOUS:                          "NTLMSSP_ANONYMOUS",
   159  		NTLMSSP_NEGOTIATE_NTLM:                     "NTLMSSP_NEGOTIATE_NTLM",
   160  		NTLMSSP_NEGOTIATE_LM_KEY:                   "NTLMSSP_NEGOTIATE_LM_KEY",
   161  		NTLMSSP_NEGOTIATE_DATAGRAM:                 "NTLMSSP_NEGOTIATE_DATAGRAM",
   162  		NTLMSSP_NEGOTIATE_SEAL:                     "NTLMSSP_NEGOTIATE_SEAL",
   163  		NTLMSSP_NEGOTIATE_SIGN:                     "NTLMSSP_NEGOTIATE_SIGN",
   164  		NTLMSSP_REQUEST_TARGET:                     "NTLMSSP_REQUEST_TARGET",
   165  		NTLM_NEGOTIATE_OEM:                         "NTLM_NEGOTIATE_OEM",
   166  		NTLMSSP_NEGOTIATE_UNICODE:                  "NTLMSSP_NEGOTIATE_UNICODE"}
   167  
   168  	return nameMap[flag]
   169  }
   170  
   171  func FlagsToString(flags uint32) string {
   172  	allFlags := [...]NegotiateFlag{
   173  		NTLMSSP_NEGOTIATE_56,
   174  		NTLMSSP_NEGOTIATE_KEY_EXCH,
   175  		NTLMSSP_NEGOTIATE_128,
   176  		NTLMSSP_NEGOTIATE_VERSION,
   177  		NTLMSSP_NEGOTIATE_TARGET_INFO,
   178  		NTLMSSP_REQUEST_NON_NT_SESSION_KEY,
   179  		NTLMSSP_NEGOTIATE_IDENTIFY,
   180  		NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY,
   181  		NTLMSSP_TARGET_TYPE_SERVER,
   182  		NTLMSSP_TARGET_TYPE_DOMAIN,
   183  		NTLMSSP_NEGOTIATE_ALWAYS_SIGN,
   184  		NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED,
   185  		NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED,
   186  		NTLMSSP_ANONYMOUS,
   187  		NTLMSSP_NEGOTIATE_NTLM,
   188  		NTLMSSP_NEGOTIATE_LM_KEY,
   189  		NTLMSSP_NEGOTIATE_DATAGRAM,
   190  		NTLMSSP_NEGOTIATE_SEAL,
   191  		NTLMSSP_NEGOTIATE_SIGN,
   192  		NTLMSSP_REQUEST_TARGET,
   193  		NTLM_NEGOTIATE_OEM,
   194  		NTLMSSP_NEGOTIATE_UNICODE}
   195  
   196  	var buffer bytes.Buffer
   197  	for i := range allFlags {
   198  		f := allFlags[i]
   199  		buffer.WriteString(fmt.Sprintf("%s: %v\n", GetFlagName(f), f.IsSet(flags)))
   200  	}
   201  	return buffer.String()
   202  }