1 // Copyright (c) 2011 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 
5 #ifndef NET_HTTP_MOCK_GSSAPI_LIBRARY_POSIX_H_
6 #define NET_HTTP_MOCK_GSSAPI_LIBRARY_POSIX_H_
7 
8 #include <list>
9 #include <string>
10 
11 #include "base/gtest_prod_util.h"
12 #include "net/http/http_auth_gssapi_posix.h"
13 
14 namespace net {
15 
16 namespace test {
17 
18 class GssContextMockImpl {
19  public:
20   GssContextMockImpl();
21   GssContextMockImpl(const GssContextMockImpl& other);
22   GssContextMockImpl(const char* src_name,
23                      const char* targ_name,
24                      OM_uint32 lifetime_rec,
25                      const gss_OID_desc& mech_type,
26                      OM_uint32 ctx_flags,
27                      int locally_initiated,
28                      int open);
29   ~GssContextMockImpl();
30 
31   void Assign(const GssContextMockImpl& other);
32 
33   std::string src_name;
34   std::string targ_name;
35   OM_uint32 lifetime_rec;
36   gss_OID_desc mech_type;
37   OM_uint32 ctx_flags;
38   int locally_initiated;
39   int open;
40 };
41 
42 // The MockGSSAPILibrary class is intended for unit tests which want to bypass
43 // the system GSSAPI library calls.
44 class MockGSSAPILibrary : public GSSAPILibrary {
45  public:
46   // Unit tests need access to this. "Friend"ing didn't help.
47   struct SecurityContextQuery {
48     SecurityContextQuery();
49     SecurityContextQuery(const std::string& expected_package,
50                          OM_uint32 response_code,
51                          OM_uint32 minor_response_code,
52                          const test::GssContextMockImpl& context_info,
53                          const char* expected_input_token,
54                          const char* output_token);
55     SecurityContextQuery(const SecurityContextQuery& other);
56     ~SecurityContextQuery();
57 
58     std::string expected_package;
59     OM_uint32 response_code;
60     OM_uint32 minor_response_code;
61     test::GssContextMockImpl context_info;
62     gss_buffer_desc expected_input_token;
63     gss_buffer_desc output_token;
64   };
65 
66   MockGSSAPILibrary();
67   ~MockGSSAPILibrary() override;
68 
69   // Establishes an expectation for a |init_sec_context()| call.
70   //
71   // Each expectation established by |ExpectSecurityContext()| must be
72   // matched by a call to |init_sec_context()| during the lifetime of
73   // the MockGSSAPILibrary. The |expected_package| argument must equal the
74   // value associated with the |target_name| argument to |init_sec_context()|
75   // for there to be a match. The expectations also establish an explicit
76   // ordering.
77   //
78   // For example, this sequence will be successful.
79   //   MockGSSAPILibrary lib;
80   //   lib.ExpectSecurityContext("NTLM", ...)
81   //   lib.ExpectSecurityContext("Negotiate", ...)
82   //   lib.init_sec_context("NTLM", ...)
83   //   lib.init_sec_context("Negotiate", ...)
84   //
85   // This sequence will fail since the queries do not occur in the order
86   // established by the expectations.
87   //   MockGSSAPILibrary lib;
88   //   lib.ExpectSecurityContext("NTLM", ...)
89   //   lib.ExpectSecurityContext("Negotiate", ...)
90   //   lib.init_sec_context("Negotiate", ...)
91   //   lib.init_sec_context("NTLM", ...)
92   //
93   // This sequence will fail because there were not enough queries.
94   //   MockGSSAPILibrary lib;
95   //   lib.ExpectSecurityContext("NTLM", ...)
96   //   lib.ExpectSecurityContext("Negotiate", ...)
97   //   lib.init_sec_context("NTLM", ...)
98   //
99   // |response_code| is used as the return value for |init_sec_context()|.
100   // If |response_code| is GSS_S_COMPLETE,
101   //
102   // |context_info| is the expected value of the |**context_handle| in after
103   // |init_sec_context()| returns.
104   void ExpectSecurityContext(const std::string& expected_package,
105                              OM_uint32 response_code,
106                              OM_uint32 minor_response_code,
107                              const test::GssContextMockImpl& context_info,
108                              const gss_buffer_desc& expected_input_token,
109                              const gss_buffer_desc& output_token);
110 
111   // GSSAPILibrary methods:
112 
113   // Initializes the library, including any necessary dynamic libraries.
114   // This is done separately from construction (which happens at startup time)
115   // in order to delay work until the class is actually needed.
116   bool Init(const NetLogWithSource& net_log) override;
117 
118   // These methods match the ones in the GSSAPI library.
119   OM_uint32 import_name(OM_uint32* minor_status,
120                         const gss_buffer_t input_name_buffer,
121                         const gss_OID input_name_type,
122                         gss_name_t* output_name) override;
123   OM_uint32 release_name(OM_uint32* minor_status,
124                          gss_name_t* input_name) override;
125   OM_uint32 release_buffer(OM_uint32* minor_status,
126                            gss_buffer_t buffer) override;
127   OM_uint32 display_name(OM_uint32* minor_status,
128                          const gss_name_t input_name,
129                          gss_buffer_t output_name_buffer,
130                          gss_OID* output_name_type) override;
131 
132   // These special status values can be used to trigger specific behavior in
133   // |display_status()|.
134   enum class DisplayStatusSpecials : OM_uint32 {
135     // A multiline status message.
136     MultiLine = 128,
137 
138     // Multiline, execept there's no ending message.
139     InfiniteLines,
140 
141     // Causes |display_status()| to fail.
142     Fail,
143 
144     // Returns an empty message.
145     EmptyMessage,
146 
147     // Returns successfully without modifying |status_string|.
148     UninitalizedBuffer,
149 
150     // Returns a message that's invalid UTF-8.
151     InvalidUtf8
152   };
153   OM_uint32 display_status(OM_uint32* minor_status,
154                            OM_uint32 status_value,
155                            int status_type,
156                            const gss_OID mech_type,
157                            OM_uint32* message_contex,
158                            gss_buffer_t status_string) override;
159   OM_uint32 init_sec_context(OM_uint32* minor_status,
160                              const gss_cred_id_t initiator_cred_handle,
161                              gss_ctx_id_t* context_handle,
162                              const gss_name_t target_name,
163                              const gss_OID mech_type,
164                              OM_uint32 req_flags,
165                              OM_uint32 time_req,
166                              const gss_channel_bindings_t input_chan_bindings,
167                              const gss_buffer_t input_token,
168                              gss_OID* actual_mech_type,
169                              gss_buffer_t output_token,
170                              OM_uint32* ret_flags,
171                              OM_uint32* time_rec) override;
172   OM_uint32 wrap_size_limit(OM_uint32* minor_status,
173                             const gss_ctx_id_t context_handle,
174                             int conf_req_flag,
175                             gss_qop_t qop_req,
176                             OM_uint32 req_output_size,
177                             OM_uint32* max_input_size) override;
178   OM_uint32 delete_sec_context(OM_uint32* minor_status,
179                                gss_ctx_id_t* context_handle,
180                                gss_buffer_t output_token) override;
181   OM_uint32 inquire_context(OM_uint32* minor_status,
182                             const gss_ctx_id_t context_handle,
183                             gss_name_t* src_name,
184                             gss_name_t* targ_name,
185                             OM_uint32* lifetime_rec,
186                             gss_OID* mech_type,
187                             OM_uint32* ctx_flags,
188                             int* locally_initiated,
189                             int* open) override;
190   const std::string& GetLibraryNameForTesting() override;
191 
192  private:
193   FRIEND_TEST_ALL_PREFIXES(HttpAuthGSSAPIPOSIXTest, GSSAPICycle);
194 
195   // |expected_security_queries| contains an ordered list of expected
196   // |init_sec_context()| calls and the return values for those
197   // calls.
198   std::list<SecurityContextQuery> expected_security_queries_;
199 
200   // Empty string. Enables GetLibraryNameForTesting() to return a reference.
201   std::string library_name_;
202 };
203 
204 }  // namespace test
205 
206 using MockAuthLibrary = test::MockGSSAPILibrary;
207 
208 }  // namespace net
209 
210 #endif  // NET_HTTP_MOCK_GSSAPI_LIBRARY_POSIX_H_
211