Changeset 7343 in josm for trunk/src/org/openstreetmap/josm/io
- Timestamp:
- 2014-07-28T16:40:19+02:00 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControlHttpsServer.java
r7338 r7343 21 21 import java.security.KeyPairGenerator; 22 22 import java.security.KeyStore; 23 import java.security.KeyStoreException; 23 24 import java.security.NoSuchAlgorithmException; 24 25 import java.security.PrivateKey; 25 26 import java.security.SecureRandom; 26 27 import java.security.cert.Certificate; 28 import java.security.cert.CertificateException; 27 29 import java.security.cert.X509Certificate; 28 30 import java.util.Arrays; … … 91 93 * @since 7335 92 94 */ 93 public StringProperty KEYSTORE_PASSWORD = new StringProperty("remotecontrol.https.keystore.password", "");95 public static final StringProperty KEYSTORE_PASSWORD = new StringProperty("remotecontrol.https.keystore.password", ""); 94 96 95 97 /** … … 97 99 * @since 7335 98 100 */ 99 public StringProperty KEYENTRY_PASSWORD = new StringProperty("remotecontrol.https.keyentry.password", ""); 101 public static final StringProperty KEYENTRY_PASSWORD = new StringProperty("remotecontrol.https.keyentry.password", ""); 102 103 /** 104 * Unique alias used to store JOSM localhost entry, both in JOSM keystore and system/browser keystores. 105 * @since 7343 106 */ 107 public static final String ENTRY_ALIAS = "josm_localhost"; 100 108 101 109 /** … … 194 202 } 195 203 204 /** 205 * Setup the JOSM internal keystore, used to store HTTPS certificate and private key. 206 * @return Path to the (initialized) JOSM keystore 207 * @throws IOException if an I/O error occurs 208 * @throws GeneralSecurityException if a security error occurs 209 * @since 7343 210 */ 211 public static Path setupJosmKeystore() throws IOException, GeneralSecurityException { 212 213 char[] storePassword = KEYSTORE_PASSWORD.get().toCharArray(); 214 char[] entryPassword = KEYENTRY_PASSWORD.get().toCharArray(); 215 216 Path dir = Paths.get(RemoteControl.getRemoteControlDir()); 217 Path path = dir.resolve(KEYSTORE_FILENAME); 218 Files.createDirectories(dir); 219 220 if (!Files.exists(path)) { 221 Main.debug("No keystore found, creating a new one"); 222 223 // Create new keystore like previous one generated with JDK keytool as follows: 224 // keytool -genkeypair -storepass josm_ssl -keypass josm_ssl -alias josm_localhost -dname "CN=localhost, OU=JOSM, O=OpenStreetMap" 225 // -ext san=ip:127.0.0.1 -keyalg RSA -validity 1825 226 227 KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); 228 generator.initialize(2048); 229 KeyPair pair = generator.generateKeyPair(); 230 231 X509Certificate cert = generateCertificate("CN=localhost, OU=JOSM, O=OpenStreetMap", pair, 1825, "SHA256withRSA", 232 "dns:localhost,ip:127.0.0.1,ip:::1,uri:https://127.0.0.1:"+HTTPS_PORT+",uri:https://::1:"+HTTPS_PORT); 233 234 KeyStore ks = KeyStore.getInstance("JKS"); 235 ks.load(null, null); 236 237 // Generate new passwords. See https://stackoverflow.com/a/41156/2257172 238 SecureRandom random = new SecureRandom(); 239 KEYSTORE_PASSWORD.put(new BigInteger(130, random).toString(32)); 240 KEYENTRY_PASSWORD.put(new BigInteger(130, random).toString(32)); 241 242 storePassword = KEYSTORE_PASSWORD.get().toCharArray(); 243 entryPassword = KEYENTRY_PASSWORD.get().toCharArray(); 244 245 ks.setKeyEntry(ENTRY_ALIAS, pair.getPrivate(), entryPassword, new Certificate[]{cert}); 246 ks.store(Files.newOutputStream(path, StandardOpenOption.CREATE), storePassword); 247 } 248 return path; 249 } 250 251 /** 252 * Loads the JOSM keystore. 253 * @return the (initialized) JOSM keystore 254 * @throws IOException if an I/O error occurs 255 * @throws GeneralSecurityException if a security error occurs 256 * @since 7343 257 */ 258 public static KeyStore loadJosmKeystore() throws IOException, GeneralSecurityException { 259 try (InputStream in = Files.newInputStream(setupJosmKeystore())) { 260 KeyStore ks = KeyStore.getInstance("JKS"); 261 ks.load(in, KEYSTORE_PASSWORD.get().toCharArray()); 262 263 if (Main.isDebugEnabled()) { 264 for (Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements();) { 265 Main.debug("Alias in JOSM keystore: "+aliases.nextElement()); 266 } 267 } 268 return ks; 269 } 270 } 271 196 272 private void initialize() { 197 273 if (!initOK) { 198 274 try { 199 char[] storePassword = KEYSTORE_PASSWORD.get().toCharArray(); 200 char[] entryPassword = KEYENTRY_PASSWORD.get().toCharArray(); 201 202 Path dir = Paths.get(RemoteControl.getRemoteControlDir()); 203 Path path = dir.resolve(KEYSTORE_FILENAME); 204 Files.createDirectories(dir); 205 206 if (!Files.exists(path)) { 207 Main.debug("No keystore found, creating a new one"); 208 209 // Create new keystore like previous one generated with JDK keytool as follows: 210 // keytool -genkeypair -storepass josm_ssl -keypass josm_ssl -alias josm_localhost -dname "CN=localhost, OU=JOSM, O=OpenStreetMap" 211 // -ext san=ip:127.0.0.1 -keyalg RSA -validity 1825 212 213 KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); 214 generator.initialize(2048); 215 KeyPair pair = generator.generateKeyPair(); 216 217 X509Certificate cert = generateCertificate("CN=localhost, OU=JOSM, O=OpenStreetMap", pair, 1825, "SHA256withRSA", 218 "dns:localhost,ip:127.0.0.1,ip:::1,uri:https://127.0.0.1:"+HTTPS_PORT+",uri:https://::1:"+HTTPS_PORT); 219 220 KeyStore ks = KeyStore.getInstance("JKS"); 221 ks.load(null, null); 222 223 // Generate new passwords. See https://stackoverflow.com/a/41156/2257172 224 SecureRandom random = new SecureRandom(); 225 KEYSTORE_PASSWORD.put(new BigInteger(130, random).toString(32)); 226 KEYENTRY_PASSWORD.put(new BigInteger(130, random).toString(32)); 227 228 storePassword = KEYSTORE_PASSWORD.get().toCharArray(); 229 entryPassword = KEYENTRY_PASSWORD.get().toCharArray(); 230 231 ks.setKeyEntry("josm_localhost", pair.getPrivate(), entryPassword, new Certificate[]{cert}); 232 ks.store(Files.newOutputStream(path, StandardOpenOption.CREATE), storePassword); 233 } 234 235 try (InputStream in = Files.newInputStream(path)) { 236 // Load keystore 237 KeyStore ks = KeyStore.getInstance("JKS"); 238 ks.load(in, storePassword); 239 240 if (Main.isDebugEnabled()) { 241 for (Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements();) { 242 Main.debug("Alias in keystore: "+aliases.nextElement()); 243 } 244 } 245 246 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 247 kmf.init(ks, entryPassword); 248 249 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 250 tmf.init(ks); 251 252 sslContext = SSLContext.getInstance("TLS"); 253 sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 254 255 if (Main.isTraceEnabled()) { 256 Main.trace("SSL Context protocol: " + sslContext.getProtocol()); 257 Main.trace("SSL Context provider: " + sslContext.getProvider()); 258 } 259 260 Enumeration<String> aliases = ks.aliases(); 261 if (aliases.hasMoreElements()) { 262 Main.platform.setupHttpsCertificate(new KeyStore.TrustedCertificateEntry(ks.getCertificate(aliases.nextElement()))); 263 } 264 265 initOK = true; 266 } 275 KeyStore ks = loadJosmKeystore(); 276 277 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 278 kmf.init(ks, KEYENTRY_PASSWORD.get().toCharArray()); 279 280 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 281 tmf.init(ks); 282 283 sslContext = SSLContext.getInstance("TLS"); 284 sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 285 286 if (Main.isTraceEnabled()) { 287 Main.trace("SSL Context protocol: " + sslContext.getProtocol()); 288 Main.trace("SSL Context provider: " + sslContext.getProvider()); 289 } 290 291 setupPlatform(ks); 292 293 initOK = true; 267 294 } catch (IOException | GeneralSecurityException e) { 268 295 Main.error(e); 269 296 } 270 297 } 298 } 299 300 /** 301 * Setup the platform-dependant certificate stuff. 302 * @param josmKs The JOSM keystore, containing localhost certificate and private key. 303 * @return {@code true} if something has changed as a result of the call (certificate installation, etc.) 304 * @throws KeyStoreException if the keystore has not been initialized (loaded) 305 * @throws NoSuchAlgorithmException in case of error 306 * @throws CertificateException in case of error 307 * @throws IOException in case of error 308 * @since 7343 309 */ 310 public static boolean setupPlatform(KeyStore josmKs) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { 311 Enumeration<String> aliases = josmKs.aliases(); 312 if (aliases.hasMoreElements()) { 313 return Main.platform.setupHttpsCertificate(ENTRY_ALIAS, 314 new KeyStore.TrustedCertificateEntry(josmKs.getCertificate(aliases.nextElement()))); 315 } 316 return false; 271 317 } 272 318
Note:
See TracChangeset
for help on using the changeset viewer.