def get(self, path): """ Perform a GET request with Kerberos authentication """ # Prepare Kerberos ticket granting ticket """ _, ctx = kerberos.authGSSClientInit( 'HTTP@{0}'.format(self.url.netloc)) kerberos.authGSSClientStep(ctx, "") tgt = kerberos.authGSSClientResponse(ctx) # Make the connection connection = httplib.HTTPSConnection(self.url.netloc, 443) log.debug("GET {0}".format(path)) connection.putrequest("GET", path) connection.putheader("Authorization", "Negotiate {0}".format(tgt)) connection.putheader("Referer", self.url_string) connection.endheaders() # Perform the request, convert response into lines response = connection.getresponse() if response.status != 200: raise ReportError( "Failed to fetch tickets: {0}".format(response.status)) lines = response.read().decode("utf8").strip().split("\n")[1:] log.debug("Tickets fetched:") log.debug(pretty(lines)) return lines
def _get_krb5_ap_req(service, server): """Returns the AP_REQ Kerberos 5 ticket for a given service.""" import kerberos, base64 try: status_code, context = kerberos.authGSSClientInit('moira@%s' % server) kerberos.authGSSClientStep(context, "") token_gssapi = base64.b64decode( kerberos.authGSSClientResponse(context)) # The following code "parses" GSSAPI token as described in RFC 2743 and RFC 4121. # "Parsing" in this context means throwing out the GSSAPI header correctly # while doing some very basic validation of its contents. # # This code is here because Python's interface provides only GSSAPI interface, # and Moira does not use GSSAPI. # (FIXTHEM: it should) # # FIXME: this probably should either parse tokens properly or use another # Kerberos bindings for Python. # Note that krb5 bindings are even more horrible. body_start = token_gssapi.find( chr(0x01) + chr(0x00)) # 01 00 indicates that this is AP_REQ if token_gssapi[0] != chr(0x60) or \ not (token_gssapi[2] == chr(0x06) or token_gssapi[4] == chr(0x06)) or \ body_start == -1 or body_start < 8 or body_start > 64: raise ConnectionError( "Invalid GSSAPI token provided by Python's Kerberos API") body = token_gssapi[body_start + 2:] return body except kerberos.GSSError as err: raise AuthenticationError("Kerberos authentication error: %s" % err[1][0])
def __init__(self, service): __, krb_context = kerberos.authGSSClientInit(service) kerberos.authGSSClientStep(krb_context, "") self._krb_context = krb_context self.auth_header = ( "Negotiate " + kerberos.authGSSClientResponse(krb_context) )
def http_error_401(self, req, fp, code, msg, headers): try: if self._retried > 5: raise urllib2.HTTPError(req.get_full_url(), 401, "negotiate auth failed", headers, None) self._retried += 1 logging.debug('gssapi handler, try %s' % self._retried) negotiate = get_negociate_value(headers) if negotiate is None: logging.debug('no negociate found in a www-authenticate header') return None logging.debug('HTTPGssapiAuthHandler: negotiate 1 is %r' % negotiate) result, self._context = krb.authGSSClientInit("HTTP@%s" % req.get_host()) if result < 1: raise GssapiAuthError("HTTPGssapiAuthHandler: init failed with %d" % result) result = krb.authGSSClientStep(self._context, negotiate) if result < 0: raise GssapiAuthError("HTTPGssapiAuthHandler: step 1 failed with %d" % result) client_response = krb.authGSSClientResponse(self._context) logging.debug('HTTPGssapiAuthHandler: client response is %s...' % client_response[:10]) req.add_unredirected_header('Authorization', "Negotiate %s" % client_response) server_response = self.parent.open(req) negotiate = get_negociate_value(server_response.info()) if negotiate is None: logging.warning('HTTPGssapiAuthHandler: failed to authenticate server') else: logging.debug('HTTPGssapiAuthHandler negotiate 2: %s' % negotiate) result = krb.authGSSClientStep(self._context, negotiate) if result < 1: raise GssapiAuthError("HTTPGssapiAuthHandler: step 2 failed with %d" % result) return server_response except GssapiAuthError, exc: logging.error(repr(exc))
def __init__(self, service): """Init self.""" __, krb_context = kerberos.authGSSClientInit(service) kerberos.authGSSClientStep(krb_context, "") self._krb_context = krb_context self.auth_header = ("Negotiate " + kerberos.authGSSClientResponse(krb_context))
def _create_kerberos_session(self, kerberos_service): __, krb_context = kerb.authGSSClientInit(kerberos_service) kerb.authGSSClientStep(krb_context, "") auth_header = ("Negotiate " + kerb.authGSSClientResponse(krb_context)) self._update_header("Authorization", auth_header) response = self._session.get(self.url, verify=self.verify_ssl) response.raise_for_status()
def gssapi_login(self, user): # Try GSSAPI login first # Used FTP response codes: # 235 [ADAT=base64data] - indicates that the security data exchange # completed successfully. # 334 [ADAT=base64data] - indicates that the requested security # mechanism is ok, and includes security data to be used by the # client to construct the next command. # 335 [ADAT=base64data] - indicates that the security data is # acceptable, and more is required to complete the security # data exchange. resp = self.sendcmd('AUTH GSSAPI') if resp.startswith('334 '): rc, self.vc = kerberos.authGSSClientInit("ftp@%s" % self.host) if kerberos.authGSSClientStep(self.vc, "") != 1: while resp[:4] in ('334 ', '335 '): authdata = kerberos.authGSSClientResponse(self.vc) resp = self.sendcmd('ADAT ' + authdata) if resp[:9] in ('235 ADAT=', '335 ADAT='): rc = kerberos.authGSSClientStep(self.vc, resp[9:]) if not ((resp.startswith('235 ') and rc == 1) or (resp.startswith('335 ') and rc == 0)): raise ftplib.error_reply, resp note( gettext("Authenticated as %s") % kerberos.authGSSClientUserName(self.vc)) # Monkey patch ftplib self.putcmd = self.mic_putcmd self.getline = self.mic_getline self.sendcmd('USER ' + user) return resp mutter("Unable to use GSSAPI authentication: %s", resp)
def _login(self, context_url, username, password): # use kerberos login, should be remove for security consideration if not username and not password: host = urlparse(context_url).hostname result, kbr_ctx = kerberos.authGSSClientInit('HTTP@%s' % host) if result < 1: raise OperationError("Kerberos login not support!") kerberos.authGSSClientStep(kbr_ctx, '') cret = 'Negotiate %s' % kerberos.authGSSClientResponse(kbr_ctx) step_auth_url = context_url if step_auth_url[-1] != '/': step_auth_url += '/' step_auth_url += 'step-auth-gss' res = self.session.get(step_auth_url, headers={ 'Authorization': cret, }) else: # prepare some cookies self.session.get(context_url) res = self.session.get(context_url, params={'os_authType': 'basic'}, auth=(username, password)) if not res.ok or not res.headers.get('X-AUSERNAME', None): # TODO delete me print res.text, res.headers raise PermissionDenied("Failed to login")
def get_kerberos_authorization(self): import kerberos _, ctx = kerberos.authGSSClientInit("HTTP@%s" % self.conn.host) kerberos.authGSSClientStep(ctx, "") tgt = kerberos.authGSSClientResponse(ctx) return "Negotiate %s" % tgt
def _get_krb5_ap_req(service, server): """Returns the AP_REQ Kerberos 5 ticket for a given service.""" import kerberos, base64 try: status_code, context = kerberos.authGSSClientInit( 'moira@%s' % server ) kerberos.authGSSClientStep(context, "") token_gssapi = base64.b64decode( kerberos.authGSSClientResponse(context) ) # The following code "parses" GSSAPI token as described in RFC 2743 and RFC 4121. # "Parsing" in this context means throwing out the GSSAPI header correctly # while doing some very basic validation of its contents. # # This code is here because Python's interface provides only GSSAPI interface, # and Moira does not use GSSAPI. # (FIXTHEM: it should) # # FIXME: this probably should either parse tokens properly or use another # Kerberos bindings for Python. # Note that krb5 bindings are even more horrible. body_start = token_gssapi.find( chr(0x01) + chr(0x00) ) # 01 00 indicates that this is AP_REQ if token_gssapi[0] != chr(0x60) or \ not (token_gssapi[2] == chr(0x06) or token_gssapi[4] == chr(0x06)) or \ body_start == -1 or body_start < 8 or body_start > 64: raise ConnectionError("Invalid GSSAPI token provided by Python's Kerberos API") body = token_gssapi[body_start + 2:] return body except kerberos.GSSError as err: raise AuthenticationError("Kerberos authentication error: %s" % err[1][0])
def gssapi_login(self, user): # Try GSSAPI login first # Used FTP response codes: # 235 [ADAT=base64data] - indicates that the security data exchange # completed successfully. # 334 [ADAT=base64data] - indicates that the requested security # mechanism is ok, and includes security data to be used by the # client to construct the next command. # 335 [ADAT=base64data] - indicates that the security data is # acceptable, and more is required to complete the security # data exchange. resp = self.sendcmd('AUTH GSSAPI') if resp.startswith('334 '): rc, self.vc = kerberos.authGSSClientInit("ftp@%s" % self.host) if kerberos.authGSSClientStep(self.vc, "") != 1: while resp[:4] in ('334 ', '335 '): authdata = kerberos.authGSSClientResponse(self.vc) resp = self.sendcmd('ADAT ' + authdata) if resp[:9] in ('235 ADAT=', '335 ADAT='): rc = kerberos.authGSSClientStep(self.vc, resp[9:]) if not ((resp.startswith('235 ') and rc == 1) or (resp.startswith('335 ') and rc == 0)): raise ftplib.error_reply, resp note(gettext("Authenticated as %s") % kerberos.authGSSClientUserName(self.vc)) # Monkey patch ftplib self.putcmd = self.mic_putcmd self.getline = self.mic_getline self.sendcmd('USER ' + user) return resp mutter("Unable to use GSSAPI authentication: %s", resp)
def tcp_client(opts, conn): ctx = krbV.default_context() if opts.ccache: ccache = krbV.CCache(name='FILE:' + opts.ccache, context=ctx) else: ccache = ctx.default_ccache() cprinc = ccache.principal() sprinc = krbV.Principal(name=opts.principal, context=ctx) tgt = krbV.Principal('krbtgt/%s@%s' % (sprinc.realm, sprinc.realm), context=ctx) try: creds = (cprinc, tgt, (0, None), (0,0,0,0), None, None, None, None, None, None) tcreds = ccache.get_credentials(creds, krbV.KRB5_GC_CACHED) creds = (cprinc, sprinc, (0, None), (0,0,0,0), None, None, None, None, tcreds[7], None) screds = ccache.get_credentials(creds, krbV.KRB5_GC_USER_USER) ac = krbV.AuthContext(context=ctx) ac, bc = ctx.mk_req(sprinc, 'None', krbV.AP_OPTS_MUTUAL_REQUIRED, cprinc, ccache, ac, screds) pdb.set_trace() _ignore, vc = kerberos.authGSSClientInit('*****@*****.**') kerberos.authGSSClientStep(vc, "") #_ignore = kerberos.authGSSClientStep(ctx, bc) #tgt = kerberos.authGSSClientResponse(ctx) headers = {'Authorization': 'Negotiate %s' % kerberos.authGSSClientResponse(vc) } servername, port = ('localhost', 80) h = httplib.HTTPConnection(servername, port) h.request('GET', "", "", headers) response = h.getresponse() print 'Successfully authenticated via tcp to service: %s' % sprinc.name except krbV.Krb5Error, e: return e
def krb_authenticate(es_client: EsClient, service=None, username=None, name=None): _logger.debug(f'Connection with Kerberos: {service}') if service is None: raise PeekError('Service is required for kerberos authentication') import kerberos result, context = kerberos.authGSSClientInit(service, principal=username) kerberos.authGSSClientStep(context, '') ticket = kerberos.authGSSClientResponse(context) _logger.debug(f'Kerberos ticket: {ticket}') auth_response = es_client.perform_request( 'POST', '/_security/oauth2/token', json.dumps({ 'grant_type': '_kerberos', 'kerberos_ticket': ticket, }), deserialize_it=True) _logger.debug(f'Kerberos Token auth response: {auth_response}') return RefreshingEsClient( es_client, '_KRB', auth_response['access_token'], auth_response['refresh_token'], auth_response['expires_in'], name=name)
def authenticate_server(self, response): """ Uses GSSAPI to authenticate the server. Returns True on success, False on failure. """ log.debug("authenticate_server(): Authenticate header: {0}".format( _negotiate_value(response))) host = urlparse(response.url).hostname try: # If this is set pass along the struct to Kerberos if self.cbt_struct: result = kerberos.authGSSClientStep(self.context[host], _negotiate_value(response), channel_bindings=self.cbt_struct) else: result = kerberos.authGSSClientStep(self.context[host], _negotiate_value(response)) except kerberos.GSSError: log.exception("authenticate_server(): authGSSClientStep() failed:") return False if result < 1: log.error("authenticate_server(): authGSSClientStep() failed: " "{0}".format(result)) return False log.debug("authenticate_server(): returning {0}".format(response)) return True
def _krb_auth_header(self): retcode = subprocess.Popen( ["klist"], stdout=subprocess.PIPE, stderr=subprocess.PIPE ).wait() krb5ccname = None if retcode or self.ktfile: old_krb5ccname = os.environ.get("KRB5CCNAME", "") _, krb5ccname = tempfile.mkstemp(prefix="krb5cc") retcode = subprocess.Popen( ["kinit", self.krb_princ, "-k", "-t", self.ktfile, "-c", krb5ccname], stdout=subprocess.PIPE, stderr=subprocess.PIPE, ).wait() try: if krb5ccname: os.environ["KRB5CCNAME"] = krb5ccname __, krb_context = kerberos.authGSSClientInit("HTTP@%s" % self.service) kerberos.authGSSClientStep(krb_context, "") self._krb_context = krb_context auth_header = "Negotiate " + kerberos.authGSSClientResponse(krb_context) finally: if krb5ccname: os.environ["KRB5CCNAME"] = old_krb5ccname os.unlink(krb5ccname) return auth_header
def thresholdCheck(service,alert_msg,thresholdTypes=[]): endpoint=config_grabber(service+"-svc-config")["endpoint"] principal=config_grabber(service+"-svc-config")["principal"] __, krb_context = kerberos.authGSSClientInit(principal) kerberos.authGSSClientStep(krb_context, "") negotiate_details = kerberos.authGSSClientResponse(krb_context) headers = {"Authorization": "Negotiate " + negotiate_details} res = requests.get(endpoint, headers=headers, verify=False) data = json.loads(res.text) df=pd.DataFrame.from_records(data['beans']) sub = '';flag = 0 for thresholdType in thresholdTypes: for key in literal_eval(config_grabber(service)[thresholdType]): for prio in literal_eval(config_grabber('root')['priority']): if (service+"|"+key) in config_grabber(prio).keys(): value=config_grabber(prio)[service+"|"+key] new_val=df.loc[0][key] #if(apply_operator(value,thresholdType,df.loc[0][key])) if(thresholdType in ['ne','eq']): res = apply_operator(value,thresholdType,str(new_val).strip()) elif(thresholdType == 'lt'): res = True if float(value) < float(new_val) else False; elif(thresholdType == 'gt'): res = True if float(new_val) > float(value) else False if(res): print(float(df.loc[0][key]),thresholdType,float(value)) alert_msg += '<tr class="'+prio+'"> <td> '+key+' </td><td> '+value+' </td><td> '+str(df.loc[0][key])+' </td></tr>' if flag == 0: sub = "ALERT "+prio+": "+service+" ";flag=1 else :alert_msg += '<tr> <td> '+key+' </td><td> '+value+' </td><td> '+str(df.loc[0][key])+' </td></tr>' return (sub,alert_msg)
def process(self, challenge=None): if not self._have_negotiated_details: kerberos.authGSSClientStep(self.context, '') _negotiated_details = kerberos.authGSSClientResponse(self.context) self._have_negotiated_details = True return base64.b64decode(_negotiated_details) challenge = base64.b64encode(challenge).decode( 'ascii') # kerberos methods expect strings, not bytes if self.user is None: ret = kerberos.authGSSClientStep(self.context, challenge) if ret == kerberos.AUTH_GSS_COMPLETE: self.user = kerberos.authGSSClientUserName(self.context) return b'' else: response = kerberos.authGSSClientResponse(self.context) if response: response = base64.b64decode(response) else: response = b'' return response kerberos.authGSSClientUnwrap(self.context, challenge) data = kerberos.authGSSClientResponse(self.context) plaintext_data = base64.b64decode(data) if len(plaintext_data) != 4: raise SASLProtocolException( "Bad response from server") # todo: better message word, = struct.unpack('!I', plaintext_data) qop_bits = word >> 24 max_length = word & 0xffffff server_offered_qops = QOP.names_from_bitmask(qop_bits) self._pick_qop(server_offered_qops) self.max_buffer = min(self.sasl.max_buffer, max_length) """ byte 0: the selected qop. 1==auth, 2==auth-int, 4==auth-conf byte 1-3: the max length for any buffer sent back and forth on this connection. (big endian) the rest of the buffer: the authorization user name in UTF-8 - not null terminated. """ auth_id = self.sasl.authorization_id or self.user l = len(auth_id) fmt = '!I' + str(l) + 's' word = QOP.flag_from_name(self.qop) << 24 | self.max_buffer out = struct.pack( fmt, word, _b(auth_id), ) encoded = base64.b64encode(out).decode('ascii') kerberos.authGSSClientWrap(self.context, encoded) response = kerberos.authGSSClientResponse(self.context) self.complete = True return base64.b64decode(response)
def __init__(self, service): ignored_code, krb_context = kerberos.authGSSClientInit(service) kerberos.authGSSClientStep(krb_context, "") # TODO authGSSClientStep may raise following error: # GSSError: (('Unspecified GSS failure. Minor code may provide more information', 851968), ("Credentials cache file '/tmp/krb5cc_1000' not found", -1765328189)) self._krb_context = krb_context gss_response = kerberos.authGSSClientResponse(krb_context) self.auth_header = "Negotiate {0}".format(gss_response)
def get_auth_header(self): if self.ctx: raise RuntimeError("Context has already been initialized") __, self.ctx = kerberos.authGSSClientInit(self.service, principal=self.principal) kerberos.authGSSClientStep(self.ctx, "") token = kerberos.authGSSClientResponse(self.ctx) return {"Authorization": "Negotiate " + token}
def __init__(self, service): ignored_code, krb_context = kerberos.authGSSClientInit(service) kerberos.authGSSClientStep(krb_context, '') # TODO authGSSClientStep may raise following error: #GSSError: (('Unspecified GSS failure. Minor code may provide more information', 851968), ("Credentials cache file '/tmp/krb5cc_1000' not found", -1765328189)) self._krb_context = krb_context gss_response = kerberos.authGSSClientResponse(krb_context) self.auth_header = 'Negotiate {0}'.format(gss_response)
def _call(self, fun, *args): if self._function_is_sessioned(fun): args = [self._get_session()] + list(args) if fun.endswith("_dig") and self._argcount(fun) == 3: if isinstance(args[1], str) or isinstance(args[1], unicode): args[1] = self._parse_digstr(args[1]) if len(args) == 2: args.append({'_': True}) elif isinstance(args[2], str) or isinstance(args[2], unicode): args[2] = self._parse_digstr(args[2]) if fun == "session_auth_kerberos": try: import kerberos except: raise ValueError( "No kerberos module installed - cannot perform kerberos authentication" ) (_res, ctx) = kerberos.authGSSClientInit("HTTP@" + self._host) kerberos.authGSSClientStep(ctx, "") token = kerberos.authGSSClientResponse(ctx) # print >>sys.stderr, "TOKEN=",token args.append(token) # Perform call, measuring passed time. start_time = time.time() rawret = self._rawcall(fun, *args) self._time = time.time() - start_time if "result" in rawret: # Call succeeded. ret = rawret["result"] # Save auth and session data from known calls. if fun == 'session_auth_login': self._auth = args[1] elif fun == 'session_deauth': self._auth = None elif fun.startswith('session_start'): self._session_id = ret if self._attrdicts: ret = self._convert_to_attrdicts(ret) return ret else: # Call returned an error err = rawret['error'] if self._attrdicts: err = self._convert_to_attrdicts(err) _errname = err['name'] raise error_object(err, self._pyexceptions)
def set_kerberos_auth(self): _, ctx = kerberos.authGSSClientInit("HTTP@" + self.host, gssflags=kerberos.GSS_C_DELEG_FLAG|kerberos.GSS_C_MUTUAL_FLAG|kerberos.GSS_C_SEQUENCE_FLAG) kerberos.authGSSClientStep(ctx, '') self.__tgt = kerberos.authGSSClientResponse(ctx) if self.__tgt: self.headers['Authorization'] = 'Negotiate %s' % self.__tgt else: raise RuntimeError(_("Couldn't authenticate via kerberos"))
def negotiate_auth(): #_, krb_context = kerberos.authGSSClientInit("HTTP@hadoop") #ipdb.set_trace() _, krb_context = kerberos.authGSSClientInit("HTTP@hadoop") kerberos.authGSSClientStep(krb_context, "") negotiate_details = kerberos.authGSSClientResponse(krb_context) headers = {"Authorization": "Negotiate" + negotiate_details} resp = requests.get("http://lg-hadoop-control01.bj:21201/webhdfs/v1/?op=liststatus", headers = headers) print resp.status_code print resp.content
def _krb_response(self, host, krb_val): logger.debug("INSIDE _krb_response") _dummy, self.krb_context = kerberos.authGSSClientInit("HTTP@%s" % host) kerberos.authGSSClientStep(self.krb_context, krb_val) response = kerberos.authGSSClientResponse(self.krb_context) logger.debug("kerb auth successful") return response
def get_response(self, challenge=""): dprint("pykerberos SSPI") try: pykerberos.authGSSClientStep(self.ctx, challenge) auth_req = pykerberos.authGSSClientResponse(self.ctx) except pykerberos.GSSError: traceback.print_exc(file=sys.stdout) return None return auth_req
def test_auth(client): hostname = "kerberos.example.com" service = f"HTTP@{hostname}" mech_oid = kerberos.GSS_MECH_OID_KRB5 rc, vc = kerberos.authGSSClientInit(service=service, mech_oid=mech_oid) kerberos.authGSSClientStep(vc, "") kerberos_token = kerberos.authGSSClientResponse(vc) headers = {"Authorization": f"Negotiate {kerberos_token}"} r = client.get("/", headers=headers) assert r.status_code == 200
def _call(self, fun, *args): if self._function_is_sessioned(fun): args = [self._get_session()] + list(args) if fun.endswith("_dig") and self._argcount(fun) == 3: if isinstance(args[1], str) or isinstance(args[1], unicode): args[1] = self._parse_digstr(args[1]) if len(args) == 2: args.append({'_': True}) elif isinstance(args[2], str) or isinstance(args[2], unicode): args[2] = self._parse_digstr(args[2]) if fun == "session_auth_kerberos": try: import kerberos except: raise ValueError("No kerberos module installed - cannot perform kerberos authentication") (_res, ctx) = kerberos.authGSSClientInit("HTTP@" + self._host) kerberos.authGSSClientStep(ctx, "") token = kerberos.authGSSClientResponse(ctx) # print >>sys.stderr, "TOKEN=",token args.append(token) # Perform call, measuring passed time. start_time = time.time() rawret = self._rawcall(fun, *args) self._time = time.time() - start_time if "result" in rawret: # Call succeeded. ret = rawret["result"] # Save auth and session data from known calls. if fun == 'session_auth_login': self._auth = args[1] elif fun == 'session_deauth': self._auth = None elif fun.startswith('session_start'): self._session_id = ret if self._attrdicts: ret = self._convert_to_attrdicts(ret) return ret else: # Call returned an error err = rawret['error'] if self._attrdicts: err = self._convert_to_attrdicts(err) _errname = err['name'] raise error_object(err, self._pyexceptions)
def process(self, challenge=None): if not self._have_negotiated_details: kerberos.authGSSClientStep(self.context, '') _negotiated_details = kerberos.authGSSClientResponse(self.context) self._have_negotiated_details = True return base64.b64decode(_negotiated_details) challenge = base64.b64encode(challenge).decode('ascii') # kerberos methods expect strings, not bytes if self.user is None: ret = kerberos.authGSSClientStep(self.context, challenge) if ret == kerberos.AUTH_GSS_COMPLETE: self.user = kerberos.authGSSClientUserName(self.context) return b'' else: response = kerberos.authGSSClientResponse(self.context) if response: response = base64.b64decode(response) else: response = b'' return response kerberos.authGSSClientUnwrap(self.context, challenge) data = kerberos.authGSSClientResponse(self.context) plaintext_data = base64.b64decode(data) if len(plaintext_data) != 4: raise SASLProtocolException("Bad response from server") # todo: better message word, = struct.unpack('!I', plaintext_data) qop_bits = word >> 24 max_length = word & 0xffffff server_offered_qops = QOP.names_from_bitmask(qop_bits) self._pick_qop(server_offered_qops) self.max_buffer = min(self.sasl.max_buffer, max_length) """ byte 0: the selected qop. 1==auth, 2==auth-int, 4==auth-conf byte 1-3: the max length for any buffer sent back and forth on this connection. (big endian) the rest of the buffer: the authorization user name in UTF-8 - not null terminated. """ auth_id = self.sasl.authorization_id or self.user l = len(auth_id) fmt = '!I' + str(l) + 's' word = QOP.flag_from_name(self.qop) << 24 | self.max_buffer out = struct.pack(fmt, word, _b(auth_id),) encoded = base64.b64encode(out).decode('ascii') kerberos.authGSSClientWrap(self.context, encoded) response = kerberos.authGSSClientResponse(self.context) self.complete = True return base64.b64decode(response)
def get_auth_headers(auth_cookie): import kerberos if auth_cookie: cookie_value = auth_cookie.output(attrs=['value'], header='' ).strip() return {'Cookie': cookie_value} else: _, krb_context = kerberos.authGSSClientInit("%s@%s" % (kerberos_service_name, kerberos_host)) kerberos.authGSSClientStep(krb_context, "") negotiate_details = kerberos.authGSSClientResponse(krb_context) return {"Authorization": "Negotiate " + negotiate_details}
def _authenticate_request(self, response, **kwargs): res, ctx = kerberos.authGSSClientInit(self._service_principal, mech_oid=self._mech_oid) kerberos.authGSSClientStep(ctx, "") token = kerberos.authGSSClientResponse(ctx) response.request.headers['Authorization'] = "Negotiate " + token response.content # NOQA - to drain the stream response.raw.release_conn() authenticated_response = response.connection.send(response.request, **kwargs) authenticated_response.history.append(response) return authenticated_response
def gssclient_token(self): os.environ['KRB5_CLIENT_KTNAME'] = self.IQUOTA_KEYTAB service = "HTTP@" + self.IQUOTA_API_HOST try: (_, vc) = kerberos.authGSSClientInit(service) kerberos.authGSSClientStep(vc, "") return kerberos.authGSSClientResponse(vc) except kerberos.GSSError as e: raise KerberosError('error initializing GSS client')
def set_headers(self, headers): ctx = kerberos.authGSSClientInit("HTTP@" + self.__host, \ gssflags=kerberos.GSS_C_DELEG_FLAG|kerberos.GSS_C_MUTUAL_FLAG|kerberos.GSS_C_SEQUENCE_FLAG)[1] kerberos.authGSSClientStep(ctx, '') tgt = kerberos.authGSSClientResponse(ctx) if tgt: headers['Authorization'] = 'Negotiate %s' % tgt return headers else: raise RuntimeError(_("Couldn't authenticate via kerberos"))
def pre_request(self, resp): # TODO: convert errors to some common error class import kerberos _, context = kerberos.authGSSClientInit( "HTTP@%s" % resp.url.host, gssflags=kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG, ) kerberos.authGSSClientStep(context, "") response = kerberos.authGSSClientResponse(context) headers = {"Authorization": "Negotiate " + response} return headers, context
def get_host_info(self, host): host, extra_headers, x509 = \ xmlrpclib.SafeTransport.get_host_info(self, host) service = "HTTP@%s" % host _, client = kerberos.authGSSClientInit(service) kerberos.authGSSClientStep(client, "") token = kerberos.authGSSClientResponse(client) extra_headers = [("Authorization", "Negotiate %s" % token)] return host, extra_headers, x509
def _authenticate_server(self, headers): logger.debug("INSIDE _authenticate_server") try: val = self._extract_krb_value(headers) except ValueError: logger.critical("Server authentication failed." "Auth value couldn't be extracted from headers.") return None if not val: logger.critical("Server authentication failed." "Empty 'Negotiate' value.") return None kerberos.authGSSClientStep(self.krb_context, val)
def _kerberos_received(self, message): # Inspired by: https://github.com/thobbs/pure-sasl/blob/0.6.2/puresasl/mechanisms.py # https://github.com/thobbs/pure-sasl/blob/0.6.2/LICENSE try: import kerberos except ImportError: raise ImportError('Please install gremlinpython[kerberos].') # First pass: get service granting ticket and return it to gremlin-server if not self._kerberos_context: try: _, kerberos_context = kerberos.authGSSClientInit( self._kerberized_service, gssflags=kerberos.GSS_C_MUTUAL_FLAG) kerberos.authGSSClientStep(kerberos_context, '') auth = kerberos.authGSSClientResponse(kerberos_context) self._kerberos_context = kerberos_context except kerberos.KrbError as e: raise ConfigurationError( 'Kerberos authentication requires a valid service name in DriverRemoteConnection, ' 'as well as a valid tgt (export KRB5CCNAME) or keytab (export KRB5_KTNAME): ' + str(e)) return request.RequestMessage('', 'authentication', {'sasl': auth}) # Second pass: completion of authentication sasl_response = message['status']['attributes']['sasl'] if not self._username: result_code = kerberos.authGSSClientStep(self._kerberos_context, sasl_response) if result_code == kerberos.AUTH_GSS_COMPLETE: self._username = kerberos.authGSSClientUserName(self._kerberos_context) return request.RequestMessage('', 'authentication', {'sasl': ''}) # Third pass: sasl quality of protection (qop) handshake # Gremlin-server Krb5Authenticator only supports qop=QOP_AUTH; use ssl for confidentiality. # Handshake content format: # byte 0: the selected qop. 1==auth, 2==auth-int, 4==auth-conf # byte 1-3: the max length for any buffer sent back and forth on this connection. (big endian) # the rest of the buffer: the authorization user name in UTF-8 - not null terminated. kerberos.authGSSClientUnwrap(self._kerberos_context, sasl_response) data = kerberos.authGSSClientResponse(self._kerberos_context) plaintext_data = base64.b64decode(data) assert len(plaintext_data) == 4, "Unexpected response from gremlin server sasl handshake" word, = struct.unpack('!I', plaintext_data) qop_bits = word >> 24 assert self.QOP_AUTH_BIT & qop_bits, "Unexpected sasl qop level received from gremlin server" name_length = len(self._username) fmt = '!I' + str(name_length) + 's' word = self.QOP_AUTH_BIT << 24 | self.MAX_CONTENT_LENGTH out = struct.pack(fmt, word, self._username.encode("utf-8"),) encoded = base64.b64encode(out).decode('ascii') kerberos.authGSSClientWrap(self._kerberos_context, encoded) auth = kerberos.authGSSClientResponse(self._kerberos_context) return request.RequestMessage('', 'authentication', {'sasl': auth})
def post_response(self, req, resp, context): import kerberos www_auth = resp.headers.get("www-authenticate", None) token = None if www_auth: match = self.auth_regex.search(www_auth) if match: token = match.group(1) if not token: raise Exception("Kerberos negotiation failed") kerberos.authGSSClientStep(context, token)
def negotiate_auth(): #_, krb_context = kerberos.authGSSClientInit("HTTP@hadoop") #ipdb.set_trace() _, krb_context = kerberos.authGSSClientInit("HTTP@hadoop") kerberos.authGSSClientStep(krb_context, "") negotiate_details = kerberos.authGSSClientResponse(krb_context) headers = {"Authorization": "Negotiate" + negotiate_details} resp = requests.get( "http://lg-hadoop-control01.bj:21201/webhdfs/v1/?op=liststatus", headers=headers) print resp.status_code print resp.content
def __init__(self, service): __, krb_context = kerberos.authGSSClientInit( service, kerberos.GSS_C_DELEG_FLAG | kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG) try: kerberos.authGSSClientStep(krb_context, "") self._krb_context = krb_context self.auth_header = ("Negotiate " + kerberos.authGSSClientResponse(krb_context)) except Exception as e: raise KerberosError(e.args)
def pre_request(self, req, resp): # TODO: convert errors to some common error class import kerberos hostname = urlparse(resp.effective_url).hostname _, context = kerberos.authGSSClientInit( "HTTP@%s" % hostname, gssflags=kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG, ) kerberos.authGSSClientStep(context, "") response = kerberos.authGSSClientResponse(context) req.headers["Authorization"] = "Negotiate " + response return context
def refresh_auth(self): flags = kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG try: (unused, vc) = kerberos.authGSSClientInit(self.service, flags) except kerberos.GSSError as e: LOG.error(_LE("caught kerberos exception %r") % e) raise IPAAuthError(str(e)) try: kerberos.authGSSClientStep(vc, "") except kerberos.GSSError as e: LOG.error(_LE("caught kerberos exception %r") % e) raise IPAAuthError(str(e)) self.token = kerberos.authGSSClientResponse(vc)
def check_auth_header(self, auth_header): if not self.ctx: raise RuntimeError("Invalid context: " + self.ctx) if not auth_header: raise RuntimeError("www-authenticate header is not valid: " + auth_header) auth_val = auth_header.split(" ", 1) if len(auth_val) != 2 or auth_val[0].lower() != "negotiate": raise RuntimeError("www-authenticate header is not valid: " + auth_header) kerberos.authGSSClientStep(self.ctx, auth_val[1]) kerberos.authGSSClientClean(self.ctx) self.ctx = None
def refresh_auth(self): service = "HTTP@" + self.hostname flags = kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG try: (_, vc) = kerberos.authGSSClientInit(service, flags) except kerberos.GSSError as e: LOG.error("caught kerberos exception %r" % e) raise IPAAuthError(str(e)) try: kerberos.authGSSClientStep(vc, "") except kerberos.GSSError as e: LOG.error("caught kerberos exception %r" % e) raise IPAAuthError(str(e)) self.token = kerberos.authGSSClientResponse(vc)
def verify_response(self, auth_header): for field in auth_header.split(","): kind, __, details = field.strip().partition(" ") if kind.lower() == "negotiate": auth_details = details.strip() break else: raise ValueError("Negotiate not found in %s" % auth_header) krb_context = self._krb_context if krb_context is None: raise RuntimeError("Ticket already used for verification") self._krb_context = None kerberos.authGSSClientStep(krb_context, auth_details) kerberos.authGSSClientClean(krb_context)
def verify_response(self, auth_header): """Handle comma-separated lists of authentication fields.""" for field in auth_header.split(","): kind, __, details = field.strip().partition(" ") if kind.lower() == "negotiate": auth_details = details.strip() break else: raise ValueError("Negotiate not found in %s" % auth_header) # Finish the Kerberos handshake krb_context = self._krb_context if krb_context is None: raise RuntimeError("Ticket already used for verification") self._krb_context = None kerberos.authGSSClientStep(krb_context, auth_details) kerberos.authGSSClientClean(krb_context)
def _validate_response(self, authdata): if authdata is None: return None result = kerberos.authGSSClientStep(self.context, authdata) if result == kerberos.AUTH_GSS_COMPLETE: return True return None
def authenticate_server(self, headers): neg_value = self.negotiate_value(headers) if neg_value is None: return None if kerberos.authGSSClientStep(self.context, neg_value) < 1: pass
def authenticate_server(self, response): """ Uses GSSAPI to authenticate the server. Returns True on success, False on failure. """ log.debug("authenticate_server(): Authenticate header: {0}".format( _negotiate_value(response))) host = urlparse(response.url).hostname try: result = kerberos.authGSSClientStep(self.context[host], _negotiate_value(response)) except kerberos.GSSError as e: log.error("authenticate_server(): authGSSClientStep() failed:") log.exception(e) return False if result < 1: log.error("authenticate_server(): authGSSClientStep() failed: " "{0}".format(result)) return False log.debug("authenticate_server(): returning {0}".format(response)) return True
def _kerberos_verify_response(self, vc, host, handler, errcode, errmsg, headers): """Kerberos auth - verify client identity""" # verify that headers contain WWW-Authenticate header auth_header = headers.get("WWW-Authenticate", None) if auth_header is None: errcode = 401 errmsg = "KERBEROS: No WWW-Authenticate header in second HTTP response" raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # verify that WWW-Authenticate contains Negotiate splits = auth_header.split(" ", 1) if (len(splits) != 2) or (splits[0].lower() != "negotiate"): errcode = 401 errmsg = "KERBEROS: Incorrect WWW-Authenticate header in second HTTP response: %s" % auth_header raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # do another client step to verify response from server errmsg = "KERBEROS: Could not verify server WWW-Authenticate header in second HTTP response" try: rc = kerberos.authGSSClientStep(vc, splits[1]) if rc == -1: errcode = 401 raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) except kerberos.GSSError, ex: errcode = 401 errmsg += ": %s/%s" % (ex[0][0], ex[1][0]) raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers)
def authenticate(self): gss_flags = kerberos.GSS_C_DELEG_FLAG | kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG _ignore, context = kerberos.authGSSClientInit('HTTP@' + self.hostname, gssflags=gss_flags) _ignore = kerberos.authGSSClientStep(context, '') response = kerberos.authGSSClientResponse(context) return response
def generate_request_header(self, req, headers, neg_value): self.retried += 1 log.debug("retry count: %d" % self.retried) host = req.get_host() log.debug("req.get_host() returned %s" % host) domain = host.rsplit(':', 1)[0] #result, self.context = k.authGSSClientInit("HTTP@%s" % domain) result, self.context = k.authGSSClientInit("HTTP@%s" % "hadoop") if result < 1: log.warning("authGSSClientInit returned result %d" % result) return None log.debug("authGSSClientInit() succeeded") result = k.authGSSClientStep(self.context, neg_value) if result < 0: log.warning("authGSSClientStep returned result %d" % result) return None log.debug("authGSSClientStep() succeeded") response = k.authGSSClientResponse(self.context) log.debug("authGSSClientResponse() succeeded") return "Negotiate %s" % response
def __gssauth(self, response): data = base64.b64encode(response) try: if self.gss_step == self.GSS_STATE_STEP: if not self.gss_vc: rc, self.gss_vc = kerberos.authGSSClientInit( 'imap@' + self.hostname) response = kerberos.authGSSClientResponse(self.gss_vc) rc = kerberos.authGSSClientStep(self.gss_vc, data) if rc != kerberos.AUTH_GSS_CONTINUE: self.gss_step = self.GSS_STATE_WRAP elif self.gss_step == self.GSS_STATE_WRAP: rc = kerberos.authGSSClientUnwrap(self.gss_vc, data) response = kerberos.authGSSClientResponse(self.gss_vc) rc = kerberos.authGSSClientWrap( self.gss_vc, response, self.username) response = kerberos.authGSSClientResponse(self.gss_vc) except kerberos.GSSError as err: # Kerberos errored out on us, respond with None to cancel the # authentication self.ui.debug('imap', '%s: %s'% (err[0][0], err[1][0])) return None if not response: response = '' return base64.b64decode(response)