Пример #1
0
/* Map a GnuPG error code to a cryptoki return value.  */
CK_RV
scute_gpg_err_to_ck (gpg_error_t err)
{
  if (err)
    DEBUG (DBG_CRIT, "Error occurred: %s (%s)\n", gpg_strerror (err),
	   gpg_strsource (err));

  switch (gpg_err_code (err))
    {
    case GPG_ERR_NO_ERROR:
      return CKR_OK;

    case GPG_ERR_NO_AGENT:
      return CKR_GENERAL_ERROR;

    case GPG_ERR_ENOMEM:
      return CKR_HOST_MEMORY;

    case GPG_ERR_BAD_PIN:
      return CKR_PIN_INCORRECT;

    case GPG_ERR_PIN_BLOCKED:
      return CKR_PIN_LOCKED;

    default:
      /* CKR_GENERAL_ERROR is too strong.  */
      return CKR_FUNCTION_FAILED;
    }
}
Пример #2
0
gpgme_assuan_result_t
gpgme_op_assuan_result (gpgme_ctx_t ctx)
{
  gpgme_error_t err;
  void *hook;
  op_data_t opd;

  TRACE_BEG (DEBUG_CTX, "gpgme_op_assuan_result", ctx);

  err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook, -1, NULL);
  opd = hook;
  /* Check in case this function is used without having run a command
     before.  */
  if (err || !opd)
    {
      TRACE_SUC0 ("result=(null)");
      return NULL;
    }

  /* All of this is a hack for the old style interface.  The new style
     interface returns op errors directly.  */
  opd->result.err = _gpgme_engine_assuan_last_op_err (ctx->engine->engine);
  if (opd->result.err)
    {
      TRACE_LOG1 ("err = %s", gpg_strerror (0));
    }
  else
    {
      TRACE_LOG2 ("err = %s <%s>", gpg_strerror (opd->result.err),
		  gpg_strsource (opd->result.err));
    }

  TRACE_SUC1 ("result=%p", &opd->result);
  return &opd->result;
}
Пример #3
0
static retvalue check_primary_keys(struct signatures *signatures) {
	/* Get the primary keys belonging to each signing key.
	   This might also invalidate a signature previously believed
	   valid if the primary key is expired */
	int i;

	for (i = 0 ; i < signatures->count ; i++) {
		gpg_error_t err;
		gpgme_key_t gpgme_key = NULL;
		gpgme_subkey_t subkey;
		struct signature *sig = &signatures->signatures[i];

		if (sig->state == sist_error || sig->state == sist_missing) {
			sig->primary_keyid = strdup(sig->keyid);
			if (FAILEDTOALLOC(sig->primary_keyid))
				return RET_ERROR_OOM;
			continue;
		}

		err = gpgme_get_key(context, sig->keyid, &gpgme_key, 0);
		if (err != 0) {
			fprintf(stderr,
"gpgme error %s:%d retrieving key '%s': %s\n",
					gpg_strsource(err),
					(int)gpg_err_code(err),
					sig->keyid, gpg_strerror(err));
			if (gpg_err_code(err) == GPG_ERR_ENOMEM)
				return RET_ERROR_OOM;
			else
				return RET_ERROR_GPGME;
		}
		assert (gpgme_key != NULL);
		/* the first "sub"key is the primary key */
		subkey = gpgme_key->subkeys;
		if (subkey->revoked) {
			sig->revoced_key = true;
			if (sig->state == sist_valid) {
				sig->state = sist_mostly;
				signatures->validcount--;
			}
		}
		if (subkey->expired) {
			sig->expired_key = true;
			if (sig->state == sist_valid) {
				sig->state = sist_mostly;
				signatures->validcount--;
			}
		}
		sig->primary_keyid = strdup(subkey->keyid);
		gpgme_key_unref(gpgme_key);
		if (FAILEDTOALLOC(sig->primary_keyid))
			return RET_ERROR_OOM;
	}
	return RET_OK;
}
Пример #4
0
/* Store the error in the context so that the error sending function
  can take out a descriptive text.  Inside the assuan code, use the
  macro set_error instead of this function. */
gpg_error_t
assuan_set_error (assuan_context_t ctx, gpg_error_t err, const char *text)
{
  TRACE4 (ctx, ASSUAN_LOG_CTX, "assuan_set_error", ctx,
	  "err=%i (%s,%s),text=%s", err, gpg_strsource (err),
	  gpg_strerror (err), text);

  ctx->err_no = err;
  ctx->err_str = text;
  return err;
}
Пример #5
0
retvalue gpgerror(gpg_error_t err) {
	if (err != 0) {
		fprintf(stderr, "gpgme gave error %s:%d:  %s\n",
				gpg_strsource(err), gpg_err_code(err),
				gpg_strerror(err));
		if (gpg_err_code(err) == GPG_ERR_ENOMEM)
			return RET_ERROR_OOM;
		else
			return RET_ERROR_GPGME;
	} else
		return RET_OK;
}
Пример #6
0
/* Use the assuan machinery to load the bulk of the OpenPGP card data.  */
static void
reload_data (GpaCMDinsig *card)
{
  static struct {
    const char *name;
    int entry_id;
    void (*updfnc) (GpaCMDinsig *card, int entry_id, char *string);
  } attrtbl[] = {
    { "SERIALNO",    ENTRY_SERIALNO },
    { NULL }
  };
  int attridx;
  gpg_error_t err, operr;
  char command[100];
  struct scd_getattr_parm parm;
  gpgme_ctx_t gpgagent;

  gpgagent = GPA_CM_OBJECT (card)->agent_ctx;
  g_return_if_fail (gpgagent);

  card->reloading++;
  parm.card = card;
  for (attridx=0; attrtbl[attridx].name; attridx++)
    {
      parm.name     = attrtbl[attridx].name;
      parm.entry_id = attrtbl[attridx].entry_id;
      parm.updfnc   = attrtbl[attridx].updfnc;
      snprintf (command, sizeof command, "SCD GETATTR %s", parm.name);
      err = gpgme_op_assuan_transact_ext (gpgagent,
                                          command,
                                          NULL, NULL,
                                          NULL, NULL,
                                          scd_getattr_cb, &parm, &operr);
      if (!err)
        err = operr;

      if (err)
        {
          if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
            ; /* Lost the card.  */
          else
            {
              g_debug ("assuan command `%s' failed: %s <%s>\n",
                       command, gpg_strerror (err), gpg_strsource (err));
            }
          clear_card_data (card);
          break;
        }
    }
  card->reloading--;
}
Пример #7
0
/* Use the assuan machinery to read the ATR.  */
static void
reload_data (GpaCMUnknown *card)
{
  gpg_error_t err, operr;
  char command[100];
  gpgme_ctx_t gpgagent;
  membuf_t mb;
  char *buf;

  gpgagent = GPA_CM_OBJECT (card)->agent_ctx;
  g_return_if_fail (gpgagent);

  card->reloading++;

  init_membuf (&mb, 512);

  err = gpgme_op_assuan_transact_ext (gpgagent,
                                      "SCD APDU --dump-atr",
                                      scd_atr_data_cb, &mb,
                                      NULL, NULL, NULL, NULL, &operr);
  if (!err)
    err = operr;

  if (!err)
    {
      put_membuf (&mb, "", 1);
      buf = get_membuf (&mb, NULL);
      if (buf)
        {
          buf = g_strdup_printf ("\n%s\n%s",
                                 _("The ATR of the card is:"),
                                 buf);
          gtk_label_set_text (GTK_LABEL (card->label), buf);
          g_free (buf);
        }
      else
        gtk_label_set_text (GTK_LABEL (card->label), "");
    }
  else
    {
      g_free (get_membuf (&mb, NULL));

      if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
        ; /* Lost the card.  */
      else
        g_debug ("assuan command `%s' failed: %s <%s>\n",
                 command, gpg_strerror (err), gpg_strsource (err));
      gtk_label_set_text (GTK_LABEL (card->label), "");
    }
  card->reloading--;
}
Пример #8
0
static int
get_err_from_str_one (char *str, gpg_error_t *err,
		      int *have_source, int *have_code)
{
  gpg_err_source_t src;
  gpg_err_code_t code;

  for (src = 0; src < GPG_ERR_SOURCE_DIM; src++)
    {
      const char *src_str = gpg_strsource (src << GPG_ERR_SOURCE_SHIFT);
      if (src_str && !strcasecmp (str, src_str))
	{
	  if (*have_source)
	    return 0;

	  *have_source = 1;
	  *err |= src << GPG_ERR_SOURCE_SHIFT;
	  return 1;
	}
    }

  for (code = 0; code < GPG_ERR_CODE_DIM; code++)
    {
      const char *code_str = gpg_strerror (code);
      if (code_str && !strcasecmp (str, code_str))
	{
	  if (*have_code)
	    return 0;
	  
	  *have_code = 1;
	  *err |= code;
	  return 1;
	}
    }

  return 0;
}
Пример #9
0
static void
gpa_file_import_operation_done_error_cb (GpaContext *context, gpg_error_t err,
					 GpaFileImportOperation *op)
{
  gpa_file_item_t file_item = GPA_FILE_OPERATION (op)->current->data;

  /* FIXME: Add the errors to a list and show a dialog with all import
     errors, similar to the verify status.  */
  switch (gpg_err_code (err))
    {
    case GPG_ERR_NO_ERROR:
    case GPG_ERR_CANCELED:
      /* Ignore these */
      break;

    case GPG_ERR_NO_DATA:
      gpa_show_warning (GPA_OPERATION (op)->window,
                        file_item->direct_name
                        ? _("\"%s\" contained no OpenPGP data.")
                        : _("The file \"%s\" contained no OpenPGP"
                            "data."),
                        file_item->direct_name
                        ? file_item->direct_name
                        : file_item->filename_in);
      break;

    default:
      gpa_show_warning (GPA_OPERATION (op)->window,
                        _("Error importing \"%s\": %s <%s>"),
                        file_item->direct_name
                        ? file_item->direct_name
                        : file_item->filename_in,
                        gpg_strerror (err), gpg_strsource (err));
      break;
    }
}
Пример #10
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*/
}
Пример #11
0
/* Call GPG to decrypt a block of data.


 */
static gpg_error_t
_gpg_decrypt (ctrl_t ctrl,
              const char *gpg_program,
              strlist_t gpg_arguments,
              const void *ciph, size_t ciphlen,
              estream_t cipher_stream,
              membuf_t *reader_mb,
              estream_t plain_stream)
{
  gpg_error_t err;
  assuan_context_t ctx = NULL;
  int outbound_fds[2] = { -1, -1 };
  int inbound_fds[2]  = { -1, -1 };
  npth_t writer_thread = (npth_t)0;
  npth_t reader_thread = (npth_t)0;
  gpg_error_t writer_err, reader_err;
  int ret;

  /* Make sure that either the stream interface xor the buffer
     interface is used.  */
  assert ((ciph == NULL) != (cipher_stream == NULL));
  assert ((reader_mb == NULL) != (plain_stream == NULL));

  /* Create two pipes.  */
  err = gnupg_create_outbound_pipe (outbound_fds, NULL, 0);
  if (!err)
    err = gnupg_create_inbound_pipe (inbound_fds, NULL, 0);
  if (err)
    {
      log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
      goto leave;
    }

  /* Start GPG and send the INPUT and OUTPUT commands.  */
  err = start_gpg (ctrl, gpg_program, gpg_arguments,
                   outbound_fds[0], inbound_fds[1], &ctx);
  if (err)
    goto leave;
  close (outbound_fds[0]); outbound_fds[0] = -1;
  close (inbound_fds[1]); inbound_fds[1] = -1;

  /* Start a writer thread to feed the INPUT command of the server.  */
  err = start_writer (outbound_fds[1], ciph, ciphlen, cipher_stream,
                      &writer_thread, &writer_err);
  if (err)
    return err;
  outbound_fds[1] = -1;  /* The thread owns the FD now.  */

  /* Start a reader thread to eat from the OUTPUT command of the
     server.  */
  err = start_reader (inbound_fds[0], reader_mb, plain_stream,
                      &reader_thread, &reader_err);
  if (err)
    return err;
  outbound_fds[0] = -1;  /* The thread owns the FD now.  */

  /* Run the decryption.  */
  err = assuan_transact (ctx, "DECRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
  if (err)
    {
      log_error ("the engine's DECRYPT command failed: %s <%s>\n",
                 gpg_strerror (err), gpg_strsource (err));
      goto leave;
    }

  /* Wait for reader and return the data.  */
  ret = npth_join (reader_thread, NULL);
  if (ret)
    {
      err = my_error_from_errno (ret);
      log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
      goto leave;
    }
  memset (&reader_thread, '\0', sizeof (reader_thread));
  if (reader_err)
    {
      err = reader_err;
      log_error ("read error in reader thread: %s\n", gpg_strerror (err));
      goto leave;
    }

  /* Wait for the writer to catch a writer error.  */
  ret = npth_join (writer_thread, NULL);
  if (ret)
    {
      err = my_error_from_errno (ret);
      log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
      goto leave;
    }
  memset (&writer_thread, '\0', sizeof (writer_thread));
  if (writer_err)
    {
      err = writer_err;
      log_error ("write error in writer thread: %s\n", gpg_strerror (err));
      goto leave;
    }

 leave:
  if (reader_thread)
    npth_detach (reader_thread);
  if (writer_thread)
    npth_detach (writer_thread);
  if (outbound_fds[0] != -1)
    close (outbound_fds[0]);
  if (outbound_fds[1] != -1)
    close (outbound_fds[1]);
  if (inbound_fds[0] != -1)
    close (inbound_fds[0]);
  if (inbound_fds[1] != -1)
    close (inbound_fds[1]);
  release_gpg (ctx);
  return err;
}
Пример #12
0
/* Call GPG to encrypt a block of data.


 */
static gpg_error_t
_gpg_encrypt (ctrl_t ctrl,
              const char *gpg_program,
              strlist_t gpg_arguments,
              const void *plain, size_t plainlen,
              estream_t plain_stream,
              strlist_t keys,
              membuf_t *reader_mb,
              estream_t cipher_stream)
{
  gpg_error_t err;
  assuan_context_t ctx = NULL;
  int outbound_fds[2] = { -1, -1 };
  int inbound_fds[2]  = { -1, -1 };
  npth_t writer_thread = (npth_t)0;
  npth_t reader_thread = (npth_t)0;
  gpg_error_t writer_err, reader_err;
  char line[ASSUAN_LINELENGTH];
  strlist_t sl;
  int ret;

  /* Make sure that either the stream interface xor the buffer
     interface is used.  */
  assert ((plain == NULL) != (plain_stream == NULL));
  assert ((reader_mb == NULL) != (cipher_stream == NULL));

  /* Create two pipes.  */
  err = gnupg_create_outbound_pipe (outbound_fds, NULL, 0);
  if (!err)
    err = gnupg_create_inbound_pipe (inbound_fds, NULL, 0);
  if (err)
    {
      log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
      goto leave;
    }

  /* Start GPG and send the INPUT and OUTPUT commands.  */
  err = start_gpg (ctrl, gpg_program, gpg_arguments,
                   outbound_fds[0], inbound_fds[1], &ctx);
  if (err)
    goto leave;
  close (outbound_fds[0]); outbound_fds[0] = -1;
  close (inbound_fds[1]); inbound_fds[1] = -1;

  /* Start a writer thread to feed the INPUT command of the server.  */
  err = start_writer (outbound_fds[1], plain, plainlen, plain_stream,
                      &writer_thread, &writer_err);
  if (err)
    return err;
  outbound_fds[1] = -1;  /* The thread owns the FD now.  */

  /* Start a reader thread to eat from the OUTPUT command of the
     server.  */
  err = start_reader (inbound_fds[0], reader_mb, cipher_stream,
                      &reader_thread, &reader_err);
  if (err)
    return err;
  outbound_fds[0] = -1;  /* The thread owns the FD now.  */

  /* Run the encryption.  */
  for (sl = keys; sl; sl = sl->next)
    {
      snprintf (line, sizeof line, "RECIPIENT -- %s", sl->d);
      err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
      if (err)
        {
          log_error ("the engine's RECIPIENT command failed: %s <%s>\n",
                 gpg_strerror (err), gpg_strsource (err));
          goto leave;
        }
    }

  err = assuan_transact (ctx, "ENCRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
  if (err)
    {
      log_error ("the engine's ENCRYPT command failed: %s <%s>\n",
                 gpg_strerror (err), gpg_strsource (err));
      goto leave;
    }

  /* Wait for reader and return the data.  */
  ret = npth_join (reader_thread, NULL);
  if (ret)
    {
      err = my_error_from_errno (ret);
      log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
      goto leave;
    }
  /* FIXME: Not really valid, as npth_t is an opaque type.  */
  memset (&reader_thread, '\0', sizeof (reader_thread));
  if (reader_err)
    {
      err = reader_err;
      log_error ("read error in reader thread: %s\n", gpg_strerror (err));
      goto leave;
    }

  /* Wait for the writer to catch  a writer error.  */
  ret = npth_join (writer_thread, NULL);
  if (ret)
    {
      err = my_error_from_errno (ret);
      log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
      goto leave;
    }
  memset (&writer_thread, '\0', sizeof (writer_thread));
  if (writer_err)
    {
      err = writer_err;
      log_error ("write error in writer thread: %s\n", gpg_strerror (err));
      goto leave;
    }

 leave:
  /* FIXME: Not valid, as npth_t is an opaque type.  */
  if (reader_thread)
    npth_detach (reader_thread);
  if (writer_thread)
    npth_detach (writer_thread);
  if (outbound_fds[0] != -1)
    close (outbound_fds[0]);
  if (outbound_fds[1] != -1)
    close (outbound_fds[1]);
  if (inbound_fds[0] != -1)
    close (inbound_fds[0]);
  if (inbound_fds[1] != -1)
    close (inbound_fds[1]);
  release_gpg (ctx);
  return err;
}
Пример #13
0
/* name must already be upper-case */
static retvalue load_key(const char *name, bool allow_subkeys, bool allow_bad, const char *full_condition, const struct known_key **key_found, int *index_found) {
	gpg_error_t err;
	gpgme_key_t gpgme_key = NULL;
	gpgme_subkey_t subkey;
	int found = -1;
	struct known_key *k;
	int i;
	size_t l = strlen(name);

	/* first look if this key was already retrieved: */
	for (k = known_keys ; k != NULL ; k = k->next) {
		for(i = 0 ; i < k->count ; i++) {
			struct known_subkey *s = &k->subkeys[i];

			if (s->name_len < l)
				continue;
			if (memcmp(name, s->name + (s->name_len - l), l) != 0)
				continue;
			return found_key(k, i, allow_subkeys, allow_bad,
					full_condition,
					key_found, index_found);
		}
	}
	/* If not yet found, request it: */
	err = gpgme_get_key(context, name, &gpgme_key, 0);
	if ((gpg_err_code(err) == GPG_ERR_EOF) && gpgme_key == NULL) {
		fprintf(stderr, "Error: unknown key '%s'!\n", name);
		return RET_ERROR_MISSING;
	}
	if (err != 0) {
		fprintf(stderr, "gpgme error %s:%d retrieving key '%s': %s\n",
				gpg_strsource(err), (int)gpg_err_code(err),
				name, gpg_strerror(err));
		if (gpg_err_code(err) == GPG_ERR_ENOMEM)
			return RET_ERROR_OOM;
		else
			return RET_ERROR_GPGME;
	}
	i = 0;
	subkey = gpgme_key->subkeys;
	while (subkey != NULL) {
		subkey = subkey->next;
		i++;
	}
	k = calloc(1, sizeof(struct known_key)
			+ i * sizeof(struct known_subkey));
	if (FAILEDTOALLOC(k)) {
		gpgme_key_unref(gpgme_key);
		return RET_ERROR_OOM;
	}
	k->count = i;
	k->next = known_keys;
	known_keys = k;

	subkey = gpgme_key->subkeys;
	for (i = 0 ; i < k->count ; i++ , subkey = subkey->next) {
		struct known_subkey *s = &k->subkeys[i];

		assert (subkey != NULL);

		s->revoked = subkey->revoked;
		s->expired = subkey->expired;
		s->cansign = subkey->can_sign && !subkey->invalid;
		s->name = strdup(subkey->keyid);
		if (FAILEDTOALLOC(s->name)) {
			gpgme_key_unref(gpgme_key);
			return RET_ERROR_OOM;
		}
		for (char *p = s->name ; *p != '\0' ; p++) {
			if (*p >= 'a' && *p <= 'z')
				*p -= 'a'-'A';
		}
		s->name_len = strlen(s->name);
		if (memcmp(name, s->name + (s->name_len - l), l) == 0)
			found = i;
	}
	assert (subkey == NULL);
	gpgme_key_unref(gpgme_key);
	if (found < 0) {
		fprintf(stderr, "Error: not a valid key id '%s'!\n"
"Use hex-igits from the end of the key as identifier\n", name);
		return RET_ERROR;
	}
	return found_key(k, found, allow_subkeys, allow_bad,
			full_condition, key_found, index_found);
}
Пример #14
0
Файл: cardman.c Проект: gpg/gpa
/* This function is called to trigger a card-reload.  */
static void
card_reload (GpaCardManager *cardman)
{
  gpg_error_t err, operr;
  const char *application;
  char *command_buf = NULL;
  const char *command;
  const char *err_desc = NULL;
  char *err_desc_buffer = NULL;
  int auto_app;

  if (!cardman->gpgagent)
    return;  /* No support for GPGME_PROTOCOL_ASSUAN.  */

  /* Start the ticker if not yet done.  */
  start_ticker (cardman);
  if (!cardman->in_card_reload)
    {
      cardman->in_card_reload++;

      update_info_visibility (cardman);

      cardman->cardtype = G_TYPE_NONE;
      cardman->cardtypename = "Unknown";

      /* The first thing we need to do is to issue the SERIALNO
         command; this makes sure that scdaemon initalizes the card if
         that has not yet been done.  */
      command = "SCD SERIALNO";
      if (cardman->app_selector
          && (gtk_combo_box_get_active
              (GTK_COMBO_BOX (cardman->app_selector)) > 0)
          && (application = gtk_combo_box_get_active_text
              (GTK_COMBO_BOX (cardman->app_selector))))
        {
          command_buf = g_strdup_printf ("%s %s", command, application);
          command = command_buf;
          auto_app = 0;
        }
      else
        auto_app = 1;
      err = gpgme_op_assuan_transact_ext (cardman->gpgagent,
                                          command,
                                          scd_data_cb, NULL,
                                          scd_inq_cb, NULL,
                                          scd_status_cb, cardman, &operr);
      if (!err)
        {
          err = operr;
          if (!auto_app
              && gpg_err_source (err) == GPG_ERR_SOURCE_SCD
              && gpg_err_code (err) == GPG_ERR_CONFLICT)
            {
              /* Not in auto select mode and the scdaemon told us
                 about a conflicting use.  We now do a restart and try
                 again to display an application selection conflict
                 error only if it is not due to our own connection to
                 the scdaemon.  */
              if (!gpgme_op_assuan_transact_ext (cardman->gpgagent,
                                                 "SCD RESTART",
                                                 NULL, NULL, NULL, NULL,
                                                 NULL, NULL, &operr)
                  && !operr)
                {
                  err = gpgme_op_assuan_transact_ext (cardman->gpgagent,
                                                      command,
                                                      scd_data_cb, NULL,
                                                      scd_inq_cb, NULL,
                                                      scd_status_cb, cardman,
                                                      &operr);
                  if (!err)
                    err = operr;
                }
            }
        }


      if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
          || gpg_err_code (err) == GPG_ERR_CARD_REMOVED)
        {
          err_desc = _("No card found.");
        }
      else if (gpg_err_source (err) == GPG_ERR_SOURCE_SCD
               && gpg_err_code (err) == GPG_ERR_CONFLICT)
        {
          err_desc = auto_app
            ? _("The selected card application is currently not available.")
            : _("Another process is using a different card application "
                "than the selected one.\n\n"
                "You may change the application selection mode to "
                "\"Auto\" to select the active application.");
        }
      else if (!auto_app
               && gpg_err_source (err) == GPG_ERR_SOURCE_SCD
               && gpg_err_code (err) == GPG_ERR_NOT_SUPPORTED)
        {
          err_desc =
            _("The selected card application is not available.");
        }
      else if (err)
        {
          g_debug ("assuan command `%s' failed: %s <%s>\n",
                   command, gpg_strerror (err), gpg_strsource (err));
          if (!gpgme_op_assuan_transact_ext (cardman->gpgagent,
                                             "SCD SERIALNO undefined",
                                             NULL, NULL, NULL, NULL,
                                             NULL, NULL, &operr) && !operr)
            err = 0;
          else
            {
              err_desc = _("Error accessing the card.");
              statusbar_update (cardman, _("Error accessing card"));
            }
        }
      g_free (command_buf);


      if (!err)
        {
          /* Get the event counter to avoid a duplicate reload due to
             the ticker.  */
          gpgme_op_assuan_transact_ext (cardman->gpgagent,
                                        "GETEVENTCOUNTER",
                                        NULL, NULL,
                                        NULL, NULL,
                                        scd_status_cb, cardman, NULL);

          /* Now we need to get the APPTYPE of the card so that the
             correct GpaCM* object can can act on the data.  */
          command = "SCD GETATTR APPTYPE";
          err = gpgme_op_assuan_transact_ext (cardman->gpgagent,
                                              command,
                                              scd_data_cb, NULL,
                                              scd_inq_cb, NULL,
                                              scd_status_cb, cardman, &operr);
          if (!err)
            err = operr;

          if (gpg_err_code (err) == GPG_ERR_CARD_NOT_PRESENT
              || gpg_err_code (err) == GPG_ERR_CARD_REMOVED)
            statusbar_update (cardman, _("No card"));
          else if (err)
            {
              g_debug ("assuan command `%s' failed: %s <%s>\n",
                       command, gpg_strerror (err), gpg_strsource (err));
              statusbar_update (cardman, _("Error accessing card"));
            }
        }


      update_card_widget (cardman, err_desc);
      g_free (err_desc_buffer);
      err_desc_buffer = NULL;
      err_desc = NULL;
      update_title (cardman);

      update_info_visibility (cardman);
      /* We decrement our lock using a idle handler with lo priority.
         This gives us a better chance not to do a reload a second
         time on behalf of the file watcher or ticker.  */
      g_object_ref (cardman);
      g_idle_add_full (G_PRIORITY_LOW,
                       card_reload_finish_idle_cb, cardman, NULL);
    }
}
Пример #15
0
/* Return a pointer to a string containing a description of the error
   source in the error value ERR.  */
const char *
gcry_strsource (gcry_error_t err)
{
  return gpg_strsource (err);
}
Пример #16
0
int
main (int argc, char *argv[])
{
  int i = 1;
  int listmode = 0;
  const char *source_sym;
  const char *error_sym;
  gpg_error_t err;

#ifndef GPG_ERR_INITIALIZED
  gpg_err_init ();
#endif

  i18n_init ();


  if (argc == 1)
    {
      fprintf (stderr, _("Usage: %s GPG-ERROR [...]\n"), 
               strrchr (argv[0],'/')? (strrchr (argv[0], '/')+1): argv[0]);
      exit (1);
    }
  else if (argc == 2 && !strcmp (argv[1], "--version"))
    {
      fputs ("gpg-error (" PACKAGE_NAME ") " PACKAGE_VERSION "\n", stdout);
      exit (0);
    }
  else if (argc == 2 && !strcmp (argv[1], "--list"))
    {
      listmode = 1;
    }


  if (listmode)
    {
      for (i=0; i <  GPG_ERR_SOURCE_DIM; i++)
        {
          /* We use error code 1 because gpg_err_make requires a
             non-zero error code. */
          err = gpg_err_make (i, 1);
          err -= 1;
	  source_sym = gpg_strsource_sym (err);
          if (source_sym)
            printf ("%u = (%u, -) = (%s, -) = (%s, -)\n",
                    err, gpg_err_source (err),
                    source_sym, gpg_strsource (err));
        }
      for (i=0; i <  GPG_ERR_CODE_DIM; i++)
        {
          err = gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, i);
	  error_sym = gpg_strerror_sym (err);
          if (error_sym)
            printf ("%u = (-, %u) = (-, %s) = (-, %s)\n",
                    err, gpg_err_code (err),
                    error_sym, gpg_strerror (err));
        }

      i = argc;  /* Don't run the usual stuff.  */
    }
  while (i < argc)
    {
      if (get_err_from_number (argv[i], &err)
	  || get_err_from_symbol (argv[i], &err)
	  || get_err_from_str (argv[i], &err))
	{
	  source_sym = gpg_strsource_sym (err);
	  error_sym = gpg_strerror_sym (err);
	  
	  printf ("%u = (%u, %u) = (%s, %s) = (%s, %s)\n",
		  err, gpg_err_source (err), gpg_err_code (err),
		  source_sym ? source_sym : "-", error_sym ? error_sym : "-",
		  gpg_strsource (err), gpg_strerror (err));
	}
      else
	fprintf (stderr, _("%s: warning: could not recognize %s\n"),
		 argv[0], argv[i]);
      i++;
    }

  exit (0);
}
Пример #17
0
int
main (int argc, char *argv[])
{
  int i = 1;
  int listmode = 0;
  const char *source_sym;
  const char *error_sym;
  gpg_error_t err;

  gpgrt_init ();
  i18n_init ();

  if (argc == 1)
    {
      fprintf (stderr, _("Usage: %s GPG-ERROR [...]\n"),
               strrchr (argv[0],'/')? (strrchr (argv[0], '/')+1): argv[0]);
      exit (1);
    }
  else if (argc == 2 && !strcmp (argv[1], "--version"))
    {
      fputs ("gpg-error (" PACKAGE_NAME ") " PACKAGE_VERSION "\n", stdout);
      exit (0);
    }
  else if (argc == 2 && !strcmp (argv[1], "--help"))
    {
      fputs ("gpg-error (" PACKAGE_NAME ") " PACKAGE_VERSION "\n", stdout);
      fputs ("Options:\n"
             "  --version      Print version\n"
             "  --lib-version  Print library version\n"
             "  --help         Print this help\n"
             "  --list         Print all error codes\n"
             "  --defines      Print all error codes as #define lines\n"
             , stdout);
      exit (0);
    }
  else if (argc == 2 && !strcmp (argv[1], "--lib-version"))
    {
      printf ("Version from header: %s (0x%06x)\n",
              GPG_ERROR_VERSION, GPG_ERROR_VERSION_NUMBER);
      printf ("Version from binary: %s\n", gpg_error_check_version (NULL));
      printf ("Copyright blurb ...:%s\n", gpg_error_check_version ("\x01\x01"));
      exit (0);
    }
  else if (argc == 2 && !strcmp (argv[1], "--list"))
    {
      listmode = 1;
    }
  else if (argc == 2 && !strcmp (argv[1], "--defines"))
    {
      listmode = 2;
    }


  if (listmode == 1)
    {
      for (i=0; i <  GPG_ERR_SOURCE_DIM; i++)
        {
          /* We use error code 1 because gpg_err_make requires a
             non-zero error code. */
          err = gpg_err_make (i, 1);
          err -= 1;
	  source_sym = gpg_strsource_sym (err);
          if (source_sym)
            printf ("%u = (%u, -) = (%s, -) = (%s, -)\n",
                    err, gpg_err_source (err),
                    source_sym, gpg_strsource (err));
        }
      for (i=0; i <  GPG_ERR_CODE_DIM; i++)
        {
          err = gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, i);
	  error_sym = gpg_strerror_sym (err);
          if (error_sym)
            printf ("%u = (-, %u) = (-, %s) = (-, %s)\n",
                    err, gpg_err_code (err),
                    error_sym, gpg_strerror (err));
        }
    }
  else if (listmode == 2)
    {
      int n, nmax;

      for (i=0, nmax=0; i <  GPG_ERR_SOURCE_DIM; i++)
        {
          err = gpg_err_make (i, 1);
	  source_sym = gpg_strsource_sym (err);
          if (source_sym)
            {
              n = strlen (source_sym);
              if (n > nmax)
                nmax = n;
            }
        }
      for (i=0; i <  GPG_ERR_SOURCE_DIM; i++)
        {
          err = gpg_err_make (i, 1);
	  source_sym = gpg_strsource_sym (err);
          if (source_sym)
            printf ("#define %-*s %3u\n", nmax,source_sym,gpg_err_source (err));
        }


      for (i=0, nmax = 0; i <  GPG_ERR_CODE_DIM; i++)
        {
          err = gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, i);
	  error_sym = gpg_strerror_sym (err);
          if (error_sym)
            {
              n = strlen (error_sym);
              if (n > nmax)
                nmax = n;
            }
        }
      for (i=0; i <  GPG_ERR_CODE_DIM; i++)
        {
          err = gpg_err_make (GPG_ERR_SOURCE_UNKNOWN, i);
	  error_sym = gpg_strerror_sym (err);
          if (error_sym)
            printf ("#define %-*s %5u\n", nmax, error_sym, gpg_err_code (err));
        }
    }
  else /* Standard mode.  */
    {
      while (i < argc)
        {
          if (get_err_from_number (argv[i], &err)
              || get_err_from_symbol (argv[i], &err)
              || get_err_from_str (argv[i], &err))
            {
              source_sym = gpg_strsource_sym (err);
              error_sym = gpg_strerror_sym (err);

              printf ("%u = (%u, %u) = (%s, %s) = (%s, %s)\n",
                      err, gpg_err_source (err), gpg_err_code (err),
                      source_sym ? source_sym : "-", error_sym ? error_sym:"-",
                      gpg_strsource (err), gpg_strerror (err));
            }
          else
            fprintf (stderr, _("%s: warning: could not recognize %s\n"),
                     argv[0], argv[i]);
          i++;
        }
    }

  exit (0);
}
Пример #18
0
/* Call this to acknowledge the current command.  */
gpg_error_t
assuan_process_done (assuan_context_t ctx, gpg_error_t rc)
{
  if (!ctx->in_command)
    return _assuan_error (ctx, GPG_ERR_ASS_GENERAL);

  ctx->in_command = 0;

  /* Check for data write errors.  */
  if (ctx->outbound.data.fp)
    {
      /* Flush the data lines.  */
      fclose (ctx->outbound.data.fp);
      ctx->outbound.data.fp = NULL;
      if (!rc && ctx->outbound.data.error)
	rc = ctx->outbound.data.error;
    }
  else
    {
      /* Flush any data send without using the data FP.  */
      assuan_send_data (ctx, NULL, 0);
      if (!rc && ctx->outbound.data.error)
	rc = ctx->outbound.data.error;
    }

  /* Error handling.  */
  if (!rc)
    {
      if (ctx->process_complete)
	{
	  /* No error checking because the peer may have already
	     disconnect. */
	  assuan_write_line (ctx, "OK closing connection");
	  ctx->finish_handler (ctx);
	}
      else
	rc = assuan_write_line (ctx, ctx->okay_line ? ctx->okay_line : "OK");
    }
  else
    {
      char errline[300];
      const char *text = ctx->err_no == rc ? ctx->err_str : NULL;
      char ebuf[50];

      gpg_strerror_r (rc, ebuf, sizeof (ebuf));
      sprintf (errline, "ERR %d %.50s <%.30s>%s%.100s",
	       rc, ebuf, gpg_strsource (rc),
	       text? " - ":"", text?text:"");

      rc = assuan_write_line (ctx, errline);
    }

  if (ctx->post_cmd_notify_fnc)
    ctx->post_cmd_notify_fnc (ctx, rc);

  ctx->flags.confidential = 0;
  if (ctx->okay_line)
    {
      _assuan_free (ctx, ctx->okay_line);
      ctx->okay_line = NULL;
    }

  return rc;
}
Пример #19
0
/* Call GPG to decrypt a block of data.


 */
gpg_error_t
gpg_decrypt_blob (ctrl_t ctrl, const void *ciph, size_t ciphlen,
                  void **r_plain, size_t *r_plainlen)
{
  gpg_error_t err;
  assuan_context_t ctx = NULL;
  int outbound_fds[2] = { -1, -1 };
  int inbound_fds[2]  = { -1, -1 };
  npth_t writer_thread = (npth_t)0;
  npth_t reader_thread = (npth_t)0;
  gpg_error_t writer_err, reader_err;
  membuf_t reader_mb;
  int ret;

  *r_plain = NULL;
  *r_plainlen = 0;

  /* Init the memory buffer to receive the encrypted stuff.  */
  init_membuf_secure (&reader_mb, 1024);

  /* Create two pipes.  */
  err = gnupg_create_outbound_pipe (outbound_fds);
  if (!err)
    err = gnupg_create_inbound_pipe (inbound_fds);
  if (err)
    {
      log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
      goto leave;
    }

  /* Start GPG and send the INPUT and OUTPUT commands.  */
  err = start_gpg (ctrl, outbound_fds[0], inbound_fds[1], &ctx);
  if (err)
    goto leave;
  close (outbound_fds[0]); outbound_fds[0] = -1;
  close (inbound_fds[1]); inbound_fds[1] = -1;

  /* Start a writer thread to feed the INPUT command of the server.  */
  err = start_writer (outbound_fds[1], ciph, ciphlen,
                      &writer_thread, &writer_err);
  if (err)
    return err;
  outbound_fds[1] = -1;  /* The thread owns the FD now.  */

  /* Start a reader thread to eat from the OUTPUT command of the
     server.  */
  err = start_reader (inbound_fds[0], &reader_mb,
                      &reader_thread, &reader_err);
  if (err)
    return err;
  outbound_fds[0] = -1;  /* The thread owns the FD now.  */

  /* Run the decryption.  */
  err = assuan_transact (ctx, "DECRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
  if (err)
    {
      log_error ("the engine's DECRYPT command failed: %s <%s>\n",
                 gpg_strerror (err), gpg_strsource (err));
      goto leave;
    }

  /* Wait for reader and return the data.  */
  ret = npth_join (reader_thread, NULL);
  if (ret)
    {
      err = gpg_error_from_errno (ret);
      log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
      goto leave;
    }
  memset (&reader_thread, '\0', sizeof (reader_thread));
  if (reader_err)
    {
      err = reader_err;
      log_error ("read error in reader thread: %s\n", gpg_strerror (err));
      goto leave;
    }

  /* Wait for the writer to catch a writer error.  */
  ret = npth_join (writer_thread, NULL);
  if (ret)
    {
      err = gpg_error_from_errno (ret);
      log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
      goto leave;
    }
  memset (&writer_thread, '\0', sizeof (writer_thread));
  if (writer_err)
    {
      err = writer_err;
      log_error ("write error in writer thread: %s\n", gpg_strerror (err));
      goto leave;
    }

  /* Return the data.  */
  *r_plain = get_membuf (&reader_mb, r_plainlen);
  if (!*r_plain)
    {
      err = gpg_error_from_syserror ();
      log_error ("error while storing the data in the reader thread: %s\n",
                 gpg_strerror (err));
      goto leave;
    }

 leave:
  if (reader_thread)
    npth_detach (reader_thread);
  if (writer_thread)
    npth_detach (writer_thread);
  if (outbound_fds[0] != -1)
    close (outbound_fds[0]);
  if (outbound_fds[1] != -1)
    close (outbound_fds[1]);
  if (inbound_fds[0] != -1)
    close (inbound_fds[0]);
  if (inbound_fds[1] != -1)
    close (inbound_fds[1]);
  release_gpg (ctx);
  xfree (get_membuf (&reader_mb, NULL));
  return err;
}
Пример #20
0
/* Call GPG to encrypt a block of data.


 */
gpg_error_t
gpg_encrypt_blob (ctrl_t ctrl, const void *plain, size_t plainlen,
                  strlist_t keys, void **r_ciph, size_t *r_ciphlen)
{
  gpg_error_t err;
  assuan_context_t ctx = NULL;
  int outbound_fds[2] = { -1, -1 };
  int inbound_fds[2]  = { -1, -1 };
  npth_t writer_thread = (npth_t)0;
  npth_t reader_thread = (npth_t)0;
  gpg_error_t writer_err, reader_err;
  membuf_t reader_mb;
  char line[ASSUAN_LINELENGTH];
  strlist_t sl;
  int ret;

  *r_ciph = NULL;
  *r_ciphlen = 0;

  /* Init the memory buffer to receive the encrypted stuff.  */
  init_membuf (&reader_mb, 4096);

  /* Create two pipes.  */
  err = gnupg_create_outbound_pipe (outbound_fds);
  if (!err)
    err = gnupg_create_inbound_pipe (inbound_fds);
  if (err)
    {
      log_error (_("error creating a pipe: %s\n"), gpg_strerror (err));
      goto leave;
    }

  /* Start GPG and send the INPUT and OUTPUT commands.  */
  err = start_gpg (ctrl, outbound_fds[0], inbound_fds[1], &ctx);
  if (err)
    goto leave;
  close (outbound_fds[0]); outbound_fds[0] = -1;
  close (inbound_fds[1]); inbound_fds[1] = -1;

  /* Start a writer thread to feed the INPUT command of the server.  */
  err = start_writer (outbound_fds[1], plain, plainlen,
                      &writer_thread, &writer_err);
  if (err)
    return err;
  outbound_fds[1] = -1;  /* The thread owns the FD now.  */

  /* Start a reader thread to eat from the OUTPUT command of the
     server.  */
  err = start_reader (inbound_fds[0], &reader_mb,
                      &reader_thread, &reader_err);
  if (err)
    return err;
  outbound_fds[0] = -1;  /* The thread owns the FD now.  */

  /* Run the encryption.  */
  for (sl = keys; sl; sl = sl->next)
    {
      snprintf (line, sizeof line, "RECIPIENT -- %s", sl->d);
      err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
      if (err)
        {
          log_error ("the engine's RECIPIENT command failed: %s <%s>\n",
                 gpg_strerror (err), gpg_strsource (err));
          goto leave;
        }
    }

  err = assuan_transact (ctx, "ENCRYPT", NULL, NULL, NULL, NULL, NULL, NULL);
  if (err)
    {
      log_error ("the engine's ENCRYPT command failed: %s <%s>\n",
                 gpg_strerror (err), gpg_strsource (err));
      goto leave;
    }

  /* Wait for reader and return the data.  */
  ret = npth_join (reader_thread, NULL);
  if (ret)
    {
      err = gpg_error_from_errno (ret);
      log_error ("waiting for reader thread failed: %s\n", gpg_strerror (err));
      goto leave;
    }
  /* FIXME: Not really valid, as npth_t is an opaque type.  */
  memset (&reader_thread, '\0', sizeof (reader_thread));
  if (reader_err)
    {
      err = reader_err;
      log_error ("read error in reader thread: %s\n", gpg_strerror (err));
      goto leave;
    }

  /* Wait for the writer to catch  a writer error.  */
  ret = npth_join (writer_thread, NULL);
  if (ret)
    {
      err = gpg_error_from_errno (ret);
      log_error ("waiting for writer thread failed: %s\n", gpg_strerror (err));
      goto leave;
    }
  memset (&writer_thread, '\0', sizeof (writer_thread));
  if (writer_err)
    {
      err = writer_err;
      log_error ("write error in writer thread: %s\n", gpg_strerror (err));
      goto leave;
    }

  /* Return the data.  */
  *r_ciph = get_membuf (&reader_mb, r_ciphlen);
  if (!*r_ciph)
    {
      err = gpg_error_from_syserror ();
      log_error ("error while storing the data in the reader thread: %s\n",
                 gpg_strerror (err));
      goto leave;
    }

 leave:
  /* FIXME: Not valid, as npth_t is an opaque type.  */
  if (reader_thread)
    npth_detach (reader_thread);
  if (writer_thread)
    npth_detach (writer_thread);
  if (outbound_fds[0] != -1)
    close (outbound_fds[0]);
  if (outbound_fds[1] != -1)
    close (outbound_fds[1]);
  if (inbound_fds[0] != -1)
    close (inbound_fds[0]);
  if (inbound_fds[1] != -1)
    close (inbound_fds[1]);
  release_gpg (ctx);
  xfree (get_membuf (&reader_mb, NULL));
  return err;
}
Пример #21
0
int
main (int argc, char **argv)
{
  gpg_error_t err;
  unsigned char *fpr;
  size_t fpr_len;
  char *url;
  void *key;
  size_t keylen;
  char const *name;

  if (argc)
    {
      argc--;
      argv++;
    }

  if (!argc)
    name = "simon.josefsson.org";
  else if (argc == 1)
    name = *argv;
  else
    {
      fputs ("usage: t-dns-cert [name]\n", stderr);
      return 1;
    }

  printf ("CERT lookup on '%s'\n", name);

  err = get_dns_cert (name, DNS_CERTTYPE_ANY, &key, &keylen,
                      &fpr, &fpr_len, &url);
  if (err)
    printf ("get_dns_cert failed: %s <%s>\n",
            gpg_strerror (err), gpg_strsource (err));
  else if (key)
    {
      printf ("Key found (%u bytes)\n", (unsigned int)keylen);
    }
  else
    {
      if (fpr)
	{
	  int i;

	  printf ("Fingerprint found (%d bytes): ", (int)fpr_len);
	  for (i = 0; i < fpr_len; i++)
	    printf ("%02X", fpr[i]);
	  putchar ('\n');
	}
      else
	printf ("No fingerprint found\n");

      if (url)
	printf ("URL found: %s\n", url);
      else
	printf ("No URL found\n");

    }

  xfree (key);
  xfree (fpr);
  xfree (url);

  return 0;
}
Пример #22
0
Файл: error.c Проект: gpg/gsti
/* Return a pointer to a string containing a description of the error
   source in the error value ERR.  */
const char *
gsti_strsource (gsti_error_t err)
{
  return gpg_strsource (err);
}