Example #1
0
/* Helper to evaluate the error code ERR from a send_request() call
   with REQUEST.  The function returns true if the caller shall try
   again.  TRIES_LEFT points to a variable to track the number of
   retries; this function decrements it and won't return true if it is
   down to zero. */
static int
handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
                           unsigned int *tries_left)
{
  int retry = 0;

  /* Fixme: Should we disable all hosts of a protocol family if a
   * request for an address of that familiy returned ENETDOWN?  */

  switch (gpg_err_code (err))
    {
    case GPG_ERR_ECONNREFUSED:
      if (tor_not_running_p (ctrl))
        break; /* A retry does not make sense.  */
      /* Okay: Tor is up or --use-tor is not used.  */
      /*FALLTHRU*/
    case GPG_ERR_ENETUNREACH:
    case GPG_ERR_ENETDOWN:
    case GPG_ERR_UNKNOWN_HOST:
    case GPG_ERR_NETWORK:
    case GPG_ERR_EIO:  /* Sometimes used by estream cookie functions.  */
    case GPG_ERR_EADDRNOTAVAIL:  /* e.g. when IPv6 is disabled */
    case GPG_ERR_EAFNOSUPPORT:  /* e.g. when IPv6 is not compiled in */
      if (mark_host_dead (request) && *tries_left)
        retry = 1;
      break;

    case GPG_ERR_ETIMEDOUT:
      if (*tries_left)
        {
          log_info ("selecting a different host due to a timeout\n");
          retry = 1;
        }
      break;

    case GPG_ERR_EACCES:
      if (dirmngr_use_tor ())
        {
          log_info ("(Tor configuration problem)\n");
          dirmngr_status (ctrl, "WARNING", "tor_config_problem 0",
                          "Please check that the \"SocksPort\" flag "
                          "\"IPv6Traffic\" is set in torrc", NULL);
        }
      break;

    default:
      break;
    }

  if (*tries_left)
    --*tries_left;

  return retry;
}
Example #2
0
File: ocsp.c Project: FMayzek/gnupg
/* Validate that CERT is indeed valid to sign an OCSP response. If
   SIGNER_FPR_LIST is not NULL we simply check that CERT matches one
   of the fingerprints in this list. */
static gpg_error_t
validate_responder_cert (ctrl_t ctrl, ksba_cert_t cert,
                         fingerprint_list_t signer_fpr_list)
{
  gpg_error_t err;
  char *fpr;

  if (signer_fpr_list)
    {
      fpr = get_fingerprint_hexstring (cert);
      for (; signer_fpr_list && strcmp (signer_fpr_list->hexfpr, fpr);
           signer_fpr_list = signer_fpr_list->next)
        ;
      if (signer_fpr_list)
        err = 0;
      else
        {
          log_error (_("not signed by a default OCSP signer's certificate"));
          err = gpg_error (GPG_ERR_BAD_CA_CERT);
        }
      xfree (fpr);
    }
  else if (opt.system_daemon)
    {
      err = validate_cert_chain (ctrl, cert, NULL, VALIDATE_MODE_OCSP, NULL);
    }
  else
    {
      /* We avoid duplicating the entire certificate validation code
         from gpgsm here.  Because we have no way calling back to the
         client and letting it compute the validity, we use the ugly
         hack of telling the client that the response will only be
         valid if the certificate given in this status message is
         valid.

         Note, that in theory we could simply ask the client via an
         inquire to validate a certificate but this might involve
         calling DirMngr again recursivly - we can't do that as of now
         (neither DirMngr nor gpgsm have the ability for concurrent
         access to DirMngr.   */

      /* FIXME: We should cache this certificate locally, so that the next
         call to dirmngr won't need to look it up - if this works at
         all. */
      fpr = get_fingerprint_hexstring (cert);
      dirmngr_status (ctrl, "ONLY_VALID_IF_CERT_VALID", fpr, NULL);
      xfree (fpr);
      err = 0;
    }

  return err;
}
Example #3
0
/* Print a warning iff Tor is not running but Tor has been requested.
 * Also return true if it is not running.  */
static int
tor_not_running_p (ctrl_t ctrl)
{
  assuan_fd_t sock;

  if (!dirmngr_use_tor ())
    return 0;

  sock = assuan_sock_connect_byname (NULL, 0, 0, NULL, ASSUAN_SOCK_TOR);
  if (sock != ASSUAN_INVALID_FD)
    {
      assuan_sock_close (sock);
      return 0;
    }

  log_info ("(it seems Tor is not running)\n");
  dirmngr_status (ctrl, "WARNING", "tor_not_running 0",
                  "Tor is enabled but the local Tor daemon"
                  " seems to be down", NULL);
  return 1;
}
Example #4
0
/* Get the key described key the KEYSPEC string from the keyserver
   identified by URI.  On success R_FP has an open stream to read the
   data.  The data will be provided in a format GnuPG can import
   (either a binary OpenPGP message or an armored one).  */
gpg_error_t
ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
{
  gpg_error_t err;
  KEYDB_SEARCH_DESC desc;
  char kidbuf[2+40+1];
  const char *exactname = NULL;
  char *searchkey = NULL;
  char *hostport = NULL;
  char *request = NULL;
  estream_t fp = NULL;
  int reselect;
  char *httphost = NULL;
  unsigned int httpflags;
  unsigned int tries = SEND_REQUEST_RETRIES;

  *r_fp = NULL;

  /* Remove search type indicator and adjust PATTERN accordingly.
     Note that HKP keyservers like the 0x to be present when searching
     by keyid.  We need to re-format the fingerprint and keyids so to
     remove the gpg specific force-use-of-this-key flag ("!").  */
  err = classify_user_id (keyspec, &desc, 1);
  if (err)
    return err;
  switch (desc.mode)
    {
    case KEYDB_SEARCH_MODE_SHORT_KID:
      snprintf (kidbuf, sizeof kidbuf, "0x%08lX", (ulong)desc.u.kid[1]);
      break;
    case KEYDB_SEARCH_MODE_LONG_KID:
      snprintf (kidbuf, sizeof kidbuf, "0x%08lX%08lX",
		(ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
      break;
    case KEYDB_SEARCH_MODE_FPR20:
    case KEYDB_SEARCH_MODE_FPR:
      /* This is a v4 fingerprint. */
      kidbuf[0] = '0';
      kidbuf[1] = 'x';
      bin2hex (desc.u.fpr, 20, kidbuf+2);
      break;

    case KEYDB_SEARCH_MODE_EXACT:
      exactname = desc.u.name;
      break;

    case KEYDB_SEARCH_MODE_FPR16:
      log_error ("HKP keyservers do not support v3 fingerprints\n");
    default:
      return gpg_error (GPG_ERR_INV_USER_ID);
    }

  searchkey = http_escape_string (exactname? exactname : kidbuf,
                                  EXTRA_ESCAPE_CHARS);
  if (!searchkey)
    {
      err = gpg_error_from_syserror ();
      goto leave;
    }

  reselect = 0;
 again:
  /* Build the request string.  */
  xfree (hostport); hostport = NULL;
  xfree (httphost); httphost = NULL;
  err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect,
                        &hostport, &httpflags, &httphost);
  if (err)
    goto leave;

  xfree (request);
  request = strconcat (hostport,
                       "/pks/lookup?op=get&options=mr&search=",
                       searchkey,
                       exactname? "&exact=on":"",
                       NULL);
  if (!request)
    {
      err = gpg_error_from_syserror ();
      goto leave;
    }

  /* Send the request.  */
  err = send_request (ctrl, request, hostport, httphost, httpflags,
                      NULL, NULL, &fp);
  if (handle_send_request_error (err, request, &tries))
    {
      reselect = 1;
      goto again;
    }
  if (err)
    goto leave;

  err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
  if (err)
    goto leave;

  /* Return the read stream and close the HTTP context.  */
  *r_fp = fp;
  fp = NULL;

 leave:
  es_fclose (fp);
  xfree (request);
  xfree (hostport);
  xfree (httphost);
  xfree (searchkey);
  return err;
}
Example #5
0
/* Search the keyserver identified by URI for keys matching PATTERN.
   On success R_FP has an open stream to read the data.  */
gpg_error_t
ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
               estream_t *r_fp)
{
  gpg_error_t err;
  KEYDB_SEARCH_DESC desc;
  char fprbuf[2+40+1];
  char *hostport = NULL;
  char *request = NULL;
  estream_t fp = NULL;
  int reselect;
  unsigned int httpflags;
  char *httphost = NULL;
  unsigned int tries = SEND_REQUEST_RETRIES;

  *r_fp = NULL;

  /* Remove search type indicator and adjust PATTERN accordingly.
     Note that HKP keyservers like the 0x to be present when searching
     by keyid.  We need to re-format the fingerprint and keyids so to
     remove the gpg specific force-use-of-this-key flag ("!").  */
  err = classify_user_id (pattern, &desc, 1);
  if (err)
    return err;
  switch (desc.mode)
    {
    case KEYDB_SEARCH_MODE_EXACT:
    case KEYDB_SEARCH_MODE_SUBSTR:
    case KEYDB_SEARCH_MODE_MAIL:
    case KEYDB_SEARCH_MODE_MAILSUB:
      pattern = desc.u.name;
      break;
    case KEYDB_SEARCH_MODE_SHORT_KID:
      snprintf (fprbuf, sizeof fprbuf, "0x%08lX", (ulong)desc.u.kid[1]);
      pattern = fprbuf;
      break;
    case KEYDB_SEARCH_MODE_LONG_KID:
      snprintf (fprbuf, sizeof fprbuf, "0x%08lX%08lX",
                (ulong)desc.u.kid[0], (ulong)desc.u.kid[1]);
      pattern = fprbuf;
      break;
    case KEYDB_SEARCH_MODE_FPR16:
      bin2hex (desc.u.fpr, 16, fprbuf);
      pattern = fprbuf;
      break;
    case KEYDB_SEARCH_MODE_FPR20:
    case KEYDB_SEARCH_MODE_FPR:
      bin2hex (desc.u.fpr, 20, fprbuf);
      pattern = fprbuf;
      break;
    default:
      return gpg_error (GPG_ERR_INV_USER_ID);
    }

  /* Build the request string.  */
  reselect = 0;
 again:
  {
    char *searchkey;

    xfree (hostport); hostport = NULL;
    xfree (httphost); httphost = NULL;
    err = make_host_part (ctrl, uri->scheme, uri->host, uri->port, reselect,
                          &hostport, &httpflags, &httphost);
    if (err)
      goto leave;

    searchkey = http_escape_string (pattern, EXTRA_ESCAPE_CHARS);
    if (!searchkey)
      {
        err = gpg_error_from_syserror ();
        goto leave;
      }

    xfree (request);
    request = strconcat (hostport,
                         "/pks/lookup?op=index&options=mr&search=",
                         searchkey,
                         NULL);
    xfree (searchkey);
    if (!request)
      {
        err = gpg_error_from_syserror ();
        goto leave;
      }
  }

  /* Send the request.  */
  err = send_request (ctrl, request, hostport, httphost, httpflags,
                      NULL, NULL, &fp);
  if (handle_send_request_error (err, request, &tries))
    {
      reselect = 1;
      goto again;
    }
  if (err)
    goto leave;

  err = dirmngr_status (ctrl, "SOURCE", hostport, NULL);
  if (err)
    goto leave;

  /* Peek at the response.  */
  {
    int c = es_getc (fp);
    if (c == -1)
      {
        err = es_ferror (fp)?gpg_error_from_syserror ():gpg_error (GPG_ERR_EOF);
        log_error ("error reading response: %s\n", gpg_strerror (err));
        goto leave;
      }
    if (c == '<')
      {
        /* The document begins with a '<': Assume a HTML response,
           which we don't support.  */
        err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
        goto leave;
      }
    es_ungetc (c, fp);
  }

  /* Return the read stream.  */
  *r_fp = fp;
  fp = NULL;

 leave:
  es_fclose (fp);
  xfree (request);
  xfree (hostport);
  xfree (httphost);
  return err;
}