From: Mathieu Baudier Date: Tue, 21 Feb 2017 21:00:22 +0000 (+0100) Subject: SPNEGO support X-Git-Tag: argeo-commons-2.1.62~10 X-Git-Url: https://git.argeo.org/?p=lgpl%2Fargeo-commons.git;a=commitdiff_plain;h=3714331f776988facff3632d86ad3f6d6352220c SPNEGO support --- diff --git a/demo/argeo_node_rap.properties b/demo/argeo_node_rap.properties index 54b4735e5..832c536b0 100644 --- a/demo/argeo_node_rap.properties +++ b/demo/argeo_node_rap.properties @@ -34,7 +34,7 @@ argeo.node.repo.type=localfs #argeo.node.useradmin.uris="dc=example,dc=com.ldif dc=example,dc=org.ldif" -sun.security.krb5.debug=true +#sun.security.krb5.debug=true # HTTP org.osgi.service.http.port=7070 diff --git a/org.argeo.cms.ui.workbench/build.properties b/org.argeo.cms.ui.workbench/build.properties index 38c575104..1b9b7bd51 100644 --- a/org.argeo.cms.ui.workbench/build.properties +++ b/org.argeo.cms.ui.workbench/build.properties @@ -3,4 +3,5 @@ output.. = bin/ bin.includes = META-INF/,\ .,\ icons/,\ - plugin.xml \ No newline at end of file + plugin.xml +additional.bundles = org.apache.commons.httpclient diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/cms/ui/workbench/internal/jcr/commands/AddRemoteRepository.java b/org.argeo.cms.ui.workbench/src/org/argeo/cms/ui/workbench/internal/jcr/commands/AddRemoteRepository.java index 8b19b51a9..6fdb274d0 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/cms/ui/workbench/internal/jcr/commands/AddRemoteRepository.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/cms/ui/workbench/internal/jcr/commands/AddRemoteRepository.java @@ -59,16 +59,14 @@ import org.eclipse.swt.widgets.Text; * Connect to a remote repository and, if successful publish it as an OSGi * service. */ -public class AddRemoteRepository extends AbstractHandler implements - WorkbenchConstants, ArgeoNames { +public class AddRemoteRepository extends AbstractHandler implements WorkbenchConstants, ArgeoNames { private RepositoryFactory repositoryFactory; private Repository nodeRepository; private Keyring keyring; public Object execute(ExecutionEvent event) throws ExecutionException { - RemoteRepositoryLoginDialog dlg = new RemoteRepositoryLoginDialog( - Display.getDefault().getActiveShell()); + RemoteRepositoryLoginDialog dlg = new RemoteRepositoryLoginDialog(Display.getDefault().getActiveShell()); if (dlg.open() == Dialog.OK) { CommandUtils.callCommand(Refresh.ID); } @@ -105,16 +103,13 @@ public class AddRemoteRepository extends AbstractHandler implements protected Control createDialogArea(Composite parent) { Composite dialogarea = (Composite) super.createDialogArea(parent); - dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, - true)); + dialogarea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); Composite composite = new Composite(dialogarea, SWT.NONE); composite.setLayout(new GridLayout(2, false)); - composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, - false)); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); setMessage("Login to remote repository", IMessageProvider.NONE); name = createLT(composite, "Name", "remoteRepository"); - uri = createLT(composite, "URI", - "http://localhost:7070/jcr/node"); + uri = createLT(composite, "URI", "http://localhost:7070/jcr/node"); username = createLT(composite, "User", ""); password = createLP(composite, "Password"); @@ -146,20 +141,19 @@ public class AddRemoteRepository extends AbstractHandler implements params.put(NodeConstants.LABELED_URI, checkedUriStr); Repository repository = repositoryFactory.getRepository(params); if (username.getText().trim().equals("")) {// anonymous - session = repository.login(); + // FIXME make it more generic + session = repository.login("main"); } else { // FIXME use getTextChars() when upgrading to 3.7 // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=297412 char[] pwd = password.getText().toCharArray(); - SimpleCredentials sc = new SimpleCredentials( - username.getText(), pwd); + SimpleCredentials sc = new SimpleCredentials(username.getText(), pwd); session = repository.login(sc, "main"); MessageDialog.openInformation(getParentShell(), "Success", "Connection to '" + uri.getText() + "' successful"); } } catch (Exception e) { - ErrorFeedback.show( - "Connection test failed for " + uri.getText(), e); + ErrorFeedback.show("Connection test failed for " + uri.getText(), e); } finally { JcrUtils.logoutQuietly(session); } @@ -172,28 +166,20 @@ public class AddRemoteRepository extends AbstractHandler implements nodeSession = nodeRepository.login(); Node home = NodeUtils.getUserHome(nodeSession); - Node remote = home.hasNode(ARGEO_REMOTE) ? home - .getNode(ARGEO_REMOTE) : home.addNode(ARGEO_REMOTE); + Node remote = home.hasNode(ARGEO_REMOTE) ? home.getNode(ARGEO_REMOTE) : home.addNode(ARGEO_REMOTE); if (remote.hasNode(name.getText())) - throw new EclipseUiException( - "There is already a remote repository named " - + name.getText()); - Node remoteRepository = remote.addNode(name.getText(), - ArgeoTypes.ARGEO_REMOTE_REPOSITORY); + throw new EclipseUiException("There is already a remote repository named " + name.getText()); + Node remoteRepository = remote.addNode(name.getText(), ArgeoTypes.ARGEO_REMOTE_REPOSITORY); remoteRepository.setProperty(ARGEO_URI, uri.getText()); remoteRepository.setProperty(ARGEO_USER_ID, username.getText()); nodeSession.save(); if (saveInKeyring.getSelection()) { - String pwdPath = remoteRepository.getPath() + '/' - + ARGEO_PASSWORD; + String pwdPath = remoteRepository.getPath() + '/' + ARGEO_PASSWORD; keyring.set(pwdPath, password.getText().toCharArray()); } nodeSession.save(); - MessageDialog.openInformation( - getParentShell(), - "Repository Added", - "Remote repository '" + username.getText() + "@" - + uri.getText() + "' added"); + MessageDialog.openInformation(getParentShell(), "Repository Added", + "Remote repository '" + username.getText() + "@" + uri.getText() + "' added"); super.okPressed(); } catch (Exception e) { @@ -213,8 +199,7 @@ public class AddRemoteRepository extends AbstractHandler implements } /** Creates label and check. */ - protected Button createLC(Composite parent, String label, - Boolean initial) { + protected Button createLC(Composite parent, String label, Boolean initial) { new Label(parent, SWT.NONE).setText(label); Button check = new Button(parent, SWT.CHECK); check.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); @@ -224,8 +209,7 @@ public class AddRemoteRepository extends AbstractHandler implements protected Text createLP(Composite parent, String label) { new Label(parent, SWT.NONE).setText(label); - Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER - | SWT.PASSWORD); + Text text = new Text(parent, SWT.SINGLE | SWT.LEAD | SWT.BORDER | SWT.PASSWORD); text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); return text; } diff --git a/org.argeo.cms.ui.workbench/src/org/argeo/cms/ui/workbench/internal/jcr/model/RemoteRepositoryElem.java b/org.argeo.cms.ui.workbench/src/org/argeo/cms/ui/workbench/internal/jcr/model/RemoteRepositoryElem.java index f34f4de24..bd3cd32d6 100644 --- a/org.argeo.cms.ui.workbench/src/org/argeo/cms/ui/workbench/internal/jcr/model/RemoteRepositoryElem.java +++ b/org.argeo.cms.ui.workbench/src/org/argeo/cms/ui/workbench/internal/jcr/model/RemoteRepositoryElem.java @@ -43,8 +43,7 @@ public class RemoteRepositoryElem extends RepositoryElem { private final RepositoryFactory repositoryFactory; private final String uri; - public RemoteRepositoryElem(String alias, - RepositoryFactory repositoryFactory, String uri, TreeParent parent, + public RemoteRepositoryElem(String alias, RepositoryFactory repositoryFactory, String uri, TreeParent parent, Session userSession, Keyring keyring, String remoteNodePath) { super(alias, null, parent); this.repositoryFactory = repositoryFactory; @@ -55,29 +54,27 @@ public class RemoteRepositoryElem extends RepositoryElem { } @Override - protected Session repositoryLogin(String workspaceName) - throws RepositoryException { + protected Session repositoryLogin(String workspaceName) throws RepositoryException { Node remoteRepository = userSession.getNode(remoteNodePath); - String userID = remoteRepository.getProperty(ArgeoNames.ARGEO_USER_ID) - .getString(); - String pwdPath = remoteRepository.getPath() + '/' - + ArgeoNames.ARGEO_PASSWORD; - char[] password = keyring.getAsChars(pwdPath); - - try { - SimpleCredentials credentials = new SimpleCredentials(userID, - password); - return getRepository().login(credentials, workspaceName); - } finally { - Arrays.fill(password, 0, password.length, ' '); + String userID = remoteRepository.getProperty(ArgeoNames.ARGEO_USER_ID).getString(); + if (userID.trim().equals("")) { + return getRepository().login(workspaceName); + } else { + String pwdPath = remoteRepository.getPath() + '/' + ArgeoNames.ARGEO_PASSWORD; + char[] password = keyring.getAsChars(pwdPath); + try { + SimpleCredentials credentials = new SimpleCredentials(userID, password); + return getRepository().login(credentials, workspaceName); + } finally { + Arrays.fill(password, 0, password.length, ' '); + } } } @Override public Repository getRepository() { if (repository == null) - repository = NodeUtils.getRepositoryByUri(repositoryFactory, - uri); + repository = NodeUtils.getRepositoryByUri(repositoryFactory, uri); return super.getRepository(); } diff --git a/org.argeo.cms/bnd.bnd b/org.argeo.cms/bnd.bnd index b638bb21b..f25797109 100644 --- a/org.argeo.cms/bnd.bnd +++ b/org.argeo.cms/bnd.bnd @@ -8,5 +8,6 @@ org.apache.jackrabbit.webdav.jcr,\ org.eclipse.equinox.http.jetty,\ org.springframework.context,\ org.springframework.core.io,\ +org.apache.commons.httpclient.cookie;resolution:=optional,\ * Provide-Capability: cms.datamodel;name=cms;cnd=/org/argeo/cms/cms.cnd;abstract=true \ No newline at end of file diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java b/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java index 6dae68d1d..fb7a6123a 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java @@ -214,6 +214,15 @@ class CmsAuthUtils { return true; } + public static T getSinglePrincipal(Subject subject, Class clss) { + Set principals = subject.getPrincipals(clss); + if (principals.isEmpty()) + return null; + if (principals.size() > 1) + throw new IllegalStateException("Only one " + clss + " principal expected in " + subject); + return principals.iterator().next(); + } + private CmsAuthUtils() { } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/SingleUserLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/SingleUserLoginModule.java index 801e4af7c..4d2cc3339 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/SingleUserLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/SingleUserLoginModule.java @@ -1,37 +1,70 @@ package org.argeo.cms.auth; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.security.Principal; import java.util.Map; import java.util.Set; +import javax.naming.ldap.LdapName; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.kerberos.KerberosPrincipal; import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; import javax.security.auth.x500.X500Principal; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.argeo.cms.internal.auth.ImpliedByPrincipal; +import org.argeo.naming.LdapAttrs; import org.argeo.node.NodeConstants; import org.argeo.node.security.DataAdminPrincipal; +import org.argeo.osgi.useradmin.IpaUtils; public class SingleUserLoginModule implements LoginModule { + private final static Log log = LogFactory.getLog(SingleUserLoginModule.class); + private Subject subject; + private Map sharedState = null; + @SuppressWarnings("unchecked") @Override public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this.subject = subject; + this.sharedState = (Map) sharedState; } @Override public boolean login() throws LoginException { + String username = System.getProperty("user.name"); + if (!sharedState.containsKey(CmsAuthUtils.SHARED_STATE_NAME)) + sharedState.put(CmsAuthUtils.SHARED_STATE_NAME, username); return true; } @Override public boolean commit() throws LoginException { - String username = System.getProperty("user.name"); - X500Principal principal = new X500Principal("uid=" + username + ",dc=localhost,dc=localdomain"); + X500Principal principal; + KerberosPrincipal kerberosPrincipal = CmsAuthUtils.getSinglePrincipal(subject, KerberosPrincipal.class); + if (kerberosPrincipal != null) { + LdapName userDn = IpaUtils.kerberosToDn(kerberosPrincipal.getName()); + principal = new X500Principal(userDn.toString()); + } else { + Object username = sharedState.get(CmsAuthUtils.SHARED_STATE_NAME); + if (username == null) + throw new LoginException("No username available"); + String hostname; + try { + hostname = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + log.warn("Using localhost as hostname", e); + hostname = "localhost"; + } + String baseDn = ("." + hostname).replaceAll("\\.", ",dc="); + principal = new X500Principal(LdapAttrs.uid + "=" + username + baseDn); + } Set principals = subject.getPrincipals(); principals.add(principal); principals.add(new ImpliedByPrincipal(NodeConstants.ROLE_ADMIN, principal)); diff --git a/org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java index ef2872e38..27de54be3 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/SpnegoLoginModule.java @@ -17,6 +17,7 @@ import org.ietf.jgss.GSSException; import org.ietf.jgss.GSSManager; import org.ietf.jgss.GSSName; +/** SPNEGO login */ public class SpnegoLoginModule implements LoginModule { private final static Log log = LogFactory.getLog(SpnegoLoginModule.class); @@ -41,22 +42,20 @@ public class SpnegoLoginModule implements LoginModule { gssContext = checkToken(spnegoToken); if (gssContext == null) return false; - try { - String clientName = gssContext.getSrcName().toString(); - String role = clientName.substring(clientName.indexOf('@') + 1); - - log.debug("SpnegoUserRealm: established a security context"); - log.debug("Client Principal is: " + gssContext.getSrcName()); - log.debug("Server Principal is: " + gssContext.getTargName()); - log.debug("Client Default Role: " + role); - } catch (GSSException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - // TODO log in - - return false; + else + return true; + // try { + // String clientName = gssContext.getSrcName().toString(); + // String role = clientName.substring(clientName.indexOf('@') + 1); + // + // log.debug("SpnegoUserRealm: established a security context"); + // log.debug("Client Principal is: " + gssContext.getSrcName()); + // log.debug("Server Principal is: " + gssContext.getTargName()); + // log.debug("Client Default Role: " + role); + // } catch (GSSException e) { + // // TODO Auto-generated catch block + // e.printStackTrace(); + // } } @Override @@ -67,29 +66,47 @@ public class SpnegoLoginModule implements LoginModule { try { Class gssUtilsClass = Class.forName("com.sun.security.jgss.GSSUtil"); Method createSubjectMethod = gssUtilsClass.getMethod("createSubject", GSSName.class, GSSCredential.class); - Subject gssSubject = (Subject) createSubjectMethod.invoke(null, gssContext.getSrcName(), - gssContext.getDelegCred()); + Subject gssSubject; + if (gssContext.getCredDelegState()) + gssSubject = (Subject) createSubjectMethod.invoke(null, gssContext.getSrcName(), + gssContext.getDelegCred()); + else + gssSubject = (Subject) createSubjectMethod.invoke(null, gssContext.getSrcName(), null); subject.getPrincipals().addAll(gssSubject.getPrincipals()); subject.getPrivateCredentials().addAll(gssSubject.getPrivateCredentials()); return true; } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - return false; + throw new LoginException("Cannot commit SPNEGO " + e); } } @Override public boolean abort() throws LoginException { - // TODO Auto-generated method stub - return false; + if (gssContext != null) { + try { + gssContext.dispose(); + } catch (GSSException e) { + if (log.isTraceEnabled()) + log.warn("Could not abort", e); + } + gssContext = null; + } + return true; } @Override public boolean logout() throws LoginException { - // TODO Auto-generated method stub - return false; + if (gssContext != null) { + try { + gssContext.dispose(); + } catch (GSSException e) { + if (log.isTraceEnabled()) + log.warn("Could not abort", e); + } + gssContext = null; + } + return true; } private GSSContext checkToken(byte[] authToken) { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java index 71049fac9..b571fcf86 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/auth/CmsSessionImpl.java @@ -75,6 +75,9 @@ public class CmsSessionImpl implements CmsSession { @Override public synchronized Session getDataSession(String cn, String workspace, Repository repository) { + // FIXME make it more robust + if (workspace == null) + workspace = "main"; String path = cn + '/' + workspace; if (dataSessionsInUse.contains(path)) { try { @@ -167,7 +170,7 @@ public class CmsSessionImpl implements CmsSession { } public String toString() { - return "CMS Session #" + localSessionId; + return "CMS Session local=" + localSessionId + ", uuid=" + uuid; } public static CmsSession getByLocalId(String localId) { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/CmsSessionProvider.java b/org.argeo.cms/src/org/argeo/cms/internal/http/CmsSessionProvider.java index c0284f4c7..e398fc956 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/CmsSessionProvider.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/CmsSessionProvider.java @@ -12,6 +12,8 @@ import javax.security.auth.login.LoginContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.jackrabbit.server.SessionProvider; import org.argeo.cms.CmsException; import org.argeo.cms.auth.CmsSession; @@ -25,8 +27,7 @@ import org.argeo.node.NodeConstants; class CmsSessionProvider implements SessionProvider, Serializable { private static final long serialVersionUID = -1358136599534938466L; - // private final static Log log = - // LogFactory.getLog(CmsSessionProvider.class); + private final static Log log = LogFactory.getLog(CmsSessionProvider.class); private final String alias; @@ -42,6 +43,9 @@ class CmsSessionProvider implements SessionProvider, Serializable { CmsSession cmsSession = WebCmsSessionImpl.getCmsSession(request); if (cmsSession == null) return anonymousSession(request, rep, workspace); + if (log.isTraceEnabled()) { + log.debug("Get JCR session from " + cmsSession); + } Session session = cmsSession.getDataSession(alias, workspace, rep); cmsSessions.put(session, cmsSession); return session; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/DataHttpContext.java b/org.argeo.cms/src/org/argeo/cms/internal/http/DataHttpContext.java index 581d6cbc1..b98419d80 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/DataHttpContext.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/DataHttpContext.java @@ -2,30 +2,16 @@ package org.argeo.cms.internal.http; import java.io.IOException; import java.net.URL; -import java.util.StringTokenizer; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.argeo.cms.CmsException; -import org.argeo.cms.auth.HttpRequestCallback; import org.argeo.cms.auth.HttpRequestCallbackHandler; import org.argeo.node.NodeConstants; -import org.ietf.jgss.GSSContext; -import org.ietf.jgss.GSSCredential; -import org.ietf.jgss.GSSException; -import org.ietf.jgss.GSSManager; -import org.ietf.jgss.GSSName; -import org.ietf.jgss.Oid; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.service.http.HttpContext; @@ -36,7 +22,17 @@ class DataHttpContext implements HttpContext { private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); // FIXME Make it more unique - private String httpAuthRealm = "Argeo"; + private final String httpAuthRealm; + private final boolean forceBasic; + + public DataHttpContext(String httpAuthrealm, boolean forceBasic) { + this.httpAuthRealm = httpAuthrealm; + this.forceBasic = forceBasic; + } + + public DataHttpContext(String httpAuthrealm) { + this(httpAuthrealm, false); + } @Override public boolean handleSecurity(final HttpServletRequest request, HttpServletResponse response) throws IOException { @@ -49,20 +45,24 @@ class DataHttpContext implements HttpContext { lc.login(); // return true; } catch (LoginException e) { - CallbackHandler token = extractHttpAuth(request, response); - if (token != null) { - try { - lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, token); - lc.login(); - } catch (LoginException e1) { - throw new CmsException("Could not login", e1); - } - } else { - lc = processUnauthorized(request, response); - if (lc == null) - return false; - } + // CallbackHandler token = extractHttpAuth(request, response); + // String token = request.getHeader(HttpUtils.HEADER_AUTHORIZATION); + // if (token != null) { + // try { + // lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER); + // lc.login(); + // } catch (LoginException e1) { + // throw new CmsException("Could not login", e1); + // } + // } else { + lc = processUnauthorized(request, response); + if (lc == null) + return false; + // } } + + // still required by open session in view + // TODO remove it request.setAttribute(NodeConstants.LOGIN_CONTEXT_USER, lc); return true; } @@ -90,91 +90,111 @@ class DataHttpContext implements HttpContext { } } - protected CallbackHandler extractHttpAuth(final HttpServletRequest httpRequest, HttpServletResponse httpResponse) { - String authHeader = httpRequest.getHeader(HttpUtils.HEADER_AUTHORIZATION); - if (authHeader != null) { - StringTokenizer st = new StringTokenizer(authHeader); - if (st.hasMoreTokens()) { - String basic = st.nextToken(); - if (basic.equalsIgnoreCase("Basic")) { - try { - // TODO manipulate char[] - String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8"); - // log.debug("Credentials: " + credentials); - int p = credentials.indexOf(":"); - if (p != -1) { - final String login = credentials.substring(0, p).trim(); - final char[] password = credentials.substring(p + 1).trim().toCharArray(); - return new CallbackHandler() { - public void handle(Callback[] callbacks) { - for (Callback cb : callbacks) { - if (cb instanceof NameCallback) - ((NameCallback) cb).setName(login); - else if (cb instanceof PasswordCallback) - ((PasswordCallback) cb).setPassword(password); - else if (cb instanceof HttpRequestCallback) { - ((HttpRequestCallback) cb).setRequest(httpRequest); - ((HttpRequestCallback) cb).setResponse(httpResponse); - } - } - } - }; - } else { - throw new CmsException("Invalid authentication token"); - } - } catch (Exception e) { - throw new CmsException("Couldn't retrieve authentication", e); - } - } else if (basic.equalsIgnoreCase("Negotiate")) { - // FIXME generalise - String _targetName = "HTTP/mostar.desktop.argeo.pro"; - String spnegoToken = st.nextToken(); - byte[] authToken = Base64.decodeBase64(spnegoToken); - GSSManager manager = GSSManager.getInstance(); - try { - Oid krb5Oid = new Oid("1.3.6.1.5.5.2"); // http://java.sun.com/javase/6/docs/technotes/guides/security/jgss/jgss-features.html - GSSName gssName = manager.createName(_targetName, null); - GSSCredential serverCreds = manager.createCredential(gssName, GSSCredential.INDEFINITE_LIFETIME, - krb5Oid, GSSCredential.ACCEPT_ONLY); - GSSContext gContext = manager.createContext(serverCreds); - - if (gContext == null) { - log.debug("SpnegoUserRealm: failed to establish GSSContext"); - } else { - while (!gContext.isEstablished()) { - byte[] outToken = gContext.acceptSecContext(authToken, 0, authToken.length); - String outTokenStr = Base64.encodeBase64String(outToken); - httpResponse.setHeader("WWW-Authenticate", "Negotiate " + outTokenStr); - } - if (gContext.isEstablished()) { - String clientName = gContext.getSrcName().toString(); - String role = clientName.substring(clientName.indexOf('@') + 1); - - log.debug("SpnegoUserRealm: established a security context"); - log.debug("Client Principal is: " + gContext.getSrcName()); - log.debug("Server Principal is: " + gContext.getTargName()); - log.debug("Client Default Role: " + role); - - // TODO log in - } - } - - } catch (GSSException gsse) { - log.warn(gsse, gsse); - } - - } - } - } - return null; - } + // protected CallbackHandler extractHttpAuth(final HttpServletRequest + // httpRequest, HttpServletResponse httpResponse) { + // String authHeader = + // httpRequest.getHeader(HttpUtils.HEADER_AUTHORIZATION); + // if (authHeader != null) { + // StringTokenizer st = new StringTokenizer(authHeader); + // if (st.hasMoreTokens()) { + // String basic = st.nextToken(); + // if (basic.equalsIgnoreCase("Basic")) { + // try { + // // TODO manipulate char[] + // String credentials = new String(Base64.decodeBase64(st.nextToken()), + // "UTF-8"); + // // log.debug("Credentials: " + credentials); + // int p = credentials.indexOf(":"); + // if (p != -1) { + // final String login = credentials.substring(0, p).trim(); + // final char[] password = credentials.substring(p + + // 1).trim().toCharArray(); + // return new CallbackHandler() { + // public void handle(Callback[] callbacks) { + // for (Callback cb : callbacks) { + // if (cb instanceof NameCallback) + // ((NameCallback) cb).setName(login); + // else if (cb instanceof PasswordCallback) + // ((PasswordCallback) cb).setPassword(password); + // else if (cb instanceof HttpRequestCallback) { + // ((HttpRequestCallback) cb).setRequest(httpRequest); + // ((HttpRequestCallback) cb).setResponse(httpResponse); + // } + // } + // } + // }; + // } else { + // throw new CmsException("Invalid authentication token"); + // } + // } catch (Exception e) { + // throw new CmsException("Couldn't retrieve authentication", e); + // } + // } else if (basic.equalsIgnoreCase("Negotiate")) { + // // FIXME generalise + // String _targetName; + // try { + // _targetName = NodeHttp.DEFAULT_SERVICE + "@" + // + InetAddress.getLocalHost().getCanonicalHostName(); + // } catch (UnknownHostException e) { + // throw new CmsException("Cannot determins target name", e); + // } + // String spnegoToken = st.nextToken(); + // byte[] authToken = Base64.decodeBase64(spnegoToken); + // GSSManager manager = GSSManager.getInstance(); + // try { + //// Oid krb5Oid = new Oid("1.3.6.1.5.5.2"); // + // http://java.sun.com/javase/6/docs/technotes/guides/security/jgss/jgss-features.html + //// GSSName gssName = manager.createName(_targetName, + // GSSName.NT_HOSTBASED_SERVICE, krb5Oid); + //// GSSCredential serverCreds = manager.createCredential(gssName, + // GSSCredential.INDEFINITE_LIFETIME, + //// krb5Oid, GSSCredential.ACCEPT_ONLY); + // GSSCredential serverCreds = Activator.getAcceptorCredentials(); + // if(serverCreds==null) + // throw new CmsException("No GSS server credentials available"); + // GSSContext gContext = manager.createContext(serverCreds); + // + // if (gContext == null) { + // log.debug("SpnegoUserRealm: failed to establish GSSContext"); + // } else { + // while (!gContext.isEstablished()) { + // byte[] outToken = gContext.acceptSecContext(authToken, 0, + // authToken.length); + // String outTokenStr = Base64.encodeBase64String(outToken); + // httpResponse.setHeader("WWW-Authenticate", "Negotiate " + outTokenStr); + // } + // if (gContext.isEstablished()) { + // String clientName = gContext.getSrcName().toString(); + // String role = clientName.substring(clientName.indexOf('@') + 1); + // + // log.debug("SpnegoUserRealm: established a security context"); + // log.debug("Client Principal is: " + gContext.getSrcName()); + // log.debug("Server Principal is: " + gContext.getTargName()); + // log.debug("Client Default Role: " + role); + // + // // TODO log in + // } + // } + // + // } catch (GSSException gsse) { + // log.warn(gsse, gsse); + // } + // + // } + // } + // } + // return null; + // } protected void askForWwwAuth(HttpServletRequest request, HttpServletResponse response) { response.setStatus(401); - response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic realm=\"" + httpAuthRealm + "\""); + // response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "basic + // realm=\"" + httpAuthRealm + "\""); + if (org.argeo.cms.internal.kernel.Activator.getAcceptorCredentials() != null && !forceBasic)// SPNEGO + response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "Negotiate"); + else + response.setHeader(HttpUtils.HEADER_WWW_AUTHENTICATE, "Basic realm=\"" + httpAuthRealm + "\""); - // SPNEGO - // response.setHeader(HEADER_WWW_AUTHENTICATE, "Negotiate"); // response.setDateHeader("Date", System.currentTimeMillis()); // response.setDateHeader("Expires", System.currentTimeMillis() + (24 * // 60 * 60 * 1000)); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/NodeHttp.java b/org.argeo.cms/src/org/argeo/cms/internal/http/NodeHttp.java index 901731aa0..98eee87d2 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/NodeHttp.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/NodeHttp.java @@ -32,42 +32,20 @@ import org.osgi.util.tracker.ServiceTracker; public class NodeHttp implements KernelConstants { private final static Log log = LogFactory.getLog(NodeHttp.class); - // Filters - // private final RootFilter rootFilter; - - // private final DoSFilter dosFilter; - // private final QoSFilter qosFilter; + public final static String DEFAULT_SERVICE = "HTTP"; private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext(); private ServiceTracker repositories; private final ServiceTracker httpServiceTracker; - public NodeHttp() { - // rootFilter = new RootFilter(); - // dosFilter = new CustomDosFilter(); - // qosFilter = new QoSFilter(); + private String httpRealm = "Argeo"; + public NodeHttp() { httpServiceTracker = new PrepareHttpStc(); httpServiceTracker.open(); } - // class CustomDosFilter extends DoSFilter { - // @Override - // protected String extractUserId(ServletRequest request) { - // HttpSession httpSession = ((HttpServletRequest) request) - // .getSession(); - // if (isSessionAuthenticated(httpSession)) { - // String userId = ((SecurityContext) httpSession - // .getAttribute(SPRING_SECURITY_CONTEXT_KEY)) - // .getAuthentication().getName(); - // return userId; - // } - // return super.extractUserId(request); - // - // } - // } - public void destroy() { repositories.close(); } @@ -111,7 +89,7 @@ public class NodeHttp implements KernelConstants { Properties ip = new Properties(); ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_CONFIG, HttpUtils.WEBDAV_CONFIG); ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path); - httpService.registerServlet(path, webdavServlet, ip, new DataHttpContext()); + httpService.registerServlet(path, webdavServlet, ip, new DataHttpContext(httpRealm)); } void registerFilesServlet(HttpService httpService, String alias, Repository repository) @@ -121,7 +99,7 @@ public class NodeHttp implements KernelConstants { Properties ip = new Properties(); ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_CONFIG, HttpUtils.WEBDAV_CONFIG); ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path); - httpService.registerServlet(path, filesServlet, ip, new PrivateHttpContext()); + httpService.registerServlet(path, filesServlet, ip, new PrivateHttpContext(httpRealm, true)); } void registerRemotingServlet(HttpService httpService, String alias, Repository repository) @@ -130,6 +108,7 @@ public class NodeHttp implements KernelConstants { String path = remotingPath(alias); Properties ip = new Properties(); ip.setProperty(JcrRemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path); + ip.setProperty(JcrRemotingServlet.INIT_PARAM_AUTHENTICATE_HEADER, "Negotiate"); // Looks like a bug in Jackrabbit remoting init Path tmpDir; @@ -142,7 +121,7 @@ public class NodeHttp implements KernelConstants { ip.setProperty(RemotingServlet.INIT_PARAM_TMP_DIRECTORY, "remoting_" + alias); ip.setProperty(RemotingServlet.INIT_PARAM_PROTECTED_HANDLERS_CONFIG, HttpUtils.DEFAULT_PROTECTED_HANDLERS); ip.setProperty(RemotingServlet.INIT_PARAM_CREATE_ABSOLUTE_URI, "false"); - httpService.registerServlet(path, remotingServlet, ip, new PrivateHttpContext()); + httpService.registerServlet(path, remotingServlet, ip, new PrivateHttpContext(httpRealm)); } private String webdavPath(String alias) { @@ -304,6 +283,7 @@ public class NodeHttp implements KernelConstants { } private class RemotingServlet extends JcrRemotingServlet { + private final Log log = LogFactory.getLog(RemotingServlet.class); private static final long serialVersionUID = 4605238259548058883L; private final Repository repository; private final SessionProvider sessionProvider; @@ -331,6 +311,8 @@ public class NodeHttp implements KernelConstants { // Subject.doAs(subject, new PrivilegedExceptionAction() { // @Override // public Void run() throws Exception { + if (log.isTraceEnabled()) + HttpUtils.logRequest(log, request); RemotingServlet.super.service(request, response); // return null; // } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/PrivateHttpContext.java b/org.argeo.cms/src/org/argeo/cms/internal/http/PrivateHttpContext.java index e0d713224..2babd188b 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/PrivateHttpContext.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/PrivateHttpContext.java @@ -4,8 +4,17 @@ import javax.security.auth.login.LoginContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +/** Requests authorisation */ class PrivateHttpContext extends DataHttpContext { + public PrivateHttpContext(String httpAuthrealm, boolean forceBasic) { + super(httpAuthrealm, forceBasic); + } + + public PrivateHttpContext(String httpAuthrealm) { + super(httpAuthrealm); + } + @Override protected LoginContext processUnauthorized(HttpServletRequest request, HttpServletResponse response) { askForWwwAuth(request, response); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java b/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java new file mode 100644 index 000000000..7d5278ef0 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoAuthScheme.java @@ -0,0 +1,166 @@ +package org.argeo.cms.internal.http.client; + +import java.net.URL; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Base64; + +import javax.security.auth.Subject; +import javax.security.auth.login.LoginContext; + +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.URIException; +import org.apache.commons.httpclient.auth.AuthPolicy; +import org.apache.commons.httpclient.auth.AuthScheme; +import org.apache.commons.httpclient.auth.AuthenticationException; +import org.apache.commons.httpclient.auth.CredentialsProvider; +import org.apache.commons.httpclient.auth.MalformedChallengeException; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.params.DefaultHttpParams; +import org.apache.commons.httpclient.params.HttpParams; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.ietf.jgss.GSSContext; +import org.ietf.jgss.GSSException; +import org.ietf.jgss.GSSManager; +import org.ietf.jgss.GSSName; +import org.ietf.jgss.Oid; + +/** Implementation of the SPNEGO auth scheme. */ +public class SpnegoAuthScheme implements AuthScheme { + private final static Log log = LogFactory.getLog(SpnegoAuthScheme.class); + + public static final String NAME = "Negotiate"; + private final static Oid KERBEROS_OID; + static { + try { + KERBEROS_OID = new Oid("1.3.6.1.5.5.2"); + } catch (GSSException e) { + throw new IllegalStateException("Cannot create Kerberos OID", e); + } + } + + private boolean complete = false; + private String realm; + + @Override + public void processChallenge(String challenge) throws MalformedChallengeException { + log.debug("processChallenge " + challenge); + + } + + @Override + public String getSchemeName() { + return NAME; + } + + @Override + public String getParameter(String name) { + log.debug("getParameter " + name); + return null; + } + + @Override + public String getRealm() { + return realm; + } + + @Override + public String getID() { + return NAME; + } + + @Override + public boolean isConnectionBased() { + return true; + } + + @Override + public boolean isComplete() { + log.debug("isComplete"); + return complete; + } + + @Override + public String authenticate(Credentials credentials, String method, String uri) throws AuthenticationException { + log.debug("authenticate " + method + " " + uri); + return null; + } + + @Override + public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException { + log.debug("authenticate " + method); + GSSContext context = null; + String tokenStr = null; + String hostname; + try { + hostname = method.getURI().getHost(); + } catch (URIException e1) { + throw new IllegalStateException("Cannot authenticate", e1); + } + String serverPrinc = "HTTP@" + hostname; + + try { + // Get service's principal name + GSSManager manager = GSSManager.getInstance(); + GSSName serverName = manager.createName(serverPrinc, GSSName.NT_HOSTBASED_SERVICE, KERBEROS_OID); + + // Get the context for authentication + context = manager.createContext(serverName, KERBEROS_OID, null, GSSContext.DEFAULT_LIFETIME); + // context.requestMutualAuth(true); // Request mutual authentication + // context.requestConf(true); // Request confidentiality + context.requestCredDeleg(true); + + byte[] token = new byte[0]; + + // token is ignored on the first call + token = context.initSecContext(token, 0, token.length); + + // Send a token to the server if one was generated by + // initSecContext + if (token != null) { + tokenStr = Base64.getEncoder().encodeToString(token); + // complete=true; + } + return "Negotiate " + tokenStr; + } catch (GSSException e) { + throw new AuthenticationException("Cannot authenticate to " + serverPrinc, e); + } + } + + public static void main(String[] args) { + if (args.length == 0) { + System.err.println("usage: java " + SpnegoAuthScheme.class.getName() + " "); + System.exit(1); + return; + } + String url = args[0]; + + URL jaasUrl = SpnegoAuthScheme.class.getResource("jaas.cfg"); + System.setProperty("java.security.auth.login.config", jaasUrl.toExternalForm()); + try { + LoginContext lc = new LoginContext("SINGLE_USER"); + lc.login(); + + AuthPolicy.registerAuthScheme(SpnegoAuthScheme.NAME, SpnegoAuthScheme.class); + HttpParams params = DefaultHttpParams.getDefaultParams(); + ArrayList schemes = new ArrayList<>(); + schemes.add(SpnegoAuthScheme.NAME); + params.setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, schemes); + params.setParameter(CredentialsProvider.PROVIDER, new SpnegoCredentialProvider()); + + int responseCode = Subject.doAs(lc.getSubject(), new PrivilegedExceptionAction() { + public Integer run() throws Exception { + HttpClient httpClient = new HttpClient(); + return httpClient.executeMethod(new GetMethod(url)); + } + }); + System.out.println("Reponse code: " + responseCode); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoCredentialProvider.java b/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoCredentialProvider.java new file mode 100644 index 000000000..fff27c0d4 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/client/SpnegoCredentialProvider.java @@ -0,0 +1,18 @@ +package org.argeo.cms.internal.http.client; + +import org.apache.commons.httpclient.Credentials; +import org.apache.commons.httpclient.auth.AuthScheme; +import org.apache.commons.httpclient.auth.CredentialsNotAvailableException; +import org.apache.commons.httpclient.auth.CredentialsProvider; + +/** SPNEGO credential provider */ +public class SpnegoCredentialProvider implements CredentialsProvider { + + @Override + public Credentials getCredentials(AuthScheme scheme, String host, int port, boolean proxy) + throws CredentialsNotAvailableException { + return new Credentials() { + }; + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/client/jaas.cfg b/org.argeo.cms/src/org/argeo/cms/internal/http/client/jaas.cfg new file mode 100644 index 000000000..21176b911 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/client/jaas.cfg @@ -0,0 +1,5 @@ +SINGLE_USER { + com.sun.security.auth.module.Krb5LoginModule optional + principal="${user.name}" + useTicketCache=true; +}; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsSecurity.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsSecurity.java index 7983ea771..34806762d 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsSecurity.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsSecurity.java @@ -8,6 +8,7 @@ import java.net.UnknownHostException; import java.nio.file.Files; import java.nio.file.Path; import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; import java.util.Iterator; import javax.security.auth.Subject; @@ -20,9 +21,18 @@ import javax.security.auth.login.Configuration; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; +import org.apache.commons.httpclient.auth.AuthPolicy; +import org.apache.commons.httpclient.auth.CredentialsProvider; +import org.apache.commons.httpclient.cookie.CookiePolicy; +import org.apache.commons.httpclient.params.DefaultHttpParams; +import org.apache.commons.httpclient.params.HttpMethodParams; +import org.apache.commons.httpclient.params.HttpParams; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; +import org.argeo.cms.internal.http.NodeHttp; +import org.argeo.cms.internal.http.client.SpnegoAuthScheme; +import org.argeo.cms.internal.http.client.SpnegoCredentialProvider; import org.argeo.naming.DnsBrowser; import org.argeo.node.NodeConstants; import org.ietf.jgss.GSSCredential; @@ -32,10 +42,10 @@ import org.ietf.jgss.GSSName; import org.ietf.jgss.Oid; /** Low-level kernel security */ -class CmsSecurity implements KernelConstants { +public class CmsSecurity implements KernelConstants { private final static Log log = LogFactory.getLog(CmsSecurity.class); // http://java.sun.com/javase/6/docs/technotes/guides/security/jgss/jgss-features.html - private final static Oid KERBEROS_OID; + public final static Oid KERBEROS_OID; static { try { KERBEROS_OID = new Oid("1.3.6.1.5.5.2"); @@ -61,7 +71,17 @@ class CmsSecurity implements KernelConstants { private Path nodeKeyTab = KernelUtils.getOsgiInstancePath(KernelConstants.NODE_KEY_TAB_PATH); - public CmsSecurity() { + CmsSecurity() { + // Register client-side SPNEGO auth scheme + AuthPolicy.registerAuthScheme(SpnegoAuthScheme.NAME, SpnegoAuthScheme.class); + HttpParams params = DefaultHttpParams.getDefaultParams(); + ArrayList schemes = new ArrayList<>(); + schemes.add(SpnegoAuthScheme.NAME); + params.setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, schemes); + params.setParameter(CredentialsProvider.PROVIDER, new SpnegoCredentialProvider()); + params.setParameter(HttpMethodParams.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY); +// params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); + if (!DeployConfig.isInitialized()) // first init FirstInit.prepareInstanceArea(); @@ -96,7 +116,7 @@ class CmsSecurity implements KernelConstants { res = DEPLOYED; } else { res = STANDALONE; - kerberosDomain = null; + // kerberosDomain = null; // FIXME make state more robust } } catch (UnknownHostException e) { @@ -118,7 +138,8 @@ class CmsSecurity implements KernelConstants { CallbackHandler callbackHandler; if (Files.exists(nodeKeyTab)) { - service = NodeConstants.NODE_SERVICE; + service = NodeHttp.DEFAULT_SERVICE; + // service = NodeConstants.NODE_SERVICE; callbackHandler = new CallbackHandler() { @Override @@ -146,7 +167,7 @@ class CmsSecurity implements KernelConstants { // throw new CmsException("Cannot create text callback handler", e); // } try { - LoginContext kernelLc = new LoginContext(NodeConstants.LOGIN_CONTEXT_SINGLE_USER, nodeSubject); + LoginContext kernelLc = new LoginContext(NodeConstants.LOGIN_CONTEXT_NODE, nodeSubject); kernelLc.login(); } catch (LoginException e) { throw new CmsException("Cannot log in kernel", e); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg index 52bf4c375..550de1074 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg @@ -20,7 +20,9 @@ NODE { SINGLE_USER { com.sun.security.auth.module.Krb5LoginModule optional + principal="${user.name}" storeKey=true + useTicketCache=true debug=true; org.argeo.cms.auth.SingleUserLoginModule requisite; }; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg index 83d36d927..9ce961b28 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg @@ -16,7 +16,11 @@ KEYRING { }; SINGLE_USER { - com.sun.security.auth.module.UnixLoginModule requisite; + com.sun.security.auth.module.Krb5LoginModule optional + principal="${user.name}" + storeKey=true + useTicketCache=true + debug=true; org.argeo.cms.auth.SingleUserLoginModule requisite; }; diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java index 978b9a669..7486e3ecf 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java @@ -120,7 +120,7 @@ public class LdapUserAdmin extends AbstractUserDirectory { throw new UserDirectoryException("Unsupported LDAP type for " + name); return res; } catch (NamingException e) { - log.error("Cannot get role: " + e.getMessage()); + log.error("Cannot get role: " + name, e); return null; } }