def run(args): [transform, params, value, fields] = parseargs(['canari %s' % cmd_name(__name__)] + args) transform_module = None fix_binpath(config['default/path']) try: transform_module = import_transform(transform) if os.name == 'posix' and hasattr(transform_module.dotransform, 'privileged') and os.geteuid(): rc = sudo(sys.argv) if rc == 1: message(MaltegoTransformResponseMessage() + UIMessage('User cancelled transform.')) elif rc == 2: message(MaltegoTransformResponseMessage() + UIMessage('Too many incorrect password attempts.')) elif rc: message(MaltegoTransformResponseMessage() + UIMessage('Unknown error occurred.')) exit(0) if hasattr(transform_module, 'onterminate'): onterminate(transform_module.onterminate) else: transform_module.__setattr__('onterminate', lambda *args: exit(-1)) input_entity = to_entity(guess_entity_type(transform_module, fields), value, fields) msg = transform_module.dotransform( MaltegoTransformRequestMessage(value, fields, params, input_entity), MaltegoTransformResponseMessage()) if get_transform_version( transform_module.dotransform ) == 2 else transform_module.dotransform( MaltegoTransformRequestMessage(value, fields, params, input_entity), MaltegoTransformResponseMessage(), config) if isinstance(msg, MaltegoTransformResponseMessage): message(msg) elif isinstance(msg, basestring): raise MaltegoException(msg) else: raise MaltegoException( 'Could not resolve message type returned by transform.') except MaltegoException, me: croak(str(me))
def dotransform(self, transform, valid_input_entity_types): try: if 'Content-Length' not in self.headers: self.send_error(500, 'What?') return request_str = self.rfile.read(int(self.headers['Content-Length'])) xml = fromstring(request_str).find( 'MaltegoTransformRequestMessage') e = xml.find('Entities/Entity') entity_type = e.get('Type', '') if valid_input_entity_types and entity_type not in valid_input_entity_types: self.send_error(400, 'Unsupported input entity!') return value = e.find('Value').text or '' fields = dict([ (f.get('Name', ''), f.text) for f in xml.findall('Entities/Entity/AdditionalFields/Field') ]) params = dict([(f.get('Name', ''), f.text) for f in xml.findall('TransformFields/Field')]) for k, i in params.items(): if '.' in k: config[k.replace('.', '/', 1)] = i else: config['default/%s' % k] = i limits = xml.find('Limits').attrib msg = transform( MaltegoTransformRequestMessage(value, fields, params, limits), request_str if hasattr(transform, 'cmd') and callable( transform.cmd) else MaltegoTransformResponseMessage() ) if get_transform_version(transform) == 2 else transform( MaltegoTransformRequestMessage(value, fields, params, limits), request_str if hasattr(transform, 'cmd') and callable(transform.cmd) else MaltegoTransformResponseMessage(), config) if isinstance(msg, MaltegoTransformResponseMessage) or isinstance( msg, basestring): message(msg, self) return else: raise MaltegoException( 'Could not resolve message type returned by transform.') except MaltegoException, me: croak(str(me), self)
def scriptable_transform_runner(transform, value, fields, params, config): global scriptable_api_initialized if not scriptable_api_initialized: scriptable_api_initialized = True def run_transform(self, transform, params=None, config=None): if isinstance(transform, basestring): transform = load_object(transform)() return scriptable_transform_runner(transform, self.value, self.fields, params or [], config or load_config()) Entity.run_transform = run_transform request = MaltegoTransformRequestMessage( parameters={ 'canari.local.arguments': Field(name='canari.local.arguments', value=params) }) request._entities = [to_entity(transform.input_type, value, fields)] msg = transform.do_transform(request, MaltegoTransformResponseMessage(), config) if isinstance(msg, MaltegoTransformResponseMessage): return Response(msg) elif isinstance(msg, basestring): raise MaltegoException(msg) else: raise MaltegoException( 'Could not resolve message type returned by transform.')
def do_transform(transform): try: # Let's get an XML object tree req = MaltegoMessage.parse(request.data).message # If our transform define an input entity type then we should check # whether the request contains the right type if transform.input_type and transform.input_type is not Unknown and \ not isinstance(req.entity, transform.input_type): return Response(application.four_o_four, status=404) # Execute it! msg = transform().do_transform(req, MaltegoTransformResponseMessage(), load_config()) # Let's serialize the return response and clean up whatever mess was left behind if isinstance(msg, MaltegoTransformResponseMessage): return message(msg) else: raise MaltegoException(str(msg)) # Unless we croaked somewhere, then we need to fix things up here... except MaltegoException as me: return croak(str(me)) except Exception: if application.debug: return croak(traceback.format_exc()) else: return croak('Transform execution failed.')
def dotransform(self, transform, valid_input_entity_types): try: if 'Content-Length' not in self.headers: self.send_error(500, 'What?') return request_str = self.rfile.read(int(self.headers['Content-Length'])) msg = MaltegoTransformRequestMessage.parse(request_str).message e = msg.entity entity_type = e.type if valid_input_entity_types and entity_type not in valid_input_entity_types: self.send_error(400, 'Unsupported input entity!') return for k, i in msg.parameters.iteritems(): if '.' in k: config[k.replace('.', '/', 1)] = i else: config['plume/%s' % k] = i msg = transform( msg, request_str if hasattr(transform, 'cmd') and callable(transform.cmd) else MaltegoTransformResponseMessage() ) if get_transform_version(transform) == 2 else transform( msg, request_str if hasattr(transform, 'cmd') and callable(transform.cmd) else MaltegoTransformResponseMessage(), config ) if isinstance(msg, MaltegoTransformResponseMessage) or isinstance(msg, basestring): message(msg, self) return else: raise MaltegoException('Could not resolve message type returned by transform.') except MaltegoException, me: croak(str(me), self)
def dotransform(transform, valid_input_entity_types): try: # Get the body of the request request_str = request.data # Let's get an XML object tree xml = fromstring(request_str).find('MaltegoTransformRequestMessage') # Get the entity being passed in. e = xml.find('Entities/Entity') entity_type = e.get('Type', '') if valid_input_entity_types and entity_type not in valid_input_entity_types: return Response(status=404) # Initialize Maltego Request values to pass into transform value = e.find('Value').text or '' fields = dict([ (f.get('Name', ''), f.text) for f in xml.findall('Entities/Entity/AdditionalFields/Field') ]) params = dict([(f.get('Name', ''), f.text) for f in xml.findall('TransformFields/Field')]) limits = xml.find('Limits').attrib # Initialize a private copy of the config to pass into the transform config = _config.CanariConfigParser() for k, i in params.items(): if '.' in k: config[k.replace('.', '/', 1)] = i else: config['default/%s' % k] = i # The private config variables CANNOT override the server's settings. This is for security? config._sections.update(_config.config._sections) # Execute it! msg = transform( MaltegoTransformRequestMessage(value, fields, params, limits), request_str if hasattr(transform, 'cmd') and callable(transform.cmd) else MaltegoTransformResponseMessage(), config) # Let's serialize the return response and clean up whatever mess was left behind if isinstance(msg, MaltegoTransformResponseMessage) or isinstance( msg, basestring): return message(msg) else: raise MaltegoException( 'Could not resolve message type returned by transform.') # Unless we croaked somewhere, then we need to fix things up here... except MaltegoException, me: return croak(str(me))
def __call__(self, value, *args, **kwargs): if os.name == 'posix' and hasattr(self.mod.dotransform, 'privileged') and os.geteuid(): print highlight( "Need to be root to run this transform... sudo'ing...", 'green', True) os.execvp('sudo', self.sudoargs) return return console_message( self.mod.dotransform( type('MaltegoTransformRequestMessage', (object, ), { 'value': value, 'params': list(args), 'fields': kwargs })(), MaltegoTransformResponseMessage()))
def dotransform(transform, valid_input_entity_types): try: # Get the body of the request request_str = request.data # Let's get an XML object tree maltego_request = MaltegoMessage.parse(request_str).message # Get the entity being passed in. e = maltego_request.entity entity_type = e.type if valid_input_entity_types and entity_type not in valid_input_entity_types: return Response(app.four_o_four, status=404) # Initialize a private copy of the config to pass into the transform config = _config.CanariConfigParser() for p in maltego_request.parameters.values(): if '.' in p.name: config[p.name.replace('.', '/', 1)] = p.value else: config['plume/%s' % p.name] = p.value # The private config variables CANNOT override the server's settings. This is for security? config._sections.update(_config.config._sections) # Execute it! msg = transform( maltego_request, request_str if hasattr(transform, 'cmd') and callable(transform.cmd) else MaltegoTransformResponseMessage(), config) # Let's serialize the return response and clean up whatever mess was left behind if isinstance(msg, MaltegoTransformResponseMessage) or isinstance( msg, basestring): return message(msg) else: raise MaltegoException( 'Could not resolve message type returned by transform.') # Unless we croaked somewhere, then we need to fix things up here... except MaltegoException, me: return croak(str(me))
def local_transform_runner(transform, value, fields, params, config, message_writer=message): """ Internal API: The local transform runner is responsible for executing the local transform. Parameters: transform - The name or module of the transform to execute (i.e sploitego.transforms.whatismyip). value - The input entity value. fields - A dict of the field names and their respective values. params - The extra parameters passed into the transform via the command line. config - The Canari configuration object. message_writer - The message writing function used to write the MaltegoTransformResponseMessage to stdout. This is can either be the console_message or message functions. Alternatively, the message_writer function can be any callable object that accepts the MaltegoTransformResponseMessage as the first parameter and writes the output to a destination of your choosing. This helper function is only used by the run-transform, debug-transform, and dispatcher commands. """ try: transform = load_object(transform)() if os.name == 'posix' and transform.superuser and os.geteuid(): rc = sudo(sys.argv) if rc == 1: message_writer(MaltegoTransformResponseMessage() + UIMessage('User cancelled transform.')) elif rc == 2: message_writer( MaltegoTransformResponseMessage() + UIMessage('Too many incorrect password attempts.')) elif rc: message_writer(MaltegoTransformResponseMessage() + UIMessage('Unknown error occurred.')) exit(rc) on_terminate(transform.on_terminate) request = MaltegoTransformRequestMessage( parameters={ 'canari.local.arguments': Field(name='canari.local.arguments', value=params) }) request._entities = [to_entity(transform.input_type, value, fields)] msg = transform.do_transform(request, MaltegoTransformResponseMessage(), config) if isinstance(msg, MaltegoTransformResponseMessage): message_writer(msg) elif isinstance(msg, basestring): raise MaltegoException(msg) else: raise MaltegoException( 'Could not resolve message type returned by transform.') except MaltegoException, me: croak(me, message_writer)