def _send_authentication(self): if not self._username or not self._password: return False logger.debug('Authenticating as %s', self._username) self._send( struct.pack(self.HEADER_STRUCT, self.MAGIC['request'], self.COMMANDS['auth_negotiation']['command'], 0, 0, 0, 0, 0, 0, 0)) (magic, opcode, keylen, extlen, datatype, status, bodylen, opaque, cas, extra_content) = self._get_response() if status == self.STATUS['server_disconnected']: return False if status == self.STATUS['unknown_command']: logger.debug('Server does not requires authentication.') self.authenticated = True return True methods = extra_content if b'PLAIN' not in methods: raise AuthenticationNotSupported( 'This module only supports ' 'PLAIN auth for now.', status) method = b'PLAIN' auth = '\x00%s\x00%s' % (self._username, self._password) if isinstance(auth, text_type): auth = auth.encode() self._send( struct.pack( self.HEADER_STRUCT + self.COMMANDS['auth_request']['struct'] % (len(method), len(auth)), self.MAGIC['request'], self.COMMANDS['auth_request']['command'], len(method), 0, 0, 0, len(method) + len(auth), 0, 0, method, auth)) (magic, opcode, keylen, extlen, datatype, status, bodylen, opaque, cas, extra_content) = self._get_response() if status == self.STATUS['server_disconnected']: return False if status == self.STATUS['auth_error']: raise InvalidCredentials("Incorrect username or password", status) if status != self.STATUS['success']: raise MemcachedException( 'Code: %d Message: %s' % (status, extra_content), status) logger.debug('Auth OK. Code: %d Message: %s', status, extra_content) self.authenticated = True return True
def authenticate(self, username, password): """ Authenticate user on server. :param username: Username used to be authenticated. :type username: basestring :param password: Password used to be authenticated. :type password: basestring :return: True if successful. :raises: InvalidCredentials, AuthenticationNotSupported, MemcachedException :rtype: bool """ logger.info('Authenticating as %s' % username) self.connection.send( struct.pack(self.HEADER_STRUCT, self.MAGIC['request'], self.COMMANDS['auth_negotiation']['command'], 0, 0, 0, 0, 0, 0, 0)) (magic, opcode, keylen, extlen, datatype, status, bodylen, opaque, cas, extra_content) = self._get_response() if status == self.STATUS['unknown_command']: logger.debug('Server does not requires authentication.') return True methods = extra_content if not 'PLAIN' in methods: raise AuthenticationNotSupported('This module only supports ' 'PLAIN auth for now.') method = 'PLAIN' auth = '\x00%s\x00%s' % (username, password) self.connection.send( struct.pack( self.HEADER_STRUCT + self.COMMANDS['auth_request']['struct'] % (len(method), len(auth)), self.MAGIC['request'], self.COMMANDS['auth_request']['command'], len(method), 0, 0, 0, len(method) + len(auth), 0, 0, method, auth)) (magic, opcode, keylen, extlen, datatype, status, bodylen, opaque, cas, extra_content) = self._get_response() if status == self.STATUS['auth_error']: raise InvalidCredentials("Incorrect username or password") if status != self.STATUS['success']: raise MemcachedException('Code: %d Message: %s' % (status, extra_content)) logger.debug('Auth OK. Code: %d Message: %s' % (status, extra_content)) self.authenticated = True return True