docs: def get_ntlm_response(self, flags, challenge, target_info=None, channel_binding=None):
          """
          Computes the 24 byte NTLM challenge response given the 8 byte server challenge, along with the session key.
          If NTLMv2 is used, the TargetInfo structure must be supplied, the updated TargetInfo structure will be returned
          :param challenge: The 8-byte challenge message generated by the server
          :return: A tuple containing the 24 byte NTLM Hash, Session Key and TargetInfo
          """
          # TODO: IMPLEMENT THE FOLLOWING FEATURES
          # If NTLM v2 authentication is used and the CHALLENGE_MESSAGE does not contain both MsvAvNbComputerName and
          # MsvAvNbDomainName AVPairs and either Integrity is TRUE or Confidentiality is TRUE, then return STATUS_LOGON_FAILURE.
  
          # If NTLM v2 authentication is used and the CHALLENGE_MESSAGE contains a TargetInfo field, the client SHOULD NOT send
          # the LmChallengeResponse and SHOULD set the LmChallengeResponseLen and LmChallengeResponseMaxLen fields in the
          # AUTHENTICATE_MESSAGE to zero.
  
          # If lm compatibility level is 3 or lower, but the server negotiated NTLM2, generate an
          # NTLM2 response in preference to the weaker NTLMv1.
          if flags & NegotiateFlag.NTLMSSP_NTLM2_KEY and self._lm_compatibility < 3:
              response, key = PasswordAuthentication.get_ntlm2_response(self._password, challenge, self._client_challenge)
  
          elif 0 <= self._lm_compatibility < 3:
              response, key = PasswordAuthentication.get_ntlmv1_response(self._password, challenge)
          else:
              # We should use the timestamp included in TargetInfo, if no timestamp is set we generate one and add it to
              # the outgoing TargetInfo. If the timestamp is set, we should also set the MIC flag
              if target_info is None:
                  target_info = TargetInfo()
              if target_info[TargetInfo.NTLMSSP_AV_TIME] is None:
                  timestamp = PasswordAuthentication._get_ntlm_timestamp()
              else:
                  # TODO: If the CHALLENGE_MESSAGE TargetInfo field (section 2.2.1.2) has an MsvAvTimestamp present,
                  # TODO: the client SHOULD provide a MIC.
                  timestamp = target_info[TargetInfo.NTLMSSP_AV_TIME][1]
  
              #target_info[TargetInfo.NTLMSSP_AV_FLAGS] = struct.pack('<I', 2)
              # Calculating channel bindings is poorly documented. It is implemented in winrmlib, and needs to be
              # moved here
              # if self._av_channel_bindings is True and channel_binding is not None:
              #     target_info[TargetInfo.NTLMSSP_AV_CHANNEL_BINDINGS] = channel_binding
  
              response, key, target_info = PasswordAuthentication.get_ntlmv2_response(
                  self._domain, self._username, self._password.encode('utf-16le'), challenge,
                  self._client_challenge, timestamp, target_info)
  
          return response, key, target_info