5050
5151/**
5252 * wolfSSL implementation of X509TrustManager, extends
53- * X509ExtendedTrustManager for additional hostname verification for HTTPS.
53+ * X509ExtendedTrustManager for additional hostname verification for
54+ * HTTPS (RFC 2818) and LDAPS (RFC 2830).
5455 *
5556 * @author wolfSSL
5657 */
@@ -59,6 +60,11 @@ public final class WolfSSLTrustX509 extends X509ExtendedTrustManager
5960
6061 private KeyStore store = null ;
6162
63+ /** X509ExtendedTrustManager hostname type HTTPS */
64+ private static int HOSTNAME_TYPE_HTTPS = 1 ;
65+ /** X509ExtendedTrustManager hostname type LDAPS */
66+ private static int HOSTNAME_TYPE_LDAPS = 2 ;
67+
6268 /**
6369 * Create new WolfSSLTrustX509 object
6470 *
@@ -430,18 +436,25 @@ private List<X509Certificate> certManagerVerify(
430436 }
431437
432438 /**
433- * Verify hostname using HTTPS verification method.
439+ * Verify hostname using HTTPS or LDAPS verification method.
434440 *
435- * This method does the following operations in an attempt to verify
436- * the HTTPS type hostname:
441+ * For HTTPS hostname verification (RFC 2818):
437442 *
438- * 1. If SNI name has been received during TLS handshake, try to
443+ * - If SNI name has been received during TLS handshake, try to
439444 * first verify peer certificate against that. Skip this step when
440445 * on server side verifying the client, since server does not set
441446 * an SNI for the client.
442- * 2. Otherwise, try to verify certificate against SSLSocket
443- * hostname (SSLSession.getHostName()).
444- * 3. If both of the above fail, fail hostname verification.
447+ * - Otherwise, try to verify certificate against SSLSocket or SSLEngine
448+ * hostname (getHandshakeSession().getHostName()).
449+ * - If both of the above fail, fail hostname verification.
450+ * - Hostname matching rules for HTTPS come from RFC 2818
451+ *
452+ * For LDAPS hostname verification (RFC 2830):
453+ *
454+ * - Try to verify certificate against hostname used to create
455+ * the SSLSocket or SSLEngine, obtained via
456+ * getHandshakeSession().getPeerHost().
457+ * - Hostname matching rules for LDAPS come from RFC 2830
445458 *
446459 * @param cert peer certificate
447460 * @param socket SSLSocket associated with connection to peer. Only one
@@ -452,10 +465,13 @@ private List<X509Certificate> certManagerVerify(
452465 * null.
453466 * @param isClient true if we are calling this from client side, otherwise
454467 * false if calling from server side.
468+ * @param type type of hostname to verify, options are
469+ * HOSTNAME_TYPE_HTTPS or HOSTNAME_TYPE_LDAPS
455470 * @throws CertificateException if hostname cannot be verified
456471 */
457- private void verifyHTTPSHostname (X509Certificate cert , SSLSocket socket ,
458- SSLEngine engine , boolean isClient ) throws CertificateException {
472+ private void verifyHostnameByType (X509Certificate cert , SSLSocket socket ,
473+ SSLEngine engine , boolean isClient , int type )
474+ throws CertificateException {
459475
460476 String peerHost = null ;
461477 List <SNIServerName > sniNames = null ;
@@ -464,8 +480,16 @@ private void verifyHTTPSHostname(X509Certificate cert, SSLSocket socket,
464480 WolfSSLCertificate peerCert = null ;
465481 int ret = WolfSSL .SSL_FAILURE ;
466482
467- WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
468- "verifying HTTPS hostname" );
483+ if (type == HOSTNAME_TYPE_HTTPS ) {
484+ WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
485+ "verifying hostname type HTTPS" );
486+ } else if (type == HOSTNAME_TYPE_LDAPS ) {
487+ WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
488+ "verifying hostname type LDAPS" );
489+ } else {
490+ throw new CertificateException ("Unsupported hostname type, " +
491+ "HTTPS and LDAPS only supported currently: " + type );
492+ }
469493
470494 /* Get session associated with SSLSocket or SSLEngine */
471495 try {
@@ -485,12 +509,15 @@ else if (engine != null) {
485509 peerHost = session .getPeerHost ();
486510 }
487511
488- /* Get SNI name if SSLSocket has received that from peer. Only check
489- * this when on the client side and verifying a server since SNI
490- * holding expected server name is available on client-side but not
491- * vice-versa */
492- if (session != null && isClient &&
493- (session instanceof ExtendedSSLSession )) {
512+ /* Get SNI name if SSLSocket/SSLEngine has received that from peer.
513+ * Only check this when on the client side and verifying a server since
514+ * SNI holding expected server name is available on client-side but not
515+ * vice-versa. Also only checked for HTTPS type, not LDAPS. As per
516+ * RFC 2830, the client MUST use the server hostname it used to open
517+ * the LDAP connection. */
518+ if ((session != null ) && isClient &&
519+ (session instanceof ExtendedSSLSession ) &&
520+ (type == HOSTNAME_TYPE_HTTPS )) {
494521 sniNames = ((ExtendedSSLSession )session ).getRequestedServerNames ();
495522
496523 for (SNIServerName name : sniNames ) {
@@ -517,8 +544,8 @@ else if (engine != null) {
517544 throw new CertificateException (e );
518545 }
519546
520- /* Try verifying hostname against SNI name */
521- if (isClient ) {
547+ /* Try verifying hostname against SNI name, if HTTPS type */
548+ if (isClient && ( type == HOSTNAME_TYPE_HTTPS ) ) {
522549 if (sniHostName != null ) {
523550 WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
524551 "trying hostname verification against SNI: " + sniHostName );
@@ -541,13 +568,18 @@ else if (engine != null) {
541568 }
542569 }
543570
544- /* Try verifying hostname against peerHost from SSLSocket/Engine */
571+ /* Try verifying hostname against peerHost from SSLSocket/SSLEngine */
545572 if (peerHost != null ) {
546573 WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
547- "trying hostname verification against peer host: " +
548- peerHost );
574+ "trying hostname verification against peer host: " + peerHost );
549575
550- ret = peerCert .checkHost (peerHost );
576+ if (type == HOSTNAME_TYPE_LDAPS ) {
577+ /* LDAPS requires wildcard left-most matching only */
578+ ret = peerCert .checkHost (peerHost ,
579+ WolfSSL .WOLFSSL_LEFT_MOST_WILDCARD_ONLY );
580+ } else {
581+ ret = peerCert .checkHost (peerHost );
582+ }
551583 if (ret == WolfSSL .SSL_SUCCESS ) {
552584 /* Hostname successfully verified against peer host name */
553585 WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
@@ -558,10 +590,16 @@ else if (engine != null) {
558590 }
559591
560592 if (isClient ) {
561- WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
562- "hostname verification failed for server peer cert, " +
563- "tried SNI (" + sniHostName + "), peer host (" + peerHost +
564- ")\n " + peerCert );
593+ if (type == HOSTNAME_TYPE_HTTPS ) {
594+ WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
595+ "hostname verification failed for server peer cert, " +
596+ "tried SNI (" + sniHostName + "), peer host (" + peerHost +
597+ ")\n " + peerCert );
598+ } else {
599+ WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
600+ "hostname verification failed for server peer cert, " +
601+ "peer host (" + peerHost + ")\n " + peerCert );
602+ }
565603 } else {
566604 WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
567605 "hostname verification failed for client peer cert, " +
@@ -593,7 +631,7 @@ protected void verifyHostname(X509Certificate cert,
593631 SSLParameters sslParams = null ;
594632 SSLSession session = null ;
595633
596- /* Hostname verification only done if Socket is of SSLSocket,
634+ /* Hostname verification on Socket done only if Socket is of SSLSocket,
597635 * not null, and connected */
598636 if ((socket != null ) && (socket instanceof SSLSocket ) &&
599637 (socket .isConnected ())) {
@@ -614,8 +652,15 @@ protected void verifyHostname(X509Certificate cert,
614652 WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
615653 "verifying hostname, endpoint identification " +
616654 "algorithm = HTTPS" );
617- verifyHTTPSHostname (cert , (SSLSocket )socket ,
618- null , isClient );
655+ verifyHostnameByType (cert , (SSLSocket )socket ,
656+ null , isClient , HOSTNAME_TYPE_HTTPS );
657+ }
658+ else if (endpointIdAlgo .equals ("LDAPS" )) {
659+ WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
660+ "verifying hostname, endpoint identification " +
661+ "algorithm = LDAPS" );
662+ verifyHostnameByType (cert , (SSLSocket )socket ,
663+ null , isClient , HOSTNAME_TYPE_LDAPS );
619664 }
620665 else {
621666 throw new CertificateException (
@@ -647,7 +692,15 @@ else if (engine != null) {
647692 WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
648693 "verifying hostname, endpoint identification " +
649694 "algorithm = HTTPS" );
650- verifyHTTPSHostname (cert , null , engine , isClient );
695+ verifyHostnameByType (cert , null , engine , isClient ,
696+ HOSTNAME_TYPE_HTTPS );
697+ }
698+ else if (endpointIdAlgo .equals ("LDAPS" )) {
699+ WolfSSLDebug .log (getClass (), WolfSSLDebug .INFO ,
700+ "verifying hostname, endpoint identification " +
701+ "algorithm = LDAPS" );
702+ verifyHostnameByType (cert , null , engine , isClient ,
703+ HOSTNAME_TYPE_LDAPS );
651704 }
652705 else {
653706 throw new CertificateException (
@@ -708,13 +761,13 @@ public void checkClientTrusted(X509Certificate[] certs, String type)
708761 * Try to build and validate the client certificate chain based on the
709762 * provided certificates and authentication type.
710763 *
711- * Also does hostname verification internally if Endpoint Identification
764+ * Does hostname verification internally if Endpoint Identification
712765 * Algorithm has been set by application in SSLParameters, and that
713- * Algorithm matches "HTTPS". If that is set, hostname verification is
714- * done using SNI first then peer host value.
766+ * Algorithm matches "HTTPS" or "LDAPS" . If "HTTPS" is set, hostname
767+ * verification is done using SNI first then peer host value.
715768 *
716- * Other Endpoint Identification Algorithms besides "HTTPS" are not
717- * currently supported.
769+ * Other Endpoint Identification Algorithms besides "HTTPS" and "LDAPS"
770+ * are not currently supported.
718771 *
719772 * @param certs peer certificate chain
720773 * @param type authentication type based on the client certificate
0 commit comments