From 0a7d938324d33848ac7dc4ef4007c73a714171ee Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Fri, 9 Oct 2015 10:11:42 +0000 Subject: [PATCH] Refactor security components to the Kernel git-svn-id: https://svn.argeo.org/commons/trunk@8467 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../src/org/argeo/cms/auth/CurrentUser.java | 52 ++-- .../argeo/cms/internal/kernel/DataHttp.java | 2 +- .../org/argeo/cms/internal/kernel/Kernel.java | 176 +++++++------ .../cms/internal/kernel/KernelThread.java | 2 +- .../argeo/cms/internal/kernel/NodeHttp.java | 2 +- .../argeo/cms/internal/kernel/NodeLogger.java | 14 +- ...ackrabbitNode.java => NodeRepository.java} | 20 +- .../cms/internal/kernel/NodeSecurity.java | 32 ++- .../cms/internal/kernel/NodeUserAdmin.java | 244 ++++++++++-------- .../argeo/cms/internal/kernel}/PkiUtils.java | 2 +- .../org/argeo/cms/internal/kernel/jaas.cfg | 2 +- .../transaction/SimpleTransactionManager.java | 2 +- .../src/org/argeo/cms/util/CmsUtils.java | 9 +- .../src/org/argeo/cms/util/UserMenu.java | 4 +- .../src/org/argeo/cms/util/UserMenuLink.java | 6 +- .../META-INF/spring/osgi.xml | 2 +- .../META-INF/spring/logger.xml | 36 --- .../META-INF/spring/osgi.xml | 12 - org.argeo.security.core/bnd.bnd | 1 - .../META-INF/spring/keyring.xml | 2 +- .../META-INF/spring/osgi.xml | 2 +- .../security/ui/RolesSourceProvider.java | 2 +- .../security/ui/internal/CurrentUser.java | 34 --- .../argeo/security/ui/views/UserProfile.java | 8 +- .../argeo/jcr/DefaultRepositoryRegister.java | 6 +- .../org/argeo/jcr/security}/JcrKeyring.java | 6 +- org.argeo.util/build.properties | 4 +- .../PasswordBasedEncryptionTest.java | 4 +- .../argeo/util/security}/AbstractKeyring.java | 8 +- .../argeo/util/security}/CryptoKeyring.java | 3 +- .../util/security}/KeyringLoginModule.java | 2 +- .../util/security}/PBEKeySpecCallback.java | 2 +- .../security}/PasswordBasedEncryption.java | 28 +- 33 files changed, 350 insertions(+), 381 deletions(-) rename org.argeo.security.core/src/org/argeo/security/SecurityUtils.java => org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java (70%) rename org.argeo.security.core/src/org/argeo/security/log4j/SecureLogger.java => org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java (96%) rename org.argeo.cms/src/org/argeo/cms/internal/kernel/{JackrabbitNode.java => NodeRepository.java} (89%) rename {org.argeo.security.core/src/org/argeo/security/crypto => org.argeo.cms/src/org/argeo/cms/internal/kernel}/PkiUtils.java (98%) delete mode 100644 org.argeo.security.core/META-INF/spring/logger.xml delete mode 100644 org.argeo.security.core/META-INF/spring/osgi.xml delete mode 100644 org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java rename {org.argeo.security.core/src/org/argeo/security/jcr => org.argeo.server.jcr/src/org/argeo/jcr/security}/JcrKeyring.java (98%) rename {org.argeo.security.core/ext/test/org/argeo/security/crypto => org.argeo.util/ext/test/org/argeo/util/security}/PasswordBasedEncryptionTest.java (98%) rename {org.argeo.security.core/src/org/argeo/security/crypto => org.argeo.util/src/org/argeo/util/security}/AbstractKeyring.java (97%) rename {org.argeo.security.core/src/org/argeo/security/crypto => org.argeo.util/src/org/argeo/util/security}/CryptoKeyring.java (91%) rename {org.argeo.security.core/src/org/argeo/security/crypto => org.argeo.util/src/org/argeo/util/security}/KeyringLoginModule.java (98%) rename {org.argeo.security.core/src/org/argeo/security/crypto => org.argeo.util/src/org/argeo/util/security}/PBEKeySpecCallback.java (98%) rename {org.argeo.security.core/src/org/argeo/security/crypto => org.argeo.util/src/org/argeo/util/security}/PasswordBasedEncryption.java (91%) diff --git a/org.argeo.security.core/src/org/argeo/security/SecurityUtils.java b/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java similarity index 70% rename from org.argeo.security.core/src/org/argeo/security/SecurityUtils.java rename to org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java index e1f7899a5..5a65fcb11 100644 --- a/org.argeo.security.core/src/org/argeo/security/SecurityUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CurrentUser.java @@ -13,40 +13,46 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security; +package org.argeo.cms.auth; import java.security.AccessController; import java.security.Principal; import java.security.acl.Group; -import java.util.Collections; import java.util.HashSet; import java.util.Set; import javax.security.auth.Subject; import javax.security.auth.x500.X500Principal; -import org.argeo.ArgeoException; +import org.argeo.cms.CmsException; +import org.argeo.cms.CmsView; +import org.argeo.cms.util.CmsUtils; import org.osgi.service.useradmin.Authorization; /** Static utilities */ -public final class SecurityUtils { - private SecurityUtils() { - } - - /** Whether the current thread has the admin role */ - public static boolean hasCurrentThreadAuthority(String authority) { - return roles().contains(authority); - } - +public final class CurrentUser { /** * @return the authenticated username or null if not authenticated / * anonymous */ - public static String getCurrentThreadUsername() { + public static String getUsername() { + return getUsername(currentSubject()); + } + + public static String getDisplayName() { + return getDisplayName(currentSubject()); + } + + private static Subject currentSubject() { Subject subject = Subject.getSubject(AccessController.getContext()); - if (subject == null) - return null; - return getUsername(subject); + if (subject != null) + return subject; + if (subject == null) { + CmsView cmsView = CmsUtils.getCmsView(); + if (cmsView != null) + return cmsView.getSubject(); + } + throw new CmsException("Cannot find related subject"); } public final static String getUsername(Subject subject) { @@ -65,16 +71,17 @@ public final class SecurityUtils { return getAuthorization(subject).toString(); } - public final static Authorization getAuthorization(Subject subject) { + private static Authorization getAuthorization(Subject subject) { return subject.getPrivateCredentials(Authorization.class).iterator() .next(); } public final static Set roles() { - Set roles = Collections.synchronizedSet(new HashSet()); - Subject subject = Subject.getSubject(AccessController.getContext()); - if (subject == null) - throw new ArgeoException("Not authenticated."); + return roles(currentSubject()); + } + + public final static Set roles(Subject subject) { + Set roles = new HashSet(); X500Principal userPrincipal = subject .getPrincipals(X500Principal.class).iterator().next(); roles.add(userPrincipal.getName()); @@ -83,4 +90,7 @@ public final class SecurityUtils { } return roles; } + + private CurrentUser() { + } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java index 102bb7702..8f95a3ef9 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java @@ -65,7 +65,7 @@ class DataHttp implements KernelConstants, ArgeoJcrConstants { // WebDav / JCR remoting private OpenInViewSessionProvider sessionProvider; - DataHttp(HttpService httpService, JackrabbitNode node) { + DataHttp(HttpService httpService, NodeRepository node) { this.httpService = httpService; sessionProvider = new OpenInViewSessionProvider(); registerRepositoryServlets(ALIAS_NODE, node); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java index 8486f8d7e..026b12116 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java @@ -1,22 +1,25 @@ package org.argeo.cms.internal.kernel; +import static org.argeo.jcr.ArgeoJcrConstants.ALIAS_NODE; +import static org.argeo.jcr.ArgeoJcrConstants.JCR_REPOSITORY_ALIAS; + import java.lang.management.ManagementFactory; import java.security.PrivilegedAction; import java.util.HashMap; +import java.util.Hashtable; import java.util.Map; import javax.jcr.Repository; import javax.jcr.RepositoryFactory; -import javax.jcr.Session; import javax.security.auth.Subject; import javax.transaction.TransactionManager; -import javax.transaction.TransactionSynchronizationRegistry; import javax.transaction.UserTransaction; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.jackrabbit.util.TransientFileFactory; import org.argeo.ArgeoException; +import org.argeo.ArgeoLogger; import org.argeo.cms.CmsException; import org.argeo.cms.internal.transaction.SimpleTransactionManager; import org.argeo.jackrabbit.OsgiJackrabbitRepositoryFactory; @@ -26,8 +29,8 @@ import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceEvent; import org.osgi.framework.ServiceListener; import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; import org.osgi.service.useradmin.UserAdmin; -import org.osgi.util.tracker.ServiceTracker; /** * Argeo CMS Kernel. Responsible for : @@ -41,17 +44,32 @@ import org.osgi.util.tracker.ServiceTracker; * */ final class Kernel implements ServiceListener { - private final static Log log = LogFactory.getLog(Kernel.class); - - private final BundleContext bundleContext = Activator.getBundleContext(); - private final NodeSecurity nodeSecurity; - - ThreadGroup threadGroup = new ThreadGroup(Kernel.class.getSimpleName()); - JackrabbitNode node; - private NodeUserAdmin userAdmin; + /* + * REGISTERED SERVICES + */ + private ServiceRegistration loggerReg; + private ServiceRegistration tmReg; + private ServiceRegistration utReg; + // private ServiceRegistration tsrReg; + private ServiceRegistration repositoryReg; + private ServiceRegistration repositoryFactoryReg; + private ServiceRegistration userAdminReg; + + /* + * SERVICES IMPLEMENTATIONS + */ + private NodeLogger logger; private SimpleTransactionManager transactionManager; private OsgiJackrabbitRepositoryFactory repositoryFactory; - private DataHttp nodeHttp; + NodeRepository repository; + private NodeUserAdmin userAdmin; + + // Members + private final static Log log = LogFactory.getLog(Kernel.class); + ThreadGroup threadGroup = new ThreadGroup(Kernel.class.getSimpleName()); + private final BundleContext bc = Activator.getBundleContext(); + private final NodeSecurity nodeSecurity; + private DataHttp dataHttp; private KernelThread kernelThread; public Kernel() { @@ -61,13 +79,11 @@ final class Kernel implements ServiceListener { final void init() { Subject.doAs(nodeSecurity.getKernelSubject(), new PrivilegedAction() { - @Override public Void run() { doInit(); return null; } - }); } @@ -79,26 +95,15 @@ final class Kernel implements ServiceListener { long begin = System.currentTimeMillis(); try { - // Transaction + // Initialise services + logger = new NodeLogger(); transactionManager = new SimpleTransactionManager(); - - // Jackrabbit node - node = new JackrabbitNode(bundleContext); - - // JCR repository factory + repository = new NodeRepository(bc); repositoryFactory = new OsgiJackrabbitRepositoryFactory(); + userAdmin = new NodeUserAdmin(transactionManager, repository); - // Authentication - Session adminSession = node.login(); - userAdmin = new NodeUserAdmin(adminSession); - userAdmin.setTransactionManager(transactionManager); - bundleContext.registerService(UserAdmin.class, userAdmin, - userAdmin.currentState()); - - // Equinox dependency - // ExtendedHttpService httpService = waitForHttpService(); - // nodeHttp = new NodeHttp(httpService, node); - ServiceReference sr = bundleContext + // HTTP + ServiceReference sr = bc .getServiceReference(ExtendedHttpService.class); if (sr != null) addHttpService(sr); @@ -109,19 +114,7 @@ final class Kernel implements ServiceListener { kernelThread.start(); // Publish services to OSGi - bundleContext.registerService(TransactionManager.class, - transactionManager, null); - bundleContext.registerService(UserTransaction.class, - transactionManager, null); - bundleContext.registerService( - TransactionSynchronizationRegistry.class, - transactionManager.getTransactionSynchronizationRegistry(), - null); - node.publish(repositoryFactory); - bundleContext.registerService(RepositoryFactory.class, - repositoryFactory, null); - - bundleContext.addServiceListener(Kernel.this); + publish(); } catch (Exception e) { log.error("Cannot initialize Argeo CMS", e); throw new ArgeoException("Cannot initialize", e); @@ -138,19 +131,45 @@ final class Kernel implements ServiceListener { directorsCut(initDuration); } + private void publish() { + // Listen to service publication (also ours) + bc.addServiceListener(Kernel.this); + + // Logging + loggerReg = bc.registerService(ArgeoLogger.class, logger, null); + // Transaction + tmReg = bc.registerService(TransactionManager.class, + transactionManager, null); + utReg = bc.registerService(UserTransaction.class, transactionManager, + null); + // tsrReg = bc.registerService(TransactionSynchronizationRegistry.class, + // transactionManager.getTsr(), null); + // User admin + userAdminReg = bc.registerService(UserAdmin.class, userAdmin, + userAdmin.currentState()); + // JCR + Hashtable regProps = new Hashtable(); + regProps.put(JCR_REPOSITORY_ALIAS, ALIAS_NODE); + repositoryReg = bc.registerService(Repository.class, repository, + regProps); + repositoryFactoryReg = bc.registerService(RepositoryFactory.class, + repositoryFactory, null); + } + void destroy() { long begin = System.currentTimeMillis(); + unpublish(); kernelThread.destroyAndJoin(); - if (nodeHttp != null) - nodeHttp.destroy(); + if (dataHttp != null) + dataHttp.destroy(); if (userAdmin != null) userAdmin.destroy(); - if (node != null) - node.destroy(); + if (repository != null) + repository.destroy(); - bundleContext.removeServiceListener(this); + bc.removeServiceListener(this); // Clean hanging threads from Jackrabbit TransientFileFactory.shutdown(); @@ -164,39 +183,47 @@ final class Kernel implements ServiceListener { + (duration % 1000) + "s ##"); } + private void unpublish() { + userAdminReg.unregister(); + repositoryFactoryReg.unregister(); + repositoryReg.unregister(); + tmReg.unregister(); + utReg.unregister(); + loggerReg.unregister(); + } + @Override public void serviceChanged(ServiceEvent event) { ServiceReference sr = event.getServiceReference(); - Object service = bundleContext.getService(sr); + Object service = bc.getService(sr); if (service instanceof Repository) { Object jcrRepoAlias = sr .getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS); if (jcrRepoAlias != null) {// JCR repository String alias = jcrRepoAlias.toString(); - Repository repository = (Repository) bundleContext - .getService(sr); + Repository repository = (Repository) bc.getService(sr); Map props = new HashMap(); for (String key : sr.getPropertyKeys()) props.put(key, sr.getProperty(key)); if (ServiceEvent.REGISTERED == event.getType()) { try { repositoryFactory.register(repository, props); - nodeHttp.registerRepositoryServlets(alias, repository); + dataHttp.registerRepositoryServlets(alias, repository); } catch (Exception e) { throw new CmsException( "Could not publish JCR repository " + alias, e); } } else if (ServiceEvent.UNREGISTERING == event.getType()) { repositoryFactory.unregister(repository, props); - nodeHttp.unregisterRepositoryServlets(alias); + dataHttp.unregisterRepositoryServlets(alias); } } } else if (service instanceof ExtendedHttpService) { if (ServiceEvent.REGISTERED == event.getType()) { addHttpService(sr); } else if (ServiceEvent.UNREGISTERING == event.getType()) { - nodeHttp.destroy(); - nodeHttp = null; + dataHttp.destroy(); + dataHttp = null; } } } @@ -204,33 +231,34 @@ final class Kernel implements ServiceListener { private void addHttpService(ServiceReference sr) { // for (String key : sr.getPropertyKeys()) // log.debug(key + "=" + sr.getProperty(key)); - ExtendedHttpService httpService = (ExtendedHttpService) bundleContext + ExtendedHttpService httpService = (ExtendedHttpService) bc .getService(sr); // TODO find constants Object httpPort = sr.getProperty("http.port"); Object httpsPort = sr.getProperty("https.port"); - nodeHttp = new DataHttp(httpService, node); + dataHttp = new DataHttp(httpService, repository); if (log.isDebugEnabled()) log.debug("HTTP " + httpPort + (httpsPort != null ? " - HTTPS " + httpsPort : "")); } - private ExtendedHttpService waitForHttpService() { - final ServiceTracker st = new ServiceTracker( - bundleContext, ExtendedHttpService.class, null); - st.open(); - ExtendedHttpService httpService; - try { - httpService = st.waitForService(1000); - } catch (InterruptedException e) { - httpService = null; - } - - if (httpService == null) - throw new CmsException("Could not find " - + ExtendedHttpService.class + " service."); - return httpService; - } + // private ExtendedHttpService waitForHttpService() { + // final ServiceTracker st = new + // ServiceTracker( + // bc, ExtendedHttpService.class, null); + // st.open(); + // ExtendedHttpService httpService; + // try { + // httpService = st.waitForService(1000); + // } catch (InterruptedException e) { + // httpService = null; + // } + // + // if (httpService == null) + // throw new CmsException("Could not find " + // + ExtendedHttpService.class + " service."); + // return httpService; + // } final private static void directorsCut(long initDuration) { // final long ms = 128l + (long) (Math.random() * 128d); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java index e58cbeef1..4b4b8026f 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelThread.java @@ -35,7 +35,7 @@ class KernelThread extends Thread { public KernelThread(Kernel kernel) { super(kernel.threadGroup, kernel.getClass().getSimpleName()); this.kernel = kernel; - this.repoStats = kernel.node.getRepositoryStatistics(); + this.repoStats = kernel.repository.getRepositoryStatistics(); } private void doSmallestPeriod() { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java index edcf719d7..bc74cf638 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeHttp.java @@ -65,7 +65,7 @@ class NodeHttp implements KernelConstants, ArgeoJcrConstants { // WebDav / JCR remoting private OpenInViewSessionProvider sessionProvider; - NodeHttp(ExtendedHttpService httpService, JackrabbitNode node) { + NodeHttp(ExtendedHttpService httpService, NodeRepository node) { // this.bundleContext = bundleContext; // this.authenticationManager = authenticationManager; diff --git a/org.argeo.security.core/src/org/argeo/security/log4j/SecureLogger.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java similarity index 96% rename from org.argeo.security.core/src/org/argeo/security/log4j/SecureLogger.java rename to org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java index 1da985703..1264b2452 100644 --- a/org.argeo.security.core/src/org/argeo/security/log4j/SecureLogger.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.log4j; +package org.argeo.cms.internal.kernel; import java.util.ArrayList; import java.util.Collections; @@ -36,10 +36,10 @@ import org.apache.log4j.spi.LoggingEvent; import org.argeo.ArgeoException; import org.argeo.ArgeoLogListener; import org.argeo.ArgeoLogger; -import org.argeo.security.SecurityUtils; +import org.argeo.cms.auth.CurrentUser; /** Not meant to be used directly in standard log4j config */ -public class SecureLogger implements ArgeoLogger { +class NodeLogger implements ArgeoLogger { private Boolean disabled = false; @@ -110,7 +110,7 @@ public class SecureLogger implements ArgeoLogger { public synchronized void register(ArgeoLogListener listener, Integer numberOfPreviousEvents) { - String username = SecurityUtils.getCurrentThreadUsername(); + String username = CurrentUser.getUsername(); if (username == null) throw new ArgeoException( "Only authenticated users can register a log listener"); @@ -141,7 +141,9 @@ public class SecureLogger implements ArgeoLogger { } public synchronized void unregister(ArgeoLogListener listener) { - String username = SecurityUtils.getCurrentThreadUsername(); + String username = CurrentUser.getUsername(); + if (username == null)// FIXME + return; if (!userListeners.containsKey(username)) throw new ArgeoException("No user listeners " + listener + " registered for user " + username); @@ -269,7 +271,7 @@ public class SecureLogger implements ArgeoLogger { protected void append(LoggingEvent event) { if (events != null) { try { - String username = SecurityUtils.getCurrentThreadUsername(); + String username = CurrentUser.getUsername(); events.put(new LogEvent(username, event)); } catch (InterruptedException e) { // silent diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitNode.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeRepository.java similarity index 89% rename from org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitNode.java rename to org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeRepository.java index 8ef16c44f..a139289be 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitNode.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeRepository.java @@ -9,7 +9,6 @@ import java.util.Dictionary; import java.util.Hashtable; import java.util.Properties; -import javax.jcr.Repository; import javax.jcr.RepositoryException; import org.apache.commons.io.IOUtils; @@ -25,21 +24,17 @@ import org.argeo.ArgeoException; import org.argeo.cms.CmsException; import org.argeo.jackrabbit.JackrabbitWrapper; import org.argeo.jcr.ArgeoJcrConstants; -import org.argeo.jcr.DefaultRepositoryRegister; import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; import org.xml.sax.InputSource; /** Jacrabbit based data layer */ -class JackrabbitNode extends JackrabbitWrapper implements KernelConstants, +class NodeRepository extends JackrabbitWrapper implements KernelConstants, ArgeoJcrConstants { - private static Log log = LogFactory.getLog(JackrabbitNode.class); + private static Log log = LogFactory.getLog(NodeRepository.class); private RepositoryContext repositoryContext; - private ServiceRegistration repositoryReg; - - public JackrabbitNode(BundleContext bundleContext) { + public NodeRepository(BundleContext bundleContext) { setBundleContext(bundleContext); JackrabbitNodeType type = JackrabbitNodeType.valueOf(prop(REPO_TYPE, h2.name())); @@ -53,16 +48,7 @@ class JackrabbitNode extends JackrabbitWrapper implements KernelConstants, } } - void publish(DefaultRepositoryRegister repositoryRegister) { - Hashtable regProps = new Hashtable(); - regProps.put(JCR_REPOSITORY_ALIAS, ALIAS_NODE); - repositoryReg = getBundleContext().registerService(Repository.class, - this, regProps); - repositoryRegister.register(this, regProps); - } - public void destroy() { - repositoryReg.unregister(); ((RepositoryImpl) getRepository()).shutdown(); } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java index b436ac8d1..b43a9fdf5 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java @@ -22,11 +22,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; import org.argeo.cms.auth.AuthConstants; -import org.argeo.security.crypto.PkiUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; -/** Authentication and user management. */ +/** Low-level kernel security */ class NodeSecurity { + public final static int HARDENED = 3; + public final static int STAGING = 2; + public final static int DEV = 1; + final static String SECURITY_PROVIDER = "BC";// Bouncy Castle private final static Log log; @@ -45,6 +48,7 @@ class NodeSecurity { } private final Subject kernelSubject; + private int securityLevel = STAGING; public NodeSecurity() { // Configure JAAS first @@ -53,10 +57,10 @@ class NodeSecurity { System.setProperty("java.security.auth.login.config", url.toExternalForm()); - this.kernelSubject = logKernel(); + this.kernelSubject = logInKernel(); } - private Subject logKernel() { + private Subject logInKernel() { final Subject kernelSubject = new Subject(); createKeyStoreIfNeeded(); @@ -66,7 +70,8 @@ class NodeSecurity { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { // alias - ((NameCallback) callbacks[1]).setName(AuthConstants.ROLE_KERNEL); + ((NameCallback) callbacks[1]) + .setName(AuthConstants.ROLE_KERNEL); // store pwd ((PasswordCallback) callbacks[2]).setPassword("changeit" .toCharArray()); @@ -93,7 +98,7 @@ class NodeSecurity { KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject); kernelLc.logout(); } catch (LoginException e) { - throw new CmsException("Cannot log in kernel", e); + throw new CmsException("Cannot log out kernel", e); } Security.removeProvider(SECURITY_PROVIDER); @@ -103,6 +108,21 @@ class NodeSecurity { return kernelSubject; } + public synchronized int getSecurityLevel() { + return securityLevel; + } + + public void setSecurityLevel(int newValue) { + if (newValue != STAGING || newValue != DEV) + throw new CmsException("Invalid value for security level " + + newValue); + if (newValue >= securityLevel) + throw new CmsException( + "Impossible to increase security level (from " + + securityLevel + " to " + newValue + ")"); + securityLevel = newValue; + } + private void createKeyStoreIfNeeded() { char[] ksPwd = "changeit".toCharArray(); char[] keyPwd = Arrays.copyOf(ksPwd, ksPwd.length); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java index 75cd44491..7408b1c1f 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java @@ -1,5 +1,8 @@ package org.argeo.cms.internal.kernel; +import static org.argeo.cms.internal.kernel.KernelUtils.getFrameworkProp; +import static org.argeo.cms.internal.kernel.KernelUtils.getOsgiInstanceDir; + import java.io.File; import java.io.IOException; import java.net.URI; @@ -14,6 +17,7 @@ import java.util.Map; import java.util.Set; import javax.jcr.Node; +import javax.jcr.Repository; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.Value; @@ -44,6 +48,10 @@ import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.User; import org.osgi.service.useradmin.UserAdmin; +/** + * Aggregates multiple {@link UserDirectory} and integrates them with this node + * system roles. + */ public class NodeUserAdmin implements UserAdmin { private final static Log log = LogFactory.getLog(NodeUserAdmin.class); final static LdapName ROLES_BASE; @@ -56,110 +64,41 @@ public class NodeUserAdmin implements UserAdmin { } } + // DAOs private UserAdmin nodeRoles = null; private Map userAdmins = new HashMap(); + // JCR /** The home base path. */ private String homeBasePath = "/home"; private String peopleBasePath = ArgeoJcrConstants.PEOPLE_BASE_PATH; + private Repository repository; private Session adminSession; - public NodeUserAdmin(Session adminSession) { - this.adminSession = adminSession; - File osgiInstanceDir = KernelUtils.getOsgiInstanceDir(); - File nodeBaseDir = new File(osgiInstanceDir, "node"); - nodeBaseDir.mkdirs(); - - String userAdminUri = KernelUtils - .getFrameworkProp(KernelConstants.USERADMIN_URIS); - if (userAdminUri == null) { - String demoBaseDn = "dc=example,dc=com"; - File businessRolesFile = new File(nodeBaseDir, demoBaseDn + ".ldif"); - if (!businessRolesFile.exists()) - try { - FileUtils.copyInputStreamToFile(getClass() - .getResourceAsStream(demoBaseDn + ".ldif"), - businessRolesFile); - } catch (IOException e) { - throw new CmsException("Cannot copy demo resource", e); - } - userAdminUri = businessRolesFile.toURI().toString(); - } - - String[] uris = userAdminUri.split(" "); - for (String uri : uris) { - URI u; - try { - u = new URI(uri); - if (u.getPath() == null) - throw new CmsException("URI " + uri - + " must have a path in order to determine base DN"); - if (u.getScheme() == null) { - if (uri.startsWith("/") || uri.startsWith("./") - || uri.startsWith("../")) - u = new File(uri).getCanonicalFile().toURI(); - else if (!uri.contains("/")) - u = new File(nodeBaseDir, uri).getCanonicalFile() - .toURI(); - else - throw new CmsException("Cannot interpret " + uri - + " as an uri"); - } else if (u.getScheme().equals("file")) { - u = new File(u).getCanonicalFile().toURI(); - } - } catch (Exception e) { - throw new CmsException( - "Cannot interpret " + uri + " as an uri", e); - } - Dictionary properties = UserAdminConf.uriAsProperties(u - .toString()); - UserDirectory businessRoles; - if (u.getScheme().startsWith("ldap")) { - businessRoles = new LdapUserAdmin(properties); - } else { - businessRoles = new LdifUserAdmin(properties); - } - businessRoles.init(); - addUserAdmin(businessRoles.getBaseDn(), (UserAdmin) businessRoles); - if (log.isDebugEnabled()) - log.debug("User directory " + businessRoles.getBaseDn() + " [" - + u.getScheme() + "] enabled."); + public NodeUserAdmin(TransactionManager transactionManager, + Repository repository) { + this.repository = repository; + try { + this.adminSession = this.repository.login(); + } catch (RepositoryException e) { + throw new CmsException("Cannot log-in", e); } - // Node roles - String nodeRolesUri = KernelUtils - .getFrameworkProp(KernelConstants.ROLES_URI); - String baseNodeRoleDn = AuthConstants.ROLES_BASEDN; - if (nodeRolesUri == null) { - File nodeRolesFile = new File(nodeBaseDir, baseNodeRoleDn + ".ldif"); - if (!nodeRolesFile.exists()) - try { - FileUtils.copyInputStreamToFile(getClass() - .getResourceAsStream("demo.ldif"), nodeRolesFile); - } catch (IOException e) { - throw new CmsException("Cannot copy demo resource", e); - } - nodeRolesUri = nodeRolesFile.toURI().toString(); - } + // DAOs + File nodeBaseDir = new File(getOsgiInstanceDir(), "node"); + nodeBaseDir.mkdirs(); + String userAdminUri = getFrameworkProp(KernelConstants.USERADMIN_URIS); + initUserAdmins(userAdminUri, nodeBaseDir); + String nodeRolesUri = getFrameworkProp(KernelConstants.ROLES_URI); + initNodeRoles(nodeRolesUri, nodeBaseDir); - Dictionary nodeRolesProperties = UserAdminConf - .uriAsProperties(nodeRolesUri); - if (!nodeRolesProperties.get(UserAdminConf.baseDn.property()).equals( - baseNodeRoleDn)) { - throw new CmsException("Invalid base dn for node roles"); - // TODO deal with "mounted" roles with a different baseDN - } - UserDirectory nodeRoles; - if (nodeRolesUri.startsWith("ldap")) { - nodeRoles = new LdapUserAdmin(nodeRolesProperties); - } else { - nodeRoles = new LdifUserAdmin(nodeRolesProperties); + // Transaction manager + ((UserDirectory) nodeRoles).setTransactionManager(transactionManager); + for (UserAdmin userAdmin : userAdmins.values()) { + if (userAdmin instanceof UserDirectory) + ((UserDirectory) userAdmin) + .setTransactionManager(transactionManager); } - nodeRoles.setExternalRoles(this); - nodeRoles.init(); - addUserAdmin(baseNodeRoleDn, (UserAdmin) nodeRoles); - if (log.isTraceEnabled()) - log.trace("Node roles enabled."); // JCR initJcr(adminSession); @@ -257,11 +196,6 @@ public class NodeUserAdmin implements UserAdmin { // USER ADMIN AGGREGATOR // public synchronized void addUserAdmin(String baseDn, UserAdmin userAdmin) { - if (baseDn.equals(AuthConstants.ROLES_BASEDN)) { - nodeRoles = userAdmin; - return; - } - if (userAdmins.containsKey(baseDn)) throw new UserDirectoryException( "There is already a user admin for " + baseDn); @@ -273,22 +207,6 @@ public class NodeUserAdmin implements UserAdmin { } } - public synchronized void removeUserAdmin(String baseDn) { - if (baseDn.equals(AuthConstants.ROLES_BASEDN)) - throw new UserDirectoryException("Node roles cannot be removed."); - LdapName base; - try { - base = new LdapName(baseDn); - } catch (InvalidNameException e) { - throw new UserDirectoryException("Badly formatted base DN " - + baseDn, e); - } - if (!userAdmins.containsKey(base)) - throw new UserDirectoryException("There is no user admin for " - + base); - userAdmins.remove(base); - } - private UserAdmin findUserAdmin(String name) { try { return findUserAdmin(new LdapName(name)); @@ -325,6 +243,106 @@ public class NodeUserAdmin implements UserAdmin { } } + private void initUserAdmins(String userAdminUri, File nodeBaseDir) { + if (userAdminUri == null) { + String demoBaseDn = "dc=example,dc=com"; + File businessRolesFile = new File(nodeBaseDir, demoBaseDn + ".ldif"); + if (!businessRolesFile.exists()) + try { + FileUtils.copyInputStreamToFile(getClass() + .getResourceAsStream(demoBaseDn + ".ldif"), + businessRolesFile); + } catch (IOException e) { + throw new CmsException("Cannot copy demo resource", e); + } + userAdminUri = businessRolesFile.toURI().toString(); + } + String[] uris = userAdminUri.split(" "); + for (String uri : uris) { + URI u; + try { + u = new URI(uri); + if (u.getPath() == null) + throw new CmsException("URI " + uri + + " must have a path in order to determine base DN"); + if (u.getScheme() == null) { + if (uri.startsWith("/") || uri.startsWith("./") + || uri.startsWith("../")) + u = new File(uri).getCanonicalFile().toURI(); + else if (!uri.contains("/")) + u = new File(nodeBaseDir, uri).getCanonicalFile() + .toURI(); + else + throw new CmsException("Cannot interpret " + uri + + " as an uri"); + } else if (u.getScheme().equals("file")) { + u = new File(u).getCanonicalFile().toURI(); + } + } catch (Exception e) { + throw new CmsException( + "Cannot interpret " + uri + " as an uri", e); + } + Dictionary properties = UserAdminConf.uriAsProperties(u + .toString()); + UserDirectory businessRoles; + if (u.getScheme().startsWith("ldap")) { + businessRoles = new LdapUserAdmin(properties); + } else { + businessRoles = new LdifUserAdmin(properties); + } + businessRoles.init(); + String baseDn = businessRoles.getBaseDn(); + if (userAdmins.containsKey(baseDn)) + throw new UserDirectoryException( + "There is already a user admin for " + baseDn); + try { + userAdmins.put(new LdapName(baseDn), (UserAdmin) businessRoles); + } catch (InvalidNameException e) { + throw new UserDirectoryException("Badly formatted base DN " + + baseDn, e); + } + addUserAdmin(businessRoles.getBaseDn(), (UserAdmin) businessRoles); + if (log.isDebugEnabled()) + log.debug("User directory " + businessRoles.getBaseDn() + " [" + + u.getScheme() + "] enabled."); + } + + } + + private void initNodeRoles(String nodeRolesUri, File nodeBaseDir) { + String baseNodeRoleDn = AuthConstants.ROLES_BASEDN; + if (nodeRolesUri == null) { + File nodeRolesFile = new File(nodeBaseDir, baseNodeRoleDn + ".ldif"); + if (!nodeRolesFile.exists()) + try { + FileUtils.copyInputStreamToFile(getClass() + .getResourceAsStream("demo.ldif"), nodeRolesFile); + } catch (IOException e) { + throw new CmsException("Cannot copy demo resource", e); + } + nodeRolesUri = nodeRolesFile.toURI().toString(); + } + + Dictionary nodeRolesProperties = UserAdminConf + .uriAsProperties(nodeRolesUri); + if (!nodeRolesProperties.get(UserAdminConf.baseDn.property()).equals( + baseNodeRoleDn)) { + throw new CmsException("Invalid base dn for node roles"); + // TODO deal with "mounted" roles with a different baseDN + } + if (nodeRolesUri.startsWith("ldap")) { + nodeRoles = new LdapUserAdmin(nodeRolesProperties); + } else { + nodeRoles = new LdifUserAdmin(nodeRolesProperties); + } + ((UserDirectory) nodeRoles).setExternalRoles(this); + ((UserDirectory) nodeRoles).init(); + addUserAdmin(baseNodeRoleDn, (UserAdmin) nodeRoles); + if (log.isTraceEnabled()) + log.trace("Node roles enabled."); + + } + /* * JCR */ diff --git a/org.argeo.security.core/src/org/argeo/security/crypto/PkiUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java similarity index 98% rename from org.argeo.security.core/src/org/argeo/security/crypto/PkiUtils.java rename to org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java index f66d3f99c..d8b39cdbc 100644 --- a/org.argeo.security.core/src/org/argeo/security/crypto/PkiUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java @@ -1,4 +1,4 @@ -package org.argeo.security.crypto; +package org.argeo.cms.internal.kernel; import java.io.File; import java.io.FileInputStream; 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 4f647cf8a..90c68bd21 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 @@ -21,7 +21,7 @@ KERNEL { }; KEYRING { - org.argeo.security.crypto.KeyringLoginModule required; + org.argeo.util.security.KeyringLoginModule required; }; SINGLE_USER { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransactionManager.java b/org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransactionManager.java index edb572681..30d9b7291 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransactionManager.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/transaction/SimpleTransactionManager.java @@ -122,7 +122,7 @@ public class SimpleTransactionManager implements TransactionManager, return transaction; } - public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() { + public TransactionSynchronizationRegistry getTsr() { return syncRegistry; } diff --git a/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java b/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java index d8cd171e2..439f48af1 100644 --- a/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/util/CmsUtils.java @@ -29,14 +29,17 @@ import org.eclipse.swt.widgets.Widget; /** Static utilities for the CMS framework. */ public class CmsUtils implements CmsConstants { - /** The CMS view related to this display. */ + /** + * The CMS view related to this display, or null if none is available from + * this call. + */ public static CmsView getCmsView() { Display display = Display.getCurrent(); if (display == null) - throw new CmsException("No display available"); + return null; CmsView cmsView = (CmsView) display.getData(CmsView.KEY); if (cmsView == null) - throw new CmsException("No CMS view available"); + return null; return cmsView; } diff --git a/org.argeo.cms/src/org/argeo/cms/util/UserMenu.java b/org.argeo.cms/src/org/argeo/cms/util/UserMenu.java index fc651e65b..801a2611b 100644 --- a/org.argeo.cms/src/org/argeo/cms/util/UserMenu.java +++ b/org.argeo.cms/src/org/argeo/cms/util/UserMenu.java @@ -24,7 +24,7 @@ import org.argeo.cms.CmsMsg; import org.argeo.cms.CmsStyles; import org.argeo.cms.CmsView; import org.argeo.cms.auth.AuthConstants; -import org.argeo.security.SecurityUtils; +import org.argeo.cms.auth.CurrentUser; import org.eclipse.rap.rwt.RWT; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; @@ -50,7 +50,7 @@ public class UserMenu extends Shell implements CmsStyles, CallbackHandler { super(source.getDisplay(), SWT.NO_TRIM | SWT.BORDER | SWT.ON_TOP); setData(RWT.CUSTOM_VARIANT, CMS_USER_MENU); - String username = SecurityUtils.getUsername(CmsUtils.getCmsView().getSubject()); + String username = CurrentUser.getUsername(CmsUtils.getCmsView().getSubject()); if (username.equalsIgnoreCase(AuthConstants.ROLE_ANONYMOUS)) { username = null; anonymousUi(); diff --git a/org.argeo.cms/src/org/argeo/cms/util/UserMenuLink.java b/org.argeo.cms/src/org/argeo/cms/util/UserMenuLink.java index f4c5f0063..704f90980 100644 --- a/org.argeo.cms/src/org/argeo/cms/util/UserMenuLink.java +++ b/org.argeo.cms/src/org/argeo/cms/util/UserMenuLink.java @@ -5,7 +5,7 @@ import javax.jcr.Node; import org.argeo.cms.CmsMsg; import org.argeo.cms.CmsStyles; import org.argeo.cms.auth.AuthConstants; -import org.argeo.security.SecurityUtils; +import org.argeo.cms.auth.CurrentUser; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.MouseEvent; @@ -23,12 +23,12 @@ public class UserMenuLink extends MenuLink { @Override public Control createUi(Composite parent, Node context) { - String username = SecurityUtils.getUsername(CmsUtils.getCmsView() + String username = CurrentUser.getUsername(CmsUtils.getCmsView() .getSubject()); if (username.equalsIgnoreCase(AuthConstants.ROLE_ANONYMOUS)) setLabel(CmsMsg.login.lead()); else { - setLabel(SecurityUtils.getDisplayName(CmsUtils.getCmsView() + setLabel(CurrentUser.getDisplayName(CmsUtils.getCmsView() .getSubject())); } Label link = (Label) ((Composite) super.createUi(parent, context)) diff --git a/org.argeo.eclipse.ui.workbench/META-INF/spring/osgi.xml b/org.argeo.eclipse.ui.workbench/META-INF/spring/osgi.xml index 255462be4..38f733291 100644 --- a/org.argeo.eclipse.ui.workbench/META-INF/spring/osgi.xml +++ b/org.argeo.eclipse.ui.workbench/META-INF/spring/osgi.xml @@ -18,6 +18,6 @@ filter="(argeo.jcr.repository.alias=node)" /> - + \ No newline at end of file diff --git a/org.argeo.security.core/META-INF/spring/logger.xml b/org.argeo.security.core/META-INF/spring/logger.xml deleted file mode 100644 index 02f48c8a8..000000000 --- a/org.argeo.security.core/META-INF/spring/logger.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/org.argeo.security.core/META-INF/spring/osgi.xml b/org.argeo.security.core/META-INF/spring/osgi.xml deleted file mode 100644 index 5e1433c2f..000000000 --- a/org.argeo.security.core/META-INF/spring/osgi.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/org.argeo.security.core/bnd.bnd b/org.argeo.security.core/bnd.bnd index d3d44a195..d31b9e77a 100644 --- a/org.argeo.security.core/bnd.bnd +++ b/org.argeo.security.core/bnd.bnd @@ -1,4 +1,3 @@ -Bundle-ActivationPolicy: lazy Import-Package:org.bouncycastle.*;resolution:=optional,\ javax.jcr.security,\ org.apache.commons.codec,\ diff --git a/org.argeo.security.ui/META-INF/spring/keyring.xml b/org.argeo.security.ui/META-INF/spring/keyring.xml index 429e4902d..74c4ad6cf 100644 --- a/org.argeo.security.ui/META-INF/spring/keyring.xml +++ b/org.argeo.security.ui/META-INF/spring/keyring.xml @@ -18,7 +18,7 @@ - + diff --git a/org.argeo.security.ui/META-INF/spring/osgi.xml b/org.argeo.security.ui/META-INF/spring/osgi.xml index 01e21244b..cb2cbfb2f 100644 --- a/org.argeo.security.ui/META-INF/spring/osgi.xml +++ b/org.argeo.security.ui/META-INF/spring/osgi.xml @@ -17,6 +17,6 @@ - \ No newline at end of file diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/RolesSourceProvider.java b/org.argeo.security.ui/src/org/argeo/security/ui/RolesSourceProvider.java index a81dc200a..42e6f10e7 100644 --- a/org.argeo.security.ui/src/org/argeo/security/ui/RolesSourceProvider.java +++ b/org.argeo.security.ui/src/org/argeo/security/ui/RolesSourceProvider.java @@ -19,7 +19,7 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import org.argeo.security.ui.internal.CurrentUser; +import org.argeo.cms.auth.CurrentUser; import org.eclipse.ui.AbstractSourceProvider; /** diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java b/org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java deleted file mode 100644 index 7086de0af..000000000 --- a/org.argeo.security.ui/src/org/argeo/security/ui/internal/CurrentUser.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.argeo.security.ui.internal; - -import java.util.Set; - -import org.argeo.security.SecurityUtils; - -/** - * Retrieves information about the current user. Not an API, can change without - * notice. - */ -public class CurrentUser { - public final static String getUsername() { - return SecurityUtils.getCurrentThreadUsername(); - } - - public final static Set roles() { - return SecurityUtils.roles(); - } -} diff --git a/org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java b/org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java index 83438e8aa..49f5bea5a 100644 --- a/org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java +++ b/org.argeo.security.ui/src/org/argeo/security/ui/views/UserProfile.java @@ -17,9 +17,9 @@ package org.argeo.security.ui.views; import java.util.TreeSet; +import org.argeo.cms.auth.CurrentUser; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.security.ui.SecurityUiPlugin; -import org.argeo.security.ui.internal.CurrentUser; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TableViewer; @@ -41,9 +41,9 @@ public class UserProfile extends ViewPart { public void createPartControl(Composite parent) { parent.setLayout(new GridLayout(2, false)); -// Authentication authentication = CurrentUser.getAuthentication(); -// EclipseUiUtils.createGridLL(parent, "Name", authentication -// .getPrincipal().toString()); + // Authentication authentication = CurrentUser.getAuthentication(); + // EclipseUiUtils.createGridLL(parent, "Name", authentication + // .getPrincipal().toString()); EclipseUiUtils.createGridLL(parent, "User ID", CurrentUser.getUsername()); diff --git a/org.argeo.server.jcr/src/org/argeo/jcr/DefaultRepositoryRegister.java b/org.argeo.server.jcr/src/org/argeo/jcr/DefaultRepositoryRegister.java index f13c84e3b..a0d972cc2 100644 --- a/org.argeo.server.jcr/src/org/argeo/jcr/DefaultRepositoryRegister.java +++ b/org.argeo.server.jcr/src/org/argeo/jcr/DefaultRepositoryRegister.java @@ -57,7 +57,6 @@ public class DefaultRepositoryRegister extends Observable implements /** Registers a service, typically called when OSGi services are bound. */ @SuppressWarnings("rawtypes") public synchronized void register(Repository repository, Map properties) { - // TODO: also check bean name? String alias; if (properties == null || !properties.containsKey(JCR_REPOSITORY_ALIAS)) { log.warn("Cannot register a repository if no " @@ -86,7 +85,10 @@ public class DefaultRepositoryRegister extends Observable implements String alias = properties.get(JCR_REPOSITORY_ALIAS).toString(); Map map = new TreeMap( repositories); - map.put(alias, repository); + if (map.remove(alias) == null) { + log.warn("No repository was registered with alias " + alias); + return; + } repositories = Collections.unmodifiableMap(map); setChanged(); notifyObservers(alias); diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/JcrKeyring.java b/org.argeo.server.jcr/src/org/argeo/jcr/security/JcrKeyring.java similarity index 98% rename from org.argeo.security.core/src/org/argeo/security/jcr/JcrKeyring.java rename to org.argeo.server.jcr/src/org/argeo/jcr/security/JcrKeyring.java index 1b9f24426..77e969509 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/JcrKeyring.java +++ b/org.argeo.server.jcr/src/org/argeo/jcr/security/JcrKeyring.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.jcr; +package org.argeo.jcr.security; import java.io.ByteArrayInputStream; import java.io.CharArrayReader; @@ -37,8 +37,8 @@ import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; import org.argeo.jcr.UserJcrUtils; -import org.argeo.security.crypto.AbstractKeyring; -import org.argeo.security.crypto.PBEKeySpecCallback; +import org.argeo.util.security.AbstractKeyring; +import org.argeo.util.security.PBEKeySpecCallback; /** JCR based implementation of a keyring */ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { diff --git a/org.argeo.util/build.properties b/org.argeo.util/build.properties index 52f323cda..9a8006a7c 100644 --- a/org.argeo.util/build.properties +++ b/org.argeo.util/build.properties @@ -1,4 +1,6 @@ source.. = src/,\ ext/test/ output.. = bin/ -additional.bundles = org.junit +additional.bundles = org.junit,\ + org.slf4j.commons.logging,\ + org.apache.log4j diff --git a/org.argeo.security.core/ext/test/org/argeo/security/crypto/PasswordBasedEncryptionTest.java b/org.argeo.util/ext/test/org/argeo/util/security/PasswordBasedEncryptionTest.java similarity index 98% rename from org.argeo.security.core/ext/test/org/argeo/security/crypto/PasswordBasedEncryptionTest.java rename to org.argeo.util/ext/test/org/argeo/util/security/PasswordBasedEncryptionTest.java index 6973f5704..42630cfee 100644 --- a/org.argeo.security.core/ext/test/org/argeo/security/crypto/PasswordBasedEncryptionTest.java +++ b/org.argeo.util/ext/test/org/argeo/util/security/PasswordBasedEncryptionTest.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.crypto; +package org.argeo.util.security; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -35,7 +35,7 @@ import junit.framework.TestCase; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.StreamUtils; -import org.argeo.security.crypto.PasswordBasedEncryption; +import org.argeo.util.security.PasswordBasedEncryption; public class PasswordBasedEncryptionTest extends TestCase { private final static Log log = LogFactory diff --git a/org.argeo.security.core/src/org/argeo/security/crypto/AbstractKeyring.java b/org.argeo.util/src/org/argeo/util/security/AbstractKeyring.java similarity index 97% rename from org.argeo.security.core/src/org/argeo/security/crypto/AbstractKeyring.java rename to org.argeo.util/src/org/argeo/util/security/AbstractKeyring.java index daa1ebd12..28763f82b 100644 --- a/org.argeo.security.core/src/org/argeo/security/crypto/AbstractKeyring.java +++ b/org.argeo.util/src/org/argeo/util/security/AbstractKeyring.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.crypto; +package org.argeo.util.security; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -43,15 +43,9 @@ import javax.security.auth.login.LoginException; import org.argeo.ArgeoException; import org.argeo.StreamUtils; -import org.argeo.util.security.Keyring; -import org.bouncycastle.jce.provider.BouncyCastleProvider; /** username / password based keyring. TODO internationalize */ public abstract class AbstractKeyring implements Keyring, CryptoKeyring { - static { - Security.addProvider(new BouncyCastleProvider()); - } - public final static String DEFAULT_KEYRING_LOGIN_CONTEXT = "KEYRING"; private String loginContextName = DEFAULT_KEYRING_LOGIN_CONTEXT; diff --git a/org.argeo.security.core/src/org/argeo/security/crypto/CryptoKeyring.java b/org.argeo.util/src/org/argeo/util/security/CryptoKeyring.java similarity index 91% rename from org.argeo.security.core/src/org/argeo/security/crypto/CryptoKeyring.java rename to org.argeo.util/src/org/argeo/util/security/CryptoKeyring.java index d25eccd22..53ce862f0 100644 --- a/org.argeo.security.core/src/org/argeo/security/crypto/CryptoKeyring.java +++ b/org.argeo.util/src/org/argeo/util/security/CryptoKeyring.java @@ -13,9 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.crypto; +package org.argeo.util.security; -import org.argeo.util.security.Keyring; /** * Advanced keyring based on cryptography that can easily be centralized and diff --git a/org.argeo.security.core/src/org/argeo/security/crypto/KeyringLoginModule.java b/org.argeo.util/src/org/argeo/util/security/KeyringLoginModule.java similarity index 98% rename from org.argeo.security.core/src/org/argeo/security/crypto/KeyringLoginModule.java rename to org.argeo.util/src/org/argeo/util/security/KeyringLoginModule.java index 34b7d4015..11a834c25 100644 --- a/org.argeo.security.core/src/org/argeo/security/crypto/KeyringLoginModule.java +++ b/org.argeo.util/src/org/argeo/util/security/KeyringLoginModule.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.crypto; +package org.argeo.util.security; import java.security.AccessController; import java.util.Map; diff --git a/org.argeo.security.core/src/org/argeo/security/crypto/PBEKeySpecCallback.java b/org.argeo.util/src/org/argeo/util/security/PBEKeySpecCallback.java similarity index 98% rename from org.argeo.security.core/src/org/argeo/security/crypto/PBEKeySpecCallback.java rename to org.argeo.util/src/org/argeo/util/security/PBEKeySpecCallback.java index e96436664..7b3a673bb 100644 --- a/org.argeo.security.core/src/org/argeo/security/crypto/PBEKeySpecCallback.java +++ b/org.argeo.util/src/org/argeo/util/security/PBEKeySpecCallback.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.crypto; +package org.argeo.util.security; import javax.crypto.spec.PBEKeySpec; import javax.security.auth.callback.Callback; diff --git a/org.argeo.security.core/src/org/argeo/security/crypto/PasswordBasedEncryption.java b/org.argeo.util/src/org/argeo/util/security/PasswordBasedEncryption.java similarity index 91% rename from org.argeo.security.core/src/org/argeo/security/crypto/PasswordBasedEncryption.java rename to org.argeo.util/src/org/argeo/util/security/PasswordBasedEncryption.java index aec25ac17..d7866a810 100644 --- a/org.argeo.security.core/src/org/argeo/security/crypto/PasswordBasedEncryption.java +++ b/org.argeo.util/src/org/argeo/util/security/PasswordBasedEncryption.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.security.crypto; +package org.argeo.util.security; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -23,7 +23,6 @@ import java.io.OutputStream; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.Key; -import java.security.Security; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; @@ -34,21 +33,11 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.argeo.ArgeoException; import org.argeo.StreamUtils; -import org.bouncycastle.jce.provider.BouncyCastleProvider; /** Simple password based encryption / decryption */ public class PasswordBasedEncryption { - private final static Log log = LogFactory - .getLog(PasswordBasedEncryption.class); - - static { - Security.addProvider(new BouncyCastleProvider()); - } - public final static Integer DEFAULT_ITERATION_COUNT = 1024; /** Stronger with 256, but causes problem with Oracle JVM */ public final static Integer DEFAULT_SECRETE_KEY_LENGTH = 256; @@ -76,11 +65,7 @@ public class PasswordBasedEncryption { private Cipher ecipher; private Cipher dcipher; - /** - * Default provider is bouncy castle, in order to have consistent behaviour - * across implementations - */ - private String securityProviderName = "BC"; + private String securityProviderName = null; /** * This is up to the caller to clear the passed array. Neither copy of nor @@ -101,8 +86,8 @@ public class PasswordBasedEncryption { } catch (InvalidKeyException e) { Integer previousSecreteKeyLength = secreteKeyLength; secreteKeyLength = DEFAULT_SECRETE_KEY_LENGTH_RESTRICTED; - log.warn("'" + e.getMessage() + "', will use " + secreteKeyLength - + " secrete key length instead of " + System.err.println("'" + e.getMessage() + "', will use " + + secreteKeyLength + " secrete key length instead of " + previousSecreteKeyLength); try { initKeyAndCiphers(password, passwordSalt, initializationVector); @@ -135,7 +120,10 @@ public class PasswordBasedEncryption { } else { key = keyFac.generateSecret(keySpec); } - ecipher = Cipher.getInstance(getCipherName(), securityProviderName); + if (securityProviderName != null) + ecipher = Cipher.getInstance(getCipherName(), securityProviderName); + else + ecipher = Cipher.getInstance(getCipherName()); ecipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); dcipher = Cipher.getInstance(getCipherName()); dcipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); -- 2.30.2