[Zope-dev] XMLRPC and Basic Auth problems

Casey Duncan casey@zope.com
Wed, 14 Aug 2002 23:47:01 -0400


--------------Boundary-00=_D69VQDL8RVUNCZZ29I7Z
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

Python's xmlrpclib doesn't support any authentication. It is easily subcl=
assed=20
to include it. I have successfully used it to connect with Zope and I do =
not=20
have any reason to believe that Zope is broken with regard to authenticat=
ion.=20

However I do think that Python's xmlrpclib should include basic auth. Per=
haps=20
I will make an effort to put this in, since it is so easy.

This how-to provides the code for extending xmlrpclib:

http://www.zope.org/Members/Amos/XML-RPC

It doesn't quite work for Python 2.1+, but I have attached a working vers=
ion I=20
use.

hth,

Casey=20

On Wednesday 14 August 2002 10:51 pm, Tim Hoffman wrote:
> I have had further from Adam Megacz <adam@megacz.com> the author of XWT
> on this issue.
>=20
> I believe I should raise a collector issue on this, however do=20
> people believe this is a correct assessment of the situation.
>=20
>=20
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> Tim Hoffman <timhoffman@cams.wa.gov.au> writes:
> > The xmlrpc spec doesn't say anything about authentication.
> > ...
> > I suppose this whole area is pretty vague.
>=20
> Actually, it references the HTTP spec, which is quite clear about
> requiring a 401.
>=20
>   http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2
>=20
> Without the 401, you don't know the authentication realm,
> authentication type, or digest nonce -- three things you need to know
> in order to authenticate (although the last one is only needed for
> Digest auth, not Basic Auth).
>=20
> Unfortunately, it seems that a lot of XML-RPC libraries are broken in
> this manner. I'm working with the Apache people right now on fixing
> the Java libraries -- could you please work with the Python people to
> get this fixed?
>=20
> I think this is a result of the fact that HTTP Auth isn't used very
> often in XML-RPC, although it should be. I'm working on an RFC for
> XML-RPC, and I will certainly include some wording which underscores
> the importance of the 401 response.
>=20
>     http://www.xwt.org/xmc/draft-megacz-xmc-05.txt
>=20
>   - a
>=20
> --=20
> Sick of HTML user interfaces?
> www.xwt.org
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
>=20
>=20
>=20
> On Thu, 2002-08-15 at 10:47, Tim Hoffman wrote:
> > Hi
> >=20
> > I am working on a project that uses XWT (xwt.org) as a frontend to Zo=
pe.
> >=20
> > XWT uses XMLRPC to communicate with a backend (in this case Zope).
> >=20
> > XWT expects an Error 401 is authentication is required on an XMLRPC
> > call, so that it can negotiate the correct auth method=20
> >=20
> > The author of XWT sent the following email to me
> >=20
> > >Tim, I've got a piece of the answer -- your server needs to return a=
n
> > >HTTP 401 (Unauthorized) if no username/password is provided. This
> > >response includes the challenge that XWT needs in order to build an
> > >authentication request (realm, digest nonce challenge, etc).
> >=20
> > However what Zope is doing is sending back a <fault> in the=20
> > XMLRPC <methodResponse> packet.=20
> >=20
> > So it appears to me that Zope doesn't send a http response 401 for=20
> > XMLRPC (over http), but will send a 401 back to the browser.
> >=20
> > XMLRPC doesn't say anything about authentication, so I suppose either
> > method is acceptable. However because XMLRPC is implemented=20
> > on top of http, I would have thought a http approach (ie error 401)
> > would be used.
> >=20
> > It appears that this behaviour is fundamental to Zope and is not an
> > artifact of cookie auth in CMF etc..
> >=20
> > Is this really correct behaviour ?
> >=20
> > Regards
> >=20
> > Tim Hoffman
> >=20
> >=20
> > =20
> >=20
> >=20
> > _______________________________________________
> > Zope-Dev maillist  -  Zope-Dev@zope.org
> > http://lists.zope.org/mailman/listinfo/zope-dev
> > **  No cross posts or HTML encoding!  **
> > (Related lists -=20
> >  http://lists.zope.org/mailman/listinfo/zope-announce
> >  http://lists.zope.org/mailman/listinfo/zope )
>=20
>=20
>=20
> _______________________________________________
> Zope-Dev maillist  -  Zope-Dev@zope.org
> http://lists.zope.org/mailman/listinfo/zope-dev
> **  No cross posts or HTML encoding!  **
> (Related lists -=20
>  http://lists.zope.org/mailman/listinfo/zope-announce
>  http://lists.zope.org/mailman/listinfo/zope )
>=20

--------------Boundary-00=_D69VQDL8RVUNCZZ29I7Z
Content-Type: text/x-python;
  charset="iso-8859-1";
  name="BasicAuthTransport.py"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="BasicAuthTransport.py"

import string, xmlrpclib, httplib
from base64 import encodestring

class BasicAuthTransport(xmlrpclib.Transport):
    verbose = 0
    
    def __init__(self, username=None, password=None):
        self.username=username
        self.password=password

    def request(self, host, handler, request_body, verbose=0):
        # issue XML-RPC request

        h = httplib.HTTP(host)
        h.putrequest("POST", handler)

        # required by HTTP/1.1
        h.putheader("Host", host)

        # required by XML-RPC
        h.putheader("User-Agent", self.user_agent)
        h.putheader("Content-Type", "text/xml")
        h.putheader("Content-Length", str(len(request_body)))

        # basic auth
        if self.username is not None and self.password is not None:
            h.putheader("AUTHORIZATION", "Basic %s" % string.replace(
                    encodestring("%s:%s" % (self.username, self.password)),
                    "\012", ""))
        h.endheaders()

        if request_body:
            h.send(request_body)

        errcode, errmsg, headers = h.getreply()

        if errcode != 200:
            raise xmlrpclib.ProtocolError(
                host + handler,
                errcode, errmsg,
                headers
                )

        return self.parse_response(h.getfile()) 



--------------Boundary-00=_D69VQDL8RVUNCZZ29I7Z--