]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java
Factorize indexed properties, thus fixing issue when creating a new user.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / kernel / NodeSecurity.java
1 package org.argeo.cms.internal.kernel;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.net.URL;
6 import java.nio.file.ProviderNotFoundException;
7 import java.security.KeyStore;
8 import java.security.Provider;
9 import java.security.Security;
10 import java.util.Arrays;
11 import java.util.Hashtable;
12
13 import javax.security.auth.Subject;
14 import javax.security.auth.callback.Callback;
15 import javax.security.auth.callback.CallbackHandler;
16 import javax.security.auth.callback.NameCallback;
17 import javax.security.auth.callback.PasswordCallback;
18 import javax.security.auth.callback.UnsupportedCallbackException;
19 import javax.security.auth.login.LoginContext;
20 import javax.security.auth.login.LoginException;
21 import javax.security.auth.x500.X500Principal;
22
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.argeo.cms.CmsException;
26 import org.argeo.cms.KernelHeader;
27 import org.argeo.security.crypto.PkiUtils;
28 import org.bouncycastle.jce.provider.BouncyCastleProvider;
29 import org.osgi.framework.BundleContext;
30 import org.osgi.framework.ServiceRegistration;
31 import org.osgi.service.useradmin.UserAdmin;
32 import org.springframework.security.authentication.AuthenticationManager;
33 import org.springframework.security.core.Authentication;
34 import org.springframework.security.core.AuthenticationException;
35
36 /** Authentication and user management. */
37 class NodeSecurity implements AuthenticationManager {
38 private final static Log log;
39 static {
40 log = LogFactory.getLog(NodeSecurity.class);
41 // Make Bouncy Castle the default provider
42 Provider provider = new BouncyCastleProvider();
43 int position = Security.insertProviderAt(provider, 1);
44 if (position == -1)
45 log.error("Provider " + provider.getName()
46 + " already installed and could not be set as default");
47 Provider defaultProvider = Security.getProviders()[0];
48 if (!defaultProvider.getName().equals(KernelHeader.SECURITY_PROVIDER))
49 log.error("Provider name is " + defaultProvider.getName()
50 + " but it should be " + KernelHeader.SECURITY_PROVIDER);
51 }
52
53 private final BundleContext bundleContext;
54 private final NodeUserAdmin userAdmin;
55 private final Subject kernelSubject;
56
57 private ServiceRegistration<AuthenticationManager> authenticationManagerReg;
58
59 private ServiceRegistration<UserAdmin> userAdminReg;
60
61 public NodeSecurity(BundleContext bundleContext) {
62 // Configure JAAS first
63 URL url = getClass().getClassLoader().getResource(
64 KernelConstants.JAAS_CONFIG);
65 System.setProperty("java.security.auth.login.config",
66 url.toExternalForm());
67
68 this.bundleContext = bundleContext;
69 this.kernelSubject = logKernel();
70 userAdmin = new NodeUserAdmin();
71 }
72
73 private Subject logKernel() {
74 final Subject kernelSubject = new Subject();
75 createKeyStoreIfNeeded();
76
77 CallbackHandler cbHandler = new CallbackHandler() {
78
79 @Override
80 public void handle(Callback[] callbacks) throws IOException,
81 UnsupportedCallbackException {
82 // alias
83 ((NameCallback) callbacks[1]).setName(KernelHeader.ROLE_KERNEL);
84 // store pwd
85 ((PasswordCallback) callbacks[2]).setPassword("changeit"
86 .toCharArray());
87 // key pwd
88 ((PasswordCallback) callbacks[3]).setPassword("changeit"
89 .toCharArray());
90 }
91 };
92 try {
93 LoginContext kernelLc = new LoginContext(
94 KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject,
95 cbHandler);
96 kernelLc.login();
97 } catch (LoginException e) {
98 throw new CmsException("Cannot log in kernel", e);
99 }
100 return kernelSubject;
101 }
102
103 public void publish() {
104 userAdminReg = bundleContext.registerService(UserAdmin.class,
105 userAdmin, userAdmin.currentState());
106 // dummy auth manager, in order to smooth transition from Argeo 1
107 authenticationManagerReg = bundleContext.registerService(
108 AuthenticationManager.class, this, null);
109 }
110
111 void destroy() {
112 authenticationManagerReg.unregister();
113
114 userAdmin.destroy();
115 userAdminReg.unregister();
116
117 // Logout kernel
118 try {
119 LoginContext kernelLc = new LoginContext(
120 KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject);
121 kernelLc.logout();
122 } catch (LoginException e) {
123 throw new CmsException("Cannot log in kernel", e);
124 }
125
126 Security.removeProvider(KernelHeader.SECURITY_PROVIDER);
127 }
128
129 public NodeUserAdmin getUserAdmin() {
130 return userAdmin;
131 }
132
133 public Subject getKernelSubject() {
134 return kernelSubject;
135 }
136
137 @Override
138 public Authentication authenticate(Authentication authentication)
139 throws AuthenticationException {
140 log.error("Authentication manager is deprecated and should not be used.");
141 throw new ProviderNotFoundException(
142 "Authentication manager is deprecated and should not be used.");
143 }
144
145 private void createKeyStoreIfNeeded() {
146 char[] ksPwd = "changeit".toCharArray();
147 char[] keyPwd = Arrays.copyOf(ksPwd, ksPwd.length);
148 File keyStoreFile = new File(KernelUtils.getOsgiInstanceDir(),
149 "node.p12");
150 if (!keyStoreFile.exists()) {
151 try {
152 keyStoreFile.getParentFile().mkdirs();
153 KeyStore keyStore = PkiUtils.getKeyStore(keyStoreFile, ksPwd);
154 PkiUtils.generateSelfSignedCertificate(keyStore,
155 new X500Principal(KernelHeader.ROLE_KERNEL), keyPwd);
156 PkiUtils.saveKeyStore(keyStoreFile, ksPwd, keyStore);
157 } catch (Exception e) {
158 throw new CmsException("Cannot create key store "
159 + keyStoreFile, e);
160 }
161 }
162 }
163 }