#ifndef NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_
#define NET_HTTP_HTTP_AUTH_GSSAPI_POSIX_H_
#include <string>
#include <string_view>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/native_library.h"
#include "base/values.h"
#include "build/build_config.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_export.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_mechanism.h"
#if BUILDFLAG(IS_APPLE)
#include <GSS/gssapi.h>
#elif BUILDFLAG(IS_FREEBSD)
#include <gssapi/gssapi.h>
#else
#include <gssapi.h>
#endif
namespace net {
class HttpAuthChallengeTokenizer;
NET_EXPORT_PRIVATE extern gss_OID CHROME_GSS_SPNEGO_MECH_OID_DESC;
class NET_EXPORT_PRIVATE GSSAPILibrary {
public:
virtual ~GSSAPILibrary() = default;
virtual bool Init(const NetLogWithSource& net_log) = 0;
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;
virtual const std::string& GetLibraryNameForTesting() = 0;
};
class NET_EXPORT_PRIVATE GSSAPISharedLibrary : public GSSAPILibrary {
public:
explicit GSSAPISharedLibrary(const std::string& gssapi_library_name);
~GSSAPISharedLibrary() override;
bool Init(const NetLogWithSource& net_log) override;
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) override;
OM_uint32 release_name(OM_uint32* minor_status,
gss_name_t* input_name) override;
OM_uint32 release_buffer(OM_uint32* minor_status,
gss_buffer_t buffer) override;
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) override;
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) override;
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) override;
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) override;
OM_uint32 delete_sec_context(OM_uint32* minor_status,
gss_ctx_id_t* context_handle,
gss_buffer_t output_token) override;
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) override;
const std::string& GetLibraryNameForTesting() override;
private:
FRIEND_TEST_ALL_PREFIXES(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup);
bool InitImpl(const NetLogWithSource& net_log);
base::NativeLibrary LoadSharedLibrary(const NetLogWithSource& net_log);
bool BindMethods(base::NativeLibrary lib,
std::string_view library_name,
const NetLogWithSource& net_log);
bool initialized_ = false;
std::string gssapi_library_name_;
base::NativeLibrary gssapi_library_ = nullptr;
decltype(&gss_import_name) import_name_ = nullptr;
decltype(&gss_release_name) release_name_ = nullptr;
decltype(&gss_release_buffer) release_buffer_ = nullptr;
decltype(&gss_display_name) display_name_ = nullptr;
decltype(&gss_display_status) display_status_ = nullptr;
decltype(&gss_init_sec_context) init_sec_context_ = nullptr;
decltype(&gss_wrap_size_limit) wrap_size_limit_ = nullptr;
decltype(&gss_delete_sec_context) delete_sec_context_ = nullptr;
decltype(&gss_inquire_context) inquire_context_ = nullptr;
};
class ScopedSecurityContext {
public:
explicit ScopedSecurityContext(GSSAPILibrary* gssapi_lib);
ScopedSecurityContext(const ScopedSecurityContext&) = delete;
ScopedSecurityContext& operator=(const ScopedSecurityContext&) = delete;
~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_ = GSS_C_NO_CONTEXT;
raw_ptr<GSSAPILibrary> gssapi_lib_;
};
class NET_EXPORT_PRIVATE HttpAuthGSSAPI : public HttpAuthMechanism {
public:
HttpAuthGSSAPI(GSSAPILibrary* library,
const gss_OID gss_oid);
~HttpAuthGSSAPI() override;
bool Init(const NetLogWithSource& net_log) override;
bool NeedsIdentity() const override;
bool AllowsExplicitCredentials() const override;
HttpAuth::AuthorizationResult ParseChallenge(
HttpAuthChallengeTokenizer* tok) override;
int GenerateAuthToken(const AuthCredentials* credentials,
const std::string& spn,
const std::string& channel_bindings,
std::string* auth_token,
const NetLogWithSource& net_log,
CompletionOnceCallback callback) override;
void SetDelegation(HttpAuth::DelegationType delegation_type) override;
private:
int GetNextSecurityToken(const std::string& spn,
const std::string& channel_bindings,
gss_buffer_t in_token,
gss_buffer_t out_token,
const NetLogWithSource& net_log);
gss_OID gss_oid_;
raw_ptr<GSSAPILibrary> library_;
std::string decoded_server_auth_token_;
ScopedSecurityContext scoped_sec_context_;
HttpAuth::DelegationType delegation_type_ = HttpAuth::DelegationType::kNone;
};
NET_EXPORT_PRIVATE base::Value::Dict GetGssStatusCodeValue(
GSSAPILibrary* gssapi_lib,
OM_uint32 status,
OM_uint32 status_code_type);
NET_EXPORT_PRIVATE base::Value::Dict GetGssStatusValue(
GSSAPILibrary* gssapi_lib,
std::string_view method,
OM_uint32 major_status,
OM_uint32 minor_status);
NET_EXPORT_PRIVATE base::Value::Dict OidToValue(const gss_OID oid);
NET_EXPORT_PRIVATE base::Value::Dict GetDisplayNameValue(
GSSAPILibrary* gssapi_lib,
const gss_name_t gss_name);
NET_EXPORT_PRIVATE base::Value::Dict GetContextStateAsValue(
GSSAPILibrary* gssapi_lib,
const gss_ctx_id_t context_handle);
}
#endif