exchangelib icon indicating copy to clipboard operation
exchangelib copied to clipboard

How to disable check_hostname

Open vanjabojic opened this issue 1 year ago • 4 comments

Describe the bug Our VPN server modify Security certificates, and I would like to disable check for validity of the same, but when connection thru VPN i get error ValueError: Cannot set verify_mode to CERT_NONE when check_hostname is enabled.

To Reproduce script that I am using (with modified data for url, etc...)

from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter
from exchangelib import Account, Credentials, Configuration
BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter
credentials = Credentials(username='DOMAIN\\user', password='pass')
config = Configuration(server='server.ba', credentials=credentials)
account = Account(primary_smtp_address='[email protected]', credentials=credentials, config=config, autodiscover=False)

Exception is raised on last line of code account = ...

Expected behavior A clear and concise description of what you expected to happen. If applicable, add links to EWS documentation on MSDN or other relevant source.

I would expect exchange lib to accept that certificate is not good, and to ignore it

Log output If applicable, add relevant output from debug logging .

Traceback (most recent call last):
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\protocol.py", line 242, in get_session
    session = self._session_pool.get(block=False)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\queue.py", line 168, in get
    raise Empty
_queue.Empty

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\runpy.py", line 198, in _run_module_as_main
    return _run_code(code, main_globals, None,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\runpy.py", line 88, in _run_code
    exec(code, run_globals)
  File "c:\Users\user\.vscode\extensions\ms-python.debugpy-2024.6.0-win32-x64\bundled\libs\debugpy\adapter/../..\debugpy\launcher/../..\debugpy\__main__.py", line 39, in <module>
    cli.main()
  File "c:\Users\user\.vscode\extensions\ms-python.debugpy-2024.6.0-win32-x64\bundled\libs\debugpy\adapter/../..\debugpy\launcher/../..\debugpy/..\debugpy\server\cli.py", line 430, in main
    run()
  File "c:\Users\user\.vscode\extensions\ms-python.debugpy-2024.6.0-win32-x64\bundled\libs\debugpy\adapter/../..\debugpy\launcher/../..\debugpy/..\debugpy\server\cli.py", line 284, in run_file
    runpy.run_path(target, run_name="__main__")
  File "c:\Users\user\.vscode\extensions\ms-python.debugpy-2024.6.0-win32-x64\bundled\libs\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_runpy.py", line 321, in run_path
    return _run_module_code(code, init_globals, run_name,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\Users\user\.vscode\extensions\ms-python.debugpy-2024.6.0-win32-x64\bundled\libs\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_runpy.py", line 135, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "c:\Users\user\.vscode\extensions\ms-python.debugpy-2024.6.0-win32-x64\bundled\libs\debugpy\_vendored\pydevd\_pydevd_bundle\pydevd_runpy.py", line 124, in _run_code
    exec(code, run_globals)
  File "D:\OneDrive - Telekomunikacije RS a.d. Banja Luka\Python\PythonProjects\Aplikacija\ai_send.py", line 6, in <module>
    account = Account(primary_smtp_address='[email protected]', credentials=credentials, config=config, autodiscover=False)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\account.py", line 205, in __init__
    self.version = self.protocol.version.copy()
                   ^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\protocol.py", line 480, in version
    self.config.version = Version.guess(self, api_version_hint=self.api_version_hint)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\version.py", line 202, in guess
    list(ConvertId(protocol=protocol).call([AlternateId(id="DUMMY", format=EWS_ID, mailbox="DUMMY")], ENTRY_ID))
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\services\common.py", line 216, in _elems_to_objs
    for elem in elems:
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\services\common.py", line 278, in _chunked_get_elements
    yield from self._get_elements(payload=payload_func(chunk, **kwargs))
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\services\common.py", line 299, in _get_elements
    yield from self._response_generator(payload=payload)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\services\common.py", line 262, in _response_generator
    response = self._get_response_xml(payload=payload)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\services\common.py", line 395, in _get_response_xml
    r = self._get_response(payload=payload, api_version=api_version)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\services\common.py", line 345, in _get_response
    session = self.protocol.get_session()
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\protocol.py", line 246, in get_session
    self.increase_poolsize()
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\protocol.py", line 212, in increase_poolsize
    self._session_pool.put(self.create_session(), block=False)
                           ^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\protocol.py", line 318, in create_session
    if self.auth_type == NTLM and self.credentials.type == self.credentials.EMAIL:
       ^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\protocol.py", line 119, in auth_type
    self.config.auth_type = self.get_auth_type()
                            ^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\protocol.py", line 470, in get_auth_type
    return get_service_authtype(protocol=self)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\exchangelib\transport.py", line 87, in get_service_authtype
    r = s.post(
        ^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\requests\sessions.py", line 637, in post
    return self.request("POST", url, data=data, json=json, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\requests\sessions.py", line 589, in request
    resp = self.send(prep, **send_kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\requests\sessions.py", line 703, in send
    r = adapter.send(request, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\requests\adapters.py", line 589, in send
    resp = conn.urlopen(
           ^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\urllib3\connectionpool.py", line 793, in urlopen
    response = self._make_request(
               ^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\urllib3\connectionpool.py", line 467, in _make_request
    self._validate_conn(conn)
  File "c:\venv\Aplikacija\Lib\site-packages\urllib3\connectionpool.py", line 1099, in _validate_conn
    conn.connect()
  File "c:\venv\Aplikacija\Lib\site-packages\urllib3\connection.py", line 653, in connect
    sock_and_verified = _ssl_wrap_socket_and_match_hostname(
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "c:\venv\Aplikacija\Lib\site-packages\urllib3\connection.py", line 768, in _ssl_wrap_socket_and_match_hostname
    context.verify_mode = resolve_cert_reqs(cert_reqs)
    ^^^^^^^^^^^^^^^^^^^
  File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\ssl.py", line 742, in verify_mode
    super(SSLContext, SSLContext).verify_mode.__set__(self, value)
ValueError: Cannot set verify_mode to CERT_NONE when check_hostname is enabled.

Additional context For example, Python and exchangelib versions. Python is 3.11.9, exchangelib 5.4.0 (but I have tried other versions also)

vanjabojic avatar May 22 '24 11:05 vanjabojic

If you need to customize the way exchangelib handles connections, you should create a custom HTTP adapter for requests. There's documentation for that at https://ecederstrand.github.io/exchangelib/#proxies-and-custom-tls-validation

ecederstrand avatar May 22 '24 13:05 ecederstrand

I did try it, but I am lacking knowledge to do so :( I have tried:

class NoHostnameAdapter(HTTPAdapter):
    # Disable check_hostname?!
    def init_poolmanager(self, connections, maxsize, block=False):
        self.poolmanager = PoolManager(num_pools=connections,
                                       maxsize=maxsize,
                                       block=block,
                                       cert_reqs='CERT_NONE',
                                       assert_hostname=False,
                                       check_hostname=False)
class NoCertAdapter(NoHostnameAdapter):
    def cert_verify(self, conn, url, verify, cert):
        # pylint: disable=unused-argument
        # We're overriding a method, so we have to keep the signature
        super().cert_verify(conn=conn, url=url, verify=False, cert=cert)

BaseProtocol.HTTP_ADAPTER_CLS = NoCertAdapter

but it does not work.

P.S. request.get with verify=False works...

urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
url = 'https://server.ba/ews/exchange.asmx'
auth = HttpNtlmAuth('DOMAIN\\'+username, password)
response = requests.get(url, auth=auth, verify=False)

vanjabojic avatar May 22 '24 13:05 vanjabojic

I would suggest asking in a forum dedicated to requests instead. This is outside the scope of exchangelib as such.

ecederstrand avatar May 22 '24 14:05 ecederstrand

Check requests package - if requests==2.32.0+ change version to 2.31.0

Barsovski avatar May 23 '24 13:05 Barsovski

Closing as this issue concerns configuration or extension of requests, not exchangelib.

ecederstrand avatar May 27 '24 09:05 ecederstrand