mongodb / winkerberos

A native Kerberos client implementation for Python on Windows
Apache License 2.0
54 stars 15 forks source link

Replacing pywin32's sspi with winkerberos leads to exception #19

Closed genotrance closed 6 years ago

genotrance commented 6 years ago

This may not really be an issue but found no other way to communicate. I'm trying to replace pywin32's SSPI implementation within Px with winkerberos due to this issue.

I have the following code:-

class NtlmMessageGenerator2:
    def __init__(self, user=None):
        if not user:
            user = win32api.GetUserName()
        status, self.ctx = winkerberos.authGSSClientInit("NTLM", gssflags=0)

    def create_auth_request(self):
        status = winkerberos.authGSSClientStep(self.ctx, "")
        if status == winkerberos.AUTH_GSS_COMPLETE:
            return winkerberos.authGSSClientResponse(self.ctx)

        return None

    def create_challenge_response(self, challenge):
        status = winkerberos.authGSSClientStep(self.ctx, challenge)
        if status == winkerberos.AUTH_GSS_COMPLETE:
            return winkerberos.authGSSClientResponse(self.ctx)

        return None

However, it fails as follows:-

Exception happened during processing of request from ('127.0.0.1', 54674)
Traceback (most recent call last):
  File "C:\Miniconda\lib\socketserver.py", line 639, in process_request_thread
    self.finish_request(request, client_address)
  File "C:\Miniconda\lib\socketserver.py", line 361, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "C:\Miniconda\lib\socketserver.py", line 696, in __init__
    self.handle()
  File "C:\Miniconda\lib\http\server.py", line 418, in handle
    self.handle_one_request()
  File "px.py", line 133, in handle_one_request
    httpserver.SimpleHTTPRequestHandler.handle_one_request(self)
  File "C:\Miniconda\lib\http\server.py", line 406, in handle_one_request
    method()
  File "px.py", line 381, in do_CONNECT
    resp, headers, body = self.do_transaction()
  File "px.py", line 301, in do_transaction
    "Proxy-Authorization": "NTLM %s" % ntlm.create_auth_request()
  File "px.py", line 117, in create_auth_request
    status = winkerberos.authGSSClientStep(self.ctx, "")
winkerberos.GSSError: SSPI: InitializeSecurityContext: The specified target is unknown or unreachable

Is NTLM not a valid service endpoint? It works fine with pywin32 (except for that issue with Python 3.6+). I'm running this on Windows 10.

Thanks in advance.

behackett commented 6 years ago

WinKerberos is not a re-implementation of pywin32's SSPI interface. All it does is re-implement PyKerberos on SSPI. It is designed to do Kerberos auth, not NTLM. That said, you can pass mech_oid=winkerberos.GSS_MECH_OID_SPNEGO to authGSSClientInit. That initializes the credentials for "Negotiate" mode, presumably for client / server setups that will negotiate to use Kerberos.

behackett commented 6 years ago

This definitely is not correct:

status, self.ctx = winkerberos.authGSSClientInit("NTLM", gssflags=0)

The first parameter is a GSSAPI service principal, <service>@<hostname>. See the docs here:

https://github.com/mongodb-labs/winkerberos/blob/0.7.0/src/winkerberos.c#L200-L264

genotrance commented 6 years ago

Thanks to your earlier comment, I got this working.

status, self.ctx = winkerberos.authGSSClientInit("NTLM", gssflags=0,
  mech_oid=winkerberos.GSS_MECH_OID_SPNEGO)

Setting service = "NTLM" works fine since I'm authenticating locally.

I've posted my changes (see class NtlmMessageGenerator) which can be used as a reference for using pywin32 SSPI and winkerberos interchangeably for local NTLM auth without a password.

Thanks a bunch for your quick reply and the great work with winkerberos.

behackett commented 6 years ago

Neat. I'm glad this project is useful for you.

genotrance commented 6 years ago

Hello @behackett, considering I have mech_oid=winkerberos.GSS_MECH_OID_SPNEGO, does it mean that winkerberos will figure out whether it should use Kerberos vs. NTLM authentication depending on how the client is setup? Looks like that is how it should be working.

I've been requested to add Kerberos support to Px but I believe it should work as is. Unfortunately I have no way to check since I don't have a setup to verify against.

Any advise is greatly appreciated, thanks in advance.

behackett commented 6 years ago

That is how it should work AFAICT. GSS_MECH_OID_SPENGO was added to match PyKerberos. I've tested it against a krb5 KDC successfully, but I don't have an NTLM environment to test it with, and WinKerberos wasn't created for NTLM.

genotrance commented 6 years ago

Thanks for getting back, ya I hope the issue submitter will try out Px in his setup and it just works.