def process(self, challenge=b''): b64_challenge = b64encode(challenge) try: if self.step == 0: result = kerberos.authGSSClientStep( self.gss, b64_challenge) if result != kerberos.AUTH_GSS_CONTINUE: self.step = 1 elif not challenge: kerberos.authGSSClientClean(self.gss) return b'' elif self.step == 1: username = self.credentials['username'] kerberos.authGSSClientUnwrap(self.gss, b64_challenge) resp = kerberos.authGSSClientResponse(self.gss) kerberos.authGSSClientWrap(self.gss, resp, username) resp = kerberos.authGSSClientResponse(self.gss) except kerberos.GSSError as e: raise SASLCancelled('Kerberos error: %s' % e) if not resp: return b'' else: return b64decode(resp)
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)
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)
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 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 _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 step(self, sec_buf): self.result = kerberos.authGSSClientStep(self.context, sec_buf.tostring()) if self.result == 0: return (array.array('B', kerberos.authGSSClientResponse(self.context)), None) else: kerberos.authGSSClientSessionKey(self.context) return (None, array.array( 'B', kerberos.authGSSClientResponse(self.context)[:16]))
def step(self, sec_buf): self.result = kerberos.authGSSClientStep( self.context, sec_buf.tostring()) if self.result == 0: return (array.array( 'B', kerberos.authGSSClientResponse(self.context)), None) else: kerberos.authGSSClientSessionKey(self.context) return (None, array.array('B', kerberos.authGSSClientResponse(self.context)[:16]))
def challenge(self, challenge): if self.step == 0: rc = kerberos.authGSSClientStep(self._gss, base64.b64encode(challenge)) if rc != kerberos.AUTH_GSS_CONTINUE: self.step = 1 elif self.step == 1: rc = kerberos.authGSSClientUnwrap(self._gss, base64.b64encode(challenge)) response = kerberos.authGSSClientResponse(self._gss) rc = kerberos.authGSSClientWrap(self._gss, response, self.username) response = kerberos.authGSSClientResponse(self._gss) if response is None: return Response("") else: return Response(base64.b64decode(response))
def mic_getline(self): resp = ftplib.FTP.getline(self) if resp[:4] != '631 ': raise AssertionError rc = kerberos.authGSSClientUnwrap(self.vc, resp[4:].strip("\r\n")) response = base64.b64decode(kerberos.authGSSClientResponse(self.vc)) return response
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 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 _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 wrap (self, plaintext): """Once a GSSAPI Context is complete, it can wrap plaintext into ciphertext. This function operates on binary strings. """ kerberos.authGSSClientWrap (self.ctx, b64encode (plaintext)) cipherdata = kerberos.authGSSClientResponse (self.ctx) return (b64decode (cipherdata) if cipherdata else "")
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 _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 get_base64_client_data(self, challenge=''): """ @return: a string containing the base64-encoded client data to be sent to the server. """ result_code = None for i in xrange(_MAX_KERBEROS_RETRIES): try: result_code = self._step(challenge) break except kerberos.GSSError as e: msg = e.args[1][0] if msg == 'Cannot determine realm for numeric host address': raise Exception(msg) elif msg == 'Server not found in Kerberos database': raise Exception(msg + ': ' + self._service) log.debug('{0}. Calling kinit.'.format(msg)) kinit_result = yield kinit(self._username, self._password, self._dcip) if kinit_result: raise Exception(kinit_result) if result_code != kerberos.AUTH_GSS_CONTINUE: raise Exception( 'kerberos authGSSClientStep failed ({0}).'.format(result_code)) base64_client_data = kerberos.authGSSClientResponse(self._context) defer.returnValue(base64_client_data)
def get_base64_client_data(self, challenge=''): """ @return: a string containing the base64-encoded client data to be sent to the server. """ result_code = None for i in xrange(_MAX_KERBEROS_RETRIES): try: result_code = self._step(challenge) break except kerberos.GSSError as e: msg = e.args[1][0] if msg == 'Cannot determine realm for numeric host address': raise Exception(msg) elif msg == 'Server not found in Kerberos database': raise Exception(msg+': '+self._service) log.debug('{0}. Calling kinit.'.format(msg)) kinit_result = yield kinit(self._username, self._password, self._dcip) if kinit_result: raise Exception(kinit_result) if result_code != kerberos.AUTH_GSS_CONTINUE: raise Exception('kerberos authGSSClientStep failed ({0}).' .format(result_code)) base64_client_data = kerberos.authGSSClientResponse(self._context) defer.returnValue(base64_client_data)
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 encrypt_body(self, body): # get original length of body. wrap will encrypt in place orig_len = len(body) # encode before sending to wrap func ebody = base64.b64encode(body) # wrap it up try: rc,pad_len = kerberos.authGSSClientWrapIov(self._context,ebody,1) if rc is not kerberos.AUTH_GSS_COMPLETE: log.debug("Unable to encrypt message body") return except AttributeError: # must be on centos 5, encryption not possible return body except kerberos.GSSError as e: msg = e.args[1][0] raise Exception(msg) # get wrapped request which is in b64 encoding ewrap = kerberos.authGSSClientResponse(self._context) # decode wrapped request payload = bytes(base64.b64decode(ewrap)) # add carriage returns to body body = _BODY.replace('\n','\r\n') body = bytes(body.format(original_length=orig_len+pad_len,emsg=payload)) return body
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 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) # We need Python 2.4 compatibility #tail, sep, head = host.rpartition(':') #domain = tail or head host_parts = host.rsplit(':', 1) domain = host_parts[0] result, self.context = k.authGSSClientInit("HTTP@%s" % domain) 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 get_kerberos_auth_handler(jenkinsurl): """ Get a handler which enabled authentication over GSSAPI :param jenkinsurl: jenkins base url, str :return: a list of handlers """ jenkinsnetloc = urlparse(jenkinsurl).netloc assert type( jenkinsnetloc ) == str, "Jenkins network location should be a string, got %s" % repr( jenkinsnetloc) _ignore, ctx = krb.authGSSClientInit('HTTP@%s' % jenkinsnetloc, gssflags=krb.GSS_C_DELEG_FLAG | krb.GSS_C_MUTUAL_FLAG | krb.GSS_C_SEQUENCE_FLAG) rc = krb.authGSSClientStep(ctx, '') if rc != krb.AUTH_GSS_CONTINUE: return [] tgt = krb.authGSSClientResponse(ctx) if not tgt: return [] krb_handler = KerberosAuthHandler(tgt) return [krb_handler]
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 challenge(self, challenge): if self.step == 0: ret = kerberos.authGSSClientStep(self._gss, base64.b64encode(challenge)) if ret != kerberos.AUTH_GSS_CONTINUE: self.step = 1 elif self.step == 1: ret = kerberos.authGSSClientUnwrap(self._gss, base64.b64encode(challenge)) response = kerberos.authGSSClientResponse(self._gss) ret = kerberos.authGSSClientWrap(self._gss, response, self.username) response = kerberos.authGSSClientResponse(self._gss) if response is None: return Response(b"") else: return Response(base64.b64decode(response))
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 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(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 _kerberos_client_request(self, host, handler, errcode, errmsg, headers): """Kerberos auth - create a client request string""" # check if "Negotiate" challenge is present in headers negotiate = [ i.lower() for i in headers.get("WWW-Authenticate", "").split(", ") ] if "negotiate" not in negotiate: # negotiate not supported, raise 401 error raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # initialize GSSAPI service = "HTTP@%s" % host rc, vc = kerberos.authGSSClientInit(service) if rc != 1: errmsg = "KERBEROS: Could not initialize GSSAPI" raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) # do a client step rc = kerberos.authGSSClientStep(vc, "") if rc != 0: errmsg = "KERBEROS: Client step failed" raise xmlrpclib.ProtocolError(host + handler, errcode, errmsg, headers) return vc, kerberos.authGSSClientResponse(vc)
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) tail, sep, head = host.rpartition(':') domain = tail if tail else head result, self.context = k.authGSSClientInit("HTTP@%s" % domain) 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 encrypt_body(self, body): # get original length of body. wrap will encrypt in place orig_len = len(body) # encode before sending to wrap func ebody = base64.b64encode(body) # wrap it up try: rc, pad_len = kerberos.authGSSClientWrapIov(self._context, ebody, 1) if rc is not kerberos.AUTH_GSS_COMPLETE: log.debug("Unable to encrypt message body") return except AttributeError: # must be on centos 5, encryption not possible return body except kerberos.GSSError as e: msg = e.args[1][0] raise Exception(msg) # get wrapped request which is in b64 encoding ewrap = kerberos.authGSSClientResponse(self._context) # decode wrapped request payload = bytes(base64.b64decode(ewrap)) # add carriage returns to body body = _BODY.replace('\n', '\r\n') body = bytes(body.format(original_length=orig_len + pad_len, emsg=payload)) return body
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 _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 generate_request_header(self, req, headers): neg_value = self.negotiate_value(headers) if neg_value is None: self.retried = 0 return None if self.retried > 5: raise urllib2.HTTPError(req.get_full_url(), 401, "negotiate auth failed", headers, None) self.retried += 1 result, self.context = kerberos.authGSSClientInit( self.service_principal) if result < 1: return None result = kerberos.authGSSClientStep(self.context, neg_value) if result < 0: return None response = kerberos.authGSSClientResponse(self.context) return "Negotiate %s" % 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 _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 __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 generate_request_header(self, response, host, is_preemptive=False): """ Generates the GSSAPI authentication token with kerberos. If any GSSAPI step fails, raise KerberosExchangeError with failure detail. """ # Flags used by kerberos module. gssflags = kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG if self.delegate: gssflags |= kerberos.GSS_C_DELEG_FLAG try: kerb_stage = "authGSSClientInit()" # contexts still need to be stored by host, but hostname_override # allows use of an arbitrary hostname for the kerberos exchange # (eg, in cases of aliased hosts, internal vs external, CNAMEs # w/ name-based HTTP hosting) kerb_host = self.hostname_override if self.hostname_override is not None else host kerb_spn = "{0}@{1}".format(self.service, kerb_host) result, self.context[host] = kerberos.authGSSClientInit(kerb_spn, gssflags=gssflags, principal=self.principal) if result < 1: raise EnvironmentError(result, kerb_stage) # if we have a previous response from the server, use it to continue # the auth process, otherwise use an empty value negotiate_resp_value = '' if is_preemptive else _negotiate_value(response) kerb_stage = "authGSSClientStep()" result = kerberos.authGSSClientStep(self.context[host], negotiate_resp_value) if result < 0: raise EnvironmentError(result, kerb_stage) kerb_stage = "authGSSClientResponse()" gss_response = kerberos.authGSSClientResponse(self.context[host]) return "Negotiate {0}".format(gss_response) except kerberos.GSSError as error: log.exception( "generate_request_header(): {0} failed:".format(kerb_stage)) log.exception(error) raise KerberosExchangeError("%s failed: %s" % (kerb_stage, str(error.args))) except EnvironmentError as error: # ensure we raised this for translation to KerberosExchangeError # by comparing errno to result, re-raise if not if error.errno != result: raise message = "{0} failed, result: {1}".format(kerb_stage, result) log.error("generate_request_header(): {0}".format(message)) raise KerberosExchangeError(message)
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 __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_get_svctk(self, spn, authdata): if authdata is None: return None result, self.context = kerberos.authGSSClientInit(spn) if result < kerberos.AUTH_GSS_COMPLETE: return None result = kerberos.authGSSClientStep(self.context, authdata) if result < kerberos.AUTH_GSS_CONTINUE: return None response = kerberos.authGSSClientResponse(self.context) return "Negotiate %s" % response
def unwrap(self, incoming): if self.qop != QOP.AUTH: incoming = base64.b64encode(incoming).decode('ascii') kerberos.authGSSClientUnwrap(self.context, incoming) conf = kerberos.authGSSClientResponseConf(self.context) if 0 == conf and self.qop == QOP.AUTH_CONF: raise Exception("Error: confidentiality requested, but not honored by the server.") return base64.b64decode(kerberos.authGSSClientResponse(self.context)) else: return incoming
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 unwrap(self, incoming): if self.qop != 'auth': incoming = base64.b64encode(incoming) kerberos.authGSSClientUnwrap(self.context, incoming) conf = kerberos.authGSSClientResponseConf(self.context) if 0 == conf and self.qop == 'auth-conf': raise StandardError("Error: confidentiality requested, but not honored by the server.") return base64.b64decode(kerberos.authGSSClientResponse(self.context)) else: return incoming
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 _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 wrap(self, outgoing): if self.qop != 'auth': outgoing = base64.b64encode(outgoing) if self.qop == 'auth-conf': protect = 1 else: protect = 0 kerberos.authGSSClientWrap(self.context, outgoing, None, protect) return base64.b64decode(kerberos.authGSSClientResponse(self.context)) else: return outgoing
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 _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 process(self, challenge=b""): b64_challenge = b64encode(challenge) try: if self.step == 0: result = kerberos.authGSSClientStep(self.gss, b64_challenge) if result != kerberos.AUTH_GSS_CONTINUE: self.step = 1 elif self.step == 1: username = self.credentials["username"] kerberos.authGSSClientUnwrap(self.gss, b64_challenge) resp = kerberos.authGSSClientResponse(self.gss) kerberos.authGSSClientWrap(self.gss, resp, username) resp = kerberos.authGSSClientResponse(self.gss) except kerberos.GSSError as e: raise SASLCancelled("Kerberos error: %s" % e.message) if not resp: return b"" else: return b64decode(resp)