Skip to content

Commit

Permalink
Support specifying the GSSAPI library that will be used.
Browse files Browse the repository at this point in the history
This preference can be set either via command-line or via group policy.

BUG=53625
TEST=unittests: ConfigurationPolicyPrefStore*; net_unittests: HttpAuthHandlerNegotiateTest.*:HttpAuthGSSAPIPOSIXTest.*; manually: start Chrome with command-line switch --gssapi-library-name=XYZ and see if this results in the Chrome process loading /usr/lib/whatever/XYZ as soon as an authenticated HTTP site is encountered.

Review URL: http://codereview.chromium.org/4560001
Patch from Jakob Kummerow <jkummerow@google.com>.

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65939 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
danno@chromium.org committed Nov 12, 2010
1 parent bb33eb1 commit ac7f3fd
Show file tree
Hide file tree
Showing 26 changed files with 173 additions and 115 deletions.
6 changes: 6 additions & 0 deletions chrome/app/policy/policy_templates.grd
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,12 @@ templates and will be translated for each locale. -->
<message name="IDS_POLICY_AUTHNEGOTIATEDELEGATEWHITELIST_DESC" desc="Description of the 'auth negotiate delegate whitelist' policy.">
Servers that <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> may delegate to.
</message>
<message name="IDS_POLICY_GSSAPILIBRARYNAME_CAPTION" desc="Caption of the 'GSSAPI library name' policy">
GSSAPI library name
</message>
<message name="IDS_POLICY_GSSAPILIBRARYNAME_DESC" desc="Description of the 'GSSAPI library name' policy">
Specifies which GSSAPI library to use for HTTP Authentication. You can set either just a library name, or a full path. If no setting is provided, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will fall back to using a default library name.
</message>
<!-- End HTTP Authentication Policy messages -->

<message name="IDS_POLICY_METRICSREPORTINGENABLED_CAPTION" desc="Caption of the 'crash reporting' policy.">
Expand Down
10 changes: 10 additions & 0 deletions chrome/app/policy/policy_templates.json
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,16 @@
'example_value': 'foobar.example.com',
}
},
{
'name': 'GSSAPILibraryName',
'type': 'string',
'annotations': {
'platforms': ['linux', 'mac'],
'products': ['chrome'],
'features': {'dynamic_refresh': 0},
'example_value': 'libgssapi_krb5.so.2',
}
},
]
},
{
Expand Down
3 changes: 3 additions & 0 deletions chrome/browser/io_thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ IOThread::IOThread(PrefService* local_state)
auth_server_whitelist_ = local_state->GetString(prefs::kAuthServerWhitelist);
auth_delegate_whitelist_ = local_state->GetString(
prefs::kAuthNegotiateDelegateWhitelist);
gssapi_library_name_ = local_state->GetString(prefs::kGSSAPILibraryName);
}

IOThread::~IOThread() {
Expand Down Expand Up @@ -428,6 +429,7 @@ void IOThread::RegisterPrefs(PrefService* local_state) {
local_state->RegisterBooleanPref(prefs::kEnableAuthNegotiatePort, false);
local_state->RegisterStringPref(prefs::kAuthServerWhitelist, "");
local_state->RegisterStringPref(prefs::kAuthNegotiateDelegateWhitelist, "");
local_state->RegisterStringPref(prefs::kGSSAPILibraryName, "");
}

net::HttpAuthHandlerFactory* IOThread::CreateDefaultAuthHandlerFactory(
Expand All @@ -447,6 +449,7 @@ net::HttpAuthHandlerFactory* IOThread::CreateDefaultAuthHandlerFactory(
supported_schemes,
globals_->url_security_manager.get(),
resolver,
gssapi_library_name_,
negotiate_disable_cname_lookup_,
negotiate_enable_port_);
}
Expand Down
1 change: 1 addition & 0 deletions chrome/browser/io_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ class IOThread : public BrowserProcessSubThread {
bool negotiate_enable_port_;
std::string auth_server_whitelist_;
std::string auth_delegate_whitelist_;
std::string gssapi_library_name_;

// These member variables are initialized by a task posted to the IO thread,
// which gets posted by calling certain member functions of IOThread.
Expand Down
5 changes: 5 additions & 0 deletions chrome/browser/policy/configuration_policy_pref_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ const ConfigurationPolicyPrefStore::PolicyToPreferenceMapEntry
prefs::kAuthServerWhitelist },
{ Value::TYPE_STRING, kPolicyAuthNegotiateDelegateWhitelist,
prefs::kAuthNegotiateDelegateWhitelist },
{ Value::TYPE_STRING, kPolicyGSSAPILibraryName,
prefs::kGSSAPILibraryName },

#if defined(OS_CHROMEOS)
{ Value::TYPE_BOOLEAN, kPolicyChromeOsLockOnIdleSuspend,
Expand Down Expand Up @@ -269,6 +271,9 @@ ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList() {
key::kAuthServerWhitelist },
{ kPolicyAuthNegotiateDelegateWhitelist, Value::TYPE_STRING,
key::kAuthNegotiateDelegateWhitelist },
{ kPolicyGSSAPILibraryName, Value::TYPE_STRING,
key::kGSSAPILibraryName },


#if defined(OS_CHROMEOS)
{ kPolicyChromeOsLockOnIdleSuspend, Value::TYPE_BOOLEAN,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@ INSTANTIATE_TEST_CASE_P(
TypeAndName(kPolicyAuthServerWhitelist,
prefs::kAuthServerWhitelist),
TypeAndName(kPolicyAuthNegotiateDelegateWhitelist,
prefs::kAuthNegotiateDelegateWhitelist)));
prefs::kAuthNegotiateDelegateWhitelist),
TypeAndName(kPolicyGSSAPILibraryName,
prefs::kGSSAPILibraryName)));

// Test cases for boolean-valued policy settings.
class ConfigurationPolicyPrefStoreBooleanTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ enum ConfigurationPolicyType {
kPolicyEnableAuthNegotiatePort,
kPolicyAuthServerWhitelist,
kPolicyAuthNegotiateDelegateWhitelist,

kPolicyGSSAPILibraryName,
};

static const int kPolicyNoProxyServerMode = 0;
Expand Down
1 change: 1 addition & 0 deletions chrome/browser/prefs/command_line_pref_store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const CommandLinePrefStore::StringSwitchToPreferenceMapEntry
{ switches::kAuthServerWhitelist, prefs::kAuthServerWhitelist },
{ switches::kAuthNegotiateDelegateWhitelist,
prefs::kAuthNegotiateDelegateWhitelist },
{ switches::kGSSAPILibraryName, prefs::kGSSAPILibraryName },
};

const CommandLinePrefStore::BooleanSwitchToPreferenceMapEntry
Expand Down
3 changes: 3 additions & 0 deletions chrome/common/chrome_switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,9 @@ const char kGpuProcess[] = "gpu-process";
// Causes the GPU process to display a dialog on launch.
const char kGpuStartupDialog[] = "gpu-startup-dialog";

// Specifies a custom name for the GSSAPI library to load.
const char kGSSAPILibraryName[] = "gssapi-library-name";

// These flags show the man page on Linux. They are equivalent to each
// other.
const char kHelp[] = "help";
Expand Down
1 change: 1 addition & 0 deletions chrome/common/chrome_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ extern const char kForceRendererAccessibility[];
extern const char kGpuLauncher[];
extern const char kGpuProcess[];
extern const char kGpuStartupDialog[];
extern const char kGSSAPILibraryName[];
extern const char kHelp[];
extern const char kHelpShort[];
extern const char kHideIcons[];
Expand Down
1 change: 1 addition & 0 deletions chrome/common/policy_constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const char kDisableAuthNegotiateCnameLookup[] =
const char kEnableAuthNegotiatePort[] = "EnableAuthNegotiatePort";
const char kAuthServerWhitelist[] = "AuthServerWhitelist";
const char kAuthNegotiateDelegateWhitelist[] = "AuthNegotiateDelegateWhitelist";
const char kGSSAPILibraryName[] = "GSSAPILibraryName";

// Chrome Frame specific policy constants
const char kChromeFrameRendererSettings[] = "ChromeFrameRendererSettings";
Expand Down
1 change: 1 addition & 0 deletions chrome/common/policy_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ extern const char kDisableAuthNegotiateCnameLookup[];
extern const char kEnableAuthNegotiatePort[];
extern const char kAuthServerWhitelist[];
extern const char kAuthNegotiateDelegateWhitelist[];
extern const char kGSSAPILibraryName[];

// Chrome Frame specific policy constants
extern const char kChromeFrameRendererSettings[];
Expand Down
2 changes: 2 additions & 0 deletions chrome/common/pref_names.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,8 @@ const char kAuthServerWhitelist[] = "auth.server_whitelist";
// with.
const char kAuthNegotiateDelegateWhitelist[] =
"auth.negotiate_delegate_whitelist";
// String that specifies the name of a custom GSSAPI library to load.
const char kGSSAPILibraryName[] = "auth.gssapi_library_name";

#if defined(OS_CHROMEOS)
// Dictionary for transient storage of settings that should go into signed
Expand Down
1 change: 1 addition & 0 deletions chrome/common/pref_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ extern const char kDisableAuthNegotiateCnameLookup[];
extern const char kEnableAuthNegotiatePort[];
extern const char kAuthServerWhitelist[];
extern const char kAuthNegotiateDelegateWhitelist[];
extern const char kGSSAPILibraryName[];

} // namespace prefs

Expand Down
8 changes: 5 additions & 3 deletions chrome_frame/metrics_service.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@

#include <atlbase.h>
#include <atlwin.h>
#include <windows.h>
#include <objbase.h>
#include <windows.h>

#include <vector>

#if defined(USE_SYSTEM_LIBBZ2)
#include <bzlib.h>
Expand Down Expand Up @@ -168,8 +170,8 @@ class ChromeFrameUploadRequestContext : public URLRequestContext {
base::SplitString(csv_auth_schemes, ',', &supported_schemes);

http_auth_handler_factory_ = net::HttpAuthHandlerRegistryFactory::Create(
supported_schemes, url_security_manager_.get(), host_resolver_, false,
false);
supported_schemes, url_security_manager_.get(), host_resolver_,
std::string(), false, false);

http_transaction_factory_ = new net::HttpCache(
net::HttpNetworkLayer::CreateFactory(host_resolver_,
Expand Down
33 changes: 20 additions & 13 deletions net/http/http_auth_gssapi_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "base/file_path.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/singleton.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "net/base/net_errors.h"
Expand Down Expand Up @@ -385,8 +384,9 @@ std::string DescribeContext(GSSAPILibrary* gssapi_lib,

} // namespace

GSSAPISharedLibrary::GSSAPISharedLibrary()
GSSAPISharedLibrary::GSSAPISharedLibrary(const std::string& gssapi_library_name)
: initialized_(false),
gssapi_library_name_(gssapi_library_name),
gssapi_library_(NULL),
import_name_(NULL),
release_name_(NULL),
Expand Down Expand Up @@ -422,19 +422,29 @@ bool GSSAPISharedLibrary::InitImpl() {
}

base::NativeLibrary GSSAPISharedLibrary::LoadSharedLibrary() {
static const char* kLibraryNames[] = {
const char** library_names;
size_t num_lib_names;
const char* user_specified_library[1];
if (!gssapi_library_name_.empty()) {
user_specified_library[0] = gssapi_library_name_.c_str();
library_names = user_specified_library;
num_lib_names = 1;
} else {
static const char* kDefaultLibraryNames[] = {
#if defined(OS_MACOSX)
"libgssapi_krb5.dylib" // MIT Kerberos
"libgssapi_krb5.dylib" // MIT Kerberos
#else
"libgssapi_krb5.so.2", // MIT Kerberos - FC, Suse10, Debian
"libgssapi.so.4", // Heimdal - Suse10, MDK
"libgssapi.so.1" // Heimdal - Suse9, CITI - FC, MDK, Suse10
"libgssapi_krb5.so.2", // MIT Kerberos - FC, Suse10, Debian
"libgssapi.so.4", // Heimdal - Suse10, MDK
"libgssapi.so.1" // Heimdal - Suse9, CITI - FC, MDK, Suse10
#endif
};
static size_t num_lib_names = arraysize(kLibraryNames);
};
library_names = kDefaultLibraryNames;
num_lib_names = arraysize(kDefaultLibraryNames);
}

for (size_t i = 0; i < num_lib_names; ++i) {
const char* library_name = kLibraryNames[i];
const char* library_name = library_names[i];
FilePath file_path(library_name);
base::NativeLibrary lib = base::LoadNativeLibrary(file_path);
if (lib) {
Expand Down Expand Up @@ -613,9 +623,6 @@ OM_uint32 GSSAPISharedLibrary::inquire_context(
locally_initiated,
open);
}
GSSAPILibrary* GSSAPILibrary::GetDefault() {
return Singleton<GSSAPISharedLibrary>::get();
}

ScopedSecurityContext::ScopedSecurityContext(GSSAPILibrary* gssapi_lib)
: security_context_(GSS_C_NO_CONTEXT),
Expand Down
8 changes: 4 additions & 4 deletions net/http/http_auth_gssapi_posix.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,14 @@ class GSSAPILibrary {
int* locally_initiated,
int* open) = 0;

// Get the default GSSPILibrary instance. The object returned is a singleton
// instance, and the caller should not delete it.
static GSSAPILibrary* GetDefault();
};

// GSSAPISharedLibrary class is defined here so that unit tests can access it.
class GSSAPISharedLibrary : public GSSAPILibrary {
public:
GSSAPISharedLibrary();
// 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:
Expand Down Expand Up @@ -179,6 +178,7 @@ class GSSAPISharedLibrary : public GSSAPILibrary {

bool initialized_;

std::string gssapi_library_name_;
// Need some way to invalidate the library.
base::NativeLibrary gssapi_library_;

Expand Down
12 changes: 9 additions & 3 deletions net/http/http_auth_gssapi_posix_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,15 @@ TEST(HttpAuthGSSAPIPOSIXTest, GSSAPIStartup) {
// TODO(ahendrickson): Manipulate the libraries and paths to test each of the
// libraries we expect, and also whether or not they have the interface
// functions we want.
GSSAPILibrary* gssapi = GSSAPILibrary::GetDefault();
DCHECK(gssapi);
gssapi->Init();
scoped_ptr<GSSAPILibrary> gssapi(new GSSAPISharedLibrary(""));
DCHECK(gssapi.get());
DCHECK(gssapi.get()->Init());
}

TEST(HttpAuthGSSAPIPOSIXTest, GSSAPILoadCustomLibrary) {
scoped_ptr<GSSAPILibrary> gssapi(
new GSSAPISharedLibrary("/this/library/does/not/exist"));
DCHECK(!gssapi.get()->Init());
}

TEST(HttpAuthGSSAPIPOSIXTest, GSSAPICycle) {
Expand Down
25 changes: 23 additions & 2 deletions net/http/http_auth_handler_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,23 @@ HttpAuthHandlerRegistryFactory* HttpAuthHandlerFactory::CreateDefault(
"basic", new HttpAuthHandlerBasic::Factory());
registry_factory->RegisterSchemeFactory(
"digest", new HttpAuthHandlerDigest::Factory());

HttpAuthHandlerNegotiate::Factory* negotiate_factory =
new HttpAuthHandlerNegotiate::Factory();
#if defined(OS_POSIX)
negotiate_factory->set_library(new GSSAPISharedLibrary(std::string()));
#elif defined(OS_WIN)
negotiate_factory->set_library(new SSPILibraryDefault());
#endif
negotiate_factory->set_host_resolver(host_resolver);
registry_factory->RegisterSchemeFactory("negotiate", negotiate_factory);
registry_factory->RegisterSchemeFactory(
"ntlm", new HttpAuthHandlerNTLM::Factory());

HttpAuthHandlerNTLM::Factory* ntlm_factory =
new HttpAuthHandlerNTLM::Factory();
#if defined(OS_WIN)
ntlm_factory->set_sspi_library(new SSPILibraryDefault());
#endif
registry_factory->RegisterSchemeFactory("ntlm", ntlm_factory);
return registry_factory;
}

Expand All @@ -73,6 +84,7 @@ HttpAuthHandlerRegistryFactory* HttpAuthHandlerRegistryFactory::Create(
const std::vector<std::string>& supported_schemes,
URLSecurityManager* security_manager,
HostResolver* host_resolver,
const std::string& gssapi_library_name,
bool negotiate_disable_cname_lookup,
bool negotiate_enable_port) {
HttpAuthHandlerRegistryFactory* registry_factory =
Expand All @@ -87,11 +99,20 @@ HttpAuthHandlerRegistryFactory* HttpAuthHandlerRegistryFactory::Create(
HttpAuthHandlerNTLM::Factory* ntlm_factory =
new HttpAuthHandlerNTLM::Factory();
ntlm_factory->set_url_security_manager(security_manager);
#if defined(OS_WIN)
ntlm_factory->set_sspi_library(new SSPILibraryDefault());
#endif
registry_factory->RegisterSchemeFactory("ntlm", ntlm_factory);
}
if (IsSupportedScheme(supported_schemes, "negotiate")) {
HttpAuthHandlerNegotiate::Factory* negotiate_factory =
new HttpAuthHandlerNegotiate::Factory();
#if defined(OS_POSIX)
negotiate_factory->set_library(
new GSSAPISharedLibrary(gssapi_library_name));
#elif defined(OS_WIN)
negotiate_factory->set_library(new SSPILibraryDefault());
#endif
negotiate_factory->set_url_security_manager(security_manager);
DCHECK(host_resolver || negotiate_disable_cname_lookup);
negotiate_factory->set_host_resolver(host_resolver);
Expand Down
4 changes: 4 additions & 0 deletions net/http/http_auth_handler_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,12 +174,16 @@ class HttpAuthHandlerRegistryFactory : public HttpAuthHandlerFactory {
// scheme is used and |negotiate_disable_cname_lookup| is false,
// |host_resolver| must not be NULL.
//
// |gssapi_library_name| specifies the name of the GSSAPI library that will
// be loaded on all platforms except Windows.
//
// |negotiate_disable_cname_lookup| and |negotiate_enable_port| both control
// how Negotiate does SPN generation, by default these should be false.
static HttpAuthHandlerRegistryFactory* Create(
const std::vector<std::string>& supported_schemes,
URLSecurityManager* security_manager,
HostResolver* host_resolver,
const std::string& gssapi_library_name,
bool negotiate_disable_cname_lookup,
bool negotiate_enable_port);

Expand Down
Loading

0 comments on commit ac7f3fd

Please sign in to comment.