Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2043)

Unified Diff: net/http/http_auth_handler_ntlm_portable.cc

Issue 388063005: Add NTLM single-sign-on support via Samba's ntlm_auth helper Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Review feedback Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/http/http_auth_handler_ntlm.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_auth_handler_ntlm_portable.cc
diff --git a/net/http/http_auth_handler_ntlm_portable.cc b/net/http/http_auth_handler_ntlm_portable.cc
index 035a6dc80170c091536c615c49c013332ce13b73..d38228cc58af416b039c79ae1d1ac91e8baf9dfc 100644
--- a/net/http/http_auth_handler_ntlm_portable.cc
+++ b/net/http/http_auth_handler_ntlm_portable.cc
@@ -12,7 +12,10 @@
#include <winsock2.h>
#endif
+#include "base/base64.h"
#include "base/md5.h"
+#include "base/process/kill.h"
+#include "base/process/launch.h"
#include "base/rand_util.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
@@ -631,28 +634,177 @@ HttpAuthHandlerNTLM::generate_random_proc_ = GenerateRandom;
HttpAuthHandlerNTLM::HostNameProc
HttpAuthHandlerNTLM::get_host_name_proc_ = GetHostName;
-HttpAuthHandlerNTLM::HttpAuthHandlerNTLM() {
+HttpAuthHandlerNTLM::HttpAuthHandlerNTLM(
+ URLSecurityManager* url_security_manager)
+ : url_security_manager_(url_security_manager) {
+ helpername_ = getenv("CHROME_NTLM_USER_HELPER");
+ if (!helpername_)
+ helpername_ = "/usr/bin/ntlm_auth";
+ try_winbind_ = !access(helpername_, X_OK);
+ ntlm_write_pipe_ = -1;
+ ntlm_read_pipe_ = -1;
+ ntlm_auth_handle_ = -1;
}
bool HttpAuthHandlerNTLM::NeedsIdentity() {
- // This gets called for each round-trip. Only require identity on
- // the first call (when auth_data_ is empty). On subsequent calls,
- // we use the initially established identity.
- return auth_data_.empty();
+ // If we think winbind might be available, return true on the first phase
+ // (when auth_data_ is empty) so that the default identity gets selected.
+ // If it's *not* available, then only return true on the second phase.
+ // This works even for the case where winbind *might* be available, but
+ // turns out not to be when we actually get round to checking for it.
+ // In that case, we'll send the portable challenge in the first phase
+ // after we realise winbind can't help us, and then get a real identity
+ // in time for the second phase.
+ return !try_winbind_ ^ auth_data_.empty();
}
-bool HttpAuthHandlerNTLM::AllowsDefaultCredentials() {
- // Default credentials are not supported in the portable implementation of
- // NTLM, but are supported in the SSPI implementation.
+bool HttpAuthHandlerNTLM::start_ntlm_helper_() {
+ /* fork_ntlm_auth_with_pipes(); */
+ int writepipe[2] = {-1, -1}; /* parent -> child */
+ int readpipe [2] = {-1, -1}; /* child -> parent */
+
+ if ( pipe(readpipe) < 0 || pipe(writepipe) < 0 )
+ {
+ VLOG(1) << "Failed to open pipes for ntlm_auth helper";
+ return false;
+ }
+ char *username = getenv("NTLMUSER");
+ if (!username)
+ username = getenv("USER");
+ if (!username) {
+ VLOG(1) << "No username. No automatic NTLM";
+ return false;
+ }
+
+ std::vector<std::string> args;
+ base::LaunchOptions options;
+ base::FileHandleMappingVector fds_to_remap;
+
+ args.push_back(helpername_);
+ args.push_back("--helper-protocol");
+ args.push_back("ntlmssp-client-1");
+ args.push_back("--use-cached-creds");
+ args.push_back("--username");
+ args.push_back(username);
+
+ fds_to_remap.push_back(std::make_pair(readpipe[1], 1));
+ fds_to_remap.push_back(std::make_pair(writepipe[0], 0));
+
+
+ options.wait = false;
+ options.fds_to_remap = &fds_to_remap;
+
+ if (base::LaunchProcess(args, options, &ntlm_auth_handle_) == false) {
+ VLOG(1) << "Failed to launch ntlm_auth helper";
+ close(writepipe[0]);
+ close(writepipe[1]);
+ close(readpipe[0]);
+ close(readpipe[1]);
+ return false;
+ }
+ ntlm_write_pipe_ = writepipe[1];
+ close(writepipe[0]);
+
+ ntlm_read_pipe_ = readpipe[0];
+ close(readpipe[1]);
+
+ if (write(ntlm_write_pipe_, "YR\n", 3) != 3) {
+ VLOG(1) << "Failed to send YR to ntlm_auth: " << strerror(errno);
+ return false;
+ }
+ return true;
+}
+
+void HttpAuthHandlerNTLM::OnFileCanWriteWithoutBlocking(int fd) {
+ NOTREACHED();
+}
+
+static bool read_line(int fd, char *buf, int len) {
+
+ while (len) {
+ int result = read(fd, buf, len);
+ if (result <= 0)
+ return false;
+ else {
+ if (buf[result - 1] == '\n') {
+ buf[result - 1] = 0;
+ return true;
+ }
+ buf += result;
+ len -= result;
+ }
+ }
return false;
}
+void HttpAuthHandlerNTLM::OnFileCanReadWithoutBlocking(int fd) {
+
+ char buf[1024];
+ if (!read_line(ntlm_read_pipe_, buf, sizeof(buf))) {
+ VLOG(1) << "Read initial response from ntlm_auth failed";
+ fall_back_to_portable:
+ void *out_buf;
+ uint32 out_buf_len;
+
+ int rv = GenerateType1Msg(&out_buf, &out_buf_len);
+ if (rv != OK) {
+ token_callback_.Run(rv);
+ return;
+ }
+
+ // Base64 encode data in output buffer and prepend "NTLM ".
+ std::string encode_input(static_cast<char*>(out_buf), out_buf_len);
+ std::string encode_output;
+ base::Base64Encode(encode_input, &encode_output);
+ // OK, we are done with |out_buf|
+ free(out_buf);
+ *callback_auth_token_ = std::string("NTLM ") + encode_output;
+
+ token_callback_.Run(OK);
+ ntlm_read_watcher_.StopWatchingFileDescriptor();
+ try_winbind_ = false;
+ return;
+ }
+ if (!strcmp(buf, "PW")) {
+ VLOG(1) << "ntlm_auth asks for password";
+ goto fall_back_to_portable;
+ }
+ if (strncmp(buf, "YR ", 3) && strncmp(buf, "KK ", 3) &&
+ strncmp(buf, "AF ", 3)) {
+ VLOG(1) << "Unknown response from ntlm_auth: " << buf;
+ goto fall_back_to_portable;
+ }
+
+ VLOG(1) << "Yay, ntlm_auth gives challenge: " << buf;
+ *callback_auth_token_ = std::string("NTLM ") + std::string(buf + 3);
+ return token_callback_.Run(OK);
+}
+
+bool HttpAuthHandlerNTLM::AllowsDefaultCredentials() {
+ // Always return true (assuning the UrlSecurityManager permits it) if
+ // it looks like the winbind helper even might be available; we can't
+ // check properly yet because we need to do that asynchronously.
+ if (!try_winbind_)
+ return false;
+ if (target_ == HttpAuth::AUTH_PROXY)
+ return true;
+ if (!url_security_manager_)
+ return false;
+ return url_security_manager_->CanUseDefaultCredentials(origin_);
+}
+
int HttpAuthHandlerNTLM::InitializeBeforeFirstChallenge() {
return OK;
}
HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() {
credentials_.Zap();
+ if (ntlm_write_pipe_ != -1)
+ close(ntlm_write_pipe_);
+ if (ntlm_read_pipe_ != -1)
+ close(ntlm_read_pipe_);
+ if (ntlm_auth_handle_ != -1)
+ base::KillProcess(ntlm_auth_handle_, 1, true);
}
// static
@@ -720,7 +872,8 @@ int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
// method and only constructing when valid.
// NOTE: Default credentials are not supported for the portable implementation
// of NTLM.
- scoped_ptr<HttpAuthHandler> tmp_handler(new HttpAuthHandlerNTLM);
+ scoped_ptr<HttpAuthHandler> tmp_handler(
+ new HttpAuthHandlerNTLM(url_security_manager()));
if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
return ERR_INVALID_RESPONSE;
handler->swap(tmp_handler);
« no previous file with comments | « net/http/http_auth_handler_ntlm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698