mageni/mageni

View on GitHub
src/backend/api/src/lsc_user.c

Summary

Maintainability
Test Coverage
/**
 * SPDX-License-Identifier: GPL-2.0-or-later
 * SPDX-FileCopyrightText: Copyright 2009-2018 Greenbone Networks GmbH
 * SPDX-FileComment: This file provides support for generating packages for LSC credentials.
 * SPDX-FileContributor: Mageni Security LLC
 * 
 */

#include <glib.h>
#include <glib/gstdio.h>
#include "../../libraries/util/fileutils.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#undef G_LOG_DOMAIN
/**
 * @brief GLib log domain.
 */
#define G_LOG_DOMAIN "md manage"

/* Key creation. */

/**
 * @brief Create an ssh key for local security checks.
 *
 * Forks and creates a key for local checks by calling
 * 'ssh-keygen -t rsa -f filepath -C "comment" -P "passhprase"'.
 * A directory will be created if it does not exist.
 *
 * @param[in]  comment     Comment to use.
 * @param[in]  passphrase  Passphrase for key, must be longer than 4 characters.
 * @param[in]  privpath    Filename of the key file.
 *
 * @return 0 if successful, -1 otherwise.
 */
static int
create_ssh_key (const char *comment,
                const char *passphrase,
                const char *privpath)
{
  gchar *astdout = NULL;
  gchar *astderr = NULL;
  GError *err = NULL;
  gint exit_status = 0;
  gchar *dir;
  char *command;

  /* Sanity-check essential parameters. */

  if (!comment || comment[0] == '\0')
    {
      g_warning ("%s: comment must be set", __FUNCTION__);
      return -1;
    }
  if (!passphrase || strlen (passphrase) < 5)
    {
      g_warning ("%s: password must be longer than 4 characters", __FUNCTION__);
      return -1;
    }

  /* Sanity check files. */

  dir = g_path_get_dirname (privpath);
  if (g_mkdir_with_parents (dir, 0755 /* "rwxr-xr-x" */))
    {
      g_warning ("%s: failed to access %s", __FUNCTION__, dir);
      g_free (dir);
      return -1;
    }
  g_free (dir);

  /* Spawn ssh-keygen. */
  command = g_strconcat ("ssh-keygen -t rsa -f ",
                         privpath,
                         " -C \"",
                         comment,
                         "\" -P \"",
                         passphrase,
                         "\"",
                         NULL);
  g_debug ("command: ssh-keygen -t rsa -f %s -C \"%s\" -P \"********\"",
           privpath,
           comment);

  if ((g_spawn_command_line_sync (
         command, &astdout, &astderr, &exit_status, &err)
       == FALSE)
      || (WIFEXITED (exit_status) == 0) || WEXITSTATUS (exit_status))
    {
      if (err)
        {
          g_warning (
            "%s: failed to create private key: %s", __FUNCTION__, err->message);
          g_error_free (err);
        }
      else
        g_warning ("%s: failed to create private key", __FUNCTION__);
      g_debug ("%s: key-gen failed with %d (WIF %i, WEX %i).\n",
               __FUNCTION__,
               exit_status,
               WIFEXITED (exit_status),
               WEXITSTATUS (exit_status));
      g_debug ("%s: stdout: %s", __FUNCTION__, astdout);
      g_debug ("%s: stderr: %s", __FUNCTION__, astderr);
      g_free (command);
      g_free (astdout);
      g_free (astderr);
      return -1;
    }
  g_free (command);
  g_free (astdout);
  g_free (astderr);
  return 0;
}

/**
 * @brief Create local security check (LSC) keys.
 *
 * @param[in]   password     Password.
 * @param[out]  private_key  Private key.
 *
 * @return 0 success, -1 error.
 */
int
lsc_user_keys_create (const gchar *password, gchar **private_key)
{
  GError *error;
  gsize length;
  char key_dir[] = "/tmp/openvas_key_XXXXXX";
  gchar *key_path = NULL;
  int ret = -1;

  /* Make a directory for the keys. */

  if (mkdtemp (key_dir) == NULL)
    return -1;

  /* Create private key. */
  key_path = g_build_filename (key_dir, "key", NULL);
  if (create_ssh_key ("Key generated by GVM", password, key_path))
    goto free_exit;

  error = NULL;
  g_file_get_contents (key_path, private_key, &length, &error);
  if (error)
    {
      g_error_free (error);
      goto free_exit;
    }
  ret = 0;
free_exit:

  g_free (key_path);
  gvm_file_remove_recurse (key_dir);
  return ret;
}

/* RPM package generation. */

/**
 * @brief Attempts creation of RPM packages to create a user and install a
 * @brief public key file for it.
 *
 * @param[in]  username         Name of user.
 * @param[in]  public_key_path  Location of public key.
 * @param[in]  to_filename      Destination filename for RPM.
 *
 * @return Path to rpm file if successful, NULL otherwise.
 */
static gboolean
lsc_user_rpm_create (const gchar *username,
                     const gchar *public_key_path,
                     const gchar *to_filename)
{
  gint exit_status;
  gchar *new_pubkey_filename = NULL;
  gchar *pubkey_basename = NULL;
  gchar **cmd;
  char tmpdir[] = "/tmp/lsc_user_rpm_create_XXXXXX";
  gboolean success = TRUE;
  gchar *standard_out = NULL;
  gchar *standard_err = NULL;

  /* Create a temporary directory. */

  g_debug ("%s: create temporary directory", __FUNCTION__);
  if (mkdtemp (tmpdir) == NULL)
    return FALSE;
  g_debug ("%s: temporary directory: %s", __FUNCTION__, tmpdir);

  /* Copy the public key into the temporary directory. */

  g_debug ("%s: copy key to temporary directory", __FUNCTION__);
  pubkey_basename = g_strdup_printf ("%s.pub", username);
  new_pubkey_filename = g_build_filename (tmpdir, pubkey_basename, NULL);
  if (gvm_file_copy (public_key_path, new_pubkey_filename) == FALSE)
    {
      g_warning ("%s: failed to copy key file %s to %s",
                 __FUNCTION__,
                 public_key_path,
                 new_pubkey_filename);
      g_free (pubkey_basename);
      g_free (new_pubkey_filename);
      return FALSE;
    }

  /* Execute create-rpm script with the temporary directory as the
   * target and the public key in the temporary directory as the key. */

  g_debug ("%s: Attempting RPM build", __FUNCTION__);
  cmd = (gchar **) g_malloc (6 * sizeof (gchar *));
  cmd[0] = g_build_filename (MAGENI_DATA_DIR, "gvm-lsc-rpm-creator.sh", NULL);
  cmd[1] = g_strdup (username);
  cmd[2] = g_strdup (new_pubkey_filename);
  cmd[3] = g_strdup (tmpdir);
  cmd[4] = g_strdup (to_filename);
  cmd[5] = NULL;
  g_debug ("%s: Spawning in %s: %s %s %s %s %s",
           __FUNCTION__,
           tmpdir,
           cmd[0],
           cmd[1],
           cmd[2],
           cmd[3],
           cmd[4]);
  if ((g_spawn_sync (tmpdir,
                     cmd,
                     NULL, /* Environment. */
                     G_SPAWN_SEARCH_PATH,
                     NULL, /* Setup function. */
                     NULL,
                     &standard_out,
                     &standard_err,
                     &exit_status,
                     NULL)
       == FALSE)
      || (WIFEXITED (exit_status) == 0) || WEXITSTATUS (exit_status))
    {
      g_warning ("%s: failed to create the rpm: %d (WIF %i, WEX %i)",
                 __FUNCTION__,
                 exit_status,
                 WIFEXITED (exit_status),
                 WEXITSTATUS (exit_status));
      g_debug ("%s: stdout: %s", __FUNCTION__, standard_out);
      g_debug ("%s: stderr: %s", __FUNCTION__, standard_err);
      success = FALSE;
    }

  g_free (cmd[0]);
  g_free (cmd[1]);
  g_free (cmd[2]);
  g_free (cmd[3]);
  g_free (cmd[4]);
  g_free (cmd);
  g_free (pubkey_basename);
  g_free (new_pubkey_filename);
  g_free (standard_out);
  g_free (standard_err);

  /* Remove the copy of the public key and the temporary directory. */

  if (gvm_file_remove_recurse (tmpdir) != 0 && success == TRUE)
    {
      g_warning (
        "%s: failed to remove temporary directory %s", __FUNCTION__, tmpdir);
      success = FALSE;
    }

  return success;
}

/**
 * @brief Recreate RPM package.
 *
 * @param[in]   name         User name.
 * @param[in]   public_key   Public key.
 * @param[out]  rpm          RPM package.
 * @param[out]  rpm_size     Size of RPM package, in bytes.
 *
 * @return 0 success, -1 error.
 */
int
lsc_user_rpm_recreate (const gchar *name,
                       const char *public_key,
                       void **rpm,
                       gsize *rpm_size)
{
  GError *error;
  char rpm_dir[] = "/tmp/rpm_XXXXXX";
  char key_dir[] = "/tmp/key_XXXXXX";
  gchar *rpm_path, *public_key_path;
  int ret = -1;

  /* Make a directory for the key. */

  if (mkdtemp (key_dir) == NULL)
    return -1;

  /* Write public key to file. */

  error = NULL;
  public_key_path = g_build_filename (key_dir, "key.pub", NULL);
  g_file_set_contents (
    public_key_path, public_key, strlen (public_key), &error);
  if (error)
    goto free_exit;

  /* Create RPM package. */

  if (mkdtemp (rpm_dir) == NULL)
    goto free_exit;
  rpm_path = g_build_filename (rpm_dir, "p.rpm", NULL);
  g_debug ("%s: rpm_path: %s", __FUNCTION__, rpm_path);
  if (lsc_user_rpm_create (name, public_key_path, rpm_path) == FALSE)
    {
      g_free (rpm_path);
      goto rm_exit;
    }

  /* Read the package into memory. */

  error = NULL;
  g_file_get_contents (rpm_path, (gchar **) rpm, rpm_size, &error);
  g_free (rpm_path);
  if (error)
    {
      g_error_free (error);
      goto rm_exit;
    }

  /* Return. */

  ret = 0;

rm_exit:

  gvm_file_remove_recurse (rpm_dir);

free_exit:

  g_free (public_key_path);

  gvm_file_remove_recurse (key_dir);

  return ret;
}

/* Deb generation. */

/**
 * @brief Attempts creation of Debian packages to create a user and install a
 * @brief public key file for it.
 *
 * @param[in]  username         Name of user.
 * @param[in]  public_key_path  Location of public key.
 * @param[in]  to_filename      Destination filename for RPM.
 * @param[in]  maintainer       Maintainer email address.
 *
 * @return Path to rpm file if successful, NULL otherwise.
 */
static gboolean
lsc_user_deb_create (const gchar *username,
                     const gchar *public_key_path,
                     const gchar *to_filename,
                     const gchar *maintainer)
{
  gint exit_status;
  gchar *new_pubkey_filename = NULL;
  gchar *pubkey_basename = NULL;
  gchar **cmd;
  char tmpdir[] = "/tmp/lsc_user_deb_create_XXXXXX";
  gboolean success = TRUE;
  gchar *standard_out = NULL;
  gchar *standard_err = NULL;

  /* Create a temporary directory. */

  g_debug ("%s: create temporary directory", __FUNCTION__);
  if (mkdtemp (tmpdir) == NULL)
    return FALSE;
  g_debug ("%s: temporary directory: %s", __FUNCTION__, tmpdir);

  /* Copy the public key into the temporary directory. */

  g_debug ("%s: copy key to temporary directory", __FUNCTION__);
  pubkey_basename = g_strdup_printf ("%s.pub", username);
  new_pubkey_filename = g_build_filename (tmpdir, pubkey_basename, NULL);
  if (gvm_file_copy (public_key_path, new_pubkey_filename) == FALSE)
    {
      g_warning ("%s: failed to copy key file %s to %s",
                 __FUNCTION__,
                 public_key_path,
                 new_pubkey_filename);
      g_free (pubkey_basename);
      g_free (new_pubkey_filename);
      return FALSE;
    }

  /* Execute create-deb script with the temporary directory as the
   * target and the public key in the temporary directory as the key. */

  g_debug ("%s: Attempting DEB build", __FUNCTION__);
  cmd = (gchar **) g_malloc (7 * sizeof (gchar *));
  cmd[0] = g_build_filename (MAGENI_DATA_DIR, "gvm-lsc-deb-creator.sh", NULL);
  cmd[1] = g_strdup (username);
  cmd[2] = g_strdup (new_pubkey_filename);
  cmd[3] = g_strdup (tmpdir);
  cmd[4] = g_strdup (to_filename);
  cmd[5] = g_strdup (maintainer);
  cmd[6] = NULL;
  g_debug ("%s: Spawning in %s: %s %s %s %s %s %s",
           __FUNCTION__,
           tmpdir,
           cmd[0],
           cmd[1],
           cmd[2],
           cmd[3],
           cmd[4],
           cmd[5]);
  if ((g_spawn_sync (tmpdir,
                     cmd,
                     NULL, /* Environment. */
                     G_SPAWN_SEARCH_PATH,
                     NULL, /* Setup function. */
                     NULL,
                     &standard_out,
                     &standard_err,
                     &exit_status,
                     NULL)
       == FALSE)
      || (WIFEXITED (exit_status) == 0) || WEXITSTATUS (exit_status))
    {
      g_warning ("%s: failed to create the deb: %d (WIF %i, WEX %i)",
                 __FUNCTION__,
                 exit_status,
                 WIFEXITED (exit_status),
                 WEXITSTATUS (exit_status));
      g_debug ("%s: stdout: %s", __FUNCTION__, standard_out);
      g_debug ("%s: stderr: %s", __FUNCTION__, standard_err);
      success = FALSE;
    }

  g_free (cmd[0]);
  g_free (cmd[1]);
  g_free (cmd[2]);
  g_free (cmd[3]);
  g_free (cmd[4]);
  g_free (cmd[5]);
  g_free (cmd);
  g_free (pubkey_basename);
  g_free (new_pubkey_filename);
  g_free (standard_out);
  g_free (standard_err);

  /* Remove the copy of the public key and the temporary directory. */

  if (gvm_file_remove_recurse (tmpdir) != 0 && success == TRUE)
    {
      g_warning (
        "%s: failed to remove temporary directory %s", __FUNCTION__, tmpdir);
      success = FALSE;
    }

  return success;
}

/**
 * @brief Recreate DEB package.
 *
 * @param[in]   name         User name.
 * @param[in]   public_key   Public key.
 * @param[in]   maintainer   The maintainer email address.
 * @param[out]  deb          DEB package.
 * @param[out]  deb_size     Size of DEB package, in bytes.
 *
 * @return 0 success, -1 error.
 */
int
lsc_user_deb_recreate (const gchar *name,
                       const char *public_key,
                       const char *maintainer,
                       void **deb,
                       gsize *deb_size)
{
  GError *error;
  char deb_dir[] = "/tmp/deb_XXXXXX";
  char key_dir[] = "/tmp/key_XXXXXX";
  gchar *deb_path, *public_key_path;
  int ret = -1;

  /* Make a directory for the key. */

  if (mkdtemp (key_dir) == NULL)
    return -1;

  /* Write public key to file. */

  error = NULL;
  public_key_path = g_build_filename (key_dir, "key.pub", NULL);
  g_file_set_contents (
    public_key_path, public_key, strlen (public_key), &error);
  if (error)
    goto free_exit;

  /* Create DEB package. */

  if (mkdtemp (deb_dir) == NULL)
    goto free_exit;
  deb_path = g_build_filename (deb_dir, "p.deb", NULL);
  g_debug ("%s: deb_path: %s", __FUNCTION__, deb_path);
  if (lsc_user_deb_create (name, public_key_path, deb_path, maintainer)
      == FALSE)
    {
      g_free (deb_path);
      goto rm_exit;
    }

  /* Read the package into memory. */

  error = NULL;
  g_file_get_contents (deb_path, (gchar **) deb, deb_size, &error);
  g_free (deb_path);
  if (error)
    {
      g_error_free (error);
      goto rm_exit;
    }

  /* Return. */

  ret = 0;

rm_exit:

  gvm_file_remove_recurse (deb_dir);

free_exit:

  g_free (public_key_path);

  gvm_file_remove_recurse (key_dir);

  return ret;
}

/* Exe generation. */

/**
 * @brief Write an NSIS installer script to file.
 *
 * @param[in]  script_name   Name of script.
 * @param[in]  package_name  Name of package.
 * @param[in]  user_name     User name.
 * @param[in]  password      User password.
 *
 * @return 0 success, -1 error.
 */
static int
create_nsis_script (const gchar *script_name,
                    const gchar *package_name,
                    const gchar *user_name,
                    const gchar *password)
{
  FILE *fd;

  fd = fopen (script_name, "w");
  if (fd == NULL)
    return -1;

  // Write part about default section
  fprintf (fd, "#Installer filename\n");
  fprintf (fd, "outfile ");
  fprintf (fd, "%s", package_name);
  fprintf (fd, "\n\n");

  fprintf (fd, "# Set desktop as install directory\n");
  fprintf (fd, "installDir $DESKTOP\n\n");

  fprintf (fd, "# Put some text\n");
  fprintf (fd, "BrandingText \"GVM Local Security Checks User\"\n\n");

  // For ms vista installers we need the UAC plugin and use the following lines:
  // This requires the user to have the UAC plugin installed and to provide the
  // the path to it.
  // fprintf (fd, "# Request application privileges for Windows Vista\n");
  // fprintf (fd, "RequestExecutionLevel admin\n\n");

  fprintf (fd, "#\n# Default (installer) section.\n#\n");
  fprintf (fd, "section\n\n");

  fprintf (fd, "# Define output path\n");
  fprintf (fd, "setOutPath $INSTDIR\n\n");

  fprintf (fd, "# Uninstaller name\n");
  fprintf (
    fd, "writeUninstaller $INSTDIR\\openvas_lsc_remove_%s.exe\n\n", user_name);

  // Need to find localized Administrators group name, create a
  // GetAdminGroupName - vb script (Thanks to Thomas Rotter)
  fprintf (fd, "# Create Thomas Rotters GetAdminGroupName.vb script\n");
  fprintf (fd,
           "ExecWait \"cmd /C Echo Set objWMIService = "
           "GetObject($\\\"winmgmts:\\\\.\\root\\cimv2$\\\") > "
           "$\\\"%%temp%%\\GetAdminGroupName.vbs$\\\" \"\n");
  fprintf (fd,
           "ExecWait \"cmd /C Echo Set colAccounts = objWMIService.ExecQuery "
           "($\\\"Select * From Win32_Group Where SID = 'S-1-5-32-544'$\\\")  "
           ">> $\\\"%%temp%%\\GetAdminGroupName.vbs$\\\"\"\n");
  fprintf (fd,
           "ExecWait \"cmd /C Echo For Each objAccount in colAccounts >> "
           "$\\\"%%temp%%\\GetAdminGroupName.vbs$\\\"\"\n");
  fprintf (fd,
           "ExecWait \"cmd /C Echo Wscript.Echo objAccount.Name >> "
           "$\\\"%%temp%%\\GetAdminGroupName.vbs$\\\"\"\n");
  fprintf (fd,
           "ExecWait \"cmd /C Echo Next >> "
           "$\\\"%%temp%%\\GetAdminGroupName.vbs$\\\"\"\n");
  fprintf (fd,
           "ExecWait \"cmd /C cscript //nologo "
           "$\\\"%%temp%%\\GetAdminGroupName.vbs$\\\" > "
           "$\\\"%%temp%%\\AdminGroupName.txt$\\\"\"\n\n");

  /** @todo provide /comment:"GVM User" /fullname:"GVM Testuser" */
  fprintf (fd, "# Create batch script that installs the user\n");
  fprintf (fd,
           "ExecWait \"cmd /C Echo Set /P AdminGroupName= "
           "^<$\\\"%%temp%%\\AdminGroupName.txt$\\\" > "
           "$\\\"%%temp%%\\AddUser.bat$\\\"\" \n");
  fprintf (fd,
           "ExecWait \"cmd /C Echo net user %s %s /add /active:yes >> "
           "$\\\"%%temp%%\\AddUser.bat$\\\"\"\n",
           user_name,
           password);
  fprintf (fd,
           "ExecWait \"cmd /C Echo net localgroup %%AdminGroupName%% "
           "%%COMPUTERNAME%%\\%s /add >> $\\\"%%temp%%\\AddUser.bat$\\\"\"\n\n",
           user_name);

  fprintf (fd, "# Execute AddUser script\n");
  fprintf (fd, "ExecWait \"cmd /C $\\\"%%temp%%\\AddUser.bat$\\\"\"\n\n");

  // Remove up temporary files for localized Administrators group names
  fprintf (fd, "# Remove temporary files for localized admin group names\n");
  fprintf (fd, "ExecWait \"del $\\\"%%temp%%\\AdminGroupName.txt$\\\"\"\n");
  fprintf (fd,
           "ExecWait \"del $\\\"%%temp%%\\GetAdminGroupName.vbs$\\\"\"\n\n");
  fprintf (fd, "ExecWait \"del $\\\"%%temp%%\\AddUser.bat$\\\"\"\n\n");

  /** @todo Display note about NTLM and SMB signing and encryption, 'Easy
   * Filesharing' in WIN XP */
  fprintf (fd, "# Display message that everything seems to be fine\n");
  fprintf (fd,
           "messageBox MB_OK \"A user has been added. An uninstaller is "
           "placed on your Desktop.\"\n\n");

  fprintf (fd, "# Default (install) section end\n");
  fprintf (fd, "sectionEnd\n\n");

  // Write part about uninstall section
  fprintf (fd, "#\n# Uninstaller section.\n#\n");
  fprintf (fd, "section \"Uninstall\"\n\n");

  fprintf (fd, "# Run cmd to remove user\n");
  fprintf (fd, "ExecWait \"net user %s /delete\"\n\n", user_name);

  /** @todo Uninstaller should remove itself */
  fprintf (fd,
           "# Unistaller should remove itself (from desktop/installdir)\n\n");

  fprintf (fd, "# Display message that everything seems to be fine\n");
  fprintf (fd,
           "messageBox MB_OK \"A user has been removed. You can now safely "
           "remove the uninstaller from your Desktop.\"\n\n");

  fprintf (fd, "# Uninstaller section end\n");
  fprintf (fd, "sectionEnd\n\n");

  if (fclose (fd))
    return -1;

  return 0;
}

/**
 * @brief Execute makensis to create a package from an NSIS script.
 *
 * Run makensis in the directory that nsis_script is in.
 *
 * @param[in]  nsis_script  Name of resulting package.
 *
 * @return 0 success, -1 error.
 */
static int
execute_makensis (const gchar *nsis_script)
{
  gchar *dirname = g_path_get_dirname (nsis_script);
  gchar **cmd;
  gint exit_status;
  int ret = 0;
  gchar *standard_out = NULL;
  gchar *standard_err = NULL;

  cmd = (gchar **) g_malloc (3 * sizeof (gchar *));

  cmd[0] = g_strdup ("makensis");
  cmd[1] = g_strdup (nsis_script);
  cmd[2] = NULL;
  g_debug ("--- executing makensis");
  g_debug ("%s: Spawning in %s: %s %s", __FUNCTION__, dirname, cmd[0], cmd[1]);
  if ((g_spawn_sync (dirname,
                     cmd,
                     NULL, /* Environment. */
                     G_SPAWN_SEARCH_PATH,
                     NULL, /* Setup func. */
                     NULL,
                     &standard_out,
                     &standard_err,
                     &exit_status,
                     NULL)
       == FALSE)
      || (WIFEXITED (exit_status) == 0) || WEXITSTATUS (exit_status))
    {
      g_warning ("%s: failed to create the exe: %d (WIF %i, WEX %i)",
                 __FUNCTION__,
                 exit_status,
                 WIFEXITED (exit_status),
                 WEXITSTATUS (exit_status));
      g_debug ("%s: stdout: %s", __FUNCTION__, standard_out);
      g_debug ("%s: stderr: %s", __FUNCTION__, standard_err);
      ret = -1;
    }

  g_free (cmd[0]);
  g_free (cmd[1]);
  g_free (cmd);
  g_free (dirname);
  g_free (standard_out);
  g_free (standard_err);

  return ret;
}

/**
 * @brief Create an NSIS package.
 *
 * @param[in]  user_name    Name of user.
 * @param[in]  password     Password of user.
 * @param[in]  to_filename  Destination filename for package.
 *
 * @return 0 success, -1 error.
 */
static int
lsc_user_exe_create (const gchar *user_name,
                     const gchar *password,
                     const gchar *to_filename)
{
  gchar *dirname = g_path_get_dirname (to_filename);
  gchar *nsis_script = g_build_filename (dirname, "p.nsis", NULL);

  g_free (dirname);

  if (create_nsis_script (nsis_script, to_filename, user_name, password))
    {
      g_warning ("%s: Failed to create NSIS script", __FUNCTION__);
      g_free (nsis_script);
      return -1;
    }

  if (execute_makensis (nsis_script))
    {
      g_warning ("%s: Failed to execute makensis", __FUNCTION__);
      g_free (nsis_script);
      return -1;
    }

  g_free (nsis_script);
  return 0;
}

/**
 * @brief Recreate NSIS package.
 *
 * @param[in]   name         User name.
 * @param[in]   password     Password.
 * @param[out]  exe          NSIS package.
 * @param[out]  exe_size     Size of NSIS package, in bytes.
 *
 * @return 0 success, -1 error.
 */
int
lsc_user_exe_recreate (const gchar *name,
                       const gchar *password,
                       void **exe,
                       gsize *exe_size)
{
  GError *error;
  char exe_dir[] = "/tmp/exe_XXXXXX";
  gchar *exe_path;
  int ret = -1;

  /* Create NSIS package. */

  if (mkdtemp (exe_dir) == NULL)
    return -1;
  exe_path = g_build_filename (exe_dir, "p.nsis", NULL);
  if (lsc_user_exe_create (name, password, exe_path))
    goto rm_exit;

  /* Read the package into memory. */

  error = NULL;
  g_file_get_contents (exe_path, (gchar **) exe, exe_size, &error);
  if (error)
    {
      g_error_free (error);
      goto rm_exit;
    }

  /* Return. */

  ret = 0;

rm_exit:

  gvm_file_remove_recurse (exe_dir);

  g_free (exe_path);

  return ret;
}