/* Put the DIGEST into an DER encoded container and return it in R_VAL. */
static int
encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo,
                    unsigned char **r_val, size_t *r_len)
{
  unsigned char *frame;
  unsigned char asn[100];
  size_t asnlen;

  *r_val = NULL;
  *r_len = 0;

  asnlen = DIM(asn);
  if (!algo || gcry_md_test_algo (algo))
    return gpg_error (GPG_ERR_DIGEST_ALGO);
  if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen))
    {
      log_error ("no object identifier for algo %d\n", algo);
      return gpg_error (GPG_ERR_INTERNAL);
    }

  frame = xtrymalloc (asnlen + digestlen);
  if (!frame)
    return out_of_core ();
  memcpy (frame, asn, asnlen);
  memcpy (frame+asnlen, digest, digestlen);
  if (DBG_CRYPTO)
    log_printhex ("encoded hash:", frame, asnlen+digestlen);
      
  *r_val = frame;
  *r_len = asnlen+digestlen;
  return 0;
}
Exemplo n.º 2
0
/* A simple callback used to return the serialnumber of a card.  */
static gpg_error_t
get_serialno_cb (void *opaque, const char *line)
{
    char **serialno = opaque;
    const char *keyword = line;
    const char *s;
    int keywordlen, n;

    for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
        ;
    while (spacep (line))
        line++;

    if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
    {
        if (*serialno)
            return gpg_error (GPG_ERR_CONFLICT); /* Unexpected status line. */
        for (n=0,s=line; hexdigitp (s); s++, n++)
            ;
        if (!n || (n&1)|| !(spacep (s) || !*s) )
            return gpg_error (GPG_ERR_ASS_PARAMETER);
        *serialno = xtrymalloc (n+1);
        if (!*serialno)
            return out_of_core ();
        memcpy (*serialno, line, n);
        (*serialno)[n] = 0;
    }

    return 0;
}
Exemplo n.º 3
0
char *
_ksba_xstrdup (const char *str)
{
  char *p = ksba_strdup (str);
  if (!p)
    out_of_core();
  return p;
}
Exemplo n.º 4
0
Arquivo: common.c Projeto: gpg/gpgol
void*
xcalloc (size_t m, size_t n)
{
    void *p = calloc (m, n);
    if (!p)
	out_of_core ();
    return p;
}
Exemplo n.º 5
0
Arquivo: memory.c Projeto: gpg/gsti
void *
_gsti_xrealloc (void *p, size_t n)
{
  void *pp = gcry_realloc (p, n);
  if (!pp)
    out_of_core ();
  return pp;
}
Exemplo n.º 6
0
Arquivo: memory.c Projeto: gpg/gsti
void *
_gsti_xmalloc (size_t n)
{
  void *p = gcry_xmalloc (n);
  if (!p)
    out_of_core ();
  return p;
}
Exemplo n.º 7
0
Arquivo: memory.c Projeto: gpg/gsti
char *
_gsti_xstrdup (const char *string)
{
  char *p = gcry_xstrdup (string);
  if (!p)
    out_of_core ();
  return p;
}
Exemplo n.º 8
0
void *
_ksba_xrealloc (void *mem, size_t n)
{
  void *p = ksba_realloc (mem,n);
  if (!p)
    out_of_core();
  return p;
}
Exemplo n.º 9
0
/* Implementations of the common xfoo() memory allocation functions */
void *
_ksba_xmalloc (size_t n )
{
  void *p = ksba_malloc (n);
  if (!p)
    out_of_core();
  return p;
}
Exemplo n.º 10
0
void *
xmalloc (size_t n)
{
  void *p = malloc (n);
  if (!p)
    out_of_core ("xmalloc");
  return p;
}
Exemplo n.º 11
0
char *
xstrdup (const char *str)
{
  char *p = strdup (str);
  if (!p)
    out_of_core ();
  return p;
}
Exemplo n.º 12
0
void *
xrealloc (void *mem, size_t n)
{
  void *p = realloc (mem, n);
  if (!p)
    out_of_core ();
  return p;
}
Exemplo n.º 13
0
void *
xcalloc (size_t n, size_t m)
{
  void *p = calloc (n, m);
  if (!p)
    out_of_core ();
  return p;
}
Exemplo n.º 14
0
Arquivo: memory.c Projeto: gpg/gsti
void *
_gsti_xcalloc (size_t n, size_t m)
{
  void *p = gcry_xcalloc (n, m);
  if (!p)
    out_of_core ();
  return p;
}
Exemplo n.º 15
0
void *
_ksba_xcalloc (size_t n, size_t m )
{
  void *p = ksba_calloc (n,m);
  if (!p)
    out_of_core();
  return p;
}
Exemplo n.º 16
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;
}
Exemplo n.º 17
0
void *
xstrdup (char const *string)
{
  char *p;

  p = malloc (strlen (string)+1);
  if (!p)
    out_of_core ("xstrdup");
  strcpy (p, string);
  return p;
}
Exemplo n.º 18
0
void *
xcalloc( size_t n, size_t m )
{
    void *p;

    if (!n)
      n = 1;
    if (!m)
      m = 1;

    p = calloc( n, m );
    if( !p )
	out_of_core();
    return p;
}
Exemplo n.º 19
0
void *
xmalloc( size_t n )
{
    void *p;

    /* Make sure that xmalloc (0) works.  This is the same behaviour
       has in gpg 2.x.  Note that in contrast to this code, Libgcrypt
       (and thus most xmallocs in gpg 2.x) detect the !n and bail out.  */
    if (!n)
      n = 1;

    p = malloc( n );
    if( !p )
	out_of_core();
    return p;
}
Exemplo n.º 20
0
static gpg_error_t
cmd_delkeys (assuan_context_t ctx, char *line)
{
  ctrl_t ctrl = assuan_get_pointer (ctx);
  char *p;
  strlist_t list, sl;
  int rc;

  /* break the line down into an strlist_t */
  list = NULL;
  for (p=line; *p; line = p)
    {
      while (*p && *p != ' ')
        p++;
      if (*p)
        *p++ = 0;
      if (*line)
        {
          sl = xtrymalloc (sizeof *sl + strlen (line));
          if (!sl)
            {
              free_strlist (list);
              return out_of_core ();
            }
          sl->flags = 0;
          strcpy_escaped_plus (sl->d, line);
          sl->next = list;
          list = sl;
        }
    }

  rc = gpgsm_delete (ctrl, list);
  free_strlist (list);

  /* close and reset the fd */
  close_message_fd (ctrl);
  assuan_close_input_fd (ctx);
  assuan_close_output_fd (ctx);

  return rc;
}
Exemplo n.º 21
0
static int
do_listkeys (assuan_context_t ctx, char *line, int mode)
{
  ctrl_t ctrl = assuan_get_pointer (ctx);
  estream_t fp;
  char *p;
  strlist_t list, sl;
  unsigned int listmode;
  gpg_error_t err;

  /* Break the line down into an strlist. */
  list = NULL;
  for (p=line; *p; line = p)
    {
      while (*p && *p != ' ')
        p++;
      if (*p)
        *p++ = 0;
      if (*line)
        {
          sl = xtrymalloc (sizeof *sl + strlen (line));
          if (!sl)
            {
              free_strlist (list);
              return out_of_core ();
            }
          sl->flags = 0;
          strcpy_escaped_plus (sl->d, line);
          sl->next = list;
          list = sl;
        }
    }

  if (ctrl->server_local->list_to_output)
    {
      int outfd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);

      if ( outfd == -1 )
        return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
      fp = es_fdopen_nc (outfd, "w");
      if (!fp)
        return set_error (gpg_err_code_from_syserror (), "es_fdopen() failed");
    }
  else
    {
      fp = es_fopencookie (ctx, "w", data_line_cookie_functions);
      if (!fp)
        return set_error (GPG_ERR_ASS_GENERAL,
                          "error setting up a data stream");
    }

  ctrl->with_colons = 1;
  listmode = mode;
  if (ctrl->server_local->list_internal)
    listmode |= (1<<6);
  if (ctrl->server_local->list_external)
    listmode |= (1<<7);
  err = gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode);
  free_strlist (list);
  es_fclose (fp);
  if (ctrl->server_local->list_to_output)
    assuan_close_output_fd (ctx);
  return err;
}
static int
ask_for_card (ctrl_t ctrl, const unsigned char *shadow_info, char **r_kid)
{
  int rc, i;
  char *serialno;
  int no_card = 0;
  char *desc;
  char *want_sn, *want_kid;
  int want_sn_displen;

  *r_kid = NULL;

  rc = parse_shadow_info (shadow_info, &want_sn, &want_kid);
  if (rc)
    return rc;

  /* We assume that a 20 byte serial number is a standard one which
     has the property to have a zero in the last nibble (Due to BCD
     representation).  We don't display this '0' because it may
     confuse the user.  */
  want_sn_displen = strlen (want_sn);
  if (want_sn_displen == 20 && want_sn[19] == '0')
    want_sn_displen--;

  for (;;)
    {
      rc = agent_card_serialno (ctrl, &serialno);
      if (!rc)
        {
          log_debug ("detected card with S/N %s\n", serialno);
          i = strcmp (serialno, want_sn);
          xfree (serialno);
          serialno = NULL;
          if (!i)
            {
              xfree (want_sn);
              *r_kid = want_kid;
              return 0; /* yes, we have the correct card */
            }
        }
      else if (gpg_err_code (rc) == GPG_ERR_CARD_NOT_PRESENT)
        {
          log_debug ("no card present\n");
          rc = 0;
          no_card = 1;
        }
      else
        {
          log_error ("error accessing card: %s\n", gpg_strerror (rc));
        }

      if (!rc)
        {
          if (asprintf (&desc,
                    "%s:%%0A%%0A"
                    "  \"%.*s\"",
                        no_card
                        ? _("Please insert the card with serial number")
                        : _("Please remove the current card and "
                            "insert the one with serial number"),
                    want_sn_displen, want_sn) < 0)
            {
              rc = out_of_core ();
            }
          else
            {
              rc = agent_get_confirmation (ctrl, desc, NULL, NULL, 0);
              xfree (desc);
            }
        }
      if (rc)
        {
          xfree (want_sn);
          xfree (want_kid);
          return rc;
        }
    }
}
Exemplo n.º 23
0
/* Run the Directory Manager's lookup command using the pattern
   compiled from the strings given in NAMES.  The caller must provide
   the callback CB which will be passed cert by cert.  Note that CTRL
   is optional.  With CACHE_ONLY the dirmngr will search only its own
   key cache. */
int 
gpgsm_dirmngr_lookup (ctrl_t ctrl, strlist_t names, int cache_only,
                      void (*cb)(void*, ksba_cert_t), void *cb_value)
{ 
  int rc;
  char *pattern;
  char line[ASSUAN_LINELENGTH];
  struct lookup_parm_s parm;
  size_t len;
  assuan_context_t ctx;

  /* The lookup function can be invoked from the callback of a lookup
     function, for example to walk the chain.  */
  if (!dirmngr_ctx_locked)
    {
      rc = start_dirmngr (ctrl);
      if (rc)
	return rc;
      ctx = dirmngr_ctx;
    }
  else if (!dirmngr2_ctx_locked)
    {
      rc = start_dirmngr2 (ctrl);
      if (rc)
	return rc;
      ctx = dirmngr2_ctx;
    }
  else
    {
      log_fatal ("both dirmngr contexts are in use\n");
    }

  pattern = pattern_from_strlist (names);
  if (!pattern)
    {
      if (ctx == dirmngr_ctx)
	release_dirmngr (ctrl);
      else
	release_dirmngr2 (ctrl);

      return out_of_core ();
    }
  snprintf (line, DIM(line)-1, "LOOKUP%s %s", 
            cache_only? " --cache-only":"", pattern);
  line[DIM(line)-1] = 0;
  xfree (pattern);

  parm.ctrl = ctrl;
  parm.ctx = ctx;
  parm.cb = cb;
  parm.cb_value = cb_value;
  parm.error = 0;
  init_membuf (&parm.data, 4096);

  rc = assuan_transact (ctx, line, lookup_cb, &parm,
                        NULL, NULL, lookup_status_cb, &parm);
  xfree (get_membuf (&parm.data, &len));

  if (ctx == dirmngr_ctx)
    release_dirmngr (ctrl);
  else
    release_dirmngr2 (ctrl);

  if (rc)
      return rc;
  return parm.error;
}
Exemplo n.º 24
0
/* Perform an encrypt operation.  

   Encrypt the data received on DATA-FD and write it to OUT_FP.  The
   recipients are take from the certificate given in recplist; if this
   is NULL it will be encrypted for a default recipient */
int
gpgsm_encrypt (ctrl_t ctrl, certlist_t recplist, int data_fd, FILE *out_fp)
{
  int rc = 0;
  Base64Context b64writer = NULL;
  gpg_error_t err;
  ksba_writer_t writer;
  ksba_reader_t reader = NULL;
  ksba_cms_t cms = NULL;
  ksba_stop_reason_t stopreason;
  KEYDB_HANDLE kh = NULL;
  struct encrypt_cb_parm_s encparm;
  DEK dek = NULL;
  int recpno;
  FILE *data_fp = NULL;
  certlist_t cl;
  int count;

  memset (&encparm, 0, sizeof encparm);

  audit_set_type (ctrl->audit, AUDIT_TYPE_ENCRYPT);

  /* Check that the certificate list is not empty and that at least
     one certificate is not flagged as encrypt_to; i.e. is a real
     recipient. */
  for (cl = recplist; cl; cl = cl->next)
    if (!cl->is_encrypt_to)
      break;
  if (!cl)
    {
      log_error(_("no valid recipients given\n"));
      gpgsm_status (ctrl, STATUS_NO_RECP, "0");
      audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, 0);
      rc = gpg_error (GPG_ERR_NO_PUBKEY);
      goto leave;
    }

  for (count = 0, cl = recplist; cl; cl = cl->next)
    count++;
  audit_log_i (ctrl->audit, AUDIT_GOT_RECIPIENTS, count);

  kh = keydb_new (0);
  if (!kh)
    {
      log_error (_("failed to allocated keyDB handle\n"));
      rc = gpg_error (GPG_ERR_GENERAL);
      goto leave;
    }

  data_fp = fdopen ( dup (data_fd), "rb");
  if (!data_fp)
    {
      rc = gpg_error (gpg_err_code_from_errno (errno));
      log_error ("fdopen() failed: %s\n", strerror (errno));
      goto leave;
    }

  err = ksba_reader_new (&reader);
  if (err)
      rc = err;
  if (!rc)
    rc = ksba_reader_set_cb (reader, encrypt_cb, &encparm);
  if (rc)
      goto leave;

  encparm.fp = data_fp;

  ctrl->pem_name = "ENCRYPTED MESSAGE";
  rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer);
  if (rc)
    {
      log_error ("can't create writer: %s\n", gpg_strerror (rc));
      goto leave;
    }

  err = ksba_cms_new (&cms);
  if (err)
    {
      rc = err;
      goto leave;
    }

  err = ksba_cms_set_reader_writer (cms, reader, writer);
  if (err)
    {
      log_debug ("ksba_cms_set_reader_writer failed: %s\n",
                 gpg_strerror (err));
      rc = err;
      goto leave;
    }

  audit_log (ctrl->audit, AUDIT_GOT_DATA);

  /* We are going to create enveloped data with uninterpreted data as
     inner content */
  err = ksba_cms_set_content_type (cms, 0, KSBA_CT_ENVELOPED_DATA);
  if (!err)
    err = ksba_cms_set_content_type (cms, 1, KSBA_CT_DATA);
  if (err)
    {
      log_debug ("ksba_cms_set_content_type failed: %s\n",
                 gpg_strerror (err));
      rc = err;
      goto leave;
    }

  /* Create a session key */
  dek = xtrycalloc_secure (1, sizeof *dek); 
  if (!dek)
    rc = out_of_core ();
  else
  {
    dek->algoid = opt.def_cipher_algoid;
    rc = init_dek (dek);
  }
  if (rc)
    {
      log_error ("failed to create the session key: %s\n",
                 gpg_strerror (rc));
      goto leave;
    }

  err = ksba_cms_set_content_enc_algo (cms, dek->algoid, dek->iv, dek->ivlen);
  if (err)
    {
      log_error ("ksba_cms_set_content_enc_algo failed: %s\n",
                 gpg_strerror (err));
      rc = err;
      goto leave;
    }

  encparm.dek = dek;
  /* Use a ~8k (AES) or ~4k (3DES) buffer */
  encparm.bufsize = 500 * dek->ivlen;
  encparm.buffer = xtrymalloc (encparm.bufsize);
  if (!encparm.buffer)
    {
      rc = out_of_core ();
      goto leave;
    }
  
  audit_log_s (ctrl->audit, AUDIT_SESSION_KEY, dek->algoid);

  /* Gather certificates of recipients, encrypt the session key for
     each and store them in the CMS object */
  for (recpno = 0, cl = recplist; cl; recpno++, cl = cl->next)
    {
      unsigned char *encval;
      
      rc = encrypt_dek (dek, cl->cert, &encval);
      if (rc)
        {
          audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, rc);
          log_error ("encryption failed for recipient no. %d: %s\n",
                     recpno, gpg_strerror (rc));
          goto leave;
        }
      
      err = ksba_cms_add_recipient (cms, cl->cert);
      if (err)
        {
          audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
          log_error ("ksba_cms_add_recipient failed: %s\n",
                     gpg_strerror (err));
          rc = err;
          xfree (encval);
          goto leave;
        }
      
      err = ksba_cms_set_enc_val (cms, recpno, encval);
      xfree (encval);
      audit_log_cert (ctrl->audit, AUDIT_ENCRYPTED_TO, cl->cert, err);
      if (err)
        {
          log_error ("ksba_cms_set_enc_val failed: %s\n",
                     gpg_strerror (err));
          rc = err;
          goto leave;
        }
    }

  /* Main control loop for encryption. */
  recpno = 0;
  do 
    {
      err = ksba_cms_build (cms, &stopreason);
      if (err)
        {
          log_debug ("ksba_cms_build failed: %s\n", gpg_strerror (err));
          rc = err;
          goto leave;
        }
    }
  while (stopreason != KSBA_SR_READY);   

  if (encparm.readerror)
    {
      log_error ("error reading input: %s\n", strerror (encparm.readerror));
      rc = gpg_error (gpg_err_code_from_errno (encparm.readerror));
      goto leave;
    }


  rc = gpgsm_finish_writer (b64writer);
  if (rc) 
    {
      log_error ("write failed: %s\n", gpg_strerror (rc));
      goto leave;
    }
  audit_log (ctrl->audit, AUDIT_ENCRYPTION_DONE);
  log_info ("encrypted data created\n");

 leave:
  ksba_cms_release (cms);
  gpgsm_destroy_writer (b64writer);
  ksba_reader_release (reader);
  keydb_release (kh); 
  xfree (dek);
  if (data_fp)
    fclose (data_fp);
  xfree (encparm.buffer);
  return rc;
}
Exemplo n.º 25
0
/* Return the secret key as an S-Exp in RESULT after locating it using
   the GRIP.  Stores NULL at RESULT if the operation shall be diverted
   to a token; in this case an allocated S-expression with the
   shadow_info part from the file is stored at SHADOW_INFO.
   CACHE_MODE defines now the cache shall be used.  DESC_TEXT may be
   set to present a custom description for the pinentry.  LOOKUP_TTL
   is an optional function to convey a TTL to the cache manager; we do
   not simply pass the TTL value because the value is only needed if an
   unprotect action was needed and looking up the TTL may have some
   overhead (e.g. scanning the sshcontrol file). */
gpg_error_t
agent_key_from_file (ctrl_t ctrl, const char *desc_text,
                     const unsigned char *grip, unsigned char **shadow_info,
                     cache_mode_t cache_mode, lookup_ttl_t lookup_ttl,
                     gcry_sexp_t *result)
{
  int rc;
  unsigned char *buf;
  size_t len, buflen, erroff;
  gcry_sexp_t s_skey;
  int got_shadow_info = 0;

  *result = NULL;
  if (shadow_info)
    *shadow_info = NULL;

  rc = read_key_file (grip, &s_skey);
  if (rc)
    return rc;

  /* For use with the protection functions we also need the key as an
     canonical encoded S-expression in a buffer.  Create this buffer
     now.  */
  rc = make_canon_sexp (s_skey, &buf, &len);
  if (rc)
    return rc;

  switch (agent_private_key_type (buf))
    {
    case PRIVATE_KEY_CLEAR:
      break; /* no unprotection needed */
    case PRIVATE_KEY_PROTECTED:
      {
	char *desc_text_final;
	char *comment = NULL;

        /* Note, that we will take the comment as a C string for
           display purposes; i.e. all stuff beyond a Nul character is
           ignored.  */
        {
          gcry_sexp_t comment_sexp;

          comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
          if (comment_sexp)
            comment = gcry_sexp_nth_string (comment_sexp, 1);
          gcry_sexp_release (comment_sexp);
        }

        desc_text_final = NULL;
	if (desc_text)
          rc = modify_description (desc_text, comment? comment:"", s_skey,
                                   &desc_text_final);
        gcry_free (comment);

	if (!rc)
	  {
	    rc = unprotect (ctrl, desc_text_final, &buf, grip,
                            cache_mode, lookup_ttl);
	    if (rc)
	      log_error ("failed to unprotect the secret key: %s\n",
			 gpg_strerror (rc));
	  }

	xfree (desc_text_final);
      }
      break;
    case PRIVATE_KEY_SHADOWED:
      if (shadow_info)
        {
          const unsigned char *s;
          size_t n;

          rc = agent_get_shadow_info (buf, &s);
          if (!rc)
            {
              n = gcry_sexp_canon_len (s, 0, NULL,NULL);
              assert (n);
              *shadow_info = xtrymalloc (n);
              if (!*shadow_info)
                rc = out_of_core ();
              else
                {
                  memcpy (*shadow_info, s, n);
                  rc = 0;
                  got_shadow_info = 1;
                }
            }
          if (rc)
            log_error ("get_shadow_info failed: %s\n", gpg_strerror (rc));
        }
      else
        rc = gpg_error (GPG_ERR_UNUSABLE_SECKEY);
      break;
    default:
      log_error ("invalid private key format\n");
      rc = gpg_error (GPG_ERR_BAD_SECKEY);
      break;
    }
  gcry_sexp_release (s_skey);
  s_skey = NULL;
  if (rc || got_shadow_info)
    {
      xfree (buf);
      return rc;
    }

  buflen = gcry_sexp_canon_len (buf, 0, NULL, NULL);
  rc = gcry_sexp_sscan (&s_skey, &erroff, (char*)buf, buflen);
  wipememory (buf, buflen);
  xfree (buf);
  if (rc)
    {
      log_error ("failed to build S-Exp (off=%u): %s\n",
                 (unsigned int)erroff, gpg_strerror (rc));
      return rc;
    }

  *result = s_skey;
  return 0;
}
Exemplo n.º 26
0
/* Reset all the certificate flags we have stored with the certificates
   for performance reasons. */
void
keydb_clear_some_cert_flags (ctrl_t ctrl, strlist_t names)
{
  gpg_error_t err;
  KEYDB_HANDLE hd = NULL;
  KEYDB_SEARCH_DESC *desc = NULL;
  int ndesc;
  strlist_t sl;
  int rc=0;
  unsigned int old_value, value;

  (void)ctrl;

  hd = keydb_new (0);
  if (!hd)
    {
      log_error ("keydb_new failed\n");
      goto leave;
    }

  if (!names)
    ndesc = 1;
  else
    {
      for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++)
        ;
    }

  desc = xtrycalloc (ndesc, sizeof *desc);
  if (!ndesc)
    {
      log_error ("allocating memory failed: %s\n",
                 gpg_strerror (out_of_core ()));
      goto leave;
    }

  if (!names)
    desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
  else
    {
      for (ndesc=0, sl=names; sl; sl = sl->next)
        {
          rc = classify_user_id (sl->d, desc+ndesc, 0);
          if (rc)
            {
              log_error ("key '%s' not found: %s\n",
                         sl->d, gpg_strerror (rc));
              rc = 0;
            }
          else
            ndesc++;
        }
    }

  err = keydb_lock (hd);
  if (err)
    {
      log_error (_("error locking keybox: %s\n"), gpg_strerror (err));
      goto leave;
    }

  while (!(rc = keydb_search (hd, desc, ndesc)))
    {
      if (!names)
        desc[0].mode = KEYDB_SEARCH_MODE_NEXT;

      err = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &old_value);
      if (err)
        {
          log_error (_("error getting stored flags: %s\n"),
                     gpg_strerror (err));
          goto leave;
        }

      value = (old_value & ~VALIDITY_REVOKED);
      if (value != old_value)
        {
          err = keydb_set_flags (hd, KEYBOX_FLAG_VALIDITY, 0, value);
          if (err)
            {
              log_error (_("error storing flags: %s\n"), gpg_strerror (err));
              goto leave;
            }
        }
    }
  if (rc && rc != -1)
    log_error ("keydb_search failed: %s\n", gpg_strerror (rc));

 leave:
  xfree (desc);
  keydb_release (hd);
}
Exemplo n.º 27
0
/* Ask for the passphrase using the supplied arguments.  The returned
   passphrase needs to be freed by the caller. */
int 
agent_get_passphrase (ctrl_t ctrl,
                      char **retpass, const char *desc, const char *prompt,
                      const char *errtext, int with_qualitybar)
{

  int rc;
  char line[ASSUAN_LINELENGTH];
  struct entry_parm_s parm;
  int saveflag;

  *retpass = NULL;
  if (opt.batch)
    return gpg_error (GPG_ERR_BAD_PASSPHRASE); 

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

  if (!prompt)
    prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");


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

  snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
  line[DIM(line)-1] = 0;
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  if (with_qualitybar && opt.min_passphrase_len)
    {
      rc = setup_qualitybar ();
      if (rc)
        return unlock_pinentry (rc);
    }

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

  memset (&parm, 0, sizeof parm);
  parm.size = ASSUAN_LINELENGTH/2 - 5;
  parm.buffer = gcry_malloc_secure (parm.size+10);
  if (!parm.buffer)
    return unlock_pinentry (out_of_core ());

  saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
  assuan_begin_confidential (entry_ctx);
  rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
                        inq_quality, entry_ctx, NULL, NULL);
  assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
  /* 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)
    xfree (parm.buffer);
  else
    *retpass = parm.buffer;
  return unlock_pinentry (rc);
}
Exemplo n.º 28
0
/* Ask for the passphrase using the supplied arguments.  The returned
   passphrase needs to be freed by the caller. */
int
agent_get_passphrase (ctrl_t ctrl,
                      char **retpass, const char *desc, const char *prompt,
                      const char *errtext, int with_qualitybar)
{

  int rc;
  char line[ASSUAN_LINELENGTH];
  struct entry_parm_s parm;
  int saveflag;
  int close_button;

  *retpass = NULL;
  if (opt.batch)
    return gpg_error (GPG_ERR_BAD_PASSPHRASE);

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

      if (ctrl->pinentry_mode == PINENTRY_MODE_LOOPBACK)
        {
	  size_t size;
	  size_t len = ASSUAN_LINELENGTH/2;
	  unsigned char *buffer = gcry_malloc_secure (len);

	  rc = pinentry_loopback(ctrl, "PASSPHRASE", &buffer, &size, len);
	  if (rc)
	    xfree(buffer);
	  else
	    {
	      buffer[size] = 0;
	      *retpass = buffer;
	    }
	  return rc;
        }
      return gpg_error (GPG_ERR_NO_PIN_ENTRY);
    }

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

  if (!prompt)
    prompt = desc && strstr (desc, "PIN")? "PIN": _("Passphrase");


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

  snprintf (line, DIM(line)-1, "SETPROMPT %s", prompt);
  line[DIM(line)-1] = 0;
  rc = assuan_transact (entry_ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  if (with_qualitybar && opt.min_passphrase_len)
    {
      rc = setup_qualitybar ();
      if (rc)
        return unlock_pinentry (rc);
    }

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

  memset (&parm, 0, sizeof parm);
  parm.size = ASSUAN_LINELENGTH/2 - 5;
  parm.buffer = gcry_malloc_secure (parm.size+10);
  if (!parm.buffer)
    return unlock_pinentry (out_of_core ());

  saveflag = assuan_get_flag (entry_ctx, ASSUAN_CONFIDENTIAL);
  assuan_begin_confidential (entry_ctx);
  close_button = 0;
  rc = assuan_transact (entry_ctx, "GETPIN", getpin_cb, &parm,
                        inq_quality, entry_ctx,
                        close_button_status_cb, &close_button);
  assuan_set_flag (entry_ctx, ASSUAN_CONFIDENTIAL, saveflag);
  /* 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);
  /* Change error code in case the window close button was clicked
     to cancel the operation.  */
  if (close_button && gpg_err_code (rc) == GPG_ERR_CANCELED)
    rc = gpg_err_make (gpg_err_source (rc), GPG_ERR_FULLY_CANCELED);

  if (rc)
    xfree (parm.buffer);
  else
    *retpass = parm.buffer;
  return unlock_pinentry (rc);
}
Exemplo n.º 29
0
static gpg_error_t
cmd_export (assuan_context_t ctx, char *line)
{
  ctrl_t ctrl = assuan_get_pointer (ctx);
  char *p;
  strlist_t list, sl;
  int use_data;

  use_data = has_option (line, "--data");

  if (use_data)
    {
      /* We need to override any possible setting done by an OUTPUT command. */
      ctrl->create_pem = has_option (line, "--armor");
      ctrl->create_base64 = has_option (line, "--base64");
    }

  line = skip_options (line);

  /* Break the line down into an strlist_t. */
  list = NULL;
  for (p=line; *p; line = p)
    {
      while (*p && *p != ' ')
        p++;
      if (*p)
        *p++ = 0;
      if (*line)
        {
          sl = xtrymalloc (sizeof *sl + strlen (line));
          if (!sl)
            {
              free_strlist (list);
              return out_of_core ();
            }
          sl->flags = 0;
          strcpy_escaped_plus (sl->d, line);
          sl->next = list;
          list = sl;
        }
    }

  if (use_data)
    {
      estream_t stream;

      stream = es_fopencookie (ctx, "w", data_line_cookie_functions);
      if (!stream)
        {
          free_strlist (list);
          return set_error (GPG_ERR_ASS_GENERAL,
                            "error setting up a data stream");
        }
      gpgsm_export (ctrl, list, stream);
      es_fclose (stream);
    }
  else
    {
      int fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1);
      estream_t out_fp;

      if (fd == -1)
        {
          free_strlist (list);
          return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL);
        }
      out_fp = es_fdopen_nc (fd, "w");
      if (!out_fp)
        {
          free_strlist (list);
          return set_error (gpg_err_code_from_syserror (), "fdopen() failed");
        }

      gpgsm_export (ctrl, list, out_fp);
      es_fclose (out_fp);
    }

  free_strlist (list);
  /* Close and reset the fds. */
  close_message_fd (ctrl);
  assuan_close_input_fd (ctx);
  assuan_close_output_fd (ctx);
  return 0;
}
Exemplo n.º 30
0
/* Fork off the pin entry if this has not already been done.  Note,
   that this function must always be used to aquire the lock for the
   pinentry - we will serialize _all_ pinentry calls.
 */
static int
start_pinentry (ctrl_t ctrl)
{
  int rc = 0;
  const char *pgmname;
  assuan_context_t ctx;
  const char *argv[5];
  int no_close_list[3];
  int i;
  const char *tmpstr;
  unsigned long pinentry_pid;
  const char *value;
  struct timespec abstime;
  int err;

  npth_clock_gettime (&abstime);
  abstime.tv_sec += LOCK_TIMEOUT;
  err = npth_mutex_timedlock (&entry_lock, &abstime);
  if (err)
    {
      if (err == ETIMEDOUT)
	rc = gpg_error (GPG_ERR_TIMEOUT);
      else
	rc = gpg_error_from_errno (rc);
      log_error (_("failed to acquire the pinentry lock: %s\n"),
                 gpg_strerror (rc));
      return rc;
    }

  entry_owner = ctrl;

  if (entry_ctx)
    return 0;

  if (opt.verbose)
    log_info ("starting a new PIN Entry\n");

#ifdef HAVE_W32_SYSTEM
  fflush (stdout);
  fflush (stderr);
#endif
  if (fflush (NULL))
    {
#ifndef HAVE_W32_SYSTEM
      gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
#endif
      log_error ("error flushing pending output: %s\n", strerror (errno));
      /* At least Windows XP fails here with EBADF.  According to docs
         and Wine an fflush(NULL) is the same as _flushall.  However
         the Wime implementaion does not flush stdin,stdout and stderr
         - see above.  Lets try to ignore the error. */
#ifndef HAVE_W32_SYSTEM
      return unlock_pinentry (tmperr);
#endif
    }

  if (!opt.pinentry_program || !*opt.pinentry_program)
    opt.pinentry_program = gnupg_module_name (GNUPG_MODULE_NAME_PINENTRY);
  pgmname = opt.pinentry_program;
  if ( !(pgmname = strrchr (opt.pinentry_program, '/')))
    pgmname = opt.pinentry_program;
  else
    pgmname++;

  /* OS X needs the entire file name in argv[0], so that it can locate
     the resource bundle.  For other systems we stick to the usual
     convention of supplying only the name of the program.  */
#ifdef __APPLE__
  argv[0] = opt.pinentry_program;
#else /*!__APPLE__*/
  argv[0] = pgmname;
#endif /*__APPLE__*/

  if (!opt.keep_display
      && (value = session_env_getenv (ctrl->session_env, "DISPLAY")))
    {
      argv[1] = "--display";
      argv[2] = value;
      argv[3] = NULL;
    }
  else
    argv[1] = NULL;

  i=0;
  if (!opt.running_detached)
    {
      if (log_get_fd () != -1)
        no_close_list[i++] = assuan_fd_from_posix_fd (log_get_fd ());
      no_close_list[i++] = assuan_fd_from_posix_fd (fileno (stderr));
    }
  no_close_list[i] = -1;

  rc = assuan_new (&ctx);
  if (rc)
    {
      log_error ("can't allocate assuan context: %s\n", gpg_strerror (rc));
      return rc;
    }
  /* We don't want to log the pinentry communication to make the logs
     easier to read.  We might want to add a new debug option to enable
     pinentry logging.  */
#ifdef ASSUAN_NO_LOGGING
  assuan_set_flag (ctx, ASSUAN_NO_LOGGING, 1);
#endif

  /* Connect to the pinentry and perform initial handshaking.  Note
     that atfork is used to change the environment for pinentry.  We
     start the server in detached mode to suppress the console window
     under Windows.  */
  rc = assuan_pipe_connect (ctx, opt.pinentry_program, argv,
			    no_close_list, atfork_cb, ctrl,
			    ASSUAN_PIPE_CONNECT_DETACHED);
  if (rc)
    {
      log_error ("can't connect to the PIN entry module '%s': %s\n",
                 opt.pinentry_program, gpg_strerror (rc));
      assuan_release (ctx);
      return unlock_pinentry (gpg_error (GPG_ERR_NO_PIN_ENTRY));
    }
  entry_ctx = ctx;

  if (DBG_ASSUAN)
    log_debug ("connection to PIN entry established\n");

  rc = assuan_transact (entry_ctx,
                        opt.no_grab? "OPTION no-grab":"OPTION grab",
                        NULL, NULL, NULL, NULL, NULL, NULL);
  if (rc)
    return unlock_pinentry (rc);

  value = session_env_getenv (ctrl->session_env, "GPG_TTY");
  if (value)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION ttyname=%s", value) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }
  value = session_env_getenv (ctrl->session_env, "TERM");
  if (value)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION ttytype=%s", value) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }
  if (ctrl->lc_ctype)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION lc-ctype=%s", ctrl->lc_ctype) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }
  if (ctrl->lc_messages)
    {
      char *optstr;
      if (asprintf (&optstr, "OPTION lc-messages=%s", ctrl->lc_messages) < 0 )
	return unlock_pinentry (out_of_core ());
      rc = assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
			    NULL);
      xfree (optstr);
      if (rc)
	return unlock_pinentry (rc);
    }

  {
    /* Provide a few default strings for use by the pinentries.  This
       may help a pinentry to avoid implementing localization code.  */
    static struct { const char *key, *value; } tbl[] = {
      /* TRANSLATORS: These are labels for buttons etc used in
         Pinentries.  An underscore indicates that the next letter
         should be used as an accelerator.  Double the underscore for
         a literal one.  The actual to be translated text starts after
         the second vertical bar.  */
      { "ok",     N_("|pinentry-label|_OK") },
      { "cancel", N_("|pinentry-label|_Cancel") },
      { "prompt", N_("|pinentry-label|PIN:") },
      { NULL, NULL}
    };
    char *optstr;
    int idx;
    const char *s, *s2;

    for (idx=0; tbl[idx].key; idx++)
      {
        s = _(tbl[idx].value);
        if (*s == '|' && (s2=strchr (s+1,'|')))
          s = s2+1;
        if (asprintf (&optstr, "OPTION default-%s=%s", tbl[idx].key, s) < 0 )
          return unlock_pinentry (out_of_core ());
        assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
                         NULL);
        xfree (optstr);
      }
  }


  /* Tell the pinentry the name of a file it shall touch after having
     messed with the tty.  This is optional and only supported by
     newer pinentries and thus we do no error checking. */
  tmpstr = opt.pinentry_touch_file;
  if (tmpstr && !strcmp (tmpstr, "/dev/null"))
    tmpstr = NULL;
  else if (!tmpstr)
    tmpstr = get_agent_socket_name ();
  if (tmpstr)
    {
      char *optstr;

      if (asprintf (&optstr, "OPTION touch-file=%s", tmpstr ) < 0 )
        ;
      else
        {
          assuan_transact (entry_ctx, optstr, NULL, NULL, NULL, NULL, NULL,
                           NULL);
          xfree (optstr);
        }
    }


  /* Now ask the Pinentry for its PID.  If the Pinentry is new enough
     it will send the pid back and we will use an inquire to notify
     our client.  The client may answer the inquiry either with END or
     with CAN to cancel the pinentry. */
  rc = assuan_transact (entry_ctx, "GETINFO pid",
                        getinfo_pid_cb, &pinentry_pid,
                        NULL, NULL, NULL, NULL);
  if (rc)
    {
      log_info ("You may want to update to a newer pinentry\n");
      rc = 0;
    }
  else if (!rc && (pid_t)pinentry_pid == (pid_t)(-1))
    log_error ("pinentry did not return a PID\n");
  else
    {
      rc = agent_inq_pinentry_launched (ctrl, pinentry_pid);
      if (gpg_err_code (rc) == GPG_ERR_CANCELED
          || gpg_err_code (rc) == GPG_ERR_FULLY_CANCELED)
        return unlock_pinentry (gpg_err_make (GPG_ERR_SOURCE_DEFAULT,
                                              gpg_err_code (rc)));
      rc = 0;
    }

  return 0;
}