package org.argeo.cms;
-import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import java.util.HashMap;
import java.util.Map;
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
import javax.security.auth.Subject;
+import javax.security.auth.login.CredentialNotFoundException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
-import javax.security.auth.x500.X500Principal;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.argeo.ArgeoException;
import org.argeo.cms.auth.AuthConstants;
+import org.argeo.cms.auth.HttpRequestCallbackHandler;
+import org.argeo.eclipse.ui.specific.UiContext;
import org.argeo.jcr.JcrUtils;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.application.AbstractEntryPoint;
private final Log log = LogFactory.getLog(AbstractCmsEntryPoint.class);
private final Subject subject;
+ private LoginContext loginContext;
private final Repository repository;
private final String workspace;
this.workspace = workspace;
this.defaultPath = defaultPath;
this.factoryProperties = new HashMap<String, String>(factoryProperties);
+ subject = new Subject();
- // load context from session
- HttpServletRequest httpRequest = RWT.getRequest();
- final HttpSession httpSession = httpRequest.getSession();
- AccessControlContext acc = (AccessControlContext) httpSession
- .getAttribute(AuthConstants.ACCESS_CONTROL_CONTEXT);
- if (acc != null
- && Subject.getSubject(acc).getPrincipals(X500Principal.class)
- .size() == 1) {
- subject = Subject.getSubject(acc);
- } else {
- subject = new Subject();
-
- // Initial login
+ // Initial login
+ try {
+ loginContext = new LoginContext(AuthConstants.LOGIN_CONTEXT_USER,
+ subject, new HttpRequestCallbackHandler(
+ UiContext.getHttpRequest()));
+ loginContext.login();
+ } catch (CredentialNotFoundException e) {
try {
- new LoginContext(AuthConstants.LOGIN_CONTEXT_USER, subject)
- .login();
- } catch (LoginException e) {
- // if (log.isTraceEnabled())
- // log.trace("Cannot authenticate user", e);
- try {
- new LoginContext(AuthConstants.LOGIN_CONTEXT_ANONYMOUS,
- subject).login();
- } catch (LoginException eAnonymous) {
- throw new ArgeoException("Cannot initialize subject",
- eAnonymous);
- }
+ loginContext = new LoginContext(
+ AuthConstants.LOGIN_CONTEXT_ANONYMOUS, subject);
+ loginContext.login();
+ } catch (LoginException e1) {
+ throw new ArgeoException("Cannot log as anonymous", e);
}
+ } catch (LoginException e) {
+ throw new ArgeoException("Cannot initialize subject", e);
}
- authChange();
+ authChange(loginContext);
jsExecutor = RWT.getClient().getService(JavaScriptExecutor.class);
browserNavigation = RWT.getClient().getService(BrowserNavigation.class);
@Override
protected final void createContents(final Composite parent) {
- getShell().getDisplay().setData(CmsView.KEY, this);
+ UiContext.setData(CmsView.KEY, this);
Subject.doAs(subject, new PrivilegedAction<Void>() {
@Override
public Void run() {
}
@Override
- public void authChange() {
+ public void logout() {
+ if (loginContext == null)
+ throw new CmsException("Login context should not be null");
+ try {
+ loginContext.logout();
+ LoginContext anonymousLc = new LoginContext(
+ AuthConstants.LOGIN_CONTEXT_ANONYMOUS, subject);
+ anonymousLc.login();
+ authChange(anonymousLc);
+ } catch (LoginException e) {
+ throw new CmsException("Cannot logout", e);
+ }
+ }
+
+ @Override
+ public void authChange(LoginContext loginContext) {
+ if (loginContext == null)
+ throw new CmsException("Login context cannot be null");
+ this.loginContext = loginContext;
Subject.doAs(subject, new PrivilegedAction<Void>() {
@Override
try {
node = session.getNode(currentPath);
} catch (Exception e) {
- try {
- // TODO find a less hacky way to log out
- new LoginContext(
- AuthConstants.LOGIN_CONTEXT_ANONYMOUS,
- subject).logout();
- new LoginContext(
- AuthConstants.LOGIN_CONTEXT_ANONYMOUS,
- subject).login();
- } catch (LoginException eAnonymous) {
- throw new ArgeoException(
- "Cannot reset to anonymous", eAnonymous);
- }
- JcrUtils.logoutQuietly(session);
+ logout();
session = repository.login(workspace);
navigateTo("~");
throw e;
+++ /dev/null
-package org.argeo.cms;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.cms.util.SimpleApp;
-
-/**
- * Configures an Argeo CMS RWT application.
- *
- * @deprecated Use {@link SimpleApp} instead (same method signatures)
- */
-@Deprecated
-public class CmsApplication extends SimpleApp {
- private final static Log log = LogFactory.getLog(CmsApplication.class);
-
- public CmsApplication() {
- super();
- log.warn("org.argeo.cms.CmsApplication will be removed soon, use org.argeo.cms.util.SimpleApp");
- }
-
- //
- // private Map<String, Map<String, String>> branding = new HashMap<String,
- // Map<String, String>>();
- // private Map<String, List<String>> styleSheets = new HashMap<String,
- // List<String>>();
- //
- // private List<String> resources = new ArrayList<String>();
- //
- // private BundleContext bundleContext;
- //
- // private Repository repository;
- // private String workspace = null;
- // private String basePath = "/";
- // private List<String> roPrincipals = Arrays.asList("anonymous",
- // "everyone");
- // private List<String> rwPrincipals = Arrays.asList("everyone");
- //
- // private CmsUiProvider header;
- // private Map<String, CmsUiProvider> pages = new LinkedHashMap<String,
- // CmsUiProvider>();
- //
- // private Integer headerHeight = 40;
- //
- // // Managers
- // private CmsImageManager imageManager = new ImageManagerImpl();
- //
- // public void configure(Application application) {
- // try {
- // application.setOperationMode(OperationMode.SWT_COMPATIBILITY);
- // application.setExceptionHandler(new CmsExceptionHandler());
- //
- // // TODO load all pics under icons
- // // loading animated gif
- // application.addResource(LOADING_IMAGE,
- // createResourceLoader(LOADING_IMAGE));
- // // empty image
- // application.addResource(NO_IMAGE, createResourceLoader(NO_IMAGE));
- //
- // for (String resource : resources) {
- // application.addResource(resource, new BundleResourceLoader(
- // bundleContext));
- // if (log.isDebugEnabled())
- // log.debug("Registered resource " + resource);
- // }
- //
- // Map<String, String> defaultBranding = null;
- // if (branding.containsKey("*"))
- // defaultBranding = branding.get("*");
- //
- // // entry points
- // for (String page : pages.keySet()) {
- // Map<String, String> properties = defaultBranding != null ? new
- // HashMap<String, String>(
- // defaultBranding) : new HashMap<String, String>();
- // if (branding.containsKey(page)) {
- // properties.putAll(branding.get(page));
- // }
- // // favicon
- // if (properties.containsKey(WebClient.FAVICON)) {
- // String faviconRelPath = properties.get(WebClient.FAVICON);
- // application.addResource(faviconRelPath,
- // new BundleResourceLoader(bundleContext));
- // if (log.isTraceEnabled())
- // log.trace("Registered favicon " + faviconRelPath);
- //
- // }
- //
- // // page title
- // if (!properties.containsKey(WebClient.PAGE_TITLE))
- // properties.put(
- // WebClient.PAGE_TITLE,
- // Character.toUpperCase(page.charAt(0))
- // + page.substring(1));
- //
- // // default body HTML
- // if (!properties.containsKey(WebClient.BODY_HTML))
- // properties.put(WebClient.BODY_HTML, DEFAULT_LOADING_BODY);
- //
- // //
- // // ADD ENTRY POINT
- // //
- // application.addEntryPoint("/" + page, new CmsEntryPointFactory(
- // pages.get(page), repository, workspace, properties),
- // properties);
- // log.info("Registered entry point /" + page);
- // }
- //
- // // stylesheets
- // for (String themeId : styleSheets.keySet()) {
- // List<String> cssLst = styleSheets.get(themeId);
- // for (String css : cssLst) {
- // application.addStyleSheet(themeId, css,
- // new BundleResourceLoader(bundleContext));
- // }
- //
- // }
- // } catch (RuntimeException e) {
- // // Easier access to initialisation errors
- // log.error("Unexpected exception when configuring RWT application.",
- // e);
- // throw e;
- // }
- // }
- //
- // public void init() throws RepositoryException {
- // Session session = null;
- // try {
- // session = JcrUtils.loginOrCreateWorkspace(repository, workspace);
- // VersionManager vm = session.getWorkspace().getVersionManager();
- // if (!vm.isCheckedOut("/"))
- // vm.checkout("/");
- // JcrUtils.mkdirs(session, basePath);
- // for (String principal : rwPrincipals)
- // JcrUtils.addPrivilege(session, basePath, principal,
- // Privilege.JCR_WRITE);
- // for (String principal : roPrincipals)
- // JcrUtils.addPrivilege(session, basePath, principal,
- // Privilege.JCR_READ);
- //
- // for (String pageName : pages.keySet()) {
- // try {
- // initPage(session, pages.get(pageName));
- // session.save();
- // } catch (Exception e) {
- // throw new CmsException(
- // "Cannot initialize page " + pageName, e);
- // }
- // }
- //
- // } finally {
- // JcrUtils.logoutQuietly(session);
- // }
- // }
- //
- // protected void initPage(Session adminSession, CmsUiProvider page)
- // throws RepositoryException {
- // if (page instanceof LifeCycleUiProvider)
- // ((LifeCycleUiProvider) page).init(adminSession);
- // }
- //
- // public void destroy() {
- // for (String pageName : pages.keySet()) {
- // try {
- // CmsUiProvider page = pages.get(pageName);
- // if (page instanceof LifeCycleUiProvider)
- // ((LifeCycleUiProvider) page).destroy();
- // } catch (Exception e) {
- // log.error("Cannot destroy page " + pageName, e);
- // }
- // }
- // }
- //
- // public void setRepository(Repository repository) {
- // this.repository = repository;
- // }
- //
- // public void setWorkspace(String workspace) {
- // this.workspace = workspace;
- // }
- //
- // public void setCmsLogin(@SuppressWarnings("deprecation") CmsLogin
- // cmsLogin) {
- // // this.cmsLogin = cmsLogin;
- // log.warn("cmsLogin"
- // +
- // " is deprecated and will be removed soon. Adapt your configuration ASAP.");
- // }
- //
- // public void setHeader(CmsUiProvider header) {
- // this.header = header;
- // }
- //
- // public void setPages(Map<String, CmsUiProvider> pages) {
- // this.pages = pages;
- // }
- //
- // public void setBasePath(String basePath) {
- // this.basePath = basePath;
- // }
- //
- // public void setRoPrincipals(List<String> roPrincipals) {
- // this.roPrincipals = roPrincipals;
- // }
- //
- // public void setRwPrincipals(List<String> rwPrincipals) {
- // this.rwPrincipals = rwPrincipals;
- // }
- //
- // public void setHeaderHeight(Integer headerHeight) {
- // this.headerHeight = headerHeight;
- // }
- //
- // public void setBranding(Map<String, Map<String, String>> branding) {
- // this.branding = branding;
- // }
- //
- // public void setStyleSheets(Map<String, List<String>> styleSheets) {
- // this.styleSheets = styleSheets;
- // }
- //
- // public void setBundleContext(BundleContext bundleContext) {
- // this.bundleContext = bundleContext;
- // }
- //
- // public void setResources(List<String> resources) {
- // this.resources = resources;
- // }
- //
- // class CmsExceptionHandler implements ExceptionHandler {
- //
- // @Override
- // public void handleException(Throwable throwable) {
- // CmsSession.current.get().exception(throwable);
- // }
- //
- // }
- //
- // private class CmsEntryPointFactory implements EntryPointFactory {
- // private final CmsUiProvider page;
- // private final Repository repository;
- // private final String workspace;
- // private final Map<String, String> properties;
- //
- // public CmsEntryPointFactory(CmsUiProvider page, Repository repository,
- // String workspace, Map<String, String> properties) {
- // this.page = page;
- // this.repository = repository;
- // this.workspace = workspace;
- // this.properties = properties;
- // }
- //
- // @Override
- // public EntryPoint create() {
- // CmsEntryPoint entryPoint = new CmsEntryPoint(repository, workspace,
- // page, properties);
- // entryPoint.setState("");
- // CmsSession.current.set(entryPoint);
- // return entryPoint;
- // }
- //
- // }
- //
- // private class CmsEntryPoint extends AbstractCmsEntryPoint {
- // private Composite headerArea;
- // private Composite bodyArea;
- // private final CmsUiProvider uiProvider;
- //
- // public CmsEntryPoint(Repository repository, String workspace,
- // CmsUiProvider uiProvider, Map<String, String> factoryProperties) {
- // super(repository, workspace, factoryProperties);
- // this.uiProvider = uiProvider;
- // }
- //
- // @Override
- // protected void createContents(Composite parent) {
- // try {
- // getShell().getDisplay().setData(CmsSession.KEY, this);
- //
- // parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
- // true));
- // parent.setLayout(CmsUtils.noSpaceGridLayout());
- //
- // headerArea = new Composite(parent, SWT.NONE);
- // headerArea.setLayout(new FillLayout());
- // GridData headerData = new GridData(SWT.FILL, SWT.FILL, false,
- // false);
- // headerData.heightHint = headerHeight;
- // headerArea.setLayoutData(headerData);
- // refreshHeader();
- //
- // bodyArea = new Composite(parent, SWT.NONE);
- // bodyArea.setData(RWT.CUSTOM_VARIANT, CmsStyles.CMS_BODY);
- // bodyArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
- // true));
- // // Should not be set here: it then prevent all children
- // // composite to define a background color via CSS
- // // bodyArea.setBackgroundMode(SWT.INHERIT_DEFAULT);
- // bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
- // refreshBody();
- // } catch (Exception e) {
- // throw new CmsException("Cannot create entrypoint contents", e);
- // }
- // }
- //
- // @Override
- // protected void refreshHeader() {
- // if (headerArea == null)
- // return;
- // for (Control child : headerArea.getChildren())
- // child.dispose();
- // try {
- // header.createUi(headerArea, getNode());
- // } catch (RepositoryException e) {
- // throw new CmsException("Cannot refresh header", e);
- // }
- // headerArea.layout(true, true);
- // }
- //
- // @Override
- // protected void refreshBody() {
- // if (bodyArea == null)
- // return;
- // // Exception
- // Throwable exception = getException();
- // if (exception != null) {
- // // new Label(bodyArea, SWT.NONE).setText("Unreachable state : "
- // // + getState());
- // // if (getNode() != null)
- // // new Label(bodyArea, SWT.NONE).setText("Context : "
- // // + getNode());
- // //
- // // Text errorText = new Text(bodyArea, SWT.MULTI | SWT.H_SCROLL
- // // | SWT.V_SCROLL);
- // // errorText.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
- // // true,
- // // true));
- // // StringWriter sw = new StringWriter();
- // // exception.printStackTrace(new PrintWriter(sw));
- // // errorText.setText(sw.toString());
- // // IOUtils.closeQuietly(sw);
- // SystemNotifications systemNotifications = new SystemNotifications(
- // bodyArea);
- // systemNotifications.notifyException(exception);
- // resetException();
- // return;
- // // TODO report
- // }
- //
- // // clear
- // for (Control child : bodyArea.getChildren())
- // child.dispose();
- // bodyArea.setLayout(CmsUtils.noSpaceGridLayout());
- //
- // String state = getState();
- // try {
- // if (state == null)
- // throw new CmsException("State cannot be null");
- // uiProvider.createUi(bodyArea, getNode());
- // } catch (RepositoryException e) {
- // throw new CmsException("Cannot refresh body", e);
- // }
- //
- // bodyArea.layout(true, true);
- // }
- //
- // @Override
- // protected Node getDefaultNode(Session session)
- // throws RepositoryException {
- // if (!session.hasPermission(basePath, "read")) {
- // if (session.getUserID().equals("anonymous"))
- // throw new LoginRequiredException();
- // else
- // throw new CmsException("Unauthorized");
- // }
- // return session.getNode(basePath);
- // }
- //
- // @Override
- // public CmsImageManager getImageManager() {
- // return imageManager;
- // }
- //
- // }
- //
- // private static ResourceLoader createResourceLoader(final String
- // resourceName) {
- // return new ResourceLoader() {
- // public InputStream getResourceAsStream(String resourceName)
- // throws IOException {
- // return getClass().getClassLoader().getResourceAsStream(
- // resourceName);
- // }
- // };
- // }
- //
- // /*
- // * TEXTS
- // */
- // private static String DEFAULT_LOADING_BODY = "<div"
- // +
- // " style=\"position: absolute; left: 50%; top: 50%; margin: -32px -32px; width: 64px; height:64px\">"
- // +
- // "<img src=\"./rwt-resources/icons/loading.gif\" width=\"32\" height=\"32\" style=\"margin: 16px 16px\"/>"
- // + "</div>";
-}
package org.argeo.cms;
import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
/** Provides interaction with the CMS system. UNSTABLE API at this stage. */
public interface CmsView {
public void navigateTo(String state);
// SECURITY
- public void authChange();
+ public void authChange(LoginContext loginContext);
public Subject getSubject();
+ public void logout();
+
// SERVICES
public void exception(Throwable e);
final static String LOGIN_CONTEXT_SINGLE_USER = "SINGLE_USER";
// HTTP
+ @Deprecated
final static String ACCESS_CONTROL_CONTEXT = "org.argeo.node.accessControlContext";
// RESERVED ROLES
public final static String ROLE_ANONYMOUS = "cn=anonymous," + ROLES_BASEDN;
// SHARED STATE KEYS
- public final static String BUNDLE_CONTEXT_KEY = "org.argeo.security.bundleContext";
- public final static String AUTHORIZATION_KEY = "org.argeo.security.authorization";
+ //public final static String BUNDLE_CONTEXT_KEY = "org.argeo.security.bundleContext";
+ //public final static String AUTHORIZATION_KEY = "org.argeo.security.authorization";
}
return getDisplayName(currentSubject());
}
+ public static boolean isAnonymous() {
+ return isAnonymous(currentSubject());
+ }
+
+ public static boolean isAnonymous(Subject subject) {
+ return getUsername(subject).equalsIgnoreCase(
+ AuthConstants.ROLE_ANONYMOUS);
+ }
+
private static Subject currentSubject() {
Subject subject = Subject.getSubject(AccessController.getContext());
if (subject != null)
--- /dev/null
+package org.argeo.cms.auth;
+
+import javax.security.auth.callback.Callback;
+import javax.servlet.http.HttpServletRequest;
+
+public class HttpRequestCallback implements Callback {
+ private HttpServletRequest request;
+
+ public HttpServletRequest getRequest() {
+ return request;
+ }
+
+ public void setRequest(HttpServletRequest request) {
+ this.request = request;
+ }
+
+}
--- /dev/null
+package org.argeo.cms.auth;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Callback handler populating {@link HttpRequestCallback}s with the provided
+ * {@link HttpServletRequest}, and ignoring any other callback.
+ */
+public class HttpRequestCallbackHandler implements CallbackHandler {
+ final private HttpServletRequest request;
+
+ public HttpRequestCallbackHandler(HttpServletRequest request) {
+ this.request = request;
+ }
+
+ @Override
+ public void handle(Callback[] callbacks) throws IOException,
+ UnsupportedCallbackException {
+ for (Callback callback : callbacks)
+ if (callback instanceof HttpRequestCallback)
+ ((HttpRequestCallback) callback).setRequest(request);
+ }
+
+}
+++ /dev/null
-package org.argeo.cms.auth;
-
-import java.util.Map;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.login.LoginException;
-import javax.security.auth.spi.LoginModule;
-
-import org.argeo.cms.internal.kernel.Activator;
-import org.eclipse.swt.widgets.Display;
-import org.osgi.service.useradmin.Authorization;
-
-/** Populates the shared state with this node context. */
-public class NodeContextLoginModule implements LoginModule, AuthConstants {
- private Subject subject;
- private Map<String, Object> sharedState;
-
- @SuppressWarnings("unchecked")
- @Override
- public void initialize(Subject subject, CallbackHandler callbackHandler,
- Map<String, ?> sharedState, Map<String, ?> options) {
- this.subject = subject;
- this.sharedState = (Map<String, Object>) sharedState;
- }
-
- @Override
- public boolean login() throws LoginException {
- sharedState.put(AuthConstants.BUNDLE_CONTEXT_KEY, Activator.getBundleContext());
- Display display = Display.getCurrent();
- if (display != null) {
- Authorization authorization = (Authorization) display
- .getData(AuthConstants.AUTHORIZATION_KEY);
- if (authorization != null)
- sharedState.put(AuthConstants.AUTHORIZATION_KEY, authorization);
- }
- return true;
- }
-
- @Override
- public boolean commit() throws LoginException {
- Display display = Display.getCurrent();
- if (display != null) {
- Authorization authorization = subject
- .getPrivateCredentials(Authorization.class).iterator()
- .next();
- display.setData(AuthConstants.AUTHORIZATION_KEY, authorization);
- }
- return true;
- }
-
- @Override
- public boolean abort() throws LoginException {
- sharedState.remove(AuthConstants.BUNDLE_CONTEXT_KEY);
- sharedState.remove(AuthConstants.AUTHORIZATION_KEY);
- Display display = Display.getCurrent();
- if (display != null)
- display.setData(AuthConstants.AUTHORIZATION_KEY, null);
- return true;
- }
-
- @Override
- public boolean logout() throws LoginException {
- sharedState.remove(AuthConstants.BUNDLE_CONTEXT_KEY);
- sharedState.remove(AuthConstants.AUTHORIZATION_KEY);
- Display display = Display.getCurrent();
- if (display != null)
- display.setData(AuthConstants.AUTHORIZATION_KEY, null);
- return true;
- }
-
-}
@Override
public boolean commit() throws LoginException {
- if (authorization != null) {
- Set<Principal> principals = subject.getPrincipals();
- try {
- String authName = authorization.getName();
-
- // determine user's principal
- final LdapName name;
- final Principal userPrincipal;
- if (authName == null) {
- name = ROLE_ANONYMOUS_NAME;
- userPrincipal = ROLE_ANONYMOUS_PRINCIPAL;
- principals.add(userPrincipal);
- principals.add(new AnonymousPrincipal());
+ if (authorization == null)
+ throw new LoginException("Authorization should not be null");
+ Set<Principal> principals = subject.getPrincipals();
+ try {
+ String authName = authorization.getName();
+
+ // determine user's principal
+ final LdapName name;
+ final Principal userPrincipal;
+ if (authName == null) {
+ name = ROLE_ANONYMOUS_NAME;
+ userPrincipal = ROLE_ANONYMOUS_PRINCIPAL;
+ principals.add(userPrincipal);
+ principals.add(new AnonymousPrincipal());
+ } else {
+ name = new LdapName(authName);
+ checkUserName(name);
+ userPrincipal = new X500Principal(name.toString());
+ principals.add(userPrincipal);
+ principals.add(new ImpliedByPrincipal(ROLE_USER_NAME,
+ userPrincipal));
+ }
+
+ // Add roles provided by authorization
+ for (String role : authorization.getRoles()) {
+ LdapName roleName = new LdapName(role);
+ if (roleName.equals(name)) {
+ // skip
} else {
- name = new LdapName(authName);
- checkUserName(name);
- userPrincipal = new X500Principal(name.toString());
- principals.add(userPrincipal);
- principals.add(new ImpliedByPrincipal(ROLE_USER_NAME,
+ checkImpliedPrincipalName(roleName);
+ principals.add(new ImpliedByPrincipal(roleName.toString(),
userPrincipal));
+ if (roleName.equals(ROLE_ADMIN_NAME))
+ principals.add(new AdminPrincipal(
+ SecurityConstants.ADMIN_ID));
}
-
- // Add roles provided by authorization
- for (String role : authorization.getRoles()) {
- LdapName roleName = new LdapName(role);
- if (roleName.equals(name)) {
- // skip
- } else {
- checkImpliedPrincipalName(roleName);
- principals.add(new ImpliedByPrincipal(roleName
- .toString(), userPrincipal));
- if (roleName.equals(ROLE_ADMIN_NAME))
- principals.add(new AdminPrincipal(
- SecurityConstants.ADMIN_ID));
- }
- }
-
- return true;
- } catch (InvalidNameException e) {
- throw new CmsException("Cannot commit", e);
}
- } else
- return false;
+
+ return true;
+ } catch (InvalidNameException e) {
+ throw new CmsException("Cannot commit", e);
+ }
}
@Override
@Override
public boolean logout() throws LoginException {
- // TODO better deal with successive logout
if (subject == null)
- return true;
- // TODO make it less brutal
+ throw new LoginException("Subject should not be null");
+ // Argeo
subject.getPrincipals().removeAll(
subject.getPrincipals(X500Principal.class));
subject.getPrincipals().removeAll(
subject.getPrincipals(ImpliedByPrincipal.class));
+ // Jackrabbit
subject.getPrincipals().removeAll(
subject.getPrincipals(AdminPrincipal.class));
subject.getPrincipals().removeAll(
package org.argeo.cms.auth;
+import java.io.IOException;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import javax.security.auth.Subject;
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.callback.UnsupportedCallbackException;
import javax.security.auth.login.CredentialNotFoundException;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
import org.argeo.ArgeoException;
+import org.argeo.cms.internal.kernel.Activator;
import org.osgi.framework.BundleContext;
+import org.osgi.service.http.HttpContext;
import org.osgi.service.useradmin.Authorization;
import org.osgi.service.useradmin.User;
import org.osgi.service.useradmin.UserAdmin;
public class UserAdminLoginModule implements LoginModule, AuthConstants {
private Subject subject;
- private Map<String, Object> sharedState;
private CallbackHandler callbackHandler;
private boolean isAnonymous = false;
- @SuppressWarnings("unchecked")
+ private HttpServletRequest request = null;
+
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String, ?> sharedState, Map<String, ?> options) {
try {
this.subject = subject;
- this.sharedState = (Map<String, Object>) sharedState;
this.callbackHandler = callbackHandler;
if (options.containsKey("anonymous"))
isAnonymous = Boolean.parseBoolean(options.get("anonymous")
@Override
public boolean login() throws LoginException {
- BundleContext bc = (BundleContext) sharedState
- .get(AuthConstants.BUNDLE_CONTEXT_KEY);
+ BundleContext bc = Activator.getBundleContext();
UserAdmin userAdmin = bc.getService(bc
.getServiceReference(UserAdmin.class));
- Authorization authorization = (Authorization) sharedState
- .get(AuthConstants.AUTHORIZATION_KEY);
- if (authorization == null)
- if (!isAnonymous) {
- // ask for username and password
- NameCallback nameCallback = new NameCallback("User");
- PasswordCallback passwordCallback = new PasswordCallback(
- "Password", false);
-
- // handle callbacks
- try {
- callbackHandler.handle(new Callback[] { nameCallback,
- passwordCallback });
- } catch (Exception e) {
- throw new ArgeoException("Cannot handle callbacks", e);
- }
+ Authorization authorization = null;
+ if (isAnonymous) {
+ authorization = userAdmin.getAuthorization(null);
+ } else {
+ HttpRequestCallback httpCallback = new HttpRequestCallback();
+ // ask for username and password
+ NameCallback nameCallback = new NameCallback("User");
+ PasswordCallback passwordCallback = new PasswordCallback(
+ "Password", false);
+ try {
+ callbackHandler.handle(new Callback[] { httpCallback,
+ nameCallback, passwordCallback });
+ } catch (IOException e) {
+ throw new LoginException("Cannot handle http callback: "
+ + e.getMessage());
+ } catch (UnsupportedCallbackException e) {
+ return false;
+ }
+ request = httpCallback.getRequest();
+ if (request != null) {
+ authorization = (Authorization) request
+ .getAttribute(HttpContext.AUTHORIZATION);
+ if (authorization == null)
+ authorization = (Authorization) request.getSession()
+ .getAttribute(HttpContext.AUTHORIZATION);
+ }
+ // if (authorization == null || authorization.getName() == null)
+ // if (!isAnonymous) {
+ // // ask for username and password
+ // NameCallback nameCallback = new NameCallback("User");
+ // PasswordCallback passwordCallback = new PasswordCallback(
+ // "Password", false);
+ //
+ // // handle callbacks
+ // try {
+ // callbackHandler.handle(new Callback[] { nameCallback,
+ // passwordCallback });
+ // } catch (Exception e) {
+ // throw new ArgeoException("Cannot handle callbacks", e);
+ // }
+ if (authorization == null) {
// create credentials
final String username = nameCallback.getName();
- if (username == null || username.trim().equals(""))
- throw new CredentialNotFoundException(
- "No credentials provided");
-
- char[] password = {};
- if (passwordCallback.getPassword() != null)
- password = passwordCallback.getPassword();
- else
+ if (username == null || username.trim().equals("")) {
+ // authorization = userAdmin.getAuthorization(null);
throw new CredentialNotFoundException(
"No credentials provided");
+ } else {
+ char[] password = {};
+ if (passwordCallback.getPassword() != null)
+ password = passwordCallback.getPassword();
+ else
+ throw new CredentialNotFoundException(
+ "No credentials provided");
- User user = userAdmin.getUser(null, username);
- if (user == null)
- return false;
- if (!user.hasCredential(null, password))
- return false;
- authorization = userAdmin.getAuthorization(user);
- } else {
- authorization = userAdmin.getAuthorization(null);
+ User user = userAdmin.getUser(null, username);
+ if (user == null)
+ return false;
+ if (!user.hasCredential(null, password))
+ return false;
+ authorization = userAdmin.getAuthorization(user);
+ }
}
+ // } else {
+ // authorization = userAdmin.getAuthorization(null);
+ // }
+ }
subject.getPrivateCredentials().add(authorization);
return true;
}
@Override
public boolean commit() throws LoginException {
+ Authorization authorization = subject
+ .getPrivateCredentials(Authorization.class).iterator().next();
+ if (request != null) {
+ request.setAttribute(HttpContext.REMOTE_USER,
+ authorization.getName());
+ request.setAttribute(HttpContext.AUTHORIZATION, authorization);
+ request.getSession().setAttribute(HttpContext.AUTHORIZATION,
+ authorization);
+ subject.getPrivateCredentials().add(request.getSession());
+ }
return true;
}
@Override
public boolean logout() throws LoginException {
+ Set<HttpSession> httpSession = subject
+ .getPrivateCredentials(HttpSession.class);
+ Iterator<HttpSession> it = httpSession.iterator();
+ while (it.hasNext()) {
+ HttpSession sess = it.next();
+ sess.setAttribute(HttpContext.AUTHORIZATION, null);
+ // sess.setMaxInactiveInterval(1);// invalidate session
+ }
+ subject.getPrivateCredentials().removeAll(httpSession);
cleanUp();
return true;
}
package org.argeo.cms.internal.kernel;
-import static org.argeo.cms.auth.AuthConstants.ACCESS_CONTROL_CONTEXT;
+import static org.argeo.cms.auth.AuthConstants.LOGIN_CONTEXT_USER;
import java.io.IOException;
import java.io.Serializable;
import java.net.URL;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.security.cert.X509Certificate;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.CredentialNotFoundException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.jackrabbit.webdav.simple.SimpleWebdavServlet;
import org.argeo.cms.CmsException;
import org.argeo.cms.auth.AuthConstants;
+import org.argeo.cms.auth.HttpRequestCallback;
+import org.argeo.cms.auth.HttpRequestCallbackHandler;
import org.argeo.jcr.ArgeoJcrConstants;
import org.argeo.jcr.JcrUtils;
import org.osgi.service.http.HttpContext;
class DataHttp implements KernelConstants, ArgeoJcrConstants {
private final static Log log = LogFactory.getLog(DataHttp.class);
- private final static String ATTR_AUTH = "auth";
+ // private final static String ATTR_AUTH = "auth";
private final static String HEADER_AUTHORIZATION = "Authorization";
private final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
- // private final AuthenticationManager authenticationManager;
private final HttpService httpService;
// FIXME Make it more unique
new DataHttpContext(anonymous));
}
- // private Boolean isSessionAuthenticated(HttpSession httpSession) {
- // SecurityContext contextFromSession = (SecurityContext) httpSession
- // .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
- // return contextFromSession != null;
- // }
-
- private void requestBasicAuth(HttpSession httpSession,
- HttpServletResponse response) {
- response.setStatus(401);
- response.setHeader(HEADER_WWW_AUTHENTICATE, "basic realm=\""
- + httpAuthRealm + "\"");
- httpSession.setAttribute(ATTR_AUTH, Boolean.TRUE);
- }
-
- private CallbackHandler basicAuth(String authHeader) {
- 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 {
- throw new CmsException(
- "Invalid authentication token");
- }
- } catch (Exception e) {
- throw new CmsException(
- "Couldn't retrieve authentication", e);
- }
- }
- }
- }
- throw new CmsException("Couldn't retrieve authentication");
- }
-
- private X509Certificate extractCertificate(HttpServletRequest req) {
- X509Certificate[] certs = (X509Certificate[]) req
- .getAttribute("javax.servlet.request.X509Certificate");
- if (null != certs && certs.length > 0) {
- return certs[0];
- }
- return null;
- }
+// private X509Certificate extractCertificate(HttpServletRequest req) {
+// X509Certificate[] certs = (X509Certificate[]) req
+// .getAttribute("javax.servlet.request.X509Certificate");
+// if (null != certs && certs.length > 0) {
+// return certs[0];
+// }
+// return null;
+// }
private Subject subjectFromRequest(HttpServletRequest request) {
- HttpSession httpSession = request.getSession();
Authorization authorization = (Authorization) request
.getAttribute(HttpContext.AUTHORIZATION);
if (authorization == null)
throw new CmsException("Not authenticated");
- AccessControlContext acc = (AccessControlContext) httpSession
- .getAttribute(AuthConstants.ACCESS_CONTROL_CONTEXT);
- Subject subject = Subject.getSubject(acc);
- return subject;
+ try {
+ LoginContext lc = new LoginContext(
+ AuthConstants.LOGIN_CONTEXT_USER,
+ new HttpRequestCallbackHandler(request));
+ lc.login();
+ return lc.getSubject();
+ } catch (LoginException e) {
+ throw new CmsException("Cannot login", e);
+ }
}
private class DataHttpContext implements HttpContext {
}
@Override
- public boolean handleSecurity(HttpServletRequest request,
+ public boolean handleSecurity(final HttpServletRequest request,
HttpServletResponse response) throws IOException {
- final Subject subject;
if (anonymous) {
- subject = KernelUtils.anonymousLogin();
+ Subject subject = KernelUtils.anonymousLogin();
Authorization authorization = subject
.getPrivateCredentials(Authorization.class).iterator()
.next();
+ request.setAttribute(REMOTE_USER, AuthConstants.ROLE_ANONYMOUS);
request.setAttribute(AUTHORIZATION, authorization);
return true;
}
- final HttpSession httpSession = request.getSession();
- AccessControlContext acc = (AccessControlContext) httpSession
- .getAttribute(AuthConstants.ACCESS_CONTROL_CONTEXT);
- if (acc != null) {
- subject = Subject.getSubject(acc);
- } else {
- // Process basic auth
- String basicAuth = request.getHeader(HEADER_AUTHORIZATION);
- if (basicAuth != null) {
- CallbackHandler token = basicAuth(basicAuth);
+ KernelUtils.logRequestHeaders(log, request);
+ try {
+ new LoginContext(LOGIN_CONTEXT_USER,
+ new HttpRequestCallbackHandler(request)).login();
+ return true;
+ } catch (CredentialNotFoundException e) {
+ CallbackHandler token = basicAuth(request);
+ if (token != null) {
try {
- LoginContext lc = new LoginContext(
- AuthConstants.LOGIN_CONTEXT_USER, token);
+ LoginContext lc = new LoginContext(LOGIN_CONTEXT_USER,
+ token);
lc.login();
- subject = lc.getSubject();
- } catch (LoginException e) {
- throw new CmsException("Could not login", e);
+ // Note: this is impossible to reliably clear the
+ // authorization header when access from a browser.
+ return true;
+ } catch (LoginException e1) {
+ throw new CmsException("Could not login", e1);
}
- Subject.doAs(subject, new PrivilegedAction<Void>() {
- public Void run() {
- // add security context to session
- httpSession.setAttribute(ACCESS_CONTROL_CONTEXT,
- AccessController.getContext());
- return null;
- }
- });
} else {
- requestBasicAuth(httpSession, response);
+ requestBasicAuth(request, response);
return false;
}
+ } catch (LoginException e) {
+ throw new CmsException("Could not login", e);
}
- // authenticate request
- Authorization authorization = subject
- .getPrivateCredentials(Authorization.class).iterator()
- .next();
- request.setAttribute(AUTHORIZATION, authorization);
- return true;
}
@Override
return null;
}
+ private void requestBasicAuth(HttpServletRequest request,
+ HttpServletResponse response) {
+ response.setStatus(401);
+ response.setHeader(HEADER_WWW_AUTHENTICATE, "basic realm=\""
+ + httpAuthRealm + "\"");
+ // request.getSession().setAttribute(ATTR_AUTH, Boolean.TRUE);
+ }
+
+ private CallbackHandler basicAuth(final HttpServletRequest httpRequest) {
+ String authHeader = httpRequest.getHeader(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);
+ }
+ }
+ };
+ } else {
+ throw new CmsException(
+ "Invalid authentication token");
+ }
+ } catch (Exception e) {
+ throw new CmsException(
+ "Couldn't retrieve authentication", e);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
}
/**
Kernel.class.getClassLoader());
long begin = System.currentTimeMillis();
+ // KernelUtils.logFrameworkProperties(log);
+
try {
// Initialise services
logger = new NodeLogger();
import org.apache.commons.logging.Log;
import org.argeo.cms.CmsException;
import org.argeo.cms.auth.AuthConstants;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
/** Package utilities */
class KernelUtils implements KernelConstants {
}
}
+ static void logFrameworkProperties(Log log) {
+ BundleContext bc = Activator.getBundleContext();
+ String[] keys = { Constants.FRAMEWORK_STORAGE,
+ Constants.FRAMEWORK_OS_NAME, Constants.FRAMEWORK_OS_VERSION,
+ Constants.FRAMEWORK_PROCESSOR, Constants.FRAMEWORK_SECURITY,
+ Constants.FRAMEWORK_TRUST_REPOSITORIES,
+ Constants.FRAMEWORK_WINDOWSYSTEM, Constants.FRAMEWORK_VENDOR,
+ Constants.FRAMEWORK_VERSION, Constants.FRAMEWORK_STORAGE_CLEAN,
+ Constants.FRAMEWORK_LANGUAGE, Constants.FRAMEWORK_UUID };
+ for (String key : keys)
+ log.debug(key + "=" + bc.getProperty(key));
+ }
+
private KernelUtils() {
}
package org.argeo.cms.internal.kernel;
-import static org.argeo.cms.auth.AuthConstants.ACCESS_CONTROL_CONTEXT;
-
import java.io.IOException;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
-import java.util.Properties;
-import java.util.StringTokenizer;
-import javax.jcr.Repository;
-import javax.security.auth.Subject;
-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.FilterChain;
-import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-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.AuthConstants;
-import org.argeo.jackrabbit.servlet.OpenInViewSessionProvider;
-import org.argeo.jackrabbit.servlet.RemotingServlet;
-import org.argeo.jackrabbit.servlet.WebdavServlet;
import org.argeo.jcr.ArgeoJcrConstants;
import org.eclipse.equinox.http.servlet.ExtendedHttpService;
-import org.osgi.service.http.NamespaceException;
/**
* Intercepts and enriches http access, mainly focusing on security and
class NodeHttp implements KernelConstants, ArgeoJcrConstants {
private final static Log log = LogFactory.getLog(NodeHttp.class);
- private final static String ATTR_AUTH = "auth";
- private final static String HEADER_AUTHORIZATION = "Authorization";
- private final static String HEADER_WWW_AUTHENTICATE = "WWW-Authenticate";
-
- // private final AuthenticationManager authenticationManager;
- private final ExtendedHttpService httpService;
-
- // FIXME Make it more unique
- private String httpAuthRealm = "Argeo";
-
// Filters
private final RootFilter rootFilter;
+
// private final DoSFilter dosFilter;
// private final QoSFilter qosFilter;
- // WebDav / JCR remoting
- private OpenInViewSessionProvider sessionProvider;
-
- NodeHttp(ExtendedHttpService httpService, NodeRepository node) {
- // this.bundleContext = bundleContext;
- // this.authenticationManager = authenticationManager;
-
- this.httpService = httpService;
-
- // Filters
+ NodeHttp(ExtendedHttpService httpService) {
rootFilter = new RootFilter();
// dosFilter = new CustomDosFilter();
// qosFilter = new QoSFilter();
- // DAV
- sessionProvider = new OpenInViewSessionProvider();
-
- registerRepositoryServlets(ALIAS_NODE, node);
try {
httpService.registerFilter("/", rootFilter, null, null);
} catch (Exception e) {
- throw new CmsException("Could not register root filter", e);
+ throw new CmsException("Cannot register filters", e);
}
}
public void destroy() {
- sessionProvider.destroy();
- unregisterRepositoryServlets(ALIAS_NODE);
- }
-
- void registerRepositoryServlets(String alias, Repository repository) {
- try {
- registerWebdavServlet(alias, repository, true);
- registerWebdavServlet(alias, repository, false);
- registerRemotingServlet(alias, repository, true);
- registerRemotingServlet(alias, repository, false);
- } catch (Exception e) {
- throw new CmsException(
- "Could not register servlets for repository " + alias, e);
- }
- }
-
- void unregisterRepositoryServlets(String alias) {
- // FIXME unregister servlets
- }
-
- void registerWebdavServlet(String alias, Repository repository,
- boolean anonymous) throws NamespaceException, ServletException {
- WebdavServlet webdavServlet = new WebdavServlet(repository,
- sessionProvider);
- String pathPrefix = anonymous ? WEBDAV_PUBLIC : WEBDAV_PRIVATE;
- String path = pathPrefix + "/" + alias;
- Properties ip = new Properties();
- ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_CONFIG, WEBDAV_CONFIG);
- ip.setProperty(WebdavServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path);
- httpService.registerFilter(path, anonymous ? new AnonymousFilter()
- : new DavFilter(), null, null);
- // Cast to servlet because of a weird behaviour in Eclipse
- httpService.registerServlet(path, (Servlet) webdavServlet, ip, null);
- }
-
- void registerRemotingServlet(String alias, Repository repository,
- boolean anonymous) throws NamespaceException, ServletException {
- String pathPrefix = anonymous ? REMOTING_PUBLIC : REMOTING_PRIVATE;
- RemotingServlet remotingServlet = new RemotingServlet(repository,
- sessionProvider);
- String path = pathPrefix + "/" + alias;
- Properties ip = new Properties();
- ip.setProperty(RemotingServlet.INIT_PARAM_RESOURCE_PATH_PREFIX, path);
-
- // Looks like a bug in Jackrabbit remoting init
- ip.setProperty(RemotingServlet.INIT_PARAM_HOME,
- KernelUtils.getOsgiInstanceDir() + "/tmp/jackrabbit");
- ip.setProperty(RemotingServlet.INIT_PARAM_TMP_DIRECTORY, "remoting");
- // in order to avoid annoying warning.
- ip.setProperty(RemotingServlet.INIT_PARAM_PROTECTED_HANDLERS_CONFIG,
- "");
- // Cast to servlet because of a weird behaviour in Eclipse
- httpService.registerFilter(path, anonymous ? new AnonymousFilter()
- : new DavFilter(), null, null);
- httpService.registerServlet(path, (Servlet) remotingServlet, ip, null);
- }
-
- // private Boolean isSessionAuthenticated(HttpSession httpSession) {
- // SecurityContext contextFromSession = (SecurityContext) httpSession
- // .getAttribute(SPRING_SECURITY_CONTEXT_KEY);
- // return contextFromSession != null;
- // }
-
- private void requestBasicAuth(HttpSession httpSession,
- HttpServletResponse response) {
- response.setStatus(401);
- response.setHeader(HEADER_WWW_AUTHENTICATE, "basic realm=\""
- + httpAuthRealm + "\"");
- httpSession.setAttribute(ATTR_AUTH, Boolean.TRUE);
- }
-
- private CallbackHandler basicAuth(String authHeader) {
- 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 {
- throw new CmsException(
- "Invalid authentication token");
- }
- } catch (Exception e) {
- throw new CmsException(
- "Couldn't retrieve authentication", e);
- }
- }
- }
- }
- throw new CmsException("Couldn't retrieve authentication");
}
/** Intercepts all requests. Authenticates. */
return null;
}
- /** Intercepts all requests. Authenticates. */
- private class AnonymousFilter extends HttpFilter {
- @Override
- public void doFilter(HttpSession httpSession,
- final HttpServletRequest request,
- final HttpServletResponse response,
- final FilterChain filterChain) throws IOException,
- ServletException {
-
- // Authenticate from session
- // if (isSessionAuthenticated(httpSession)) {
- // filterChain.doFilter(request, response);
- // return;
- // }
-
- Subject subject = KernelUtils.anonymousLogin();
- try {
- Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
- public Void run() throws IOException, ServletException {
- filterChain.doFilter(request, response);
- return null;
- }
- });
- } catch (PrivilegedActionException e) {
- if (e.getCause() instanceof ServletException)
- throw (ServletException) e.getCause();
- else if (e.getCause() instanceof IOException)
- throw (IOException) e.getCause();
- else
- throw new CmsException("Unexpected exception", e.getCause());
- }
- }
- }
-
- /** Intercepts all requests. Authenticates. */
- private class DavFilter extends HttpFilter {
-
- @Override
- public void doFilter(final HttpSession httpSession,
- final HttpServletRequest request,
- final HttpServletResponse response,
- final FilterChain filterChain) throws IOException,
- ServletException {
-
- AccessControlContext acc = (AccessControlContext) httpSession
- .getAttribute(AuthConstants.ACCESS_CONTROL_CONTEXT);
- final Subject subject;
- if (acc != null) {
- subject = Subject.getSubject(acc);
- } else {
- // Process basic auth
- String basicAuth = request.getHeader(HEADER_AUTHORIZATION);
- if (basicAuth != null) {
- CallbackHandler token = basicAuth(basicAuth);
- try {
- LoginContext lc = new LoginContext(
- AuthConstants.LOGIN_CONTEXT_USER, token);
- lc.login();
- subject = lc.getSubject();
- } catch (LoginException e) {
- throw new CmsException("Could not login", e);
- }
- } else {
- requestBasicAuth(httpSession, response);
- return;
- }
- }
- // do filter as subject
- try {
- Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
- public Void run() throws IOException, ServletException {
- // add security context to session
- httpSession.setAttribute(ACCESS_CONTROL_CONTEXT,
- AccessController.getContext());
- filterChain.doFilter(request, response);
- return null;
- }
- });
- } catch (PrivilegedActionException e) {
- if (e.getCause() instanceof ServletException)
- throw (ServletException) e.getCause();
- else if (e.getCause() instanceof IOException)
- throw (IOException) e.getCause();
- else
- throw new CmsException("Unexpected exception", e.getCause());
- }
-
- }
- }
-
// class CustomDosFilter extends DoSFilter {
// @Override
// protected String extractUserId(ServletRequest request) {
USER {
- org.argeo.cms.auth.NodeContextLoginModule requisite;
org.argeo.cms.auth.UserAdminLoginModule requisite;
org.argeo.cms.auth.NodeUserLoginModule requisite;
};
ANONYMOUS {
- org.argeo.cms.auth.NodeContextLoginModule requisite;
org.argeo.cms.auth.UserAdminLoginModule requisite anonymous=true;
org.argeo.cms.auth.NodeUserLoginModule requisite;
};
import org.argeo.cms.CmsConstants;
import org.argeo.cms.CmsException;
import org.argeo.cms.CmsView;
+import org.argeo.eclipse.ui.specific.UiContext;
import org.argeo.jcr.JcrUtils;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.service.ResourceManager;
* this call.
*/
public static CmsView getCmsView() {
- Display display = Display.getCurrent();
- if (display == null)
- return null;
- CmsView cmsView = (CmsView) display.getData(CmsView.KEY);
- if (cmsView == null)
- return null;
- return cmsView;
+ return UiContext.getData(CmsView.KEY);
}
/** @deprecated Use rowData16px() instead. GridData should not be reused. */
+++ /dev/null
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * 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 org.argeo.cms.util;
-
-import java.security.AccessController;
-import java.security.Principal;
-import java.security.acl.Group;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.security.auth.Subject;
-import javax.security.auth.x500.X500Principal;
-
-import org.argeo.ArgeoException;
-
-/**
- * Retrieves information about the current user. Not an API, can change without
- * notice.
- */
-class CurrentUserUtils {
- public final static String getUsername() {
- Subject subject = getSubject();
- if (subject == null)
- return null;
- Principal principal = subject.getPrincipals(X500Principal.class)
- .iterator().next();
- return principal.getName();
-
- }
-
- public final static Set<String> roles() {
- Set<String> roles = Collections.synchronizedSet(new HashSet<String>());
- // roles.add("ROLE_USER");
- Subject subject = getSubject();
- X500Principal userPrincipal = subject
- .getPrincipals(X500Principal.class).iterator().next();
- roles.add(userPrincipal.getName());
- for (Principal group : subject.getPrincipals(Group.class)) {
- roles.add(group.getName());
- }
- return roles;
- }
-
- public final static Subject getSubject() {
- Subject subject = Subject.getSubject(AccessController.getContext());
- if (subject == null) {
- subject = CmsUtils.getCmsView().getSubject();
- if (subject == null)
- throw new ArgeoException("Not authenticated.");
- }
- return subject;
- }
-}
package org.argeo.cms.util;
-import static org.argeo.cms.auth.AuthConstants.ACCESS_CONTROL_CONTEXT;
import static org.argeo.cms.auth.AuthConstants.LOGIN_CONTEXT_ANONYMOUS;
import static org.argeo.cms.auth.AuthConstants.LOGIN_CONTEXT_USER;
import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
import org.argeo.cms.CmsException;
import org.argeo.cms.CmsMsg;
import org.argeo.cms.CmsView;
import org.argeo.cms.auth.AuthConstants;
import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.auth.HttpRequestCallback;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
cmsView = CmsUtils.getCmsView();
if (cmsView != null) {
- String username = CurrentUser.getUsername(CmsUtils.getCmsView()
- .getSubject());
+ String username = CurrentUser.getUsername(cmsView.getSubject());
if (username == null
|| username.equalsIgnoreCase(AuthConstants.ROLE_ANONYMOUS)) {
username = null;
protected void login() {
Subject subject = cmsView.getSubject();
+ LoginContext loginContext;
try {
//
// LOGIN
//
new LoginContext(LOGIN_CONTEXT_ANONYMOUS, subject).logout();
- LoginContext loginContext = new LoginContext(LOGIN_CONTEXT_USER,
- subject, this);
+ loginContext = new LoginContext(LOGIN_CONTEXT_USER, subject, this);
loginContext.login();
-
- // save context in session
- final HttpSession httpSession = RWT.getRequest().getSession();
- Subject.doAs(subject, new PrivilegedAction<Void>() {
-
- @Override
- public Void run() {
- httpSession.setAttribute(ACCESS_CONTROL_CONTEXT,
- AccessController.getContext());
- return null;
- }
- });
} catch (LoginException e1) {
- try {
- new LoginContext(LOGIN_CONTEXT_ANONYMOUS, subject).login();
- } catch (LoginException e) {
- throw new CmsException("Cannot authenticate anonymous", e1);
- }
throw new CmsException("Cannot authenticate", e1);
}
closeShell();
- cmsView.authChange();
+ cmsView.authChange(loginContext);
}
protected void logout() {
- Subject subject = cmsView.getSubject();
- try {
- //
- // LOGOUT
- //
- new LoginContext(LOGIN_CONTEXT_USER, subject).logout();
- new LoginContext(LOGIN_CONTEXT_ANONYMOUS, subject).login();
-
- HttpServletRequest httpRequest = RWT.getRequest();
- HttpSession httpSession = httpRequest.getSession();
- httpSession.setAttribute(ACCESS_CONTROL_CONTEXT, null);
- } catch (LoginException e1) {
- throw new CmsException("Cannot authenticate anonymous", e1);
- }
closeShell();
+ cmsView.logout();
cmsView.navigateTo("~");
- cmsView.authChange();
}
@Override
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
- ((NameCallback) callbacks[0]).setName(username.getText());
- ((PasswordCallback) callbacks[1]).setPassword(password.getTextChars());
+ for (Callback callback : callbacks) {
+ if (callback instanceof NameCallback)
+ ((NameCallback) callback).setName(username.getText());
+ else if (callback instanceof PasswordCallback)
+ ((PasswordCallback) callback).setPassword(password
+ .getTextChars());
+ else if (callback instanceof HttpRequestCallback)
+ ((HttpRequestCallback) callback).setRequest(RWT.getRequest());
+ }
}
public Shell getShell() {
return shell;
}
-
}
package org.argeo.cms.util;
import javax.jcr.Node;
+import javax.security.auth.Subject;
import org.argeo.cms.CmsMsg;
import org.argeo.cms.CmsStyles;
@Override
public Control createUi(Composite parent, Node context) {
- String username = CurrentUser.getUsername(CmsUtils.getCmsView()
- .getSubject());
+ Subject subject = CmsUtils.getCmsView().getSubject();
+ String username = CurrentUser.getUsername(subject);
if (username.equalsIgnoreCase(AuthConstants.ROLE_ANONYMOUS))
setLabel(CmsMsg.login.lead());
else {
- setLabel(CurrentUser.getDisplayName(CmsUtils.getCmsView()
- .getSubject()));
+ setLabel(CurrentUser.getDisplayName(subject));
}
Label link = (Label) ((Composite) super.createUi(parent, context))
.getChildren()[0];
--- /dev/null
+package org.argeo.eclipse.ui.specific;
+
+/** Exception related to SWT/RWT single sourcing. */
+public class SingleSourcingException extends RuntimeException {
+ private static final long serialVersionUID = -727700418055348468L;
+
+ public SingleSourcingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public SingleSourcingException(String message) {
+ super(message);
+ }
+
+}
--- /dev/null
+package org.argeo.eclipse.ui.specific;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.rap.rwt.RWT;
+import org.eclipse.swt.widgets.Display;
+
+/** Singleton class providing single sources infos about the UI context. */
+public class UiContext {
+
+ public static HttpServletRequest getHttpRequest() {
+ return RWT.getRequest();
+ }
+
+ /** Can always be null */
+ @SuppressWarnings("unchecked")
+ public static <T> T getData(String key) {
+ Display display = getDisplay();
+ if (display == null)
+ return null;
+ return (T) display.getData(key);
+ }
+
+ public static void setData(String key, Object value) {
+ Display display = getDisplay();
+ if (display == null)
+ throw new SingleSourcingException(
+ "Not display available in RAP context");
+ display.setData(key, value);
+ }
+
+ private static Display getDisplay() {
+ return Display.getCurrent();
+ }
+
+ private UiContext() {
+ }
+
+}
package org.argeo.security.ui.rap;
+import javax.servlet.http.HttpServletRequest;
+
import org.argeo.security.ui.login.WorkbenchLogin;
+import org.eclipse.rap.rwt.RWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
return new RapWorkbenchAdvisor(username);
}
+ protected HttpServletRequest getRequest() {
+ return RWT.getRequest();
+ }
}
import java.security.PrivilegedAction;
import javax.security.auth.Subject;
+import javax.security.auth.login.CredentialNotFoundException;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.servlet.http.HttpServletRequest;
+import org.argeo.ArgeoException;
+import org.argeo.cms.CmsException;
import org.argeo.cms.CmsImageManager;
import org.argeo.cms.CmsView;
+import org.argeo.cms.auth.AuthConstants;
import org.argeo.cms.auth.CurrentUser;
+import org.argeo.cms.auth.HttpRequestCallbackHandler;
import org.argeo.cms.util.UserMenu;
+import org.argeo.eclipse.ui.specific.UiContext;
import org.eclipse.rap.rwt.application.EntryPoint;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
public abstract class WorkbenchLogin implements EntryPoint, CmsView {
+ // private final static Log log = LogFactory.getLog(WorkbenchLogin.class);
private final Subject subject = new Subject();
+ private LoginContext loginContext;
@Override
public int createUI() {
final Display display = PlatformUI.createDisplay();
- display.setData(CmsView.KEY, this);
- Shell shell = new Shell(display, SWT.NO_TRIM);
- shell.setMaximized(true);
- UserMenu userMenu = new UserMenu(shell, false);
- shell.open();
- while (!userMenu.getShell().isDisposed()) {
- if (!display.readAndDispatch()) {
- display.sleep();
+ UiContext.setData(CmsView.KEY, this);
+ try {
+ loginContext = new LoginContext(AuthConstants.LOGIN_CONTEXT_USER,
+ subject, new HttpRequestCallbackHandler(getRequest()));
+ loginContext.login();
+ } catch (CredentialNotFoundException e) {
+ Shell shell = new Shell(display, SWT.NO_TRIM);
+ shell.setMaximized(true);
+ //shell.setBackground(display.getSystemColor(SWT.COLOR_CYAN));
+ UserMenu userMenu = new UserMenu(shell, false);
+ shell.open();
+ while (!userMenu.getShell().isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
}
+ } catch (LoginException e) {
+ throw new ArgeoException("Cannot log in", e);
}
//
// RUN THE WORKBENCH
} finally {
display.dispose();
}
+ // explicit workbench closing
+ logout();
return returnCode;
- // display.dispose();
- // return 0;
}
protected abstract int createAndRunWorkbench(Display display,
String username);
+ // private void fullLogout() {
+ // String username = CurrentUser.getUsername(subject);
+ // try {
+ // LoginContext loginContext = new LoginContext(
+ // AuthConstants.LOGIN_CONTEXT_USER, subject);
+ // loginContext.logout();
+ // HttpServletRequest httpRequest = getRequest();
+ // httpRequest.setAttribute(HttpContext.AUTHORIZATION, null);
+ // HttpSession httpSession = httpRequest.getSession();
+ // httpSession.setAttribute(HttpContext.AUTHORIZATION, null);
+ // httpSession.setMaxInactiveInterval(1);
+ // log.info("Logged out " + (username != null ? username : "")
+ // + " (THREAD=" + Thread.currentThread().getId() + ")");
+ // } catch (LoginException e) {
+ // log.error("Error when logging out", e);
+ // }
+ // }
+
+ protected HttpServletRequest getRequest() {
+ return UiContext.getHttpRequest();
+ }
+
@Override
public void navigateTo(String state) {
// TODO Auto-generated method stub
}
@Override
- public void authChange() {
+ public void authChange(LoginContext loginContext) {
+ this.loginContext = loginContext;
+ }
+
+ @Override
+ public void logout() {
+ if (loginContext == null)
+ throw new CmsException("Login context should not bet null");
+ try {
+ loginContext.logout();
+ } catch (LoginException e) {
+ throw new CmsException("Cannot log out", e);
+ }
}
@Override