1 17 18 package org.apache.tomcat.util.net.jsse; 19 20 import java.io.File ; 21 import java.io.FileInputStream ; 22 import java.io.FileNotFoundException ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.net.InetAddress ; 26 import java.net.ServerSocket ; 27 import java.net.Socket ; 28 import java.net.SocketException ; 29 import java.security.KeyStore ; 30 import java.security.SecureRandom ; 31 import java.security.cert.CRL ; 32 import java.security.cert.CRLException ; 33 import java.security.cert.CertPathParameters ; 34 import java.security.cert.CertStore ; 35 import java.security.cert.CertStoreParameters ; 36 import java.security.cert.CertificateException ; 37 import java.security.cert.CertificateFactory ; 38 import java.security.cert.CollectionCertStoreParameters ; 39 import java.security.cert.PKIXBuilderParameters ; 40 import java.security.cert.X509CertSelector ; 41 import java.util.Collection ; 42 import java.util.Vector ; 43 44 import javax.net.ssl.CertPathTrustManagerParameters; 45 import javax.net.ssl.KeyManager; 46 import javax.net.ssl.KeyManagerFactory; 47 import javax.net.ssl.ManagerFactoryParameters; 48 import javax.net.ssl.SSLContext; 49 import javax.net.ssl.SSLException; 50 import javax.net.ssl.SSLServerSocket; 51 import javax.net.ssl.SSLServerSocketFactory; 52 import javax.net.ssl.SSLSocket; 53 import javax.net.ssl.TrustManager; 54 import javax.net.ssl.TrustManagerFactory; 55 import javax.net.ssl.X509KeyManager; 56 57 import org.apache.tomcat.util.res.StringManager; 58 59 66 67 78 public class JSSESocketFactory 79 extends org.apache.tomcat.util.net.ServerSocketFactory { 80 81 private static StringManager sm = 82 StringManager.getManager("org.apache.tomcat.util.net.jsse.res"); 83 84 static String defaultProtocol = "TLS"; 86 static boolean defaultClientAuth = false; 87 static String defaultKeystoreType = "JKS"; 88 private static final String defaultKeystoreFile 89 = System.getProperty("user.home") + "/.keystore"; 90 private static final String defaultKeyPass = "changeit"; 91 static org.apache.commons.logging.Log log = 92 org.apache.commons.logging.LogFactory.getLog(JSSESocketFactory.class); 93 94 protected boolean initialized; 95 protected String clientAuth = "false"; 96 protected SSLServerSocketFactory sslProxy = null; 97 protected String [] enabledCiphers; 98 99 102 protected boolean requireClientAuth = false; 103 104 107 protected boolean wantClientAuth = false; 108 109 110 public JSSESocketFactory () { 111 } 112 113 public ServerSocket createSocket (int port) 114 throws IOException 115 { 116 if (!initialized) init(); 117 ServerSocket socket = sslProxy.createServerSocket(port); 118 initServerSocket(socket); 119 return socket; 120 } 121 122 public ServerSocket createSocket (int port, int backlog) 123 throws IOException 124 { 125 if (!initialized) init(); 126 ServerSocket socket = sslProxy.createServerSocket(port, backlog); 127 initServerSocket(socket); 128 return socket; 129 } 130 131 public ServerSocket createSocket (int port, int backlog, 132 InetAddress ifAddress) 133 throws IOException 134 { 135 if (!initialized) init(); 136 ServerSocket socket = sslProxy.createServerSocket(port, backlog, 137 ifAddress); 138 initServerSocket(socket); 139 return socket; 140 } 141 142 public Socket acceptSocket(ServerSocket socket) 143 throws IOException 144 { 145 SSLSocket asock = null; 146 try { 147 asock = (SSLSocket)socket.accept(); 148 configureClientAuth(asock); 149 } catch (SSLException e){ 150 throw new SocketException ("SSL handshake error" + e.toString()); 151 } 152 return asock; 153 } 154 155 public void handshake(Socket sock) throws IOException { 156 ((SSLSocket)sock).startHandshake(); 157 } 158 159 168 protected String [] getEnabledCiphers(String requestedCiphers, 169 String [] supportedCiphers) { 170 171 String [] enabledCiphers = null; 172 173 if (requestedCiphers != null) { 174 Vector vec = null; 175 String cipher = requestedCiphers; 176 int index = requestedCiphers.indexOf(','); 177 if (index != -1) { 178 int fromIndex = 0; 179 while (index != -1) { 180 cipher = requestedCiphers.substring(fromIndex, index).trim(); 181 if (cipher.length() > 0) { 182 186 for (int i=0; supportedCiphers != null 187 && i<supportedCiphers.length; i++) { 188 if (supportedCiphers[i].equals(cipher)) { 189 if (vec == null) { 190 vec = new Vector (); 191 } 192 vec.addElement(cipher); 193 break; 194 } 195 } 196 } 197 fromIndex = index+1; 198 index = requestedCiphers.indexOf(',', fromIndex); 199 } cipher = requestedCiphers.substring(fromIndex); 201 } 202 203 if (cipher != null) { 204 cipher = cipher.trim(); 205 if (cipher.length() > 0) { 206 210 for (int i=0; supportedCiphers != null 211 && i<supportedCiphers.length; i++) { 212 if (supportedCiphers[i].equals(cipher)) { 213 if (vec == null) { 214 vec = new Vector (); 215 } 216 vec.addElement(cipher); 217 break; 218 } 219 } 220 } 221 } 222 223 if (vec != null) { 224 enabledCiphers = new String [vec.size()]; 225 vec.copyInto(enabledCiphers); 226 } 227 } else { 228 enabledCiphers = sslProxy.getDefaultCipherSuites(); 229 } 230 231 return enabledCiphers; 232 } 233 234 237 protected String getKeystorePassword() { 238 String keyPass = (String )attributes.get("keypass"); 239 if (keyPass == null) { 240 keyPass = defaultKeyPass; 241 } 242 String keystorePass = (String )attributes.get("keystorePass"); 243 if (keystorePass == null) { 244 keystorePass = keyPass; 245 } 246 return keystorePass; 247 } 248 249 252 protected KeyStore getKeystore(String type, String pass) 253 throws IOException { 254 255 String keystoreFile = (String )attributes.get("keystore"); 256 if (keystoreFile == null) 257 keystoreFile = defaultKeystoreFile; 258 259 return getStore(type, keystoreFile, pass); 260 } 261 262 265 protected KeyStore getTrustStore(String keystoreType) throws IOException { 266 KeyStore trustStore = null; 267 268 String trustStoreFile = (String )attributes.get("truststoreFile"); 269 if(trustStoreFile == null) { 270 trustStoreFile = System.getProperty("javax.net.ssl.trustStore"); 271 } 272 if(log.isDebugEnabled()) { 273 log.debug("Truststore = " + trustStoreFile); 274 } 275 String trustStorePassword = (String )attributes.get("truststorePass"); 276 if( trustStorePassword == null) { 277 trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword"); 278 } 279 if( trustStorePassword == null ) { 280 trustStorePassword = getKeystorePassword(); 281 } 282 if(log.isDebugEnabled()) { 283 log.debug("TrustPass = " + trustStorePassword); 284 } 285 String truststoreType = (String )attributes.get("truststoreType"); 286 if(truststoreType == null) { 287 truststoreType = keystoreType; 288 } 289 if(log.isDebugEnabled()) { 290 log.debug("trustType = " + truststoreType); 291 } 292 if (trustStoreFile != null && trustStorePassword != null){ 293 trustStore = getStore(truststoreType, trustStoreFile, 294 trustStorePassword); 295 } 296 297 return trustStore; 298 } 299 300 303 private KeyStore getStore(String type, String path, String pass) 304 throws IOException { 305 306 KeyStore ks = null; 307 InputStream istream = null; 308 try { 309 ks = KeyStore.getInstance(type); 310 if(! "PKCS11".equalsIgnoreCase(type) ) { 311 File keyStoreFile = new File (path); 312 if (!keyStoreFile.isAbsolute()) { 313 keyStoreFile = new File (System.getProperty("catalina.base"), 314 path); 315 } 316 istream = new FileInputStream (keyStoreFile); 317 } 318 319 ks.load(istream, pass.toCharArray()); 320 } catch (FileNotFoundException fnfe) { 321 throw fnfe; 322 } catch (IOException ioe) { 323 throw ioe; 324 } catch(Exception ex) { 325 log.error("Exception trying to load keystore " +path,ex); 326 throw new IOException ("Exception trying to load keystore " + 327 path + ": " + ex.getMessage() ); 328 } finally { 329 if (istream != null) { 330 try { 331 istream.close(); 332 } catch (IOException ioe) { 333 } 335 } 336 } 337 338 return ks; 339 } 340 341 344 void init() throws IOException { 345 try { 346 347 String clientAuthStr = (String ) attributes.get("clientauth"); 348 if("true".equalsIgnoreCase(clientAuthStr) || 349 "yes".equalsIgnoreCase(clientAuthStr)) { 350 requireClientAuth = true; 351 } else if("want".equalsIgnoreCase(clientAuthStr)) { 352 wantClientAuth = true; 353 } 354 355 String protocol = (String ) attributes.get("protocol"); 357 if (protocol == null) { 358 protocol = defaultProtocol; 359 } 360 361 String algorithm = (String ) attributes.get("algorithm"); 363 if (algorithm == null) { 364 algorithm = KeyManagerFactory.getDefaultAlgorithm();; 365 } 366 367 String keystoreType = (String ) attributes.get("keystoreType"); 368 if (keystoreType == null) { 369 keystoreType = defaultKeystoreType; 370 } 371 372 String trustAlgorithm = (String )attributes.get("truststoreAlgorithm"); 373 if( trustAlgorithm == null ) { 374 trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 375 } 376 SSLContext context = SSLContext.getInstance(protocol); 378 context.init(getKeyManagers(keystoreType, algorithm, 379 (String ) attributes.get("keyAlias")), 380 getTrustManagers(keystoreType, trustAlgorithm), 381 new SecureRandom ()); 382 383 sslProxy = context.getServerSocketFactory(); 385 386 String requestedCiphers = (String )attributes.get("ciphers"); 388 enabledCiphers = getEnabledCiphers(requestedCiphers, 389 sslProxy.getSupportedCipherSuites()); 390 391 } catch(Exception e) { 392 if( e instanceof IOException ) 393 throw (IOException )e; 394 throw new IOException (e.getMessage()); 395 } 396 } 397 398 401 protected KeyManager[] getKeyManagers(String keystoreType, 402 String algorithm, 403 String keyAlias) 404 throws Exception { 405 406 KeyManager[] kms = null; 407 408 String keystorePass = getKeystorePassword(); 409 410 KeyStore ks = getKeystore(keystoreType, keystorePass); 411 if (keyAlias != null && !ks.isKeyEntry(keyAlias)) { 412 throw new IOException (sm.getString("jsse.alias_no_key_entry", keyAlias)); 413 } 414 415 KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); 416 kmf.init(ks, keystorePass.toCharArray()); 417 418 kms = kmf.getKeyManagers(); 419 if (keyAlias != null) { 420 if (JSSESocketFactory.defaultKeystoreType.equals(keystoreType)) { 421 keyAlias = keyAlias.toLowerCase(); 422 } 423 for(int i=0; i<kms.length; i++) { 424 kms[i] = new JSSEKeyManager((X509KeyManager)kms[i], keyAlias); 425 } 426 } 427 428 return kms; 429 } 430 431 434 protected TrustManager[] getTrustManagers(String keystoreType, String algorithm) 435 throws Exception { 436 String crlf = (String ) attributes.get("crlFile"); 437 438 TrustManager[] tms = null; 439 440 String truststoreType = (String ) attributes.get("truststoreType"); 441 if (truststoreType == null) { 442 truststoreType = keystoreType; 443 } 444 KeyStore trustStore = getTrustStore(truststoreType); 445 if (trustStore != null) { 446 if (crlf == null) { 447 TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); 448 tmf.init(trustStore); 449 tms = tmf.getTrustManagers(); 450 } else { 451 TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); 452 CertPathParameters params = getParameters(algorithm, crlf, trustStore); 453 ManagerFactoryParameters mfp = new CertPathTrustManagerParameters(params); 454 tmf.init(mfp); 455 tms = tmf.getTrustManagers(); 456 } 457 } 458 459 return tms; 460 } 461 462 471 protected CertPathParameters getParameters(String algorithm, 472 String crlf, 473 KeyStore trustStore) 474 throws Exception { 475 CertPathParameters params = null; 476 if("PKIX".equalsIgnoreCase(algorithm)) { 477 PKIXBuilderParameters xparams = new PKIXBuilderParameters (trustStore, 478 new X509CertSelector ()); 479 Collection crls = getCRLs(crlf); 480 CertStoreParameters csp = new CollectionCertStoreParameters (crls); 481 CertStore store = CertStore.getInstance("Collection", csp); 482 xparams.addCertStore(store); 483 xparams.setRevocationEnabled(true); 484 String trustLength = (String )attributes.get("trustMaxCertLength"); 485 if(trustLength != null) { 486 try { 487 xparams.setMaxPathLength(Integer.parseInt(trustLength)); 488 } catch(Exception ex) { 489 log.warn("Bad maxCertLength: "+trustLength); 490 } 491 } 492 493 params = xparams; 494 } else { 495 throw new CRLException ("CRLs not supported for type: "+algorithm); 496 } 497 return params; 498 } 499 500 501 505 protected Collection <? extends CRL > getCRLs(String crlf) 506 throws IOException , CRLException , CertificateException { 507 508 File crlFile = new File (crlf); 509 if( !crlFile.isAbsolute() ) { 510 crlFile = new File (System.getProperty("catalina.base"), crlf); 511 } 512 Collection <? extends CRL > crls = null; 513 InputStream is = null; 514 try { 515 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 516 is = new FileInputStream (crlFile); 517 crls = cf.generateCRLs(is); 518 } catch(IOException iex) { 519 throw iex; 520 } catch(CRLException crle) { 521 throw crle; 522 } catch(CertificateException ce) { 523 throw ce; 524 } finally { 525 if(is != null) { 526 try{ 527 is.close(); 528 } catch(Exception ex) { 529 } 530 } 531 } 532 return crls; 533 } 534 535 540 protected void setEnabledProtocols(SSLServerSocket socket, String []protocols){ 541 if (protocols != null) { 542 socket.setEnabledProtocols(protocols); 543 } 544 } 545 546 556 protected String [] getEnabledProtocols(SSLServerSocket socket, 557 String requestedProtocols){ 558 String [] supportedProtocols = socket.getSupportedProtocols(); 559 560 String [] enabledProtocols = null; 561 562 if (requestedProtocols != null) { 563 Vector vec = null; 564 String protocol = requestedProtocols; 565 int index = requestedProtocols.indexOf(','); 566 if (index != -1) { 567 int fromIndex = 0; 568 while (index != -1) { 569 protocol = requestedProtocols.substring(fromIndex, index).trim(); 570 if (protocol.length() > 0) { 571 575 for (int i=0; supportedProtocols != null 576 && i<supportedProtocols.length; i++) { 577 if (supportedProtocols[i].equals(protocol)) { 578 if (vec == null) { 579 vec = new Vector (); 580 } 581 vec.addElement(protocol); 582 break; 583 } 584 } 585 } 586 fromIndex = index+1; 587 index = requestedProtocols.indexOf(',', fromIndex); 588 } protocol = requestedProtocols.substring(fromIndex); 590 } 591 592 if (protocol != null) { 593 protocol = protocol.trim(); 594 if (protocol.length() > 0) { 595 599 for (int i=0; supportedProtocols != null 600 && i<supportedProtocols.length; i++) { 601 if (supportedProtocols[i].equals(protocol)) { 602 if (vec == null) { 603 vec = new Vector (); 604 } 605 vec.addElement(protocol); 606 break; 607 } 608 } 609 } 610 } 611 612 if (vec != null) { 613 enabledProtocols = new String [vec.size()]; 614 vec.copyInto(enabledProtocols); 615 } 616 } 617 618 return enabledProtocols; 619 } 620 621 627 protected void configureClientAuth(SSLServerSocket socket){ 628 if (wantClientAuth){ 629 socket.setWantClientAuth(wantClientAuth); 630 } else { 631 socket.setNeedClientAuth(requireClientAuth); 632 } 633 } 634 635 641 protected void configureClientAuth(SSLSocket socket){ 642 } 645 646 650 private void initServerSocket(ServerSocket ssocket) { 651 652 SSLServerSocket socket = (SSLServerSocket) ssocket; 653 654 if (enabledCiphers != null) { 655 socket.setEnabledCipherSuites(enabledCiphers); 656 } 657 658 String requestedProtocols = (String ) attributes.get("protocols"); 659 setEnabledProtocols(socket, getEnabledProtocols(socket, 660 requestedProtocols)); 661 662 configureClientAuth(socket); 665 } 666 667 } 668 | Popular Tags |