]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java
Improve social networking
[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 static org.argeo.cms.internal.kernel.KernelUtils.getOsgiInstanceDir;
4
5 import java.io.File;
6 import java.io.IOException;
7 import java.net.URL;
8 import java.security.KeyStore;
9 import java.security.Provider;
10 import java.security.Security;
11 import java.util.Arrays;
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.auth.AuthConstants;
27 import org.bouncycastle.jce.provider.BouncyCastleProvider;
28
29 /** Low-level kernel security */
30 class NodeSecurity implements KernelConstants {
31 public final static int HARDENED = 3;
32 public final static int STAGING = 2;
33 public final static int DEV = 1;
34
35 private final boolean firstInit;
36
37 private final Subject kernelSubject;
38 private int securityLevel = STAGING;
39
40 private final File keyStoreFile;
41
42 public NodeSecurity() {
43 // Configure JAAS first
44 URL url = getClass().getClassLoader().getResource(
45 KernelConstants.JAAS_CONFIG);
46 System.setProperty("java.security.auth.login.config",
47 url.toExternalForm());
48 // log.debug("JASS config: " + url.toExternalForm());
49 // disable Jetty autostart
50 // System.setProperty("org.eclipse.equinox.http.jetty.autostart",
51 // "false");
52
53 firstInit = !new File(getOsgiInstanceDir(), DIR_NODE).exists();
54
55 this.keyStoreFile = new File(KernelUtils.getOsgiInstanceDir(),
56 "node.p12");
57 this.kernelSubject = logInKernel();
58 }
59
60 private Subject logInKernel() {
61 final Subject kernelSubject = new Subject();
62 createKeyStoreIfNeeded();
63
64 CallbackHandler cbHandler = new CallbackHandler() {
65
66 @Override
67 public void handle(Callback[] callbacks) throws IOException,
68 UnsupportedCallbackException {
69 // alias
70 ((NameCallback) callbacks[1])
71 .setName(AuthConstants.ROLE_KERNEL);
72 // store pwd
73 ((PasswordCallback) callbacks[2]).setPassword("changeit"
74 .toCharArray());
75 // key pwd
76 ((PasswordCallback) callbacks[3]).setPassword("changeit"
77 .toCharArray());
78 }
79 };
80 try {
81 LoginContext kernelLc = new LoginContext(
82 KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject,
83 cbHandler);
84 kernelLc.login();
85 } catch (LoginException e) {
86 throw new CmsException("Cannot log in kernel", e);
87 }
88 return kernelSubject;
89 }
90
91 void destroy() {
92 // Logout kernel
93 try {
94 LoginContext kernelLc = new LoginContext(
95 KernelConstants.LOGIN_CONTEXT_KERNEL, kernelSubject);
96 kernelLc.logout();
97 } catch (LoginException e) {
98 throw new CmsException("Cannot log out kernel", e);
99 }
100
101 Security.removeProvider(SECURITY_PROVIDER);
102 }
103
104 public Subject getKernelSubject() {
105 return kernelSubject;
106 }
107
108 public synchronized int getSecurityLevel() {
109 return securityLevel;
110 }
111
112 public boolean isFirstInit() {
113 return firstInit;
114 }
115
116 public void setSecurityLevel(int newValue) {
117 if (newValue != STAGING || newValue != DEV)
118 throw new CmsException("Invalid value for security level "
119 + newValue);
120 if (newValue >= securityLevel)
121 throw new CmsException(
122 "Impossible to increase security level (from "
123 + securityLevel + " to " + newValue + ")");
124 securityLevel = newValue;
125 }
126
127 private void createKeyStoreIfNeeded() {
128 char[] ksPwd = "changeit".toCharArray();
129 char[] keyPwd = Arrays.copyOf(ksPwd, ksPwd.length);
130 if (!keyStoreFile.exists()) {
131 try {
132 keyStoreFile.getParentFile().mkdirs();
133 KeyStore keyStore = PkiUtils.getKeyStore(keyStoreFile, ksPwd);
134 PkiUtils.generateSelfSignedCertificate(keyStore,
135 new X500Principal(AuthConstants.ROLE_KERNEL), keyPwd);
136 PkiUtils.saveKeyStore(keyStoreFile, ksPwd, keyStore);
137 } catch (Exception e) {
138 throw new CmsException("Cannot create key store "
139 + keyStoreFile, e);
140 }
141 }
142 }
143
144 File getHttpServerKeyStore() {
145 return keyStoreFile;
146 }
147
148 private final static String SECURITY_PROVIDER = "BC";// Bouncy Castle
149 private final static Log log;
150 static {
151 log = LogFactory.getLog(NodeSecurity.class);
152 // Make Bouncy Castle the default provider
153 Provider provider = new BouncyCastleProvider();
154 int position = Security.insertProviderAt(provider, 1);
155 if (position == -1)
156 log.error("Provider " + provider.getName()
157 + " already installed and could not be set as default");
158 Provider defaultProvider = Security.getProviders()[0];
159 if (!defaultProvider.getName().equals(SECURITY_PROVIDER))
160 log.error("Provider name is " + defaultProvider.getName()
161 + " but it should be " + SECURITY_PROVIDER);
162 }
163 }