Skip to content

Commit

Permalink
Merge pull request #28 from cannatag/dev
Browse files Browse the repository at this point in the history
Dev to master 0.9.7.9
  • Loading branch information
cannatag committed Feb 27, 2015
2 parents e144103 + 43696e8 commit 64b5a7a
Show file tree
Hide file tree
Showing 28 changed files with 345 additions and 281 deletions.
21 changes: 19 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LDAP3
:target: https://pypi.python.org/pypi/ldap3/
:alt: License

ldap3 is a strictly RFC 4511 conforming LDAP V3 pure Python client. The same codebase works with Python, Python 3, PyPy and PyPy3.
ldap3 is a strictly RFC 4511 conforming LDAP V3 pure Python **client**. The same codebase works with Python, Python 3, PyPy and PyPy3.

This project was formerly named **python3-ldap**. The name has been changed to avoid confusion with the python-ldap library.

Expand Down Expand Up @@ -85,14 +85,31 @@ Contact me

For information and suggestions you can contact me at cannatag@gmail.com or you can also a support ticket on https://github.com/cannatag/ldap3/issues/new

Changelog
---------

* 0.9.7.9 2015.02.27
- Fixed bug in PagedSearch when server has a hard limit on the number of entries returned (thanks Reimar)
- 0.9.7.6 not working for pypi problems
- 0.9.7.7 not working for pypi problems
- 0.9.7.8 not working for pypi problems

* 0.9.7.5 2015.02.20
- Fixed exception raised when opening a connection to a server. If there is only one candidate address and there is an error it returns the specific Exception, not a generic LDAPException error
- Address_info filters out any impossible address to reach
- Address_info include an IPV4MAPPED address for IPV6 host that try to reach an IPV4 only server
- Added SyncMock strategy (needs the sldap3 package)
- Fixed bug when using the aproximation operation in ldap search operations (thanks Laurent)
- Removed response from exception raised with raise_exceptions=True to avoid very long exceptions message

* 0.9.7.4 2015.02.02
- Added connection.entries property for storing response from search operations as and abstract.Entry collection.

* 0.9.7.3 2015.01.25
- Modify operation type can also be passed as integer

* 0.9.7.2 2015.01.16
- Fixed a bug when resolving IP address with getaddrinfo(). On OSX returned an UDP connection.
- Fixed a bug when resolving IP address with getaddrinfo(). On OSX returned an UDP connection (thanks Hiroshi).

* 0.9.7.1 2015.01.05
- Moved to Github
Expand Down
35 changes: 35 additions & 0 deletions _changelog.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
* 0.9.7.9 2015.02.27
- Fixed bug in PagedSearch when server has a hard limit on the number of entries returned (thanks Reimar)
- 0.9.7.6 not working for pypi problems
- 0.9.7.7 not working for pypi problems
- 0.9.7.8 not working for pypi problems

* 0.9.7.5 2015.02.20
- Fixed exception raised when opening a connection to a server. If there is only one candidate address and there is an error it returns the specific Exception, not a generic LDAPException error
- Address_info filters out any impossible address to reach
- Address_info include an IPV4MAPPED address for IPV6 host that try to reach an IPV4 only server
- Added SyncMock strategy (needs the sldap3 package)
- Fixed bug when using the aproximation operation in ldap search operations (thanks Laurent)
- Removed response from exception raised with raise_exceptions=True to avoid very long exceptions message

* 0.9.7.4 2015.02.02
- Added connection.entries property for storing response from search operations as and abstract.Entry collection.

* 0.9.7.3 2015.01.25
- Modify operation type can also be passed as integer

* 0.9.7.2 2015.01.16
- Fixed a bug when resolving IP address with getaddrinfo(). On OSX returned an UDP connection (thanks Hiroshi).

* 0.9.7.1 2015.01.05
- Moved to Github
- Moved to Travis-CI for continuous integration
- Moved to ReadTheDocs for documentation
- Moved testing servers in the cloud, to allow testing from Travis-CI
- Project renamed from python3-ldap to ldap3 to avoid name clashing with the existing python-ldap library
- Constant values in ldap3 are now strings. This is helpful in testing and debugging
- Test suite fully refactored to be used in cloud lab and local development lab
- Test suite includes options for testing against eDirectory, Active Directory and OpenLDAP


Previous versions changelog is available at http://pythonhosted.org//python3-ldap/changelog.html
11 changes: 11 additions & 0 deletions _version.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"package_folder": ".",
"email": "cannatag@gmail.com",
"status": "development - beta",
"package_name": "ldap3",
"url": "https://github.com/cannatag/ldap3",
"description": "A strictly RFC 4511 conforming LDAP V3 pure Python client. Same codebase for Python 2, Python3, PyPy and PyPy 3",
"author": "Giovanni Cannata",
"version": "0.9.7.9",
"license": "LGPL v3"
}
32 changes: 0 additions & 32 deletions _version.py

This file was deleted.

14 changes: 7 additions & 7 deletions build-dist.cmd
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
rd dist build ldap3.egg-info /S /Q
\Python\Python34\python.exe setup.py clean
\Python\Python34\python.exe setup.py build sdist --format=gztar
\Python\Python34\python.exe setup.py build bdist_wininst
\Python\Python34\python.exe setup.py build bdist_wheel --universal
\Python\Python26\python.exe setup.py bdist_egg
\Python\Python27\python.exe setup.py bdist_egg
\Python\Python34\python.exe setup.py bdist_egg
py -3 setup.py clean
py -3 setup.py build sdist --format=gztar
py -3 setup.py build bdist_wininst
py -3 setup.py build bdist_wheel --universal
py -2.6 setup.py bdist_egg
py -2.7 setup.py bdist_egg
py -3 setup.py bdist_egg
1 change: 1 addition & 0 deletions deploy-to-pypi.cmd
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
call prepare-dist.cmd
call build-dist.cmd
call upload-to-pypi.cmd
3 changes: 3 additions & 0 deletions docs/manual/source/abstraction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ you get back the whole attribute object, not only the key as in a standard dicti
for attr in person_entry:
print(attr.key)


An Entry can be converted to ldif with the entry.entry_to_ldif() method and to json with the entry.entry_to_json() method.
Entries can be easily printed at the interactive prompt::

Expand Down Expand Up @@ -262,6 +263,7 @@ Entries can be easily printed at the interactive prompt::
subordinateCount: 33
subschemaSubentry: cn=schema


and each attribute of the entry can be accessed as a dictionary or as a namespace::

>>> c.entries[0].GUID
Expand All @@ -273,6 +275,7 @@ and each attribute of the entry can be accessed as a dictionary or as a namespac
>>> c.entries[0].GUID.values
['fd9a0d90-15be-2841-fd82-fd9a0d9015be']


you can obtain already formatted values when requesting the schema in the Server object.


Expand Down
19 changes: 1 addition & 18 deletions docs/manual/source/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,23 +1,6 @@
CHANGELOG
=========
* 0.9.7.4 2015.02.02
- Added connection.entries property for storing response from search operations as and abstract.Entry collection.

* 0.9.7.3 2015.01.25
- Modify operation type can also be passed as integer

* 0.9.7.2 2015.01.16
- Fixed a bug when resolving IP address with getaddrinfo(). On OSX returned an UDP connection.

* 0.9.7.1 2015.01.05
- Moved to Github
- Moved to Travis-CI for continuous integration
- Moved to ReadTheDocs for documentation
- Moved testing servers in the cloud, to allow testing from Travis-CI
- Project renamed from python3-ldap to ldap3 to avoid name clashing with the existing python-ldap library
- Constant values in ldap3 are now strings. This is helpful in testing and debugging
- Test suite fully refactored to be used in cloud lab and local development lab
- Test suite includes options for testing against eDirectory, Active Directory and OpenLDAP
.. include:: ../../../_changelog.txt

* 0.9.7 2014.12.17
- Fixed bug for auto_range used in paged search
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@
epub_title = 'ldap3'
epub_author = __author__
epub_publisher = __author__
epub_copyright = '2013 - ' + __author__
epub_copyright = '2015 - ' + __author__

# The basename for the epub file. It defaults to the project name.
#epub_basename = 'ldap3'
Expand Down
5 changes: 2 additions & 3 deletions docs/manual/source/exceptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ any unsuccesful LDAP operation will throw an exception of this class, subclassed
to the specific LDAP result code exception. For example if you get an
INVALID_DN_SYNTAX (result code 34) the connection will raise the
LDAPInvalidDNSyntaxResult exception, with the following parameter:
result, description, dn, message, response_type, and the whole
response filled with the values received in the response of the LDAP
operation. You can specify which result codes you don't want to raise
result, description, dn, message and the response_type.
You can specify which result codes you don't want to raise
exceptions, the default is : RESULT_COMPARE_FALSE, RESULT_COMPARE_TRUE,
RESULT_REFERRAL (and of course RESULT_SUCCESS). You can change this
behaviour in the ldap3 __init__.py package or at runtime modifying the
Expand Down
2 changes: 1 addition & 1 deletion docs/manual/source/quicktour.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ After a search operation you can access the connection.entries property, to get
print(entry.entry_get_dn())
print(entry.givenName, entry.sn)

Look at 'Entry' in the 'abstraction layer' chapter for the description of the Entry object)
Look at 'Entry' in the 'abstraction layer' chapter for the description of the Entry object)

Connection context manager
--------------------------
Expand Down
3 changes: 3 additions & 0 deletions docs/rfc/ldap_proposed_standard/rfc4511.txt
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,9 @@ RFC 4511 LDAPv3 June 2006
Sermersheim Standards Track [Page 16]

RFC 4511 LDAPv3 June 2006
Textual passwords (consisting of a character sequence with a known
character set and encoding) transferred to the server using the
simple AuthenticationChoice SHALL be transferred as UTF-8 [RFC3629]
encoded [Unicode]. Prior to transfer, clients SHOULD prepare text
passwords as "query" strings by applying the SASLprep [RFC4013]
profile of the stringprep [RFC3454] algorithm. Passwords
Expand Down
3 changes: 2 additions & 1 deletion ldap3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@
ASYNC,
LDIF,
RESTARTABLE,
REUSABLE]
REUSABLE,
MOCK_SYNC]

# get rootDSE info
NONE = 'NO_INFO'
Expand Down
19 changes: 12 additions & 7 deletions ldap3/core/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@
from ..strategy.ldifProducer import LdifProducerStrategy
from ..strategy.sync import SyncStrategy
from ..strategy.restartable import RestartableStrategy
from ..strategy.mockSync import MockSyncStrategy
from ..strategy.mockAsync import MockAsyncStrategy
from ..operation.unbind import unbind_operation
from ..protocol.rfc2696 import RealSearchControlValue, Cookie, Size
from .usage import ConnectionUsage
Expand All @@ -65,6 +63,13 @@
LDAPObjectError
from ..utils.conv import prepare_for_stream, check_json_dict, format_json

try:
from ..strategy.mockSync import MockSyncStrategy
from ..strategy.mockAsync import MockAsyncStrategy
except ImportError:
MockSyncStrategy = NotImplemented
MockAsyncStrategy = NotImplemented


def _format_socket_endpoint(endpoint):
if endpoint and len(endpoint) == 2:
Expand Down Expand Up @@ -256,11 +261,11 @@ def __init__(self,
if not self.bound:
self.last_error = 'automatic bind not successful' + (' - ' + self.last_error if self.last_error else '')
raise LDAPBindError(self.last_error)
elif self.strategy.no_real_dsa:
self.server = None
else:
self.last_error = 'invalid LDAP server'
raise LDAPInvalidServerError(self.last_error)
# elif self.strategy.no_real_dsa:
# self.server = None
# else:
# self.last_error = 'invalid LDAP server'
# raise LDAPInvalidServerError(self.last_error)

def __str__(self):
s = [
Expand Down
2 changes: 1 addition & 1 deletion ldap3/core/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def address_info(self):
if not self._address_info or (datetime.now() - self._address_info_resolved_time).seconds > ADDRESS_INFO_REFRESH_TIME:
# converts addresses tuple to list and adds a 6th parameter for availability (None = not checked, True = available, False=not available) and a 7th parameter for the checking time
try:
self._address_info = [list(address) + [None, None] for address in socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, socket.IPPROTO_TCP, 0)]
self._address_info = [list(address) + [None, None] for address in socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, socket.IPPROTO_TCP, socket.AI_ADDRCONFIG | socket.AI_V4MAPPED)]
self._address_info_resolved_time = datetime.now()
except Exception:
self._address_info = []
Expand Down
5 changes: 4 additions & 1 deletion ldap3/core/tls.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,10 @@ def wrap_socket(self, connection, do_handshake=False):
"""

if use_ssl_context:
ssl_context = create_default_context(purpose=Purpose.SERVER_AUTH, cafile=self.ca_certs_file, capath=self.ca_certs_path, cadata=self.ca_certs_data)
ssl_context = create_default_context(purpose=Purpose.SERVER_AUTH,
cafile=self.ca_certs_file,
capath=self.ca_certs_path,
cadata=self.ca_certs_data)
if self.private_key_file:
ssl_context.load_cert_chain(self.certificate_file, keyfile=self.private_key_file, password=self.private_key_password)
ssl_context.check_hostname = False
Expand Down
6 changes: 5 additions & 1 deletion ldap3/extend/standard/PagedSearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,11 @@ def paged_search_generator(connection,
response = connection.response
result = connection.result
responses.extend(response)
cookie = result['controls']['1.2.840.113556.1.4.319']['value']['cookie']
try:
cookie = result['controls']['1.2.840.113556.1.4.319']['value']['cookie']
except KeyError:
cookie = None

while responses:
yield responses.pop()

Expand Down
33 changes: 29 additions & 4 deletions ldap3/operation/bind.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@

from .. import SIMPLE, ANONYMOUS, SASL
from ..core.exceptions import LDAPPasswordIsMandatoryError, LDAPUnknownAuthenticationMethodError
from ..protocol.rfc4511 import Referral, ServerSaslCreds
from ..protocol.sasl.sasl import validate_simple_password
from ..protocol.rfc4511 import Version, AuthenticationChoice, Simple, BindRequest, ResultCode, SaslCredentials
from ..protocol.rfc4511 import Version, AuthenticationChoice, Simple, BindRequest, ResultCode, SaslCredentials, LDAPResult, BindResponse, \
LDAPDN, LDAPString
from ..protocol.convert import authentication_choice_to_dict, referrals_to_list

# BindRequest ::= [APPLICATION 0] SEQUENCE {
# version INTEGER (1 .. 127),
# name LDAPDN,
# authentication AuthenticationChoice }
# version INTEGER (1 .. 127),
# name LDAPDN,
# authentication AuthenticationChoice }


def bind_operation(version,
Expand Down Expand Up @@ -71,6 +73,29 @@ def bind_request_to_dict(request):
'name': str(request['name']),
'authentication': authentication_choice_to_dict(request['authentication'])}

# BindResponse ::= [APPLICATION 1] SEQUENCE {
# COMPONENTS OF LDAPResult,
# serverSaslCreds [7] OCTET STRING OPTIONAL }


def bind_response_operation(result_code,
matched_dn='',
diagnostic_message='',
referral=None,
server_sasl_credentials=None):

response = BindResponse()
response['resultCode'] = ResultCode(result_code)
response['matchedDN'] = LDAPDN(matched_dn)
response['diagnosticMessage'] = LDAPString(diagnostic_message)
if referral:
response['referral'] = Referral(referral)

if server_sasl_credentials:
response['serverSaslCreds'] = ServerSaslCreds(server_sasl_credentials)

return response


def bind_response_to_dict(response):
return {'result': int(response['resultCode']),
Expand Down
4 changes: 2 additions & 2 deletions ldap3/operation/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
SEARCH_MATCH_OR_CONTROL = 23


class FilterNode():
class FilterNode(object):
def __init__(self, tag=None, assertion=None):
self.tag = tag
self.parent = None
Expand Down Expand Up @@ -105,7 +105,7 @@ def evaluate_match(match, schema):
match = match.strip()
if '~=' in match:
tag = MATCH_APPROX
left_part, _, right_part = match.split('~=')
left_part, _, right_part = match.partition('~=')
left_part = left_part.strip()
right_part = right_part.strip()
assertion = {'attr': left_part, 'value': validate_assertion_value(schema, left_part, right_part)}
Expand Down

0 comments on commit 64b5a7a

Please sign in to comment.