Search code examples
pythonpython-2.7openssldynamic-linkingpython-module

Cannot install a python module written in C, that links OpenSSL


I am trying to build and install a following "simple" module, that doesn't really do anything, but it fails.

In setup.py, I have this:

from distutils.core import setup, Extension

setup (
        name = 'sslmodule', 
        ext_modules = [
        Extension(
            'sslmodule',
            libraries = ['ssl'],
            sources = ['source.c'],
         )
   ]
)

In source.c, I have this code (that generates prime and then throws it away)

#include <Python.h>
#include <openssl/bn.h>

static PyObject * foobar(PyObject *self, PyObject *args) {
        BIGNUM * n; 

        n = BN_generate_prime(NULL, 5, 0, NULL, NULL, NULL, NULL);

        BN_clear_free(n);

        return NULL;
}


static PyMethodDef MyMethods[] = {
  {"foobar", foobar, METH_VARARGS, "does nothing"},
  {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initsslmodule(void)
{
    (void) Py_InitModule("sslmodule", MyMethods);
}

Nothing else in the module.

When running python setup.py build, this happens (wrapped here for better readability)

$ python setup.py build
running build
running build_ext
building 'sslmodule' extension
creating build
creating build/temp.linux-i686-2.7
i686-linux-gnu-gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall \
    -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c source.c -o \
    build/temp.linux-i686-2.7/source.o
creating build/lib.linux-i686-2.7
i686-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions \
    -Wl,-Bsymbolic-functions -Wl,-z,relro -fno-strict-aliasing -DNDEBUG -g -fwrapv \
    -O2 -Wall -Wstrict-prototypes -D_FORTIFY_SOURCE=2 -g -fstack-protector \
    --param=ssp-buffer-size=4 -Wformat -Werror=format-security \
    build/temp.linux-i686-2.7/source.o -lssl \
    -o build/lib.linux-i686-2.7/sslmodule.so 

When I run install, this happens (all OK)

$ sudo python setup.py install
running install
running build
running build_ext
running install_lib
copying build/lib.linux-i686-2.7/sslmodule.so -> /usr/local/lib/python2.7/dist-packages
running install_egg_info
Removing /usr/local/lib/python2.7/dist-packages/sslmodule-0.0.0.egg-info
Writing /usr/local/lib/python2.7/dist-packages/sslmodule-0.0.0.egg-info

However, when I try to import it into python, this happens

$ python -c 'import sslmodule'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: /usr/local/lib/python2.7/dist-packages/sslmodule.so: undefined symbol: BN_generate_prime

The sslmodule apparently isn't correctly linked to the SSL library. When I run ldd on the module, this happens (not sure if it's relevant) - no SSL dynamically linked

$ ldd  /usr/local/lib/python2.7/dist-packages/sslmodule.so
        linux-gate.so.1 =>  (0xb76e7000)
        libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb76a9000)
        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xb74fa000)
        /lib/ld-linux.so.2 (0xb76e8000)

I have Ubuntu, with python2.7, with packages libssl-dev, libssl1.0.0, libssl1.0.0-dbg all installed. What is wrong?

(In reality, it's actually this module that I can't install (issue here), but I tried to simplify the code here.)


edit:

When I try to run the auto-generated gcc command, but with -Xlinker --verbose, I got a lot of output, but this part is important for the ssl:

attempt to open /usr/lib/gcc/i686-linux-gnu/4.8/libssl.so failed
attempt to open /usr/lib/gcc/i686-linux-gnu/4.8/libssl.a failed
attempt to open /usr/lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/libssl.so succeeded
-lssl (/usr/lib/gcc/i686-linux-gnu/4.8/../../../i386-linux-gnu/libssl.so)

Which would suggest that the SSL is linked correctly. Yet, ldd still doesn't show libssl on the finished .so.


edit2:

It seems the question is morphing from python question to ld/gcc question. Anyway. When I add -z defs to the second gcc command, I see this

build/temp.linux-i686-2.7/source.o: In function `foobar':
(current directory)/source.c:7: undefined reference to `BN_generate_prime'
(current directory)/source.c:9: undefined reference to `BN_clear_free'
build/temp.linux-i686-2.7/source.o: In function `initsslmodule':
(current directory)/source.c:23: undefined reference to `Py_InitModule4'
collect2: error: ld returned 1 exit status

I have no idea why are the libraries not linked.


Solution

  • The answer was adding libcrypto as a library. So, in setup.py, changing this

    libraries = ['ssl'],
    

    into this

    libraries = ['ssl', 'crypto'],