]> git.argeo.org Git - lgpl/argeo-commons.git/blob - NodeSecurity.java
aed824fbdff830b3b21f0cbd7ba22c39e48e6821
[lgpl/argeo-commons.git] / 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 authenticationManagerReg = bundleContext.registerService(
105 AuthenticationManager.class, this, null);
106 Hashtable<String, Object> properties = new Hashtable<String, Object>();
107 // properties.put(KernelConstants.USERADMIN_URI,
108 // userAdmin.asConfigUris());
109 userAdminReg = bundleContext.registerService(UserAdmin.class,
110 userAdmin, properties);
111 }
112
113 void destroy() {
114 authenticationManagerReg.unregister();
115
116 userAdmin.destroy();
117 userAdminReg.unregister();
118
119 // Logout kernel
120 try {
121 LoginContext kernelLc = new LoginContext(
122 KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject);
123 kernelLc.logout();
124 } catch (LoginException e) {
125 throw new CmsException("Cannot log in kernel", e);
126 }
127
128 Security.removeProvider(KernelHeader.SECURITY_PROVIDER);
129 }
130
131 public NodeUserAdmin getUserAdmin() {
132 return userAdmin;
133 }
134
135 public Subject getKernelSubject() {
136 return kernelSubject;
137 }
138
139 @Override
140 public Authentication authenticate(Authentication authentication)
141 throws AuthenticationException {
142 log.error("Authentication manager is deprecated and should not be used.");
143 throw new ProviderNotFoundException(
144 "Authentication manager is deprecated and should not be used.");
145 }
146
147 private void createKeyStoreIfNeeded() {
148 char[] ksPwd = "changeit".toCharArray();
149 char[] keyPwd = Arrays.copyOf(ksPwd, ksPwd.length);
150 File keyStoreFile = new File(KernelUtils.getOsgiInstanceDir(),
151 "node.p12");
152 if (!keyStoreFile.exists()) {
153 try {
154 keyStoreFile.getParentFile().mkdirs();
155 KeyStore keyStore = PkiUtils.getKeyStore(keyStoreFile, ksPwd);
156 PkiUtils.generateSelfSignedCertificate(keyStore,
157 new X500Principal(KernelHeader.ROLE_KERNEL), keyPwd);
158 PkiUtils.saveKeyStore(keyStoreFile, ksPwd, keyStore);
159 } catch (Exception e) {
160 throw new CmsException("Cannot create key store "
161 + keyStoreFile, e);
162 }
163 }
164 }
165 }