Coder Social home page Coder Social logo

pywebcorp's Introduction

HTTP and HTTPS web access via NTLM-authenticated proxy using SSPI for "single sign-on"

Motivation

Presently in large organisations ("corporate" domains), python software (particularly installers such as pip and conda) often is unable to access the internet, despite that other software can (e.g. all common web browsers). This is not a policy issue; the obstacle is that the necessary protocols are not fully supported by the usual python web access libraries (e.g. requests and urllib2).

Goal

The aim is to resolve this in httplib, urllib/urllib2, urllib3, or requests (or respective python 3 equivalents), so that downstream software just works (or can be made to work with minimal modification).

Failing that, the goal is to produce an easily-distributable patch for conda, to enable installing python behind a corporate firewall.

Status

Successfully demonstrating download from the web through an authenticated (NTLM) proxy, without needing to prompt for credentials. It is not dependent on pywin32 because it contains an alternative implementation of SSPI using ctypes. Conda works.

Possible future steps are to seek integration into requests or urllib3, or to try to replace python-ntlm (using standard crypto libraries).

Instructions

Disclaimer: Use at own risk. Still under development!

The main steps involved are:

  • ensure your python installation is able to detect your web proxy.
  • make the pywebcorp package available to your system.
  • ensure pywebcorp.patch gets imported before python software tries to access the web.

Installation for conda

Conda is the recommended "best-practice" python package manager (e.g. it manages dependencies including compiled libraries and the interpreter itself, and uses seperated virtual environments to manage dependency conflicts). Install miniconda for single-user.

Download the pywebcorp zip archive from GitHub, and copy the pywebcorp sub-directory into your conda global site-packages (e.g. C:\Users\YourName\AppData\Local\Continuum\Miniconda3\Lib\site-packages\pywebcorp).

In Internet Explorer - Internet Options - Connections - LAN Settings - Proxy server: ensure "Use proxy" is checked and the address/port are correct. These settings will also be inherited within python.

Also in the conda global site-packages, locate the requests package and its initialisation module (e.g. ...\Continuum\Miniconda3\Lib\site-packages\requests\__init__.py), open it in a text editor (such as IDLE or WordPad), and append the line import pywebcorp.patch to the end of it.

Finally, in a cmd.exe terminal, activate the root conda environment, use the conda create and conda install commands to download libraries into a fresh python environment.

Installation for pip

Note: untested.

If you are using a non-conda python installation, first locate where it is installed. (e.g. at a cmd.exe prompt, for %i in (python.exe) do @echo. %~$PATH:i)

From this python location, navigate to Lib\site-packages and copy pywebcorp as described above (e.g. to C:\Python27\Lib\site-packages\pywebcorp).

Pip may be using its own separate copy of the requests library. Append the import pywebcorp.patch line to e.g. C:\Python27\Lib\site-packages\pip\_vendor\requests\__init__.py.

Testing

Please report back whether pywebcorp assists to access the internet from your network.

Background

There appears to be no previous python implementation of NTLM web proxy authentication with SSPI credentials.

What currently (i.e. previously) exists:

Relevant projects or code

  • In pywin32 (popular library) there is an sspi module, accompanied by a demo for http download using NTLM/SSPI with no proxy (and other code relevent for testing SSPI). Its win32security module also wraps SSPI API.
  • Ntlmaps (a python equivalent of CNTLM) is a local proxy for forwarding connections through an NTLM authenticated proxy without SSPI.
  • Other attempts at supporting NTLM (without SSPI and generally excluding proxies) include ntlmpool (in urllib3.contrib), python-ntlm (for urllib2) and requests-ntlm (which does not currently seek integration).
  • An example of python instead using native windows HTTP API to automagically support any necessary protocols http://serverfault.com/a/755936
  • The SSPI API is also accessible using ctypes.windll (from the standard library, potentially mitagating pywin32 vendoring in installers, which is a concern expressed e.g. by pip developers). There already exists an attempt at reimplementing pywin32 using ctypes but it does not yet include SSPI. https://github.com/enthought/pywin32-ctypes
  • Python web access libraries (e.g. urllib) already support proxy host/port autodetection, which on Windows gets "Internet Options" from registry (i.e. as set by OS in control panel and iexplorer) or is overridden by env vars.
  • There is a gssapi (cross-platform analog of SSPI) python library, but it does not support MS-Windows.

Resources

Python ecosystem

The recommended approach for python web access (and used by pip and conda) is the requests library. This incorporates the urllib3 library, which differentiates from previous urllibs in support for connection reuse (which is particularly appropriate to NTLM because the handshake is once per usable connection). All urllibs employ httplib.

The relevent existing libraries (requests-ntlm, ntlmpool, ..) all rely on python-ntlm (or a fork thereof). Note that python-ntlm is LGPL, and appears to include a python reimplementation of cryptography algorithms.

pywebcorp's People

Contributors

benjimin avatar

Stargazers

Bruno avatar Luke Paris avatar nambot avatar  avatar Rob Blackbourn avatar aleks avatar  avatar Damien Ayers avatar Nicolas Bareil avatar Victor Uriarte avatar

Watchers

Damien Ayers avatar  avatar  avatar Pascal J avatar

pywebcorp's Issues

Test with pip

Need to test this resolution of pypa/pip#1182 (i.e. making pip support NTLM, but in a manner which will utilise OS-mediated authentication rather than requiring the user to enter credentials insecurely).

Exception ResponseNotReady

Hi,

I stumbled upon your efforts with pywebcorp. Thanks for that. I gave it a try with
python 3.6.7 on win64, requests 2.21.0 (downgraded to 2.13.0 for testing an old version at the time of ~April 2017). With this code, I get the following error:

import requests
import pywebcorp.patch

r = requests.get(url='https://httpbin.org/get', verify=False)
print(r.text)
Traceback (most recent call last):
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 594, in urlopen
    self._prepare_proxy(conn)
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 810, in _prepare_proxy
    conn.connect()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\pywebcorp\patch.py", line 95, in connect
    return super(NTLM_HTTPS, self).connect()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\packages\urllib3\connection.py", line 294, in connect
    self._tunnel()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\pywebcorp\patch.py", line 78, in _tunnel
    return self._tunnel()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\pywebcorp\patch.py", line 67, in _tunnel
    r = self.getresponse()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\pywebcorp\patch.py", line 54, in getresponse
    return self.getresponse()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\http\client.py", line 1321, in getresponse
    raise ResponseNotReady(self.__state)
http.client.ResponseNotReady: Request-sent

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\adapters.py", line 423, in send
    timeout=timeout
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 649, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\packages\urllib3\util\retry.py", line 347, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\packages\urllib3\packages\six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 594, in urlopen
    self._prepare_proxy(conn)
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 810, in _prepare_proxy
    conn.connect()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\pywebcorp\patch.py", line 95, in connect
    return super(NTLM_HTTPS, self).connect()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\packages\urllib3\connection.py", line 294, in connect
    self._tunnel()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\pywebcorp\patch.py", line 78, in _tunnel
    return self._tunnel()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\pywebcorp\patch.py", line 67, in _tunnel
    r = self.getresponse()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\pywebcorp\patch.py", line 54, in getresponse
    return self.getresponse()
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\http\client.py", line 1321, ingetresponse
    raise ResponseNotReady(self.__state)
requests.packages.urllib3.exceptions.ProtocolError: ('Connection aborted.', ResponseNotReady('Request-sent',))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "Y:\python\pywebcorp\test.py", line 7, in <module>
    r = requests.get(url='https://httpbin.org/get', verify=False)
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\USERNAME\conda_envs\pywebcorp\lib\site-packages\requests\adapters.py", line 473, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', ResponseNotReady('Request-sent',))

Do you have any idea that might help me?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.