/* Copyright (C) 1998 Thorsten Kukuk
   Author: Thorsten Kukuk <kukuk@vt.uni-paderborn.de>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.

   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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

/* Set secret key on local machine. This version is a complete rewrite of the
   keylogin from SUNRPC 4.0 */

#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif

#define _GNU_SOURCE

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
#include "lib/compat/getopt.h"
#endif
#include <locale.h>
#include <libintl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <rpc/rpc.h>
#include <rpc/key_prot.h>

#ifndef _
#define _(String) gettext (String)
#endif

#define ROOTKEY_FILE "/etc/.rootkey"

extern int key_setnet (struct key_netstarg *arg);

/* Name and version of program.  */
/* Print the version information.  */
static inline void
print_version (void)
{
  fprintf (stdout, "keylogin (%s) %s\n", PACKAGE, VERSION);
  fprintf (stdout, gettext ("\
Copyright (C) %s Thorsten Kukuk.\n\
This is free software; see the source for copying conditions.  There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
"), "1998");
  /* fprintf (stdout, _("Written by %s.\n"), "Thorsten Kukuk"); */
}

static inline void
print_usage (void)
{
  fputs (_("Usage: keylogin [-r]\n"), stdout);
}

static void
print_help (void)
{
  print_usage ();
  fputs (_("keylogin - decrypt and store secret key with keyserv\n\n"),
         stdout);

  fputs (_("  -r             Update the /etc/.rootkey file\n"), stdout);
  fputs (_("  --help         Give this help list\n"), stdout);
  fputs (_("  --usage        Give a short usage message\n"), stdout);
  fputs (_("  --version      Print program version\n"), stdout);
}

static inline void
print_error (void)
{
  const char *program = "keylogin";

  fprintf (stderr,
           _("Try `%s --help' or `%s --usage' for more information.\n"),
           program, program);
}

int
main (int argc, char *argv[])
{
  char fullname[MAXNETNAMELEN + 1];
  struct key_netstarg net;
  int mkrootkey = 0;
  int fd;

  setlocale (LC_MESSAGES, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  while (1)
    {
      int c;
      int option_index = 0;
      static struct option long_options[] =
      {
	{"version", no_argument, NULL, '\255'},
	{"help", no_argument, NULL, '\253'},
	{"usage", no_argument, NULL, '\254'},
	{"root", no_argument, NULL, 'r'},
	{NULL, 0, NULL, '\0'}
      };

      c = getopt_long (argc, argv, "r", long_options, &option_index);
      if (c == EOF)
	break;
      switch (c)
	{
	case 'r':
	  if (geteuid () != 0)
	    {
	      fputs (_("Must be root to use -r option.\n"), stderr);
	      print_error ();
	      return 1;
	    }
	  mkrootkey = 1;
	  break;
	case '\253':
	  print_help ();
	  return 0;
	case '\255':
	  print_version ();
	  return 0;
	case '\254':
	  print_usage ();
	  return 0;
	default:
	  print_error ();
	  return 1;
	}
    }
  argc -= optind;
  argv += optind;

  if (argc != 0)
    {
      fprintf (stderr, _("%s: To many arguments\n"), "keylogin");
      print_error ();
      return 1;
    }

  getnetname (fullname);
  if (!getsecretkey (fullname, (char *)&net.st_priv_key,
		     getpass (_("Password:"))))
    {
      fprintf (stderr, _("Can't find %s's secret key\n"), fullname);
      return 1;
    }

  if (net.st_priv_key[0] == 0)
    {
      fprintf (stderr, _("Password incorrect for %s\n"), fullname);
      return 1;
    }

  /* write unencrypted secret key into root key file */
  if (mkrootkey == 1)
    {
      unlink (ROOTKEY_FILE);
      if ((fd = open (ROOTKEY_FILE, O_WRONLY + O_CREAT, 0600)) != -1)
	{
	  const char *lf = "\n";
	  write (fd, net.st_priv_key, HEXKEYBYTES);
	  write (fd, lf, 1);
	  close (fd);
	  fprintf (stderr, _("Wrote secret key into %s\n"), ROOTKEY_FILE);
	}
      else
	fprintf (stderr, _("Could not open %s for update\n"), ROOTKEY_FILE);
    }
  /* give unencrypted secret key to keyserv */
  net.st_pub_key[0] = 0;
  net.st_netname = (char *)&fullname;
  if (key_setnet (&net) < 0)
    {
      fprintf (stderr, _("Could not set %s's secret key\n"), fullname);
      fputs (_("Maybe the keyserver is down?\n"), stderr);
      return 1;
    }
  return 0;
}
