示例#1
0
/* Call the agent to learn about a smartcard */
int
agent_learn (struct agent_card_info_s *info)
{
    int rc;

    rc = start_agent (1);
    if (rc)
        return rc;

    /* Send the serialno command to initialize the connection.  We don't
       care about the data returned.  If the card has already been
       initialized, this is a very fast command.  The main reason we
       need to do this here is to handle a card removed case so that an
       "l" command in --card-edit can be used to show ta newly inserted
       card.  We request the openpgp card because that is what we
       expect. */
    rc = assuan_transact (agent_ctx, "SCD SERIALNO openpgp",
                          NULL, NULL, NULL, NULL, NULL, NULL);
    if (rc)
        return rc;


    memset (info, 0, sizeof *info);
    rc = assuan_transact (agent_ctx, "SCD LEARN --force",
                          dummy_data_cb, NULL, default_inq_cb, NULL,
                          learn_status_cb, info);
    /* Also try to get the key attributes.  */
    if (!rc)
        agent_scd_getattr ("KEY-ATTR", info);

    return rc;
}
示例#2
0
文件: cert-gpgsm.c 项目: gpg/scute
/* Invoke SEARCH_CB for each certificate found using assuan connection
   CTX to GPGSM.  */
static gpg_error_t
scute_gpgsm_search_certs (assuan_context_t ctx, cert_search_cb_t search_cb,
			  void *search_cb_hook)
{
  gpg_error_t err;
  struct search_ctx search;

  err = assuan_transact (ctx, "OPTION with-key-data", NULL, NULL,
			 NULL, NULL, NULL, NULL);
  if (err)
    return err;

  search.pending_len = 0;
  search.search_cb = search_cb;
  search.search_cb_hook = search_cb_hook;
  memset (&search.cert, '\0', sizeof (search.cert));

  err = assuan_transact (ctx, "DUMPKEYS", &search_certs, &search, NULL,
			 NULL, NULL, NULL);
  if (err)
    goto out;

  /* Signal the EOF.  This is not done by Assuan for us.  */
  err = search_certs (&search, NULL, 0);
  if (err)
    goto out;

 out:
  cert_reset (&search.cert);
  return err;
}
示例#3
0
文件: call-scd.c 项目: CSNW/gnupg
/* Create a signature using the current card.  MDALGO is either 0 or
   gives the digest algorithm.  */
int
agent_card_pksign (ctrl_t ctrl,
                   const char *keyid,
                   int (*getpin_cb)(void *, const char *, char*, size_t),
                   void *getpin_cb_arg,
                   int mdalgo,
                   const unsigned char *indata, size_t indatalen,
                   unsigned char **r_buf, size_t *r_buflen)
{
  int rc;
  char line[ASSUAN_LINELENGTH];
  membuf_t data;
  struct inq_needpin_s inqparm;

  *r_buf = NULL;
  rc = start_scd (ctrl);
  if (rc)
    return rc;

  if (indatalen*2 + 50 > DIM(line))
    return unlock_scd (ctrl, gpg_error (GPG_ERR_GENERAL));

  bin2hex (indata, indatalen, stpcpy (line, "SETDATA "));

  rc = assuan_transact (ctrl->scd_local->ctx, line,
                        NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_scd (ctrl, rc);

  init_membuf (&data, 1024);
  inqparm.ctx = ctrl->scd_local->ctx;
  inqparm.getpin_cb = getpin_cb;
  inqparm.getpin_cb_arg = getpin_cb_arg;
  inqparm.passthru = 0;
  inqparm.any_inq_seen = 0;
  if (ctrl->use_auth_call)
    snprintf (line, sizeof line, "PKAUTH %s", keyid);
  else
    snprintf (line, sizeof line, "PKSIGN %s %s",
              hash_algo_option (mdalgo), keyid);
  rc = assuan_transact (ctrl->scd_local->ctx, line,
                        membuf_data_cb, &data,
                        inq_needpin, &inqparm,
                        NULL, NULL);
  if (inqparm.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED ||
	gpg_err_code(rc) == GPG_ERR_ASS_CANCELED))
    rc = cancel_inquire (ctrl, rc);

  if (rc)
    {
      size_t len;

      xfree (get_membuf (&data, &len));
      return unlock_scd (ctrl, rc);
    }

  *r_buf = get_membuf (&data, r_buflen);
  return unlock_scd (ctrl, 0);
}
示例#4
0
/* Send a sign command to the scdaemon via gpg-agent's pass thru
   mechanism. */
int
agent_scd_pksign (const char *serialno, int hashalgo,
                  const unsigned char *indata, size_t indatalen,
                  unsigned char **r_buf, size_t *r_buflen)
{
    int rc, i;
    char *p, line[ASSUAN_LINELENGTH];
    membuf_t data;
    size_t len;

    /* Note, hashalgo is not yet used but hardwired to SHA1 in SCdaemon. */

    *r_buf = NULL;
    *r_buflen = 0;

    rc = start_agent (1);
    if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT
            || gpg_err_code (rc) == GPG_ERR_NOT_SUPPORTED)
        rc = 0; /* We check later.  */
    if (rc)
        return rc;

    if (indatalen*2 + 50 > DIM(line))
        return gpg_error (GPG_ERR_GENERAL);

    rc = select_openpgp (serialno);
    if (rc)
        return rc;

    sprintf (line, "SCD SETDATA ");
    p = line + strlen (line);
    for (i=0; i < indatalen ; i++, p += 2 )
        sprintf (p, "%02X", indata[i]);
    rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
    if (rc)
        return rc;

    init_membuf (&data, 1024);
#if 0
    if (!hashalgo) /* Temporary test hack. */
        snprintf (line, DIM(line)-1, "SCD PKAUTH %s", serialno);
    else
#endif
        snprintf (line, DIM(line)-1, "SCD PKSIGN %s %s",
                  hash_algo_option (hashalgo), serialno);
    line[DIM(line)-1] = 0;
    rc = assuan_transact (agent_ctx, line, membuf_data_cb, &data,
                          default_inq_cb, NULL, NULL, NULL);
    if (rc)
    {
        xfree (get_membuf (&data, &len));
    }
    else
        *r_buf = get_membuf (&data, r_buflen);

    status_sc_op_failure (rc);
    return rc;
}
示例#5
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;
}
示例#6
0
/* Helper for agent_askpin and agent_get_passphrase.  */
static int
setup_qualitybar (void)
{
  int rc;
  char line[ASSUAN_LINELENGTH];
  char *tmpstr, *tmpstr2;
  const char *tooltip;

  /* TRANSLATORS: This string is displayed by Pinentry as the label
     for the quality bar.  */
  tmpstr = try_percent_escape (_("Quality:"), "\t\r\n\f\v");
  snprintf (line, DIM(line)-1, "SETQUALITYBAR %s", tmpstr? tmpstr:"");
  line[DIM(line)-1] = 0;
  xfree (tmpstr);
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc == 103 /*(Old assuan error code)*/
      || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
    ; /* Ignore Unknown Command from old Pinentry versions.  */
  else if (rc)
    return rc;

  tmpstr2 = gnupg_get_help_string ("pinentry.qualitybar.tooltip", 0);
  if (tmpstr2)
    tooltip = tmpstr2;
  else
    {
      /* TRANSLATORS: This string is a tooltip, shown by pinentry when
         hovering over the quality bar.  Please use an appropriate
         string to describe what this is about.  The length of the
         tooltip is limited to about 900 characters.  If you do not
         translate this entry, a default english text (see source)
         will be used. */
      tooltip =  _("pinentry.qualitybar.tooltip");
      if (!strcmp ("pinentry.qualitybar.tooltip", tooltip))
        tooltip = ("The quality of the text entered above.\n"
                   "Please ask your administrator for "
                   "details about the criteria.");
    }
  tmpstr = try_percent_escape (tooltip, "\t\r\n\f\v");
  xfree (tmpstr2);
  snprintf (line, DIM(line)-1, "SETQUALITYBAR_TT %s", tmpstr? tmpstr:"");
  line[DIM(line)-1] = 0;
  xfree (tmpstr);
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc == 103 /*(Old assuan error code)*/
          || gpg_err_code (rc) == GPG_ERR_ASS_UNKNOWN_CMD)
    ; /* Ignore Unknown Command from old pinentry versions.  */
  else if (rc)
    return rc;

  return 0;
}
示例#7
0
/* Client main.  If true is returned, a disconnect has not been done. */
static int
client (assuan_context_t ctx, const char *fname)
{
  int rc;
  FILE *fp;
  int i;

  log_info ("client started. Servers's pid is %ld\n",
            (long)assuan_get_pid (ctx));

  for (i=0; i < 6; i++)
    {
      fp = fopen (fname, "r");
      if (!fp)
        {
          log_error ("failed to open `%s': %s\n", fname,
                     strerror (errno));
          return -1;
        }
      
      rc = assuan_sendfd (ctx, fileno (fp));
      if (rc)
        {
          log_error ("assuan_sendfd failed: %s\n", gpg_strerror (rc));
          return -1;
        }
      fclose (fp);

      rc = assuan_transact (ctx, "INPUT FD", NULL, NULL, NULL, NULL,
                            NULL, NULL);
      if (rc)
        {
          log_error ("sending INPUT FD failed: %s\n", gpg_strerror (rc));
          return -1;
        }

      rc = assuan_transact (ctx, "ECHO", NULL, NULL, NULL, NULL, NULL, NULL);
      if (rc)
        {
          log_error ("sending ECHO failed: %s\n", gpg_strerror (rc));
          return -1;
        }
    }

  /* Give us some time to check with lsof that all descriptors are closed. */
/*   sleep (10); */

  assuan_release (ctx);
  return 0;
}
示例#8
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];
  pth_attr_t tattr;

  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);
    }

  tattr = pth_attr_new();
  pth_attr_set (tattr, PTH_ATTR_JOINABLE, 1);
  pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 256*1024);
  pth_attr_set (tattr, PTH_ATTR_NAME, "popup-message");

  popup_finished = 0;
  popup_tid = pth_spawn (tattr, popup_message_thread, NULL);
  if (!popup_tid)
    {
      rc = gpg_error_from_syserror ();
      log_error ("error spawning popup message handler: %s\n",
                 strerror (errno) );
      pth_attr_destroy (tattr);
      return unlock_pinentry (rc);
    }
  pth_attr_destroy (tattr);

  return 0;
}
示例#9
0
/* Try to connect to the agent via socket or fork it off and work by
   pipes.  Handle the server's initial greeting.  */
static gpg_error_t
start_agent (void)
{
  gpg_error_t err;

  /* Fixme: This code is not thread safe, thus we don't build it with
     pth.  We will need a context for each thread or serialize the
     access to the agent.  */
  if (agent_ctx)
    return 0;

  err = start_new_gpg_agent (&agent_ctx,
                             agentargs.errsource,
                             agentargs.homedir,
                             agentargs.agent_program,
                             agentargs.lc_ctype,
                             agentargs.lc_messages,
                             agentargs.session_env,
                             1, agentargs.verbosity, 0, NULL, NULL);
  if (!err)
    {
      /* Tell the agent that we support Pinentry notifications.  No
         error checking so that it will work with older agents.  */
      assuan_transact (agent_ctx, "OPTION allow-pinentry-notify",
                       NULL, NULL, NULL, NULL, NULL, NULL);
    }

  return err;
}
示例#10
0
文件: call-scd.c 项目: CSNW/gnupg
/* Read a certificate with ID into R_BUF and R_BUFLEN. */
int
agent_card_readcert (ctrl_t ctrl,
                     const char *id, char **r_buf, size_t *r_buflen)
{
  int rc;
  char line[ASSUAN_LINELENGTH];
  membuf_t data;
  size_t len;

  *r_buf = NULL;
  rc = start_scd (ctrl);
  if (rc)
    return rc;

  init_membuf (&data, 1024);
  snprintf (line, DIM(line)-1, "READCERT %s", id);
  line[DIM(line)-1] = 0;
  rc = assuan_transact (ctrl->scd_local->ctx, line,
                        membuf_data_cb, &data,
                        NULL, NULL,
                        NULL, NULL);
  if (rc)
    {
      xfree (get_membuf (&data, &len));
      return unlock_scd (ctrl, rc);
    }
  *r_buf = get_membuf (&data, r_buflen);
  if (!*r_buf)
    return unlock_scd (ctrl, gpg_error (GPG_ERR_ENOMEM));

  return unlock_scd (ctrl, 0);
}
示例#11
0
文件: call-scd.c 项目: CSNW/gnupg
/* Perform the LEARN command and return a list of all private keys
   stored on the card. */
int
agent_card_learn (ctrl_t ctrl,
                  void (*kpinfo_cb)(void*, const char *),
                  void *kpinfo_cb_arg,
                  void (*certinfo_cb)(void*, const char *),
                  void *certinfo_cb_arg,
                  void (*sinfo_cb)(void*, const char *, size_t, const char *),
                  void *sinfo_cb_arg)
{
  int rc;
  struct learn_parm_s parm;

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

  memset (&parm, 0, sizeof parm);
  parm.kpinfo_cb = kpinfo_cb;
  parm.kpinfo_cb_arg = kpinfo_cb_arg;
  parm.certinfo_cb = certinfo_cb;
  parm.certinfo_cb_arg = certinfo_cb_arg;
  parm.sinfo_cb = sinfo_cb;
  parm.sinfo_cb_arg = sinfo_cb_arg;
  rc = assuan_transact (ctrl->scd_local->ctx, "LEARN --force",
                        NULL, NULL, NULL, NULL,
                        learn_status_cb, &parm);
  if (rc)
    return unlock_scd (ctrl, rc);

  return unlock_scd (ctrl, 0);
}
示例#12
0
文件: call-scd.c 项目: CSNW/gnupg
int
agent_card_writekey (ctrl_t ctrl,  int force, const char *serialno,
                     const char *id, const char *keydata, size_t keydatalen,
                     int (*getpin_cb)(void *, const char *, char*, size_t),
                     void *getpin_cb_arg)
{
  int rc;
  char line[ASSUAN_LINELENGTH];
  struct writekey_parm_s parms;

  (void)serialno;
  rc = start_scd (ctrl);
  if (rc)
    return rc;

  snprintf (line, DIM(line)-1, "WRITEKEY %s%s", force ? "--force " : "", id);
  line[DIM(line)-1] = 0;
  parms.ctx = ctrl->scd_local->ctx;
  parms.getpin_cb = getpin_cb;
  parms.getpin_cb_arg = getpin_cb_arg;
  parms.passthru = 0;
  parms.any_inq_seen = 0;
  parms.keydata = keydata;
  parms.keydatalen = keydatalen;

  rc = assuan_transact (ctrl->scd_local->ctx, line, NULL, NULL,
                        inq_writekey_parms, &parms, NULL, NULL);
  if (parms.any_inq_seen && (gpg_err_code(rc) == GPG_ERR_CANCELED ||
                             gpg_err_code(rc) == GPG_ERR_ASS_CANCELED))
    rc = cancel_inquire (ctrl, rc);
  return unlock_scd (ctrl, rc);
}
示例#13
0
/* Return the S2K iteration count as computed by gpg-agent.  */
gpg_error_t
agent_get_s2k_count (unsigned long *r_count)
{
    gpg_error_t err;
    membuf_t data;
    char *buf;

    *r_count = 0;

    err = start_agent (0);
    if (err)
        return err;

    init_membuf (&data, 32);
    err = assuan_transact (agent_ctx, "GETINFO s2k_count",
                           membuf_data_cb, &data,
                           NULL, NULL, NULL, NULL);
    if (err)
        xfree (get_membuf (&data, NULL));
    else
    {
        put_membuf (&data, "", 1);
        buf = get_membuf (&data, NULL);
        if (!buf)
            err = gpg_error_from_syserror ();
        else
        {
            *r_count = strtoul (buf, NULL, 10);
            xfree (buf);
        }
    }
    return err;
}
示例#14
0
/* Send a WRITEKEY command to the SCdaemon. */
int
agent_scd_writekey (int keyno, const char *serialno,
                    const unsigned char *keydata, size_t keydatalen)
{
    int rc;
    char line[ASSUAN_LINELENGTH];
    struct writekey_parm_s parms;

    (void)serialno;

    rc = start_agent (1);
    if (rc)
        return rc;

    memset (&parms, 0, sizeof parms);

    snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
    line[DIM(line)-1] = 0;
    parms.ctx = agent_ctx;
    parms.keydata = keydata;
    parms.keydatalen = keydatalen;

    rc = assuan_transact (agent_ctx, line, NULL, NULL,
                          inq_writekey_parms, &parms, NULL, NULL);

    status_sc_op_failure (rc);
    return rc;
}
示例#15
0
/* Send a READCERT command to the SCdaemon. */
int
agent_scd_readcert (const char *certidstr,
                    void **r_buf, size_t *r_buflen)
{
    int rc;
    char line[ASSUAN_LINELENGTH];
    membuf_t data;
    size_t len;

    *r_buf = NULL;
    rc = start_agent (1);
    if (rc)
        return rc;

    init_membuf (&data, 2048);

    snprintf (line, DIM(line)-1, "SCD READCERT %s", certidstr);
    line[DIM(line)-1] = 0;
    rc = assuan_transact (agent_ctx, line,
                          membuf_data_cb, &data,
                          default_inq_cb, NULL, NULL, NULL);
    if (rc)
    {
        xfree (get_membuf (&data, &len));
        return rc;
    }
    *r_buf = get_membuf (&data, r_buflen);
    if (!*r_buf)
        return gpg_error (GPG_ERR_ENOMEM);

    return 0;
}
示例#16
0
文件: cert-gpgsm.c 项目: gpg/scute
static gpg_error_t
export_cert (char *fpr, struct cert *cert)
{
  gpg_error_t err;
  assuan_context_t ctx;
  const char *argv[] = { "gpgsm", "--server", NULL };
#define COMMANDLINELEN 80
  char cmd[COMMANDLINELEN];
  struct export_hook exp;

  err = assuan_new (&ctx);
  if (err)
    {
      DEBUG (DBG_CRIT, "failed to allocate assuan context: %s",
	     gpg_strerror (err));
      return err;
    }

  err = assuan_pipe_connect (ctx, get_gpgsm_path (), argv, NULL,
			     NULL, NULL, 128);
  if (err)
    {
      assuan_release (ctx);
      DEBUG (DBG_CRIT, "spawning %s\n", get_gpgsm_path ());
      return err;
    }

  exp.buffer = NULL;
  exp.buffer_len = 0;
  exp.buffer_size = 0;

  snprintf (cmd, sizeof (cmd), "EXPORT --data -- %s\n", cert->fpr);
  err = assuan_transact (ctx, cmd, export_cert_cb, &exp,
			 NULL, NULL, NULL, NULL);
  assuan_release (ctx);

  if (!err)
    {
      cert->cert_der = exp.buffer;
      cert->cert_der_len = exp.buffer_len;
    }
#ifdef COMPAT_FALLBACK
  else if (gpg_err_code (err) == GPG_ERR_ASS_NO_OUTPUT)
    {
      /* For compatibility with GPGSM 2.0.0, we fall back to a work
	 around in that case.  */
      if (cert->cert_der)
	{
	  free (cert->cert_der);
	  cert->cert_der = NULL;
	}
      err = export_cert_compat (fpr, cert);
    }
#endif

  if (!err)
    err = scute_agent_is_trusted (fpr, &cert->is_trusted);

  return err;
}
示例#17
0
文件: call-scd.c 项目: CSNW/gnupg
/* Send the line CMDLINE with command for the SCDdaemon to it and send
   all status messages back.  This command is used as a general quoting
   mechanism to pass everything verbatim to SCDAEMON.  The PIN
   inquiry is handled inside gpg-agent.  */
int
agent_card_scd (ctrl_t ctrl, const char *cmdline,
                int (*getpin_cb)(void *, const char *, char*, size_t),
                void *getpin_cb_arg, void *assuan_context)
{
  int rc;
  struct inq_needpin_s inqparm;
  int saveflag;

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

  inqparm.ctx = ctrl->scd_local->ctx;
  inqparm.getpin_cb = getpin_cb;
  inqparm.getpin_cb_arg = getpin_cb_arg;
  inqparm.passthru = assuan_context;
  inqparm.any_inq_seen = 0;
  saveflag = assuan_get_flag (ctrl->scd_local->ctx, ASSUAN_CONVEY_COMMENTS);
  assuan_set_flag (ctrl->scd_local->ctx, ASSUAN_CONVEY_COMMENTS, 1);
  rc = assuan_transact (ctrl->scd_local->ctx, cmdline,
                        pass_data_thru, assuan_context,
                        inq_needpin, &inqparm,
                        pass_status_thru, assuan_context);
  if (inqparm.any_inq_seen && gpg_err_code(rc) == GPG_ERR_ASS_CANCELED)
    rc = cancel_inquire (ctrl, rc);

  assuan_set_flag (ctrl->scd_local->ctx, ASSUAN_CONVEY_COMMENTS, saveflag);
  if (rc)
    {
      return unlock_scd (ctrl, rc);
    }

  return unlock_scd (ctrl, 0);
}
示例#18
0
/* Send a WRITECERT command to the SCdaemon. */
int
agent_scd_writecert (const char *certidstr,
                     const unsigned char *certdata, size_t certdatalen)
{
    int rc;
    char line[ASSUAN_LINELENGTH];
    struct writecert_parm_s parms;

    rc = start_agent (1);
    if (rc)
        return rc;

    memset (&parms, 0, sizeof parms);

    snprintf (line, DIM(line)-1, "SCD WRITECERT %s", certidstr);
    line[DIM(line)-1] = 0;
    parms.ctx = agent_ctx;
    parms.certdata = certdata;
    parms.certdatalen = certdatalen;

    rc = assuan_transact (agent_ctx, line, NULL, NULL,
                          inq_writecert_parms, &parms, NULL, NULL);

    return rc;
}
示例#19
0
/* Pop up the PINentry, display the text DESC and a button with the
   text OK_BTN (which may be NULL to use the default of "OK") and wait
   for the user to hit this button.  The return value is not
   relevant.  */
int
agent_show_message (ctrl_t ctrl, const char *desc, const char *ok_btn)
{
  int rc;
  char line[ASSUAN_LINELENGTH];

  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);
  /* Most pinentries out in the wild return the old Assuan error code
     for canceled which gets translated to an assuan Cancel error and
     not to the code for a user cancel.  Fix this here. */
  if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
    rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);

  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);
    }

  rc = assuan_transact (entry_ctx, "CONFIRM --one-button", NULL, NULL, NULL,
                        NULL, NULL, NULL);
  if (rc && gpg_err_source (rc) && gpg_err_code (rc) == GPG_ERR_ASS_CANCELED)
    rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_CANCELED);

  return unlock_pinentry (rc);
}
示例#20
0
void Pin::cmd(const char *command) {
  gpg_error_t res;
  res = assuan_transact(ctx, command,
			&assuan_data_cb, assuan_data_cb_arg,
			&assuan_inquire_cb, assuan_inquire_cb_arg,
			&assuan_status_cb, assuan_status_cb_arg);
  if(res)
    throw runtime_error(strprintf("assuan_transaction: %s", gpg_strerror(res)));
}
示例#21
0
/* Pass COMMAND to dirmngr and print all output generated by Dirmngr
   to stdout.  A couple of inquiries are defined (see above).  ARGC
   arguments in ARGV are given to the Dirmngr.  Spaces, plus and
   percent characters within the argument strings are percent escaped
   so that blanks can act as delimiters. */
int
gpgsm_dirmngr_run_command (ctrl_t ctrl, const char *command,
                           int argc, char **argv)
{ 
  int rc;
  int i;
  const char *s;
  char *line, *p;
  size_t len;
  struct run_command_parm_s parm;

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

  parm.ctx = dirmngr_ctx;

  len = strlen (command) + 1;
  for (i=0; i < argc; i++)
    len += 1 + 3*strlen (argv[i]); /* enough space for percent escaping */
  line = xtrymalloc (len);
  if (!line)
    {
      release_dirmngr (ctrl);
      return out_of_core ();
    }

  p = stpcpy (line, command);
  for (i=0; i < argc; i++)
    {
      *p++ = ' ';
      for (s=argv[i]; *s; s++)
        {
          if (!isascii (*s))
            *p++ = *s;
          else if (*s == ' ')
            *p++ = '+';
          else if (!isprint (*s) || *s == '+')
            {
              sprintf (p, "%%%02X", *(const unsigned char *)s);
              p += 3;
            }
          else
            *p++ = *s;
        }
    }
  *p = 0;

  rc = assuan_transact (dirmngr_ctx, line,
                        run_command_cb, NULL,
                        run_command_inq_cb, &parm,
                        run_command_status_cb, ctrl);
  xfree (line);
  log_info ("response of dirmngr: %s\n", rc? gpg_strerror (rc): "okay");
  release_dirmngr (ctrl);
  return rc;
}
示例#22
0
文件: call-scd.c 项目: CSNW/gnupg
/* Reset the SCD if it has been used.  Actually it is not a reset but
   a cleanup of resources used by the current connection. */
int
agent_reset_scd (ctrl_t ctrl)
{
  if (ctrl->scd_local)
    {
      if (ctrl->scd_local->ctx)
        {
          /* We can't disconnect the primary context because libassuan
             does a waitpid on it and thus the system would hang.
             Instead we send a reset and keep that connection for
             reuse. */
          if (ctrl->scd_local->ctx == primary_scd_ctx)
            {
              /* Send a RESTART to the SCD.  This is required for the
                 primary connection as a kind of virtual EOF; we don't
                 have another way to tell it that the next command
                 should be viewed as if a new connection has been
                 made.  For the non-primary connections this is not
                 needed as we simply close the socket.  We don't check
                 for an error here because the RESTART may fail for
                 example if the scdaemon has already been terminated.
                 Anyway, we need to set the reusable flag to make sure
                 that the aliveness check can clean it up. */
              assuan_transact (primary_scd_ctx, "RESTART",
                               NULL, NULL, NULL, NULL, NULL, NULL);
              primary_scd_ctx_reusable = 1;
            }
          else
            assuan_release (ctrl->scd_local->ctx);
          ctrl->scd_local->ctx = NULL;
        }

      /* Remove the local context from our list and release it. */
      if (!scd_local_list)
        BUG ();
      else if (scd_local_list == ctrl->scd_local)
        scd_local_list = ctrl->scd_local->next_local;
      else
        {
          struct scd_local_s *sl;

          for (sl=scd_local_list; sl->next_local; sl = sl->next_local)
            if (sl->next_local == ctrl->scd_local)
              break;
          if (!sl->next_local)
            BUG ();
          sl->next_local = ctrl->scd_local->next_local;
        }
      xfree (ctrl->scd_local);
      ctrl->scd_local = NULL;
    }

  return 0;
}
std::string Pinentry::GETPIN() {
  std::string ret;
  gpg_error_t error;
  if ((error = assuan_transact(_pinentry, "GETPIN",
          set_string, &ret,  // data callback
          nullptr, nullptr,  // inquiry callback
          nullptr, nullptr)  // status callback
        ) != GPG_ERR_NO_ERROR)
    throw std::system_error(error, gpg_category());
  return ret;
}
示例#24
0
/* Send a GENKEY command to the SCdaemon.  SERIALNO is not used in
   this implementation.  If CREATEDATE has been given, it will be
   passed to SCDAEMON so that the key can be created with this
   timestamp; note the user needs to use the returned timestamp as old
   versions of scddaemon don't support this option.  */
int
agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force,
                  const char *serialno, u32 createtime, gcry_sexp_t *r_pubkey)
{
    int rc;
    char line[ASSUAN_LINELENGTH];
    gnupg_isotime_t tbuf;
    membuf_t data;
    unsigned char *buf;
    size_t len;

    (void)serialno;

    rc = start_agent (1);
    if (rc)
        return rc;

    if (createtime)
        epoch2isotime (tbuf, createtime);
    else
        *tbuf = 0;

    memset (info, 0, sizeof *info);
    snprintf (line, DIM(line)-1, "SCD GENKEY %s%s %s %d",
              *tbuf? "--timestamp=":"", tbuf,
              force? "--force":"",
              keyno);
    line[DIM(line)-1] = 0;

    memset (info, 0, sizeof *info);
    init_membuf_secure (&data, 1024);
    rc = assuan_transact (agent_ctx, line,
                          membuf_data_cb, &data, default_inq_cb, NULL,
                          scd_genkey_cb, info);

    status_sc_op_failure (rc);

    if (rc)
    {
        xfree (get_membuf (&data, &len));
    }
    else
    {
        buf = get_membuf (&data, &len);
        if (!buf)
            return gpg_error_from_syserror ();
        rc = gcry_sexp_sscan (r_pubkey, NULL, buf, len);
        xfree (buf);
    }

    return rc;
}
示例#25
0
static gpgme_error_t
gpgsm_set_locale (void *engine, int category, const char *value)
{
  engine_gpgsm_t gpgsm = 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.  GPGSM needs support
     for this.  */
  if (0)
    ;
#ifdef LC_CTYPE
  else if (category == LC_CTYPE)
    {
      catstr = "lc-ctype";
      if (!value && gpgsm->lc_ctype_set)
	return gpg_error (GPG_ERR_INV_VALUE);
      if (value)
	gpgsm->lc_ctype_set = 1;
    }
#endif
#ifdef LC_MESSAGES
  else if (category == LC_MESSAGES)
    {
      catstr = "lc-messages";
      if (!value && gpgsm->lc_messages_set)
	return gpg_error (GPG_ERR_INV_VALUE);
      if (value)
	gpgsm->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_syserror ();
  else
    {
      err = assuan_transact (gpgsm->assuan_ctx, optstr, NULL, NULL,
			     NULL, NULL, NULL, NULL);
      free (optstr);
    }

  return err;
}
static void nodata_command(assuan_context_t ctx,
    const std::string& command, const std::string& data) {
  char buf[ASSUAN_LINELENGTH];
  std::snprintf(buf, ASSUAN_LINELENGTH,
      "%s %s",
      command.c_str(), data.c_str());
  gpg_error_t error;
  if ((error = assuan_transact(ctx, buf,
          nullptr, nullptr,  // data callback
          nullptr, nullptr,  // inquiry callback
          nullptr, nullptr)  // status callback
          ) != GPG_ERR_NO_ERROR)
    throw std::system_error(error, gpg_category());
}
示例#27
0
/* The thread running the popup message. */
static void *
popup_message_thread (void *arg)
{
  (void)arg;

  /* We use the --one-button hack instead of the MESSAGE command to
     allow the use of old Pinentries.  Those old Pinentries will then
     show an additional Cancel button but that is mostly a visual
     annoyance. */
  assuan_transact (entry_ctx, "CONFIRM --one-button",
                   NULL, NULL, NULL, NULL, NULL, NULL);
  popup_finished = 1;
  return NULL;
}
bool Pinentry::CONFIRM() {
  gpg_error_t error;
  switch (gpg_err_code(error = assuan_transact(_pinentry, "CONFIRM",
        nullptr, nullptr,
        nullptr, nullptr,
        nullptr, nullptr))) {
    case GPG_ERR_NO_ERROR:
      return true;
    case GPG_ERR_NOT_CONFIRMED:
      return false;
    default:
      throw std::system_error(error, gpg_category());
  }
}
示例#29
0
/* Ask the dirmngr for the policy flags and return them as an estream
 * memory stream.  If no policy flags are set, NULL is stored at
 * R_BUFFER.  */
gpg_error_t
wkd_get_policy_flags (const char *addrspec, estream_t *r_buffer)
{
  gpg_error_t err;
  assuan_context_t ctx;
  struct wkd_get_parm_s parm;
  char *line = NULL;
  char *buffer = NULL;

  memset (&parm, 0, sizeof parm);
  *r_buffer = NULL;

  err = connect_dirmngr (&ctx);
  if (err)
    return err;

  line = es_bsprintf ("WKD_GET --policy-flags -- %s", addrspec);
  if (!line)
    {
      err = gpg_error_from_syserror ();
      goto leave;
    }
  if (strlen (line) + 2 >= ASSUAN_LINELENGTH)
    {
      err = gpg_error (GPG_ERR_TOO_LARGE);
      goto leave;
    }

  parm.memfp = es_fopenmem (0, "rwb");
  if (!parm.memfp)
    {
      err = gpg_error_from_syserror ();
      goto leave;
    }
  err = assuan_transact (ctx, line, wkd_get_data_cb, &parm,
                         NULL, NULL, wkd_get_status_cb, &parm);
  if (err)
    goto leave;

  es_rewind (parm.memfp);
  *r_buffer = parm.memfp;
  parm.memfp = 0;

 leave:
  es_free (buffer);
  es_fclose (parm.memfp);
  xfree (line);
  assuan_release (ctx);
  return err;
}
示例#30
0
/* This function prepares the dirmngr for a new session.  The
   audit-events option is used so that other dirmngr clients won't get
   disturbed by such events.  */
static void
prepare_dirmngr (ctrl_t ctrl, assuan_context_t ctx, gpg_error_t err)
{
  struct keyserver_spec *server;

  if (!err)
    {
      err = assuan_transact (ctx, "OPTION audit-events=1",
			     NULL, NULL, NULL, NULL, NULL, NULL);
      if (gpg_err_code (err) == GPG_ERR_UNKNOWN_OPTION)
	err = 0;  /* Allow the use of old dirmngr versions.  */
    }
  audit_log_ok (ctrl->audit, AUDIT_DIRMNGR_READY, err);

  if (!ctx || err)
    return;

  server = opt.keyserver;
  while (server)
    {
      char line[ASSUAN_LINELENGTH];
      char *user = server->user ? server->user : "";
      char *pass = server->pass ? server->pass : "";
      char *base = server->base ? server->base : "";
      
      snprintf (line, DIM (line) - 1, "LDAPSERVER %s:%i:%s:%s:%s",
		server->host, server->port, user, pass, base);
      line[DIM (line) - 1] = 0;

      err = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
      if (gpg_err_code (err) == GPG_ERR_ASS_UNKNOWN_CMD)
	err = 0;  /* Allow the use of old dirmngr versions.  */

      server = server->next;
    }
}