Beispiel #1
0
static gpgme_error_t
_gpgme_op_import_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t keydata)
{
  gpgme_error_t err;
  void *hook;
  op_data_t opd;

  err = _gpgme_op_reset (ctx, synchronous);
  if (err)
    return err;

  err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook,
			       sizeof (*opd), release_op_data);
  opd = hook;
  if (err)
    return err;
  opd->lastp = &opd->result.imports;

  if (!keydata)
    return gpg_error (GPG_ERR_NO_DATA);

  _gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx);

  return _gpgme_engine_op_import (ctx->engine, keydata, NULL);
}
Beispiel #2
0
gpgme_error_t
gpgme_op_trustlist_start (gpgme_ctx_t ctx, const char *pattern, int max_level)
{
  gpgme_error_t err = 0;
  void *hook;
  op_data_t opd;

  if (!pattern || !*pattern)
    return gpg_error (GPG_ERR_INV_VALUE);

  err = _gpgme_op_reset (ctx, 2);
  if (err)
    return err;

  err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook,
			       sizeof (*opd), NULL);
  opd = hook;
  if (err)
    return err;

  _gpgme_engine_set_status_handler (ctx->engine,
				    trustlist_status_handler, ctx);
  err = _gpgme_engine_set_colon_line_handler (ctx->engine,
					      trustlist_colon_handler, ctx);
  if (err)
    return err;

  return _gpgme_engine_op_trustlist (ctx->engine, pattern);
}
Beispiel #3
0
static gpgme_error_t
vfs_start (gpgme_ctx_t ctx, int synchronous,
	   const char *command,
	   gpgme_assuan_data_cb_t data_cb,
	   void *data_cb_value,
	   gpgme_assuan_inquire_cb_t inq_cb,
	   void *inq_cb_value,
	   gpgme_assuan_status_cb_t status_cb,
	   void *status_cb_value)
{
  gpgme_error_t err;
  void *hook;
  op_data_t opd;

  if (!command || !*command)
    return gpg_error (GPG_ERR_INV_VALUE);

  /* The flag value 256 is used to suppress an engine reset.  This is
     required to keep the connection running.  */
  err = _gpgme_op_reset (ctx, ((synchronous & 255) | 256));
  if (err)
    return err;

  err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, sizeof (*opd),
			       NULL);
  opd = hook;
  if (err)
    return err;

  return _gpgme_engine_op_assuan_transact (ctx->engine, command,
					   data_cb, data_cb_value,
					   inq_cb, inq_cb_value,
					   status_cb, status_cb_value);
}
Beispiel #4
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;
}
Beispiel #5
0
gpgme_error_t
gpgme_op_trustlist_start (gpgme_ctx_t ctx, const char *pattern, int max_level)
{
  gpgme_error_t err = 0;
  void *hook;
  op_data_t opd;

  TRACE_BEG2 (DEBUG_CTX, "gpgme_op_trustlist_start", ctx,
	      "pattern=%s, max_level=%i", pattern, max_level);

  if (!pattern || !*pattern)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  err = _gpgme_op_reset (ctx, 2);
  if (err)
    return TRACE_ERR (err);

  err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook,
			       sizeof (*opd), NULL);
  opd = hook;
  if (err)
    return TRACE_ERR (err);

  _gpgme_engine_set_status_handler (ctx->engine,
				    trustlist_status_handler, ctx);
  err = _gpgme_engine_set_colon_line_handler (ctx->engine,
					      trustlist_colon_handler, ctx);
  if (err)
    return TRACE_ERR (err);

  err = _gpgme_engine_op_trustlist (ctx->engine, pattern);
  return TRACE_ERR (err);
}
Beispiel #6
0
static gpgme_error_t
import_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
  gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
  gpgme_error_t err;
  void *hook;
  op_data_t opd;

  err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook, -1, NULL);
  opd = hook;
  if (err)
    return err;

  switch (code)
    {
    case GPGME_STATUS_IMPORT_OK:
    case GPGME_STATUS_IMPORT_PROBLEM:
      err = parse_import (args, opd->lastp,
			  code == GPGME_STATUS_IMPORT_OK ? 0 : 1);
      if (err)
	return err;

      opd->lastp = &(*opd->lastp)->next;
      break;

    case GPGME_STATUS_IMPORT_RES:
      err = parse_import_res (args, &opd->result);
      break;

    default:
      break;
    }
  return 0;
}
Beispiel #7
0
static gpgme_error_t
genkey_start(gpgme_ctx_t ctx, int synchronous, const char *parms,
             gpgme_data_t pubkey, gpgme_data_t seckey)
{
    gpgme_error_t err;
    void *hook;
    op_data_t opd;
    err = _gpgme_op_reset(ctx, synchronous);
    if(err)
        return err;

    err = _gpgme_op_data_lookup(ctx, OPDATA_GENKEY, &hook,
                                sizeof(*opd), release_op_data);
    opd = hook;
    if(err)
        return err;

    err = get_key_parameter(parms, &opd->key_parameter);
    if(err)
        return err;

    _gpgme_engine_set_status_handler(ctx->engine, genkey_status_handler, ctx);

    return _gpgme_engine_op_genkey(ctx->engine, opd->key_parameter,
                                   ctx->use_armor, pubkey, seckey);
}
Beispiel #8
0
gpgme_error_t
gpgme_op_trustlist_next (gpgme_ctx_t ctx, gpgme_trust_item_t *r_item)
{
  gpgme_error_t err;
  void *hook;
  op_data_t opd;
  struct trust_queue_item_s *q;

  TRACE_BEG (DEBUG_CTX, "gpgme_op_trustlist_next", ctx);

  if (!r_item)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
  *r_item = NULL;
  if (!ctx)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
  opd = hook;
  if (err)
    return TRACE_ERR (err);
  if (opd == NULL)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (!opd->trust_queue)
    {
      err = _gpgme_wait_on_condition (ctx, &opd->trust_cond, NULL);
      if (err)
	return TRACE_ERR (err);
      if (!opd->trust_cond)
	return TRACE_ERR (gpg_error (GPG_ERR_EOF));
      opd->trust_cond = 0; 
      assert (opd->trust_queue);
    }
  q = opd->trust_queue;
  opd->trust_queue = q->next;

  *r_item = q->item;
  free (q);
  if ((*r_item)->type == 1)
    {
      TRACE_SUC5 ("trust_item=%p: %s: owner trust %s with level %i "
		  "and validity 0x%x", *r_item, (*r_item)->keyid,
		  (*r_item)->owner_trust, (*r_item)->level,
		  (*r_item)->validity);
    }
  else if ((*r_item)->type == 2)
    {
      TRACE_SUC5 ("trust_item=%p: %s: UID %s with level %i "
		  "and validity 0x%x", *r_item, (*r_item)->keyid,
		  (*r_item)->name, (*r_item)->level, (*r_item)->validity);
    }
  else
    {
      TRACE_SUC5 ("trust_item=%p: %s: unknown type %i with level %i "
		  "and validity 0x%x", *r_item, (*r_item)->keyid,
		  (*r_item)->type, (*r_item)->level, (*r_item)->validity);
    }
  return 0;
}
Beispiel #9
0
gpgme_error_t
_gpgme_op_verify_init_result (gpgme_ctx_t ctx)
{
  void *hook;
  op_data_t opd;

  return _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook,
				sizeof (*opd), release_op_data);
}
Beispiel #10
0
gpgme_verify_result_t
gpgme_op_verify_result (gpgme_ctx_t ctx)
{
  void *hook;
  op_data_t opd;
  gpgme_error_t err;

  TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_result", ctx);
  err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
  opd = hook;
  if (err || !opd)
    {
      TRACE_SUC0 ("result=(null)");
      return NULL;
    }

  if (_gpgme_debug_trace ())
    {
      gpgme_signature_t sig = opd->result.signatures;
      int i = 0;

      while (sig)
	{
	  TRACE_LOG4 ("sig[%i] = fpr %s, summary 0x%x, status %s",
		      i, sig->fpr, sig->summary, gpg_strerror (sig->status));
	  TRACE_LOG6 ("sig[%i] = timestamps 0x%x/0x%x flags:%s%s%s",
		      i, sig->timestamp, sig->exp_timestamp,
		      sig->wrong_key_usage ? "wrong key usage" : "",
		      sig->pka_trust == 1 ? "pka bad"
		      : (sig->pka_trust == 2 ? "pka_okay" : "pka RFU"),
		      sig->chain_model ? "chain model" : "");
	  TRACE_LOG5 ("sig[%i] = validity 0x%x (%s), algos %s/%s",
		      i, sig->validity, gpg_strerror (sig->validity_reason),
		      gpgme_pubkey_algo_name (sig->pubkey_algo),
		      gpgme_hash_algo_name (sig->hash_algo));
	  if (sig->pka_address)
	    {
	      TRACE_LOG2 ("sig[%i] = PKA address %s", i, sig->pka_address);
	    }
	  if (sig->notations)
	    {
	      TRACE_LOG1 ("sig[%i] = has notations (not shown)", i);
	    }	  
	  sig = sig->next;
	  i++;
	}
    }

  TRACE_SUC1 ("result=%p", &opd->result);
  return &opd->result;
}
Beispiel #11
0
gpgme_import_result_t
gpgme_op_import_result (gpgme_ctx_t ctx)
{
  void *hook;
  op_data_t opd;
  gpgme_error_t err;

  TRACE_BEG (DEBUG_CTX, "gpgme_op_import_result", ctx);

  err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook, -1, NULL);
  opd = hook;
  if (err || !opd)
    {
      TRACE_SUC0 ("result=(null)");
      return NULL;
    }

  
  if (_gpgme_debug_trace ())
    {
      gpgme_import_status_t impstat;
      int i;

      TRACE_LOG5 ("%i considered, %i no UID, %i imported, %i imported RSA, "
		  "%i unchanged", opd->result.considered,
		  opd->result.no_user_id, opd->result.imported,
		  opd->result.imported_rsa, opd->result.unchanged);
      TRACE_LOG4 ("%i new UIDs, %i new sub keys, %i new signatures, "
		  "%i new revocations", opd->result.new_user_ids,
		  opd->result.new_sub_keys, opd->result.new_signatures,
		  opd->result.new_revocations);
      TRACE_LOG3 ("%i secret keys, %i imported, %i unchanged",
		  opd->result.secret_read, opd->result.secret_imported,
		  opd->result.secret_unchanged);
      TRACE_LOG2 ("%i skipped new keys, %i not imported",
		  opd->result.skipped_new_keys, opd->result.not_imported);

      impstat = opd->result.imports;
      i = 0;
      while (impstat)
	{
	  TRACE_LOG4 ("import[%i] for %s = 0x%x (%s)",
		      i, impstat->fpr, impstat->status, impstat->result);
	  impstat = impstat->next;
	  i++;
	}
    }

  TRACE_SUC1 ("result=%p", &opd->result);
  return &opd->result;
}
Beispiel #12
0
gpgme_verify_result_t
gpgme_op_verify_result(gpgme_ctx_t ctx)
{
    void *hook;
    op_data_t opd;
    gpgme_error_t err;

    err = _gpgme_op_data_lookup(ctx, OPDATA_VERIFY, &hook, -1, NULL);
    opd = hook;
    if(err || !opd)
        return NULL;

    return &opd->result;
}
Beispiel #13
0
gpgme_decrypt_result_t
gpgme_op_decrypt_result (gpgme_ctx_t ctx)
{
  void *hook;
  op_data_t opd;
  gpgme_error_t err;

  err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
  opd = hook;
  if (err || !opd)
    return NULL;

  return &opd->result;
}
Beispiel #14
0
static gpgme_error_t
genkey_status_handler(void *priv, gpgme_status_code_t code, char *args)
{
    gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
    gpgme_error_t err;
    void *hook;
    op_data_t opd;

    /* Pipe the status code through the progress status handler.  */
    err = _gpgme_progress_status_handler(ctx, code, args);
    if(err)
        return err;

    err = _gpgme_op_data_lookup(ctx, OPDATA_GENKEY, &hook, -1, NULL);
    opd = hook;
    if(err)
        return err;

    switch(code)
    {
        case GPGME_STATUS_KEY_CREATED:
            if(args && *args)
            {
                if(*args == 'B' || *args == 'P')
                    opd->result.primary = 1;
                if(*args == 'B' || *args == 'S')
                    opd->result.sub = 1;
                if(args[1] == ' ')
                {
                    if(opd->result.fpr)
                        free(opd->result.fpr);
                    opd->result.fpr = strdup(&args[2]);
                    if(!opd->result.fpr)
                        return gpg_error_from_errno(errno);
                }
            }
            break;

        case GPGME_STATUS_EOF:
            /* FIXME: Should return some more useful error value.  */
            if(!opd->result.primary && !opd->result.sub)
                return gpg_error(GPG_ERR_GENERAL);
            break;

        default:
            break;
    }
    return 0;
}
Beispiel #15
0
gpgme_error_t
_gpgme_op_decrypt_init_result (gpgme_ctx_t ctx)
{
  gpgme_error_t err;
  void *hook;
  op_data_t opd;

  err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook,
			       sizeof (*opd), release_op_data);
  opd = hook;
  if (err)
    return err;

  opd->last_recipient_p = &opd->result.recipients;
  return 0;
}
Beispiel #16
0
gpgme_vfs_mount_result_t
gpgme_op_vfs_mount_result (gpgme_ctx_t ctx)
{
  gpgme_error_t err;
  void *hook;
  op_data_t opd;

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

  return &opd->result;
}
Beispiel #17
0
gpgme_decrypt_result_t
gpgme_op_decrypt_result (gpgme_ctx_t ctx)
{
  void *hook;
  op_data_t opd;
  gpgme_error_t err;

  TRACE_BEG (DEBUG_CTX, "gpgme_op_decrypt_result", ctx);

  err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
  opd = hook;
  if (err || !opd)
    {
      TRACE_SUC0 ("result=(null)");
      return NULL;
    }

  if (_gpgme_debug_trace ())
    {
      gpgme_recipient_t rcp;

      if (opd->result.unsupported_algorithm)
	{
	  TRACE_LOG1 ("result: unsupported_algorithm: %s",
		      opd->result.unsupported_algorithm);
	}
      if (opd->result.wrong_key_usage)
	{
	  TRACE_LOG ("result: wrong key usage");
	}
      rcp = opd->result.recipients;
      while (rcp)
	{
	  TRACE_LOG3 ("result: recipient: keyid=%s, pubkey_algo=%i, "
		      "status=%s", rcp->keyid, rcp->pubkey_algo,
		      gpg_strerror (rcp->status));
	  rcp = rcp->next;
	}
      if (opd->result.file_name)
	{
	  TRACE_LOG1 ("result: original file name: %s", opd->result.file_name);
	}
    }

  TRACE_SUC1 ("result=%p", &opd->result);
  return &opd->result;
}
Beispiel #18
0
static gpgme_error_t
_gpgme_op_import_keys_start (gpgme_ctx_t ctx, int synchronous, 
                             gpgme_key_t *keys)
{
  gpgme_error_t err;
  void *hook;
  op_data_t opd;
  int idx, firstidx, nkeys;

  err = _gpgme_op_reset (ctx, synchronous);
  if (err)
    return err;

  err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook,
			       sizeof (*opd), release_op_data);
  opd = hook;
  if (err)
    return err;
  opd->lastp = &opd->result.imports;

  if (!keys)
    return gpg_error (GPG_ERR_NO_DATA);

  for (idx=nkeys=0, firstidx=-1; keys[idx]; idx++)
    {
      /* We only consider keys of the current protocol.  */
      if (keys[idx]->protocol != ctx->protocol)
        continue;
      if (firstidx == -1)
        firstidx = idx;
      /* If a key has been found using a different key listing mode,
         we bail out.  This makes the processing easier.  Fixme: To
         allow a mix of keys we would need to sort them by key listing
         mode and start two import operations one after the other.  */
      if (keys[idx]->keylist_mode != keys[firstidx]->keylist_mode)
        return gpg_error (GPG_ERR_CONFLICT);
      nkeys++;
    }
  if (!nkeys)
    return gpg_error (GPG_ERR_NO_DATA);

  _gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx);

  return _gpgme_engine_op_import (ctx->engine, NULL, keys);
}
Beispiel #19
0
gpgme_error_t
_gpgme_passphrase_command_handler (void *priv, gpgme_status_code_t code,
				   const char *key, int fd, int *processed)
{
  gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
  gpgme_error_t err;
  void *hook;
  op_data_t opd;

  assert (ctx->passphrase_cb);

  err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook,
			       sizeof (*opd), release_op_data);
  opd = hook;
  if (err)
    return err;

  if (code == GPGME_STATUS_GET_HIDDEN
      && (!strcmp (key, "passphrase.enter")
          || !strcmp (key, "passphrase.pin.ask")))
    {
      if (processed)
	*processed = 1;

      if (ctx->status_cb && opd->maxlen)
        err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN",
                              opd->maxlen);

      if (!err)
        err = ctx->passphrase_cb (ctx->passphrase_cb_value,
                                  opd->uid_hint, opd->passphrase_info,
                                  opd->bad_passphrase, fd);

      /* Reset bad passphrase flag, in case it is correct now.  */
      opd->bad_passphrase = 0;

      return err;
    }

  return 0;
}
Beispiel #20
0
void
_gpgme_op_trustlist_event_cb (void *data, gpgme_event_io_t type,
			      void *type_data)
{
  gpgme_ctx_t ctx = (gpgme_ctx_t) data;
  gpgme_error_t err;
  void *hook;
  op_data_t opd;
  gpgme_trust_item_t item = (gpgme_trust_item_t) type_data;
  struct trust_queue_item_s *q, *q2;

  assert (type == GPGME_EVENT_NEXT_TRUSTITEM);

  err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
  opd = hook;
  if (err)
    return;

  q = malloc (sizeof *q);
  if (!q)
    {
      gpgme_trust_item_unref (item);
      /* FIXME: GPGME_Out_Of_Core; */
      return;
    }
  q->item = item;
  q->next = NULL;
  /* FIXME: Use a tail pointer */
  q2 = opd->trust_queue;
  if (!q2)
    opd->trust_queue = q;
  else
    {
      while (q2->next)
	q2 = q2->next;
      q2->next = q;
    }
  /* FIXME: unlock queue */
  opd->trust_cond = 1;
}
Beispiel #21
0
static gpgme_error_t
_gpgme_vfs_mount_status_handler (void *priv, const char *code, const char *args)
{
  gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
  gpgme_error_t err;
  void *hook;
  op_data_t opd;

  err = _gpgme_op_data_lookup (ctx, OPDATA_VFS_MOUNT, &hook, -1, NULL);
  opd = hook;
  if (err)
    return err;

  if (! strcasecmp ("MOUNTPOINT", code))
    {
      if (opd->result.mount_dir)
	free (opd->result.mount_dir);
      opd->result.mount_dir = strdup (args);
    }

  return 0;
}
Beispiel #22
0
gpgme_error_t
gpgme_op_trustlist_next (gpgme_ctx_t ctx, gpgme_trust_item_t *r_item)
{
  gpgme_error_t err;
  void *hook;
  op_data_t opd;
  struct trust_queue_item_s *q;

  if (!r_item)
    return gpg_error (GPG_ERR_INV_VALUE);
  *r_item = NULL;
  if (!ctx)
    return gpg_error (GPG_ERR_INV_VALUE);

  err = _gpgme_op_data_lookup (ctx, OPDATA_TRUSTLIST, &hook, -1, NULL);
  opd = hook;
  if (err)
    return err;
  if (opd == NULL)
    return gpg_error (GPG_ERR_INV_VALUE);

  if (!opd->trust_queue)
    {
      err = _gpgme_wait_on_condition (ctx, &opd->trust_cond);
      if (err)
	return err;
      if (!opd->trust_cond)
	return gpg_error (GPG_ERR_EOF);
      opd->trust_cond = 0; 
      assert (opd->trust_queue);
    }
  q = opd->trust_queue;
  opd->trust_queue = q->next;

  *r_item = q->item;
  free (q);
  return 0;
}
Beispiel #23
0
static gpgme_error_t
opassuan_start (gpgme_ctx_t ctx, int synchronous,
                const char *command,
                gpgme_assuan_data_cb_t data_cb,
                void *data_cb_value,
                gpgme_assuan_inquire_cb_t inq_cb,
                void *inq_cb_value,
                gpgme_assuan_status_cb_t status_cb,
                void *status_cb_value)
{
  gpgme_error_t err;

  if (!command || !*command)
    return gpg_error (GPG_ERR_INV_VALUE);

  /* The flag value 256 is used to suppress an engine reset.  This is
     required to keep the connection running.  */
  err = _gpgme_op_reset (ctx, ((synchronous&255) | 256));
  if (err)
    return err;

  {
    /* LEGACY: Remove this when removing the deprecated result
       structure.  */
    void *hook;
    op_data_t opd;
    err = _gpgme_op_data_lookup (ctx, OPDATA_ASSUAN, &hook,
				 sizeof (*opd), NULL);
    if (err)
      return err;
  }

  return _gpgme_engine_op_assuan_transact (ctx->engine, command,
                                           data_cb, data_cb_value,
                                           inq_cb, inq_cb_value,
                                           status_cb, status_cb_value);
}
Beispiel #24
0
gpgme_error_t
_gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
				  char *args)
{
  gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
  gpgme_error_t err;
  void *hook;
  op_data_t opd;

  err = _gpgme_op_data_lookup (ctx, OPDATA_PASSPHRASE, &hook,
			       sizeof (*opd), release_op_data);
  opd = hook;
  if (err)
    return err;

  switch (code)
    {
    case GPGME_STATUS_INQUIRE_MAXLEN:
      free (opd->maxlen);
      if (!(opd->maxlen = strdup (args)))
        return gpg_error_from_syserror ();
      break;
    case GPGME_STATUS_USERID_HINT:
      if (opd->uid_hint)
	free (opd->uid_hint);
      if (!(opd->uid_hint = strdup (args)))
        return gpg_error_from_syserror ();
      break;

    case GPGME_STATUS_BAD_PASSPHRASE:
      opd->bad_passphrase++;
      opd->no_passphrase = 0;
      break;

    case GPGME_STATUS_GOOD_PASSPHRASE:
      opd->bad_passphrase = 0;
      opd->no_passphrase = 0;
      break;

    case GPGME_STATUS_NEED_PASSPHRASE:
    case GPGME_STATUS_NEED_PASSPHRASE_SYM:
    case GPGME_STATUS_NEED_PASSPHRASE_PIN:
      if (opd->passphrase_info)
	free (opd->passphrase_info);
      opd->passphrase_info = strdup (args);
      if (!opd->passphrase_info)
	return gpg_error_from_syserror ();
      break;

    case GPGME_STATUS_MISSING_PASSPHRASE:
      opd->no_passphrase = 1;
      break;

    case GPGME_STATUS_EOF:
      if (opd->no_passphrase || opd->bad_passphrase)
	return gpg_error (GPG_ERR_BAD_PASSPHRASE);
      break;

    case GPGME_STATUS_ERROR:
      /* We abuse this status handler to forward ERROR status codes to
         the caller.  This should better be done in a generic handler,
         but for now this is sufficient.  */
      if (ctx->status_cb)
        {
          err = ctx->status_cb (ctx->status_cb_value, "ERROR", args);
          if (err)
            return err;
        }
      break;

    case GPGME_STATUS_FAILURE:
      /* We abuse this status handler to forward FAILURE status codes
         to the caller.  This should better be done in a generic
         handler, but for now this is sufficient.  */
      if (ctx->status_cb)
        {
          err = ctx->status_cb (ctx->status_cb_value, "FAILURE", args);
          if (err)
            return err;
        }
      break;


    default:
      /* Ignore all other codes.  */
      break;
    }
  return 0;
}
Beispiel #25
0
gpgme_error_t
_gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
  gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
  gpgme_error_t err;
  void *hook;
  op_data_t opd;
  gpgme_signature_t sig;
  char *end;

  err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
  opd = hook;
  if (err)
    return err;

  sig = opd->current_sig;

  switch (code)
    {
    case GPGME_STATUS_NEWSIG:
      if (sig)
        calc_sig_summary (sig);
      err = prepare_new_sig (opd);
      opd->only_newsig_seen = 1;
      return err;

    case GPGME_STATUS_GOODSIG:
    case GPGME_STATUS_EXPSIG:
    case GPGME_STATUS_EXPKEYSIG:
    case GPGME_STATUS_BADSIG:
    case GPGME_STATUS_ERRSIG:
    case GPGME_STATUS_REVKEYSIG:
      if (sig && !opd->did_prepare_new_sig)
	calc_sig_summary (sig);
      opd->only_newsig_seen = 0;
      return parse_new_sig (opd, code, args, ctx->protocol);

    case GPGME_STATUS_VALIDSIG:
      opd->only_newsig_seen = 0;
      return sig ? parse_valid_sig (sig, args, ctx->protocol)
	: trace_gpg_error (GPG_ERR_INV_ENGINE);

    case GPGME_STATUS_NODATA:
      opd->only_newsig_seen = 0;
      if (!sig)
	return gpg_error (GPG_ERR_NO_DATA);
      sig->status = gpg_error (GPG_ERR_NO_DATA);
      break;

    case GPGME_STATUS_UNEXPECTED:
      opd->only_newsig_seen = 0;
      if (!sig)
	return gpg_error (GPG_ERR_GENERAL);
      sig->status = gpg_error (GPG_ERR_NO_DATA);
      break;

    case GPGME_STATUS_NOTATION_NAME:
    case GPGME_STATUS_NOTATION_FLAGS:
    case GPGME_STATUS_NOTATION_DATA:
    case GPGME_STATUS_POLICY_URL:
      opd->only_newsig_seen = 0;
      return sig ? parse_notation (sig, code, args)
	: trace_gpg_error (GPG_ERR_INV_ENGINE);

    case GPGME_STATUS_TRUST_UNDEFINED:
    case GPGME_STATUS_TRUST_NEVER:
    case GPGME_STATUS_TRUST_MARGINAL:
    case GPGME_STATUS_TRUST_FULLY:
    case GPGME_STATUS_TRUST_ULTIMATE:
      opd->only_newsig_seen = 0;
      return sig ? parse_trust (sig, code, args)
	: trace_gpg_error (GPG_ERR_INV_ENGINE);

    case GPGME_STATUS_PKA_TRUST_BAD:
    case GPGME_STATUS_PKA_TRUST_GOOD:
      opd->only_newsig_seen = 0;
      /* Check that we only get one of these status codes per
         signature; if not the crypto backend misbehaves.  */
      if (!sig || sig->pka_trust || sig->pka_address)
        return trace_gpg_error (GPG_ERR_INV_ENGINE);
      sig->pka_trust = code == GPGME_STATUS_PKA_TRUST_GOOD? 2 : 1;
      end = strchr (args, ' ');
      if (end)
        *end = 0;
      sig->pka_address = strdup (args);
      break;

    case GPGME_STATUS_TOFU_USER:
      opd->only_newsig_seen = 0;
      return sig ? parse_tofu_user (sig, args)
        /*    */ : trace_gpg_error (GPG_ERR_INV_ENGINE);

    case GPGME_STATUS_TOFU_STATS:
      opd->only_newsig_seen = 0;
      return sig ? parse_tofu_stats (sig, args)
        /*    */ : trace_gpg_error (GPG_ERR_INV_ENGINE);

    case GPGME_STATUS_TOFU_STATS_LONG:
      opd->only_newsig_seen = 0;
      return sig ? parse_tofu_stats_long (sig, args, ctx->raw_description)
        /*    */ : trace_gpg_error (GPG_ERR_INV_ENGINE);

    case GPGME_STATUS_ERROR:
      opd->only_newsig_seen = 0;
      /* Some  error stati are informational, so we don't return an
         error code if we are not ready to process this status.  */
      return parse_error (sig, args, !!sig );

    case GPGME_STATUS_FAILURE:
      opd->failure_code = _gpgme_parse_failure (args);
      break;

    case GPGME_STATUS_EOF:
      if (sig && !opd->did_prepare_new_sig)
	calc_sig_summary (sig);
      if (opd->only_newsig_seen && sig)
        {
          gpgme_signature_t sig2;
          /* The last signature has no valid information - remove it
             from the list. */
          assert (!sig->next);
          if (sig == opd->result.signatures)
            opd->result.signatures = NULL;
          else
            {
              for (sig2 = opd->result.signatures; sig2; sig2 = sig2->next)
                if (sig2->next == sig)
                  {
                    sig2->next = NULL;
                    break;
                  }
            }
          /* Note that there is no need to release the members of SIG
             because we won't be here if they have been set. */
          free (sig);
          opd->current_sig = NULL;
        }
      opd->only_newsig_seen = 0;
      if (opd->failure_code)
        return opd->failure_code;
      break;

    case GPGME_STATUS_PLAINTEXT:
      if (++opd->plaintext_seen > 1)
        return gpg_error (GPG_ERR_BAD_DATA);
      err = _gpgme_parse_plaintext (args, &opd->result.file_name);
      if (err)
	return err;

    default:
      break;
    }
  return 0;
}
Beispiel #26
0
gpgme_verify_result_t
gpgme_op_verify_result (gpgme_ctx_t ctx)
{
  void *hook;
  op_data_t opd;
  gpgme_error_t err;
  gpgme_signature_t sig;

  TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_result", ctx);
  err = _gpgme_op_data_lookup (ctx, OPDATA_VERIFY, &hook, -1, NULL);
  opd = hook;
  if (err || !opd)
    {
      TRACE_SUC0 ("result=(null)");
      return NULL;
    }

  /* It is possible that we saw a new signature only followed by an
     ERROR line for that.  In particular a missing X.509 key triggers
     this.  In this case it is surprising that the summary field has
     not been updated.  We fix it here by explicitly looking for this
     case.  The real fix would be to have GPGME emit ERRSIG.  */
  for (sig = opd->result.signatures; sig; sig = sig->next)
    {
      if (!sig->summary)
        {
          switch (gpg_err_code (sig->status))
            {
            case GPG_ERR_KEY_EXPIRED:
              sig->summary |= GPGME_SIGSUM_KEY_EXPIRED;
              break;

            case GPG_ERR_NO_PUBKEY:
              sig->summary |= GPGME_SIGSUM_KEY_MISSING;
              break;

            default:
              break;
            }
        }
    }

  /* Now for some tracing stuff. */
  if (_gpgme_debug_trace ())
    {
      int i;

      for (sig = opd->result.signatures, i = 0; sig; sig = sig->next, i++)
	{
	  TRACE_LOG4 ("sig[%i] = fpr %s, summary 0x%x, status %s",
		      i, sig->fpr, sig->summary, gpg_strerror (sig->status));
	  TRACE_LOG6 ("sig[%i] = timestamps 0x%x/0x%x flags:%s%s%s",
		      i, sig->timestamp, sig->exp_timestamp,
		      sig->wrong_key_usage ? "wrong key usage" : "",
		      sig->pka_trust == 1 ? "pka bad"
		      : (sig->pka_trust == 2 ? "pka_okay" : "pka RFU"),
		      sig->chain_model ? "chain model" : "");
	  TRACE_LOG5 ("sig[%i] = validity 0x%x (%s), algos %s/%s",
		      i, sig->validity, gpg_strerror (sig->validity_reason),
		      gpgme_pubkey_algo_name (sig->pubkey_algo),
		      gpgme_hash_algo_name (sig->hash_algo));
	  if (sig->pka_address)
	    {
	      TRACE_LOG2 ("sig[%i] = PKA address %s", i, sig->pka_address);
	    }
	  if (sig->notations)
	    {
	      TRACE_LOG1 ("sig[%i] = has notations (not shown)", i);
	    }
	}
    }

  TRACE_SUC1 ("result=%p", &opd->result);
  return &opd->result;
}
Beispiel #27
0
gpgme_error_t
_gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
			       char *args)
{
  gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
  gpgme_error_t err;
  void *hook;
  op_data_t opd;

  err = _gpgme_passphrase_status_handler (priv, code, args);
  if (err)
    return err;

  err = _gpgme_op_data_lookup (ctx, OPDATA_DECRYPT, &hook, -1, NULL);
  opd = hook;
  if (err)
    return err;

  switch (code)
    {
    case GPGME_STATUS_FAILURE:
      opd->failure_code = _gpgme_parse_failure (args);
      break;

    case GPGME_STATUS_EOF:
      /* FIXME: These error values should probably be attributed to
	 the underlying crypto engine (as error source).  */
      if (opd->failed)
	return gpg_error (GPG_ERR_DECRYPT_FAILED);
      else if (!opd->okay)
	return gpg_error (GPG_ERR_NO_DATA);
      else if (opd->failure_code)
        return opd->failure_code;
      break;

    case GPGME_STATUS_DECRYPTION_INFO:
      /* Fixme: Provide a way to return the used symmetric algorithm. */
      break;

    case GPGME_STATUS_DECRYPTION_OKAY:
      opd->okay = 1;
      break;

    case GPGME_STATUS_DECRYPTION_FAILED:
      opd->failed = 1;
      break;

    case GPGME_STATUS_ERROR:
      /* Note that this is an informational status code which should
         not lead to an error return unless it is something not
         related to the backend.  */
      {
	const char d_alg[] = "decrypt.algorithm";
	const char k_alg[] = "decrypt.keyusage";

	if (!strncmp (args, d_alg, sizeof (d_alg) - 1))
	  {
	    args += sizeof (d_alg) - 1;
	    while (*args == ' ')
	      args++;

	    if (gpg_err_code (atoi (args)) == GPG_ERR_UNSUPPORTED_ALGORITHM)
	      {
		char *end;

		while (*args && *args != ' ')
		  args++;
		while (*args == ' ')
		  args++;

		end = strchr (args, ' ');
		if (end)
		  *end = '\0';

		if (!(*args == '?' && *(args + 1) == '\0'))
		  {
		    opd->result.unsupported_algorithm = strdup (args);
		    if (!opd->result.unsupported_algorithm)
		      return gpg_error_from_syserror ();
		  }
	      }
	  }
	else if (!strncmp (args, k_alg, sizeof (k_alg) - 1))
	  {
	    args += sizeof (k_alg) - 1;
	    while (*args == ' ')
	      args++;

	    if (gpg_err_code (atoi (args)) == GPG_ERR_WRONG_KEY_USAGE)
	      opd->result.wrong_key_usage = 1;
	  }
      }
      break;

    case GPGME_STATUS_ENC_TO:
      err = parse_enc_to (args, opd->last_recipient_p, ctx->protocol);
      if (err)
	return err;

      opd->last_recipient_p = &(*opd->last_recipient_p)->next;
      break;

    case GPGME_STATUS_NO_SECKEY:
      {
	gpgme_recipient_t rec = opd->result.recipients;

	while (rec)
	  {
	    if (!strcmp (rec->keyid, args))
	      {
		rec->status = gpg_error (GPG_ERR_NO_SECKEY);
		break;
	      }
	    rec = rec->next;
	  }
	/* FIXME: Is this ok?  */
	if (!rec)
	  return trace_gpg_error (GPG_ERR_INV_ENGINE);
      }
      break;

    case GPGME_STATUS_PLAINTEXT:
      err = _gpgme_parse_plaintext (args, &opd->result.file_name);
      if (err)
	return err;
      break;

    case GPGME_STATUS_INQUIRE_MAXLEN:
      if (ctx->status_cb)
        {
          err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
          if (err)
            return err;
        }
      break;

    default:
      break;
    }

  return 0;
}