Skip to content

"no such file" when connecting #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
thanatos opened this issue Feb 20, 2018 · 5 comments
Closed

"no such file" when connecting #176

thanatos opened this issue Feb 20, 2018 · 5 comments

Comments

@thanatos
Copy link

thanatos commented Feb 20, 2018

Issue description:

I am doing the following:

In [8]: con = ldap.initialize('ldaps://our-ldap-server.example.com', bytes_mode=False)
In [9]: con.bind('example', 'example')
---------------------------------------------------------------------------
SERVER_DOWN                               Traceback (most recent call last)
<ipython-input-9-fab3d0981c58> in <module>()
[… snip this frame; it's the above bind call …]
/opt/python3/lib/python3.6/site-packages/ldap/ldapobject.py in bind(self, who, cred, method)
    429     """
    430     assert method==ldap.AUTH_SIMPLE,'Only simple bind supported in LDAPObject.bind()'
--> 431     return self.simple_bind(who,cred)
    432
    433   def bind_s(self,who,cred,method=ldap.AUTH_SIMPLE):

/opt/python3/lib/python3.6/site-packages/ldap/ldapobject.py in simple_bind(self, who, cred, serverctrls, clientctrls)
    414         who = self._bytesify_input('who', who)
    415         cred = self._bytesify_input('cred', cred)
--> 416     return self._ldap_call(self._l.simple_bind,who,cred,RequestControlTuples(serverctrls),RequestControlTuples(clientctrls))
    417
    418   def simple_bind_s(self,who=None,cred=None,serverctrls=None,clientctrls=None):

/opt/python3/lib/python3.6/site-packages/ldap/ldapobject.py in _ldap_call(self, func, *args, **kwargs)
    306         self._trace_file.write('=> LDAPError - %s: %s\n' % (e.__class__.__name__,str(e)))
    307       try:
--> 308         reraise(exc_type, exc_value, exc_traceback)
    309       finally:
    310         exc_type = exc_value = exc_traceback = None

/opt/python3/lib/python3.6/site-packages/ldap/compat.py in reraise(exc_type, exc_value, exc_traceback)
     42         """
     43         # In Python 3, all exception info is contained in one object.
---> 44         raise exc_value
     45
     46 try:

/opt/python3/lib/python3.6/site-packages/ldap/ldapobject.py in _ldap_call(self, func, *args, **kwargs)
    290     try:
    291       try:
--> 292         result = func(*args,**kwargs)
    293         if __debug__ and self._trace_level>=2:
    294           if func.__name__!="unbind_ext":

SERVER_DOWN: {'desc': "Can't contact LDAP server", 'errno': 2, 'info': 'No such file or directory'}

I can definitely connect to that hostname/URL:

In [11]: socket.create_connection(('our-ldap-server.example.com', 443))
Out[11]: <socket.socket fd=12, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('X.X.X.X', 57860), raddr=('X.X.X.X', 443)>

Edit: I can also connect to port 636, which appears to be the port LDAP/TLS uses:

In [12]: socket.create_connection(('our-ldap-server.example.com', 636))
Out[12]: <socket.socket fd=13, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('X.X.X.X', 41318), raddr=('X.X.X.X', 636)>

But I don't think that's the problem; the nature of the error message ("not such file") seems to indicate that it is trying to connect to a Unix domain socket; I, of course, need it to use TCP. I think this is a simple error of some sort on my part, but looking at the docs, I am not sure what that is.

(I also expect to need to supply some form of certificate, s.t. TLS can authenticate. I don't see a place to that. I see #55, but that ticket's comments aren't informative enough to me for me to figure out where I'm going wrong.)

Steps to reproduce: (the above)

Operating system: Ubuntu Xenial

Python version: 3.6.4

python-ldap version: 3.0.0b4

@tiran
Copy link
Member

tiran commented Feb 20, 2018

The message No such file or directory is a red herring. It's simply the human readable message for ENOENT.

>>> import os, errno
>>> errno.ENOENT
2
>>> os.strerror(2)
'No such file or directory'

You can get more information by increasing the global debug level to 255, ldap.set_option(ldap.OPT_DEBUG_LEVEL, 255)

@thanatos
Copy link
Author

Yes, my presumption is that some underlying system call is emitting the ENOENT error, and given the rather abysmal lack of information in the stack trace, I had to guess.

The debug level change emits the following:

ldap_sasl_bind
ldap_send_initial_request
ldap_new_connection 1 1 0
ldap_int_open_connection
ldap_connect_to_host: TCP our-ldap-server.example.com:636
ldap_new_socket: 15
ldap_prepare_socket: 15
ldap_connect_to_host: Trying <ip of our-ldap-server.example.com>:636
ldap_pvt_connect: fd: 15 tm: -1 async: 0
attempting to connect:
connect success
ldap_err2string

So, it does seem to be connecting okay, but no information about where the failure is.

@thanatos
Copy link
Author

thanatos commented Feb 20, 2018

strace seems to indicate that it is attempting to open /etc/ssl/certs/ca-certificates.crt:

open("/etc/ssl/certs/ca-certificates.crt", O_RDONLY) = -1 ENOENT (No such file or directory)
write(2, "Traceback (most recent call last"..., 35Traceback (most recent call last):
) = 35

I've added con.set_option(ldap.OPT_X_TLS_CACERTFILE, "/ca-certs.crt"), but that doesn't actually cause it to stop trying to open that file.

Edit: but doing ldap.set_option(<same args>) appears to work; is that option only settable globally?

@tiran
Copy link
Member

tiran commented Feb 21, 2018

The option works also locally but you have to create a new TLS context after you have modified one or more TLS-related setting. It's a not so well-known quirk in OpenLDAP. I'll include a workaround in python-ldap 3.1.

con.set_option(ldap.OPT_X_TLS_CACERTFILE, "/ca-certs.crt")
con.set_option(ldap.OPT_X_TLS_NEWCTX, 0)

The ENOENT error may leak through OpenLDAP's TLS layer. What's the output of ldap.get_option(ldap.OPT_X_TLS_PACKAGE)?

@tiran
Copy link
Member

tiran commented May 28, 2020

I'm closing the issue as there was no activity in the last two years.

@tiran tiran closed this as completed May 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants