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