summaryrefslogtreecommitdiffstats
path: root/java/com/google/gerrit/httpd/auth/ldap/LdapLoginServlet.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/google/gerrit/httpd/auth/ldap/LdapLoginServlet.java')
-rw-r--r--java/com/google/gerrit/httpd/auth/ldap/LdapLoginServlet.java154
1 files changed, 154 insertions, 0 deletions
diff --git a/java/com/google/gerrit/httpd/auth/ldap/LdapLoginServlet.java b/java/com/google/gerrit/httpd/auth/ldap/LdapLoginServlet.java
new file mode 100644
index 0000000000..a09866e603
--- /dev/null
+++ b/java/com/google/gerrit/httpd/auth/ldap/LdapLoginServlet.java
@@ -0,0 +1,154 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.httpd.auth.ldap;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Strings;
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.common.Nullable;
+import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.httpd.CanonicalWebUrl;
+import com.google.gerrit.httpd.HtmlDomUtil;
+import com.google.gerrit.httpd.LoginUrlToken;
+import com.google.gerrit.httpd.WebSession;
+import com.google.gerrit.httpd.template.SiteHeaderFooter;
+import com.google.gerrit.server.account.AccountException;
+import com.google.gerrit.server.account.AccountManager;
+import com.google.gerrit.server.account.AccountUserNameException;
+import com.google.gerrit.server.account.AuthRequest;
+import com.google.gerrit.server.account.AuthResult;
+import com.google.gerrit.server.account.AuthenticationFailedException;
+import com.google.gerrit.server.auth.AuthenticationUnavailableException;
+import com.google.gerrit.util.http.CacheHeaders;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/** Handles username/password based authentication against the directory. */
+@Singleton
+class LdapLoginServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+ private final AccountManager accountManager;
+ private final DynamicItem<WebSession> webSession;
+ private final CanonicalWebUrl urlProvider;
+ private final SiteHeaderFooter headers;
+
+ @Inject
+ LdapLoginServlet(
+ AccountManager accountManager,
+ DynamicItem<WebSession> webSession,
+ CanonicalWebUrl urlProvider,
+ SiteHeaderFooter headers) {
+ this.accountManager = accountManager;
+ this.webSession = webSession;
+ this.urlProvider = urlProvider;
+ this.headers = headers;
+ }
+
+ private void sendForm(
+ HttpServletRequest req, HttpServletResponse res, @Nullable String errorMessage)
+ throws IOException {
+ String self = req.getRequestURI();
+ String cancel = MoreObjects.firstNonNull(urlProvider.get(req), "/");
+ cancel += LoginUrlToken.getToken(req);
+
+ Document doc = headers.parse(LdapLoginServlet.class, "LoginForm.html");
+ HtmlDomUtil.find(doc, "hostName").setTextContent(req.getServerName());
+ HtmlDomUtil.find(doc, "login_form").setAttribute("action", self);
+ HtmlDomUtil.find(doc, "cancel_link").setAttribute("href", cancel);
+
+ Element emsg = HtmlDomUtil.find(doc, "error_message");
+ if (Strings.isNullOrEmpty(errorMessage)) {
+ emsg.getParentNode().removeChild(emsg);
+ } else {
+ emsg.setTextContent(errorMessage);
+ }
+
+ byte[] bin = HtmlDomUtil.toUTF8(doc);
+ res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
+ res.setContentType("text/html");
+ res.setCharacterEncoding(UTF_8.name());
+ res.setContentLength(bin.length);
+ try (ServletOutputStream out = res.getOutputStream()) {
+ out.write(bin);
+ }
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
+ sendForm(req, res, null);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse res)
+ throws ServletException, IOException {
+ req.setCharacterEncoding(UTF_8.name());
+ String username = Strings.nullToEmpty(req.getParameter("username")).trim();
+ String password = Strings.nullToEmpty(req.getParameter("password"));
+ String remember = Strings.nullToEmpty(req.getParameter("rememberme"));
+ if (username.isEmpty() || password.isEmpty()) {
+ sendForm(req, res, "Invalid username or password.");
+ return;
+ }
+
+ AuthRequest areq = AuthRequest.forUser(username);
+ areq.setPassword(password);
+
+ AuthResult ares;
+ try {
+ ares = accountManager.authenticate(areq);
+ } catch (AccountUserNameException e) {
+ sendForm(req, res, e.getMessage());
+ return;
+ } catch (AuthenticationUnavailableException e) {
+ sendForm(req, res, "Authentication unavailable at this time.");
+ return;
+ } catch (AuthenticationFailedException e) {
+ // This exception is thrown if the user provided wrong credentials, we don't need to log a
+ // stacktrace for it.
+ logger.atWarning().log("'%s' failed to sign in: %s", username, e.getMessage());
+ sendForm(req, res, "Invalid username or password.");
+ return;
+ } catch (AccountException e) {
+ logger.atWarning().withCause(e).log("'%s' failed to sign in", username);
+ sendForm(req, res, "Authentication failed.");
+ return;
+ } catch (RuntimeException e) {
+ logger.atSevere().withCause(e).log("LDAP authentication failed");
+ sendForm(req, res, "Authentication unavailable at this time.");
+ return;
+ }
+
+ StringBuilder dest = new StringBuilder();
+ dest.append(urlProvider.get(req));
+ dest.append(LoginUrlToken.getToken(req));
+
+ CacheHeaders.setNotCacheable(res);
+ webSession.get().login(ares, "1".equals(remember));
+ res.sendRedirect(dest.toString());
+ }
+}