示例#1
0
static void
test_isotime2epoch (void)
{
  struct { const char *string; time_t expected; } array [] = {
    { "19700101T000001",  1 },
    { "19700101T235959",  86399 },
    { "19980815T143712",  903191832 },
    { "19700101T000000",  0 },
    { "19691231T235959",  INVALID },
    { "19000101T000000",  INVALID },
    { "",                 INVALID },
    { "19000101T00000",   INVALID },
    { "20010101t123456",  INVALID },
    { "20010101T123456",  978352496 },
    { "20070629T160000",  1183132800 },
    { "20070629T160000:",  1183132800 },
    { "20070629T160000,",  1183132800 },
    { "20070629T160000 ",  1183132800 },
    { "20070629T160000\n", 1183132800 },
    { "20070629T160000.",  INVALID },
    { NULL, 0 }
  };
  int idx;
  time_t val;
  gnupg_isotime_t tbuf;

  for (idx=0; array[idx].string; idx++)
    {
      val = isotime2epoch (array[idx].string);
      if (val != array[idx].expected )
        {
          fail (idx);
          if (verbose)
            fprintf (stderr, "string `%s' exp: %ld got: %ld\n",
                     array[idx].string, (long)array[idx].expected,
                     (long)val);
        }
      if (array[idx].expected != INVALID)
        {
          epoch2isotime (tbuf, val);
          if (strlen (tbuf) != 15)
            {
              if (verbose)
                fprintf (stderr, "string `%s', time-t %ld, revert: `%s'\n",
                         array[idx].string, (long)val, tbuf);
              fail (idx);
            }
          if (strncmp (array[idx].string, tbuf, 15))
            fail (idx);
        }
    }
}
示例#2
0
int
main ( int argc, char **argv)
{
  ARGPARSE_ARGS pargs;
  int orig_argc;
  char **orig_argv;
  gpg_error_t err = 0;
  /* const char *fname; */
  int may_coredump;
  FILE *configfp = NULL;
  char *configname = NULL;
  unsigned configlineno;
  int parse_debug = 0;
  int no_more_options = 0;
  int default_config =1;
  char *logfile = NULL;
  /* int debug_wait = 0; */
  int use_random_seed = 1;
  /* int nodetach = 0; */
  /* int nokeysetup = 0; */
  struct server_control_s ctrl;

  /*mtrace();*/

  early_system_init ();
  gnupg_reopen_std (G13_NAME "-syshelp");
  set_strusage (my_strusage);
  gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);

  log_set_prefix (G13_NAME "-syshelp", 1);

  /* Make sure that our subsystems are ready.  */
  i18n_init ();
  init_common_subsystems (&argc, &argv);

  /* Check that the Libgcrypt is suitable.  */
  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
    log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
               NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );

  /* Take extra care of the random pool.  */
  gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);

  may_coredump = disable_core_dumps ();

  g13_init_signals ();

  dotlock_create (NULL, 0); /* Register locking cleanup.  */

  opt.session_env = session_env_new ();
  if (!opt.session_env)
    log_fatal ("error allocating session environment block: %s\n",
               strerror (errno));

  opt.homedir = default_homedir ();
  /* Fixme: We enable verbose mode here because there is currently no
     way to do this when starting g13-syshelp.  To fix that we should
     add a g13-syshelp.conf file in /etc/gnupg.  */
  opt.verbose = 1;

  /* First check whether we have a debug option on the commandline.  */
  orig_argc = argc;
  orig_argv = argv;
  pargs.argc = &argc;
  pargs.argv = &argv;
  pargs.flags= (ARGPARSE_FLAG_KEEP | ARGPARSE_FLAG_NOVERSION);
  while (arg_parse( &pargs, opts))
    {
      if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
        parse_debug++;
    }

  /* Initialize the secure memory. */
  gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
  maybe_setuid = 0;

  /*
     Now we are now working under our real uid
  */

  /* Setup malloc hooks. */
  {
    struct assuan_malloc_hooks malloc_hooks;

    malloc_hooks.malloc = gcry_malloc;
    malloc_hooks.realloc = gcry_realloc;
    malloc_hooks.free = gcry_free;
    assuan_set_malloc_hooks (&malloc_hooks);
  }

  /* Prepare libassuan.  */
  assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
  /*assuan_set_system_hooks (ASSUAN_SYSTEM_NPTH);*/
  setup_libassuan_logging (&opt.debug);

  /* Setup a default control structure for command line mode.  */
  memset (&ctrl, 0, sizeof ctrl);
  g13_syshelp_init_default_ctrl (&ctrl);
  ctrl.no_server = 1;
  ctrl.status_fd = -1; /* No status output. */

  if (default_config )
    configname = make_filename (gnupg_sysconfdir (),
                                G13_NAME"-syshelp.conf", NULL);

  argc        = orig_argc;
  argv        = orig_argv;
  pargs.argc  = &argc;
  pargs.argv  = &argv;
  pargs.flags =  1;  /* Do not remove the args.  */

 next_pass:
  if (configname)
    {
      configlineno = 0;
      configfp = fopen (configname, "r");
      if (!configfp)
        {
          if (default_config)
            {
              if (parse_debug)
                log_info (_("NOTE: no default option file '%s'\n"), configname);
            }
          else
            {
              log_error (_("option file '%s': %s\n"),
                         configname, strerror(errno));
              g13_exit(2);
            }
          xfree (configname);
          configname = NULL;
        }
      if (parse_debug && configname)
        log_info (_("reading options from '%s'\n"), configname);
      default_config = 0;
    }

  while (!no_more_options
         && optfile_parse (configfp, configname, &configlineno, &pargs, opts))
    {
      switch (pargs.r_opt)
        {
        case oQuiet: opt.quiet = 1; break;

        case oDryRun: opt.dry_run = 1; break;

        case oVerbose:
          opt.verbose++;
          gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
          break;
        case oNoVerbose:
          opt.verbose = 0;
          gcry_control (GCRYCTL_SET_VERBOSITY, (int)opt.verbose);
          break;

        case oLogFile: logfile = pargs.r.ret_str; break;
        case oNoLogFile: logfile = NULL; break;

        case oNoDetach: /*nodetach = 1; */break;

        case oDebug:
          if (parse_debug_flag (pargs.r.ret_str, &opt.debug, debug_flags))
            {
              pargs.r_opt = ARGPARSE_INVALID_ARG;
              pargs.err = ARGPARSE_PRINT_ERROR;
            }
            break;
        case oDebugAll: debug_value = ~0; break;
        case oDebugNone: debug_value = 0; break;
        case oDebugLevel: debug_level = pargs.r.ret_str; break;
        case oDebugWait: /*debug_wait = pargs.r.ret_int; */break;
        case oDebugAllowCoreDump:
          may_coredump = enable_core_dumps ();
          break;

        case oStatusFD: ctrl.status_fd = pargs.r.ret_int; break;
        case oLoggerFD: log_set_fd (pargs.r.ret_int ); break;

        case oHomedir: opt.homedir = pargs.r.ret_str; break;

        case oFakedSystemTime:
          {
            time_t faked_time = isotime2epoch (pargs.r.ret_str);
            if (faked_time == (time_t)(-1))
              faked_time = (time_t)strtoul (pargs.r.ret_str, NULL, 10);
            gnupg_set_time (faked_time, 0);
          }
          break;

        case oNoSecmemWarn: gcry_control (GCRYCTL_DISABLE_SECMEM_WARN); break;

        case oNoRandomSeedFile: use_random_seed = 0; break;

        default:
          pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
          break;
	}
    }

  if (configfp)
    {
      fclose (configfp);
      configfp = NULL;
      /* Keep a copy of the config filename. */
      opt.config_filename = configname;
      configname = NULL;
      goto next_pass;
    }
  xfree (configname);
  configname = NULL;

  if (!opt.config_filename)
    opt.config_filename = make_filename (opt.homedir, G13_NAME".conf", NULL);

  if (log_get_errorcount(0))
    g13_exit(2);

  /* Now that we have the options parsed we need to update the default
     control structure.  */
  g13_syshelp_init_default_ctrl (&ctrl);

  if (may_coredump && !opt.quiet)
    log_info (_("WARNING: program may create a core file!\n"));

  if (logfile)
    {
      log_set_file (logfile);
      log_set_prefix (NULL, 1|2|4);
    }

  if (gnupg_faked_time_p ())
    {
      gnupg_isotime_t tbuf;

      log_info (_("WARNING: running with faked system time: "));
      gnupg_get_isotime (tbuf);
      dump_isotime (tbuf);
      log_printf ("\n");
    }

  /* Print any pending secure memory warnings.  */
  gcry_control (GCRYCTL_RESUME_SECMEM_WARN);

  /* Setup the debug flags for all subsystems.  */
  set_debug ();

  /* Install a regular exit handler to make real sure that the secure
     memory gets wiped out.  */
  g13_install_emergency_cleanup ();

  /* Terminate if we found any error until now.  */
  if (log_get_errorcount(0))
    g13_exit (2);

  /* Set the standard GnuPG random seed file.  */
  if (use_random_seed)
    {
      char *p = make_filename (opt.homedir, "random_seed", NULL);
      gcry_control (GCRYCTL_SET_RANDOM_SEED_FILE, p);
      xfree(p);
    }

  /* Get the UID of the caller.  */
#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
  {
    const char *uidstr;
    struct passwd *pwd = NULL;

    uidstr = getenv ("USERV_UID");

    /* Print a quick note if we are not started via userv.  */
    if (!uidstr)
      {
        if (getuid ())
          {
            log_info ("WARNING: Not started via userv\n");
            ctrl.fail_all_cmds = 1;
          }
        ctrl.client.uid = getuid ();
      }
    else
      {
        unsigned long myuid;

        errno = 0;
        myuid = strtoul (uidstr, NULL, 10);
        if (myuid == ULONG_MAX && errno)
          {
            log_info ("WARNING: Started via broken userv: %s\n",
                      strerror (errno));
            ctrl.fail_all_cmds = 1;
            ctrl.client.uid = getuid ();
          }
        else
          ctrl.client.uid = (uid_t)myuid;
      }

    pwd = getpwuid (ctrl.client.uid);
    if (!pwd || !*pwd->pw_name)
      {
        log_info ("WARNING: Name for UID not found: %s\n", strerror (errno));
        ctrl.fail_all_cmds = 1;
        ctrl.client.uname = xstrdup ("?");
      }
    else
      ctrl.client.uname = xstrdup (pwd->pw_name);

    /* Check that the user name does not contain a directory
       separator. */
    if (strchr (ctrl.client.uname, '/'))
      {
        log_info ("WARNING: Invalid user name passed\n");
        ctrl.fail_all_cmds = 1;
      }
  }
#else /*!HAVE_PWD_H || !HAVE_GETPWUID*/
  log_info ("WARNING: System does not support required syscalls\n");
  ctrl.fail_all_cmds = 1;
  ctrl.client.uid = getuid ();
  ctrl.client.uname = xstrdup ("?");
#endif /*!HAVE_PWD_H || !HAVE_GETPWUID*/

  /* Read the table entries for this user.  */
  if (!ctrl.fail_all_cmds
      && !(ctrl.client.tab = parse_g13tab (ctrl.client.uname)))
    ctrl.fail_all_cmds = 1;

  /* Start the server.  */
  err = syshelp_server (&ctrl);
  if (err)
    log_error ("server exited with error: %s <%s>\n",
               gpg_strerror (err), gpg_strsource (err));

  /* Cleanup.  */
  g13_syshelp_deinit_default_ctrl (&ctrl);
  g13_exit (0);
  return 8; /*NOTREACHED*/
}
示例#3
0
gpg_error_t cmd_genkey (assuan_context_t ctx, char *line)
{
	gpg_err_code_t error = GPG_ERR_GENERAL;
	pkcs11h_certificate_id_t cert_id = NULL;
	gcry_mpi_t n_mpi = NULL;
	gcry_mpi_t e_mpi = NULL;
	unsigned char *n_hex = NULL;
	unsigned char *e_hex = NULL;
	char *n_resp = strdup ("n ");
	char *e_resp = strdup ("e ");
	unsigned char *blob = NULL;
	char *serial = NULL;
	char *key = NULL;
	size_t blob_size;
	char timestamp[100] = {0};

	while (*line != '\x0' && !isdigit (*line)) {
		if (*line == '-') {
			static const char *ts = "--timestamp=";
			char *p = line;

			while (*line != '\x0' && !isspace (*line)) {
				line++;
			}
			line++;

			if (!strncmp (p, ts, strlen (ts))) {
				p += strlen (ts);
				sprintf (timestamp, "%d", (int)isotime2epoch (p));
			}
		}
		else {
			line++;
		}
	}

	if (*line == '\x0') {
		error = GPG_ERR_INV_DATA;
		goto cleanup;
	}

	if (strlen (timestamp) == 0) {
		sprintf (timestamp, "%d", (int)time (NULL));
	}

	if (
		(error = _get_certificate_by_name (
			ctx,
			NULL,
			atoi(line),
			&cert_id,
			&key
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (
		(error = assuan_write_status (
			ctx,
			"KEY-FPR",
			key
		)) != GPG_ERR_NO_ERROR ||
		(error = assuan_write_status(
			ctx,
			"KEY-CREATED-AT",
			timestamp
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if ((error = get_serial_of_tokenid(cert_id->token_id, &serial)) != GPG_ERR_NO_ERROR) {
		goto cleanup;
	}

	if (
		(error = assuan_write_status (
			ctx,
			"SERIALNO",
			serial
		)) != GPG_ERR_NO_ERROR ||
		(error = get_cert_blob (
			ctx,
			cert_id,
			&blob,
			&blob_size
		)) != GPG_ERR_NO_ERROR ||
		(error = keyutil_get_cert_mpi (
			blob,
			blob_size,
			&n_mpi,
			&e_mpi
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (
		gcry_mpi_aprint (
			GCRYMPI_FMT_HEX,
			&n_hex,
			NULL,
			n_mpi
		) ||
		gcry_mpi_aprint (
			GCRYMPI_FMT_HEX,
			&e_hex,
			NULL,
			e_mpi
		)
	) {
		error = GPG_ERR_BAD_KEY;
		goto cleanup;
	}

	if (
		!encoding_strappend (&n_resp, (char *)n_hex) ||
		!encoding_strappend (&e_resp, (char *)e_hex)
	) {
		error = GPG_ERR_ENOMEM;
		goto cleanup;
	}

	if (
		(error = assuan_write_status(
			ctx,
			"KEY-DATA",
			n_resp
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	if (
		(error = assuan_write_status(
			ctx,
			"KEY-DATA",
			e_resp
		)) != GPG_ERR_NO_ERROR
	) {
		goto cleanup;
	}

	error = GPG_ERR_NO_ERROR;

cleanup:

	if (n_mpi != NULL) {
		gcry_mpi_release (n_mpi);
		n_mpi = NULL;
	}

	if (e_mpi != NULL) {
		gcry_mpi_release (e_mpi);
		e_mpi = NULL;
	}

	if (n_hex != NULL) {
		gcry_free (n_hex);
		n_hex = NULL;
	}

	if (e_hex != NULL) {
		gcry_free (e_hex);
		e_hex = NULL;
	}

	if (n_resp != NULL) {
		free (n_resp);
		n_resp = NULL;
	}

	if (e_resp != NULL) {
		free (e_resp);
		e_resp = NULL;
	}

	if (blob != NULL) {
		free (blob);
		blob = NULL;
	}

	if (cert_id != NULL) {
		pkcs11h_certificate_freeCertificateId (cert_id);
		cert_id = NULL;
	}

	if (serial != NULL) {
		free(serial);
		serial = NULL;
	}

	return gpg_error (error);
}