[Moin-user] xmlrpc with NTLM and GivenAuth
Mark Scheufele
mark.scheufele at diasemi.com
Tue Dec 21 08:48:33 EST 2010
Hi Moin users,
about a month ago I did ask for some hints how to get the xmlrpc access working under the following circumstances:
- moin version 1.9.3
- IIS with windows authentication SSPI(NTLM)
- moin authentication is auth = [GivenAuth(strip_windomain=True,autocreate=1)]
This means that the xmlrpc calls are only forwarded to the wiki after a successful ntlm authentication by the IIS webserver. The wiki then uses the REMOTE_USER variable to create or run the request under a specific account (this is explained here http://moinmo.in/HelpOnAuthentication)
When I run the following script:
import sys
import xmlrpclib
wikiurl = "http://nb-it-lt-ms/testwiki"
homewiki = xmlrpclib.ServerProxy(wikiurl + "?action=xmlrpc2",allow_none=True)
mc=xmlrpclib.MultiCall(homewiki)
mc.getRPCVersionSupported()
mc.getPage("StartPage")
try:
auth_token = homewiki.getAuthToken("mscheufe", "blah")
if not auth_token:
print "auth_token is empty"
for i in mc():
print i
except xmlrpclib.Fault as err:
print str(err)
I get the following error message:
Traceback (most recent call last):
File "test.py", line 15, in <module>
auth_token = homewiki.getAuthToken("mscheufe", "blah")
File "c:\python26\lib\xmlrpclib.py", line 1199, in __call__
return self.__send(self.__name, args)
File "c:\python26\lib\xmlrpclib.py", line 1489, in __request
verbose=self.__verbose
File "c:\python26\lib\xmlrpclib.py", line 1243, in request
headers
xmlrpclib.ProtocolError: <ProtocolError for nb-it-lt-ms/testwiki?action=xmlrpc2: 401 Unauthorized>
I managed to get the ntlm authentication against the webserver to work by writing my own xmlrpc.Transport object. (code see below). Now the ntlm authentication is working and my xmlrpc requests are forwarded to the wiki. But my calls are still not properly authenticated against the wiki by the xmlrpc interface.
Have a look at this sample:
import sys
sys.path.append("c:/Temp/MoinXmlRPC")
import xmlrpclib
from ntlmTransport import *
wikiurl = "http://nb-it-lt-ms/testwiki"
p=ntlmTransport()
homewiki = xmlrpclib.ServerProxy(wikiurl + "?action=xmlrpc2",allow_none=True,transport=p)
mc=xmlrpclib.MultiCall(homewiki)
mc.getRPCVersionSupported()
mc.getPage("StartPage")
try:
auth_token = homewiki.getAuthToken("mscheufe", "blah")
if not auth_token:
print "auth_token is empty"
for i in mc():
print i
except xmlrpclib.Fault as err:
print str(err)
The output of the script is:
auth_token is empty
2
<Fault 1: 'You are not allowed to read this page.'>
As one can see the xmlrpc calls are forwarded to the wiki but as the getAuthToken() method does not return a token I cannot authenticate against the wiki.
At the minute I am stuck here. I really would be interested to get the xmlrpc interface working with GivenAuth. It would be great if someone could point me into the right direction how this problem could be solved.
Many thanks in advance,
mark
###################################
# ntlm xmlrpclib.Transport object #
###################################
import xmlrpclib,sys,httplib,base64
from types import *
#code for WindoewNtlmMessageGenerator orignates from http://stackoverflow.com/questions/2969481/ntlm-authentication-in-python
class WindoewNtlmMessageGenerator:
def __init__(self,user=None):
import win32api,sspi
if not user:
user = win32api.GetUserName()
self.sspi_client = sspi.ClientAuth("NTLM",user)
def create_auth_req(self):
import pywintypes
output_buffer = None
error_msg = None
try:
error_msg, output_buffer = self.sspi_client.authorize(None)
except pywintypes.error:
return None
auth_req = output_buffer[0].Buffer
auth_req = base64.b64encode(auth_req)
return auth_req
def create_challenge_response(self,challenge):
import pywintypes
output_buffer = None
input_buffer = challenge
error_msg = None
try:
error_msg, output_buffer = self.sspi_client.authorize(input_buffer)
except pywintypes.error:
return None
response_msg = output_buffer[0].Buffer
response_msg = base64.b64encode(response_msg)
return response_msg
class ntlmTransport(xmlrpclib.Transport):
def __init__(self,use_datetime=0):
xmlrpclib.Transport.__init__(self,use_datetime)
def request(self, host, handler, request_body, verbose=0):
# issue XML-RPC request
h = self.make_connection(host)
if verbose:
h.set_debuglevel(1)
#run the ntlm handshake to get an auth token
extra_headers=self.get_ntlm_header(h,handler,request_body)
self.send_request(h, handler, request_body)
self.send_host(h,host,extra_headers)
self.send_user_agent(h)
self.send_content(h, request_body)
errcode, errmsg, headers = h.getreply()
if errcode != 200:
raise ProtocolError(
host + handler,
errcode, errmsg,
headers
)
self.verbose = verbose
try:
sock = h._conn.sock
except AttributeError:
sock = None
return self._parse_response(h.getfile(), sock)
def get_ntlm_header(self,connection,handler,request_body):
ntlm_gen = WindoewNtlmMessageGenerator()
auth_req_msg = ntlm_gen.create_auth_req()
extra_headers=[('Connection','Keep-Alive')]
self.send_request(connection,handler,request_body)
connection.putheader("Content-length","0")
connection.putheader("Connection","Keep-Alive")
connection.putheader('Authorization','NTLM'+' '+auth_req_msg)
connection.endheaders()
resp = connection._conn.getresponse()
#always read from response otherwise the subsequent call with the current http connection handle won't work
resp.read()
#generate the NTLM auth_token
challenge = resp.msg.get('WWW-Authenticate')
challenge_dec = base64.b64decode(challenge.split()[1])
auth_token = ntlm_gen.create_challenge_response(challenge_dec)
extra_headers.append(('Authorization','NTLM'+' '+auth_token))
return extra_headers
def send_host(self,connection,host,extra_headers):
host, not_used_headers, x509 = self.get_host_info(host)
for key, value in extra_headers:
connection.putheader(key, value)
_______________________________________________________________________________________
Dialog Semiconductor GmbH
Neue Str. 95
D-73230 Kirchheim
Managing Director: Dr. Jalal Bagherli
Chairman of the Supervisory Board: Gregorio Reyes
Commercial register: Amtsgericht Stuttgart: HRB 231181
UST-ID-Nr. DE 811121668
Legal Disclaimer: This e-mail communication (and any attachment/s) is confidential and
contains proprietary information, some or all of which may be legally privileged. It is
intended solely for the use of the individual or entity to which it is addressed. Access
to this email by anyone else is unauthorized. If you are not the intended recipient, any
disclosure, copying, distribution or any action taken or omitted to be taken in reliance
on it, is prohibited and may be unlawful.
More information about the Moin-user
mailing list