/* OpenVAS-Client
 * $Id$
 * Description: Export ssh public keys with a script to a rpm package that will
                install that user.
 *
 * Authors:
 * Felix Wolfsteller <felix.wolfsteller@intevation.de>
 *
 * Copyright:
 * Copyright (C) 2009 Intevation GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2,
 * or, at your option, any later version as published by the Free
 * Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * In addition, as a special exception, you have
 * permission to link the code of this program with the OpenSSL
 * library (or with modified versions of OpenSSL that use the same
 * license as OpenSSL), and distribute linked combinations including
 * the two. You must obey the GNU General Public License in all
 * respects for all of the code used other than OpenSSL. If you
 * modify this file, you may extend this exception to your version
 * of the file, but you are not obligated to do so. If you do not
 * wish to do so, delete this exception statement from your version.
 */

#include "openvas_ssh_login.h"
#include "file_utils.h"
#include "nessus_i18n.h"
#include "error_dlg.h"
#include <glib/gstdio.h>
#include "includes.h" /* For stdio (function: remove) */
#include "preferences.h" /* For prefs_get_nessushome */
#include "context.h" /* For check_is_dir (!) and context_remove_directory (!): @TODO */
#include "openvas_lsc_target_prep.h"
#include "openvas_lsc_user_rpm.h"


/**
 * @brief Returns the path to the directory where the rpm generator
 * @brief ("openvas-ssh-client-rpm-creator.sh") is located.
 * 
 * The search will be performed just once.
 * 
 * @return Path to the directory with the rpm generator or NULL (shall not be
 *         freed!).
 */
static gchar*
get_rpm_generator_path ()
{
  static gchar* rpm_generator_path = NULL;

  if (rpm_generator_path == NULL)
    {
      // Search in two location 
      gchar* path_exec = g_build_filename (OPENVASCLIENT_LSCRPMGEN_DIR, "openvas-ssh-client-rpm-creator.sh", NULL);
      if (check_is_file (path_exec) == 0)
        {
          g_free (path_exec);
          path_exec = g_build_filename ("tools", "openvas-ssh-client-rpm-creator.sh", NULL);
          if (check_is_file (path_exec) == 0)
            {
              // Could not be found at all
               g_free (path_exec);
            }
          else
            g_free (path_exec);
            rpm_generator_path = g_strdup ("tools");
        }
      else
        rpm_generator_path = g_strdup (OPENVASCLIENT_LSCRPMGEN_DIR);
    }

  return rpm_generator_path;
}


/**
 * @brief Returns the path to rpm package 'installer' for a given
 * @brief openvas_ssh_login.
 *
 * Installers will be placed to or read from this location. It equals the path
 * to the public key but with a different file extension (.rpm).
 *
 * @return Path to installer for given openvas_ssh_login, has to be freed using
 *         g_free, NULL in case of errors.
 */
gchar*
openvas_lsc_user_rpm_filename (const char* accountname)
{
  return openvas_lsc_target_prep_filename (accountname, "rpm");
}

/**
 * @brief Returns whether the rpm generator script was found.
 * 
 * The search will be performed only once.
 * 
 * @return TRUE if the script was found, FALSE otherwise.
 */
gboolean
openvas_lsc_user_rpm_generator_found ()
{
  static gboolean searched = FALSE;
  static gboolean found    = FALSE;

  if (searched == FALSE)
    {
      searched = TRUE;
      gchar* rpmgen_path = get_rpm_generator_path ();
      if (rpmgen_path != NULL)
        found = TRUE;
    }

  return found;
}

/**
 * @brief Attempts creation of RPM packages to install a users public key file.
 * 
 * @param loginfo openvas_ssh_login struct to create rpm for.
 * 
 * @return Path to rpm file if successfull, NULL otherwise.
 */
gboolean
openvas_lsc_user_rpm_create (openvas_ssh_login* loginfo, const gchar* to_filename)
{
  // The scripts to create rpms are currently in trunk/tools/openvas-lsc-target-preparation.
  // Move to trunk/openvas-client/tools will be done when function is stable.
  gchar* oltap_path;
  gchar* rpm_path = NULL;
  gint exit_status;
  gchar* new_pubkey_filename = NULL;
  gchar* pubkey_basename = NULL;
  gchar** cmd;
  gchar* tmpdir = NULL;
  gboolean success = TRUE;

  oltap_path = get_rpm_generator_path ();

  // First, create a temporary directory
  printf ("--- RPM-builder: create temporary directory\n");
  tmpdir = openvas_lsc_target_prep_create_tmp_dir();
  if (tmpdir == NULL)
    {
      return FALSE;
    }

  // Then, copy public key into temporary directory
  printf ("--- RPM-builder: copy key to temporary directory\n");
  pubkey_basename     = g_strdup_printf ("%s.pub", loginfo->username);
  new_pubkey_filename = g_build_filename (tmpdir, pubkey_basename, NULL);
  if (file_utils_copy_file (loginfo->public_key_path, new_pubkey_filename) == FALSE)
    {
      show_error ("Could not copy key file %s to %s.",
                  loginfo->public_key_path, new_pubkey_filename);
      g_free (pubkey_basename);
      g_free (new_pubkey_filename);
      g_free (tmpdir);
      return FALSE;
    }

  // Next, execute create-rpm script
  printf ("--- RPM-builder: Attempt RPM build\n");
  cmd = (gchar **) g_malloc (5 * sizeof (gchar *));
  cmd[0] = g_strdup ("./openvas-ssh-client-rpm-creator.sh");
  cmd[1] = g_strdup ("--target");
  cmd[2] = g_strdup (tmpdir);
  cmd[3] = g_build_filename (tmpdir, pubkey_basename, NULL);
  cmd[4] = NULL;
  printf ("Spawning in %s: %s %s %s %s\n", oltap_path, cmd[0], cmd[1], cmd[2], cmd[3]);
  if (g_spawn_sync (oltap_path,
                    cmd,
                    NULL, // env
                    G_SPAWN_SEARCH_PATH,
                    NULL, // setup func
                    NULL,
                    NULL,
                    NULL,
                    &exit_status,
                    NULL                 ) == FALSE
      || exit_status != 0)
    {
      show_error(_("Error (%d) creating the rpm with.\n"
                   "For further information consult your shell."), exit_status, cmd);
      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);
  printf ("--- RPM-builder: returned %d.\n", exit_status);

  // e.g. RPMS/noarch/openvas-lsc-target-example_user-0.5-1.noarch.rpm
  gchar* rpmfile = g_strconcat ("openvas-lsc-target-",
                                loginfo->username, "-0.5-1.noarch.rpm", NULL);
  rpm_path = g_build_filename (tmpdir, rpmfile, NULL);

  // Move that file
  if (file_utils_move_file(rpm_path, to_filename) == FALSE && success == TRUE)
    {
      show_error(_("RPM- File %s couldn't be moved to %s.\nFile will be deleted."),
                     rpm_path, to_filename);
      success = FALSE;
    }

  // Now remove the copy of the public key and the temporary directory
  if (file_utils_rmdir_rf (tmpdir) != 0 && success == TRUE)
    {
      show_error (_("Temporary directory (%s) which contains private information could not be deleted."), tmpdir);
    }

  g_free (tmpdir);
  g_free (rpm_path);
  g_free (rpmfile);

  return success;
}
