ZSI Stuff

From PeformIQ Upgrade
Jump to navigation Jump to search

Back to Python Python - ZSI Module

Digest Authentication ZSI 1.7

Just for the record. After accepting that pythons build-in digest
authentication (HTTPDigestAuthHandler)  does *NOT* work, I made my own
digest authentication handler and built it into ZSI, they have recieved
and accepted the patch so it should be part of the next ZSI release
(current 1.7).

I have tested the implementation with Microsoft MapPoint services,
seems OK:

#-------------------------------------
#Usage example (MapPoint SOAP Services):
#-------------------------------------
from CommonService_services import *
loc = FindServiceLocator()
import sys
import ZSI
kw={'tracefile':sys.stdout, 'auth' : (
ZSI.AUTH.httpdigest, 'username', 'passwd') }
portType = loc.getFindServiceSoap(**kw)

AddressLine='Lergravsvej 28'
PostalCode='8660'
CountryRegion='DK'
InputAddress = ns1.Address_Def()
InputAddress._AddressLine = AddressLine
InputAddress._PostalCode = PostalCode
InputAddress._CountryRegion = CountryRegion

specification = ns1.FindAddressSpecification_Def()
specification._InputAddress = InputAddress
specification._DataSourceName = 'MapPoint.EU'
request = FindAddressSoapInWrapper()

request._specification = specification

res = portType.FindAddress(request)
#-----------------------------------------

Best regards
Jakob Simon-Gaarde
{noformat}
{noformat}
Digest MD5 authentication over using ZSI
trapeze.jsg at gmail.com trapeze.jsg at gmail.com
Sun Sep 4 01:03:20 CEST 2005

    * Previous message: PyChecker lives, version 0.8.15 released
    * Next message: Digest MD5 authentication over using ZSI
    * Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

Hi.

I am trying to get through to Microsoft MapPoint Services using ZSI for
soap handling. I can generate the service classes and also the
soap-requests generated by the service classes seem to be OK. The
problem I am facing is that I can't seem to authenticate myself. I have
made a small change to ZSI.client so that when I get a "401
Unauthorized" response from the remote server I build up a nice
authorization request:

POST /Find-30/FindService.asmx HTTP/1.1
Host: findv3.staging.mappoint.net
Accept-Encoding: identity
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client
Protocol 1.1.4322.573)
SOAPAction: "http://s.mappoint.net/mappoint-30/FindAddress"
Authorization: Digest username="106288", realm="MapPoint",
nonce="91168da8e3a097f41264875211009a194b99a94ffe5bc619415820880a5b",
uri="/Find-30/FindService.asmx",
response="26aa9e36f9ff2a8308030810ab83dad1", qop=auth, nc=00000001,
cnonce="623c12f33f0eb883"
Content-length: 0
Expect: 100-continue


The problem is that the server won't authorize me. I have a C# .net
program that does exactly the same I'm trying in python, and it is
authorized nicely:

POST /Find-30/FindService.asmx HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services Client
Protocol 1.1.4322.573)
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://s.mappoint.net/mappoint-30/FindAddress"
Authorization: Digest
username="106288",realm="MapPoint",nonce="487911f02ed2ef706326675211008a8ec39cfa4fb09304757c8dde417354",uri="/Find-30/FindService.asmx",cnonce="e1ed9880c5e3777a4ba280cec1c9e362",nc=00000001,qop="auth",response="b4119a4db73814fd09ae5fec11fc9730"
Content-Length: 523
Expect: 100-continue
Host: findv3.staging.mappoint.net

So I guess the problem is in the Digest calculation. Unfortunately I
don't know much about the issue but I have managed to "steel" this from
urllib2 and changed it a bit to fit my usage (see below).

1. Can I do this another way?
2. Has anybody made a digest MD5 authenticator for ZSI?
3. Whats wrong with my calculation or is it the header??
4. Can I use urllib2 to test the authentication part of a Soap Service.

----------------- My authentication calculator ---->

import md5
import sha
import re
import time
import random
import os.path


def randombytes(n):
    """Return n random bytes."""
    # Use /dev/urandom if it is available.  Fall back to random module
    # if not.  It might be worthwhile to extend this function to use
    # other platform-specific mechanisms for getting random bytes.
    if os.path.exists("/dev/urandom"):
        f = open("/dev/urandom")
        s = f.read(n)
        f.close()
        return s
    else:
        L = [chr(random.randrange(0, 256)) for i in range(n)]
        return "".join(L)


class Challenge:
  def __init__(self,challenge):
    self.params = {}
    self.no_chal=0
    if challenge.upper().find('WWW-Authenticate:'.upper())==-1:
      self.no_chal=1
    rx =
re.compile('WWW-Authenticate:.*qop="(\w+)"',re.IGNORECASE|re.MULTILINE)
    m = rx.search(challenge)
    if m:
      self.params['qop'] = m.group(1)

    rx =
re.compile('WWW-Authenticate:.*realm="(\w+)"',re.IGNORECASE|re.MULTILINE)
    m = rx.search(challenge)
    if m:
      self.params['realm'] = m.group(1)

    rx =
re.compile('WWW-Authenticate:.*algorithm="(\w+)"',re.IGNORECASE|re.MULTILINE)
    m = rx.search(challenge)
    if m:
      self.params['algorithm'] = m.group(1)

    rx =
re.compile('WWW-Authenticate:.*nonce="(\w+)"',re.IGNORECASE|re.MULTILINE)
    m = rx.search(challenge)
    if m:
      self.params['nonce'] = m.group(1)

    rx =
re.compile('WWW-Authenticate:.*opaque="(\w+)"',re.IGNORECASE|re.MULTILINE)
    m = rx.search(challenge)
    if m:
      self.params['opaque'] = m.group(1)

    rx =
re.compile('WWW-Authenticate:.*Digest.*"',re.IGNORECASE|re.MULTILINE)
    m = rx.search(challenge)
    if m:
      self.params['Digest'] = 1


  def get(self,keyword,default=None):
    if self.params.has_key(keyword):
      return self.params[keyword]
    else:
      return default

  def no_challenge(self):
    return self.no_chal


class AbstractDigestAuthHandler:
    # Digest authentication is specified in RFC 2617.

    # XXX The client does not inspect the Authentication-Info header
    # in a successful response.

    # XXX It should be possible to test this implementation against
    # a mock server that just generates a static set of challenges.

    # XXX qop="auth-int" supports is shaky

    def __init__(self, user, passwd):
        self.user = user
        self.passwd = passwd
        self.retried = 0
        self.nonce_count = 0

    def reset_retry_count(self):
        self.retried = 0

    def retry_http_digest_auth(self, req, auth):
        token, challenge = auth.split(' ', 1)
        chal = parse_keqv_list(parse_http_list(challenge))
        auth = self.get_authorization(req, chal)
        if auth:
            auth_val = 'Digest %s' % auth
            if req.headers.get(self.auth_header, None) == auth_val:
                return None
            req.add_header(self.auth_header, auth_val)
            resp = self.parent.open(req)
            return resp

    def get_cnonce(self, nonce):
        # The cnonce-value is an opaque
        # quoted string value provided by the client and used by both client
        # and server to avoid chosen plaintext attacks, to provide mutual
        # authentication, and to provide some message integrity protection.
        # This isn't a fabulous effort, but it's probably Good Enough.
        dig = sha.new("%s:%s:%s:%s" % (self.nonce_count, nonce, time.ctime(),
                                       randombytes(8))).hexdigest()
        return dig[:16]

    def get_authorization(self, chal, method, selector):
        try:
            realm = chal.get('realm')
            nonce = chal.get('nonce')
            qop = chal.get('qop')
            algorithm = chal.get('algorithm', 'MD5')
            # mod_digest doesn't send an opaque, even though it isn't
            # supposed to be optional
            opaque = chal.get('opaque', None)
        except KeyError:
            return None

        H, KD = self.get_algorithm_impls(algorithm)
        if H is None:
            return None

        user, pw = self.user, self.passwd
        if user is None:
            return None

        # XXX not implemented yet
        entdig = None
        #if req.has_data():
        #    entdig = self.get_entity_digest(req.get_data(), chal)

        A1 = "%s:%s:%s" % (user, realm, pw)
        A2 = "%s:%s" % (method,
                        # XXX selector: what about proxies and full urls
                        selector)
        if qop == 'auth':
            self.nonce_count += 1
            ncvalue = '%08x' % self.nonce_count
            cnonce = self.get_cnonce(nonce)
            noncebit = "%s:%s:%s:%s:%s" % (nonce, ncvalue, cnonce, qop, H(A2))
            respdig = KD(H(A1), noncebit)
        else:
            pass
        # XXX should the partial digests be encoded too?

        base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \
               'response="%s"' % (user, realm, nonce, selector,
                                  respdig)
        if opaque:
            base = base + ', opaque="%s"' % opaque
        if entdig:
            base = base + ', digest="%s"' % entdig
        if algorithm != 'MD5':
            base = base + ', algorithm="%s"' % algorithm
        if qop:
            base = base + ', qop=auth, nc=%s, cnonce="%s"' % (ncvalue, cnonce)
        return base

    def get_algorithm_impls(self, algorithm):
        # lambdas assume digest modules are imported at the top level
        if algorithm == 'MD5':
            H = lambda x: md5.new(x).hexdigest()
        elif algorithm == 'SHA':
            H = lambda x: sha.new(x).hexdigest()
        # XXX MD5-sess
        KD = lambda s, d: H("%s:%s" % (s, d))
        return H, KD

    def get_entity_digest(self, data, chal):
        # XXX not implemented yet
        return None

<---------------


Ethereal request sniffer: (the authorization request and server
response)


No.     Time        Source                Destination
Protocol Info
     15 0.757244    192.168.0.106         64.4.58.250           HTTP
 POST /Find-30/FindService.asmx HTTP/1.1

Frame 15 (612 bytes on wire, 612 bytes captured)
    Arrival Time: Sep  3, 2005 23:57:20.487466000
    Time delta from previous packet: 0.000111000 seconds
    Time since reference or first frame: 0.757244000 seconds
    Frame Number: 15
    Packet Length: 612 bytes
    Capture Length: 612 bytes
    Protocols in frame: eth:ip:tcp:http
Ethernet II, Src: FirstInt_6c:a0:01 (00:40:ca:6c:a0:01), Dst:
D-Link_36:0e:3d (00:0d:88:36:0e:3d)
    Destination: D-Link_36:0e:3d (00:0d:88:36:0e:3d)
    Source: FirstInt_6c:a0:01 (00:40:ca:6c:a0:01)
    Type: IP (0x0800)
Internet Protocol, Src: 192.168.0.106 (192.168.0.106), Dst: 64.4.58.250
(64.4.58.250)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
        0000 00.. = Differentiated Services Codepoint: Default (0x00)
        .... ..0. = ECN-Capable Transport (ECT): 0
        .... ...0 = ECN-CE: 0
    Total Length: 598
    Identification: 0x7797 (30615)
    Flags: 0x04 (Don't Fragment)
        0... = Reserved bit: Not set
        .1.. = Don't fragment: Set
        ..0. = More fragments: Not set
    Fragment offset: 0
    Time to live: 128
    Protocol: TCP (0x06)
    Header checksum: 0x44fa [correct]
    Source: 192.168.0.106 (192.168.0.106)
    Destination: 64.4.58.250 (64.4.58.250)
Transmission Control Protocol, Src Port: 3183 (3183), Dst Port: http
(80), Seq: 1, Ack: 1, Len: 558
    Source port: 3183 (3183)
    Destination port: http (80)
    Sequence number: 1    (relative sequence number)
    Next sequence number: 559    (relative sequence number)
    Acknowledgement number: 1    (relative ack number)
    Header length: 20 bytes
    Flags: 0x0018 (PSH, ACK)
        0... .... = Congestion Window Reduced (CWR): Not set
        .0.. .... = ECN-Echo: Not set
        ..0. .... = Urgent: Not set
        ...1 .... = Acknowledgment: Set
        .... 1... = Push: Set
        .... .0.. = Reset: Not set
        .... ..0. = Syn: Not set
        .... ...0 = Fin: Not set
    Window size: 64512
    Checksum: 0x9143 [correct]
Hypertext Transfer Protocol
    POST /Find-30/FindService.asmx HTTP/1.1\r\n
        Request Method: POST
        Request URI: /Find-30/FindService.asmx
        Request Version: HTTP/1.1
    Host: findv3.staging.mappoint.net\r\n
    Accept-Encoding: identity\r\n
    User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; MS Web Services
Client Protocol 1.1.4322.573)\r\n
    SOAPAction: "http://s.mappoint.net/mappoint-30/FindAddress"\r\n
    Authorization: Digest username="106288", realm="MapPoint",
nonce="8033d257de12190a048487521100021388b534e89ffd4bad4292666e620c",
uri="/Find-30/FindService.asmx",
response="0ff36d6cbaf353f4aba183cef52d1de9", qop=auth, nc=00000001,
cnonce="8
    Content-length: 0\r\n
    Expect: 100-continue\r\n
    \r\n

0000  00 0d 88 36 0e 3d 00 40 ca 6c a0 01 08 00 45 00
...6.=. at .l....E.
0010  02 56 77 97 40 00 80 06 44 fa c0 a8 00 6a 40 04
.Vw. at ...D....j@.
0020  3a fa 0c 6f 00 50 88 c9 eb f1 f0 ea 88 6f 50 18
:..o.P.......oP.
0030  fc 00 91 43 00 00 50 4f 53 54 20 2f 46 69 6e 64   ...C..POST
/Find
0040  2d 33 30 2f 46 69 6e 64 53 65 72 76 69 63 65 2e
-30/FindService.
0050  61 73 6d 78 20 48 54 54 50 2f 31 2e 31 0d 0a 48   asmx
HTTP/1.1..H
0060  6f 73 74 3a 20 66 69 6e 64 76 33 2e 73 74 61 67   ost:
findv3.stag
0070  69 6e 67 2e 6d 61 70 70 6f 69 6e 74 2e 6e 65 74
ing.mappoint.net
0080  0d 0a 41 63 63 65 70 74 2d 45 6e 63 6f 64 69 6e
..Accept-Encodin
0090  67 3a 20 69 64 65 6e 74 69 74 79 0d 0a 55 73 65   g:
identity..Use
00a0  72 2d 41 67 65 6e 74 3a 20 4d 6f 7a 69 6c 6c 61   r-Agent:
Mozilla
00b0  2f 34 2e 30 20 28 63 6f 6d 70 61 74 69 62 6c 65   /4.0
(compatible
00c0  3b 20 4d 53 49 45 20 36 2e 30 3b 20 4d 53 20 57   ; MSIE 6.0; MS
W
00d0  65 62 20 53 65 72 76 69 63 65 73 20 43 6c 69 65   eb Services
Clie
00e0  6e 74 20 50 72 6f 74 6f 63 6f 6c 20 31 2e 31 2e   nt Protocol
1.1.
00f0  34 33 32 32 2e 35 37 33 29 0d 0a 53 4f 41 50 41
4322.573)..SOAPA
0100  63 74 69 6f 6e 3a 20 22 68 74 74 70 3a 2f 2f 73   ction:
"http://s
0110  2e 6d 61 70 70 6f 69 6e 74 2e 6e 65 74 2f 6d 61
.mappoint.net/ma
0120  70 70 6f 69 6e 74 2d 33 30 2f 46 69 6e 64 41 64
ppoint-30/FindAd
0130  64 72 65 73 73 22 0d 0a 41 75 74 68 6f 72 69 7a
dress"..Authoriz
0140  61 74 69 6f 6e 3a 20 44 69 67 65 73 74 20 75 73   ation: Digest
us
0150  65 72 6e 61 6d 65 3d 22 31 30 36 32 38 38 22 2c
ername="106288",
0160  20 72 65 61 6c 6d 3d 22 4d 61 70 50 6f 69 6e 74
realm="MapPoint
0170  22 2c 20 6e 6f 6e 63 65 3d 22 38 30 33 33 64 32   ",
nonce="8033d2
0180  35 37 64 65 31 32 31 39 30 61 30 34 38 34 38 37
57de12190a048487
0190  35 32 31 31 30 30 30 32 31 33 38 38 62 35 33 34
521100021388b534
01a0  65 38 39 66 66 64 34 62 61 64 34 32 39 32 36 36
e89ffd4bad429266
01b0  36 65 36 32 30 63 22 2c 20 75 72 69 3d 22 2f 46   6e620c",
uri="/F
01c0  69 6e 64 2d 33 30 2f 46 69 6e 64 53 65 72 76 69
ind-30/FindServi
01d0  63 65 2e 61 73 6d 78 22 2c 20 72 65 73 70 6f 6e   ce.asmx",
respon
01e0  73 65 3d 22 30 66 66 33 36 64 36 63 62 61 66 33
se="0ff36d6cbaf3
01f0  35 33 66 34 61 62 61 31 38 33 63 65 66 35 32 64
53f4aba183cef52d
0200  31 64 65 39 22 2c 20 71 6f 70 3d 61 75 74 68 2c   1de9",
qop=auth,
0210  20 6e 63 3d 30 30 30 30 30 30 30 31 2c 20 63 6e    nc=00000001,
cn
0220  6f 6e 63 65 3d 22 38 61 63 33 34 34 37 33 63 33
once="8ac34473c3
0230  33 32 66 61 38 66 22 0d 0a 43 6f 6e 74 65 6e 74
32fa8f"..Content
0240  2d 6c 65 6e 67 74 68 3a 20 30 0d 0a 45 78 70 65   -length:
0..Expe
0250  63 74 3a 20 31 30 30 2d 63 6f 6e 74 69 6e 75 65   ct:
100-continue
0260  0d 0a 0d 0a                                       ....

No.     Time        Source                Destination
Protocol Info
     16 0.950469    64.4.58.250           192.168.0.106         HTTP
 HTTP/1.1 401 Unauthorized

Frame 16 (387 bytes on wire, 387 bytes captured)
    Arrival Time: Sep  3, 2005 23:57:20.680691000
    Time delta from previous packet: 0.193225000 seconds
    Time since reference or first frame: 0.950469000 seconds
    Frame Number: 16
    Packet Length: 387 bytes
    Capture Length: 387 bytes
    Protocols in frame: eth:ip:tcp:http
Ethernet II, Src: D-Link_36:0e:3d (00:0d:88:36:0e:3d), Dst:
FirstInt_6c:a0:01 (00:40:ca:6c:a0:01)
    Destination: FirstInt_6c:a0:01 (00:40:ca:6c:a0:01)
    Source: D-Link_36:0e:3d (00:0d:88:36:0e:3d)
    Type: IP (0x0800)
Internet Protocol, Src: 64.4.58.250 (64.4.58.250), Dst: 192.168.0.106
(192.168.0.106)
    Version: 4
    Header length: 20 bytes
    Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
        0000 00.. = Differentiated Services Codepoint: Default (0x00)
        .... ..0. = ECN-Capable Transport (ECT): 0
        .... ...0 = ECN-CE: 0
    Total Length: 373
    Identification: 0x395f (14687)
    Flags: 0x04 (Don't Fragment)
        0... = Reserved bit: Not set
        .1.. = Don't fragment: Set
        ..0. = More fragments: Not set
    Fragment offset: 0
    Time to live: 108
    Protocol: TCP (0x06)
    Header checksum: 0x9813 [correct]
    Source: 64.4.58.250 (64.4.58.250)
    Destination: 192.168.0.106 (192.168.0.106)
Transmission Control Protocol, Src Port: http (80), Dst Port: 3183
(3183), Seq: 1, Ack: 559, Len: 333
    Source port: http (80)
    Destination port: 3183 (3183)
    Sequence number: 1    (relative sequence number)
    Next sequence number: 334    (relative sequence number)
    Acknowledgement number: 559    (relative ack number)
    Header length: 20 bytes
    Flags: 0x0018 (PSH, ACK)
        0... .... = Congestion Window Reduced (CWR): Not set
        .0.. .... = ECN-Echo: Not set
        ..0. .... = Urgent: Not set
        ...1 .... = Acknowledgment: Set
        .... 1... = Push: Set
        .... .0.. = Reset: Not set
        .... ..0. = Syn: Not set
        .... ...0 = Fin: Not set
    Window size: 17122
    Checksum: 0x0f4b [correct]
    SEQ/ACK analysis
        This is an ACK to the segment in frame: 15
        The RTT to ACK the segment was: 0.193225000 seconds
Hypertext Transfer Protocol
    HTTP/1.1 401 Unauthorized\r\n
        Request Version: HTTP/1.1
        Response Code: 401
    Connection: close\r\n
    Date: Sat, 03 Sep 2005 22:00:41 GMT\r\n
    Server: Microsoft-IIS/6.0\r\n
    P3P:CP="BUS CUR CONo FIN IVDo ONL OUR PHY SAMo TELo"\r\n
    X-Powered-By: ASP.NET\r\n
    WWW-Authenticate: Digest qop="auth", realm="MapPoint",
nonce="13c38f357408a1fc148487521100702d0fadd05e6b7cf54806565713c790"\r\n
    Content-Length: 0\r\n
    \r\n

0000  00 40 ca 6c a0 01 00 0d 88 36 0e 3d 08 00 45 00  . at .l.....6.=..E.
0010  01 75 39 5f 40 00 6c 06 98 13 40 04 3a fa c0 a8  .u9_ at .l...@.:...
0020  00 6a 00 50 0c 6f f0 ea 88 6f 88 c9 ee 1f 50 18  .j.P.o...o....P.
0030  42 e2 0f 4b 00 00 48 54 54 50 2f 31 2e 31 20 34   B..K..HTTP/1.14
0040  30 31 20 55 6e 61 75 74 68 6f 72 69 7a 65 64 0d   01 Unauthorized.
0050  0a 43 6f 6e 6e 65 63 74 69 6f 6e 3a 20 63 6c 6f   .Connection: clo
0060  73 65 0d 0a 44 61 74 65 3a 20 53 61 74 2c 20 30   se..Date: Sat, 0
0070  33 20 53 65 70 20 32 30 30 35 20 32 32 3a 30 30   3 Sep 2005 22:00
0080  3a 34 31 20 47 4d 54 0d 0a 53 65 72 76 65 72 3a   :41 GMT..Server:
0090  20 4d 69 63 72 6f 73 6f 66 74 2d 49 49 53 2f 36   Microsoft-IIS/6
00a0  2e 30 0d 0a 50 33 50 3a 43 50 3d 22 42 55 53 20   .0..P3P:CP="BUS

00b0  43 55 52 20 43 4f 4e 6f 20 46 49 4e 20 49 56 44   CUR CONo FINIVD
00c0  6f 20 4f 4e 4c 20 4f 55 52 20 50 48 59 20 53 41   o ONL OUR PHYSA
00d0  4d 6f 20 54 45 4c 6f 22 0d 0a 58 2d 50 6f 77 65   MoTELo"..X-Powe
00e0  72 65 64 2d 42 79 3a 20 41 53 50 2e 4e 45 54 0d   red-By:ASP.NET.
00f0  0a 57 57 57 2d 41 75 74 68 65 6e 74 69 63 61 74   .WWW-Authenticat
0100  65 3a 20 44 69 67 65 73 74 20 71 6f 70 3d 22 61   e: Digestqop="a
0110  75 74 68 22 2c 20 72 65 61 6c 6d 3d 22 4d 61 70   uth",realm="Map
0120  50 6f 69 6e 74 22 2c 20 6e 6f 6e 63 65 3d 22 31   Point",nonce="1
0130  33 63 33 38 66 33 35 37 34 30 38 61 31 66 63 31   3c38f357408a1fc1
0140  34 38 34 38 37 35 32 31 31 30 30 37 30 32 64 30   48487521100702d0
0150  66 61 64 64 30 35 65 36 62 37 63 66 35 34 38 30   fadd05e6b7cf5480
0160  36 35 36 35 37 31 33 63 37 39 30 22 0d 0a 43 6f   6565713c790"..Co
0170  6e 74 65 6e 74 2d 4c 65 6e 67 74 68 3a 20 30 0d   ntent-Length:0.
0180  0a 0d 0a                                          ...


    * Previous message: PyChecker lives, version 0.8.15 released
    * Next message: Digest MD5 authentication over using ZSI
    * Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

More information about the Python-list mailing list

NTLM Authentication

Re: NTLM Authentication
Subject: 	Re: NTLM Authentication
List-id: 	Discussion of Python and Web services <pywebsvcs-talk.lists.sourceforge.net>

> Date: Fri, 17 Nov 2006 10:50:56 -0500
> From: Chris Lambacher <chris@xxxxxxxxxxxxxxxx>
> Subject: Re: [Pywebsvcs-talk] NTLM Authentication
> To: Charlie Moad <cwmoad@xxxxxxxxx>
> Cc: pywebsvcs-talk <pywebsvcs-talk@xxxxxxxxxxxxxxxxxxxxx>
> Message-ID: <20061117155056.GA16275@xxxxxxxxxxxxxxxx>
> Content-Type: text/plain; charset=us-ascii
>
> On Fri, Nov 17, 2006 at 09:26:01AM -0500, Charlie Moad wrote:
> > Has anyone ever done, or know how to do NTLM authentication
> with ZSI?
> ZSI uses httplib from the standard library to perform HTTP
> communication.
> Nothing in the standard library supports NTLM authentication.
>  You will have
> to do a lot of fiddling to get this to work.  You can find a python
> implementation at:
> http://ntlmaps.sourceforge.net/
>
> It provides a proxy, which might be a sufficient solution for you.
>
> -Chris
>
NTLMaps does its job quite well in my experience.

I wrote a ZSI_Transport module to pass to client.Binding.
It emulates enough of httplib.HTTPConnection to satisfy ZSI, and
calls urllib2 to handle the proxy. That's kind of an upside down
approach, since in my opinion, ZSI should be using urllib2
directly, but it gets the job done. I'm using it with 2.0rc2.
I don't know if the approach is still valid with the latest
release.

I haven't obtained permission from my employer to publish the
code, but I'd be happy to answer any questions I can about how
I did it.

This email and any files transmitted with it are confidential and are intended
solely for the use of the individual or entity to whom they are addressed.  If
you are not the original recipient or the person responsible for delivering the
email to the intended recipient, be advised that you have received this email
in error, and that any use, dissemination, forwarding, printing, or copying of
this email is strictly prohibited. If you received this email in error, please
immediately notify the sender and delete the original.

Back to Python Python - ZSI Module