示例#1
0
def SignComponent(component_filename, overwrite=False, token=None):
  """Sign and upload the component to the data store."""
  print "Signing and uploading component %s" % component_filename
  component = rdf_client.ClientComponent(open(component_filename).read())
  print "Opened component %s." % component.summary.name

  client_context = ["Platform:%s" % component.build_system.system.title(),
                    "Arch:%s" % component.build_system.arch]

  sig_key = config_lib.CONFIG.Get(
      "PrivateKeys.executable_signing_private_key",
      context=client_context)

  ver_key = config_lib.CONFIG.Get("Client.executable_signing_public_key",
                                  context=client_context)

  # For each platform specific component, we have a component summary object
  # which contains high level information in common to all components of this
  # specific version.
  component_urn = config_lib.CONFIG.Get(
      "Config.aff4_root").Add("components").Add(
          "%s_%s" % (component.summary.name, component.summary.version))

  component_fd = aff4.FACTORY.Create(component_urn, "ComponentObject",
                                     mode="rw", token=token)

  component_summary = component_fd.Get(component_fd.Schema.COMPONENT)
  if overwrite or component_summary is None:
    print "Storing component summary at %s" % component_urn

    component_summary = component.summary
    component_summary.seed = "%x%x" % (time.time(), utils.PRNG.GetULong())
    component_summary.url = (
        config_lib.CONFIG.Get(
            "Client.component_url_stem",
            context=client_context) + component_summary.seed)

    component_fd.Set(component_fd.Schema.COMPONENT, component_summary)
    component_fd.Close()

  else:
    print "Using seed from stored component summary at %s" % component_urn
    component.summary.url = component_summary.url
    component.summary.seed = component_summary.seed

  # Sign the component, encrypt it and store it at the static aff4 location.
  signed_component = rdf_crypto.SignedBlob()
  signed_component.Sign(component.SerializeToString(), sig_key, ver_key,
                        prompt=True)

  aff4_urn = config_lib.CONFIG.Get(
      "Client.component_aff4_stem", context=client_context).Add(
          component.summary.seed).Add(component.build_system.signature())

  print "Storing signed component at %s" % aff4_urn
  with aff4.FACTORY.Create(aff4_urn, "AFF4MemoryStream", token=token) as fd:
    fd.Write(component_summary.cipher.Encrypt(
        signed_component.SerializeToString()))

  return component
示例#2
0
def SignComponentContent(component_filename, output_filename):
    """Some OSs require the contents of a component to be signed as well.

  Specifically this action unzips the component and authenticode signs all
  binaries. The component is then repacked.

  Args:
    component_filename: The filename of the component.
    output_filename: We write the new signed component here.

  Raises:
    RuntimeError: If called for any other OS than windows.
  """
    component = rdf_client.ClientComponent(open(component_filename).read())
    print "Opened component %s." % component.summary.name

    if component.build_system.system == "Windows":
        _SignWindowsComponent(component, output_filename)
        return

    raise RuntimeError("Component signing is not implemented for OS %s." %
                       component.build_system.system)
示例#3
0
    def Run(self, request):
        """Load the component requested.

    The component defines a set of python imports which should be imported into
    the running program. The purpose of this client action is to ensure that the
    imports are available and of the correct version. We ensure this by:

    1) Attempt to import the relevant modules.

    2) If that fails checks for the presence of a component installed at the
       require path. Attempt to import the modules again.

    3) If no component is installed, we fetch and install the component from the
       server. We then attempt to use it.

    If all imports succeed we return a success status, otherwise we raise an
    exception.

    Args:
      request: The LoadComponent request.

    Raises:
      RuntimeError: If the component is invalid.
    """
        summary = request.summary
        # Just try to load the required modules.
        try:
            self.LoadComponent(summary)
            # If we succeed we just report this component is done.
            self.SendReply(request)
            return
        except ImportError:
            pass

        # Try to add an existing component path.
        component_path = utils.JoinPath(
            config_lib.CONFIG.Get("Client.component_path"), summary.name,
            summary.version)

        # Add the component path to the site packages:
        site = Site()
        site.AddSiteDir(component_path)
        LOADED_COMPONENTS[summary.name] = summary.version

        try:
            self.LoadComponent(summary)
            logging.info("Component %s already present.", summary.name)
            self.SendReply(request)
            return

        except ImportError:
            pass

        # Could not import component - will have to fetch it.
        logging.info("Unable to import component %s.", summary.name)

        # Derive the name of the component that we need depending on the current
        # architecture. The client build system should have burned its environment
        # into the client config file. This is the best choice because it will
        # choose the same component that was built together with the client
        # itself (on the same build environment).
        build_environment = config_lib.CONFIG.Get("Client.build_environment")
        if not build_environment:
            # Failing this we try to get something similar to the running system.
            build_environment = rdf_client.Uname.FromCurrentSystem().signature(
            )

        url = "%s/%s" % (summary.url, build_environment)
        logging.info("Fetching component from %s", url)
        crypted_data = self.grr_worker.http_manager.OpenServerEndpoint(
            url).data

        # Decrypt and check signature. The cipher is created when the component is
        # uploaded and contains the key to decrypt it.
        signed_blob = rdf_crypto.SignedBlob(
            summary.cipher.Decrypt(crypted_data))

        # Ensure the blob is signed with the correct key.
        signed_blob.Verify(
            config_lib.CONFIG["Client.executable_signing_public_key"])

        component = rdf_client.ClientComponent(signed_blob.data)

        # Make sure its the component we actually want.
        if (component.summary.name != summary.name
                or component.summary.version != summary.version):
            raise RuntimeError(
                "Downloaded component is not the correct version")

        # Make intermediate directories.
        try:
            os.makedirs(component_path)
        except (OSError, IOError):
            pass

        # Unzip the component into the path.
        logging.info("Installing component to %s", component_path)
        component_zip = zipfile.ZipFile(StringIO.StringIO(component.raw_data))
        component_zip.extractall(component_path)

        # Add the component to the site packages:
        site.AddSiteDir(component_path)
        LOADED_COMPONENTS[component.summary.name] = component.summary.version

        # If this does not work now, we just fail.
        self.LoadComponent(summary)

        # If we succeed we just report this component is done.
        self.SendReply(request)
示例#4
0
文件: component.py 项目: peanode/grr
def BuildComponent(setup_path, output_dir=None):
    """Builds a single component."""

    if not output_dir:
        output_dir = config_lib.CONFIG["ClientBuilder.components_dir"]

    # Get component configuration from setup.py.
    module = imp.load_source("setup", setup_path)
    setup_args = module.setup_args

    with utils.TempDirectory() as tmp_dirname:
        print "Building component %s, Version %s" % (setup_args["name"],
                                                     setup_args["version"])
        print "Creating Virtual Env %s" % tmp_dirname
        subprocess.check_call(["virtualenv", tmp_dirname],
                              env=GetCleanEnvironment())

        interpreter = os.path.join(tmp_dirname, "bin/python")
        if not os.access(interpreter, os.X_OK):
            interpreter = os.path.join(tmp_dirname, "Scripts/python")

        subprocess.check_call([interpreter, "setup.py", "sdist", "install"],
                              cwd=os.path.dirname(module.__file__),
                              env=GetCleanEnvironment())

        out_fd = StringIO.StringIO()
        component_archive = zipfile.ZipFile(out_fd,
                                            "w",
                                            compression=zipfile.ZIP_DEFLATED)

        path = os.path.join(tmp_dirname, "lib/python2.7/site-packages")
        if not os.access(path, os.R_OK):
            path = os.path.join(tmp_dirname, "lib/site-packages")

        # Warn about incompatible modules.
        CheckUselessComponentModules(interpreter)

        # These modules are assumed to already exist in the client and therefore do
        # not need to be re-packaged in the component.
        skipped_modules = SKIPPED_MODULES
        for root, dirs, files in os.walk(path):
            for file_name in files:
                filename = os.path.join(root, file_name)
                # Unzip egg files to keep it simple.
                if filename.endswith(".egg"):
                    data = StringIO.StringIO(open(filename, "rb").read())
                    os.unlink(filename)
                    zipfile.ZipFile(data).extractall(filename)
                    dirs.append(filename)
                    continue

                archive_filename = os.path.relpath(filename, path)
                if archive_filename.endswith(".pyc"):
                    continue

                if _PathStartsWithSkippedModules(archive_filename,
                                                 skipped_modules):
                    continue

                component_archive.write(filename, archive_filename)

        component_archive.close()

        result = rdf_client.ClientComponent(
            summary=rdf_client.ClientComponentSummary(
                name=setup_args["name"],
                version=setup_args["version"],
                modules=setup_args["py_modules"],
            ),
            build_system=rdf_client.Uname.FromCurrentSystem(),
        )

        # Components will be encrypted using AES128CBC
        result.summary.cipher.SetAlgorithm("AES128CBC")

        # Clear these non important fields about the build box.
        result.build_system.fqdn = None
        result.build_system.node = None
        result.build_system.kernel = None

        print "Built component:"
        print result

        result.raw_data = out_fd.getvalue()

        utils.EnsureDirExists(output_dir)

        output = os.path.join(
            output_dir,
            "%s_%s_%s.bin" % (result.summary.name, result.summary.version,
                              result.build_system.signature()))

        with open(output, "wb") as fd:
            fd.write(result.SerializeToString())

        print "Component saved as %s" % output

        return result