From 7e333073d07b780efe681306a1842a750cbea83c Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Fri, 21 Oct 2016 14:25:36 +0000 Subject: [PATCH] Continue finalising security. Fix issues with login in web. git-svn-id: https://svn.argeo.org/commons/trunk@9273 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../security/ui/rap/RapWorkbenchLogin.java | 27 ++++---- .../argeo/cms/ui/AbstractCmsEntryPoint.java | 28 ++++---- .../src/org/argeo/cms/ui/CmsView.java | 4 +- .../src/org/argeo/cms/util/CmsUtils.java | 2 +- .../org/argeo/cms/util/LoginEntryPoint.java | 45 ++++++++----- .../src/org/argeo/cms/util/OpenUserMenu.java | 1 + .../src/org/argeo/cms/util/UserMenu.java | 1 + .../src/org/argeo/cms/util/UserMenuLink.java | 7 +- .../cms/util/useradmin/UserAdminUtils.java | 59 ++++++++--------- .../org/argeo/cms/widgets/auth/CmsLogin.java | 27 ++++---- .../argeo/cms/widgets/auth/CmsLoginShell.java | 10 ++- .../src/org/argeo/cms/auth/CmsAuthUtils.java | 64 ++++++------------- .../src/org/argeo/cms/auth/CurrentUser.java | 23 ++++--- .../argeo/cms/auth/DataAdminLoginModule.java | 2 +- ...odule.java => HttpSessionLoginModule.java} | 28 ++++++-- .../argeo/cms/auth/UserAdminLoginModule.java | 4 +- .../org/argeo/cms/internal/kernel/jaas.cfg | 2 +- .../jackrabbit/ArgeoSecurityManager.java | 9 ++- .../SystemJackrabbitLoginModule.java | 17 +++-- .../src/org/argeo/jcr/SimplePrincipal.java | 2 +- .../src/org/argeo/node/NodeAuthenticated.java | 10 --- .../src/org/argeo/node/NodeConstants.java | 1 + .../node/security/AnonymousPrincipal.java | 36 +++++++++++ .../{ => security}/DataAdminPrincipal.java | 7 +- .../node/security/NodeAuthenticated.java | 11 ++++ .../node/security/NodeSecurityUtils.java | 38 +++++++++++ .../argeo/node/security/UserPrincipal.java | 37 +++++++++++ 27 files changed, 312 insertions(+), 190 deletions(-) rename org.argeo.cms/src/org/argeo/cms/auth/{HttpLoginModule.java => HttpSessionLoginModule.java} (89%) delete mode 100644 org.argeo.node.api/src/org/argeo/node/NodeAuthenticated.java create mode 100644 org.argeo.node.api/src/org/argeo/node/security/AnonymousPrincipal.java rename org.argeo.node.api/src/org/argeo/node/{ => security}/DataAdminPrincipal.java (75%) create mode 100644 org.argeo.node.api/src/org/argeo/node/security/NodeAuthenticated.java create mode 100644 org.argeo.node.api/src/org/argeo/node/security/NodeSecurityUtils.java create mode 100644 org.argeo.node.api/src/org/argeo/node/security/UserPrincipal.java diff --git a/org.argeo.cms.ui.workbench.rap/src/org/argeo/security/ui/rap/RapWorkbenchLogin.java b/org.argeo.cms.ui.workbench.rap/src/org/argeo/security/ui/rap/RapWorkbenchLogin.java index 7bf487a88..06fc62e2e 100644 --- a/org.argeo.cms.ui.workbench.rap/src/org/argeo/security/ui/rap/RapWorkbenchLogin.java +++ b/org.argeo.cms.ui.workbench.rap/src/org/argeo/security/ui/rap/RapWorkbenchLogin.java @@ -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() { - public Integer run() { - int result = createAndRunWorkbench(display, - CurrentUser.getUsername(getSubject())); - return new Integer(result); - } - }); + returnCode = Subject.doAs(subject, new PrivilegedAction() { + 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()); diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java index 5072c628d..030b4104c 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java @@ -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(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() { + Subject.doAs(loginContext.getSubject(), new PrivilegedAction() { @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() { + Subject.doAs(loginContext.getSubject(), new PrivilegedAction() { @Override public Void run() { refresh(); diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsView.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsView.java index 8ef468a70..d39d6df16 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsView.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/ui/CmsView.java @@ -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); diff --git a/org.argeo.cms.ui/src/org/argeo/cms/util/CmsUtils.java b/org.argeo.cms.ui/src/org/argeo/cms/util/CmsUtils.java index 27f83807f..7864dde8b 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/util/CmsUtils.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/util/CmsUtils.java @@ -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; diff --git a/org.argeo.cms.ui/src/org/argeo/cms/util/LoginEntryPoint.java b/org.argeo.cms.ui/src/org/argeo/cms/util/LoginEntryPoint.java index 3c3746b72..1f46f100e 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/util/LoginEntryPoint.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/util/LoginEntryPoint.java @@ -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 diff --git a/org.argeo.cms.ui/src/org/argeo/cms/util/OpenUserMenu.java b/org.argeo.cms.ui/src/org/argeo/cms/util/OpenUserMenu.java index bb2bb3990..78531463a 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/util/OpenUserMenu.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/util/OpenUserMenu.java @@ -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; diff --git a/org.argeo.cms.ui/src/org/argeo/cms/util/UserMenu.java b/org.argeo.cms.ui/src/org/argeo/cms/util/UserMenu.java index a654dddd4..58dea8086 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/util/UserMenu.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/util/UserMenu.java @@ -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; diff --git a/org.argeo.cms.ui/src/org/argeo/cms/util/UserMenuLink.java b/org.argeo.cms.ui/src/org/argeo/cms/util/UserMenuLink.java index 08af8d3da..f8dd86a0f 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/util/UserMenuLink.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/util/UserMenuLink.java @@ -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]; diff --git a/org.argeo.cms.ui/src/org/argeo/cms/util/useradmin/UserAdminUtils.java b/org.argeo.cms.ui/src/org/argeo/cms/util/useradmin/UserAdminUtils.java index 6684b261f..fdd61d69d 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/util/useradmin/UserAdminUtils.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/util/useradmin/UserAdminUtils.java @@ -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); } /** diff --git a/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLogin.java b/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLogin.java index 792471996..180999807 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLogin.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLogin.java @@ -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()); } diff --git a/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLoginShell.java b/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLoginShell.java index c31ad9657..dea632de8 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLoginShell.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/widgets/auth/CmsLoginShell.java @@ -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); + } } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java b/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java index 2e585237d..86800e282 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java @@ -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 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() { diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java b/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java index bc438a255..68848f7df 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java @@ -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 roles() { @@ -95,9 +96,7 @@ public final class CurrentUser { public final static Set roles(Subject subject) { Set roles = new HashSet(); - 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()); } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/DataAdminLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/DataAdminLoginModule.java index 5c7b64377..215ed96b4 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/DataAdminLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/DataAdminLoginModule.java @@ -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/HttpSessionLoginModule.java similarity index 89% rename from org.argeo.cms/src/org/argeo/cms/auth/HttpLoginModule.java rename to org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java index 9a07e3c20..491acf9bc 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/HttpLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java @@ -24,8 +24,8 @@ 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); +public class HttpSessionLoginModule implements LoginModule, AuthConstants { + private final static Log log = LogFactory.getLog(HttpSessionLoginModule.class); private Subject subject = null; private CallbackHandler callbackHandler = null; @@ -35,11 +35,13 @@ public class HttpLoginModule implements LoginModule, AuthConstants { private BundleContext bc; + private Authorization authorization; + @SuppressWarnings("unchecked") @Override public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { - bc = FrameworkUtil.getBundle(HttpLoginModule.class).getBundleContext(); + bc = FrameworkUtil.getBundle(HttpSessionLoginModule.class).getBundleContext(); assert bc != null; this.subject = subject; this.callbackHandler = callbackHandler; @@ -59,7 +61,7 @@ public class HttpLoginModule implements LoginModule, AuthConstants { request = httpCallback.getRequest(); if (request == null) return false; - Authorization authorization = checkHttp(); + authorization = checkHttp(); if (authorization == null) return false; sharedState.put(SHARED_STATE_AUTHORIZATION, authorization); @@ -99,9 +101,15 @@ public class HttpLoginModule implements LoginModule, AuthConstants { @Override public boolean commit() throws LoginException { - Authorization authorization = (Authorization) sharedState.get(SHARED_STATE_AUTHORIZATION); - if (authorization == null) + // 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(); @@ -147,7 +155,13 @@ public class HttpLoginModule implements LoginModule, AuthConstants { throw new LoginException( "Subject already logged with session " + storedSessionId + " (not " + httpSessionId + ")"); } - return true; + + if (authorization != null) { + CmsAuthUtils.addAuthentication(subject, authorization); + return true; + } else { + return false; + } } @Override diff --git a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java index 52a90c7a5..515f4dc0d 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java @@ -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; } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg index 7d900fbe6..fdce43b6a 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg @@ -1,5 +1,5 @@ USER { - org.argeo.cms.auth.HttpLoginModule requisite; + org.argeo.cms.auth.HttpSessionLoginModule sufficient; org.argeo.cms.auth.UserAdminLoginModule requisite; }; diff --git a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java b/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java index 978be436b..046829fe5 100644 --- a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java +++ b/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoSecurityManager.java @@ -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 = subject + .getPrincipals(AnonymousPrincipal.class); + if(!anonymousPrincipal.isEmpty()) + return NodeConstants.ROLE_ANONYMOUS; Set 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) diff --git a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java b/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java index 62f8fa02b..f7de8d003 100644 --- a/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java +++ b/org.argeo.ext.jackrabbit/src/org/argeo/security/jackrabbit/SystemJackrabbitLoginModule.java @@ -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 anonPrincipal = subject.getPrincipals(org.argeo.node.security.AnonymousPrincipal.class); + if (!anonPrincipal.isEmpty()) { + subject.getPrincipals().add(new AnonymousPrincipal()); + return true; + } + Set 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 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; } } diff --git a/org.argeo.jcr/src/org/argeo/jcr/SimplePrincipal.java b/org.argeo.jcr/src/org/argeo/jcr/SimplePrincipal.java index 804ce0725..aee319698 100644 --- a/org.argeo.jcr/src/org/argeo/jcr/SimplePrincipal.java +++ b/org.argeo.jcr/src/org/argeo/jcr/SimplePrincipal.java @@ -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/NodeAuthenticated.java b/org.argeo.node.api/src/org/argeo/node/NodeAuthenticated.java deleted file mode 100644 index ed254903d..000000000 --- a/org.argeo.node.api/src/org/argeo/node/NodeAuthenticated.java +++ /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(); - -} diff --git a/org.argeo.node.api/src/org/argeo/node/NodeConstants.java b/org.argeo.node.api/src/org/argeo/node/NodeConstants.java index 2bba10cdc..566ae37d1 100644 --- a/org.argeo.node.api/src/org/argeo/node/NodeConstants.java +++ b/org.argeo.node.api/src/org/argeo/node/NodeConstants.java @@ -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 index 000000000..141f9d1f4 --- /dev/null +++ b/org.argeo.node.api/src/org/argeo/node/security/AnonymousPrincipal.java @@ -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/DataAdminPrincipal.java b/org.argeo.node.api/src/org/argeo/node/security/DataAdminPrincipal.java similarity index 75% rename from org.argeo.node.api/src/org/argeo/node/DataAdminPrincipal.java rename to org.argeo.node.api/src/org/argeo/node/security/DataAdminPrincipal.java index 743c96f2e..280d537ae 100644 --- a/org.argeo.node.api/src/org/argeo/node/DataAdminPrincipal.java +++ b/org.argeo.node.api/src/org/argeo/node/security/DataAdminPrincipal.java @@ -1,11 +1,12 @@ -package org.argeo.node; +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 { - // FIXME put auth constants in API - private final String name = "OU=node"; + private final String name = NodeConstants.ROLE_DATA_ADMIN; @Override public String getName() { 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 index 000000000..a316af55a --- /dev/null +++ b/org.argeo.node.api/src/org/argeo/node/security/NodeAuthenticated.java @@ -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 index 000000000..97618d5ec --- /dev/null +++ b/org.argeo.node.api/src/org/argeo/node/security/NodeSecurityUtils.java @@ -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 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 index 000000000..0c51adbd0 --- /dev/null +++ b/org.argeo.node.api/src/org/argeo/node/security/UserPrincipal.java @@ -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; + } + +} -- 2.30.2