reauthenticate user on mercurial hooks

This commit is contained in:
Sebastian Sdorra
2011-10-15 15:55:17 +02:00
parent 6328a14654
commit 84f63e94c0
4 changed files with 106 additions and 5 deletions

View File

@@ -47,12 +47,14 @@ import sonia.scm.repository.RepositoryManager;
import sonia.scm.util.AssertUtil; import sonia.scm.util.AssertUtil;
import sonia.scm.web.cgi.CGIExecutor; import sonia.scm.web.cgi.CGIExecutor;
import sonia.scm.web.cgi.CGIExecutorFactory; import sonia.scm.web.cgi.CGIExecutorFactory;
import sonia.scm.web.cgi.EnvList;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Enumeration;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -60,6 +62,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/** /**
* *
@@ -78,6 +81,9 @@ public class HgCGIServlet extends HttpServlet
/** Field description */ /** Field description */
public static final String ENV_REPOSITORY_PATH = "SCM_REPOSITORY_PATH"; public static final String ENV_REPOSITORY_PATH = "SCM_REPOSITORY_PATH";
/** Field description */
public static final String ENV_SESSION_PREFIX = "SCM_";
/** Field description */ /** Field description */
private static final long serialVersionUID = -3492811300905099810L; private static final long serialVersionUID = -3492811300905099810L;
@@ -175,6 +181,13 @@ public class HgCGIServlet extends HttpServlet
directory.getAbsolutePath()); directory.getAbsolutePath());
executor.getEnvironment().set(ENV_PYTHON_PATH, pythonPath); executor.getEnvironment().set(ENV_PYTHON_PATH, pythonPath);
HttpSession session = request.getSession();
if (session != null)
{
passSessionAttributes(executor.getEnvironment(), session);
}
String interpreter = getInterpreter(); String interpreter = getInterpreter();
if (interpreter != null) if (interpreter != null)
@@ -185,6 +198,28 @@ public class HgCGIServlet extends HttpServlet
executor.execute(command.getAbsolutePath()); executor.execute(command.getAbsolutePath());
} }
/**
* Method description
*
*
* @param env
* @param session
*/
private void passSessionAttributes(EnvList env, HttpSession session)
{
Enumeration<String> 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 ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/** /**

View File

@@ -49,8 +49,10 @@ import sonia.scm.repository.HgRepositoryHookEvent;
import sonia.scm.repository.RepositoryHookType; import sonia.scm.repository.RepositoryHookType;
import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryNotFoundException; import sonia.scm.repository.RepositoryNotFoundException;
import sonia.scm.security.CipherUtil;
import sonia.scm.util.HttpUtil; import sonia.scm.util.HttpUtil;
import sonia.scm.util.Util; import sonia.scm.util.Util;
import sonia.scm.web.security.WebSecurityContext;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
@@ -81,6 +83,9 @@ public class HgHookCallbackServlet extends HttpServlet
/** Field description */ /** Field description */
private static final String PARAM_CHALLENGE = "challenge"; private static final String PARAM_CHALLENGE = "challenge";
/** Field description */
private static final String PARAM_CREDENTIALS = "credentials";
/** Field description */ /** Field description */
private static final String PARAM_NODE = "node"; private static final String PARAM_NODE = "node";
@@ -102,17 +107,19 @@ public class HgHookCallbackServlet extends HttpServlet
* @param handler * @param handler
* @param hookManager * @param hookManager
* @param contextProvider * @param contextProvider
* @param securityContextProvider
*/ */
@Inject @Inject
public HgHookCallbackServlet(RepositoryManager repositoryManager, public HgHookCallbackServlet(
HgRepositoryHandler handler, RepositoryManager repositoryManager, HgRepositoryHandler handler,
HgHookManager hookManager, HgHookManager hookManager, Provider<HgContext> contextProvider,
Provider<HgContext> contextProvider) Provider<WebSecurityContext> securityContextProvider)
{ {
this.repositoryManager = repositoryManager; this.repositoryManager = repositoryManager;
this.handler = handler; this.handler = handler;
this.hookManager = hookManager; this.hookManager = hookManager;
this.contextProvider = contextProvider; this.contextProvider = contextProvider;
this.securityContextProvider = securityContextProvider;
} }
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
@@ -147,6 +154,13 @@ public class HgHookCallbackServlet extends HttpServlet
if (Util.isNotEmpty(node)) if (Util.isNotEmpty(node))
{ {
String credentials = request.getParameter(PARAM_CREDENTIALS);
if (Util.isNotEmpty(credentials))
{
authenticate(request, response, credentials);
}
hookCallback(response, repositoryId, type, challenge, node); hookCallback(response, repositoryId, type, challenge, node);
} }
else if (logger.isDebugEnabled()) 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 * Method description
* *
@@ -281,4 +329,7 @@ public class HgHookCallbackServlet extends HttpServlet
/** Field description */ /** Field description */
private RepositoryManager repositoryManager; private RepositoryManager repositoryManager;
/** Field description */
private Provider<WebSecurityContext> securityContextProvider;
} }

View File

@@ -40,6 +40,7 @@ import os, urllib
baseUrl = "${url}" baseUrl = "${url}"
challenge = "${challenge}" challenge = "${challenge}"
credentials = os.environ['SCM_CREDENTIALS']
def callback(ui, repo, hooktype, node=None, source=None, **kwargs): def callback(ui, repo, hooktype, node=None, source=None, **kwargs):
failure = True failure = True
@@ -47,7 +48,7 @@ def callback(ui, repo, hooktype, node=None, source=None, **kwargs):
try: try:
url = baseUrl + os.path.basename(repo.root) + "/" + hooktype url = baseUrl + os.path.basename(repo.root) + "/" + hooktype
ui.debug( "send scm-hook to " + url + " and " + node + "\n" ) 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); conn = urllib.urlopen(url, data);
if conn.code >= 200 and conn.code < 300: if conn.code >= 200 and conn.code < 300:
ui.debug( "scm-hook " + hooktype + " success with status code " + str(conn.code) + "\n" ) ui.debug( "scm-hook " + hooktype + " success with status code " + str(conn.code) + "\n" )

View File

@@ -44,6 +44,7 @@ import org.slf4j.LoggerFactory;
import sonia.scm.config.ScmConfiguration; import sonia.scm.config.ScmConfiguration;
import sonia.scm.group.Group; import sonia.scm.group.Group;
import sonia.scm.group.GroupManager; import sonia.scm.group.GroupManager;
import sonia.scm.security.CipherUtil;
import sonia.scm.user.User; import sonia.scm.user.User;
import sonia.scm.user.UserManager; import sonia.scm.user.UserManager;
import sonia.scm.util.Util; import sonia.scm.util.Util;
@@ -67,6 +68,9 @@ import javax.servlet.http.HttpSession;
public class BasicSecurityContext implements WebSecurityContext public class BasicSecurityContext implements WebSecurityContext
{ {
/** Field description */
public static final String SCM_CREDENTIALS = "SCM_CREDENTIALS";
/** Field description */ /** Field description */
public static final String USER_ANONYMOUS = "anonymous"; public static final String USER_ANONYMOUS = "anonymous";
@@ -154,6 +158,16 @@ public class BasicSecurityContext implements WebSecurityContext
{ {
logGroups(); 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) catch (Exception ex)
{ {