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