예제 #1
0
    def _JitSessionToOtherSide(self, clientID):
        clientTransportID = self.machoNet.transportIDbyClientID[clientID]
        clientTransport = self.machoNet.transportsByID[clientTransportID]
        remoteSessionVersion = clientTransport.dependants.get(
            self.transportID, 0)
        sess = clientTransport.sessions[clientID]
        if remoteSessionVersion != sess.version:
            sessData = {}
            self.machoNet.LogInfo('JITing session ', sess.sid, ' (clientID ',
                                  clientID, '), localVer = ', sess.version,
                                  ' remoteVer = ', remoteSessionVersion)
            if remoteSessionVersion == 0:
                for v in sess.GetDistributedProps(0):
                    sessData[v] = getattr(sess, v)

                sessionprops = SessionInitialStateNotification(
                    source=MachoAddress(clientID=clientID),
                    destination=MachoAddress(nodeID=self.nodeID),
                    sid=sess.sid,
                    sessionType=sess.sessionType,
                    initialstate=sessData)
            else:
                for v in sess.GetDistributedProps(1):
                    sessData[v] = (None, getattr(sess, v))

                sessionprops = SessionChangeNotification(
                    source=MachoAddress(clientID=clientID),
                    destination=MachoAddress(nodeID=self.nodeID),
                    sid=sess.sid,
                    change=(1, sessData))
            clientTransport.dependants[self.transportID] = sess.version
            self.Write(sessionprops, jitSession=0)
예제 #2
0
    def __init__(self, *args, **keywords):
        self.userID = None
        self.compressedPart = 0
        self.source = MachoAddress()
        self.destination = MachoAddress()
        self.contextKey = None
        self.applicationID = None
        self.languageID = None
        self.oob = {}
        dtc = 0
        for each in keywords.iterkeys():
            if each != 'donttypecheck':
                setattr(self, each, keywords[each])
            else:
                dtc = 1

        self.command = self.__machodesc__['command']
        if not dtc:
            for each in self.__machodesc__['params']:
                if each[-1:] != '?':
                    if not hasattr(self, each):
                        raise TypeError('%s requires %s to be specified' %
                                        (self.__class__.__name__, each))

        self.pickleSize = 0
예제 #3
0
 def GetMachoAddressOfOtherSide(self):
     if macho.mode == 'client':
         return MachoAddress(nodeID=self.machoNet.myProxyNodeID)
     elif self.clientID:
         return MachoAddress(clientID=self.clientID)
     else:
         return MachoAddress(nodeID=self.nodeID)
    def __init__(self, sess, gpcs, objectID, pa, refID):
        try:
            self.__dict__['session'] = weakref.proxy(sess)
        except TypeError:
            self.__dict__['session'] = sess
            sys.exc_clear()

        self.__dict__['objectID'] = objectID
        self.__dict__['sessionCheck'] = None
        self.__dict__['persistantObjectID'] = objectID
        self.__dict__['gpcs'] = weakref.proxy(gpcs)
        self.__dict__['__publicattributes__'] = pa
        self.__dict__['objectChangeHandlers'] = weakref.WeakKeyDictionary({})
        mask = sess.Masquerade()
        try:
            self.__dict__['clisid'] = gpcs.machoNet.GetClientSessionID()
        finally:
            mask.UnMask()

        if objectID[0] == 'C':
            self.__dict__['blocking'] = 0
            cid, oid = objectID.split(':')
            cid = cid.split('=')[1]
            self.__dict__['destination'] = MachoAddress(clientID=long(cid))
        else:
            self.__dict__['blocking'] = 1
            nid, oid = objectID.split(':')
            nid = nid.split('=')[1]
            self.__dict__['destination'] = MachoAddress(nodeID=long(nid))
        self.__dict__['deleted'] = 0
        sess.RegisterMachoObjectConnection(objectID, self, refID)
    def InvalidateCachedObjects(self, objectIDs, forward=1):
        deleted = 0
        for each in objectIDs:
            if each in self.cachedMethodCalls:
                del self.cachedMethodCalls[each]
                self.__CacheIsDirty('cachedMethodCalls', each)
            if type(each) in (types.TupleType, types.ListType):
                objectID = each[0]
                version = each[1]
            else:
                objectID = each
                version = None
            if objectID in self.cachedObjects and not isinstance(
                    self.cachedObjects[objectID], uthread.Semaphore):
                if version is None or self.__OlderVersion(
                        self.cachedObjects[objectID].version, version):
                    del self.cachedObjects[objectID]
                    self.__CacheIsDirty('cachedObjects', objectID)

        gpcs = sm.services['machoNet']
        gpcs.GetGPCS()
        if macho.mode == 'client':
            return
        if macho.mode == 'proxy':
            for eachNodeID in sm.services['machoNet'].GetConnectedSolNodes():
                gpcs.RemoteServiceNotify(
                    self.session,
                    MachoAddress(nodeID=eachNodeID, service='objectCaching'),
                    'objectCaching', 'InvalidateCachedObjects', objectIDs, 0)

        elif forward and sm.services['machoNet'].GetConnectedProxyNodes():
            eachNodeID = random.choice(
                sm.services['machoNet'].GetConnectedProxyNodes())
            gpcs.RemoteServiceNotify(
                self.session,
                MachoAddress(nodeID=eachNodeID, service='objectCaching'),
                'objectCaching', 'InvalidateCachedObjects', objectIDs, 0)
예제 #6
0
 def ConnectToClientService(self, svc, idtype, theID):
     if machobase.mode == 'proxy':
         s = self.GetSessionFromParams(idtype, theID)
         return sm.services['machoNet'].ConnectToRemoteService(
             svc, MachoAddress(clientID=s.clientID, service=svc), s)
     proxyNodeID = self.GetProxyNodeFromID(idtype, theID)
     try:
         return self.GetProxySessionManager(
             proxyNodeID).ConnectToClientService(svc, idtype, theID)
     except UnMachoDestination:
         sys.exc_clear()
         if not refreshed:
             return self.GetProxySessionManager(
                 self.GetProxyNodeFromID(idtype, theID,
                                         1)).ConnectToClientService(
                                             svc, idtype, theID)
예제 #7
0
class MachoPacket():
    __guid__ = 'macho.MachoPacket'
    __intorstringtype__ = (types.IntType, types.StringType, types.UnicodeType)
    __bizzarrerouters__ = (
        const.cluster.MACHONETMSG_TYPE_SESSIONCHANGENOTIFICATION,
        const.cluster.MACHONETMSG_TYPE_SESSIONINITIALSTATENOTIFICATION,
        const.cluster.MACHONETMSG_TYPE_PING_REQ,
        const.cluster.MACHONETMSG_TYPE_PING_RSP)

    def __init__(self, *args, **keywords):
        self.userID = None
        self.compressedPart = 0
        self.source = MachoAddress()
        self.destination = MachoAddress()
        self.contextKey = None
        self.applicationID = None
        self.languageID = None
        self.oob = {}
        dtc = 0
        for each in keywords.iterkeys():
            if each != 'donttypecheck':
                setattr(self, each, keywords[each])
            else:
                dtc = 1

        self.command = self.__machodesc__['command']
        if not dtc:
            for each in self.__machodesc__['params']:
                if each[-1:] != '?':
                    if not hasattr(self, each):
                        raise TypeError('%s requires %s to be specified' %
                                        (self.__class__.__name__, each))

        self.pickleSize = 0

    def __getstate__(self):
        params = self.__machodesc__['params']
        body = [None] * len(params)
        for i in range(len(params)):
            if params[i].endswith('?'):
                tmp = params[i][:-1]
                if hasattr(self, tmp):
                    body[i] = getattr(self, tmp)
                else:
                    body.pop(-1)
                break
            else:
                body[i] = getattr(self, params[i])

        oob = None
        if self.oob or self.compressedPart:
            oob = self.oob
        if self.compressedPart:
            oob['compressedPart'] = self.compressedPart
        return (self.command, self.source, self.destination, self.userID,
                tuple(body), oob, self.contextKey, self.applicationID,
                self.languageID)

    def __setstate__(self, state):
        self.command, self.source, self.destination, self.userID, body, self.oob, self.contextKey, self.applicationID, self.languageID = state
        if self.oob is None:
            self.oob = {}
        self.compressedPart = self.oob.get('compressedPart', 0)
        params = self.__machodesc__['params']
        l = len(params)
        if len(body) < l:
            l = len(body)
        for i in range(l):
            if params[i].endswith('?'):
                tmp = params[i][:-1]
            else:
                tmp = params[i]
            setattr(self, tmp, body[i])

    def Response(self, *args, **keywords):
        if not self.__machodesc__.has_key('response'):
            raise AttributeError(
                self.__class__.__name__, 'Response',
                'There is no such thing as a response to a %s' %
                self.__class__.__name__)
        theResponse = apply(self.__machodesc__['response'], (),
                            {'donttypecheck': 1})
        theResponse.source = self.destination
        theResponse.destination = self.source
        theResponse.userID = self.userID
        theResponse.contextKey = None
        theResponse.applicationID = None
        theResponse.languageId = None
        responseParams = theResponse.__machodesc__['params']
        i = 0
        for each in responseParams:
            if each.endswith('?'):
                if len(args) > i:
                    setattr(theResponse, each[:-1], args[i])
                break
            else:
                if len(args) <= i:
                    break
                setattr(theResponse, each, args[i])
            i = i + 1

        for each in keywords.iterkeys():
            if each not in responseParams:
                raise TypeError('%s.Response does not take %s as a parameter' %
                                (self.__class__.__name__, each))
            setattr(theResponse, each, keywords[each])

        for each in responseParams:
            if not each.endswith('?') and not hasattr(theResponse, each):
                raise TypeError(
                    '%s.Response requires %s as a parameter, but it was not specified'
                    % (self.__class__.__name__, each))

        return theResponse

    def ErrorResponse(self, code, payload):
        theResponse = ErrorResponse(originalCommand=self.command,
                                    code=code,
                                    payload=payload)
        theResponse.source = self.destination
        theResponse.destination = self.source
        theResponse.userID = self.userID
        theResponse.contextKey = None
        theResponse.applicationID = None
        theResponse.languageID = None
        return theResponse

    def SetPickle(self, thePickle):
        self.__dict__['thePickle'] = thePickle
        self.__dict__['pickleSize'] = len(self.thePickle)

    def GetPickle(self):
        if not hasattr(self, 'thePickle'):
            self.__dict__['thePickle'] = machobase.Dumps(self)
            self.__dict__['pickleSize'] = len(self.thePickle)
        return self.thePickle

    def GetPickleSize(self, machoNet):
        if not self.pickleSize:
            self.GetPickle()
        return self.pickleSize

    def Changed(self):
        if hasattr(self, 'thePickle'):
            delattr(self, 'thePickle')

    def RoutesTo(self, towhat):
        if self.command in self.__bizzarrerouters__:
            return 1
        if self.command == const.cluster.MACHONETMSG_TYPE_AUTHENTICATION_REQ and machobase.mode == 'proxy':
            return 0
        return self.destination.RoutesTo(towhat, self.source)

    def __setattr__(self, attr, value):
        if hasattr(self, 'thePickle'):
            if hasattr(self, attr):
                curr = getattr(self, attr)
                if type(curr) not in self.__intorstringtype__ or type(
                        value
                ) not in self.__intorstringtype__ or curr != value:
                    self.Changed()
            else:
                self.Changed()
        self.__dict__[attr] = value

    def __repr__(self):
        try:
            if self.__guid__ == 'macho.AuthenticationReq':
                return 'Packet::AuthenticationReq(%s,%s,%s,%s,%s)' % (
                    self.source, self.destination, self.clientinfo,
                    self.userName, getattr(self, 'address', None))
            self.GetPickle()
            if len(self.thePickle) > 1500000:
                return 'Packet::%s (%s,%s,GENOCIDAL PAYLOAD(%d bytes),%s, %s)' % (
                    self.__class__.__name__, self.source, self.destination,
                    len(self.thePickle), self.oob, self.contextKey)
            if len(self.thePickle) > 1000000:
                return 'Packet::%s (%s,%s,MURDEROUS PAYLOAD(%d bytes),%s, %s)' % (
                    self.__class__.__name__, self.source, self.destination,
                    len(self.thePickle), self.oob, self.contextKey)
            if len(self.thePickle) > 100000:
                return 'Packet::%s (%s,%s,GARGANTUAN PAYLOAD(%d bytes),%s, %s)' % (
                    self.__class__.__name__, self.source, self.destination,
                    len(self.thePickle), self.oob, self.contextKey)
            if len(self.thePickle) > 10000:
                return 'Packet::%s (%s,%s,HUGE PAYLOAD(%d bytes),%s, %s)' % (
                    self.__class__.__name__, self.source, self.destination,
                    len(self.thePickle), self.oob, self.contextKey)
            if len(self.thePickle) > 1000:
                return 'Packet::%s (%s,%s,LARGE PAYLOAD(%d bytes),%s, %s)' % (
                    self.__class__.__name__, self.source, self.destination,
                    len(self.thePickle), self.oob, self.contextKey)
            try:
                l = len(self.thePickle)
                params = []
                for each in self.__machodesc__['params']:
                    if each[-1:] == '?':
                        tmp = each[:-1]
                        if hasattr(self, tmp):
                            params.append(getattr(self, tmp))
                    else:
                        params.append(getattr(self, each))

                if hasattr(self, 'strayload'):
                    return 'Packet::%s (%s,%s,%s bytes,%s,%s, %s)' % (
                        self.__class__.__name__, self.source, self.destination,
                        l, self.strayload, self.oob, self.contextKey)
                return 'Packet::%s (%s,%s,%s bytes,%s,%s, %s)' % (
                    self.__class__.__name__, self.source, self.destination, l,
                    params, self.oob, self.contextKey)
            except Exception:
                log.LogException()
                return 'Packet::%s (CRAPPY TUPLE)' % self.__class__.__name__

        except Exception:
            log.LogException()
            return 'Packet containing crappy data'

    __str__ = __repr__
예제 #8
0
    def Read(self):
        self.currentReaders += 1
        try:
            thePickle = self.transport.Read()
        finally:
            self.currentReaders -= 1

        if getattr(self, 'userID', None) and len(thePickle) > 100000:
            self.machoNet.LogWarn(
                'Read a ', len(thePickle),
                ' byte packet (before decompression) from userID=',
                getattr(self, 'userID',
                        'non-user'), ' on address ', self.transport.address)
        elif len(thePickle) > 5000000:
            self.machoNet.LogWarn(
                'Read a ', len(thePickle),
                ' byte packet (before decompression) from userID=',
                getattr(self, 'userID',
                        'non-user'), ' on address ', self.transport.address)
        if thePickle[0] not in '}~':
            before = len(thePickle)
            try:
                with bluepy.Timer(
                        'machoNet::MachoTransport::Read::DeCompress'):
                    thePickle = zlib.decompress(thePickle)
            except zlib.error as e:
                raise RuntimeError('Decompression Failure: ' + strx(e))

            after = len(thePickle)
            if after <= before:
                self.machoNet.LogError('Decompress shrank data from ', before,
                                       ' to ', after, ' bytes')
            else:
                self.machoNet.decompressedBytes.Add(after - before)
        if getattr(self, 'userID', None) and len(thePickle) > 100000:
            self.machoNet.LogWarn(
                'Read a ', len(thePickle),
                ' byte packet (after decompression, if appropriate) from userID=',
                getattr(self, 'userID',
                        'non-user'), ' on address ', self.transport.address)
        elif len(thePickle) > 5000000:
            self.machoNet.LogWarn(
                'Read a ', len(thePickle),
                ' byte packet (after decompression, if appropriate) from userID=',
                getattr(self, 'userID',
                        'non-user'), ' on address ', self.transport.address)
        if self.clientID:
            self.machoNet.dataReceived.Add(len(thePickle))
        else:
            self.machoNet.dataReceived.AddFrom(self.nodeID, len(thePickle))
        try:
            message = macho.Loads(thePickle)
        except GPSTransportClosed as e:
            self.transport.Close(**e.GetCloseArgs())
            raise
        except StandardError:
            if self.transportName == 'tcp:packet:client':
                self._LogPotentialAttackAndClose(thePickle)
            raise

        message.SetPickle(thePickle)
        if macho.mode == 'client' and message.source.addressType == const.ADDRESS_TYPE_NODE and message.destination.addressType == const.ADDRESS_TYPE_BROADCAST:
            message.oob['sn'] = self.machoNet.notifySequenceIDByNodeID[
                message.source.nodeID]
            self.machoNet.notifySequenceIDByNodeID[message.source.nodeID] += 1
        if self.transportName == 'tcp:packet:client':
            message.source = MachoAddress(clientID=self.clientID,
                                          callID=message.source.callID)
            if message.contextKey is not None or message.applicationID is not None or message.languageID is not None:
                self._LogPotentialAttackAndClose(thePickle)
                raise StandardError(
                    'Packet containing contextKey received on a client transport. Hack?'
                )
        if hasattr(self, 'userID'):
            message.userID = self.userID
        if message.command != const.cluster.MACHONETMSG_TYPE_MOVEMENTNOTIFICATION or MACHONET_LOGMOVEMENT:
            self.LogInfo('Read: ', message)
        if macho.mode == 'proxy':
            for objectID, refID in message.oob.get('OID-', {}).iteritems():
                s = self.sessions.get(self.clientID, None)
                if s is None:
                    s = self.sessions.get(self.nodeID, None)
                if s is not None:
                    s.UnregisterMachoObject(objectID, refID)

        if macho.mode == 'server':
            ls = localstorage.GetLocalStorage()
            ls['applicationID'] = message.applicationID
            ls['languageID'] = message.languageID
        return message