diff --git a/README.rdoc b/README.rdoc
index 53e2d468..f1b1ea36 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -52,12 +52,10 @@ This task will run the test suite and the
rake rubotest
-To run the integration tests against an LDAP server:
-
- cd test/support/vm/openldap
- vagrant up
- cd ../../../..
- INTEGRATION=openldap bundle exec rake rubotest
+CI takes too long? If your local box supports
+{Vagrant}[https://www.vagrantup.com/], you can run most of the tests
+in a VM on your local box. For more details and setup instructions, see
+{test/support/vm/openldap/README.md}[https://github.com/ruby-ldap/ruby-net-ldap/tree/master/test/support/vm/openldap/README.md]
== Release
diff --git a/lib/net/ldap.rb b/lib/net/ldap.rb
index a79d6c55..f7a98ef5 100644
--- a/lib/net/ldap.rb
+++ b/lib/net/ldap.rb
@@ -476,61 +476,73 @@ def self.result2string(code) #:nodoc:
# specify a treebase. If you give a treebase value in any particular
# call to #search, that value will override any treebase value you give
# here.
+ # * :force_no_page => Set to true to prevent paged results even if your
+ # server says it supports them. This is a fix for MS Active Directory
+ # * :instrumentation_service => An object responsible for instrumenting
+ # operations, compatible with ActiveSupport::Notifications' public API.
# * :encryption => specifies the encryption to be used in communicating
# with the LDAP server. The value must be a Hash containing additional
# parameters, which consists of two keys:
# method: - :simple_tls or :start_tls
- # options: - Hash of options for that method
+ # tls_options: - Hash of options for that method
# The :simple_tls encryption method encrypts all communications
# with the LDAP server. It completely establishes SSL/TLS encryption with
# the LDAP server before any LDAP-protocol data is exchanged. There is no
# plaintext negotiation and no special encryption-request controls are
# sent to the server. The :simple_tls option is the simplest, easiest
# way to encrypt communications between Net::LDAP and LDAP servers.
- # It's intended for cases where you have an implicit level of trust in the
- # authenticity of the LDAP server. No validation of the LDAP server's SSL
- # certificate is performed. This means that :simple_tls will not produce
- # errors if the LDAP server's encryption certificate is not signed by a
- # well-known Certification Authority. If you get communications or
- # protocol errors when using this option, check with your LDAP server
- # administrator. Pay particular attention to the TCP port you are
- # connecting to. It's impossible for an LDAP server to support plaintext
- # LDAP communications and simple TLS connections on the same port.
- # The standard TCP port for unencrypted LDAP connections is 389, but the
- # standard port for simple-TLS encrypted connections is 636. Be sure you
- # are using the correct port.
- #
+ # If you get communications or protocol errors when using this option,
+ # check with your LDAP server administrator. Pay particular attention
+ # to the TCP port you are connecting to. It's impossible for an LDAP
+ # server to support plaintext LDAP communications and simple TLS
+ # connections on the same port. The standard TCP port for unencrypted
+ # LDAP connections is 389, but the standard port for simple-TLS
+ # encrypted connections is 636. Be sure you are using the correct port.
# The :start_tls like the :simple_tls encryption method also encrypts all
# communcations with the LDAP server. With the exception that it operates
# over the standard TCP port.
#
- # In order to verify certificates and enable other TLS options, the
- # :tls_options hash can be passed alongside :simple_tls or :start_tls.
- # This hash contains any options that can be passed to
- # OpenSSL::SSL::SSLContext#set_params(). The most common options passed
- # should be OpenSSL::SSL::SSLContext::DEFAULT_PARAMS, or the :ca_file option,
- # which contains a path to a Certificate Authority file (PEM-encoded).
- #
- # Example for a default setup without custom settings:
- # {
- # :method => :simple_tls,
- # :tls_options => OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
- # }
+ # To validate the LDAP server's certificate (a security must if you're
+ # talking over the public internet), you need to set :tls_options
+ # something like this...
#
- # Example for specifying a CA-File and only allowing TLSv1.1 connections:
- #
- # {
- # :method => :start_tls,
- # :tls_options => { :ca_file => "/etc/cafile.pem", :ssl_version => "TLSv1_1" }
+ # Net::LDAP.new(
+ # # ... set host, bind dn, etc ...
+ # encryption: {
+ # method: :simple_tls,
+ # tls_options: OpenSSL::SSL::SSLContext::DEFAULT_PARAMS,
# }
- # * :force_no_page => Set to true to prevent paged results even if your
- # server says it supports them. This is a fix for MS Active Directory
- # * :instrumentation_service => An object responsible for instrumenting
- # operations, compatible with ActiveSupport::Notifications' public API.
+ # )
+ #
+ # The above will use the operating system-provided store of CA
+ # certificates to validate your LDAP server's cert.
+ # If cert validation fails, it'll happen during the #bind
+ # whenever you first try to open a connection to the server.
+ # Those methods will throw Net::LDAP::ConnectionError with
+ # a message about certificate verify failing. If your
+ # LDAP server's certificate is signed by DigiCert, Comodo, etc.,
+ # you're probably good. If you've got a self-signed cert but it's
+ # been added to the host's OS-maintained CA store (e.g. on Debian
+ # add foobar.crt to /usr/local/share/ca-certificates/ and run
+ # `update-ca-certificates`), then the cert should pass validation.
+ # To ignore the OS's CA store, put your CA in a PEM-encoded file and...
+ #
+ # encryption: {
+ # method: :simple_tls,
+ # tls_options: { ca_file: '/path/to/my-little-ca.pem',
+ # ssl_version: 'TLSv1_1' },
+ # }
+ #
+ # As you might guess, the above example also fails the connection
+ # if the client can't negotiate TLS v1.1.
+ # tls_options is ultimately passed to OpenSSL::SSL::SSLContext#set_params
+ # For more details, see
+ # http://ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
#
# Instantiating a Net::LDAP object does not result in network
# traffic to the LDAP server. It simply stores the connection and binding
- # parameters in the object.
+ # parameters in the object. That's why Net::LDAP.new doesn't throw
+ # cert validation errors itself; #bind does instead.
def initialize(args = {})
@host = args[:host] || DefaultHost
@port = args[:port] || DefaultPort
diff --git a/lib/net/ldap/connection.rb b/lib/net/ldap/connection.rb
index 05f676cc..4f311748 100644
--- a/lib/net/ldap/connection.rb
+++ b/lib/net/ldap/connection.rb
@@ -52,6 +52,15 @@ def open_connection(server)
hosts.each do |host, port|
begin
prepare_socket(server.merge(socket: @socket_class.new(host, port, socket_opts)), timeout)
+ if encryption
+ if encryption[:tls_options] &&
+ encryption[:tls_options][:verify_mode] &&
+ encryption[:tls_options][:verify_mode] == OpenSSL::SSL::VERIFY_NONE
+ warn "not verifying SSL hostname of LDAPS server '#{host}:#{port}'"
+ else
+ @conn.post_connection_check(host)
+ end
+ end
return
rescue Net::LDAP::Error, SocketError, SystemCallError,
OpenSSL::SSL::SSLError => e
@@ -392,12 +401,11 @@ def search(args = nil)
# should collect this into a private helper to clarify the structure
query_limit = 0
if size > 0
- if paged
- query_limit = (((size - n_results) < 126) ? (size -
- n_results) : 0)
- else
- query_limit = size
- end
+ query_limit = if paged
+ (((size - n_results) < 126) ? (size - n_results) : 0)
+ else
+ size
+ end
end
request = [
diff --git a/script/generate-fixture-ca b/script/generate-fixture-ca
new file mode 100755
index 00000000..89eb3d8d
--- /dev/null
+++ b/script/generate-fixture-ca
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+BASE_PATH=$( cd "`dirname $0`/../test/fixtures/ca" && pwd )
+cd "${BASE_PATH}" || exit 4
+
+USAGE=$( cat << EOS
+Usage:
+ $0 --regenerate
+
+Generates a new self-signed CA, for integration testing. This should only need
+to be run if you are writing new TLS/SSL tests, and need to generate
+additional fixtuer CAs.
+
+This script uses the GnuTLS certtool CLI. If you are on macOS,
+'brew install gnutls', and it will be installed as 'gnutls-certtool'.
+Apple unfortunately ships with an incompatible /usr/bin/certtool that does
+different things.
+EOS
+)
+
+if [ "x$1" != 'x--regenerate' ]; then
+ echo "${USAGE}"
+ exit 1
+fi
+
+TOOL=`type -p certtool`
+if [ "$(uname)" = "Darwin" ]; then
+ TOOL=`type -p gnutls-certtool`
+ if [ ! -x "${TOOL}" ]; then
+ echo "Sorry, Darwin requires gnutls-certtool; try `brew install gnutls`"
+ exit 2
+ fi
+fi
+
+if [ ! -x "${TOOL}" ]; then
+ echo "Sorry, no certtool found!"
+ exit 3
+fi
+export TOOL
+
+
+${TOOL} --generate-privkey > ./cakey.pem
+${TOOL} --generate-self-signed \
+ --load-privkey ./cakey.pem \
+ --template ./ca.info \
+ --outfile ./cacert.pem
+
+echo "cert and private key generated! Don't forget to check them in"
diff --git a/script/install-openldap b/script/install-openldap
index efb0cbaa..3e391d87 100755
--- a/script/install-openldap
+++ b/script/install-openldap
@@ -2,8 +2,8 @@
set -e
set -x
-BASE_PATH="$( cd `dirname $0`/../test/fixtures/openldap && pwd )"
-SEED_PATH="$( cd `dirname $0`/../test/fixtures && pwd )"
+BASE_PATH=$( cd "`dirname $0`/../test/fixtures/openldap" && pwd )
+SEED_PATH=$( cd "`dirname $0`/../test/fixtures" && pwd )
dpkg -s slapd time ldap-utils gnutls-bin ssl-cert > /dev/null ||\
DEBIAN_FRONTEND=noninteractive apt-get update -y --force-yes && \
@@ -48,47 +48,58 @@ chown -R openldap.openldap /var/lib/ldap
rm -rf $TMPDIR
# SSL
+export CA_CERT="/usr/local/share/ca-certificates/rubyldap-ca.crt"
+export CA_KEY="/etc/ssl/private/rubyldap-ca.key"
-sh -c "certtool --generate-privkey > /etc/ssl/private/cakey.pem"
+# The self-signed fixture CA cert & key are generated by
+# `script/generate-fiuxture-ca` and checked into version control.
+# You shouldn't need to muck with these unless you're writing more
+# TLS/SSL integration tests, and need special magic values in the cert.
-sh -c "cat > /etc/ssl/ca.info < /etc/ssl/ldap01.info <> /etc/ssl/ldap01.info
+done
+
# Create the server certificate
certtool --generate-certificate \
--load-privkey /etc/ssl/private/ldap01_slapd_key.pem \
- --load-ca-certificate /etc/ssl/certs/cacert.pem \
- --load-ca-privkey /etc/ssl/private/cakey.pem \
+ --load-ca-certificate "${CA_CERT}" \
+ --load-ca-privkey "${CA_KEY}" \
--template /etc/ssl/ldap01.info \
--outfile /etc/ssl/certs/ldap01_slapd_cert.pem
ldapmodify -Y EXTERNAL -H ldapi:/// <> /etc/hosts
+grep ldap02 /etc/hosts || echo "127.0.0.1 ldap02.example.com" >> /etc/hosts
+grep bogus /etc/hosts || echo "127.0.0.1 bogus.example.com" >> /etc/hosts
service slapd restart
diff --git a/test/fixtures/ca/ca.info b/test/fixtures/ca/ca.info
new file mode 100644
index 00000000..c0fd3629
--- /dev/null
+++ b/test/fixtures/ca/ca.info
@@ -0,0 +1,4 @@
+cn = rubyldap
+ca
+cert_signing_key
+expiration_days = 7200
diff --git a/test/fixtures/ca/cacert.pem b/test/fixtures/ca/cacert.pem
new file mode 100644
index 00000000..0218dd8a
--- /dev/null
+++ b/test/fixtures/ca/cacert.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID7zCCAlegAwIBAgIMV7zWei6SNfABx6jMMA0GCSqGSIb3DQEBCwUAMBMxETAP
+BgNVBAMTCHJ1YnlsZGFwMB4XDTE2MDgyMzIzMDQyNloXDTM2MDUxMDIzMDQyNlow
+EzERMA8GA1UEAxMIcnVieWxkYXAwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGK
+AoIBgQDGe9wziGHZJhIf+IEKSk1tpT9Mu7YgsUwjrlutvkoO1Q6K+amTAVDXizPf
+1DVSDpZP5+CfBOznhgLMsPvrQ02w4qx5/6X9L+zJcMk8jTNYSKj5uIKpK52E7Uok
+aygMXeaqroPONGkoJIZiVGgdbWfTvcffTm8FOhztXUbMrMXJNinFsocGHEoMNN8b
+vqgAyG4+DFHoK4L0c6eQjE4nZBChieZdShUhaBpV7r2qSNbPw67cvAKuEzml58mV
+1ZF1F73Ua8gPWXHEfUe2GEfG0NnRq6sGbsDYe/DIKxC7AZ89udZF3WZXNrPhvXKj
+ZT7njwcMQemns4dNPQ0k2V4vAQ8pD8r8Qvb65FiSopUhVaGQswAnIMS1DnFq88AQ
+KJTKIXbBuMwuaNNSs6R/qTS2RDk1w+CGpRXAg7+1SX5NKdrEsu1IaABA/tQ/zKKk
+OLLJaD0giX1weBVmNeFcKxIoT34VS59eEt5APmPcguJnx+aBrA9TLzSO788apBN0
+4lGAmR0CAwEAAaNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwQA
+MB0GA1UdDgQWBBRTvXSkge03oqLu7UUjFI+oLYwnujANBgkqhkiG9w0BAQsFAAOC
+AYEATSZQWH+uSN5GvOUvJ8LHWkeVovn0UhboK0K7GzmMeGz+dp/Xrj6eQ4ONK0zI
+RCJyoo/nCR7CfQ5ujVXr03XD2SUgyD565ulXuhw336DasL5//fucmQYDeqhwbKML
+FTzsF9H9dO4J5TjxJs7e5dRJ0wrP/XEY+WFhXXdSHTl8vGCI6QqWc7TvDpmbS4iX
+uTzjJswu9Murt9JUJNMN2DlDi/vBBeruaj4c2cMMnKMvkfj14kd8wMocmzj+gVQl
+r+fRQbKAJNec65lA4/Zeb6sD9SAi0ZIVgxA4a7g8/sdNWHIAxPicpJkIJf30TsyY
+F+8+Hd5mBtCbvFfAVkT6bHBP1OiAgNke+Rh/j/sQbyWbKCKw0+jpFJgO9KUNGfC0
+O/CqX+J4G7HqL8VJqrLnBvOdhfetAvNQtf1gcw5ZwpeEFM+Kvx/lsILaIYdAUSjX
+ePOc5gI2Bi9WXq+T9AuhSf+TWUR874m/rdTWe5fM8mXCNl7C4I5zCqLltEDkSoMP
+jDj/
+-----END CERTIFICATE-----
diff --git a/test/fixtures/ca/cakey.pem b/test/fixtures/ca/cakey.pem
new file mode 100644
index 00000000..d75ab299
--- /dev/null
+++ b/test/fixtures/ca/cakey.pem
@@ -0,0 +1,190 @@
+Public Key Info:
+ Public Key Algorithm: RSA
+ Key Security Level: High (3072 bits)
+
+modulus:
+ 00:c6:7b:dc:33:88:61:d9:26:12:1f:f8:81:0a:4a:4d
+ 6d:a5:3f:4c:bb:b6:20:b1:4c:23:ae:5b:ad:be:4a:0e
+ d5:0e:8a:f9:a9:93:01:50:d7:8b:33:df:d4:35:52:0e
+ 96:4f:e7:e0:9f:04:ec:e7:86:02:cc:b0:fb:eb:43:4d
+ b0:e2:ac:79:ff:a5:fd:2f:ec:c9:70:c9:3c:8d:33:58
+ 48:a8:f9:b8:82:a9:2b:9d:84:ed:4a:24:6b:28:0c:5d
+ e6:aa:ae:83:ce:34:69:28:24:86:62:54:68:1d:6d:67
+ d3:bd:c7:df:4e:6f:05:3a:1c:ed:5d:46:cc:ac:c5:c9
+ 36:29:c5:b2:87:06:1c:4a:0c:34:df:1b:be:a8:00:c8
+ 6e:3e:0c:51:e8:2b:82:f4:73:a7:90:8c:4e:27:64:10
+ a1:89:e6:5d:4a:15:21:68:1a:55:ee:bd:aa:48:d6:cf
+ c3:ae:dc:bc:02:ae:13:39:a5:e7:c9:95:d5:91:75:17
+ bd:d4:6b:c8:0f:59:71:c4:7d:47:b6:18:47:c6:d0:d9
+ d1:ab:ab:06:6e:c0:d8:7b:f0:c8:2b:10:bb:01:9f:3d
+ b9:d6:45:dd:66:57:36:b3:e1:bd:72:a3:65:3e:e7:8f
+ 07:0c:41:e9:a7:b3:87:4d:3d:0d:24:d9:5e:2f:01:0f
+ 29:0f:ca:fc:42:f6:fa:e4:58:92:a2:95:21:55:a1:90
+ b3:00:27:20:c4:b5:0e:71:6a:f3:c0:10:28:94:ca:21
+ 76:c1:b8:cc:2e:68:d3:52:b3:a4:7f:a9:34:b6:44:39
+ 35:c3:e0:86:a5:15:c0:83:bf:b5:49:7e:4d:29:da:c4
+ b2:ed:48:68:00:40:fe:d4:3f:cc:a2:a4:38:b2:c9:68
+ 3d:20:89:7d:70:78:15:66:35:e1:5c:2b:12:28:4f:7e
+ 15:4b:9f:5e:12:de:40:3e:63:dc:82:e2:67:c7:e6:81
+ ac:0f:53:2f:34:8e:ef:cf:1a:a4:13:74:e2:51:80:99
+ 1d:
+
+public exponent:
+ 01:00:01:
+
+private exponent:
+ 1d:0d:9a:50:ec:c0:ad:e1:75:bb:ba:4b:61:2f:39:20
+ 38:95:08:6d:5d:9e:71:75:5c:af:b3:f9:bd:a5:e7:7f
+ e6:4e:0f:77:73:ee:38:60:24:9f:26:3f:50:c2:bf:21
+ df:76:68:99:be:45:d3:29:f9:94:ee:bf:21:53:cb:b6
+ 7d:a7:93:80:09:53:03:45:dc:c2:a6:a2:37:64:f1:a2
+ 49:21:ac:91:6b:a3:d7:bd:d2:62:0c:ec:a6:83:10:e7
+ a7:ca:3d:be:dc:4b:1c:36:24:79:96:33:5b:43:5d:74
+ 50:0e:46:b0:9b:6d:9f:71:06:89:a5:c8:65:ed:d9:a3
+ 15:00:3c:3e:a9:75:50:9d:72:cb:c9:aa:e1:ba:a3:9c
+ 07:77:14:32:30:d4:4d:65:f4:7c:23:1d:79:84:9b:2e
+ 9a:19:df:43:ed:cd:e3:08:1f:d5:ff:6b:42:98:36:f7
+ 44:cc:48:b4:f7:b8:16:b3:23:37:8d:b8:22:3f:8a:86
+ db:71:b3:85:2d:6d:42:44:b7:dc:c1:36:e0:c4:0f:fe
+ cb:76:84:81:e2:83:f5:82:76:a9:7b:35:d5:44:00:d1
+ 1a:fc:ef:b9:a4:2b:62:aa:f8:56:eb:60:e5:16:33:f1
+ 28:e1:da:91:50:e3:a4:c7:d6:30:21:cf:04:07:cd:8c
+ b6:9e:b0:a7:6c:96:57:2e:09:5b:39:26:d0:60:be:e3
+ 90:59:a3:8e:e7:6e:3f:62:7e:b4:2a:e1:8f:00:37:7a
+ 83:9e:7a:9c:d2:ae:ba:50:84:73:65:3a:64:95:d8:48
+ f9:fd:0e:c3:5b:6e:08:3b:c5:c9:1c:29:55:bb:67:e8
+ fa:50:40:30:2a:d1:b7:cf:54:a8:f0:f0:76:89:ad:19
+ e7:a0:3a:56:6c:75:c5:bc:d8:46:ce:1e:66:f2:61:96
+ 11:e4:57:cc:52:ff:e4:ed:6b:2c:ce:78:15:ba:b7:ed
+ 31:f2:68:88:79:bf:7c:29:3c:2f:66:71:0b:09:b7:41
+
+
+prime1:
+ 00:fd:c2:37:b9:6f:77:88:51:a2:f7:4f:c2:3c:a4:57
+ bf:ba:71:14:f3:61:f4:39:78:22:3d:bc:d8:d2:4e:c0
+ 4b:9e:c2:6d:38:a8:21:e2:70:1a:96:48:95:18:85:01
+ 46:fb:62:a4:81:09:f8:2a:3a:87:78:07:5d:93:54:ce
+ 2a:51:b3:51:6f:61:0a:2e:9d:b0:51:37:e3:13:bd:81
+ 23:2b:61:53:fa:ac:08:dc:a0:e6:63:a3:b0:cc:cf:73
+ 1d:65:b7:11:bc:29:70:fb:72:ea:63:9d:67:02:d6:35
+ 24:13:1d:bc:72:fb:9e:3d:ab:0b:57:6e:bd:a1:51:56
+ f9:bc:96:15:74:a3:31:16:c6:b8:98:1b:0a:a2:59:7c
+ c8:b7:14:b8:5b:f3:2e:26:b4:f0:46:c4:3d:27:dd:41
+ 31:52:a7:15:a8:af:6a:98:a5:9c:20:17:f9:1d:54:54
+ ff:10:91:a3:a5:ca:ac:63:e7:16:2b:71:3c:3a:cd:4f
+ ed:
+
+prime2:
+ 00:c8:3c:a8:9f:8a:db:42:b5:8d:cf:2a:a1:2f:e5:73
+ 05:de:30:d8:17:b9:5c:9d:08:60:02:c9:66:9d:88:50
+ ac:cd:0f:b5:47:b4:a8:73:3b:7d:65:79:bf:4c:6f:d0
+ e2:03:ed:d4:28:4e:00:07:23:00:01:4f:05:de:9b:44
+ 1a:84:ae:09:4a:d6:ed:61:5d:77:e2:fa:13:99:4c:b7
+ 76:72:3d:f8:53:93:69:78:e8:bd:26:cb:b0:f9:01:f4
+ 1d:20:4f:60:f5:ab:3c:19:85:73:34:f3:ec:d2:67:ef
+ 56:b8:5d:93:73:8e:d9:3e:28:ff:87:f5:4a:26:fa:b1
+ ae:c6:d3:9d:03:e3:fd:c2:24:48:af:85:2a:8e:3b:5b
+ 93:07:38:91:21:ae:49:cb:6d:e3:30:81:15:ed:65:eb
+ dc:01:df:3b:9d:43:fd:a6:e1:df:ef:ad:22:42:34:f1
+ 3f:81:5e:57:0a:e0:56:94:f2:2a:00:d0:cc:c5:50:67
+ f1:
+
+coefficient:
+ 00:bd:23:8c:2e:a7:7b:6b:1e:85:77:db:7d:77:f6:e5
+ b0:15:c6:e1:9e:35:57:72:df:35:6d:93:89:7f:83:9f
+ 63:7f:08:0a:b3:d4:ba:63:9b:10:7f:0f:d3:55:e9:38
+ cf:90:37:3d:85:3d:a7:97:8c:33:f2:c2:b1:38:2b:db
+ 39:ca:a8:d0:23:d7:89:cc:8d:02:7d:61:9b:b6:04:69
+ 14:e8:c9:84:34:36:6c:fb:84:58:cc:9a:53:74:a4:42
+ bd:1d:25:1b:ba:82:c0:fb:23:2c:90:bb:35:4b:5b:b0
+ 98:d0:ab:9d:61:6e:ea:e8:84:e7:a7:6c:ae:1b:2c:00
+ cb:0f:1a:f8:e2:7c:fd:42:1a:e2:13:52:c7:50:fa:65
+ c9:5f:ed:40:a8:7f:46:0e:ce:f6:56:83:6f:0e:8e:39
+ f8:33:5f:83:de:be:be:ef:8c:66:ad:16:c8:ec:98:d4
+ b2:b2:55:66:a2:9e:27:6a:84:f1:31:07:e8:bf:a7:a7
+ bd:
+
+exp1:
+ 00:b6:50:0c:53:19:07:8b:14:03:fe:a4:fa:0b:31:93
+ ad:b7:18:b9:91:a6:c5:9d:68:77:49:5d:dd:75:33:89
+ 2a:8b:54:6a:be:32:e5:ad:57:17:72:f3:90:d2:fd:f4
+ 0d:f8:5c:45:8e:44:08:5c:e6:92:1f:a5:43:10:af:f4
+ 33:29:61:a8:d7:59:a3:c4:1c:1c:ea:2d:39:e3:1b:da
+ a4:d6:ec:e5:36:0a:d5:8f:15:b6:90:cd:b1:1f:64:c7
+ f2:cd:fa:3a:2e:b2:a3:6e:b4:80:3b:b3:81:a7:e3:18
+ 68:e3:a7:10:96:97:ba:77:d9:e4:9b:1b:7f:f8:5f:85
+ 1a:85:e8:5a:5f:e3:43:48:76:db:76:c4:ae:de:37:66
+ d4:99:dc:b4:1b:b3:da:6b:8a:c1:ba:46:11:1e:0b:f3
+ 63:a9:5b:4b:cf:56:c0:42:0d:71:df:08:fa:3c:9d:33
+ 37:d1:c2:a1:0d:63:50:79:b2:34:16:60:13:82:b7:b1
+ 7d:
+
+exp2:
+ 00:98:38:2c:c4:24:4e:2c:b7:52:17:a4:43:a6:e2:99
+ ff:62:fa:e4:bb:9c:49:40:83:66:61:97:f3:af:5c:3a
+ 60:32:ff:77:03:0c:de:65:c3:5a:bf:72:bf:2f:7f:6d
+ 5e:f4:37:af:69:f8:69:e3:03:03:74:fb:3a:ee:10:40
+ c4:9c:0a:a5:bb:c4:09:ef:53:9b:d8:eb:dd:4c:53:da
+ c0:6b:76:9a:ba:06:3d:4f:12:37:01:30:25:d8:16:59
+ 1a:6f:3e:88:ea:19:83:75:af:52:76:75:dc:99:d3:33
+ 4a:4c:9b:ae:85:51:99:ea:bc:46:0d:78:36:27:cd:ba
+ 97:b0:44:9c:7f:a1:a9:7e:16:11:3f:85:4f:65:92:d0
+ 39:c4:6a:87:42:00:79:ce:f1:39:9d:dc:f3:eb:65:e8
+ d8:76:7f:da:94:e2:64:08:a2:7b:97:7b:99:a8:95:10
+ b5:03:46:d1:8a:ce:22:63:d6:78:81:e8:39:52:e2:9e
+ 31:
+
+
+Public Key ID: 53:BD:74:A4:81:ED:37:A2:A2:EE:ED:45:23:14:8F:A8:2D:8C:27:BA
+Public key's random art:
++--[ RSA 3072]----+
+| . o. . |
+| . +...+ |
+| . o o.+ . |
+| o o . . .ooo |
+| o = . S o..o . |
+| . o . .+.. |
+|. . .. |
+| . .. . |
+|E oo.o |
++-----------------+
+
+-----BEGIN RSA PRIVATE KEY-----
+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
+-----END RSA PRIVATE KEY-----
diff --git a/test/fixtures/cacert.pem b/test/fixtures/cacert.pem
deleted file mode 100644
index f8b134e1..00000000
--- a/test/fixtures/cacert.pem
+++ /dev/null
@@ -1,20 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDRzCCAf+gAwIBAgIEVHpbmjANBgkqhkiG9w0BAQsFADATMREwDwYDVQQDEwhy
-dWJ5bGRhcDAeFw0xNDExMjkyMzQ5NDZaFw0xNTExMjkyMzQ5NDZaMBMxETAPBgNV
-BAMTCHJ1YnlsZGFwMIIBUjANBgkqhkiG9w0BAQEFAAOCAT8AMIIBOgKCATEA4pKe
-cDCNuL53fkpO/WSAS+gmMTsOs+oOK71kZlk2QT/MBz8TxC6m358qCADjnXcMVVxa
-ySQbQlVKZMkIvLNciZbiLDgC5II0NbHACNa8rqenoKRjS4J9W3OhA8EmnXn/Me+8
-uMCI9tfnKNRZYdkQZlra4I+Idn+xYfl/5q5b/7ZjPS2zY/585hFEYE+5vfOZVBSU
-3HMNSeuJvTehLv7dD7aQfXNM4cRgHXequkJQ/HLLFAO4AgJ+LJrFWpj7GWz3crgr
-9G5px4T78wJH3NQiOsG6UBXPw8c4T+Z6GAWX2l1zs1gZsaiCVbAraqK3404lL7yp
-+ThbsW3ifzgNPhmjScXBLdbEDrrAKosW7kkTOGzxiMCBmNlj2SKhcztoduAtfF1f
-Fs2Jk8MRTHwO8ThD7wIDAQABo0MwQTAPBgNVHRMBAf8EBTADAQH/MA8GA1UdDwEB
-/wQFAwMHBAAwHQYDVR0OBBYEFJDm67ekyFu4/Z7VcO6Vk/5pinGcMA0GCSqGSIb3
-DQEBCwUAA4IBMQDHeEPzfYRtjynpUKyrtxx/6ZVOfCLuz4eHkBZggz/pJacDCv/a
-I//W03XCk8RWq/fWVVUzvxXgPwnYcw992PLM7XW81zp6ruRUDWooYnjHZZz3bRhe
-kC4QvM2mZhcsMVmhmWWKZn81qXgVdUY1XNRhk87cuXjF/UTpEieFvWAsCUkFZkqB
-AmySCuI/FuPaauT1YAltkIlYAEIGNJGZDMf2BTVUQpXhTXeS9/AZWLNDBwiq+fwo
-YYnsr9MnBXCEmg1gVSR/Ay2AZmbYfiYtb5kU8uq2lSWAUb4LX6HZl82wo3OilrJ2
-WXl6Qf+Fcy4qqkRt4AKHjtzizpEDCOVYuuG0Zoy+QnxNXRsEzpb8ymnJFrcgYfk/
-6Lv2gWAFl5FqCZp7gBWg55eL2coT4C+mbNTF
------END CERTIFICATE-----
diff --git a/test/integration/test_bind.rb b/test/integration/test_bind.rb
index b7fa35bc..bd1281e2 100644
--- a/test/integration/test_bind.rb
+++ b/test/integration/test_bind.rb
@@ -2,19 +2,23 @@
class TestBindIntegration < LDAPIntegrationTestCase
def test_bind_success
- assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect
+ assert @ldap.bind(BIND_CREDS),
+ @ldap.get_operation_result.inspect
end
def test_bind_timeout
@ldap.port = 8389
error = assert_raise Net::LDAP::Error do
- @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1")
+ @ldap.bind BIND_CREDS
end
- assert_equal('Connection timed out - user specified timeout', error.message)
+ msgs = ['Operation timed out - user specified timeout',
+ 'Connection timed out - user specified timeout']
+ assert_send([msgs, :include?, error.message])
end
def test_bind_anonymous_fail
- refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: ""), @ldap.get_operation_result.inspect
+ refute @ldap.bind(BIND_CREDS.merge(password: '')),
+ @ldap.get_operation_result.inspect
result = @ldap.get_operation_result
assert_equal Net::LDAP::ResultCodeUnwillingToPerform, result.code
@@ -25,18 +29,216 @@ def test_bind_anonymous_fail
end
def test_bind_fail
- refute @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "not my password"), @ldap.get_operation_result.inspect
+ refute @ldap.bind(BIND_CREDS.merge(password: "not my password")),
+ @ldap.get_operation_result.inspect
end
def test_bind_tls_with_cafile
- tls_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.merge(:ca_file => CA_FILE)
- @ldap.encryption(method: :start_tls, tls_options: tls_options)
- assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: TLS_OPTS.merge(ca_file: CA_FILE),
+ )
+ assert @ldap.bind(BIND_CREDS),
+ @ldap.get_operation_result.inspect
end
- def test_bind_tls_with_verify_none
- tls_options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.merge(:verify_mode => OpenSSL::SSL::VERIFY_NONE)
- @ldap.encryption(method: :start_tls, tls_options: tls_options)
- assert @ldap.bind(method: :simple, username: "uid=user1,ou=People,dc=rubyldap,dc=com", password: "passworD1"), @ldap.get_operation_result.inspect
+ def test_bind_tls_with_bad_hostname_verify_none_no_ca_passes
+ @ldap.host = '127.0.0.1'
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: { verify_mode: OpenSSL::SSL::VERIFY_NONE },
+ )
+ assert @ldap.bind(BIND_CREDS),
+ @ldap.get_operation_result.inspect
+ end
+
+ def test_bind_tls_with_bad_hostname_verify_none_no_ca_opt_merge_passes
+ @ldap.host = '127.0.0.1'
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: TLS_OPTS.merge(verify_mode: OpenSSL::SSL::VERIFY_NONE),
+ )
+ assert @ldap.bind(BIND_CREDS),
+ @ldap.get_operation_result.inspect
+ end
+
+ def test_bind_tls_with_bad_hostname_verify_peer_ca_fails
+ @ldap.host = '127.0.0.1'
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: { verify_mode: OpenSSL::SSL::VERIFY_PEER,
+ ca_file: CA_FILE },
+ )
+ error = assert_raise Net::LDAP::Error,
+ Net::LDAP::ConnectionRefusedError do
+ @ldap.bind BIND_CREDS
+ end
+ assert_equal(
+ "hostname \"#{@ldap.host}\" does not match the server certificate",
+ error.message,
+ )
+ end
+
+ def test_bind_tls_with_bad_hostname_ca_default_opt_merge_fails
+ @ldap.host = '127.0.0.1'
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: TLS_OPTS.merge(ca_file: CA_FILE),
+ )
+ error = assert_raise Net::LDAP::Error,
+ Net::LDAP::ConnectionRefusedError do
+ @ldap.bind BIND_CREDS
+ end
+ assert_equal(
+ "hostname \"#{@ldap.host}\" does not match the server certificate",
+ error.message,
+ )
+ end
+
+ def test_bind_tls_with_bad_hostname_ca_no_opt_merge_fails
+ @ldap.host = '127.0.0.1'
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: { ca_file: CA_FILE },
+ )
+ error = assert_raise Net::LDAP::Error,
+ Net::LDAP::ConnectionRefusedError do
+ @ldap.bind BIND_CREDS
+ end
+ assert_equal(
+ "hostname \"#{@ldap.host}\" does not match the server certificate",
+ error.message,
+ )
+ end
+
+ def test_bind_tls_with_valid_hostname_default_opts_passes
+ @ldap.host = 'localhost'
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: TLS_OPTS.merge(verify_mode: OpenSSL::SSL::VERIFY_PEER,
+ ca_file: CA_FILE),
+ )
+ assert @ldap.bind(BIND_CREDS),
+ @ldap.get_operation_result.inspect
+ end
+
+ def test_bind_tls_with_valid_hostname_just_verify_peer_ca_passes
+ @ldap.host = 'localhost'
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: { verify_mode: OpenSSL::SSL::VERIFY_PEER,
+ ca_file: CA_FILE },
+ )
+ assert @ldap.bind(BIND_CREDS),
+ @ldap.get_operation_result.inspect
+ end
+
+ def test_bind_tls_with_bogus_hostname_system_ca_fails
+ @ldap.host = '127.0.0.1'
+ @ldap.encryption(method: :start_tls, tls_options: {})
+ error = assert_raise Net::LDAP::Error,
+ Net::LDAP::ConnectionRefusedError do
+ @ldap.bind BIND_CREDS
+ end
+ assert_equal(
+ "hostname \"#{@ldap.host}\" does not match the server certificate",
+ error.message,
+ )
+ end
+
+ # The following depend on /etc/hosts hacking.
+ # We can do that on CI, but it's less than cool on people's dev boxes
+ def test_bind_tls_with_multiple_hosts
+ omit_unless ENV['TRAVIS'] == 'true'
+
+ @ldap.host = nil
+ @ldap.hosts = [['ldap01.example.com', 389], ['ldap02.example.com', 389]]
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: TLS_OPTS.merge(verify_mode: OpenSSL::SSL::VERIFY_PEER,
+ ca_file: CA_FILE),
+ )
+ assert @ldap.bind(BIND_CREDS),
+ @ldap.get_operation_result.inspect
+ end
+
+ def test_bind_tls_with_multiple_bogus_hosts
+ omit_unless ENV['TRAVIS'] == 'true'
+
+ @ldap.host = nil
+ @ldap.hosts = [['127.0.0.1', 389], ['bogus.example.com', 389]]
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: TLS_OPTS.merge(verify_mode: OpenSSL::SSL::VERIFY_PEER,
+ ca_file: CA_FILE),
+ )
+ error = assert_raise Net::LDAP::Error,
+ Net::LDAP::ConnectionError do
+ @ldap.bind BIND_CREDS
+ end
+ assert_equal("Unable to connect to any given server: ",
+ error.message.split("\n").shift)
+ end
+
+ def test_bind_tls_with_multiple_bogus_hosts_no_verification
+ omit_unless ENV['TRAVIS'] == 'true'
+
+ @ldap.host = nil
+ @ldap.hosts = [['127.0.0.1', 389], ['bogus.example.com', 389]]
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: TLS_OPTS.merge(verify_mode: OpenSSL::SSL::VERIFY_NONE),
+ )
+ assert @ldap.bind(BIND_CREDS),
+ @ldap.get_operation_result.inspect
+ end
+
+ def test_bind_tls_with_multiple_bogus_hosts_ca_check_only_fails
+ omit_unless ENV['TRAVIS'] == 'true'
+
+ @ldap.host = nil
+ @ldap.hosts = [['127.0.0.1', 389], ['bogus.example.com', 389]]
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: { ca_file: CA_FILE },
+ )
+ error = assert_raise Net::LDAP::Error,
+ Net::LDAP::ConnectionError do
+ @ldap.bind BIND_CREDS
+ end
+ assert_equal("Unable to connect to any given server: ",
+ error.message.split("\n").shift)
+ end
+
+ # This test is CI-only because we can't add the fixture CA
+ # to the system CA store on people's dev boxes.
+ def test_bind_tls_valid_hostname_system_ca_on_travis_passes
+ omit_unless ENV['TRAVIS'] == 'true'
+
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: { verify_mode: OpenSSL::SSL::VERIFY_PEER },
+ )
+ assert @ldap.bind(BIND_CREDS),
+ @ldap.get_operation_result.inspect
+ end
+
+ # Inverse of the above! Don't run this on Travis, only on Vagrant.
+ # Since Vagrant's hypervisor *won't* have the CA in the system
+ # x509 store, we can assume validation will fail
+ def test_bind_tls_valid_hostname_system_on_vagrant_fails
+ omit_if ENV['TRAVIS'] == 'true'
+
+ @ldap.encryption(
+ method: :start_tls,
+ tls_options: { verify_mode: OpenSSL::SSL::VERIFY_PEER },
+ )
+ error = assert_raise Net::LDAP::Error do
+ @ldap.bind BIND_CREDS
+ end
+ assert_equal(
+ "SSL_connect returned=1 errno=0 state=error: certificate verify failed",
+ error.message,
+ )
end
end
diff --git a/test/support/vm/openldap/README.md b/test/support/vm/openldap/README.md
index a2769567..f79f4dc6 100644
--- a/test/support/vm/openldap/README.md
+++ b/test/support/vm/openldap/README.md
@@ -1,8 +1,31 @@
# Local OpenLDAP Integration Testing
-Set up a [Vagrant](http://www.vagrantup.com/) VM to run integration tests against OpenLDAP locally.
+Set up a [Vagrant](http://www.vagrantup.com/) VM to run integration
+tests against OpenLDAP locally. *NOTE*: To support some of the SSL tests,
+Vagrant forwards localhost port 9389 to VM host port 9389. The port mapping
+goes away when you run `vagrant destroy`.
-To run integration tests locally:
+## Install Vagrant
+
+*NOTE*: The Vagrant gem (`gem install vagrant`) is
+[no longer supported](https://www.vagrantup.com/docs/installation/). If you've
+previously installed it, run `gem uninstall vagrant`. If you're an rbenv
+user, you probably want to follow that up with `rbenv rehash; hash -r`.
+
+If you use Homebrew on macOS:
+``` bash
+$ brew update
+$ brew cask install virtualbox
+$ brew cask install vagrant
+$ brew cask install vagrant-manager
+$ vagrant plugin install vagrant-vbguest
+```
+
+Installing Vagrant and virtualbox on other operating systems is left
+as an exercise to the reader. Note the `vagrant-vbguest` plugin is required
+to update the VirtualBox guest extensions in the guest VM image.
+
+## Run the tests
``` bash
# start VM (from the correct directory)
@@ -15,6 +38,9 @@ $ ip=$(vagrant ssh -- "ifconfig eth1 | grep -o -E '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]
# change back to root project directory
$ cd ../../../..
+# set the TCP port for testing
+$ export INTEGRATION_PORT=9389
+
# run all tests, including integration tests
$ time INTEGRATION=openldap INTEGRATION_HOST=$ip bundle exec rake
@@ -27,6 +53,12 @@ $ export INTEGRATION_HOST=$ip
# now run tests without having to set ENV variables
$ time bundle exec rake
+
+# Once you're all done
+$ cd test/support/vm/openldap
+$ vagrant destroy
```
-You may need to `gem install vagrant` first in order to provision the VM.
+If at any point your VM appears to have broken itself, `vagrant destroy`
+from the `test/support/vm/openldap` directory will blow it away. You can
+then do `vagrant up` and start over.
diff --git a/test/support/vm/openldap/Vagrantfile b/test/support/vm/openldap/Vagrantfile
index 96233e92..1f375e76 100644
--- a/test/support/vm/openldap/Vagrantfile
+++ b/test/support/vm/openldap/Vagrantfile
@@ -10,6 +10,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "hashicorp/precise64"
config.vm.network "private_network", type: :dhcp
+ config.vm.network "forwarded_port", guest: 389, host: 9389
config.ssh.forward_agent = true
diff --git a/test/test_helper.rb b/test/test_helper.rb
index cd34017c..0a976be4 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -14,10 +14,18 @@
if File.exist?("/etc/ssl/certs/cacert.pem")
"/etc/ssl/certs/cacert.pem"
else
- File.expand_path("fixtures/cacert.pem", File.dirname(__FILE__))
+ File.expand_path("fixtures/ca/cacert.pem", File.dirname(__FILE__))
end
end
+BIND_CREDS = {
+ method: :simple,
+ username: "uid=user1,ou=People,dc=rubyldap,dc=com",
+ password: "passworD1",
+}.freeze
+
+TLS_OPTS = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.merge({}).freeze
+
if RUBY_VERSION < "2.0"
class String
def b