示例#1
0
文件: app.c 项目: Juul/gnupg
/* Lock the reader SLOT.  This function shall be used right before
   calling any of the actual application functions to serialize access
   to the reader.  We do this always even if the reader is not
   actually used.  This allows an actual connection to assume that it
   never shares a reader (while performing one command).  Returns 0 on
   success; only then the unlock_reader function must be called after
   returning from the handler. */
static gpg_error_t
lock_reader (int slot, ctrl_t ctrl)
{
  int res;

  if (slot < 0 || slot >= DIM (lock_table))
    return gpg_error (slot<0? GPG_ERR_INV_VALUE : GPG_ERR_RESOURCE_LIMIT);

  if (!lock_table[slot].initialized)
    {
      res = npth_mutex_init (&lock_table[slot].lock, NULL);
      if (res)
        {
          log_error ("error initializing mutex: %s\n", strerror (res));
          return gpg_error_from_errno (res);
        }
      lock_table[slot].initialized = 1;
      lock_table[slot].app = NULL;
      lock_table[slot].last_app = NULL;
    }

  res = npth_mutex_lock (&lock_table[slot].lock);
  if (res)
    {
      log_error ("failed to acquire APP lock for slot %d: %s\n",
                 slot, strerror (res));
      return gpg_error_from_errno (res);
    }

  apdu_set_progress_cb (slot, print_progress_line, ctrl);

  return 0;
}
示例#2
0
static gpgme_error_t
gpgsm_keylist(void *engine, const char *pattern, int secret_only,
              gpgme_keylist_mode_t mode)
{
    engine_gpgsm_t gpgsm = engine;
    char *line;
    gpgme_error_t err;
    int list_mode = 0;

    if(mode & GPGME_KEYLIST_MODE_LOCAL)
        list_mode |= 1;
    if(mode & GPGME_KEYLIST_MODE_EXTERN)
        list_mode |= 2;

    if(!pattern)
        pattern = "";

    /* Always send list-mode option because RESET does not reset it.  */
    if(asprintf(&line, "OPTION list-mode=%d", (list_mode & 3)) < 0)
        return gpg_error_from_errno(errno);
    err = gpgsm_assuan_simple_command(gpgsm->assuan_ctx, line, NULL, NULL);
    free(line);
    if(err)
        return err;


    /* Always send key validation because RESET does not reset it.  */

    /* Use the validation mode if required.  We don't check for an error
       yet because this is a pretty fresh gpgsm features. */
    gpgsm_assuan_simple_command(gpgsm->assuan_ctx,
                                (mode & GPGME_KEYLIST_MODE_VALIDATE) ?
                                "OPTION with-validation=1" :
                                "OPTION with-validation=0" ,
                                NULL, NULL);


    /* Length is "LISTSECRETKEYS " + p + '\0'.  */
    line = malloc(15 + strlen(pattern) + 1);
    if(!line)
        return gpg_error_from_errno(errno);
    if(secret_only)
    {
        strcpy(line, "LISTSECRETKEYS ");
        strcpy(&line[15], pattern);
    }
    else
    {
        strcpy(line, "LISTKEYS ");
        strcpy(&line[9], pattern);
    }

    gpgsm_clear_fd(gpgsm, INPUT_FD);
    gpgsm_clear_fd(gpgsm, OUTPUT_FD);
    gpgsm_clear_fd(gpgsm, MESSAGE_FD);

    err = start(gpgsm, line);
    free(line);
    return err;
}
示例#3
0
gpgme_error_t
_gpgme_data_inbound_handler(void *opaque, int fd)
{
    gpgme_data_t dh = (gpgme_data_t) opaque;
    char buffer[BUFFER_SIZE];
    char *bufp = buffer;
    ssize_t buflen;

    buflen = _gpgme_io_read(fd, buffer, BUFFER_SIZE);
    if(buflen < 0)
        return gpg_error_from_errno(errno);
    if(buflen == 0)
    {
        _gpgme_io_close(fd);
        return 0;
    }

    do
    {
        ssize_t amt = gpgme_data_write(dh, bufp, buflen);
        if(amt == 0 || (amt < 0 && errno != EINTR))
            return gpg_error_from_errno(errno);
        bufp += amt;
        buflen -= amt;
    }
    while(buflen > 0);
    return 0;
}
示例#4
0
/* Create a LDAP URL from DN and FILTER and return it in URL.  We don't
   need the host and port because this will be specified using the
   override options. */
static gpg_error_t
make_url (char **url, const char *dn, const char *filter)
{
  gpg_error_t err;
  char *u_dn, *u_filter;
  char const attrs[] = (USERCERTIFICATE ","
/*                         USERSMIMECERTIFICATE "," */
                        CACERTIFICATE ","
                        X509CACERT );

  *url = NULL;

  u_dn = escape4url (dn);
  if (!u_dn)
      return gpg_error_from_errno (errno);

  u_filter = escape4url (filter);
  if (!u_filter)
    {
      err = gpg_error_from_errno (errno);
      xfree (u_dn);
      return err;
    }

  *url = strconcat ("ldap:///", u_dn, "?", attrs, "?sub?", u_filter, NULL);
  if (!*url)
    err = gpg_error_from_syserror ();
  else
    err = 0;

  xfree (u_dn);
  xfree (u_filter);
  return err;
}
示例#5
0
static gpgme_error_t
set_recipients(engine_gpgsm_t gpgsm, gpgme_key_t recp[])
{
    gpgme_error_t err = 0;
    assuan_context_t ctx = gpgsm->assuan_ctx;
    char *line;
    int linelen;
    int invalid_recipients = 0;
    int i = 0;

    linelen = 10 + 40 + 1;	/* "RECIPIENT " + guess + '\0'.  */
    line = malloc(10 + 40 + 1);
    if(!line)
        return gpg_error_from_errno(errno);
    strcpy(line, "RECIPIENT ");
    while(!err && recp[i])
    {
        char *fpr;
        int newlen;

        if(!recp[i]->subkeys || !recp[i]->subkeys->fpr)
        {
            invalid_recipients++;
            continue;
        }
        fpr = recp[i]->subkeys->fpr;

        newlen = 11 + strlen(fpr);
        if(linelen < newlen)
        {
            char *newline = realloc(line, newlen);
            if(! newline)
            {
                int saved_errno = errno;
                free(line);
                return gpg_error_from_errno(saved_errno);
            }
            line = newline;
            linelen = newlen;
        }
        strcpy(&line[10], fpr);

        err = gpgsm_assuan_simple_command(ctx, line, gpgsm->status.fnc,
                                          gpgsm->status.fnc_value);
        /* FIXME: This requires more work.  */
        if(gpg_err_code(err) == GPG_ERR_NO_PUBKEY)
            invalid_recipients++;
        else if(err)
        {
            free(line);
            return err;
        }
        i++;
    }
    free(line);
    return gpg_error(invalid_recipients
                     ? GPG_ERR_UNUSABLE_PUBKEY : GPG_ERR_NO_ERROR);
}
示例#6
0
static gpgme_error_t
set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
{
  gpgme_error_t err = 0;
  assuan_context_t ctx = uiserver->assuan_ctx;
  char *line;
  int linelen;
  int invalid_recipients = 0;
  int i;

  linelen = 10 + 40 + 1;	/* "RECIPIENT " + guess + '\0'.  */
  line = malloc (10 + 40 + 1);
  if (!line)
    return gpg_error_from_errno (errno);
  strcpy (line, "RECIPIENT ");
  for (i=0; !err && recp[i]; i++)
    {
      char *uid;
      int newlen;

      /* We use only the first user ID of the key.  */
      if (!recp[i]->uids || !(uid=recp[i]->uids->uid) || !*uid)
	{
	  invalid_recipients++;
	  continue;
	}

      newlen = 11 + strlen (uid);
      if (linelen < newlen)
	{
	  char *newline = realloc (line, newlen);
	  if (! newline)
	    {
	      int saved_errno = errno;
	      free (line);
	      return gpg_error_from_errno (saved_errno);
	    }
	  line = newline;
	  linelen = newlen;
	}
      /* FIXME: need to do proper escaping  */
      strcpy (&line[10], uid);

      err = uiserver_assuan_simple_command (ctx, line, uiserver->status.fnc,
                                            uiserver->status.fnc_value);
      /* FIXME: This might requires more work.  */
      if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
	invalid_recipients++;
      else if (err)
	{
	  free (line);
	  return err;
	}
    }
  free (line);
  return gpg_error (invalid_recipients
		    ? GPG_ERR_UNUSABLE_PUBKEY : GPG_ERR_NO_ERROR);
}
示例#7
0
/* Pop up a message window similar to the confirm one but keep it open
   until agent_popup_message_stop has been called.  It is crucial for
   the caller to make sure that the stop function gets called as soon
   as the message is not anymore required because the message is
   system modal and all other attempts to use the pinentry will fail
   (after a timeout). */
int
agent_popup_message_start (ctrl_t ctrl, const char *desc, const char *ok_btn)
{
  int rc;
  char line[ASSUAN_LINELENGTH];
  npth_attr_t tattr;
  int err;

  if (ctrl->pinentry_mode != PINENTRY_MODE_ASK)
    return gpg_error (GPG_ERR_CANCELED);

  rc = start_pinentry (ctrl);
  if (rc)
    return rc;

  if (desc)
    snprintf (line, DIM(line)-1, "SETDESC %s", desc);
  else
    snprintf (line, DIM(line)-1, "RESET");
  line[DIM(line)-1] = 0;
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  if (ok_btn)
    {
      snprintf (line, DIM(line)-1, "SETOK %s", ok_btn);
      line[DIM(line)-1] = 0;
      rc = assuan_transact (entry_ctx, line, NULL,NULL,NULL,NULL,NULL,NULL);
      if (rc)
        return unlock_pinentry (rc);
    }

  err = npth_attr_init (&tattr);
  if (err)
    return unlock_pinentry (gpg_error_from_errno (err));
  npth_attr_setdetachstate (&tattr, NPTH_CREATE_JOINABLE);

  popup_finished = 0;
  err = npth_create (&popup_tid, &tattr, popup_message_thread, NULL);
  npth_attr_destroy (&tattr);
  if (err)
    {
      rc = gpg_error_from_errno (err);
      log_error ("error spawning popup message handler: %s\n",
                 strerror (err) );
      return unlock_pinentry (rc);
    }
  npth_setname_np (popup_tid, "popup-message");

  return 0;
}
示例#8
0
/* Register the file descriptor FD with the handler FNC (which gets
   FNC_DATA as its first argument) for the direction DIR.  DATA should
   be the context for which the fd is added.  R_TAG will hold the tag
   that can be used to remove the fd.  */
gpgme_error_t
_gpgme_add_io_cb (void *data, int fd, int dir, gpgme_io_cb_t fnc,
		  void *fnc_data, void **r_tag)
{
  gpgme_error_t err;
  gpgme_ctx_t ctx = (gpgme_ctx_t) data;
  fd_table_t fdt;
  struct wait_item_s *item;
  struct tag *tag;

  assert (fnc);
  assert (ctx);

  fdt = &ctx->fdt;
  assert (fdt);

  tag = malloc (sizeof *tag);
  if (!tag)
    return gpg_error_from_errno (errno);
  tag->ctx = ctx;

  /* Allocate a structure to hold information about the handler.  */
  item = calloc (1, sizeof *item);
  if (!item)
    {
      int saved_errno = errno;
      free (tag);
      return gpg_error_from_errno (saved_errno);
    }
  item->ctx = ctx;
  item->dir = dir;
  item->handler = fnc;
  item->handler_value = fnc_data;

  err = fd_table_put (fdt, fd, dir, item, &tag->idx);
  if (err)
    {
      free (tag);
      free (item);
      return err;
    }

  TRACE3 (DEBUG_CTX, "_gpgme_add_io_cb", ctx,
	  "fd %d, dir=%d -> tag=%p", fd, dir, tag);

  *r_tag = tag;
  return 0;
}
示例#9
0
static gpgme_error_t
gpgsm_export(void *engine, const char *pattern, unsigned int reserved,
             gpgme_data_t keydata, int use_armor)
{
    engine_gpgsm_t gpgsm = engine;
    gpgme_error_t err = 0;
    char *cmd;

    if(!gpgsm || reserved)
        return gpg_error(GPG_ERR_INV_VALUE);

    if(!pattern)
        pattern = "";

    cmd = malloc(7 + strlen(pattern) + 1);
    if(!cmd)
        return gpg_error_from_errno(errno);
    strcpy(cmd, "EXPORT ");
    strcpy(&cmd[7], pattern);

    gpgsm->output_cb.data = keydata;
    err = gpgsm_set_fd(gpgsm, OUTPUT_FD, use_armor ? "--armor" : 0);
    if(err)
        return err;
    gpgsm_clear_fd(gpgsm, INPUT_FD);
    gpgsm_clear_fd(gpgsm, MESSAGE_FD);

    err = start(gpgsm, cmd);
    free(cmd);
    return err;
}
示例#10
0
/* Generic function to add an extension to a certificate request.  The
   extension must be provided readily encoded in the buffer DER of
   length DERLEN bytes; the OID is to be given in OID and IS_CRIT
   should be set to true if that extension shall be marked
   critical. */
gpg_error_t
ksba_certreq_add_extension (ksba_certreq_t cr,
                            const char *oid, int is_crit,
                            const void *der, size_t derlen)
{
  size_t oidlen;
  struct extn_list_s *e;

  if (!cr || !oid|| !*oid || !der || !derlen)
    return gpg_error (GPG_ERR_INV_VALUE);

  oidlen = strlen (oid);
  e = xtrymalloc (sizeof *e + derlen + oidlen);
  if (!e)
    return gpg_error_from_errno (errno);
  e->critical = is_crit;
  e->derlen = derlen;
  memcpy (e->der, der, derlen);
  strcpy (e->der+derlen, oid);
  e->oid = e->der + derlen;

  e->next = cr->extn_list;
  cr->extn_list = e;

  return 0;
}
示例#11
0
static gpgme_error_t
gpgconf_new (void **engine, const char *file_name, const char *home_dir)
{
  gpgme_error_t err = 0;
  engine_gpgconf_t gpgconf;

  gpgconf = calloc (1, sizeof *gpgconf);
  if (!gpgconf)
    return gpg_error_from_errno (errno);

  gpgconf->file_name = strdup (file_name ? file_name
			       : _gpgme_get_gpgconf_path ());
  if (!gpgconf->file_name)
    err = gpg_error_from_syserror ();

  if (!err && home_dir)
    {
      gpgconf->home_dir = strdup (home_dir);
      if (!gpgconf->home_dir)
	err = gpg_error_from_syserror ();
    }

  if (err)
    gpgconf_release (gpgconf);
  else
    *engine = gpgconf;

  return err;
}
示例#12
0
/* Add KEY to list of signers in CTX.  */
gpgme_error_t
gpgme_signers_add (gpgme_ctx_t ctx, const gpgme_key_t key)
{
  TRACE_BEG2 (DEBUG_CTX, "gpgme_signers_add", ctx,
	      "key=%p (%s)", key, (key->subkeys && key->subkeys->fpr) ?
	      key->subkeys->fpr : "invalid");

  if (!ctx || !key)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (ctx->signers_len == ctx->signers_size)
    {
      gpgme_key_t *newarr;
      int n = ctx->signers_size + 5;
      int j;

      newarr = realloc (ctx->signers, n * sizeof (*newarr));
      if (!newarr)
	return TRACE_ERR (gpg_error_from_errno (errno));
      for (j = ctx->signers_size; j < n; j++)
	newarr[j] = NULL;
      ctx->signers = newarr;
      ctx->signers_size = n;
    }

  gpgme_key_ref (key);
  ctx->signers[ctx->signers_len++] = key;
  return TRACE_SUC ();
}
示例#13
0
/* Clear the error and eof indicators for READER, so that it can be
   continued to use.  Also dicards any unread bytes. This is usually
   required if the upper layer want to send to send an EOF to indicate
   the logical end of one part of a file.  If BUFFER and BUFLEN are
   not NULL, possible unread data is copied to a newly allocated
   buffer and this buffer is assigned to BUFFER, BUFLEN will be set to
   the length of the unread bytes. */
gpg_error_t
ksba_reader_clear (ksba_reader_t r, unsigned char **buffer, size_t *buflen)
{
  size_t n;

  if (!r)
    return gpg_error (GPG_ERR_INV_VALUE);
      
  r->eof = 0;
  r->error = 0;
  r->nread = 0;
  n = r->unread.length;
  r->unread.length = 0;

  if (buffer && buflen)
    {
      *buffer = NULL;
      *buflen = 0;
      if (n)
        {
          *buffer = xtrymalloc (n);
          if (!*buffer)
            return gpg_error_from_errno (errno);
          memcpy (*buffer, r->unread.buf, n);
          *buflen = n;
        }
    }
      
  return 0;
}
示例#14
0
/* XXX We should keep a marker and roll over for speed.  */
static gpgme_error_t
fd_table_put(fd_table_t fdt, int fd, int dir, void *opaque, int *idx)
{
    unsigned int i, j;
    struct io_select_fd_s *new_fds;

    for(i = 0; i < fdt->size; i++)
    {
        if(fdt->fds[i].fd == -1)
            break;
    }
    if(i == fdt->size)
    {
#define FDT_ALLOCSIZE 10
        new_fds = realloc(fdt->fds, (fdt->size + FDT_ALLOCSIZE)
                          * sizeof(*new_fds));
        if(!new_fds)
            return gpg_error_from_errno(errno);

        fdt->fds = new_fds;
        fdt->size += FDT_ALLOCSIZE;
        for(j = 0; j < FDT_ALLOCSIZE; j++)
            fdt->fds[i + j].fd = -1;
    }

    fdt->fds[i].fd = fd;
    fdt->fds[i].for_read = (dir == 1);
    fdt->fds[i].for_write = (dir == 0);
    fdt->fds[i].frozen = 0;
    fdt->fds[i].signaled = 0;
    fdt->fds[i].opaque = opaque;
    *idx = i;
    return 0;
}
示例#15
0
文件: verify.c 项目: nobled/gpgme
static gpgme_error_t
prepare_new_sig (op_data_t opd)
{
  gpgme_signature_t sig;

  if (opd->only_newsig_seen && opd->current_sig)
    {
      /* We have only seen the NEWSIG status and nothing else - we
         better skip this signature therefore and reuse it for the
         next possible signature. */
      sig = opd->current_sig;
      memset (sig, 0, sizeof *sig);
      assert (opd->result.signatures == sig);
    }
  else
    {
      sig = calloc (1, sizeof (*sig));
      if (!sig)
        return gpg_error_from_errno (errno);
      if (!opd->result.signatures)
        opd->result.signatures = sig;
      if (opd->current_sig)
        opd->current_sig->next = sig;
      opd->current_sig = sig;
    }
  opd->did_prepare_new_sig = 1;
  opd->only_newsig_seen = 0;
  return 0;
}
示例#16
0
gpgme_error_t
_gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type, void **hook,
		       int size, void (*cleanup) (void *))
{
  struct ctx_op_data *data = ctx->op_data;
  while (data && data->type != type)
    data = data->next;
  if (!data)
    {
      if (size < 0)
	{
	  *hook = NULL;
	  return 0;
	}

      data = calloc (1, sizeof (struct ctx_op_data) + size);
      if (!data)
	return gpg_error_from_errno (errno);
      data->next = ctx->op_data;
      data->type = type;
      data->cleanup = cleanup;
      data->hook = (void *) (((char *) data) + sizeof (struct ctx_op_data));
      ctx->op_data = data;
    }
  *hook = data->hook;
  return 0;
}
示例#17
0
/**
 * ksba_reader_new:
 * 
 * Create a new but uninitialized ksba_reader_t Object.  Using this
 * reader object in unitialized state does always yield eof.
 * 
 * Return value: ksba_reader_t object or an error code.
 **/
gpg_error_t
ksba_reader_new (ksba_reader_t *r_r)
{
  *r_r = xtrycalloc (1, sizeof **r_r);
  if (!*r_r)
    return gpg_error_from_errno (errno);
  return 0;
}
示例#18
0
/**
 * ksba_cms_new:
 *
 * Create a new and empty CMS object
 *
 * Return value: A CMS object or an error code.
 **/
gpg_error_t
ksba_certreq_new (ksba_certreq_t *r_cr)
{
  *r_cr = xtrycalloc (1, sizeof **r_cr);
  if (!*r_cr)
    return gpg_error_from_errno (errno);

  return 0;
}
示例#19
0
文件: trustlist.c 项目: nobled/gpgme
/* This handler is used to parse the output of --list-trust-path:
   Format:
   level:keyid:type:recno:ot:val:mc:cc:name:
   With TYPE = U for a user ID
               K for a key
   The RECNO is either the one of the dir record or the one of the uid
   record.  OT is the the usual trust letter and only availabel on K
   lines.  VAL is the calcualted validity MC is the marginal trust
   counter and only available on U lines CC is the same for the
   complete count NAME ist the username and only printed on U
   lines.  */
static gpgme_error_t
trustlist_colon_handler (void *priv, char *line)
{
  gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
  gpgme_error_t err;
  char *p, *pend;
  int field = 0;
  gpgme_trust_item_t item = NULL;

  if (!line)
    return 0; /* EOF */

  for (p = line; p; p = pend)
    {
      field++;
      pend = strchr (p, ':');
      if (pend) 
	*pend++ = 0;

      switch (field)
	{
	case 1: /* level */
	  err = _gpgme_trust_item_new (&item);
	  if (err)
	    return err;
	  item->level = atoi (p);
	  break;
	case 2: /* long keyid */
	  if (strlen (p) == DIM(item->keyid) - 1)
	    strcpy (item->keyid, p);
	  break;
	case 3: /* type */
	  item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0;
	  break;
	case 5: /* owner trust */
	  item->_owner_trust[0] = *p;
	  break;
	case 6: /* validity */
	  item->_validity[0] = *p;
	  break;
	case 9: /* user ID */
	  item->name = strdup (p);
	  if (!item->name)
	    {
	      int saved_errno = errno;
	      gpgme_trust_item_unref (item);
	      return gpg_error_from_errno (saved_errno);
	    }
	  break;
        }
    }

  if (item)
    _gpgme_engine_io_event (ctx->engine, GPGME_EVENT_NEXT_TRUSTITEM, item);
  return 0;
}
示例#20
0
文件: runner.c 项目: 0ndorio/gnupg
/* Spawn a new thread to let RUNNER work as a coprocess.  */
gpg_error_t
runner_spawn (runner_t runner)
{
  gpg_error_t err;
  npth_attr_t tattr;
  npth_t thread;
  int ret;

  if (check_already_spawned (runner, "runner_spawn"))
    return gpg_error (GPG_ERR_BUG);

  /* In case we have an input fd, open it as an estream so that the
     Pth scheduling will work.  The stdio functions don't work with
     Pth because they don't call the pth counterparts of read and
     write unless linker tricks are used.  */
  if (runner->in_fd != -1)
    {
      estream_t fp;

      fp = es_fdopen (runner->in_fd, "r");
      if (!fp)
        {
          err = gpg_error_from_syserror ();
          log_error ("can't fdopen pipe for reading: %s\n", gpg_strerror (err));
          return err;
        }
      runner->status_fp = fp;
      runner->in_fd = -1;  /* Now owned by status_fp.  */
    }

  npth_attr_init (&tattr);
  npth_attr_setdetachstate (&tattr, NPTH_CREATE_DETACHED);

  ret = npth_create (&thread, &tattr, runner_thread, runner);
  if (ret)
    {
      err = gpg_error_from_errno (ret);
      log_error ("error spawning runner thread: %s\n", gpg_strerror (err));
      return err;
    }
  npth_setname_np (thread, runner->name);

  /* The scheduler has not yet kicked in, thus we can safely set the
     spawned flag and the tid.  */
  runner->spawned = 1;
  runner->thread = thread;
  runner->next_running = running_threads;
  running_threads = runner;

  npth_attr_destroy (&tattr);

  /* The runner thread is now runnable.  */

  return 0;
}
示例#21
0
gpgme_error_t
gpgme_data_rewind (gpgme_data_t dh)
{
  gpgme_error_t err;
  TRACE_BEG (DEBUG_DATA, "gpgme_data_rewind", dh);

  err = (gpgme_data_seek (dh, 0, SEEK_SET) == -1)
    ? gpg_error_from_errno (errno) : 0;

  return TRACE_ERR (err);
}
示例#22
0
gpgme_error_t cm_gpgme_data_rewind(gpgme_data_t dh)
{
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
	if (gpgme_data_seek(dh, (off_t)0, SEEK_SET) == -1)
		return gpg_error_from_errno(errno);
	else
		return 0;
#else
	return gpgme_data_rewind(dh);
#endif
}
示例#23
0
gpgme_error_t
_gpgme_data_outbound_handler(void *opaque, int fd)
{
    gpgme_data_t dh = (gpgme_data_t) opaque;
    ssize_t nwritten;

    if(!dh->pending_len)
    {
        ssize_t amt = gpgme_data_read(dh, dh->pending, BUFFER_SIZE);
        if(amt < 0)
            return gpg_error_from_errno(errno);
        if(amt == 0)
        {
            _gpgme_io_close(fd);
            return 0;
        }
        dh->pending_len = amt;
    }

    nwritten = _gpgme_io_write(fd, dh->pending, dh->pending_len);
    if(nwritten == -1 && errno == EAGAIN)
        return 0;

    if(nwritten == -1 && errno == EPIPE)
    {
        /* Not much we can do.  The other end closed the pipe, but we
        still have data.  This should only ever happen if the other
         end is going to tell us what happened on some other channel.
         Silently close our end.  */
        _gpgme_io_close(fd);
        return 0;
    }

    if(nwritten <= 0)
        return gpg_error_from_errno(errno);

    if(nwritten < dh->pending_len)
        memmove(dh->pending, dh->pending + nwritten, dh->pending_len - nwritten);
    dh->pending_len -= nwritten;
    return 0;
}
示例#24
0
/* Create new, empty Poldi context.  Return proper error code.   */
static gpg_error_t
create_context (poldi_ctx_t *context, pam_handle_t *pam_handle)
{
  gpg_error_t err;
  poldi_ctx_t ctx;

  err = 0;

  /* Allocate. */
  ctx = xtrymalloc (sizeof (*ctx));
  if (!ctx)
    {
      err = gpg_error_from_errno (errno);
      goto out;
    }

  /* Initialize. */

  *ctx = poldi_ctx_NULL;

  ctx->auth_method = -1;
  ctx->cardinfo = scd_cardinfo_null;
  ctx->pam_handle = pam_handle;

  err = log_create (&ctx->loghandle);
  if (err)
    goto out;

  err = simpleparse_create (&ctx->parsehandle);
  if (err)
    goto out;

  simpleparse_set_loghandle (ctx->parsehandle, ctx->loghandle);
  simpleparse_set_parse_cb (ctx->parsehandle, pam_poldi_options_cb, ctx);
  simpleparse_set_specs (ctx->parsehandle, opt_specs);
  simpleparse_set_i18n_cb (ctx->parsehandle, i18n_cb, NULL);

  *context = ctx;

 out:

  if (err)
    {
      if (ctx)
	{
	  simpleparse_destroy (ctx->parsehandle);
	  log_destroy (ctx->loghandle);
	  xfree (ctx);
	}
    }

  return err;
}
示例#25
0
文件: decrypt.c 项目: nobled/gpgme
static gpgme_error_t
parse_enc_to (char *args, gpgme_recipient_t *recp)
{
  gpgme_recipient_t rec;
  char *tail;
  int i;

  rec = malloc (sizeof (*rec));
  if (!rec)
    return gpg_error_from_errno (errno);

  rec->next = NULL;
  rec->keyid = rec->_keyid;
  rec->status = 0;

  for (i = 0; i < sizeof (rec->_keyid) - 1; i++)
    {
      if (args[i] == '\0' || args[i] == ' ')
	break;

      rec->_keyid[i] = args[i];
    }
  rec->_keyid[i] = '\0';

  args = &args[i];
  if (*args != '\0' && *args != ' ')
    {
      free (rec);
      return gpg_error (GPG_ERR_INV_ENGINE);
    }

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

  if (*args)
    {
      errno = 0;
      rec->pubkey_algo = strtol (args, &tail, 0);
      if (errno || args == tail || *tail != ' ')
	{
	  /* The crypto backend does not behave.  */
	  free (rec);
	  return gpg_error (GPG_ERR_INV_ENGINE);
	}
    }

  /* FIXME: The key length is always 0 right now, so no need to parse
     it.  */

  *recp = rec;
  return 0;
}
示例#26
0
/* Create a new data buffer filled with the content of file FNAME.
   COPY must be non-zero (delayed reads are not supported yet).  */
gpgme_error_t
gpgme_data_new_from_file (gpgme_data_t *dh, const char *fname, int copy)
{
  struct stat statbuf;

  if (!fname || !copy)
    return gpg_error (GPG_ERR_INV_VALUE);

  if (stat (fname, &statbuf) < 0)
    return gpg_error_from_errno (errno);

  return gpgme_data_new_from_filepart (dh, fname, NULL, 0, statbuf.st_size);
}
示例#27
0
/* FIXME: Missing a way to specify --silent.  */
static gpgme_error_t
uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
	      gpgme_data_t plaintext)
{
  engine_uiserver_t uiserver = engine;
  gpgme_error_t err;
  const char *protocol;
  char *cmd;

  if (!uiserver)
    return gpg_error (GPG_ERR_INV_VALUE);
  if (uiserver->protocol == GPGME_PROTOCOL_DEFAULT)
    protocol = "";
  else if (uiserver->protocol == GPGME_PROTOCOL_OpenPGP)
    protocol = " --protocol=OpenPGP";
  else if (uiserver->protocol == GPGME_PROTOCOL_CMS)
    protocol = " --protocol=CMS";
  else
    return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);

  if (asprintf (&cmd, "VERIFY%s", protocol) < 0)
    return gpg_error_from_errno (errno);

  uiserver->input_cb.data = sig;
  err = uiserver_set_fd (uiserver, INPUT_FD,
			 map_data_enc (uiserver->input_cb.data));
  if (err)
    {
      free (cmd);
      return err;
    }
  if (plaintext)
    {
      /* Normal or cleartext signature.  */
      uiserver->output_cb.data = plaintext;
      err = uiserver_set_fd (uiserver, OUTPUT_FD, 0);
    }
  else
    {
      /* Detached signature.  */
      uiserver->message_cb.data = signed_text;
      err = uiserver_set_fd (uiserver, MESSAGE_FD, 0);
    }
  uiserver->inline_data = NULL;

  if (!err)
    err = start (uiserver, cmd);

  free (cmd);
  return err;
}
示例#28
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;
}
示例#29
0
static gpgme_error_t
uiserver_set_locale (void *engine, int category, const char *value)
{
  engine_uiserver_t uiserver = engine;
  gpgme_error_t err;
  char *optstr;
  char *catstr;

  /* FIXME: If value is NULL, we need to reset the option to default.
     But we can't do this.  So we error out here.  UISERVER needs support
     for this.  */
  if (category == LC_CTYPE)
    {
      catstr = "lc-ctype";
      if (!value && uiserver->lc_ctype_set)
	return gpg_error (GPG_ERR_INV_VALUE);
      if (value)
	uiserver->lc_ctype_set = 1;
    }
#ifdef LC_MESSAGES
  else if (category == LC_MESSAGES)
    {
      catstr = "lc-messages";
      if (!value && uiserver->lc_messages_set)
	return gpg_error (GPG_ERR_INV_VALUE);
      if (value)
	uiserver->lc_messages_set = 1;
    }
#endif /* LC_MESSAGES */
  else
    return gpg_error (GPG_ERR_INV_VALUE);

  /* FIXME: Reset value to default.  */
  if (!value)
    return 0;

  if (asprintf (&optstr, "OPTION %s=%s", catstr, value) < 0)
    err = gpg_error_from_errno (errno);
  else
    {
      err = assuan_transact (uiserver->assuan_ctx, optstr, NULL, NULL,
			     NULL, NULL, NULL, NULL);
      free (optstr);
    }

  return err;
}
示例#30
0
/* Create a new data buffer filled with the content of file FNAME.
   COPY must be non-zero (delayed reads are not supported yet).  */
gpgme_error_t
gpgme_data_new_from_file (gpgme_data_t *r_dh, const char *fname, int copy)
{
  gpgme_error_t err;
  struct stat statbuf;
  TRACE_BEG3 (DEBUG_DATA, "gpgme_data_new_from_filepart", r_dh,
	      "file_name=%s, copy=%i (%s)", fname, copy, copy ? "yes" : "no");

  if (!fname || !copy)
    return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));

  if (stat (fname, &statbuf) < 0)
    return TRACE_ERR (gpg_error_from_errno (errno));

  err = gpgme_data_new_from_filepart (r_dh, fname, NULL, 0, statbuf.st_size);
  return TRACE_ERR (err);
}