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