| // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_ |
| #define NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_ |
| #pragma once |
| |
| #include <string> |
| |
| #include "base/gtest_prod_util.h" |
| #include "base/native_library.h" |
| #include "base/string16.h" |
| #include "net/http/http_auth.h" |
| |
| #define GSS_USE_FUNCTION_POINTERS |
| #include "net/third_party/gssapi/gssapi.h" |
| |
| namespace net { |
| |
| extern gss_OID CHROME_GSS_C_NT_HOSTBASED_SERVICE_X; |
| extern gss_OID CHROME_GSS_C_NT_HOSTBASED_SERVICE; |
| extern gss_OID CHROME_GSS_KRB5_MECH_OID_DESC; |
| |
| // GSSAPILibrary is introduced so unit tests can mock the calls to the GSSAPI |
| // library. The default implementation attempts to load one of the standard |
| // GSSAPI library implementations, then simply passes the arguments on to |
| // that implementation. |
| class GSSAPILibrary { |
| public: |
| virtual ~GSSAPILibrary() {} |
| |
| // Initializes the library, including any necessary dynamic libraries. |
| // This is done separately from construction (which happens at startup time) |
| // in order to delay work until the class is actually needed. |
| virtual bool Init() = 0; |
| |
| // These methods match the ones in the GSSAPI library. |
| virtual OM_uint32 import_name( |
| OM_uint32* minor_status, |
| const gss_buffer_t input_name_buffer, |
| const gss_OID input_name_type, |
| gss_name_t* output_name) = 0; |
| virtual OM_uint32 release_name( |
| OM_uint32* minor_status, |
| gss_name_t* input_name) = 0; |
| virtual OM_uint32 release_buffer( |
| OM_uint32* minor_status, |
| gss_buffer_t buffer) = 0; |
| virtual OM_uint32 display_name( |
| OM_uint32* minor_status, |
| const gss_name_t input_name, |
| gss_buffer_t output_name_buffer, |
| gss_OID* output_name_type) = 0; |
| virtual OM_uint32 display_status( |
| OM_uint32* minor_status, |
| OM_uint32 status_value, |
| int status_type, |
| const gss_OID mech_type, |
| OM_uint32* message_contex, |
| gss_buffer_t status_string) = 0; |
| virtual OM_uint32 init_sec_context( |
| OM_uint32* minor_status, |
| const gss_cred_id_t initiator_cred_handle, |
| gss_ctx_id_t* context_handle, |
| const gss_name_t target_name, |
| const gss_OID mech_type, |
| OM_uint32 req_flags, |
| OM_uint32 time_req, |
| const gss_channel_bindings_t input_chan_bindings, |
| const gss_buffer_t input_token, |
| gss_OID* actual_mech_type, |
| gss_buffer_t output_token, |
| OM_uint32* ret_flags, |
| OM_uint32* time_rec) = 0; |
| virtual OM_uint32 wrap_size_limit( |
| OM_uint32* minor_status, |
| const gss_ctx_id_t context_handle, |
| int conf_req_flag, |
| gss_qop_t qop_req, |
| OM_uint32 req_output_size, |
| OM_uint32* max_input_size) = 0; |
| virtual OM_uint32 delete_sec_context( |
| OM_uint32* minor_status, |
| gss_ctx_id_t* context_handle, |
| gss_buffer_t output_token) = 0; |
| virtual OM_uint32 inquire_context( |
| OM_uint32* minor_status, |
| const gss_ctx_id_t context_handle, |
| gss_name_t* src_name, |
| gss_name_t* targ_name, |
| OM_uint32* lifetime_rec, |
| gss_OID* mech_type, |
| OM_uint32* ctx_flags, |
| int* locally_initiated, |
| int* open) = 0; |
| |
| }; |
| |
| // GSSAPISharedLibrary class is defined here so that unit tests can access it. |
| class GSSAPISharedLibrary : public GSSAPILibrary { |
| public: |
| // If |gssapi_library_name| is empty, hard-coded default library names are |
| // used. |
| explicit GSSAPISharedLibrary(const std::string& gssapi_library_name); |
| virtual ~GSSAPISharedLibrary(); |
| |
| // GSSAPILibrary methods: |
| virtual bool Init(); |
| virtual OM_uint32 import_name( |
| OM_uint32* minor_status, |
| const gss_buffer_t input_name_buffer, |
| const gss_OID input_name_type, |
| gss_name_t* output_name); |
| virtual OM_uint32 release_name( |
| OM_uint32* minor_status, |
| gss_name_t* input_name); |
| virtual OM_uint32 release_buffer( |
| OM_uint32* minor_status, |
| gss_buffer_t buffer); |
| virtual OM_uint32 display_name( |
| OM_uint32* minor_status, |
| const gss_name_t input_name, |
| gss_buffer_t output_name_buffer, |
| gss_OID* output_name_type); |
| virtual OM_uint32 display_status( |
| OM_uint32* minor_status, |
| OM_uint32 status_value, |
| int status_type, |
| const gss_OID mech_type, |
| OM_uint32* message_contex, |
| gss_buffer_t status_string); |
| virtual OM_uint32 init_sec_context( |
| OM_uint32* minor_status, |
| const gss_cred_id_t initiator_cred_handle, |
| gss_ctx_id_t* context_handle, |
| const gss_name_t target_name, |
| const gss_OID mech_type, |
| OM_uint32 req_flags, |
| OM_uint32 time_req, |
| const gss_channel_bindings_t input_chan_bindings, |
| const gss_buffer_t input_token, |
| gss_OID* actual_mech_type, |
| gss_buffer_t output_token, |
| OM_uint32* ret_flags, |
| OM_uint32* time_rec); |
| virtual OM_uint32 wrap_size_limit( |
| OM_uint32* minor_status, |
| const gss_ctx_id_t context_handle, |
| int conf_req_flag, |
| gss_qop_t qop_req, |
| OM_uint32 req_output_size, |
| OM_uint32* max_input_size); |
| virtual OM_uint32 delete_sec_context( |
| OM_uint32* minor_status, |
| gss_ctx_id_t* context_handle, |
| gss_buffer_t output_token); |
| virtual OM_uint32 inquire_context( |
| OM_uint32* minor_status, |
| const gss_ctx_id_t context_handle, |
| gss_name_t* src_name, |
| gss_name_t* targ_name, |
| OM_uint32* lifetime_rec, |
| gss_OID* mech_type, |
| OM_uint32* ctx_flags, |
| int* locally_initiated, |
| int* open); |
| |
| private: |
| FRIEND_TEST_ALL_PREFIXES(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup); |
| |
| bool InitImpl(); |
| // Finds a usable dynamic library for GSSAPI and loads it. The criteria are: |
| // 1. The library must exist. |
| // 2. The library must export the functions we need. |
| base::NativeLibrary LoadSharedLibrary(); |
| bool BindMethods(base::NativeLibrary lib); |
| |
| bool initialized_; |
| |
| std::string gssapi_library_name_; |
| // Need some way to invalidate the library. |
| base::NativeLibrary gssapi_library_; |
| |
| // Function pointers |
| gss_import_name_type import_name_; |
| gss_release_name_type release_name_; |
| gss_release_buffer_type release_buffer_; |
| gss_display_name_type display_name_; |
| gss_display_status_type display_status_; |
| gss_init_sec_context_type init_sec_context_; |
| gss_wrap_size_limit_type wrap_size_limit_; |
| gss_delete_sec_context_type delete_sec_context_; |
| gss_inquire_context_type inquire_context_; |
| }; |
| |
| // ScopedSecurityContext releases a gss_ctx_id_t when it goes out of |
| // scope. |
| class ScopedSecurityContext { |
| public: |
| explicit ScopedSecurityContext(GSSAPILibrary* gssapi_lib); |
| ~ScopedSecurityContext(); |
| |
| gss_ctx_id_t get() const { return security_context_; } |
| gss_ctx_id_t* receive() { return &security_context_; } |
| |
| private: |
| gss_ctx_id_t security_context_; |
| GSSAPILibrary* gssapi_lib_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ScopedSecurityContext); |
| }; |
| |
| |
| // TODO(ahendrickson): Share code with HttpAuthSSPI. |
| class HttpAuthGSSAPI { |
| public: |
| HttpAuthGSSAPI(GSSAPILibrary* library, |
| const std::string& scheme, |
| const gss_OID gss_oid); |
| ~HttpAuthGSSAPI(); |
| |
| bool Init(); |
| |
| bool NeedsIdentity() const; |
| |
| HttpAuth::AuthorizationResult ParseChallenge( |
| HttpAuth::ChallengeTokenizer* tok); |
| |
| // Generates an authentication token. |
| // The return value is an error code. If it's not |OK|, the value of |
| // |*auth_token| is unspecified. |
| // |spn| is the Service Principal Name of the server that the token is |
| // being generated for. |
| // If this is the first round of a multiple round scheme, credentials are |
| // obtained using |*username| and |*password|. If |username| and |password| |
| // are NULL, the default credentials are used instead. |
| int GenerateAuthToken(const string16* username, |
| const string16* password, |
| const std::wstring& spn, |
| std::string* auth_token); |
| |
| // Delegation is allowed on the Kerberos ticket. This allows certain servers |
| // to act as the user, such as an IIS server retrieiving data from a |
| // Kerberized MSSQL server. |
| void Delegate(); |
| |
| private: |
| int GetNextSecurityToken(const std::wstring& spn, |
| gss_buffer_t in_token, |
| gss_buffer_t out_token); |
| |
| std::string scheme_; |
| gss_OID gss_oid_; |
| GSSAPILibrary* library_; |
| std::string decoded_server_auth_token_; |
| ScopedSecurityContext scoped_sec_context_; |
| bool can_delegate_; |
| }; |
| |
| } // namespace net |
| |
| #endif // NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_ |