def NotifyUp(self, packet): if packet.payload[0]: if getattr(packet.destination, 'service', None) is not None: if session.contextOnly and packet.command != const.cluster.MACHONETMSG_TYPE_SESSIONCHANGENOTIFICATION and packet.command != const.cluster.MACHONETMSG_TYPE_SESSIONINITIALSTATENOTIFICATION: packet.srcTransport.InstallSessionIfRequired( packet.destination.service, packet.payload[1]) packet.srcTransport = None method = getattr(packet.service, packet.payload[1]) callTimer = base.CallTimer( '%s::%s (ServiceNotify\\Server)' % (packet.destination.service, packet.payload[1])) try: if len(packet.payload) == 3: ClockThisWithoutTheStars( 'Remote Service Notify::%s::%s' % (packet.destination.service, packet.payload[1]), method, packet.payload[2]) else: ClockThisWithoutTheStars( 'Remote Service Notify::%s::%s' % (packet.destination.service, packet.payload[1]), method, packet.payload[2], packet.payload[3]) finally: callTimer.Done() return else: packet.payload = packet.payload[1] return self.ForwardNotifyUp(packet)
def NotifyUp(self, packet): if packet.payload[0] == 1: tup = self.FromPickle(packet.payload[1], packet.source) objectID, method, args = tup[0], tup[1], tup[2] if method == 'ClientHasReleasedTheseObjects': oidsandrefs = objectID for each in oidsandrefs: objectID, refID = each if objectID in session.machoObjectsByID: object = session.machoObjectsByID[objectID][1] objectType, guts = self.__GetObjectTypeAndGuts(object) session.UnregisterMachoObject(objectID, refID) return else: if objectID[0] == 'C' and macho.mode == 'client': cid, oid = objectID.split(':') objectID = '%s:%s' % (self.identifier, oid) if objectID not in session.machoObjectsByID: raise UnMachoDestination( 'The specified object (%s) is not a member of this session' % objectID) object = session.machoObjectsByID[objectID][1] if isinstance(object, base.ObjectConnection): objclass = object.GetObjectConnectionLogClass() else: objclass = macho.AssignLogName(object) callTimer = base.CallTimer('%s::%s (ObjectNotify\\Server)' % (objclass, method)) try: func = getattr(object, method) if method in object.__dict__.get( '__restrictedcalls__', {}) or method.startswith('_'): raise RuntimeError( 'This call can only be the result of a hack attack', method) if not isinstance(object, base.ObjectConnection) and len( tup) == 4 and 'machoVersion' in tup[3]: if len(tup[3]) == 1: tup = (tup[0], tup[1], tup[2]) else: del tup[3]['machoVersion'] if len(tup) == 3: ClockThisWithoutTheStars( 'Remote Object Notify::%s::%s' % (objclass, method), func, args) else: ClockThisWithoutTheStars( 'Remote Object Notify::%s::%s' % (objclass, method), func, args, tup[3]) finally: callTimer.Done() return else: packet.payload = self.FromPickle(packet.payload[1], packet.source) self.ForwardNotifyUp(packet)
def CallUp(self, packet): if packet.payload[0]: if getattr(packet.destination, 'service', None) is not None: if packet.payload[1] in packet.service.__dict__.get('__restrictedcalls__', {}) or packet.payload[1].startswith('_'): raise RuntimeError('This call can only be the result of a hack attack', packet.payload[1]) if packet.payload[1] == 'MachoBindObject': args = packet.payload[2][:-1] nodeID = packet.service.MachoResolveObject(args[0], 0) if nodeID and nodeID != self.machoNet.GetNodeID(): self.machoNet.LogError('MachoBindObject received on wrong node. Should have gone to ', nodeID, ', bindParams=', args[0], ', packet=', packet) raise WrongMachoNode(nodeID) call = packet.payload[2][-1] boundObject = packet.service.MachoGetObjectBoundToSession(packet.payload[2][0], session) if self.logClientCall and packet.source.addressType == const.ADDRESS_TYPE_CLIENT: kwargs = packet.payload[3] if len(packet.payload) >= 4 else None self.machoNet.LogClientCall(session, packet.destination.service, packet.payload[1], packet.payload[2], kwargs) if call is not None: if isinstance(boundObject, base.ObjectConnection): objclass = boundObject.GetObjectConnectionLogClass() else: objclass = macho.AssignLogName(object) method, args, keywords = call if method in boundObject.__dict__.get('__restrictedcalls__', {}) or method.startswith('_'): raise RuntimeError('This call can only be the result of a hack attack', method) callTimer = base.CallTimer('%s::%s (UnBoundObjectCall\\Server)' % (objclass, method)) try: func = getattr(boundObject, method) self.UpdateRecvServiceCallStats(objclass, method, packet.source) if not keywords: retval = ClockThisWithoutTheStars('Remote Unbound Object Call::%s::%s' % (objclass, method), func, args) else: retval = ClockThisWithoutTheStars('Remote Unbound Object Call::%s::%s' % (objclass, method), func, args, keywords) payload = (boundObject, retval) finally: callTimer.Done() else: payload = (boundObject, None) else: args = packet.payload[2] method = getattr(packet.service, packet.payload[1]) callTimer = base.CallTimer('%s::%s (ServiceCall\\Server)' % (packet.destination.service, packet.payload[1])) if self.logClientCall and packet.source.addressType == const.ADDRESS_TYPE_CLIENT and packet.payload[1] != 'MachoBindObject': kwargs = packet.payload[3] if len(packet.payload) >= 4 else None self.machoNet.LogClientCall(session, packet.destination.service, packet.payload[1], args, kwargs) try: self.UpdateRecvServiceCallStats(packet.destination.service, method.__method__, packet.source) if len(packet.payload) == 3: payload = ClockThisWithoutTheStars('Remote Service Call::%s::%s' % (packet.destination.service, packet.payload[1]), method, args) else: payload = ClockThisWithoutTheStars('Remote Service Call::%s::%s' % (packet.destination.service, packet.payload[1]), method, args, packet.payload[3]) finally: callTimer.Done() if session.contextOnly: packet.srcTransport.InstallSessionIfRequired(packet.destination.service, packet.payload[1]) packet.srcTransport = None return packet.Response(payload=payload) else: packet.payload = packet.payload[1] return self.ForwardCallUp(packet)
def CallUp(self, packet): if packet.command == const.cluster.MACHONETMSG_TYPE_AUTHENTICATION_REQ: retval = self.ForwardCallUp(packet) self.__StringifyPayloadForLogging(retval, retval.payload) retval.payload = self.ToPickle(retval.payload) if self.added_objects: retval.oob['OID+'] = self.added_objects retval.compressedPart = self.compressedPart return retval elif packet.payload[0]: tup = self.FromPickle(packet.payload[1], packet.source) objectID, method, args = tup[0], tup[1], tup[2] if objectID[0] == 'C' and macho.mode == 'client': cid, oid = objectID.split(':') objectID = '%s:%s' % (self.identifier, oid) if objectID not in session.machoObjectsByID: session.DumpSession('OBJECTNOTMEMBER', 'The specified object (%s) is not a member of this session' % objectID) raise UnMachoDestination('The specified object (%s) is not a member of this session' % objectID) object = session.machoObjectsByID[objectID][1] if isinstance(object, base.ObjectConnection): objclass = object.GetObjectConnectionLogClass() else: objclass = macho.AssignLogName(object) callTimer = base.CallTimer('%s::%s (ObjectCall\\Server)' % (objclass, method)) if self.logClientCall and packet.source.addressType == const.ADDRESS_TYPE_CLIENT: kwargs = tup[3] if len(tup) >= 4 else None self.machoNet.LogClientCall(session, objclass, method, args, kwargs) try: func = getattr(object, method) if method in object.__dict__.get('__restrictedcalls__', {}) or method.startswith('_'): raise RuntimeError('This call can only be the result of a hack attack', method) if not isinstance(object, base.ObjectConnection): if 0 == session.role & service.ROLE_SERVICE and hasattr(object, '__exportedcalls__') and method not in object.__exportedcalls__: raise RuntimeError('%s call is not exported from this pass-by-reference object.' % method) if not session.role & service.ROLE_SERVICE: paramList = object.__exportedcalls__.get(method, None) paramDict = None if paramList is not None: if type(paramList) is list: if len(paramList): tmp = {} tmp['role'] = paramList[0] tmp['preargs'] = paramList[1:] paramDict = tmp elif type(paramList) is dict: paramDict = paramList if paramDict is not None: role = paramDict.get('role', service.ROLE_SERVICE) if not role & session.role: session.LogSessionError("Called %s::%s, which requires role 0x%x, which the user doesn't have. User has role 0x%x" % (object.__class__.__name__, method, role, session.role)) raise RuntimeError('RoleNotAssigned', "%s::%s requires role 0x%x, which the user doesn't have. User has role 0x%x. Calling session: %s" % (object.__class__.__name__, method, role, session.role, str(session))) preargs = paramDict.get('preargs', []) args2 = len(preargs) * [None] + list(args) for i in range(len(preargs)): args2[i] = getattr(session, preargs[i]) args = tuple(args2) if len(tup) == 4 and 'machoVersion' in tup[3]: if len(tup[3]) == 1: tup = (tup[0], tup[1], tup[2]) else: del tup[3]['machoVersion'] if len(tup) == 3: retval = ClockThisWithoutTheStars('Remote Object Call::%s::%s' % (objclass, method), func, args) else: retval = ClockThisWithoutTheStars('Remote Object Call::%s::%s' % (objclass, method), func, args, tup[3]) retpickle = self.ToPickle(retval) retval = packet.Response(payload=retpickle) if self.added_objects: retval.oob['OID+'] = self.added_objects self.__StringifyPayloadForLogging(retval, retpickle) retval.compressedPart = self.compressedPart finally: callTimer.Done() return retval else: packet.payload = self.FromPickle(packet.payload[1], packet.source) retval = self.ForwardCallUp(packet) self.__StringifyPayloadForLogging(retval, retval.payload) retval.payload = self.ToPickle(retval.payload) if self.added_objects: retval.oob['OID+'] = self.added_objects retval.compressedPart = self.compressedPart return retval
def NotifySessionChangeWithoutTheStars(self, eventid, args, keywords=None): if keywords is None: keywords = {} if eventid not in ('DoSessionChanging', 'ProcessSessionChange', 'OnSessionChanged'): raise RuntimeError( 'NotifySessionChange called with eventid ', eventid, '. Must be one of DoSessionChanging, ProcessSessionChange or OnSessionChanged' ) if eventid == 'ProcessSessionChange' and stackless.getcurrent( ).block_trap or stackless.getcurrent().is_main: raise RuntimeError( "ChainEvent (NotifySessionChange) is blocking by design, but you're block trapped." ) if eventid == 'DoSessionChanging': old_block_trap = stackless.getcurrent().block_trap stackless.getcurrent().block_trap = 1 shouldLogMethodCalls = self.ShouldLogMethodCalls() if shouldLogMethodCalls: self.LogMethodCall('NotifySessionChange(', eventid, ',*args=', args, ',**kw=', keywords, ')') prefix = blue.pyos.taskletTimer.GetCurrent( ) + '::NotifySessionChange_' + eventid + '::' ret = [] myNodeID = self.services['machoNet'].GetNodeID() isSessionRelevant = boot.role != 'server' or session.contextOnly try: for srv in self.notify.get(eventid, []): try: logname = prefix + self.GetLogName(srv) if ObjectShouldReceiveMessages(srv): if shouldLogMethodCalls: self.LogMethodCall('Calling ' + logname) if eventid == 'OnSessionChanged': if not isSessionRelevant and srv.MachoResolve( session.GetActualSession()) == myNodeID: isSessionRelevant = True srvGuid = getattr(srv, '__guid__', logname) uthread.worker(prefix + srvGuid, self.MollycoddledUthread, srvGuid, eventid, getattr(srv, eventid), args, keywords) else: retval = ClockThisWithoutTheStars( logname, getattr(srv, eventid), args, keywords) ret.append(retval) elif shouldLogMethodCalls: self.LogMethodCall('Skipping ', logname, ' (service not running)') except StandardError: log.LogException('In %s.%s' % (getattr( srv, '__guid__', self.GetLogName(srv)), eventid)) sys.exc_clear() notifiedToRemove = [] for weakObj in self.notifyObs.get(eventid, []): obj = weakObj() if obj is None or not getattr(obj, eventid, None): notifiedToRemove.append(weakObj) else: try: if shouldLogMethodCalls: logname = prefix + str(obj) self.LogMethodCall('Calling ', logname) if eventid == 'OnSessionChanged': uthread.workerWithoutTheStars( '', getattr(obj, eventid), args, keywords) else: ClockThisWithoutTheStars( prefix + self.GetLogName(weakObj), getattr(obj, eventid), args, keywords) except StandardError: self.LogError('In %s.%s' % (getattr(weakObj, '__guid__', self.GetLogName(srv)), eventid)) log.LogException() sys.exc_clear() for toRemove in notifiedToRemove: if toRemove in self.notifyObs[eventid]: self.notifyObs[eventid].remove(toRemove) if not session.contextOnly: if not isSessionRelevant: if session.irrelevanceTime is None: session.irrelevanceTime = blue.os.GetWallclockTime() log.LogInfo('CTXSESS: session ', session.sid, ' = ', session, ' is no longer relevant to any service') elif session.irrelevanceTime is not None: log.LogInfo('CTXSESS: session ', session.sid, ' became relevant again') session.irrelevanceTime = None finally: if eventid == 'DoSessionChanging': bt = 0 if old_block_trap: bt = 1 stackless.getcurrent().block_trap = bt return tuple(ret)
def ChainEventWithoutTheStars(self, eventid, args, keywords=None): if keywords is None: keywords = {} if not eventid.startswith('Process'): self.LogError( 'ChainEvent called with event ', eventid, ". All events sent via ChainEvent should start with 'Process'" ) self.LogError( "Not only is the programmer responsible for this a 10z3r, but he wears his mother's underwear as well" ) log.LogTraceback() if stackless.getcurrent().block_trap or stackless.getcurrent().is_main: raise RuntimeError( "ChainEvent is blocking by design, but you're block trapped. You have'll have to find some alternative means to do Your Thing, dude." ) if not self.notify.get(eventid, []) and not self.notifyObs.get( eventid, []): self.LogInfo("Orphan'd event. ", eventid, "doesn't have any listeners") shouldLogMethodCalls = self.ShouldLogMethodCalls() if shouldLogMethodCalls: self.LogMethodCall('ChainEvent(', eventid, ',*args=', args, ',**kw=', keywords, ')') prefix = blue.pyos.taskletTimer.GetCurrent( ) + '::ChainEvent_' + eventid + '::' ret = [] for srv in self.notify.get(eventid, []): contextName = self.GetLogName(srv) try: logname = prefix + contextName if ObjectShouldReceiveMessages(srv): if shouldLogMethodCalls: self.LogMethodCall('Calling ', logname) retval = ClockThisWithoutTheStars(logname, getattr(srv, eventid), args, keywords) ret.append(retval) elif shouldLogMethodCalls: self.LogMethodCall('Skipping ', logname, ' (service not running)') except StandardError: self.LogError('In %s.%s' % (contextName, eventid)) log.LogException() sys.exc_clear() notifiedToRemove = [] for weakObj in self.notifyObs.get(eventid, []): obj = weakObj() if obj is None: notifiedToRemove.append(weakObj) else: contextName = self.GetLogName(weakObj) try: logname = prefix + contextName if shouldLogMethodCalls: self.LogMethodCall('Calling ', prefix + str(obj)) ClockThisWithoutTheStars(logname, getattr(obj, eventid), args, keywords) except StandardError: self.LogError('In %s.%s:' % (contextName, eventid)) log.LogException() sys.exc_clear() for toRemove in notifiedToRemove: if toRemove in self.notifyObs[eventid]: self.notifyObs[eventid].remove(toRemove) return tuple(ret)
def SendEventWithoutTheStars(self, eventid, args, keywords=None): if keywords is None: keywords = {} if not eventid.startswith('Do'): self.LogError( 'SendEvent called with event ', eventid, ". All events sent via SendEvent should start with 'Do'") self.LogError( "Not only is the programmer responsible for this a 10z3r, but he wears his mother's underwear as well" ) log.LogTraceback() if not self.notify.get(eventid, []) and not self.notifyObs.get( eventid, []): self.LogInfo("Orphan'd event. ", eventid, "doesn't have any listeners") shouldLogMethodCalls = self.ShouldLogMethodCalls() if shouldLogMethodCalls: if IsFullLogging(): self.LogMethodCall('SendEvent(', eventid, ',*args=', args, ',**kw=', keywords, ')') else: self.LogMethodCall('SendEvent(', eventid, ')') prefix = blue.pyos.taskletTimer.GetCurrent( ) + '::SendEvent_' + eventid + '::' old_block_trap = stackless.getcurrent().block_trap stackless.getcurrent().block_trap = 1 ret = [] try: for srv in self.notify.get(eventid, []): try: logname = prefix + self.GetLogName(srv) if ObjectShouldReceiveMessages(srv): if shouldLogMethodCalls: self.LogMethodCall('Calling ', logname) ret.append( ClockThisWithoutTheStars(logname, getattr(srv, eventid), args, keywords)) elif shouldLogMethodCalls: self.LogMethodCall('Skipping ', logname, ' (service not running)') except StandardError: self.LogError('In %s.%s' % (getattr(srv, '__guid__', logname), eventid)) log.LogException() sys.exc_clear() notifiedToRemove = [] for weakObj in self.notifyObs.get(eventid, []): obj = weakObj() if obj is None: notifiedToRemove.append(weakObj) else: try: if shouldLogMethodCalls: logname = prefix + str(obj) self.LogMethodCall('Calling ', logname) apply(getattr(obj, eventid), args, keywords) except StandardError: self.LogError( 'In %s.%s' % (getattr(weakObj, '__guid__', self.GetLogName(weakObj)), eventid)) log.LogException() sys.exc_clear() for toRemove in notifiedToRemove: if toRemove in self.notifyObs[eventid]: self.notifyObs[eventid].remove(toRemove) finally: bt = 0 if old_block_trap: bt = 1 stackless.getcurrent().block_trap = bt return tuple(ret)