1 // Copyright (c) 2010 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_HTTP_AUTH_GSSAPI_POSIX_H_ 6 #define NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_ 7 #pragma once 8 9 #include <string> 10 11 #include "base/gtest_prod_util.h" 12 #include "base/native_library.h" 13 #include "base/string16.h" 14 #include "net/http/http_auth.h" 15 16 #define GSS_USE_FUNCTION_POINTERS 17 #include "net/third_party/gssapi/gssapi.h" 18 19 namespace net { 20 21 extern gss_OID CHROME_GSS_C_NT_HOSTBASED_SERVICE_X; 22 extern gss_OID CHROME_GSS_C_NT_HOSTBASED_SERVICE; 23 extern gss_OID CHROME_GSS_KRB5_MECH_OID_DESC; 24 25 // GSSAPILibrary is introduced so unit tests can mock the calls to the GSSAPI 26 // library. The default implementation attempts to load one of the standard 27 // GSSAPI library implementations, then simply passes the arguments on to 28 // that implementation. 29 class GSSAPILibrary { 30 public: 31 virtual ~GSSAPILibrary() {} 32 33 // Initializes the library, including any necessary dynamic libraries. 34 // This is done separately from construction (which happens at startup time) 35 // in order to delay work until the class is actually needed. 36 virtual bool Init() = 0; 37 38 // These methods match the ones in the GSSAPI library. 39 virtual OM_uint32 import_name( 40 OM_uint32* minor_status, 41 const gss_buffer_t input_name_buffer, 42 const gss_OID input_name_type, 43 gss_name_t* output_name) = 0; 44 virtual OM_uint32 release_name( 45 OM_uint32* minor_status, 46 gss_name_t* input_name) = 0; 47 virtual OM_uint32 release_buffer( 48 OM_uint32* minor_status, 49 gss_buffer_t buffer) = 0; 50 virtual OM_uint32 display_name( 51 OM_uint32* minor_status, 52 const gss_name_t input_name, 53 gss_buffer_t output_name_buffer, 54 gss_OID* output_name_type) = 0; 55 virtual OM_uint32 display_status( 56 OM_uint32* minor_status, 57 OM_uint32 status_value, 58 int status_type, 59 const gss_OID mech_type, 60 OM_uint32* message_contex, 61 gss_buffer_t status_string) = 0; 62 virtual OM_uint32 init_sec_context( 63 OM_uint32* minor_status, 64 const gss_cred_id_t initiator_cred_handle, 65 gss_ctx_id_t* context_handle, 66 const gss_name_t target_name, 67 const gss_OID mech_type, 68 OM_uint32 req_flags, 69 OM_uint32 time_req, 70 const gss_channel_bindings_t input_chan_bindings, 71 const gss_buffer_t input_token, 72 gss_OID* actual_mech_type, 73 gss_buffer_t output_token, 74 OM_uint32* ret_flags, 75 OM_uint32* time_rec) = 0; 76 virtual OM_uint32 wrap_size_limit( 77 OM_uint32* minor_status, 78 const gss_ctx_id_t context_handle, 79 int conf_req_flag, 80 gss_qop_t qop_req, 81 OM_uint32 req_output_size, 82 OM_uint32* max_input_size) = 0; 83 virtual OM_uint32 delete_sec_context( 84 OM_uint32* minor_status, 85 gss_ctx_id_t* context_handle, 86 gss_buffer_t output_token) = 0; 87 virtual OM_uint32 inquire_context( 88 OM_uint32* minor_status, 89 const gss_ctx_id_t context_handle, 90 gss_name_t* src_name, 91 gss_name_t* targ_name, 92 OM_uint32* lifetime_rec, 93 gss_OID* mech_type, 94 OM_uint32* ctx_flags, 95 int* locally_initiated, 96 int* open) = 0; 97 98 }; 99 100 // GSSAPISharedLibrary class is defined here so that unit tests can access it. 101 class GSSAPISharedLibrary : public GSSAPILibrary { 102 public: 103 // If |gssapi_library_name| is empty, hard-coded default library names are 104 // used. 105 explicit GSSAPISharedLibrary(const std::string& gssapi_library_name); 106 virtual ~GSSAPISharedLibrary(); 107 108 // GSSAPILibrary methods: 109 virtual bool Init(); 110 virtual OM_uint32 import_name( 111 OM_uint32* minor_status, 112 const gss_buffer_t input_name_buffer, 113 const gss_OID input_name_type, 114 gss_name_t* output_name); 115 virtual OM_uint32 release_name( 116 OM_uint32* minor_status, 117 gss_name_t* input_name); 118 virtual OM_uint32 release_buffer( 119 OM_uint32* minor_status, 120 gss_buffer_t buffer); 121 virtual OM_uint32 display_name( 122 OM_uint32* minor_status, 123 const gss_name_t input_name, 124 gss_buffer_t output_name_buffer, 125 gss_OID* output_name_type); 126 virtual OM_uint32 display_status( 127 OM_uint32* minor_status, 128 OM_uint32 status_value, 129 int status_type, 130 const gss_OID mech_type, 131 OM_uint32* message_contex, 132 gss_buffer_t status_string); 133 virtual OM_uint32 init_sec_context( 134 OM_uint32* minor_status, 135 const gss_cred_id_t initiator_cred_handle, 136 gss_ctx_id_t* context_handle, 137 const gss_name_t target_name, 138 const gss_OID mech_type, 139 OM_uint32 req_flags, 140 OM_uint32 time_req, 141 const gss_channel_bindings_t input_chan_bindings, 142 const gss_buffer_t input_token, 143 gss_OID* actual_mech_type, 144 gss_buffer_t output_token, 145 OM_uint32* ret_flags, 146 OM_uint32* time_rec); 147 virtual OM_uint32 wrap_size_limit( 148 OM_uint32* minor_status, 149 const gss_ctx_id_t context_handle, 150 int conf_req_flag, 151 gss_qop_t qop_req, 152 OM_uint32 req_output_size, 153 OM_uint32* max_input_size); 154 virtual OM_uint32 delete_sec_context( 155 OM_uint32* minor_status, 156 gss_ctx_id_t* context_handle, 157 gss_buffer_t output_token); 158 virtual OM_uint32 inquire_context( 159 OM_uint32* minor_status, 160 const gss_ctx_id_t context_handle, 161 gss_name_t* src_name, 162 gss_name_t* targ_name, 163 OM_uint32* lifetime_rec, 164 gss_OID* mech_type, 165 OM_uint32* ctx_flags, 166 int* locally_initiated, 167 int* open); 168 169 private: 170 FRIEND_TEST_ALL_PREFIXES(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup); 171 172 bool InitImpl(); 173 // Finds a usable dynamic library for GSSAPI and loads it. The criteria are: 174 // 1. The library must exist. 175 // 2. The library must export the functions we need. 176 base::NativeLibrary LoadSharedLibrary(); 177 bool BindMethods(base::NativeLibrary lib); 178 179 bool initialized_; 180 181 std::string gssapi_library_name_; 182 // Need some way to invalidate the library. 183 base::NativeLibrary gssapi_library_; 184 185 // Function pointers 186 gss_import_name_type import_name_; 187 gss_release_name_type release_name_; 188 gss_release_buffer_type release_buffer_; 189 gss_display_name_type display_name_; 190 gss_display_status_type display_status_; 191 gss_init_sec_context_type init_sec_context_; 192 gss_wrap_size_limit_type wrap_size_limit_; 193 gss_delete_sec_context_type delete_sec_context_; 194 gss_inquire_context_type inquire_context_; 195 }; 196 197 // ScopedSecurityContext releases a gss_ctx_id_t when it goes out of 198 // scope. 199 class ScopedSecurityContext { 200 public: 201 explicit ScopedSecurityContext(GSSAPILibrary* gssapi_lib); 202 ~ScopedSecurityContext(); 203 204 gss_ctx_id_t get() const { return security_context_; } 205 gss_ctx_id_t* receive() { return &security_context_; } 206 207 private: 208 gss_ctx_id_t security_context_; 209 GSSAPILibrary* gssapi_lib_; 210 211 DISALLOW_COPY_AND_ASSIGN(ScopedSecurityContext); 212 }; 213 214 215 // TODO(ahendrickson): Share code with HttpAuthSSPI. 216 class HttpAuthGSSAPI { 217 public: 218 HttpAuthGSSAPI(GSSAPILibrary* library, 219 const std::string& scheme, 220 const gss_OID gss_oid); 221 ~HttpAuthGSSAPI(); 222 223 bool Init(); 224 225 bool NeedsIdentity() const; 226 227 HttpAuth::AuthorizationResult ParseChallenge( 228 HttpAuth::ChallengeTokenizer* tok); 229 230 // Generates an authentication token. 231 // The return value is an error code. If it's not |OK|, the value of 232 // |*auth_token| is unspecified. 233 // |spn| is the Service Principal Name of the server that the token is 234 // being generated for. 235 // If this is the first round of a multiple round scheme, credentials are 236 // obtained using |*username| and |*password|. If |username| and |password| 237 // are NULL, the default credentials are used instead. 238 int GenerateAuthToken(const string16* username, 239 const string16* password, 240 const std::wstring& spn, 241 std::string* auth_token); 242 243 // Delegation is allowed on the Kerberos ticket. This allows certain servers 244 // to act as the user, such as an IIS server retrieiving data from a 245 // Kerberized MSSQL server. 246 void Delegate(); 247 248 private: 249 int GetNextSecurityToken(const std::wstring& spn, 250 gss_buffer_t in_token, 251 gss_buffer_t out_token); 252 253 std::string scheme_; 254 gss_OID gss_oid_; 255 GSSAPILibrary* library_; 256 std::string decoded_server_auth_token_; 257 ScopedSecurityContext scoped_sec_context_; 258 bool can_delegate_; 259 }; 260 261 } // namespace net 262 263 #endif // NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_ 264