Пример #1
0
        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)
Пример #2
0
    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)
Пример #3
0
 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
Пример #4
0
 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
Пример #5
0
 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
Пример #6
0
    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)
Пример #7
0
    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})
Пример #8
0
 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
Пример #9
0
 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
Пример #10
0
 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
Пример #11
0
    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)
Пример #12
0
    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)
Пример #13
0
        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)
Пример #14
0
 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))
Пример #15
0
        def process(self, challenge=b''):
            b64_challenge = b64encode(challenge).decode('ascii')
            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.decode())

                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)
Пример #16
0
 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))
Пример #17
0
		def step (rcv):
			#DEBUG# print 'New Call with Complete:', self.complete
			#DEBUG# print 'Received:', '"' + b64encode (rcv) + '"'
			if not self.complete:
				# Initiate the GSSAPI Client
				#ALT# rc, self.ctx = kerberos.authGSSClientInit ('imap@' + hostname, gssflags=kerberos.GSS_C_SEQUENCE_FLAG)
				#STD# rc, self.ctx = kerberos.authGSSClientInit ('imap@' + hostname)
				if not self.ctx:
					rc, self.ctx = kerberos.authGSSClientInit ('imap@' + hostname)
				rc = kerberos.authGSSClientStep (self.ctx, b64encode (rcv))
				#DEBUG# print 'ClientStep Result Code:', ['CONTINUE', 'COMPLETE'] [rc]
				if rc == kerberos.AUTH_GSS_COMPLETE:
					self.complete = True
				# if rc != 0:
				# 	print 'Error making a step'
				# 	return None
				snd = kerberos.authGSSClientResponse (self.ctx)
				return (b64decode (snd) if snd else "")
			else:
				# Unwrap and interpret the information token
				rc = kerberos.authGSSClientUnwrap (self.ctx, b64encode (rcv))
				# if rc != 0:
				# 	print 'Error unwrapping'
				# 	return None
				token = b64decode (kerberos.authGSSClientResponse (self.ctx))
				if len (token) != 4:
					#DEBUG# print 'Error unwrapping token after GSSAPI handshake'
					return None
				flags = ord (token [0])
				#DEBUG# print 'Flags:', '0x%02x' % flags
				if flags & kerberos.GSS_C_INTEG_FLAG:
					pass #DEBUG# print 'Integrity Supported'
				if flags & kerberos.GSS_C_CONF_FLAG:
					pass #DEBUG# print 'Confidentialtiy Supported'
				maxlen = (ord (token [1]) << 16) | (ord (token [2]) << 8) | (ord (token [3]))
				#DEBUG# print 'Maxlen:', maxlen
				rettok = (chr (0) * 4) + 'ofo'
				return self.wrap (rettok)
Пример #18
0
 def gssauth(self, response):
     if not HAVE_KERBEROS_GSS:
         # shouldn't get here
         raise ValueError('kerberos GSS support not available')
     data = ''.join(str(response).encode('base64').splitlines())
     if self.gss_step == GSS_STATE_STEP:
         if not self.gss_vc:
             (rc, self.gss_vc) = kerberos.authGSSClientInit(
                 'imap@%s' % self.conf['server']
             )
             response = kerberos.authGSSClientResponse(self.gss_vc)
         rc = kerberos.authGSSClientStep(self.gss_vc, data)
         if rc != kerberos.AUTH_GSS_CONTINUE:
             self.gss_step = GSS_STATE_WRAP
     elif self.gss_step == GSS_STATE_WRAP:
         rc = kerberos.authGSSClientUnwrap(self.gss_vc, data)
         response = kerberos.authGSSClientResponse(self.gss_vc)
         rc = kerberos.authGSSClientWrap(self.gss_vc, response,
                                         self.conf['username'])
     response = kerberos.authGSSClientResponse(self.gss_vc)
     if not response:
         response = ''
     return response.decode('base64')
Пример #19
0
	def SASLHandler(self, conn, challenge):
		''' Perform next SASL auth step. Used internally. '''
		if challenge.getNamespace() != NS_SASL: 
			return
		if challenge.getName() == 'failure':
			self.startsasl = 'failure'
			try: 
				reason = challenge.getChildren()[0]
			except Exception: 
				reason = challenge
			self.DEBUG('Failed SASL authentification: %s' % reason, 'error')
			if self.on_sasl :
				self.on_sasl ()
			raise NodeProcessed
		elif challenge.getName() == 'success':
			self.startsasl='success'
			self.DEBUG('Successfully authenticated with remote server.', 'ok')
			handlers=self._owner.Dispatcher.dumpHandlers()
			self._owner.Dispatcher.PlugOut()
			dispatcher_nb.Dispatcher().PlugIn(self._owner)
			self._owner.Dispatcher.restoreHandlers(handlers)
			self._owner.User = self.username
			if self.on_sasl :
				self.on_sasl ()
			raise NodeProcessed
########################################3333
		incoming_data = challenge.getData()
		data=base64.decodestring(incoming_data)
		self.DEBUG('Got challenge:'+data,'ok')
		if self.mechanism == "GSSAPI":
			if self.gss_step == GSS_STATE_STEP:
				rc = kerberos.authGSSClientStep(self.gss_vc, incoming_data)
				if rc != kerberos.AUTH_GSS_CONTINUE:
					self.gss_step = GSS_STATE_WRAP
			elif self.gss_step == GSS_STATE_WRAP:
				rc = kerberos.authGSSClientUnwrap(self.gss_vc, incoming_data)
				response = kerberos.authGSSClientResponse(self.gss_vc)
				rc = kerberos.authGSSClientWrap(self.gss_vc, response,
												self.username)
			response = kerberos.authGSSClientResponse(self.gss_vc)
			if not response:
				response = ''
			self._owner.send(Node('response', attrs={'xmlns':NS_SASL},
						payload=response).__str__())
			raise NodeProcessed
		chal = challenge_splitter(data)
		if not self.realm and 'realm' in chal:
			self.realm = chal['realm']
		if 'qop' in chal and ((isinstance(chal['qop'], str) and \
		chal['qop'] =='auth') or (isinstance(chal['qop'], list) and 'auth' in \
		chal['qop'])):
			resp={}
			resp['username'] = self.username
			if self.realm:
				resp['realm'] = self.realm
			else:
				resp['realm'] = self._owner.Server
			resp['nonce']=chal['nonce']
			cnonce=''
			for i in range(7):
				cnonce += hex(int(random.random() * 65536 * 4096))[2:]
			resp['cnonce'] = cnonce
			resp['nc'] = ('00000001')
			resp['qop'] = 'auth'
			resp['digest-uri'] = 'xmpp/'+self._owner.Server
			A1=C([H(C([resp['username'], resp['realm'], self.password])), 
						resp['nonce'], resp['cnonce']])
			A2=C(['AUTHENTICATE',resp['digest-uri']])
			response= HH(C([HH(A1), resp['nonce'], resp['nc'], resp['cnonce'],
						resp['qop'], HH(A2)]))
			resp['response'] = response
			resp['charset'] = 'utf-8'
			sasl_data=''
			for key in ('charset', 'username', 'realm', 'nonce', 'nc', 'cnonce', 'digest-uri', 'response', 'qop'):
				if key in ['nc','qop','response','charset']: 
					sasl_data += "%s=%s," % (key,resp[key])
				else: 
					sasl_data += '%s="%s",' % (key,resp[key])
########################################3333
			node=Node('response', attrs={'xmlns':NS_SASL}, 
				payload=[base64.encodestring(sasl_data[:-1]).replace('\r','').replace('\n','')])
			self._owner.send(node.__str__())
		elif 'rspauth' in chal: 
			self._owner.send(Node('response', attrs={'xmlns':NS_SASL}).__str__())
		else: 
			self.startsasl='failure'
			self.DEBUG('Failed SASL authentification: unknown challenge', 'error')
		if self.on_sasl :
				self.on_sasl ()
		raise NodeProcessed
Пример #20
0
    def callback(self,response):
        '''Callback for use with imaplib.authenticate(mech,callback)
        Will be repeatedly called with data from server,
        and its return data passed back to server.
        '''


        response = "".join(str(response).encode('base64').splitlines())
##        print "Entering callback with response={}".format(response)

        ctx = self.context
        if ctx is None:
            raise Exception("GSS context is None.")

        # GSSAPI SASL: two states
        # First negotiate GSS security context
        # Then negotiate security protection layer

        if (self.state == STATE_ONE): 
            # Negotiating security context
            rc = kerberos.authGSSClientStep(ctx, response)
            if (rc != AUTH_GSS_CONTINUE and rc != AUTH_GSS_COMPLETE):
                raise Exception("Bad GSSAPI return code: {}".format(rc))
            elif (rc == AUTH_GSS_COMPLETE):
                # -> State transition
                self.state = STATE_TWO 
            payload = kerberos.authGSSClientResponse(ctx)

        elif (self.state == STATE_TWO):
            # Negotiating protection layer
            rc = kerberos.authGSSClientUnwrap(ctx, response)
            if (rc != AUTH_GSS_CONTINUE and rc != AUTH_GSS_COMPLETE):
                raise Exception("Bad GSSAPI return code: {}".format(rc))
            data = kerberos.authGSSClientResponse(ctx)

            # At this point, the protocol says we should unwrap a
            # security mask from the leading bytes of the decoded
            # data.  However we can't, because the C code in
            # kerberosgss.c forces GSS_AUTH_P_NONE and also does
            # not allow setting conf_flag in the wrap.

            ### Stuff we should do, but can't ###
            # bytestring = base64.b64decode(data)
            # bytes = struct.unpack('4B', bytestring)
            # bufsiz = ((bytes[1] << 8) + bytes[2] << 8) + bytes[3]
            # security_mask = bytes[0]
            # for layer in 4,2,1:
            #     then choose a desired_security layer from security_mask
            # bytestring = struct.pack('4B', desired_security, *bytes[1:])
            # then wrap with conf_flag suitable for the desired_security
            ### End stuff ###

            # So instead of unwrapping a security mask, we just
            # assert that we use GSS_AUTH_P_NONE ('\x01')

            bytestring = base64.b64decode(data)
            newdata = '\x01' + bytestring[1:]
            newdata = str(newdata).encode('base64')
            rc = kerberos.authGSSClientWrap(ctx, newdata, self.username)
            if (rc != AUTH_GSS_CONTINUE and rc != AUTH_GSS_COMPLETE):
                raise Exception("Bad GSSAPI return code: {}".format(rc))
            payload = kerberos.authGSSClientResponse(ctx)

        else:
            raise Exception("Unexpected state: {}".format(self.state))

        if payload is None:
            payload = ''
##        print "Leaving callback with payload={}".format(payload)
        payload = str(payload).decode('base64')
        return payload
Пример #21
0
def _authenticate_gssapi(credentials, sock_info, cmd_func):
    """Authenticate using GSSAPI.
    """
    try:
        dummy, username, gsn = credentials
        # Starting here and continuing through the while loop below - establish
        # the security context. See RFC 4752, Section 3.1, first paragraph.
        result, ctx = kerberos.authGSSClientInit(
            gsn + '@' + sock_info.host, gssflags=kerberos.GSS_C_MUTUAL_FLAG)

        if result != kerberos.AUTH_GSS_COMPLETE:
            raise OperationFailure('Kerberos context failed to initialize.')

        try:
            # pykerberos uses a weird mix of exceptions and return values
            # to indicate errors.
            # 0 == continue, 1 == complete, -1 == error
            # Only authGSSClientStep can return 0.
            if kerberos.authGSSClientStep(ctx, '') != 0:
                raise OperationFailure('Unknown kerberos '
                                       'failure in step function.')

            # Start a SASL conversation with mongod/s
            # Note: pykerberos deals with base64 encoded byte strings.
            # Since mongo accepts base64 strings as the payload we don't
            # have to use bson.binary.Binary.
            payload = kerberos.authGSSClientResponse(ctx)
            cmd = SON([('saslStart', 1),
                       ('mechanism', 'GSSAPI'),
                       ('payload', payload),
                       ('autoAuthorize', 1)])
            response, _ = cmd_func(sock_info, '$external', cmd)

            # Limit how many times we loop to catch protocol / library issues
            for _ in xrange(10):
                result = kerberos.authGSSClientStep(ctx,
                                                    str(response['payload']))
                if result == -1:
                    raise OperationFailure('Unknown kerberos '
                                           'failure in step function.')

                payload = kerberos.authGSSClientResponse(ctx) or ''

                cmd = SON([('saslContinue', 1),
                           ('conversationId', response['conversationId']),
                           ('payload', payload)])
                response, _ = cmd_func(sock_info, '$external', cmd)

                if result == kerberos.AUTH_GSS_COMPLETE:
                    break
            else:
                raise OperationFailure('Kerberos '
                                       'authentication failed to complete.')

            # Once the security context is established actually authenticate.
            # See RFC 4752, Section 3.1, last two paragraphs.
            if kerberos.authGSSClientUnwrap(ctx,
                                            str(response['payload'])) != 1:
                raise OperationFailure('Unknown kerberos '
                                       'failure during GSS_Unwrap step.')

            if kerberos.authGSSClientWrap(ctx,
                                          kerberos.authGSSClientResponse(ctx),
                                          username) != 1:
                raise OperationFailure('Unknown kerberos '
                                       'failure during GSS_Wrap step.')

            payload = kerberos.authGSSClientResponse(ctx)
            cmd = SON([('saslContinue', 1),
                       ('conversationId', response['conversationId']),
                       ('payload', payload)])
            response, _ = cmd_func(sock_info, '$external', cmd)

        finally:
            kerberos.authGSSClientClean(ctx)

    except kerberos.KrbError, exc:
        raise OperationFailure(str(exc))
Пример #22
0
	def unwrap (self, ciphertext):
		"""Once a GSSAPI Context is complete, it can unwrap ciphertext
		   into plaintext.  This function operates on binary strings.
		"""
		kerberos.authGSSClientUnwrap (self.ctx, b64encode (ciphertext))
		return b64decode (kerberos.authGSSClientResponse (self.ctx))
Пример #23
0
def _authenticate_gssapi(credentials, sock_info, cmd_func):
    """Authenticate using GSSAPI.
    """
    try:
        dummy, username, gsn = credentials
        # Starting here and continuing through the while loop below - establish
        # the security context. See RFC 4752, Section 3.1, first paragraph.
        result, ctx = kerberos.authGSSClientInit(
            gsn + '@' + sock_info.host, gssflags=kerberos.GSS_C_MUTUAL_FLAG)

        if result != kerberos.AUTH_GSS_COMPLETE:
            raise OperationFailure('Kerberos context failed to initialize.')

        try:
            # pykerberos uses a weird mix of exceptions and return values
            # to indicate errors.
            # 0 == continue, 1 == complete, -1 == error
            # Only authGSSClientStep can return 0.
            if kerberos.authGSSClientStep(ctx, '') != 0:
                raise OperationFailure('Unknown kerberos '
                                       'failure in step function.')

            # Start a SASL conversation with mongod/s
            # Note: pykerberos deals with base64 encoded byte strings.
            # Since mongo accepts base64 strings as the payload we don't
            # have to use bson.binary.Binary.
            payload = kerberos.authGSSClientResponse(ctx)
            cmd = SON([('saslStart', 1), ('mechanism', 'GSSAPI'),
                       ('payload', payload), ('autoAuthorize', 1)])
            response, _ = cmd_func(sock_info, '$external', cmd)

            # Limit how many times we loop to catch protocol / library issues
            for _ in xrange(10):
                result = kerberos.authGSSClientStep(ctx,
                                                    str(response['payload']))
                if result == -1:
                    raise OperationFailure('Unknown kerberos '
                                           'failure in step function.')

                payload = kerberos.authGSSClientResponse(ctx) or ''

                cmd = SON([('saslContinue', 1),
                           ('conversationId', response['conversationId']),
                           ('payload', payload)])
                response, _ = cmd_func(sock_info, '$external', cmd)

                if result == kerberos.AUTH_GSS_COMPLETE:
                    break
            else:
                raise OperationFailure('Kerberos '
                                       'authentication failed to complete.')

            # Once the security context is established actually authenticate.
            # See RFC 4752, Section 3.1, last two paragraphs.
            if kerberos.authGSSClientUnwrap(ctx, str(
                    response['payload'])) != 1:
                raise OperationFailure('Unknown kerberos '
                                       'failure during GSS_Unwrap step.')

            if kerberos.authGSSClientWrap(
                    ctx, kerberos.authGSSClientResponse(ctx), username) != 1:
                raise OperationFailure('Unknown kerberos '
                                       'failure during GSS_Wrap step.')

            payload = kerberos.authGSSClientResponse(ctx)
            cmd = SON([('saslContinue', 1),
                       ('conversationId', response['conversationId']),
                       ('payload', payload)])
            response, _ = cmd_func(sock_info, '$external', cmd)

        finally:
            kerberos.authGSSClientClean(ctx)

    except kerberos.KrbError, exc:
        raise OperationFailure(str(exc))
Пример #24
0
def sasl_gssapi(connection, controls):
    """
    Performs a bind using the Kerberos v5 ("GSSAPI") SASL mechanism
    from RFC 4752. Does not support any security layers, only authentication!

    sasl_credentials can be empty or a 1-element tuple with the requested
    target_name or the True value to request the target_name from DNS
    """
    if connection.sasl_credentials and len(connection.sasl_credentials) == 1 \
            and connection.sasl_credentials[0]:
        if connection.sasl_credentials[0] is True:
            hostname = \
                socket.gethostbyaddr(connection.socket.getpeername()[0])[0]
            target_name = 'ldap@' + hostname
        else:
            target_name = connection.sasl_credentials[0]
    else:
        target_name = 'ldap@' + connection.server.host

    gssflags = (kerberos.GSS_C_MUTUAL_FLAG | kerberos.GSS_C_SEQUENCE_FLAG
                | kerberos.GSS_C_INTEG_FLAG | kerberos.GSS_C_CONF_FLAG)

    _, ctx = kerberos.authGSSClientInit(target_name, gssflags=gssflags)

    try:
        in_token = b''
        while True:
            status = kerberos.authGSSClientStep(
                ctx,
                base64.b64encode(in_token).decode('ascii'))
            out_token = kerberos.authGSSClientResponse(ctx) or ''
            result = send_sasl_negotiation(connection, controls,
                                           base64.b64decode(out_token))
            in_token = result['saslCreds'] or b''
            if status == kerberos.AUTH_GSS_COMPLETE:
                break

        kerberos.authGSSClientUnwrap(
            ctx,
            base64.b64encode(in_token).decode('ascii'))

        unwrapped_token = base64.b64decode(
            kerberos.authGSSClientResponse(ctx) or '')

        if len(unwrapped_token) != 4:
            raise LDAPCommunicationError("Incorrect response from server")

        server_security_layers = unwrapped_token[0]
        if not isinstance(server_security_layers, int):
            server_security_layers = ord(server_security_layers)
        if not server_security_layers & NO_SECURITY_LAYER:
            raise LDAPCommunicationError(
                "Server requires a security layer, but this is not implemented"
            )

        client_security_layers = bytearray([NO_SECURITY_LAYER, 0, 0, 0])
        kerberos.authGSSClientWrap(
            ctx,
            base64.b64encode(client_security_layers).decode('ascii'))
        out_token = kerberos.authGSSClientResponse(ctx) or ''
        return send_sasl_negotiation(connection, controls,
                                     base64.b64decode(out_token))
    except (kerberos.GSSError, LDAPCommunicationError):
        abort_sasl_negotiation(connection, controls)
        raise
Пример #25
0
    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)
        if self.user is None:
            ret = kerberos.authGSSClientStep(self.context, challenge)
            if ret == kerberos.AUTH_GSS_COMPLETE:
                self.user = kerberos.authGSSClientUserName(self.context)
                return ''
            else:
                response = kerberos.authGSSClientResponse(self.context)
                if response:
                    response = base64.b64decode(response)
                else:
                    response = ''
            return response

        ret = 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

        layers_supported, = struct.unpack('B', plaintext_data[0])
        server_offered_qops = []
        if 0x01 & layers_supported:
            server_offered_qops.append('auth')
        if 0x02 & layers_supported:
            server_offered_qops.append('auth-int')
        if 0x04 & layers_supported:
            server_offered_qops.append('auth-conf')

        self._pick_qop(server_offered_qops)

        max_length, = struct.unpack('!i', '\x00' + plaintext_data[1:])
        self.max_buffer = min(self.sasl.max_buffer, max_length)

        """
        Construct the reply.

        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.

        So, we write the max length and authorization user name first, then
        overwrite the first byte of the buffer with the qop.  This is ok since
        the max length is writen out in big endian.
        """
        i = len(self.user)
        fmt = '!I' + str(i) + 's'
        outdata = create_string_buffer(4 + i)
        struct.pack_into(fmt, outdata, 0, self.max_buffer, self.user)

        qop = 1
        if self.qop == 'auth-int':
            qop = 2
        elif self.qop == 'auth-conf':
            qop = 4
        struct.pack_into('!B', outdata, 0, qop)

        encodeddata = base64.b64encode(outdata)

        ret = kerberos.authGSSClientWrap(self.context, data)
        response = kerberos.authGSSClientResponse(self.context)
        self.complete = True
        return base64.b64decode(response)
Пример #26
0
    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)
        if self.user is None:
            ret = kerberos.authGSSClientStep(self.context, challenge)
            if ret == kerberos.AUTH_GSS_COMPLETE:
                self.user = kerberos.authGSSClientUserName(self.context)
                return ''
            else:
                response = kerberos.authGSSClientResponse(self.context)
                if response:
                    response = base64.b64decode(response)
                else:
                    response = ''
            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

        layers_supported, = struct.unpack('B', plaintext_data[0])
        server_offered_qops = []
        if 0x01 & layers_supported:
            server_offered_qops.append('auth')
        if 0x02 & layers_supported:
            server_offered_qops.append('auth-int')
        if 0x04 & layers_supported:
            server_offered_qops.append('auth-conf')

        self._pick_qop(server_offered_qops)

        max_length, = struct.unpack('!i', '\x00' + plaintext_data[1:])
        self.max_buffer = min(self.sasl.max_buffer, max_length)
        """
        Construct the reply.

        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.

        So, we write the max length and authorization user name first, then
        overwrite the first byte of the buffer with the qop.  This is ok since
        the max length is writen out in big endian.
        """
        i = len(self.user)
        fmt = '!I' + str(i) + 's'
        outdata = create_string_buffer(4 + i)
        struct.pack_into(fmt, outdata, 0, self.max_buffer, self.user)

        qop = 1
        if self.qop == 'auth-int':
            qop = 2
        elif self.qop == 'auth-conf':
            qop = 4
        struct.pack_into('!B', outdata, 0, qop)

        encodeddata = base64.b64encode(outdata)

        kerberos.authGSSClientWrap(self.context, encodeddata)
        response = kerberos.authGSSClientResponse(self.context)
        self.complete = True
        return base64.b64decode(response)