Home | History | Annotate | Download | only in http
      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