ntlm_client.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol
  5. // Specification version 28.0 [1], an unofficial NTLM reference [2], and a
  6. // blog post describing Extended Protection for Authentication [3].
  7. //
  8. // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
  9. // [2] http://davenport.sourceforge.net/ntlm.html
  10. // [3]
  11. // https://blogs.msdn.microsoft.com/openspecification/2013/03/26/ntlm-and-channel-binding-hash-aka-extended-protection-for-authentication/
  12. #ifndef NET_NTLM_NTLM_CLIENT_H_
  13. #define NET_NTLM_NTLM_CLIENT_H_
  14. #include <stddef.h>
  15. #include <stdint.h>
  16. #include <memory>
  17. #include <string>
  18. #include "base/check.h"
  19. #include "base/containers/span.h"
  20. #include "base/strings/string_piece.h"
  21. #include "net/base/net_export.h"
  22. #include "net/ntlm/ntlm_constants.h"
  23. namespace net::ntlm {
  24. // Provides an implementation of an NTLMv1 or NTLMv2 Client with support
  25. // for MIC and EPA [1]. This implementation does not support the key exchange,
  26. // signing or sealing feature as the NTLMSSP_NEGOTIATE_KEY_EXCH flag is never
  27. // negotiated.
  28. //
  29. // [1] -
  30. // https://support.microsoft.com/en-us/help/968389/extended-protection-for-authentication
  31. class NET_EXPORT_PRIVATE NtlmClient {
  32. public:
  33. // Pass feature flags to enable/disable NTLMv2 and additional NTLMv2
  34. // features such as Extended Protection for Authentication (EPA) and Message
  35. // Integrity Check (MIC).
  36. explicit NtlmClient(NtlmFeatures features);
  37. NtlmClient(const NtlmClient&) = delete;
  38. NtlmClient& operator=(const NtlmClient&) = delete;
  39. ~NtlmClient();
  40. bool IsNtlmV2() const { return features_.enable_NTLMv2; }
  41. bool IsMicEnabled() const { return IsNtlmV2() && features_.enable_MIC; }
  42. bool IsEpaEnabled() const { return IsNtlmV2() && features_.enable_EPA; }
  43. // Returns the Negotiate message.
  44. std::vector<uint8_t> GetNegotiateMessage() const;
  45. // Returns a the Authenticate message. If the method fails an empty vector
  46. // is returned.
  47. //
  48. // |username| is treated case insensitively by NTLM however the mechanism
  49. // to uppercase is not clearly defined. In this implementation the default
  50. // locale is used. Additionally for names longer than 20 characters, the
  51. // fully qualified name in the new '@' format must be used.
  52. // eg. very_long_name@domain.com. Names shorter than 20 characters can
  53. // optionally omit the '@domain.com' part.
  54. // |hostname| can be a short NetBIOS name or an FQDN, however the server will
  55. // only inspect this field if the default domain policy is to restrict NTLM.
  56. // In this case the hostname will be compared to an allowlist stored in this
  57. // group policy [1].
  58. // |channel_bindings| is a string supplied out of band (usually from a web
  59. // browser) and is a (21+sizeof(hash)) byte ASCII string, where 'hash' is
  60. // usually a SHA-256 of the servers certificate, but may be another hash
  61. // algorithm. The format as defined by RFC 5929 Section 4 is shown below;
  62. //
  63. // [0-20] - "tls-server-end-point:" (Literal string)
  64. // [21-(20+sizeof(hash)] - HASH(server_certificate) (Certificate hash)
  65. //
  66. // |spn| is a string supplied out of band (usually from a web browser) and
  67. // is a Service Principal Name [2]. For NTLM over HTTP the value of this
  68. // string will usually be "HTTP/<hostname>".
  69. // |client_time| 64 bit Windows timestamp defined as the number of
  70. // 100 nanosecond ticks since midnight Jan 01, 1601 (UTC). If the server does
  71. // not send a timestamp, the client timestamp is used in the Proof Input
  72. // instead.
  73. // |server_challenge_message| is the full content of the challenge message
  74. // sent by the server.
  75. //
  76. // [1] - https://technet.microsoft.com/en-us/library/jj852267(v=ws.11).aspx
  77. std::vector<uint8_t> GenerateAuthenticateMessage(
  78. const std::u16string& domain,
  79. const std::u16string& username,
  80. const std::u16string& password,
  81. const std::string& hostname,
  82. const std::string& channel_bindings,
  83. const std::string& spn,
  84. uint64_t client_time,
  85. base::span<const uint8_t, kChallengeLen> client_challenge,
  86. base::span<const uint8_t> server_challenge_message) const;
  87. // Simplified method for NTLMv1 which does not require |channel_bindings|,
  88. // |spn|, or |client_time|. See |GenerateAuthenticateMessage| for more
  89. // details.
  90. std::vector<uint8_t> GenerateAuthenticateMessageV1(
  91. const std::u16string& domain,
  92. const std::u16string& username,
  93. const std::u16string& password,
  94. const std::string& hostname,
  95. base::span<const uint8_t, 8> client_challenge,
  96. base::span<const uint8_t> server_challenge_message) const {
  97. DCHECK(!IsNtlmV2());
  98. return GenerateAuthenticateMessage(
  99. domain, username, password, hostname, std::string(), std::string(), 0,
  100. client_challenge, server_challenge_message);
  101. }
  102. private:
  103. // Returns the length of the Authenticate message based on the length of the
  104. // variable length parts of the message and whether Unicode support was
  105. // negotiated.
  106. size_t CalculateAuthenticateMessageLength(
  107. bool is_unicode,
  108. const std::u16string& domain,
  109. const std::u16string& username,
  110. const std::string& hostname,
  111. size_t updated_target_info_len) const;
  112. bool CalculatePayloadLayout(bool is_unicode,
  113. const std::u16string& domain,
  114. const std::u16string& username,
  115. const std::string& hostname,
  116. size_t updated_target_info_len,
  117. SecurityBuffer* lm_info,
  118. SecurityBuffer* ntlm_info,
  119. SecurityBuffer* domain_info,
  120. SecurityBuffer* username_info,
  121. SecurityBuffer* hostname_info,
  122. SecurityBuffer* session_key_info,
  123. size_t* authenticate_message_len) const;
  124. // Returns the length of the header part of the Authenticate message.
  125. size_t GetAuthenticateHeaderLength() const;
  126. // Returns the length of the NTLM response.
  127. size_t GetNtlmResponseLength(size_t updated_target_info_len) const;
  128. // Generates the negotiate message (which is always the same) into
  129. // |negotiate_message_|.
  130. void GenerateNegotiateMessage();
  131. const NtlmFeatures features_;
  132. NegotiateFlags negotiate_flags_;
  133. std::vector<uint8_t> negotiate_message_;
  134. };
  135. } // namespace net::ntlm
  136. #endif // NET_NTLM_NTLM_CLIENT_H_