diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java index 0c08fb9e9a..ad46358cc1 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgCGIServlet.java @@ -47,12 +47,14 @@ import sonia.scm.repository.RepositoryManager; import sonia.scm.util.AssertUtil; import sonia.scm.web.cgi.CGIExecutor; import sonia.scm.web.cgi.CGIExecutorFactory; +import sonia.scm.web.cgi.EnvList; //~--- JDK imports ------------------------------------------------------------ import java.io.File; import java.io.IOException; +import java.util.Enumeration; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -60,6 +62,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; /** * @@ -78,6 +81,9 @@ public class HgCGIServlet extends HttpServlet /** Field description */ public static final String ENV_REPOSITORY_PATH = "SCM_REPOSITORY_PATH"; + /** Field description */ + public static final String ENV_SESSION_PREFIX = "SCM_"; + /** Field description */ private static final long serialVersionUID = -3492811300905099810L; @@ -175,6 +181,13 @@ public class HgCGIServlet extends HttpServlet directory.getAbsolutePath()); executor.getEnvironment().set(ENV_PYTHON_PATH, pythonPath); + HttpSession session = request.getSession(); + + if (session != null) + { + passSessionAttributes(executor.getEnvironment(), session); + } + String interpreter = getInterpreter(); if (interpreter != null) @@ -185,6 +198,28 @@ public class HgCGIServlet extends HttpServlet executor.execute(command.getAbsolutePath()); } + /** + * Method description + * + * + * @param env + * @param session + */ + private void passSessionAttributes(EnvList env, HttpSession session) + { + Enumeration enm = session.getAttributeNames(); + + while (enm.hasMoreElements()) + { + String key = enm.nextElement(); + + if (key.startsWith(ENV_SESSION_PREFIX)) + { + env.set(key, session.getAttribute(key).toString()); + } + } + } + //~--- get methods ---------------------------------------------------------- /** diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java index 62b50cb443..a59303ae02 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java @@ -49,8 +49,10 @@ import sonia.scm.repository.HgRepositoryHookEvent; import sonia.scm.repository.RepositoryHookType; import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryNotFoundException; +import sonia.scm.security.CipherUtil; import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; +import sonia.scm.web.security.WebSecurityContext; //~--- JDK imports ------------------------------------------------------------ @@ -81,6 +83,9 @@ public class HgHookCallbackServlet extends HttpServlet /** Field description */ private static final String PARAM_CHALLENGE = "challenge"; + /** Field description */ + private static final String PARAM_CREDENTIALS = "credentials"; + /** Field description */ private static final String PARAM_NODE = "node"; @@ -102,17 +107,19 @@ public class HgHookCallbackServlet extends HttpServlet * @param handler * @param hookManager * @param contextProvider + * @param securityContextProvider */ @Inject - public HgHookCallbackServlet(RepositoryManager repositoryManager, - HgRepositoryHandler handler, - HgHookManager hookManager, - Provider contextProvider) + public HgHookCallbackServlet( + RepositoryManager repositoryManager, HgRepositoryHandler handler, + HgHookManager hookManager, Provider contextProvider, + Provider securityContextProvider) { this.repositoryManager = repositoryManager; this.handler = handler; this.hookManager = hookManager; this.contextProvider = contextProvider; + this.securityContextProvider = securityContextProvider; } //~--- methods -------------------------------------------------------------- @@ -147,6 +154,13 @@ public class HgHookCallbackServlet extends HttpServlet if (Util.isNotEmpty(node)) { + String credentials = request.getParameter(PARAM_CREDENTIALS); + + if (Util.isNotEmpty(credentials)) + { + authenticate(request, response, credentials); + } + hookCallback(response, repositoryId, type, challenge, node); } else if (logger.isDebugEnabled()) @@ -170,6 +184,40 @@ public class HgHookCallbackServlet extends HttpServlet } } + /** + * Method description + * + * + * @param request + * @param response + * @param credentials + */ + private void authenticate(HttpServletRequest request, + HttpServletResponse response, String credentials) + { + try + { + credentials = CipherUtil.getInstance().decode(credentials); + + if (Util.isNotEmpty(credentials)) + { + String[] credentialsArray = credentials.split(":"); + + if (credentialsArray.length >= 2) + { + WebSecurityContext context = securityContextProvider.get(); + + context.authenticate(request, response, credentialsArray[0], + credentialsArray[1]); + } + } + } + catch (Exception ex) + { + logger.error("could not authenticate user", ex); + } + } + /** * Method description * @@ -281,4 +329,7 @@ public class HgHookCallbackServlet extends HttpServlet /** Field description */ private RepositoryManager repositoryManager; + + /** Field description */ + private Provider securityContextProvider; } diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py index 4daef36aa7..3e28fa2bef 100644 --- a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py +++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hghook.py @@ -40,6 +40,7 @@ import os, urllib baseUrl = "${url}" challenge = "${challenge}" +credentials = os.environ['SCM_CREDENTIALS'] def callback(ui, repo, hooktype, node=None, source=None, **kwargs): failure = True @@ -47,7 +48,7 @@ def callback(ui, repo, hooktype, node=None, source=None, **kwargs): try: url = baseUrl + os.path.basename(repo.root) + "/" + hooktype ui.debug( "send scm-hook to " + url + " and " + node + "\n" ) - data = urllib.urlencode({'node': node, 'challenge': challenge}) + data = urllib.urlencode({'node': node, 'challenge': challenge, 'credentials': credentials}) conn = urllib.urlopen(url, data); if conn.code >= 200 and conn.code < 300: ui.debug( "scm-hook " + hooktype + " success with status code " + str(conn.code) + "\n" ) diff --git a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java index 1cbf49d620..58891c3a47 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java +++ b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java @@ -44,6 +44,7 @@ import org.slf4j.LoggerFactory; import sonia.scm.config.ScmConfiguration; import sonia.scm.group.Group; import sonia.scm.group.GroupManager; +import sonia.scm.security.CipherUtil; import sonia.scm.user.User; import sonia.scm.user.UserManager; import sonia.scm.util.Util; @@ -67,6 +68,9 @@ import javax.servlet.http.HttpSession; public class BasicSecurityContext implements WebSecurityContext { + /** Field description */ + public static final String SCM_CREDENTIALS = "SCM_CREDENTIALS"; + /** Field description */ public static final String USER_ANONYMOUS = "anonymous"; @@ -154,6 +158,16 @@ public class BasicSecurityContext implements WebSecurityContext { logGroups(); } + + String credentials = dbUser.getName(); + + if (Util.isNotEmpty(password)) + { + credentials = credentials.concat(":").concat(password); + } + + credentials = CipherUtil.getInstance().encode(credentials); + request.getSession(true).setAttribute(SCM_CREDENTIALS, credentials); } catch (Exception ex) {