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