Continue finalising security. Fix issues with login in web.
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 21 Oct 2016 14:25:36 +0000 (14:25 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 21 Oct 2016 14:25:36 +0000 (14:25 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@9273 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

29 files changed:
org.argeo.cms.ui.workbench.rap/src/org/argeo/security/ui/rap/RapWorkbenchLogin.java
org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java
org.argeo.cms.ui/src/org/argeo/cms/ui/CmsView.java
org.argeo.cms.ui/src/org/argeo/cms/util/CmsUtils.java
org.argeo.cms.ui/src/org/argeo/cms/util/LoginEntryPoint.java
org.argeo.cms.ui/src/org/argeo/cms/util/OpenUserMenu.java
org.argeo.cms.ui/src/org/argeo/cms/util/UserMenu.java
org.argeo.cms.ui/src/org/argeo/cms/util/UserMenuLink.java
org.argeo.cms.ui/src/org/argeo/cms/util/useradmin/UserAdminUtils.java
org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLogin.java
org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLoginShell.java
org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java
org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java
org.argeo.cms/src/org/argeo/cms/auth/DataAdminLoginModule.java
org.argeo.cms/src/org/argeo/cms/auth/HttpLoginModule.java [deleted file]
org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg
org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java
org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java
org.argeo.jcr/src/org/argeo/jcr/SimplePrincipal.java
org.argeo.node.api/src/org/argeo/node/DataAdminPrincipal.java [deleted file]
org.argeo.node.api/src/org/argeo/node/NodeAuthenticated.java [deleted file]
org.argeo.node.api/src/org/argeo/node/NodeConstants.java
org.argeo.node.api/src/org/argeo/node/security/AnonymousPrincipal.java [new file with mode: 0644]
org.argeo.node.api/src/org/argeo/node/security/DataAdminPrincipal.java [new file with mode: 0644]
org.argeo.node.api/src/org/argeo/node/security/NodeAuthenticated.java [new file with mode: 0644]
org.argeo.node.api/src/org/argeo/node/security/NodeSecurityUtils.java [new file with mode: 0644]
org.argeo.node.api/src/org/argeo/node/security/UserPrincipal.java [new file with mode: 0644]

index 7bf487a887d02369c14ba4bb935056cdbd1efb20..06fc62e2e41d9cd33c7700294bf9739fb57f1c9e 100644 (file)
@@ -30,13 +30,13 @@ public class RapWorkbenchLogin extends LoginEntryPoint {
 
        @Override
        public int createUI() {
-               JavaScriptExecutor jsExecutor = RWT.getClient().getService(
-                               JavaScriptExecutor.class);
+               JavaScriptExecutor jsExecutor = RWT.getClient().getService(JavaScriptExecutor.class);
                int returnCode;
                try {
                        returnCode = super.createUI();
                } finally {
                        // always reload
+                       // TODO optimise?
                        jsExecutor.execute("location.reload()");
                }
                return returnCode;
@@ -44,25 +44,22 @@ public class RapWorkbenchLogin extends LoginEntryPoint {
 
        @Override
        protected int postLogin() {
+               Subject subject = getLoginContext().getSubject();
                final Display display = Display.getCurrent();
-               Subject subject = getSubject();
                if (subject.getPrincipals(X500Principal.class).isEmpty()) {
-                       RWT.getClient().getService(JavaScriptExecutor.class)
-                                       .execute("location.reload()");
+                       RWT.getClient().getService(JavaScriptExecutor.class).execute("location.reload()");
                }
                //
                // RUN THE WORKBENCH
                //
                Integer returnCode = null;
                try {
-                       returnCode = Subject.doAs(getSubject(),
-                                       new PrivilegedAction<Integer>() {
-                                               public Integer run() {
-                                                       int result = createAndRunWorkbench(display,
-                                                                       CurrentUser.getUsername(getSubject()));
-                                                       return new Integer(result);
-                                               }
-                                       });
+                       returnCode = Subject.doAs(subject, new PrivilegedAction<Integer>() {
+                               public Integer run() {
+                                       int result = createAndRunWorkbench(display, CurrentUser.getUsername(subject));
+                                       return new Integer(result);
+                               }
+                       });
                        // explicit workbench closing
                        logout();
                } finally {
@@ -77,8 +74,8 @@ public class RapWorkbenchLogin extends LoginEntryPoint {
        }
 
        @Override
-       protected void extendsCredentialsBlock(Composite credentialsBlock,
-                       Locale selectedLocale, SelectionListener loginSelectionListener) {
+       protected void extendsCredentialsBlock(Composite credentialsBlock, Locale selectedLocale,
+                       SelectionListener loginSelectionListener) {
                Button loginButton = new Button(credentialsBlock, SWT.PUSH);
                loginButton.setText(CmsMsg.login.lead(selectedLocale));
                loginButton.setLayoutData(CmsUtils.fillWidth());
index 5072c628dce5b6aa32bfe625a245495a728c7147..030b4104cda738f7607d7e1c4e33a2080226dea6 100644 (file)
@@ -23,8 +23,8 @@ import org.argeo.cms.CmsException;
 import org.argeo.cms.auth.HttpRequestCallbackHandler;
 import org.argeo.eclipse.ui.specific.UiContext;
 import org.argeo.jcr.JcrUtils;
-import org.argeo.node.NodeAuthenticated;
 import org.argeo.node.NodeConstants;
+import org.argeo.node.security.NodeAuthenticated;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.AbstractEntryPoint;
 import org.eclipse.rap.rwt.client.WebClient;
@@ -42,7 +42,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
 
        private final Log log = LogFactory.getLog(AbstractCmsEntryPoint.class);
 
-       private final Subject subject;
+       // private final Subject subject;
        private LoginContext loginContext;
 
        private final Repository repository;
@@ -68,16 +68,16 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
                this.workspace = workspace;
                this.defaultPath = defaultPath;
                this.factoryProperties = new HashMap<String, String>(factoryProperties);
-               subject = new Subject();
+               // subject = new Subject();
 
                // Initial login
                try {
-                       loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject,
+                       loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
                                        new HttpRequestCallbackHandler(UiContext.getHttpRequest()));
                        loginContext.login();
                } catch (CredentialNotFoundException e) {
                        try {
-                               loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS, subject);
+                               loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS);
                                loginContext.login();
                        } catch (LoginException e1) {
                                throw new CmsException("Cannot log as anonymous", e);
@@ -112,7 +112,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
        @Override
        protected final void createContents(final Composite parent) {
                UiContext.setData(NodeAuthenticated.KEY, this);
-               Subject.doAs(subject, new PrivilegedAction<Void>() {
+               Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Void>() {
                        @Override
                        public Void run() {
                                try {
@@ -137,7 +137,8 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
         */
        protected Node getDefaultNode(Session session) throws RepositoryException {
                if (!session.hasPermission(defaultPath, "read")) {
-                       if (session.getUserID().equals(NodeConstants.ROLE_ANONYMOUS))
+                       String userId = session.getUserID();
+                       if (userId.equals(NodeConstants.ROLE_ANONYMOUS))
                                // TODO throw a special exception
                                throw new CmsException("Login required");
                        else
@@ -158,9 +159,14 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
                        browserNavigation.pushState(state, title);
        }
 
+       // @Override
+       // public synchronized Subject getSubject() {
+       // return subject;
+       // }
+
        @Override
-       public synchronized Subject getSubject() {
-               return subject;
+       public LoginContext getLoginContext() {
+               return loginContext;
        }
 
        @Override
@@ -169,7 +175,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
                        throw new CmsException("Login context should not be null");
                try {
                        loginContext.logout();
-                       LoginContext anonymousLc = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS, subject);
+                       LoginContext anonymousLc = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS);
                        anonymousLc.login();
                        authChange(anonymousLc);
                } catch (LoginException e) {
@@ -216,7 +222,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement
        }
 
        protected synchronized void doRefresh() {
-               Subject.doAs(subject, new PrivilegedAction<Void>() {
+               Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Void>() {
                        @Override
                        public Void run() {
                                refresh();
index 8ef468a702f928c0155d20a7aa6e69f9c8207335..d39d6df162f200a75150a2254b8e79845a951cb4 100644 (file)
@@ -2,7 +2,7 @@ package org.argeo.cms.ui;
 
 import javax.security.auth.login.LoginContext;
 
-import org.argeo.node.NodeAuthenticated;
+import org.argeo.node.security.NodeAuthenticated;
 
 /** Provides interaction with the CMS system. UNSTABLE API at this stage. */
 public interface CmsView extends NodeAuthenticated {
@@ -15,6 +15,8 @@ public interface CmsView extends NodeAuthenticated {
        void authChange(LoginContext loginContext);
 
        void logout();
+       
+//     void registerCallbackHandler(CallbackHandler callbackHandler);
 
        // SERVICES
        void exception(Throwable e);
index 27f83807f43d16e73d793aad109f2c4cc063c379..7864dde8b645999e094529dce4facb70bfdf441e 100644 (file)
@@ -14,9 +14,9 @@ import org.argeo.cms.ui.CmsConstants;
 import org.argeo.cms.ui.CmsView;
 import org.argeo.eclipse.ui.specific.UiContext;
 import org.argeo.jcr.JcrUtils;
-import org.argeo.node.NodeAuthenticated;
 import org.argeo.node.NodeConstants;
 import org.argeo.node.NodeUtils;
+import org.argeo.node.security.NodeAuthenticated;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.service.ResourceManager;
 import org.eclipse.swt.SWT;
index 3c3746b72b42ac5a6324bd2df8c6f9a863c0f2af..1f46f100e0c98cbce2a5e45496c7017b10eba5f0 100644 (file)
@@ -2,7 +2,6 @@ package org.argeo.cms.util;
 
 import java.util.Locale;
 
-import javax.security.auth.Subject;
 import javax.security.auth.login.CredentialNotFoundException;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
@@ -10,15 +9,14 @@ import javax.servlet.http.HttpServletRequest;
 
 import org.argeo.cms.CmsException;
 import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.auth.HttpRequestCallbackHandler;
 import org.argeo.cms.ui.CmsImageManager;
 import org.argeo.cms.ui.CmsView;
 import org.argeo.cms.ui.UxContext;
 import org.argeo.cms.widgets.auth.CmsLogin;
 import org.argeo.cms.widgets.auth.CmsLoginShell;
 import org.argeo.eclipse.ui.specific.UiContext;
-import org.argeo.node.NodeAuthenticated;
 import org.argeo.node.NodeConstants;
+import org.argeo.node.security.NodeAuthenticated;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.EntryPoint;
 import org.eclipse.swt.events.SelectionListener;
@@ -27,7 +25,7 @@ import org.eclipse.swt.widgets.Display;
 
 public class LoginEntryPoint implements EntryPoint, CmsView {
        // private final static Log log = LogFactory.getLog(WorkbenchLogin.class);
-       private final Subject subject = new Subject();
+       // private final Subject subject = new Subject();
        private LoginContext loginContext;
        private UxContext uxContext = null;
 
@@ -35,13 +33,13 @@ public class LoginEntryPoint implements EntryPoint, CmsView {
        public int createUI() {
                final Display display = createDisplay();
                UiContext.setData(NodeAuthenticated.KEY, this);
+               CmsLoginShell loginShell = createCmsLoginShell();
                try {
                        // try pre-auth
-                       loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
-                                       subject, new HttpRequestCallbackHandler(getRequest()));
+                       loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, loginShell);
                        loginContext.login();
                } catch (CredentialNotFoundException e) {
-                       CmsLoginShell loginShell = createCmsLoginShell();
+                       loginShell.createUi();
                        loginShell.open();
                        while (!loginShell.getShell().isDisposed()) {
                                // try {
@@ -78,6 +76,8 @@ public class LoginEntryPoint implements EntryPoint, CmsView {
        protected HttpServletRequest getRequest() {
                return RWT.getRequest();
        }
+       
+       
 
        protected CmsLoginShell createCmsLoginShell() {
                return new CmsLoginShell(this) {
@@ -88,11 +88,9 @@ public class LoginEntryPoint implements EntryPoint, CmsView {
                        }
 
                        @Override
-                       protected void extendsCredentialsBlock(Composite credentialsBlock,
-                                       Locale selectedLocale,
+                       protected void extendsCredentialsBlock(Composite credentialsBlock, Locale selectedLocale,
                                        SelectionListener loginSelectionListener) {
-                               LoginEntryPoint.this.extendsCredentialsBlock(credentialsBlock,
-                                               selectedLocale, loginSelectionListener);
+                               LoginEntryPoint.this.extendsCredentialsBlock(credentialsBlock, selectedLocale, loginSelectionListener);
                        }
 
                };
@@ -108,8 +106,8 @@ public class LoginEntryPoint implements EntryPoint, CmsView {
                login.defaultCreateContents(parent);
        }
 
-       protected void extendsCredentialsBlock(Composite credentialsBlock,
-                       Locale selectedLocale, SelectionListener loginSelectionListener) {
+       protected void extendsCredentialsBlock(Composite credentialsBlock, Locale selectedLocale,
+                       SelectionListener loginSelectionListener) {
 
        }
 
@@ -134,11 +132,19 @@ public class LoginEntryPoint implements EntryPoint, CmsView {
                        throw new CmsException("Cannot log out", e);
                }
        }
+       
+       
 
-       @Override
-       public final Subject getSubject() {
-               return subject;
-       }
+       // @Override
+       // public final Subject getSubject() {
+       // return subject;
+       // }
+
+//     @Override
+//     public void registerCallbackHandler(CallbackHandler callbackHandler) {
+//             throw new UnsupportedOperationException();
+//             
+//     }
 
        @Override
        public void exception(Throwable e) {
@@ -146,6 +152,11 @@ public class LoginEntryPoint implements EntryPoint, CmsView {
 
        }
 
+       @Override
+       public LoginContext getLoginContext() {
+               return loginContext;
+       }
+
        @Override
        public CmsImageManager getImageManager() {
                // TODO Auto-generated method stub
index bb2bb3990f6937f946514505058d0edf686e53e2..78531463aa4f7be567e0b9d984a55dd788987157 100644 (file)
@@ -5,6 +5,7 @@ import org.eclipse.swt.events.MouseEvent;
 import org.eclipse.swt.widgets.Control;
 
 /** Open the user menu when clicked */
+@Deprecated
 public class OpenUserMenu extends MouseAdapter {
        private static final long serialVersionUID = 3634864186295639792L;
 
index a654dddd4054f7aa27b318352afe65d892a0ec29..58dea808695b2a9497e339d0bdd36625d8a352fa 100644 (file)
@@ -15,6 +15,7 @@ public class UserMenu extends CmsLoginShell {
 
        public UserMenu(Control source) {
                super(CmsUtils.getCmsView());
+               createUi();
                if (source == null)
                        throw new CmsException("Source control cannot be null.");
                this.source = source;
index 08af8d3da419df52971e20c1cc5862381da4e012..f8dd86a0f2c56da7bbb02c13ac3e86743a89e8db 100644 (file)
@@ -1,7 +1,6 @@
 package org.argeo.cms.util;
 
 import javax.jcr.Node;
-import javax.security.auth.Subject;
 
 import org.argeo.cms.CmsMsg;
 import org.argeo.cms.auth.CurrentUser;
@@ -24,12 +23,10 @@ public class UserMenuLink extends MenuLink {
 
        @Override
        public Control createUi(Composite parent, Node context) {
-               Subject subject = CmsUtils.getCmsView().getSubject();
-               String username = CurrentUser.getUsername(subject);
-               if (username.equalsIgnoreCase(NodeConstants.ROLE_ANONYMOUS))
+               if (CurrentUser.isAnonymous())
                        setLabel(CmsMsg.login.lead());
                else {
-                       setLabel(CurrentUser.getDisplayName(subject));
+                       setLabel(CurrentUser.getDisplayName());
                }
                Label link = (Label) ((Composite) super.createUi(parent, context))
                                .getChildren()[0];
index 6684b261fb0d6dc6647eaabece5d82ee53b7104b..fdd61d69dd461f7a6af2100305a145d12fb8d005 100644 (file)
@@ -1,19 +1,14 @@
 package org.argeo.cms.util.useradmin;
 
-import java.security.AccessController;
 import java.util.List;
 import java.util.Set;
 
 import javax.naming.InvalidNameException;
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.Rdn;
-import javax.security.auth.Subject;
-import javax.security.auth.x500.X500Principal;
 
 import org.argeo.cms.CmsException;
 import org.argeo.cms.auth.CurrentUser;
-import org.argeo.cms.ui.CmsView;
-import org.argeo.cms.util.CmsUtils;
 import org.argeo.eclipse.ui.EclipseUiUtils;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.naming.LdapAttrs;
@@ -73,13 +68,13 @@ public class UserAdminUtils {
 
        /** Simply retrieves the current logged-in user display name. */
        public static String getCurrentUserDisplayName(UserAdmin userAdmin) {
-               String username = getCurrentUsername();
+               String username = CurrentUser.getUsername();
                return getUserDisplayName(userAdmin, username);
        }
 
        /** Simply retrieves the current logged-in user display name. */
        public static String getCurrentUserMail(UserAdmin userAdmin) {
-               String username = getCurrentUsername();
+               String username = CurrentUser.getUsername();
                return getUserMail(userAdmin, username);
        }
 
@@ -106,37 +101,38 @@ public class UserAdminUtils {
                        else
                                return false;
                } catch (InvalidNameException e) {
-                       throw new CmsException("User " + user + " has an unvalid dn: "
-                                       + userName, e);
+                       throw new CmsException("User " + user + " has an unvalid dn: " + userName, e);
                }
        }
 
        public final static LdapName getCurrentUserLdapName() {
-               String name = getCurrentUsername();
+               String name = CurrentUser.getUsername();
                return getLdapName(name);
        }
 
-       /** Simply retrieves username for current user, generally a LDAP dn */
-       public static String getCurrentUsername() {
-               Subject subject = currentSubject();
-               String name = subject.getPrincipals(X500Principal.class).iterator()
-                               .next().toString();
-               return name;
-       }
-
        /**
-        * Fork of the {@link CurrentUser#currentSubject} method that is private.
-        * TODO Enhance and factorize
+        * Simply retrieves username for current user, generally a LDAP dn
+        * 
+        * @deprecated Use {@link CurrentUser#getUsername()}
         */
-       private static Subject currentSubject() {
-               CmsView cmsView = CmsUtils.getCmsView();
-               if (cmsView != null)
-                       return cmsView.getSubject();
-               Subject subject = Subject.getSubject(AccessController.getContext());
-               if (subject != null)
-                       return subject;
-               throw new RuntimeException("Cannot find related subject");
-       }
+       @Deprecated
+       public static String getCurrentUsername() {
+               return CurrentUser.getUsername();
+       }
+
+       // /**
+       // * Fork of the {@link CurrentUser#currentSubject} method that is private.
+       // * TODO Enhance and factorize
+       // */
+       // private static Subject currentSubject() {
+       // CmsView cmsView = CmsUtils.getCmsView();
+       // if (cmsView != null)
+       // return cmsView.getSubject();
+       // Subject subject = Subject.getSubject(AccessController.getContext());
+       // if (subject != null)
+       // return subject;
+       // throw new RuntimeException("Cannot find related subject");
+       // }
 
        // HOME MANAGEMENT
        /**
@@ -144,7 +140,7 @@ public class UserAdminUtils {
         * the base home node
         */
        public static String getCurrentUserHomeRelPath() {
-               return getHomeRelPath(getCurrentUsername());
+               return getHomeRelPath(CurrentUser.getUsername());
        }
 
        /**
@@ -166,8 +162,7 @@ public class UserAdminUtils {
                                || last.getType().toLowerCase().equals(LdapAttrs.cn.name()))
                        return (String) last.getValue();
                else
-                       throw new CmsException("Cannot retrieve user uid, "
-                                       + "non valid dn: " + dn);
+                       throw new CmsException("Cannot retrieve user uid, " + "non valid dn: " + dn);
        }
 
        /**
index 792471996a81965ebdfb4bca364a202ce2af4414..1809998070bc5e2a724a90b34b4e02a58cfd93fb 100644 (file)
@@ -7,7 +7,6 @@ import java.io.IOException;
 import java.util.List;
 import java.util.Locale;
 
-import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.LanguageCallback;
@@ -28,8 +27,8 @@ import org.argeo.cms.ui.CmsStyles;
 import org.argeo.cms.ui.CmsView;
 import org.argeo.cms.ui.internal.Activator;
 import org.argeo.cms.util.CmsUtils;
+import org.argeo.eclipse.ui.specific.UiContext;
 import org.argeo.node.NodeConstants;
-import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.MouseAdapter;
 import org.eclipse.swt.events.MouseEvent;
@@ -81,7 +80,7 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
        }
 
        protected boolean isAnonymous() {
-               return CurrentUser.isAnonymous(cmsView.getSubject());
+               return CurrentUser.isAnonymous(cmsView.getLoginContext().getSubject());
        }
 
        public final void createUi(Composite parent) {
@@ -122,7 +121,7 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
                specificUserUi(credentialsBlock);
 
                Label l = new Label(credentialsBlock, SWT.NONE);
-               l.setData(RWT.CUSTOM_VARIANT, CMS_USER_MENU_ITEM);
+               CmsUtils.style(l, CMS_USER_MENU_ITEM);
                l.setText(CmsMsg.logout.lead(locale));
                GridData lData = CmsUtils.fillWidth();
                lData.widthHint = 120;
@@ -151,12 +150,12 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
                credentialsBlock.setLayoutData(CmsUtils.fillAll());
 
                Integer textWidth = 120;
-               parent.setData(RWT.CUSTOM_VARIANT, CMS_USER_MENU);
+               CmsUtils.style(parent, CMS_USER_MENU);
 
                // new Label(this, SWT.NONE).setText(CmsMsg.username.lead());
                usernameT = new Text(credentialsBlock, SWT.BORDER);
                usernameT.setMessage(username.lead(locale));
-               usernameT.setData(RWT.CUSTOM_VARIANT, CMS_LOGIN_DIALOG_USERNAME);
+               CmsUtils.style(usernameT, CMS_LOGIN_DIALOG_USERNAME);
                GridData gd = CmsUtils.fillWidth();
                gd.widthHint = textWidth;
                usernameT.setLayoutData(gd);
@@ -164,7 +163,7 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
                // new Label(this, SWT.NONE).setText(CmsMsg.password.lead());
                passwordT = new Text(credentialsBlock, SWT.BORDER | SWT.PASSWORD);
                passwordT.setMessage(password.lead(locale));
-               passwordT.setData(RWT.CUSTOM_VARIANT, CMS_LOGIN_DIALOG_PASSWORD);
+               CmsUtils.style(passwordT, CMS_LOGIN_DIALOG_PASSWORD);
                gd = CmsUtils.fillWidth();
                gd.widthHint = textWidth;
                passwordT.setLayoutData(gd);
@@ -247,14 +246,14 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
        }
 
        protected boolean login() {
-               Subject subject = cmsView.getSubject();
-               LoginContext loginContext;
+               // Subject subject = cmsView.getLoginContext().getSubject();
+               LoginContext loginContext = cmsView.getLoginContext();
                try {
                        //
                        // LOGIN
                        //
-                       new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS, subject).logout();
-                       loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject, this);
+                       loginContext.logout();
+                       loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, this);
                        loginContext.login();
                } catch (FailedLoginException e) {
                        log.warn(e.getMessage());
@@ -281,12 +280,12 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
        @Override
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
                for (Callback callback : callbacks) {
-                       if (callback instanceof NameCallback)
+                       if (callback instanceof NameCallback && usernameT != null)
                                ((NameCallback) callback).setName(usernameT.getText());
-                       else if (callback instanceof PasswordCallback)
+                       else if (callback instanceof PasswordCallback && passwordT != null)
                                ((PasswordCallback) callback).setPassword(passwordT.getTextChars());
                        else if (callback instanceof HttpRequestCallback)
-                               ((HttpRequestCallback) callback).setRequest(RWT.getRequest());
+                               ((HttpRequestCallback) callback).setRequest(UiContext.getHttpRequest());
                        else if (callback instanceof LanguageCallback && localeChoice != null)
                                ((LanguageCallback) callback).setLocale(localeChoice.getSelectedLocale());
                }
index c31ad96579d08853f1c95e6fd6cd6569c56ae5ef..dea632de8b2f29ab2bc6e79152c22c90d9aa3ff9 100644 (file)
@@ -1,7 +1,7 @@
 package org.argeo.cms.widgets.auth;
 
 import org.argeo.cms.ui.CmsView;
-import org.eclipse.rap.rwt.RWT;
+import org.argeo.cms.util.CmsUtils;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Display;
@@ -14,8 +14,8 @@ public class CmsLoginShell extends CmsLogin {
        public CmsLoginShell(CmsView cmsView) {
                super(cmsView);
                shell = createShell();
-               shell.setData(RWT.CUSTOM_VARIANT, CMS_USER_MENU);
-               createUi(shell);
+               CmsUtils.style(shell, CMS_USER_MENU);
+//             createUi(shell);
        }
 
        /** To be overridden. */
@@ -65,4 +65,8 @@ public class CmsLoginShell extends CmsLogin {
        public Shell getShell() {
                return shell;
        }
+       
+       public void createUi(){
+               createUi(shell);
+       }
 }
index 2e585237df754f36a479e5e48e76e11c9272c0e6..86800e282627441a3d6dbda5cf1d49320ba69b2e 100644 (file)
@@ -1,9 +1,6 @@
 package org.argeo.cms.auth;
 
 import java.security.Principal;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
 import java.util.Set;
 
 import javax.naming.InvalidNameException;
@@ -11,37 +8,21 @@ import javax.naming.ldap.LdapName;
 import javax.security.auth.Subject;
 import javax.security.auth.x500.X500Principal;
 
-import org.apache.jackrabbit.core.security.AnonymousPrincipal;
-import org.apache.jackrabbit.core.security.SecurityConstants;
-import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
+//import org.apache.jackrabbit.core.security.AnonymousPrincipal;
+//import org.apache.jackrabbit.core.security.SecurityConstants;
+//import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
 import org.argeo.cms.CmsException;
 import org.argeo.cms.internal.auth.ImpliedByPrincipal;
-import org.argeo.node.NodeConstants;
+import org.argeo.node.security.AnonymousPrincipal;
+import org.argeo.node.security.NodeSecurityUtils;
 import org.osgi.service.useradmin.Authorization;
 
 class CmsAuthUtils {
-       final static LdapName ROLE_ADMIN_NAME, ROLE_ANONYMOUS_NAME, ROLE_USER_NAME;
-       final static List<LdapName> RESERVED_ROLES;
-       final static X500Principal ROLE_ANONYMOUS_PRINCIPAL;
-       static {
-               try {
-                       // ROLE_KERNEL_NAME = new LdapName(AuthConstants.ROLE_KERNEL);
-                       ROLE_ADMIN_NAME = new LdapName(NodeConstants.ROLE_ADMIN);
-                       ROLE_USER_NAME = new LdapName(NodeConstants.ROLE_USER);
-                       ROLE_ANONYMOUS_NAME = new LdapName(NodeConstants.ROLE_ANONYMOUS);
-                       RESERVED_ROLES = Collections.unmodifiableList(Arrays.asList(new LdapName[] { ROLE_ADMIN_NAME,
-                                       ROLE_ANONYMOUS_NAME, ROLE_USER_NAME, new LdapName(AuthConstants.ROLE_GROUP_ADMIN),
-                                       new LdapName(NodeConstants.ROLE_USER_ADMIN) }));
-                       ROLE_ANONYMOUS_PRINCIPAL = new X500Principal(ROLE_ANONYMOUS_NAME.toString());
-               } catch (InvalidNameException e) {
-                       throw new Error("Cannot initialize login module class", e);
-               }
-       }
 
        static void addAuthentication(Subject subject, Authorization authorization) {
                assert subject != null;
                assert authorization != null;
-               
+
                // required for display name:
                subject.getPrivateCredentials().add(authorization);
 
@@ -53,16 +34,16 @@ class CmsAuthUtils {
                        final LdapName name;
                        final Principal userPrincipal;
                        if (authName == null) {
-                               name = ROLE_ANONYMOUS_NAME;
-                               userPrincipal = ROLE_ANONYMOUS_PRINCIPAL;
+                               name = NodeSecurityUtils.ROLE_ANONYMOUS_NAME;
+                               userPrincipal = new AnonymousPrincipal();
                                principals.add(userPrincipal);
-                               principals.add(new AnonymousPrincipal());
+                               // principals.add(new AnonymousPrincipal());
                        } else {
                                name = new LdapName(authName);
-                               checkUserName(name);
+                               NodeSecurityUtils.checkUserName(name);
                                userPrincipal = new X500Principal(name.toString());
                                principals.add(userPrincipal);
-                               principals.add(new ImpliedByPrincipal(ROLE_USER_NAME, userPrincipal));
+                               principals.add(new ImpliedByPrincipal(NodeSecurityUtils.ROLE_USER_NAME, userPrincipal));
                        }
 
                        // Add roles provided by authorization
@@ -71,10 +52,11 @@ class CmsAuthUtils {
                                if (roleName.equals(name)) {
                                        // skip
                                } else {
-                                       checkImpliedPrincipalName(roleName);
+                                       NodeSecurityUtils.checkImpliedPrincipalName(roleName);
                                        principals.add(new ImpliedByPrincipal(roleName.toString(), userPrincipal));
-                                       if (roleName.equals(ROLE_ADMIN_NAME))
-                                               principals.add(new AdminPrincipal(SecurityConstants.ADMIN_ID));
+                                       // if (roleName.equals(ROLE_ADMIN_NAME))
+                                       // principals.add(new
+                                       // AdminPrincipal(SecurityConstants.ADMIN_ID));
                                }
                        }
 
@@ -83,23 +65,13 @@ class CmsAuthUtils {
                }
        }
 
-       static void checkUserName(LdapName name) {
-               if (RESERVED_ROLES.contains(name))
-                       throw new CmsException(name + " is a reserved name");
-       }
-
-       static void checkImpliedPrincipalName(LdapName roleName) {
-               if (ROLE_USER_NAME.equals(roleName) || ROLE_ANONYMOUS_NAME.equals(roleName))
-                       throw new CmsException(roleName + " cannot be listed as role");
-       }
-       
-       static void cleanUp(Subject subject){
+       static void cleanUp(Subject subject) {
                // 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(subject.getPrincipals(AnonymousPrincipal.class));
+               // subject.getPrincipals().removeAll(subject.getPrincipals(AdminPrincipal.class));
+               // subject.getPrincipals().removeAll(subject.getPrincipals(AnonymousPrincipal.class));
        }
 
        private CmsAuthUtils() {
index bc438a255a6bcd445846c09c38cad8818b370fee..68848f7df7bc7b658efbd1b14fcb17f215f5a4ba 100644 (file)
@@ -26,8 +26,8 @@ import javax.security.auth.x500.X500Principal;
 
 import org.argeo.cms.CmsException;
 import org.argeo.eclipse.ui.specific.UiContext;
-import org.argeo.node.NodeAuthenticated;
 import org.argeo.node.NodeConstants;
+import org.argeo.node.security.NodeAuthenticated;
 import org.osgi.service.useradmin.Authorization;
 
 /** Static utilities */
@@ -49,15 +49,16 @@ public final class CurrentUser {
        }
 
        public static boolean isAnonymous(Subject subject) {
+               if (subject == null)
+                       return true;
                String username = getUsername(subject);
-               return username == null
-                               || username.equalsIgnoreCase(NodeConstants.ROLE_ANONYMOUS);
+               return username == null || username.equalsIgnoreCase(NodeConstants.ROLE_ANONYMOUS);
        }
 
        private static Subject currentSubject() {
                NodeAuthenticated cmsView = getNodeAuthenticated();
                if (cmsView != null)
-                       return cmsView.getSubject();
+                       return cmsView.getLoginContext().getSubject();
                Subject subject = Subject.getSubject(AccessController.getContext());
                if (subject != null)
                        return subject;
@@ -73,10 +74,11 @@ public final class CurrentUser {
        }
 
        public final static String getUsername(Subject subject) {
+               if (subject == null)
+                       throw new CmsException("Subject cannot be null");
                if (subject.getPrincipals(X500Principal.class).size() != 1)
-                       return null;
-               Principal principal = subject.getPrincipals(X500Principal.class)
-                               .iterator().next();
+                       return NodeConstants.ROLE_ANONYMOUS;
+               Principal principal = subject.getPrincipals(X500Principal.class).iterator().next();
                return principal.getName();
        }
 
@@ -85,8 +87,7 @@ public final class CurrentUser {
        }
 
        private static Authorization getAuthorization(Subject subject) {
-               return subject.getPrivateCredentials(Authorization.class).iterator()
-                               .next();
+               return subject.getPrivateCredentials(Authorization.class).iterator().next();
        }
 
        public final static Set<String> roles() {
@@ -95,9 +96,7 @@ public final class CurrentUser {
 
        public final static Set<String> roles(Subject subject) {
                Set<String> roles = new HashSet<String>();
-               X500Principal userPrincipal = subject
-                               .getPrincipals(X500Principal.class).iterator().next();
-               roles.add(userPrincipal.getName());
+               roles.add(getUsername(subject));
                for (Principal group : subject.getPrincipals(Group.class)) {
                        roles.add(group.getName());
                }
index 5c7b64377cd80422c952f9b3e4d2662251d43e9a..215ed96b448325134f2e17b3d1a4998458eabbbf 100644 (file)
@@ -7,7 +7,7 @@ import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
 
-import org.argeo.node.DataAdminPrincipal;
+import org.argeo.node.security.DataAdminPrincipal;
 
 public class DataAdminLoginModule implements LoginModule {
        private Subject subject;
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpLoginModule.java
deleted file mode 100644 (file)
index 9a07e3c..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-package org.argeo.cms.auth;
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Map;
-
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginException;
-import javax.security.auth.spi.LoginModule;
-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.cms.CmsException;
-import org.argeo.cms.internal.kernel.WebCmsSessionImpl;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.HttpContext;
-import org.osgi.service.useradmin.Authorization;
-
-public class HttpLoginModule implements LoginModule, AuthConstants {
-       private final static Log log = LogFactory.getLog(HttpLoginModule.class);
-
-       private Subject subject = null;
-       private CallbackHandler callbackHandler = null;
-       private Map<String, Object> sharedState = null;
-
-       private HttpServletRequest request = null;
-
-       private BundleContext bc;
-
-       @SuppressWarnings("unchecked")
-       @Override
-       public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
-                       Map<String, ?> options) {
-               bc = FrameworkUtil.getBundle(HttpLoginModule.class).getBundleContext();
-               assert bc != null;
-               this.subject = subject;
-               this.callbackHandler = callbackHandler;
-               this.sharedState = (Map<String, Object>) sharedState;
-       }
-
-       @Override
-       public boolean login() throws LoginException {
-               HttpRequestCallback httpCallback = new HttpRequestCallback();
-               try {
-                       callbackHandler.handle(new Callback[] { httpCallback });
-               } catch (IOException e) {
-                       throw new LoginException("Cannot handle http callback: " + e.getMessage());
-               } catch (UnsupportedCallbackException e) {
-                       return false;
-               }
-               request = httpCallback.getRequest();
-               if (request == null)
-                       return false;
-               Authorization authorization = checkHttp();
-               if (authorization == null)
-                       return false;
-               sharedState.put(SHARED_STATE_AUTHORIZATION, authorization);
-               return true;
-       }
-
-       private Authorization checkHttp() {
-               Authorization authorization = null;
-               if (request != null) {
-                       authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION);
-                       if (authorization == null) {
-                               String httpSessionId = request.getSession().getId();
-                               authorization = (Authorization) request.getSession().getAttribute(HttpContext.AUTHORIZATION);
-                               if (authorization == null) {
-                                       Collection<ServiceReference<WebCmsSession>> sr;
-                                       try {
-                                               sr = bc.getServiceReferences(WebCmsSession.class,
-                                                               "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
-                                       } catch (InvalidSyntaxException e) {
-                                               throw new CmsException("Cannot get CMS session for id " + httpSessionId, e);
-                                       }
-                                       if (sr.size() == 1) {
-                                               WebCmsSession cmsSession = bc.getService(sr.iterator().next());
-                                               authorization = cmsSession.getAuthorization();
-                                               if (log.isTraceEnabled())
-                                                       log.trace("Retrieved authorization from " + cmsSession);
-                                       } else if (sr.size() == 0)
-                                               return null;
-                                       else
-                                               throw new CmsException(
-                                                               sr.size() + ">1 web sessions detected for http session " + httpSessionId);
-                               }
-                       }
-               }
-               return authorization;
-       }
-
-       @Override
-       public boolean commit() throws LoginException {
-               Authorization authorization = (Authorization) sharedState.get(SHARED_STATE_AUTHORIZATION);
-               if (authorization == null)
-                       return false;
-               if (request == null)
-                       return false;
-               String httpSessionId = request.getSession().getId();
-               if (authorization.getName() != null) {
-                       request.setAttribute(HttpContext.REMOTE_USER, authorization.getName());
-                       request.setAttribute(HttpContext.AUTHORIZATION, authorization);
-
-                       HttpSession httpSession = request.getSession();
-                       if (httpSession.getAttribute(HttpContext.AUTHORIZATION) == null) {
-
-                               Collection<ServiceReference<WebCmsSession>> sr;
-                               try {
-                                       sr = bc.getServiceReferences(WebCmsSession.class,
-                                                       "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
-                               } catch (InvalidSyntaxException e) {
-                                       throw new CmsException("Cannot get CMS session for id " + httpSessionId, e);
-                               }
-                               ServiceReference<WebCmsSession> cmsSessionRef;
-                               if (sr.size() == 1) {
-                                       cmsSessionRef = sr.iterator().next();
-                               } else if (sr.size() == 0) {
-                                       WebCmsSessionImpl cmsSessionImpl = new WebCmsSessionImpl(httpSessionId, authorization);
-                                       cmsSessionRef = cmsSessionImpl.getServiceRegistration().getReference();
-                                       if (log.isDebugEnabled())
-                                               log.debug("Initialized " + cmsSessionImpl + " for " + authorization.getName());
-                               } else
-                                       throw new CmsException(sr.size() + " CMS sessions registered for " + httpSessionId);
-
-                               WebCmsSessionImpl cmsSession = (WebCmsSessionImpl) bc.getService(cmsSessionRef);
-                               cmsSession.addHttpSession(request);
-                               if (log.isTraceEnabled())
-                                       log.trace("Added " + request.getServletPath() + " to " + cmsSession + " (" + request.getRequestURI()
-                                                       + ")");
-                               httpSession.setAttribute(HttpContext.REMOTE_USER, authorization.getName());
-                               httpSession.setAttribute(HttpContext.AUTHORIZATION, authorization);
-                       }
-               }
-               if (subject.getPrivateCredentials(HttpSessionId.class).size() == 0)
-                       subject.getPrivateCredentials().add(new HttpSessionId(httpSessionId));
-               else {
-                       String storedSessionId = subject.getPrivateCredentials(HttpSessionId.class).iterator().next().getValue();
-                       if (storedSessionId.equals(httpSessionId))
-                               throw new LoginException(
-                                               "Subject already logged with session " + storedSessionId + " (not " + httpSessionId + ")");
-               }
-               return true;
-       }
-
-       @Override
-       public boolean abort() throws LoginException {
-               return false;
-       }
-
-       @Override
-       public boolean logout() throws LoginException {
-               String httpSessionId;
-               if (subject.getPrivateCredentials(HttpSessionId.class).size() == 1)
-                       httpSessionId = subject.getPrivateCredentials(HttpSessionId.class).iterator().next().getValue();
-               else
-                       return false;
-               Collection<ServiceReference<WebCmsSession>> srs;
-               try {
-                       srs = bc.getServiceReferences(WebCmsSession.class,
-                                       "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
-               } catch (InvalidSyntaxException e) {
-                       throw new CmsException("Cannot retrieve CMS session #" + httpSessionId, e);
-               }
-
-               if (srs.size() == 0)
-                       throw new CmsException("No CMS web session found for http session " + httpSessionId);
-               else if (srs.size() > 1)
-                       throw new CmsException(srs.size() + " CMS web sessions found for http session " + httpSessionId);
-
-               WebCmsSessionImpl cmsSession = (WebCmsSessionImpl) bc.getService(srs.iterator().next());
-               cmsSession.cleanUp();
-               subject.getPrivateCredentials().removeAll(subject.getPrivateCredentials(HttpSessionId.class));
-               if (log.isDebugEnabled())
-                       log.debug("Cleaned up " + cmsSession);
-               return true;
-       }
-
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java
new file mode 100644 (file)
index 0000000..491acf9
--- /dev/null
@@ -0,0 +1,200 @@
+package org.argeo.cms.auth;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+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.cms.CmsException;
+import org.argeo.cms.internal.kernel.WebCmsSessionImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.useradmin.Authorization;
+
+public class HttpSessionLoginModule implements LoginModule, AuthConstants {
+       private final static Log log = LogFactory.getLog(HttpSessionLoginModule.class);
+
+       private Subject subject = null;
+       private CallbackHandler callbackHandler = null;
+       private Map<String, Object> sharedState = null;
+
+       private HttpServletRequest request = null;
+
+       private BundleContext bc;
+
+       private Authorization authorization;
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
+                       Map<String, ?> options) {
+               bc = FrameworkUtil.getBundle(HttpSessionLoginModule.class).getBundleContext();
+               assert bc != null;
+               this.subject = subject;
+               this.callbackHandler = callbackHandler;
+               this.sharedState = (Map<String, Object>) sharedState;
+       }
+
+       @Override
+       public boolean login() throws LoginException {
+               HttpRequestCallback httpCallback = new HttpRequestCallback();
+               try {
+                       callbackHandler.handle(new Callback[] { httpCallback });
+               } catch (IOException e) {
+                       throw new LoginException("Cannot handle http callback: " + e.getMessage());
+               } catch (UnsupportedCallbackException e) {
+                       return false;
+               }
+               request = httpCallback.getRequest();
+               if (request == null)
+                       return false;
+               authorization = checkHttp();
+               if (authorization == null)
+                       return false;
+               sharedState.put(SHARED_STATE_AUTHORIZATION, authorization);
+               return true;
+       }
+
+       private Authorization checkHttp() {
+               Authorization authorization = null;
+               if (request != null) {
+                       authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION);
+                       if (authorization == null) {
+                               String httpSessionId = request.getSession().getId();
+                               authorization = (Authorization) request.getSession().getAttribute(HttpContext.AUTHORIZATION);
+                               if (authorization == null) {
+                                       Collection<ServiceReference<WebCmsSession>> sr;
+                                       try {
+                                               sr = bc.getServiceReferences(WebCmsSession.class,
+                                                               "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
+                                       } catch (InvalidSyntaxException e) {
+                                               throw new CmsException("Cannot get CMS session for id " + httpSessionId, e);
+                                       }
+                                       if (sr.size() == 1) {
+                                               WebCmsSession cmsSession = bc.getService(sr.iterator().next());
+                                               authorization = cmsSession.getAuthorization();
+                                               if (log.isTraceEnabled())
+                                                       log.trace("Retrieved authorization from " + cmsSession);
+                                       } else if (sr.size() == 0)
+                                               return null;
+                                       else
+                                               throw new CmsException(
+                                                               sr.size() + ">1 web sessions detected for http session " + httpSessionId);
+                               }
+                       }
+               }
+               return authorization;
+       }
+
+       @Override
+       public boolean commit() throws LoginException {
+               // TODO create CmsSession in another module
+               if (authorization == null) {
+                       authorization = (Authorization) sharedState.get(SHARED_STATE_AUTHORIZATION);
+               } else { // this login module did the authorization
+                       CmsAuthUtils.addAuthentication(subject, authorization);
+               }
+               if (authorization == null) {
+                       return false;
+               }
+               if (request == null)
+                       return false;
+               String httpSessionId = request.getSession().getId();
+               if (authorization.getName() != null) {
+                       request.setAttribute(HttpContext.REMOTE_USER, authorization.getName());
+                       request.setAttribute(HttpContext.AUTHORIZATION, authorization);
+
+                       HttpSession httpSession = request.getSession();
+                       if (httpSession.getAttribute(HttpContext.AUTHORIZATION) == null) {
+
+                               Collection<ServiceReference<WebCmsSession>> sr;
+                               try {
+                                       sr = bc.getServiceReferences(WebCmsSession.class,
+                                                       "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
+                               } catch (InvalidSyntaxException e) {
+                                       throw new CmsException("Cannot get CMS session for id " + httpSessionId, e);
+                               }
+                               ServiceReference<WebCmsSession> cmsSessionRef;
+                               if (sr.size() == 1) {
+                                       cmsSessionRef = sr.iterator().next();
+                               } else if (sr.size() == 0) {
+                                       WebCmsSessionImpl cmsSessionImpl = new WebCmsSessionImpl(httpSessionId, authorization);
+                                       cmsSessionRef = cmsSessionImpl.getServiceRegistration().getReference();
+                                       if (log.isDebugEnabled())
+                                               log.debug("Initialized " + cmsSessionImpl + " for " + authorization.getName());
+                               } else
+                                       throw new CmsException(sr.size() + " CMS sessions registered for " + httpSessionId);
+
+                               WebCmsSessionImpl cmsSession = (WebCmsSessionImpl) bc.getService(cmsSessionRef);
+                               cmsSession.addHttpSession(request);
+                               if (log.isTraceEnabled())
+                                       log.trace("Added " + request.getServletPath() + " to " + cmsSession + " (" + request.getRequestURI()
+                                                       + ")");
+                               httpSession.setAttribute(HttpContext.REMOTE_USER, authorization.getName());
+                               httpSession.setAttribute(HttpContext.AUTHORIZATION, authorization);
+                       }
+               }
+               if (subject.getPrivateCredentials(HttpSessionId.class).size() == 0)
+                       subject.getPrivateCredentials().add(new HttpSessionId(httpSessionId));
+               else {
+                       String storedSessionId = subject.getPrivateCredentials(HttpSessionId.class).iterator().next().getValue();
+                       if (storedSessionId.equals(httpSessionId))
+                               throw new LoginException(
+                                               "Subject already logged with session " + storedSessionId + " (not " + httpSessionId + ")");
+               }
+
+               if (authorization != null) {
+                       CmsAuthUtils.addAuthentication(subject, authorization);
+                       return true;
+               } else {
+                       return false;
+               }
+       }
+
+       @Override
+       public boolean abort() throws LoginException {
+               return false;
+       }
+
+       @Override
+       public boolean logout() throws LoginException {
+               String httpSessionId;
+               if (subject.getPrivateCredentials(HttpSessionId.class).size() == 1)
+                       httpSessionId = subject.getPrivateCredentials(HttpSessionId.class).iterator().next().getValue();
+               else
+                       return false;
+               Collection<ServiceReference<WebCmsSession>> srs;
+               try {
+                       srs = bc.getServiceReferences(WebCmsSession.class,
+                                       "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")");
+               } catch (InvalidSyntaxException e) {
+                       throw new CmsException("Cannot retrieve CMS session #" + httpSessionId, e);
+               }
+
+               if (srs.size() == 0)
+                       throw new CmsException("No CMS web session found for http session " + httpSessionId);
+               else if (srs.size() > 1)
+                       throw new CmsException(srs.size() + " CMS web sessions found for http session " + httpSessionId);
+
+               WebCmsSessionImpl cmsSession = (WebCmsSessionImpl) bc.getService(srs.iterator().next());
+               cmsSession.cleanUp();
+               subject.getPrivateCredentials().removeAll(subject.getPrivateCredentials(HttpSessionId.class));
+               if (log.isDebugEnabled())
+                       log.debug("Cleaned up " + cmsSession);
+               return true;
+       }
+
+}
index 52a90c7a5eed86bc2f2eb5b1827b9386721cc05d..515f4dc0daee943e880b740f01bb69e9027b2c07 100644 (file)
@@ -111,8 +111,8 @@ public class UserAdminLoginModule implements LoginModule, AuthConstants {
                                }
                        }
                }
-               // if (!sharedState.containsKey(SHARED_STATE_AUTHORIZATION))
-               // sharedState.put(SHARED_STATE_AUTHORIZATION, authorization);
+               if (!sharedState.containsKey(SHARED_STATE_AUTHORIZATION))
+                       sharedState.put(SHARED_STATE_AUTHORIZATION, authorization);
                return authorization != null;
        }
 
index 7d900fbe610a77903b568431229f1af60492af02..fdce43b6a7ac0727d1a30a568afa0dd010df38a8 100644 (file)
@@ -1,5 +1,5 @@
 USER {
-    org.argeo.cms.auth.HttpLoginModule requisite;
+    org.argeo.cms.auth.HttpSessionLoginModule sufficient;
     org.argeo.cms.auth.UserAdminLoginModule requisite;
 };
 
index 978be436b648623c1e6cf00199a226c26c96ace0..046829fe51b6d3d8db552a85e4c0b7ca6c75e1b1 100644 (file)
@@ -29,6 +29,8 @@ import org.apache.jackrabbit.core.security.AMContext;
 import org.apache.jackrabbit.core.security.AccessManager;
 import org.apache.jackrabbit.core.security.SecurityConstants;
 import org.apache.jackrabbit.core.security.authorization.WorkspaceAccessManager;
+import org.argeo.node.NodeConstants;
+import org.argeo.node.security.AnonymousPrincipal;
 
 /** Integrates Spring Security and Jackrabbit Security users and roles. */
 public class ArgeoSecurityManager extends DefaultSecurityManager {
@@ -56,10 +58,15 @@ public class ArgeoSecurityManager extends DefaultSecurityManager {
        @Override
        public String getUserID(Subject subject, String workspaceName)
                        throws RepositoryException {
+               Set<AnonymousPrincipal> anonymousPrincipal = subject
+                               .getPrincipals(AnonymousPrincipal.class);
+               if(!anonymousPrincipal.isEmpty())
+                       return NodeConstants.ROLE_ANONYMOUS;
                Set<X500Principal> userPrincipal = subject
                                .getPrincipals(X500Principal.class);
                if (userPrincipal.isEmpty())
-                       return super.getUserID(subject, workspaceName);
+                       throw new IllegalStateException("Subject is neither anonymous nor logged-in");
+//                     return super.getUserID(subject, workspaceName);
                if (userPrincipal.size() > 1) {
                        StringBuilder buf = new StringBuilder();
                        for (X500Principal principal : userPrincipal)
index 62f8fa02b1d23860011f456253e84b54cabadc9a..f7de8d003f73cb68562fc6b968a8882e90973cb1 100644 (file)
@@ -9,12 +9,12 @@ import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
 import javax.security.auth.x500.X500Principal;
 
+import org.apache.jackrabbit.core.security.AnonymousPrincipal;
 import org.apache.jackrabbit.core.security.SecurityConstants;
 import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
-import org.argeo.node.DataAdminPrincipal;
+import org.argeo.node.security.DataAdminPrincipal;
 
 public class SystemJackrabbitLoginModule implements LoginModule {
-
        private Subject subject;
 
        @Override
@@ -30,6 +30,12 @@ public class SystemJackrabbitLoginModule implements LoginModule {
 
        @Override
        public boolean commit() throws LoginException {
+               Set<org.argeo.node.security.AnonymousPrincipal> anonPrincipal = subject.getPrincipals(org.argeo.node.security.AnonymousPrincipal.class);
+               if (!anonPrincipal.isEmpty()) {
+                       subject.getPrincipals().add(new AnonymousPrincipal());
+                       return true;
+               }
+
                Set<DataAdminPrincipal> initPrincipal = subject.getPrincipals(DataAdminPrincipal.class);
                if (!initPrincipal.isEmpty()) {
                        subject.getPrincipals().add(new AdminPrincipal(SecurityConstants.ADMIN_ID));
@@ -52,11 +58,8 @@ public class SystemJackrabbitLoginModule implements LoginModule {
 
        @Override
        public boolean logout() throws LoginException {
-               Set<DataAdminPrincipal> initPrincipal = subject.getPrincipals(DataAdminPrincipal.class);
-               if (!initPrincipal.isEmpty()) {
-                       subject.getPrincipals(AdminPrincipal.class);
-                       return true;
-               }
+               subject.getPrincipals().removeAll(subject.getPrincipals(AnonymousPrincipal.class));
+               subject.getPrincipals().removeAll(subject.getPrincipals(AdminPrincipal.class));
                return true;
        }
 }
index 804ce0725c0c6e3b15816690696a293931c8815a..aee319698ba32380d6fa9ad67d8bb88aaca1467c 100644 (file)
@@ -18,7 +18,7 @@ package org.argeo.jcr;
 import java.security.Principal;
 
 /** Canonical implementation of a {@link Principal} */
-public class SimplePrincipal implements Principal {
+class SimplePrincipal implements Principal {
        private final String name;
 
        public SimplePrincipal(String name) {
diff --git a/org.argeo.node.api/src/org/argeo/node/DataAdminPrincipal.java b/org.argeo.node.api/src/org/argeo/node/DataAdminPrincipal.java
deleted file mode 100644 (file)
index 743c96f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.argeo.node;
-
-import java.security.Principal;
-
-/** Allows to modify any data. */
-public final class DataAdminPrincipal implements Principal {
-       // FIXME put auth constants in API
-       private final String name = "OU=node";
-
-       @Override
-       public String getName() {
-               return name;
-       }
-
-       @Override
-       public int hashCode() {
-               return name.hashCode();
-       }
-
-       @Override
-       public boolean equals(Object obj) {
-               return this == obj;
-       }
-
-       @Override
-       public String toString() {
-               return name.toString();
-       }
-
-}
diff --git a/org.argeo.node.api/src/org/argeo/node/NodeAuthenticated.java b/org.argeo.node.api/src/org/argeo/node/NodeAuthenticated.java
deleted file mode 100644 (file)
index ed25490..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.argeo.node;
-
-import javax.security.auth.Subject;
-
-public interface NodeAuthenticated {
-       String KEY = "org.argeo.node.authenticated";
-
-       Subject getSubject();
-
-}
index 2bba10cdc2604cdfe74a79a90828ca2598cf0cce..566ae37d149d1fc2d553530ce3550aafb04b1f51 100644 (file)
@@ -57,6 +57,7 @@ public interface NodeConstants {
        String ROLES_BASEDN = "ou=roles,ou=node";
        String ROLE_ADMIN = "cn=admin," + ROLES_BASEDN;
        String ROLE_USER_ADMIN = "cn=userAdmin," + ROLES_BASEDN;
+       String ROLE_DATA_ADMIN = "cn=dataAdmin," + ROLES_BASEDN;
        // Special system groups that cannot be edited:
        // user U anonymous = everyone
        String ROLE_USER = "cn=user," + ROLES_BASEDN;
diff --git a/org.argeo.node.api/src/org/argeo/node/security/AnonymousPrincipal.java b/org.argeo.node.api/src/org/argeo/node/security/AnonymousPrincipal.java
new file mode 100644 (file)
index 0000000..141f9d1
--- /dev/null
@@ -0,0 +1,36 @@
+package org.argeo.node.security;
+
+import java.security.Principal;
+
+import javax.naming.ldap.LdapName;
+
+import org.argeo.node.NodeConstants;
+
+/** Marker for anonymous users. */
+public final class AnonymousPrincipal implements Principal {
+       private final String name = NodeConstants.ROLE_ANONYMOUS;
+
+       @Override
+       public String getName() {
+               return name;
+       }
+
+       @Override
+       public int hashCode() {
+               return name.hashCode();
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               return this == obj;
+       }
+
+       @Override
+       public String toString() {
+               return name.toString();
+       }
+
+       public LdapName getLdapName(){
+               return NodeSecurityUtils.ROLE_ANONYMOUS_NAME;
+       }
+}
diff --git a/org.argeo.node.api/src/org/argeo/node/security/DataAdminPrincipal.java b/org.argeo.node.api/src/org/argeo/node/security/DataAdminPrincipal.java
new file mode 100644 (file)
index 0000000..280d537
--- /dev/null
@@ -0,0 +1,31 @@
+package org.argeo.node.security;
+
+import java.security.Principal;
+
+import org.argeo.node.NodeConstants;
+
+/** Allows to modify any data. */
+public final class DataAdminPrincipal implements Principal {
+       private final String name = NodeConstants.ROLE_DATA_ADMIN;
+
+       @Override
+       public String getName() {
+               return name;
+       }
+
+       @Override
+       public int hashCode() {
+               return name.hashCode();
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               return this == obj;
+       }
+
+       @Override
+       public String toString() {
+               return name.toString();
+       }
+
+}
diff --git a/org.argeo.node.api/src/org/argeo/node/security/NodeAuthenticated.java b/org.argeo.node.api/src/org/argeo/node/security/NodeAuthenticated.java
new file mode 100644 (file)
index 0000000..a316af5
--- /dev/null
@@ -0,0 +1,11 @@
+package org.argeo.node.security;
+
+import javax.security.auth.login.LoginContext;
+
+public interface NodeAuthenticated {
+       String KEY = "org.argeo.node.authenticated";
+
+//     Subject getSubject();
+       LoginContext getLoginContext();
+
+}
diff --git a/org.argeo.node.api/src/org/argeo/node/security/NodeSecurityUtils.java b/org.argeo.node.api/src/org/argeo/node/security/NodeSecurityUtils.java
new file mode 100644 (file)
index 0000000..97618d5
--- /dev/null
@@ -0,0 +1,38 @@
+package org.argeo.node.security;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import javax.naming.InvalidNameException;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.node.NodeConstants;
+
+public class NodeSecurityUtils {
+       public final static LdapName ROLE_ADMIN_NAME, ROLE_ANONYMOUS_NAME, ROLE_USER_NAME, ROLE_USER_ADMIN_NAME;
+       public final static List<LdapName> RESERVED_ROLES;
+       static {
+               try {
+                       ROLE_ADMIN_NAME = new LdapName(NodeConstants.ROLE_ADMIN);
+                       ROLE_USER_NAME = new LdapName(NodeConstants.ROLE_USER);
+                       ROLE_USER_ADMIN_NAME = new LdapName(NodeConstants.ROLE_USER_ADMIN);
+                       ROLE_ANONYMOUS_NAME = new LdapName(NodeConstants.ROLE_ANONYMOUS);
+                       RESERVED_ROLES = Collections.unmodifiableList(Arrays.asList(
+                                       new LdapName[] { ROLE_ADMIN_NAME, ROLE_ANONYMOUS_NAME, ROLE_USER_NAME, ROLE_USER_ADMIN_NAME }));
+               } catch (InvalidNameException e) {
+                       throw new Error("Cannot initialize login module class", e);
+               }
+       }
+
+       public static void checkUserName(LdapName name) throws IllegalArgumentException {
+               if (RESERVED_ROLES.contains(name))
+                       throw new IllegalArgumentException(name + " is a reserved name");
+       }
+
+       public static void checkImpliedPrincipalName(LdapName roleName) throws IllegalArgumentException {
+               if (ROLE_USER_NAME.equals(roleName) || ROLE_ANONYMOUS_NAME.equals(roleName))
+                       throw new IllegalArgumentException(roleName + " cannot be listed as role");
+       }
+
+}
diff --git a/org.argeo.node.api/src/org/argeo/node/security/UserPrincipal.java b/org.argeo.node.api/src/org/argeo/node/security/UserPrincipal.java
new file mode 100644 (file)
index 0000000..0c51adb
--- /dev/null
@@ -0,0 +1,37 @@
+package org.argeo.node.security;
+
+import java.security.Principal;
+
+import javax.naming.ldap.LdapName;
+
+import org.argeo.node.NodeConstants;
+
+/** Marker for logged in users. */
+public final class UserPrincipal implements Principal {
+       private final String name = NodeConstants.ROLE_USER;
+
+       @Override
+       public String getName() {
+               return name;
+       }
+
+       @Override
+       public int hashCode() {
+               return name.hashCode();
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               return this == obj;
+       }
+
+       @Override
+       public String toString() {
+               return name.toString();
+       }
+
+       public LdapName getLdapName(){
+               return NodeSecurityUtils.ROLE_USER_NAME;
+       }
+
+}