Skip to content

Instantly share code, notes, and snippets.

@KasparNagu
Created January 3, 2016 16:30
Show Gist options
  • Save KasparNagu/25a35d81a53337812ca7 to your computer and use it in GitHub Desktop.
Save KasparNagu/25a35d81a53337812ca7 to your computer and use it in GitHub Desktop.
Spnego over GSSAPI and SSPI
from requests.auth import AuthBase
import re
import base64
import gssapi
from requests.compat import urlparse
class HTTPAuthSPNEGOGSSAPI(AuthBase):
"""Attaches HTTP GSSAPI/Kerberos Authentication to the given Request
object."""
negoRegex = re.compile('(?:.*,)*\s*Negotiate\s*([^,]*),?', re.I)
def __call__(self,request):
self.handle_request(request)
return request
def handle_request(self, request):
host = urlparse(request.url).hostname
request.headers['Authorization'] = "%s %s" % (self.authScheme,self.authorizeToken(host,""))
def authorizeToken(self,host,negoToken):
negoTokenBin = base64.b64decode(negoToken)
authBin = self.generate_request_header(host,negoTokenBin)
return base64.b64encode(authBin)
def __init__(
self,
service="HTTP"):
self.context = {}
self.service = service
self.host = None
self.context = None
self.authScheme = "Negotiate"
def initWithHost(self,host):
self.release()
self.host = host
targetspn = "%s@%s"%(self.service,self.host)
service_name = gssapi.Name(targetspn,gssapi.C_NT_HOSTBASED_SERVICE)
spnegoMechOid = gssapi.oids.OID.mech_from_string("1.3.6.1.5.5.2")
self.context = gssapi.InitContext(service_name,mech_type=spnegoMechOid)
def release(self):
if self.context:
self.context.delete()
self.context = None
def __del__(self):
self.release()
def generate_request_header(self,host,negoTokenBin):
self.initWithHost(host)
return self.context.step(negoTokenBin)
from requests.auth import AuthBase
import re
import base64
import sspi
from requests.compat import urlparse
class HTTPAuthSPNEGOSSPI(AuthBase):
"""Attaches HTTP GSSAPI/Kerberos Authentication to the given Request
object."""
negoRegex = re.compile('(?:.*,)*\s*Negotiate\s*([^,]*),?', re.I)
def __call__(self,request):
self.handle_request(request)
return request
def handle_request(self, request):
host = urlparse(request.url).hostname
request.headers['Authorization'] = "%s %s" % (self.authScheme,self.authorizeToken(host,""))
def authorizeToken(self,host,negoToken):
negoTokenBin = base64.b64decode(negoToken)
authBin = self.generate_request_header(host,negoTokenBin)
return base64.b64encode(authBin)
def __init__(
self,
service="http"):
self.context = {}
self.service = service
self.host = None
self.context = None
self.authScheme = "Negotiate"
def release(self):
pass
def initWithHost(self,host):
if self.host != host:
self.host = host
targetspn = "%s/%s"%(self.service,self.host)
self.clientAuth = sspi.ClientAuth("Negotiate", targetspn="http/%s" % self.host)
self.authScheme = self.clientAuth.pkg_info['Name']
else:
self.clientAuth.reset()
def generate_request_header(self,host,negoTokenBin):
self.initWithHost(host)
err, out_buf = self.clientAuth.authorize(negoTokenBin)
return out_buf[0].Buffer
@KasparNagu
Copy link
Author

This worked for me for a Mediawiki Server with Kerberos/LDAP Authentication.
GSSAPI variant is for Linux (with krb5 setup working, i.e. kinit and klist working), the SSPI variant is for windows (needs pywin32).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment