cannatag / ldap3 Goto Github PK
View Code? Open in Web Editor NEWa strictly RFC 4510 conforming LDAP V3 pure Python client. The same codebase works with Python 2. Python 3, PyPy and PyPy3
License: Other
a strictly RFC 4510 conforming LDAP V3 pure Python client. The same codebase works with Python 2. Python 3, PyPy and PyPy3
License: Other
Short version: When searching from a top level domain against a sub-domain, an LDAPInvalidScopeError is thrown. When printed to the console, the arguments are of different types than those expected by the value checks.
With an authenticated bind to:
dc=mydomain,dc=tld
I submit the following to the search function:
search_base
'cn=users,dc=subdomain,dc=mydomain,dc=tld'
search_filter
'(objectclass=*)'
search_scope
'SUBTREE'
size_limit
500
I put pass the arguments for search_operation() in ldap3/operation/search.py to print(), prior to any value checks, and get the following output:
search_base
'cn=users,dc=subdomain,dc=mydomain,dc=tld'
search_filter
'(objectclass=*)'
search_scope
2
dereference_aliases
3
attributes
['1.1']
size_limit
0
time_limit
0
types_only
False
schema
None
Sorry for all the bug reports. Ready to test changes, please advise.
Hi,
trying to install this package with easy_install
fails.
$ easy_install-3.4 ldap3
Searching for ldap3
Reading https://pypi.python.org/simple/ldap3/
Best match: ldap3 0.9.7.1
Downloading https://pypi.python.org/packages/source/l/ldap3/ldap3-0.9.7.1.tar.gz#md5=da7e3dc4d6c41e406cfe9de24f91ded8
Processing ldap3-0.9.7.1.tar.gz
Writing /tmp/easy_install-2ai16tq3/ldap3-0.9.7.1/setup.cfg
Running ldap3-0.9.7.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-2ai16tq3/ldap3-0.9.7.1/egg-dist-tmp-yai_rxoa
error: [Errno 2] No such file or directory: '_version.py'
pip install
does work, probably because it unpacks and runs setup in the same directory. You could define your _version.py attributes in setup.cfg
Hello,
I'm trying to implement an LDAP login screen interfacing with an OpenLDAP server. Normal negotiations are executing fine, however the OpenLDAP server I'm negotiating with also implements Password Policy Overlay
. This overlay requires its Control Request
to contain two fields. The Control Value
field should not be sent, otherwise OpenLDAP server returns a ProtocolError
(even if the field is empty).
Unfortunately there's no way to not to send the value field with the control requests. Adding the ability to send controls with no value fields is necessary to implement Password Policy Overlay
. It's not possible to implement Password Policy Overlay
.
Hi
When I print an Attribute which holds a non-string value (an int in this case) I get this error:
__str__ returned non-string (type int)
I believe the following will fix the issue:
@@ -63,7 +63,7 @@ class Attribute(object):
def __str__(self):
if len(self.values) == 1:
- return self.values[0]
+ return str(self.values[0])
else:
return str(self.values)
I think i found an issue within the PagedSearch.py
Line 67: cookie = result['controls']['1.2.840.113556.1.4.319']['value']['cookie']
Suppose the openldap server has a result limit (olcSizeLimit) of 500 and the client requests a query which yields more than 500 results. This will raise an KeyError on the given line. This is probably due to the fact that the server cleared the cookie when the client hit the hard limit of 500 results. Can this be handled some how on the client side?
Thanks a lot btw for a great library :-)
Here is my code:
from ldap3 import Server, Connection, ALL, BASE, STRATEGY_SYNC, ANONYMOUS
s = Server('dmc.solarcity.local',port=389,get_info=ALL)
with Connection(server=s,auto_bind=True,client_strategy=STRATEGY_SYNC,authentication=ANONYMOUS) as c:
print(c.result)
c.search(search_base='OU=SolarCity Users,DC=SolarCity,DC=local',search_filter='(objectclass=user)',search_scope=BASE)
print(c.result)
that outputs the following:
{'referrals': None, 'description': 'success', 'dn': '', 'type': 'bindResponse',
'saslCreds': None, 'result': 0, 'message': ''}
{'referrals': None, 'description': 'operationsError', 'message': '000004DC: Ldap
Err: DSID-0C0906E8, comment: In order to perform this operation a successful bin
d must be completed on the connection., data 0, v1db1\x00', 'dn': '', 'type': 's
earchResDone', 'result': 1}
Why is the bind successful and then in the very next line saying that it is not successful? Thanks.
EDIT: I figured it out, thanks, it was an issue on my end.
I have only seen this issue with the accountExpires attribute. Upon returning from a search, it is not being converted to a datetime object like other such attributes (lastLogon, badPasswordTime, etc.).
Clearly other values are being formatted with format_ad_timestamp() but accountExpires is consistently returned as a binary string.
Hi,
I have a DN and want to get the data for this object. I could not figure how to to this with ldap3.
Thank you very much
Regards
Ludwig
I think I found a bug, but maybe it is user error.
I'm trying to create an add that replicates:
dn: cn=test2,ou=Groups,dc=example,dc=edu
changetype: add
objectClass: groupOfNames
objectClass: top
cn: test2
member:
Having member:
empty is valid for 389-ds which is used to create an empty groupOfNames
object. I have not been able to replicate this using ldap3.
Using variations of:
.add(
groupDn,
object_class=['groupOfNames', 'top'],
attributes={'cn': "test2", 'member': None},
controls=None
)
I've tried setting member
to None
, ''
, and []
. They either cause TypeErrors or LDAP errors. Leaving the member
attribute out all together causes an error because member
is a required attribute.
Thoughts?
Hi,
I made some performance comparisons between AD and OpenLDAP using ldap3, and I found that AD was very very slow.
After some investigations with a profiling tools, I found that a lot of time was spent in _getkey from cidict.py. A simple BIND takes 5s, cidict.py was called 5491 time (the same test with OpenLdap reports 0.09s and 662 calls).
After updating the code by adding a _insensitive_key_map dict to save the correspondance between key.lower() and key, and removing the loop, the performance was 0.67s for the BIND in AD and 0.07s for OpenLDAP.
Best regards,
Pierre Mellier
Hi,
I just noticed that when the bind occurs, the message['type'] is empty and makes the method update_transmitted_message() crash.
How to reproduce:
Try to bind with Connection(..., collect_usage=True, ...)
.
Here is how I init my connection object:
self.connection = Connection(self.server,
auto_bind=True,
client_strategy=SYNC,
user=username,
password=password,
authentication=SIMPLE,
check_names=True,
collect_usage=True)
It would crash in usage.py on line 161, at the first if:
def update_transmitted_message(self, message, length):
self.bytes_transmitted += length
self.operations += 1
self.messages_transmitted += 1
if message['type'] == 'abandonRequest': <---- crashes because message is None
self.abandon_operations += 1
...
It is possible to quick fix by putting the IFs in a try/catch block, but it doesn't fix the issue that message['type'] isn't set for bind requests.
In Python 3.x on OpenBSD 5.7, socket.AI_V4MAPPED is not defined. I am afraid AI_V4MAPPED is not supported by the OS.
As a result, core/server.address_info()'s reference to the constant causes an error.
I would like you to remove the flag unless it it is absolutely needed,
From reading the available docs, I cannot find out how to replace the
following python-ldap script fragment:
c = ldap.open('ldap.example.com')
DN = 'cn=objectcn,dc=ldap,dc=example,dc=com'
ATT = 'cn'
OVAL = 'testValue'
NVAL = 'setValue'
c.modify_s(DN, [(ldap.MOD_ADD, ATT, OVAL),
(ldap.MOD_DELETE, ATT, NVAL)])
which would translate to the following LDIF atomic change operation:
dn: cn=objectcn,dc=ldap,dc=example,dc=com
changetype: modify
delete: cn
cn: testValue
-
add: cn
cn: setValue
While the change operations are sequenced, the modify change will happen atomically on the server.
For the use of the operation as a locking primitive, see:
Any attempt to connect to an LDAP server fails with "LDAPSocketOpenError: invalid server address" on FreeBSD. This is because getaddrinfo(3) on FreeBSD does not accept AI_V4MAPPED flag as a hint, and fails with error code 3 ("Invalid value for ai_flags") if this flag is set. The following patch fixed (or worked around) the problem for me: https://gist.github.com/andriy-s/ac502e1d27ba4f19912d
In operation/search.py, line 109,
left_part, _, right_part = match.split('=')=')
should be
left_part, _, right_part = match.partition('
(like other operators)
Hello.
Given the ldap search filter:
(&(objectClass=person)(objectClass=top)(objectClass=inetOrgPerson (objectClass=organizationalPerson)(!(uid=tuz)))
I am getting the error:
[...]
File "/home/brian/tree/karaage/python-tldap/tldap/backend/base.py", line 162, in first_results
base, filterstr, scope, attributes=attrlist, paged_size=limit)
File "/usr/lib/python2.7/dist-packages/ldap3/core/connection.py", line 568, in search
request = search_operation(search_base, search_filter, search_scope, dereference_aliases, attributes, size_limit, time_limit, types_only, self.server.schema if self.server else None)
File "/usr/lib/python2.7/dist-packages/ldap3/operation/search.py", line 365, in search_operation
request['filter'] = build_filter(search_filter, schema) # parse the searchFilter string and compile it starting from the root node
File "/usr/lib/python2.7/dist-packages/ldap3/operation/search.py", line 312, in build_filter
return compile_filter(parse_filter(search_filter, schema).elements[0])
File "/usr/lib/python2.7/dist-packages/ldap3/operation/search.py", line 243, in compile_filter
boolean_filter[pos] = compile_filter(element)
File "/usr/lib/python2.7/dist-packages/ldap3/operation/search.py", line 256, in compile_filter
compiled_filter['notFilter'] = boolean_filter
File "/usr/lib/python2.7/dist-packages/pyasn1/type/univ.py", line 824, in __setitem__
self.setComponentByName(idx, value)
File "/usr/lib/python2.7/dist-packages/pyasn1/type/univ.py", line 859, in setComponentByName
self._componentType.getPositionByName(name),value,verifyConstraints
File "/usr/lib/python2.7/dist-packages/pyasn1/type/univ.py", line 1093, in setComponentByPosition
self._verifyComponent(idx, value)
File "/usr/lib/python2.7/dist-packages/pyasn1/type/univ.py", line 848, in _verifyComponent
raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, t))
PyAsn1Error: Component value is tag-incompatible: Not(componentType=NamedTypes(NamedType('innerNotFilter', Filter(componentType=NamedTypes(NamedType('and', And(componentType=None)), NamedType('or', Or(componentType=None)), NamedType('notFilter', Not(componentType=NamedTypes(), tagSet=TagSet((), ))), NamedType('equalityMatch', EqualityMatch(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('substringFilter', SubstringFilter(componentType=NamedTypes(NamedType('type', AttributeDescription()), NamedType('substrings', Substrings())))), NamedType('greaterOrEqual', GreaterOrEqual(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('lessOrEqual', LessOrEqual(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('present', Present()), NamedType('approxMatch', ApproxMatch(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('extensibleMatch', ExtensibleMatch(componentType=NamedTypes(OptionalNamedType('matchingRule', MatchingRule()), OptionalNamedType('type', Type()), NamedType('matchValue', MatchValue()), DefaultedNamedType('dnAttributes', DnAttributes('False')))))))))).setComponents(Filter(componentType=NamedTypes(NamedType('and', And(componentType=None)), NamedType('or', Or(componentType=None)), NamedType('notFilter', Not(componentType=NamedTypes(), tagSet=TagSet((), ))), NamedType('equalityMatch', EqualityMatch(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('substringFilter', SubstringFilter(componentType=NamedTypes(NamedType('type', AttributeDescription()), NamedType('substrings', Substrings())))), NamedType('greaterOrEqual', GreaterOrEqual(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('lessOrEqual', LessOrEqual(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('present', Present()), NamedType('approxMatch', ApproxMatch(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('extensibleMatch', ExtensibleMatch(componentType=NamedTypes(OptionalNamedType('matchingRule', MatchingRule()), OptionalNamedType('type', Type()), NamedType('matchValue', MatchValue()), DefaultedNamedType('dnAttributes', DnAttributes('False'))))))).setComponents(None, None, None, EqualityMatch(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue()))).setComponents(AttributeDescription('uid'), AssertionValue('tuz')))) vs Not(componentType=NamedTypes(), tagSet=TagSet((), ))
----------------------------------------------------------------------
This was working, I suspect an update in another package may have broken it.
This is with python-ldap3 version 0.9.8.4
pyasn1 is the obvious suspect. Debian/jessie has version 0.1.7, which works; Debian/sid has version 0.1.8 which fails. Will try to prove if the change in version of pyasn1 causes the problem or not.
First, thanks for a really well done library! It's already been extraordinarily helpful for us.
Our local setup uses the GSSAPI SASL mechanism to authenticate to LDAP via Kerberos. From reading the code, I don't think this is currently supported by ldap3, though it looks like some other SASL mechanisms are supported already.
I'm not sure how practical it is, but it'd be really cool if this was supported in some future release.
I notice there's a python-gssapi module, which looks like it might be helpful, but it's using a C extension to interface with GSSAPI, which I'm guessing might be an issue.
I'm going to try to get something working with python-gssapi as a starting point, but any insights you have would be greatly appreciated!
new_password = c.extend.standard.modify_password('uid=boris,ou=people,dc=foo,dc=bar,dc=com', 'OLDPASS', 'NEWPASS', 'SALTED_SHA256')
File "/usr/lib64/python3.4/site-packages/ldap3/extend/__init__.py", line 61, in modify_password
return ModifyPassword(self._connection, user, old_password, new_password, hashed).send()
File "/usr/lib64/python3.4/site-packages/ldap3/extend/standard/modifyPassword.py", line 52, in __init__
self.request_value['newPasswd'] = hashed(hash_algorithm, new_password, salt)
File "/usr/lib64/python3.4/site-packages/ldap3/utils/hashed.py", line 74, in hashed
digest = hashed(salted_table[algorithm][1], value + salt, raw=True) + salt
TypeError: Can't convert 'bytes' object to str implicitly
It looks like there is a documentation error on this page:
http://ldap3.readthedocs.org/en/latest/connections.html
Specifically, the changes structure for the modify operation is listed as:
{โattribute1โ: [(operation, [val1, val2, ...])], โattribute2โ: [(operation, [val1, val2, ...])]}
This does not work, giving ldap3.core.exceptions.LDAPChangesError: malformed change
. Looking at the test code, it should be:
{โattribute1โ: (operation, [val1, val2, ...]), โattribute2โ: (operation, [val1, val2, ...])}
Thanks!
(There operation Tuple should not be enclosed in a list.)
Hi, I've got a package that has a pinned requirement to 0.9.8.2 which doesn't seem to be available anymore on pypi. I'm just wondering if that was removed from pypi for a specific reason, or if it would be possible to keep old versions available there.
thanks!
On Samba and Windows, when attempting to retrieve entries with entries(), a KeyError is thrown for the attributes key.
>>>
connection.entries()
Traceback (most recent call last):
File "", line 1, in
File "/venv/lib/python3.4/site-packages/ldap3/core/connection.py", line 1174, in entries
self._entries = self._get_entries(self.response)
File "/venv/lib/python3.4/site-packages/ldap3/core/connection.py", line 1184, in _get_entries
resp_attr_set = set(response['attributes'].keys())
KeyError: 'attributes'
It appears that the issue is in the response object. connection.py iterates over connection.response and uses the key attributes to access the dictionary. However, on Samba and Windows, connection.response also contains elements of type: searchResRef with referral uri's for other naming contexts. For example:
[{'attributes': {'givenName': 'john'},
'dn': 'CN=jbaker,OU=Engineering,OU=departments,DC=mydomain,DC=com',
'raw_attributes': {'givenName': [b'john']},
'type': 'searchResEntry'},
{'type': 'searchResRef',
'uri': ['ldap://mydomain.com/CN=Configuration,DC=mydomain,DC=com']},
{'type': 'searchResRef',
'uri': ['ldap://mydomain.com/DC=DomainDnsZones,DC=mydomain,DC=com']},
{'type': 'searchResRef',
'uri': ['ldap://mydomain.com/DC=ForestDnsZones,DC=mydomain,DC=com']}]
Am I missing something? I'm really enjoying this module. Thanks for the great work you've done.
When attempting to rename an object with connection.modify_dn(), an error is raised with the message ERROR, 00002035: Unwilling to perform. Old RDN must be deleted on Samba domain controllers. With full debug logging on, it appears that the correct information is being transmitted to the server. This operation has been tested against Microsoft Server 2008 R2 and OpenLDAP with success.
I've had similar issues in the past with the python-ldap library but currently I cannot find the code to illustrate resolution. This issue may be specifically Samba related but thought it should be noted here.
Default values for an AttrDef
that are falsy, will not be used. For example:
user = ObjectDef()
user += AttrDef('memberOf', key='groups', default=[])
# Load an user entry that has no "memberOf" attribute with a reader
# If you now access the "groups" attribute of the entry ...
entry.groups
# ... you get
ldap3.core.exceptions.LDAPKeyError: 'key not found'
The problem is the test for default values in reader module.
These are my first steps to ldap3. I have an OpenLDAP server that accepts StartTLS on port 389.
want to use SSL-certs to authz-to to a special user. This all works perfectly with python-ldap in python2.7. Now that I try to port some software to python3.4, I wanted to use ldap3.
Here is what I tried so far:
import ssl
from ldap3 import Server, Connection, Tls, AUTH_SASL, SUBTREE
tls_configuration = Tls(local_private_key_file='/etc/ssl/private/mx.roessner-net.de.key',
local_certificate_file='/etc/ssl/certs/mx.roessner-net.de.crt',
ca_certs_file='/etc/ssl/certs/ca-certificates.crt',
validate=ssl.CERT_REQUIRED,
version=ssl.PROTOCOL_TLSv1)
server = Server('db.roessner-net.de',
tls=tls_configuration)
conn = Connection(server,
authentication=AUTH_SASL,
sasl_mechanism='EXTERNAL',
sasl_credentials=())
conn.open()
conn.start_tls()
bind = conn.do_sasl_bind(controls=None)
print("bind: %s" % str(bind))
i_am = conn.extend.standard.who_am_i()
print(i_am)
conn.search(search_base='ou=people,ou=it,dc=roessner-net,dc=de',
search_filter='(objectclass=*)',
attributes=['cn'],
search_scope=SUBTREE)
print(conn)
Trying to use this, I receive an error:
bind: {'type': 'bindResponse', 'dn': '', 'saslCreds': b'', 'referrals': None, 'message': 'SASL(0): successful result: ', 'description': 'saslBindInProgress', 'result': 14}
Traceback (most recent call last):
File "./ldap-test.py", line 27, in
i_am = conn.extend.standard.who_am_i()
File "/usr/lib64/python3.4/site-packages/ldap3/extend/init.py", line 53, in who_am_i
return WhoAmI(self._connection).send()
File "/usr/lib64/python3.4/site-packages/ldap3/extend/operation.py", line 57, in send
self.decode_response()
File "/usr/lib64/python3.4/site-packages/ldap3/extend/operation.py", line 69, in decode_response
raise LDAPExtensionError('extended operation error: ' + self.result['description'] + ' - ' + self.result['message'])
ldap3.core.exceptions.LDAPExtensionError: extended operation error: operationsError - SASL bind in progress
I spent hours now, but I do not get it to work. I have no idea, if I did something wrong or if I just encountered a bug. So I ask you, if you can give me a hint.
I want ldap3 for automx, which you also find as an OSS here on Github ;-)
Hello,
For some reason I thought this was already fixed, but it seems like I was mistaken. I can't find that bug right now.
I get Connection Refused when connecting to localhost, if localhost resolves as ::1 and 127.0.0.1, and when the ldap server is only listening on 127.0.0.1
If the IPv6 connection fails, it should fall back to the IPv4 address automatically.
Regards
As far as I understand, I could use this package to parse an LDIF file like this:
from ldap3 import Connection, LDIF
c = Connection(None, client_strategy=LDIF, read_only=True)
c.stream = open('foo.ldif', 'w')
with c:
...
If the stream object is not writable (i.e. not stream.writable()
) this won't work. I guess this is the desired effect when talking to a real server. But it is at least confusing when parsing a file.
I can see multiple solutions to this:
server
is None
and read_only
is trueMaybe a solution is aleady in place and I just did not find it. In that case I would be thankful for a hint.
Somewhere between commits 568b69a...6e918c3 the ssl.SSLError
exception is no longer raised when a certificate issue is detected. Using the following example:
import inspect
import ssl
import ldap3
# username, password, host, port defined here
server = ldap3.Server(host, port=port, use_ssl=True,
tls=ldap3.Tls(validate=ssl.CERT_REQUIRED))
conn = ldap3.Connection(server, user=username, password=password,
raise_exceptions=True)
try:
conn.open()
except Exception as e:
from pprint import pprint
pprint(inspect.getmro(type(e)))
the following is output in 568b69a
(<class 'ldap3.core.exceptions.LDAPSocketOpenError'>,
<class 'ldap3.core.exceptions.LDAPSocketOpenError'>,
<class 'ldap3.core.exceptions.LDAPCommunicationError'>,
<class 'ldap3.core.exceptions.LDAPExceptionError'>,
<class 'ldap3.core.exceptions.LDAPException'>,
<class 'ssl.SSLError'>,
<class 'socket.error'>,
<type 'exceptions.IOError'>,
<type 'exceptions.EnvironmentError'>,
<type 'exceptions.StandardError'>,
<type 'exceptions.Exception'>,
<type 'exceptions.BaseException'>,
<type 'object'>)
but in 6e918c3 it is as follows:
(<class 'ldap3.core.exceptions.LDAPSocketOpenError'>,
<class 'ldap3.core.exceptions.LDAPCommunicationError'>,
<class 'ldap3.core.exceptions.LDAPExceptionError'>,
<class 'ldap3.core.exceptions.LDAPException'>,
<type 'exceptions.Exception'>,
<type 'exceptions.BaseException'>,
<type 'object'>)
There should be some way to differentiate between a connection error due to a port not actually being open and an error due to certificate verification problems.
Is there a way to connect to the AD that the current machine is connected to, without supplying connection parameters?
File "/lib/python3.4/site-packages/ldap3/extend/init.py", line 61, in modify_password
return ModifyPassword(self._connection, user, old_password, new_password, hashed).send()
File "/lib/python3.4/site-packages/ldap3/extend/standard/modifyPassword.py", line 52, in init
self.request_value['newPasswd'] = hashed(hash_algorithm, new_password, salt)
File "/lib/python3.4/site-packages/ldap3/utils/hashed.py", line 81, in hashed
digest = hashlib.new(algorithm, value).digest()
File "/lib/python3.4/hashlib.py", line 122, in __hash_new
return _hashlib.new(name, data)
TypeError: name must be a string
Hello ldap3 team,
I'm trying to use your library to authenticate with an LDAP server. I'm not sure I'm performing the search operation correctly and would really appreciate it if you guys could help with the expected syntax (RFC4515 compliant) of the search_filter
argument. I've opened a question on stackoverflow and would really appreciate it if you guys could help.
Please find the link below:
Thank you.
Regards,
Khalid F. Al Khalili
Hello,
If I try to connect using START_TLS to a server using its IP address instead of its hostname, it still works.
This is despite the fact that only the hostname is included in the certificate.
This allows man in the middle attacks because I might be trying to connect to server.example.org, but get a valid certificate from maninthemiddle.example.org instead, and I will send my credentials to the wrong server.
Ideally this needs to be configurable, as I do have some broken systems that do identify themselves with the wrong name.
This is with validate = ssl.CERT_REQUIRED
Looking at the code, it looks like it is suppose to check the certificate in the check_hostname function, so I am going to try and work out why that doesn't appear to be working (or if I am doing something wrong), and I will report back here.
Thanks
When using a server pool with active=True
and exhaust=True
, if an LDAP server goes offline, it is never able to be used again. In a case where there may only be 2 servers in the pool, this is really detrimental to a stateful app, and requires the app to be restarted in order to re-negotiate connections to these LDAP servers.
To try combat this, I have attempted to use exhaust=False
. With the server offline, I attempt to make an LDAP connection, however the pool ends up in a loop attempting to find an active server. The loop never breaks when the server comes back online, and leads to an endless loop of polling.
Hi,
Is there a way to intercept messages that are sent and received from the LDAP server?
It would be useful for troubleshooting.
Right now I was thinking about extending a client strategy (i.e. extend the SYNC strategy) methods to get the messages but it doesn't seems to be the best way of doing that. Any idea?
Thanks!
--Phil
I can't get SSLv3 to work on my install. I have an LDAP that for various reasons is not TLS capable, only SSLv3.
Trying:
s = Server('ldaps.oldserver.com', port=636, use_ssl=True)
c = Connection(s, user='test', password='test', auto_bind=True)
Yields:
LDAPSocketOpenError: ('socket ssl wrapping error: [SSL: UNSUPPORTED_PROTOCOL] unsupported protocol (_ssl.c:600)',)
I then tried:
s = Server('ldaps.oldserver.com', port=636, use_ssl=True, tls=Tls(version=ssl.PROTOCOL_SSLv3)
c = Connection(s, user='test', password='test', auto_bind=True)
with the same result.
Reading into the python ssl module documentation (https://docs.python.org/dev/library/ssl.html#context-creation) shows that the default is to have SSLv3 disabled.
I tried adding the workaround in the documentation to the ldap3 code, but it still doesn't work.
In the end, I changed the code where the SSL context is created from using create_default_context to creating an SSLContext with protocol on creating and then adding the settings, though I doubt this is the correct solution.
Documentation mentions a .search_sub_tree()
method on Reader
in abstraction.rst:146 but the code is nowhere to be found. Is the function still available ?
I would really like to take advantage of this in an ongoing project.
I tried to look inside the documentation but it wasn't clear on how someone can get a list of supported attributes for a certain LDAP class.
I want to get a list of attributes for the person class. Thanks.
I am regularly hitting an issue where I have a specific ldap3 version in my requirements files but these older versions keep disappearing from PyPI (ie. v0.9.7.11 was only release in March but is no longer available - https://pypi.python.org/simple/ldap3/).
This is a real pain because I have specifically pinned certain versions of ldap3 because that is what has been tested against and provide a known working environment. It means that when I come back to work on a project after no touching it for a few month I can no longer recreate the known working environment because the old versions no longer exist.
Are these old versions being actively deleted? if so can they be restored, or at a minimum can older version no longer be deleted from this point onwards.
It would be nice if ldap3 would support SASL NTLM, to be able to bind to active directorY, that has no domain controller certificate enrolled.
I define my connection look like this:
self.conn = Connection(self.server,
user=user,
password=str(password),
authentication=AUTH_SIMPLE,
auto_bind=AUTO_BIND_NO_TLS)
the result of self.conn is OK:
{'result': 0, 'description': 'success', 'saslCreds': None, 'referrals': None, 'message': '', 'dn': '', 'type': 'bindResponse'}
but when i use this self.conn to modify my userPassword, it returned a different result, and the modify action failed.
with self.conn as c:
c.extend.standard.modify_password(user=dn,
old_password=old_password,
new_password=new_password)
the result looks like this:
{'dn': '', 'type': 'extendedResp', 'responseName': None, 'referrals': None, 'result': 50, 'description': 'insufficientAccessRights', 'message': '', 'responseValue': b''}
why the the value of result changes to 50? should i need something special when i do an extend request?
Is there an example for using the SASL credentials with creating the connection?
This does not work for me:
c = Connection(s,
auto_bind = False,
client_strategy = SYNC,
sasl_mechanism="DIGEST-MD5",
sasl_credentials=('cn=mydn,dc=organization,'mypassword'),
authentication=SASL,
check_names=True)
c.open()
r = c.bind()
c.unbind()
r will always be False.
In http://ldap3.readthedocs.org/en/latest/quicktour.html#connections it says:
c.search('o=test','(objectClass=*)', SUBTREE, attributes = ['sn', 'objectClass'], get_operational_attribute = True)
I think it should say get_operational_attributes with an s at the end.
Hi:
I use ldap3, but doesn't have hash method choose for modify passwd.I need choose md5 hash...
using python 3.4.0 with ldap3 '0.9.7.4'.
The following code raises LDAPInvalidCredentialsResult when proper user DN and password are used.
from ldap3 import Server, Connection, AUTH_SIMPLE, STRATEGY_SYNC, ALL
s = Server(HOST, port=389, get_info=ALL)
c = Connection(s, authentication=AUTH_SIMPLE, user=user_dn, password=PASSWORD, check_names=True, lazy=False, client_strategy=STRATEGY_SYNC, raise_exceptions=True)
c.open()
c.bind()
However, within the exception, 'description': 'success' seems to point to the fact that the user bind is successful, since when the password is given as incorrect, this 'success' message does not appear in the returned exception.
Correct password exception example:
ldap3.core.exceptions.LDAPInvalidCredentialsResult: LDAPInvalidCredentialsResult - 49 - invalidCredentials - [{'dn': '', 'message': '', 'type': 'bindResponse', 'result': 0, 'saslCreds': 'None', 'description': 'success', 'referrals': None}]
See the below link for more details:
http://stackoverflow.com/questions/28575359/how-to-bind-authenticate-a-user-with-ldap3-in-python3/28616485?noredirect=1#comment45568301_28616485
Not sure how to query for the remote ldap server info. I tried the following, but it didn't seem to give me much:
$ ldapsearch -LLL -h host -b "" -s base -D "DNstuff" -W "(objectclass=*)" vendorversion objectClass isGlobalCatalogReady vendorname
Enter LDAP Password:
dn:
objectClass: top
objectClass: OpenLDAProotDSE
When opening a connection to an IBM TDS your code crashes with:
...
File "/.../site-packages/ldap3/protocol/rfc4512.py", line 80, in quoted_string_to_list
return string
IndexError: string index out of range
The problem is, that the quoted_string_to_list function is called with an empty string.
Adding something like
if len(string) == 0:
return string
before accessing string[0] fixes the problem.
Hello,
Not sure if this has already been fixed or not, however with python3-ldap 0.9.6.2 I get this incredibly long exception message:
ldap3.core.exceptions.LDAPSizeLimitExceededResult: LDAPSizeLimitExceededResult - 4 - sizeLimitExceeded - None - None - searchResDone - [ < ....> ].
Where <...> lists every single result and every single attribute that was obtained before the size got too big.
This is huge.
Thanks
I'm generating data for my database using generators but at the point it's being passed back to the database it's being interpreted incorrectly. I'm more or less doing:
new_values = (i for i in range(3))
changes = {'testAttribute' : new_values}
connection.modify('ou=test,dc=example,dc=com', changes)
which ends up writing something like (retrieved using ldapsearch
on the command line):
dn: ou=test,dc=example,dc=com
testAttribute:: PGdlbmVyYXRvciBvYmplY3QgPGdlbmV4cHI+IGF0IDB4N2Y3YTQ0ZjQwYTY4Pg==
which is the base64 encoded version of:
dn: ou=test,dc=example,dc=com
testAttribute: <generator object <genexpr> at 0x7f7a44f40a68>
but I would expect:
dn: ou=test,dc=example,dc=com
testAttribute: 0
testAttribute: 1
testAttribute: 2
So it's writing the __str__
version of the object rather than iterating its values. This seems to come down to the explicit type testing happening at https://github.com/cannatag/ldap3/blob/master/ldap3/operation/modify.py#L64 by testing against ldap3.SEQUENCE_TYPES
. Perhaps it would be better to use collections.abc.Iterable
with a special case to filter out string types?
I expect this applies to Connection.add()
as well.
I saw these tests failing on python 2.x in your travis CI.
It's failing at your assertion comparing a bytes literal to the variable 'validated'.
ldap3.protocol.sasl.sasl.validate_simple_password will give any non-bytes password a pass through sasl_prep, then if it's not running in python 3.x, it will byte encode the prepped result.
The problem is, in python 2.x sasl_prep also returns a unicode string instead of 2.x's standard byte-based str. So it needs encoded to bytes either way, and it's not being done running on 2.x.
I forked and fixed it, I'll submit the pull request when my own CI tests finish running.
Hello,
It's entirely possible I'm doing it wrong, but I've been unsuccessful updating the thumbnailPhoto attribute.
The following code works using ldap with python 2.x
f = open('path/to/img.jpg', 'rb')
img = f.read()
ok = ldap_obj.modify(dn, [(ldap.MOD_REPLACE, 'thumbnailPhoto', img)])
I realize that f.read() in python3 returns bytes so i've tried casting to str or calling .decode with both utf-8 and cp437 as the format, in all cases, this fails:
foto = str(img)
ok = ldap_obj.modify(dn, {'thumbnailPhoto': (ldap3.MODIFY_REPLACE, [foto]) })
using version 0.9.7.2 on python 3.4.2
After setting up connection c:
c.search('dc=testbase', '(testattribute=true)') # searches fine
c.search('dc=testbase', '(!(testattribute=true))') # search throws error in pyasn1
"""
Error:
Traceback (most recent call last):
File <file info>
c.search('dc=testbase', "(!(testattribute=true))")
File "/lib/python3.4/site-packages/ldap3/core/connection.py", line 568, in search
request = search_operation(search_base, search_filter, search_scope, dereference_aliases, attributes, size_limit, time_limit, types_only, self.server.schema if self.server else None)
File "/lib/python3.4/site-packages/ldap3/operation/search.py", line 365, in search_operation
request['filter'] = build_filter(search_filter, schema) # parse the searchFilter string and compile it starting from the root node
File "/lib/python3.4/site-packages/ldap3/operation/search.py", line 312, in build_filter
return compile_filter(parse_filter(search_filter, schema).elements[0])
File "/lib/python3.4/site-packages/ldap3/operation/search.py", line 256, in compile_filter
compiled_filter['notFilter'] = boolean_filter
File "/lib/python3.4/site-packages/pyasn1/type/univ.py", line 824, in __setitem__
self.setComponentByName(idx, value)
File "/lib/python3.4/site-packages/pyasn1/type/univ.py", line 859, in setComponentByName
self._componentType.getPositionByName(name),value,verifyConstraints
File "/lib/python3.4/site-packages/pyasn1/type/univ.py", line 1093, in setComponentByPosition
self._verifyComponent(idx, value)
File "/lib/python3.4/site-packages/pyasn1/type/univ.py", line 848, in _verifyComponent
raise error.PyAsn1Error('Component value is tag-incompatible: %r vs %r' % (value, t))
pyasn1.error.PyAsn1Error: Component value is tag-incompatible: Not(componentType=NamedTypes(NamedType('innerNotFilter', Filter(componentType=NamedTypes(NamedType('and', And(componentType=None)), NamedType('or', Or(componentType=None)), NamedType('notFilter', Not(componentType=NamedTypes(), tagSet=TagSet((), ))), NamedType('equalityMatch', EqualityMatch(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('substringFilter', SubstringFilter(componentType=NamedTypes(NamedType('type', AttributeDescription()), NamedType('substrings', Substrings())))), NamedType('greaterOrEqual', GreaterOrEqual(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('lessOrEqual', LessOrEqual(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('present', Present()), NamedType('approxMatch', ApproxMatch(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('extensibleMatch', ExtensibleMatch(componentType=NamedTypes(OptionalNamedType('matchingRule', MatchingRule()), OptionalNamedType('type', Type()), NamedType('matchValue', MatchValue()), DefaultedNamedType('dnAttributes', DnAttributes('False')))))))))).setComponents(Filter(componentType=NamedTypes(NamedType('and', And(componentType=None)), NamedType('or', Or(componentType=None)), NamedType('notFilter', Not(componentType=NamedTypes(), tagSet=TagSet((), ))), NamedType('equalityMatch', EqualityMatch(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('substringFilter', SubstringFilter(componentType=NamedTypes(NamedType('type', AttributeDescription()), NamedType('substrings', Substrings())))), NamedType('greaterOrEqual', GreaterOrEqual(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('lessOrEqual', LessOrEqual(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('present', Present()), NamedType('approxMatch', ApproxMatch(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue())))), NamedType('extensibleMatch', ExtensibleMatch(componentType=NamedTypes(OptionalNamedType('matchingRule', MatchingRule()), OptionalNamedType('type', Type()), NamedType('matchValue', MatchValue()), DefaultedNamedType('dnAttributes', DnAttributes('False'))))))).setComponents(None, None, None, EqualityMatch(componentType=NamedTypes(NamedType('attributeDesc', AttributeDescription()), NamedType('assertionValue', AssertionValue()))).setComponents(AttributeDescription(b'testattribute'), AssertionValue(b'true')))) vs Not(componentType=NamedTypes(), tagSet=TagSet((), ))
"""
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.