MinGW, OpenSSL and OpenLDAP

This document seeks to guide the reader through the steps involved in building OpenSSL and OpenLDAP (with SSL/TLS support) on Windows using the MinGW toolset (and MSYS). It is aimed primarily at an audience wishing to compile LDAP client libraries for high-level languages such as Python or Ruby.

Therefore, instructions are included for the appropriate modules in both of these languages (python-ldap and Ruby/LDAP, respectively).

Software requirements/versions

I used the following versions of various software packages. Other versions will likely work fine, but have not been tested.

MinGW and MSYS

The “natural habitat” of OpenSSL and OpenLDAP is the landscape of Unix-like POSIX-compliant operating systems (Linux, Mac OS X, *BSD, and so on). However, circumstances place many users in front of Windows machines, while still desiring software tailor-made for a POSIX environment. MinGW (Minimalist GNU for Windows) is one response to this dilemma. It allows compiling of a large quantity of GNU (freely available) software so that it runs natively on Windows. The resulting executables or DLLs are redistributable, needing no extra libraries in order to run. (Cygwin, an alternative, needs its own library for its binaries to work.)

MSYS (Minimal SYStem) is a build environment for MinGW, offering POSIX-similar behavior so that automatic configuration scripts and build tools run as intended.

Installation

MinGW installation is fairly straight-forward, if you download the automated installer. I use the default path, “C:\MinGW” for my installation.

For MSYS, start by downloading the exe file (1.0.10 at the time of this writing). I then downloaded most of the packages in the Technology Preview category, which may be unnecessary. Unfortunately, each of them needs to be installed separately. If you do not have the tar utility and its friends (or if you prefer a graphical interface), free compression utilities like TUGZip or 7-zip work very well.

A better alternative: (Thanks to Waldemar Osuch for this advice!) Simply download and install msysCORE-1.0.11-2007.01.19-1.tar.bz2, then run "msys/postinstall/pi.bat".

Once MSYS is installed and optionally upgraded, a couple other packages are needed: libiconv, zlib, and GNU regex. The first two are available as mingwPORTs, and that is how I installed them. Just follow the directions, and things should work fine. There is a user contributed port of GNU regex to MinGW available from the MinGW downloads. I used it, and it worked well.

OpenSSL

If you have no need of security, OpenLDAP will work fine without OpenSSL. However, most prefer encryption when authenticating remotely. SSL/TLS in OpenLDAP depend on OpenSSL.

Installation

  1. The configuration script wants to use Perl. There is a good MSYS-tailored version available from MSYS Supplementary Tools. On windows, Strawberry Perl is also a good option. Install it before proceeding. If you already have Perl installed, just be sure it is in your PATH.
  2. Extract the OpenSSL package to a location of your choosing. If you have Cygwin installed you can typethe following at the Cygwin prompt: tar zxf openssl-0.9.8g.tar.gz If you do not, TUGZip and 7-zip should extract the files without a problem. MinGW's tar has trouble with symlinks.
  3. OpenLDAP appears to want the OpenSSL libraries built “shared.” In order to do this, however, the “Configure” script needs to be edited as follows (many thanks to Victor Wagner for this hint):
    • Find the line that begins "mingw" Conveniently, the previous line reads # MinGW
    • Look at the end of the line where the code reads: -DOPENSSL_USE_APPLINK:-mno-cygwin -shared:.dll.a
    • And change it to read: -DOPENSSL_USE_APPLINK:-mno-cygwin -Wl,--export-all -shared:.dll.a
  4. Now launch MSYS, cd to the openssl directory, and type: ./config --prefix=/mingw --openssldir=/mingw/openssl shared (I do not think the openssldir is all that important, for our purposes anyway. The prefix, however, is.)
  5. When this is finished, type make
  6. Then make install
  7. Copy the appropriate libraries to where the compiler can see them: cp *.a /mingw/lib
  8. And the same for the DLLs: cp *.dll /mingw/bin

OpenLDAP

This is what we came here to do. Again, I am only interested in the client libraries, so I do not intend to compile slapd, slurpd, etc. The same procedures may work with some modifications, but I have not tested it.

Installation

  1. OpenLDAP wants a couple utilities available before compiling and installation will proceed smoothly:
    • It uses cygpath.exe to check actual pathnames, and this can be downloaded from Cygwin. If you don't want all of Cygwin, I put together a self-extracting archive of the two files needed. Just extract them in your PATH.
    • For documentation (which we don't need, ironically), it uses soelim.exe, which I downloaded from the GnuWin32 groff package. Place it in your PATH (C:\MinGW\bin is as good a place as any).
  2. Now you can configure OpenLDAP. Again, I have disabled things that I do not need. I have also designated the configuration directory to be the root of the C: drive. This will result in the creation of C:\openldap\ldap.conf when you run “make install.” Sorry that it is hard-coded. I do not know of another way. Anyone you give your DLLs to will need to have this directory at the same location if they want to configure OpenLDAP (with certs, and so on). (Note: the following should be all one line.) ./configure --with-ssl --with-tls --disable-slapd --disable-backends --disable-slurpd --prefix=/mingw --sysconfdir=/c
  3. If it configured correctly, you should be able to enter (each will take some time): make depend
    make
    make install
  4. Copy the following DLLs into your PATH. They should be in your normal PATH, not /mingw/bin (where they likely already are), unless this is normally in your PATH. These are the DLLs that will need to be distributed with any software package you give to others.
    • cryptoeay32-0.9.8.dll
    • ssleay32-0.9.8.dll
    • liblber.dll
    • libldap.dll
    • libldap_r.dll
  5. Check that you have a directory C:\openldap, and that it has ldap.conf in it. If you know what you are doing with certs, etc., go ahead and configure it how you want. I go for a simple, albeit insecure, configuration by adding the following line to ldap.conf. Otherwise, my LDAP clients are unable to connect successfully using SSL or TLS. TLS_REQCERT never

Python-ldap

Installation

Compiling the python-ldap module is fairly simple. Again, once complete, you will still need the previously-compiled DLLs somewhere in your PATH.
  1. Unpack the python-ldap source.
  2. Launch MSYS and cd to the python-ldap source.
  3. Edit config.cfg. Mine (download it, if you want) looks like this: [_ldap]
    class = OpenLDAP2
    defines = WIN32

    library_dirs = /mingw/lib
    include_dirs = /mingw/include

    libs = ldap_r lber ssl crypto ws2_32 gdi32

    # Installation options
    [install]
    compile = 1
    optimize = 1

    [bdist_wininst]
    target_version = 2.5
  4. Build it (using the path to your Python; mine is in C:\Python25): /c/python25/python setup.py build --compiler=mingw32
  5. Build the Windows installer /c/python25/python setup.py bdist_wininst
  6. In dist, you should see “python-ldap-2.3.1.win32-py2.5.exe”

Note: Waldemar Osuch has some helpful advice:

When building the python extension I have temporarily tweaked Mingw32CCompiler from distutils/cygwincompiler.py to force static linking. No need for *.dll distribution. 294 # ld_version >= "2.13" support -shared so use it instead of
295 # -mdll -static
296 if self.ld_version >= "2.13":
297 shared_option = "-shared"
298 else:
299 shared_option = "-mdll -static"
300 #TODO Uncomment for python-ldap
301 #shared_option = "-mdll -static"

Ruby/LDAP

Now that you have come this far, I should point out that Ruby/LDAP builds fine using Microsoft Visual C++ 2003, and uses Microsoft's very own wldap32.dll. If you are interfacing with Active Directory, I would stick with the Microsoft option. However, if you are working with another solution, such as eDirectory or an OpenLDAP server, you may have security problems when wldap32.dll doesn't find exactly what it wants in terms of certificates, etc. Or, as in our situation, you may be developing Ruby on Rails apps locally, and want to be sure that your development environment uses similar libraries to the ones on your Linux or *BSD web server (which most likely uses OpenLDAP). Compiling Ruby/LDAP against OpenLDAP may be a good option.

Installation

  1. This is a little more complicated than Python's procedure. First, we need to compile Ruby using MinGW/MSYS. Download the source, unpack it, launch MSYS and cd to the source directory.
  2. Configure it: ./configure --prefix=/mingw --with-winsock2
  3. Then run the following, in order: make
    make install
  4. Now, unpack the ruby-ldap source
  5. cd into it, then run ruby extconf.rb
  6. If no errors you should be able to make
  7. You can now copy ldap.so and lib/ldap/ to C:\ruby\lib\ruby\site_ruby\1.8\i386-msvcrt
  8. Or...

Building the gem

  1. Copy ldap.so into the lib directory cp ldap.so lib
  2. Create an ldap.gemspec file in the root of the source tree. I use the following (or you can download it): Gem::Specification.new do |spec|
      spec.authors = ['Takaaki Tateishi', 'Ian Macdonald']
      spec.email = 'ian@caliban.org'
      spec.has_rdoc = true
      spec.homepage = 'http://ruby-ldap.sourceforge.net/'
      spec.name = 'ldap'
      spec.summary = 'LDAP library for Ruby'
      spec.description = <<-EOF
        ldap is a Ruby library to perform queries on an LDAP server
      EOF
      spec.version = '0.9.7'
      spec.platform = Gem::Platform::CURRENT
      spec.files = Dir['lib/**/*.rb'] + Dir['lib/*.so']
      spec.required_ruby_version = '>= 1.8.0'
      spec.require_paths = ['lib']
    end
  3. Enter gem build ldap.gemspec
  4. Take the gem anywhere, and install it with: gem install gem install ldap-0.9.7-x86-mswin32.gem
  5. If you have the OpenLDAP/OpenSSL DLLs and ldap.conf installed properly, things should work for you.
Written by Jonathan Bowman, April 22, 2008.