예제 #1
0
파일: certdump.c 프로젝트: FMayzek/gnupg
void
gpgsm_print_time (estream_t fp, ksba_isotime_t t)
{
  if (!t || !*t)
    es_fputs (_("none"), fp);
  else
    es_fprintf (fp, "%.4s-%.2s-%.2s %.2s:%.2s:%s",
                t, t+4, t+6, t+9, t+11, t+13);
}
예제 #2
0
/* Same as above but outputs the error code only.  */
void
write_status_errcode (const char *where, int errcode)
{
  if (!statusfp || !status_currently_allowed (STATUS_ERROR))
    return;  /* Not enabled or allowed. */

  es_fprintf (statusfp, "[GNUPG:] %s %s %u\n",
              get_status_string (STATUS_ERROR), where, gpg_err_code (errcode));
  if (es_fflush (statusfp) && opt.exit_on_status_write_error)
    g10_exit (0);
}
예제 #3
0
파일: certdump.c 프로젝트: FMayzek/gnupg
/* Print a DN part to STREAM or if STREAM is NULL to FP. */
static void
print_dn_part (FILE *fp, estream_t stream,
               struct dn_array_s *dn, const char *key, int translate)
{
  struct dn_array_s *first_dn = dn;

  for (; dn->key; dn++)
    {
      if (!dn->done && !strcmp (dn->key, key))
        {
          /* Forward to the last multi-valued RDN, so that we can
             print them all in reverse in the correct order.  Note
             that this overrides the the standard sequence but that
             seems to a reasonable thing to do with multi-valued
             RDNs. */
          while (dn->multivalued && dn[1].key)
            dn++;
        next:
          if (!dn->done && dn->value && *dn->value)
            {
              if (stream)
                {
                  es_fprintf (stream, "/%s=", dn->key);
                  if (translate)
                    es_write_sanitized_utf8_buffer (stream, dn->value,
                                                    strlen (dn->value),
                                                    "/", NULL);
                  else
                    es_write_sanitized (stream, dn->value, strlen (dn->value),
                                        "/", NULL);
                }
              else
                {
                  fprintf (fp, "/%s=", dn->key);
                  if (translate)
                    print_sanitized_utf8_string (fp, dn->value, '/');
                  else
                    print_sanitized_string (fp, dn->value, '/');
                }
            }
          dn->done = 1;
          if (dn > first_dn && dn[-1].multivalued)
            {
              dn--;
              goto next;
            }
        }
    }
}
예제 #4
0
파일: t-poll.c 프로젝트: cobaugh/rt-rpm
/* This thread feeds data to the given stream.  */
static THREAD_RET_TYPE
producer_thread (void *argaddr)
{
  struct thread_arg *arg = argaddr;
  int i = 0;

  (void)arg;

  while (!arg->stop_me && i++ < 3)
    {
      show ("thread '%s' about to write\n", arg->name);
      es_fprintf (arg->stream, "This is '%s' count=%d\n", arg->name, i);
      es_fflush (arg->stream);
    }
  es_fclose (arg->stream);
  return THREAD_RET_VALUE;
}
예제 #5
0
/* Helper for ks_hkp_put.  */
static gpg_error_t
put_post_cb (void *opaque, http_t http)
{
  struct put_post_parm_s *parm = opaque;
  gpg_error_t err = 0;
  estream_t fp;
  size_t len;

  fp = http_get_write_ptr (http);
  len = strlen (parm->datastring);

  es_fprintf (fp,
              "Content-Type: application/x-www-form-urlencoded\r\n"
              "Content-Length: %zu\r\n", len+8 /* 8 is for "keytext" */);
  http_start_data (http);
  if (es_fputs ("keytext=", fp) || es_write (fp, parm->datastring, len, NULL))
    err = gpg_error_from_syserror ();
  return err;
}
예제 #6
0
파일: tdbdump.c 프로젝트: larryv/gnupg
/*
 * Dump the entire trustdb to FP or only the entries of one key.
 */
void
list_trustdb (ctrl_t ctrl, estream_t fp, const char *username)
{
  TRUSTREC rec;

  (void)username;

  init_trustdb (ctrl, 0);
  /* For now we ignore the user ID. */
  if (1)
    {
      ulong recnum;
      int i;

      es_fprintf (fp, "TrustDB: %s\n", tdbio_get_dbname ());
      for (i = 9 + strlen (tdbio_get_dbname()); i > 0; i-- )
        es_fputc ('-', fp);
      es_putc ('\n', fp);
      for (recnum=0; !tdbio_read_record (recnum, &rec, 0); recnum++)
        tdbio_dump_record (&rec, fp);
    }
}
예제 #7
0
파일: ttyio.c 프로젝트: 0ndorio/gnupg
/****************
 * Print a string, but filter all control characters out.  If FP is
 * not NULL print to that stream instead to the tty.
 */
void
tty_print_string (estream_t fp, const byte *p, size_t n )
{
    if (no_terminal && !fp)
        return;

    if( !initialized & !fp)
        init_ttyfp();

#ifdef USE_W32_CONSOLE
    /* not so effective, change it if you want */
    if (fp)
    {
        for( ; n; n--, p++ )
        {
            if( iscntrl( *p ) )
            {
                if( *p == '\n' )
                    tty_fprintf (fp, "\\n");
                else if( !*p )
                    tty_fprintf (fp, "\\0");
                else
                    tty_fprintf (fp, "\\x%02x", *p);
            }
            else
                tty_fprintf (fp, "%c", *p);
        }
    }
    else
    {
        for( ; n; n--, p++ )
        {
            if( iscntrl( *p ) )
            {
                if( *p == '\n' )
                    tty_printf ("\\n");
                else if( !*p )
                    tty_printf ("\\0");
                else
                    tty_printf ("\\x%02x", *p);
            }
            else
                tty_printf ("%c", *p);
        }
    }
#else
    if (fp)
    {
        for( ; n; n--, p++ )
        {
            if (iscntrl (*p))
            {
                es_putc ('\\', fp);
                if ( *p == '\n' )
                    es_putc ('n', fp);
                else if ( !*p )
                    es_putc ('0', fp);
                else
                    es_fprintf (fp, "x%02x", *p);
            }
            else
                es_putc (*p, fp);
        }
    }
    else
    {
        for (; n; n--, p++)
        {
            if (iscntrl (*p))
            {
                putc ('\\', ttyfp);
                if ( *p == '\n' )
                    putc ('n', ttyfp);
                else if ( !*p )
                    putc ('0', ttyfp);
                else
                    fprintf (ttyfp, "x%02x", *p );
            }
            else
                putc (*p, ttyfp);
        }
    }
#endif
}
예제 #8
0
파일: logging.c 프로젝트: 0ndorio/gnupg
static gpgrt_ssize_t
fun_writer (void *cookie_arg, const void *buffer, size_t size)
{
  struct fun_cookie_s *cookie = cookie_arg;

  /* FIXME: Use only estream with a callback for socket writing.  This
     avoids the ugly mix of fd and estream code.  */

  /* Note that we always try to reconnect to the socket but print
     error messages only the first time an error occurred.  If
     RUNNING_DETACHED is set we don't fall back to stderr and even do
     not print any error messages.  This is needed because detached
     processes often close stderr and by writing to file descriptor 2
     we might send the log message to a file not intended for logging
     (e.g. a pipe or network connection). */
  if (cookie->want_socket && cookie->fd == -1)
    {
#ifdef WITH_IPV6
      struct sockaddr_in6 srvr_addr_in6;
#endif
      struct sockaddr_in srvr_addr_in;
#ifndef HAVE_W32_SYSTEM
      struct sockaddr_un srvr_addr_un;
#endif
      size_t addrlen;
      struct sockaddr *srvr_addr = NULL;
      unsigned short port = 0;
      int af = AF_LOCAL;
      int pf = PF_LOCAL;
      const char *name = cookie->name;

      /* Not yet open or meanwhile closed due to an error. */
      cookie->is_socket = 0;

      /* Check whether this is a TCP socket or a local socket.  */
      if (!strncmp (name, "tcp://", 6) && name[6])
        {
          name += 6;
          af = AF_INET;
          pf = PF_INET;
        }
#ifndef HAVE_W32_SYSTEM
      else if (!strncmp (name, "socket://", 9) && name[9])
        name += 9;
#endif

      if (af == AF_LOCAL)
        {
#ifdef HAVE_W32_SYSTEM
          addrlen = 0;
#else
          memset (&srvr_addr, 0, sizeof srvr_addr);
          srvr_addr_un.sun_family = af;
          strncpy (srvr_addr_un.sun_path,
                   name, sizeof (srvr_addr_un.sun_path)-1);
          srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path)-1] = 0;
          srvr_addr = (struct sockaddr *)&srvr_addr_un;
          addrlen = SUN_LEN (&srvr_addr_un);
#endif
        }
      else
        {
          char *addrstr, *p;
#ifdef HAVE_INET_PTON
          void *addrbuf = NULL;
#endif /*HAVE_INET_PTON*/

          addrstr = xtrymalloc (strlen (name) + 1);
          if (!addrstr)
            addrlen = 0; /* This indicates an error.  */
          else if (*name == '[')
            {
              /* Check for IPv6 literal address.  */
              strcpy (addrstr, name+1);
              p = strchr (addrstr, ']');
              if (!p || p[1] != ':' || !parse_portno (p+2, &port))
                {
                  gpg_err_set_errno (EINVAL);
                  addrlen = 0;
                }
              else
                {
                  *p = 0;
#ifdef WITH_IPV6
                  af = AF_INET6;
                  pf = PF_INET6;
                  memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6);
                  srvr_addr_in6.sin6_family = af;
                  srvr_addr_in6.sin6_port = htons (port);
#ifdef HAVE_INET_PTON
                  addrbuf = &srvr_addr_in6.sin6_addr;
#endif /*HAVE_INET_PTON*/
                  srvr_addr = (struct sockaddr *)&srvr_addr_in6;
                  addrlen = sizeof srvr_addr_in6;
#else
                  gpg_err_set_errno (EAFNOSUPPORT);
                  addrlen = 0;
#endif
                }
            }
          else
            {
              /* Check for IPv4 literal address.  */
              strcpy (addrstr, name);
              p = strchr (addrstr, ':');
              if (!p || !parse_portno (p+1, &port))
                {
                  gpg_err_set_errno (EINVAL);
                  addrlen = 0;
                }
              else
                {
                  *p = 0;
                  memset (&srvr_addr_in, 0, sizeof srvr_addr_in);
                  srvr_addr_in.sin_family = af;
                  srvr_addr_in.sin_port = htons (port);
#ifdef HAVE_INET_PTON
                  addrbuf = &srvr_addr_in.sin_addr;
#endif /*HAVE_INET_PTON*/
                  srvr_addr = (struct sockaddr *)&srvr_addr_in;
                  addrlen = sizeof srvr_addr_in;
                }
            }

          if (addrlen)
            {
#ifdef HAVE_INET_PTON
              if (inet_pton (af, addrstr, addrbuf) != 1)
                addrlen = 0;
#else /*!HAVE_INET_PTON*/
              /* We need to use the old function.  If we are here v6
                 support isn't enabled anyway and thus we can do fine
                 without.  Note that Windows has a compatible inet_pton
                 function named inetPton, but only since Vista.  */
              srvr_addr_in.sin_addr.s_addr = inet_addr (addrstr);
              if (srvr_addr_in.sin_addr.s_addr == INADDR_NONE)
                addrlen = 0;
#endif /*!HAVE_INET_PTON*/
            }

          xfree (addrstr);
        }

      cookie->fd = addrlen? socket (pf, SOCK_STREAM, 0) : -1;
      if (cookie->fd == -1)
        {
          if (!cookie->quiet && !running_detached
              && isatty (es_fileno (es_stderr)))
            es_fprintf (es_stderr, "failed to create socket for logging: %s\n",
                        strerror(errno));
        }
      else
        {
          if (connect (cookie->fd, srvr_addr, addrlen) == -1)
            {
              if (!cookie->quiet && !running_detached
                  && isatty (es_fileno (es_stderr)))
                es_fprintf (es_stderr, "can't connect to '%s': %s\n",
                            cookie->name, strerror(errno));
              sock_close (cookie->fd);
              cookie->fd = -1;
            }
        }

      if (cookie->fd == -1)
        {
          if (!running_detached)
            {
              /* Due to all the problems with apps not running
                 detached but being called with stderr closed or used
                 for a different purposes, it does not make sense to
                 switch to stderr.  We therefore disable it. */
              if (!cookie->quiet)
                {
                  /* fputs ("switching logging to stderr\n", stderr);*/
                  cookie->quiet = 1;
                }
              cookie->fd = -1; /*fileno (stderr);*/
            }
        }
      else /* Connection has been established. */
        {
          cookie->quiet = 0;
          cookie->is_socket = 1;
        }
    }

  log_socket = cookie->fd;
  if (cookie->fd != -1)
    {
#ifdef HAVE_W32CE_SYSTEM
      if (cookie->use_writefile)
        {
          DWORD nwritten;

          WriteFile ((HANDLE)cookie->fd, buffer, size, &nwritten, NULL);
          return (gpgrt_ssize_t)size; /* Okay.  */
        }
#endif
      if (!writen (cookie->fd, buffer, size, cookie->is_socket))
        return (gpgrt_ssize_t)size; /* Okay. */
    }

  if (!running_detached && cookie->fd != -1
      && isatty (es_fileno (es_stderr)))
    {
      if (*cookie->name)
        es_fprintf (es_stderr, "error writing to '%s': %s\n",
                    cookie->name, strerror(errno));
      else
        es_fprintf (es_stderr, "error writing to file descriptor %d: %s\n",
                    cookie->fd, strerror(errno));
    }
  if (cookie->is_socket && cookie->fd != -1)
    {
      sock_close (cookie->fd);
      cookie->fd = -1;
      log_socket = -1;
    }

  return (gpgrt_ssize_t)size;
}
예제 #9
0
/*
 * Write a status line with a buffer using %XX escapes.  If WRAP is >
 * 0 wrap the line after this length.  If STRING is not NULL it will
 * be prepended to the buffer, no escaping is done for string.
 * A wrap of -1 forces spaces not to be encoded as %20.
 */
void
write_status_text_and_buffer (int no, const char *string,
                              const char *buffer, size_t len, int wrap)
{
  const char *s, *text;
  int esc, first;
  int lower_limit = ' ';
  size_t n, count, dowrap;

  if (!statusfp || !status_currently_allowed (no))
    return;  /* Not enabled or allowed. */

  if (wrap == -1)
    {
      lower_limit--;
      wrap = 0;
    }

  text = get_status_string (no);
  count = dowrap = first = 1;
  do
    {
      if (dowrap)
        {
          es_fprintf (statusfp, "[GNUPG:] %s ", text);
          count = dowrap = 0;
          if (first && string)
            {
              es_fputs (string, statusfp);
              count += strlen (string);
              /* Make sure that there is a space after the string.  */
              if (*string && string[strlen (string)-1] != ' ')
                {
                  es_putc (' ', statusfp);
                  count++;
                }
            }
          first = 0;
        }
      for (esc=0, s=buffer, n=len; n && !esc; s++, n--)
        {
          if (*s == '%' || *(const byte*)s <= lower_limit
              || *(const byte*)s == 127 )
            esc = 1;
          if (wrap && ++count > wrap)
            {
              dowrap=1;
              break;
            }
        }
      if (esc)
        {
          s--; n++;
        }
      if (s != buffer)
        es_fwrite (buffer, s-buffer, 1, statusfp);
      if ( esc )
        {
          es_fprintf (statusfp, "%%%02X", *(const byte*)s );
          s++; n--;
        }
      buffer = s;
      len = n;
      if (dowrap && len)
        es_putc ('\n', statusfp);
    }
  while (len);

  es_putc ('\n',statusfp);
  if (es_fflush (statusfp) && opt.exit_on_status_write_error)
    g10_exit (0);
}
예제 #10
0
파일: gpgconf.c 프로젝트: 0ndorio/gnupg
/* gpgconf main. */
int
main (int argc, char **argv)
{
  ARGPARSE_ARGS pargs;
  const char *fname;
  int no_more_options = 0;
  enum cmd_and_opt_values cmd = 0;
  estream_t outfp = NULL;

  early_system_init ();
  gnupg_reopen_std (GPGCONF_NAME);
  set_strusage (my_strusage);
  log_set_prefix (GPGCONF_NAME, 1);

  /* Make sure that our subsystems are ready.  */
  i18n_init();
  init_common_subsystems (&argc, &argv);

  /* Parse the command line. */
  pargs.argc  = &argc;
  pargs.argv  = &argv;
  pargs.flags =  1;  /* Do not remove the args.  */
  while (!no_more_options && optfile_parse (NULL, NULL, NULL, &pargs, opts))
    {
      switch (pargs.r_opt)
        {
        case oOutput:    opt.outfile = pargs.r.ret_str; break;
	case oQuiet:     opt.quiet = 1; break;
        case oDryRun:    opt.dry_run = 1; break;
        case oRuntime:
	  opt.runtime = 1;
	  break;
        case oVerbose:   opt.verbose++; break;
        case oNoVerbose: opt.verbose = 0; break;

	case aListDirs:
        case aListComponents:
        case aCheckPrograms:
        case aListOptions:
        case aChangeOptions:
        case aCheckOptions:
        case aApplyDefaults:
        case aListConfig:
        case aCheckConfig:
        case aReload:
        case aLaunch:
        case aKill:
	  cmd = pargs.r_opt;
	  break;

        default: pargs.err = 2; break;
	}
    }

  if (log_get_errorcount (0))
    exit (2);

  /* Print a warning if an argument looks like an option.  */
  if (!opt.quiet && !(pargs.flags & ARGPARSE_FLAG_STOP_SEEN))
    {
      int i;

      for (i=0; i < argc; i++)
        if (argv[i][0] == '-' && argv[i][1] == '-')
          log_info (_("Note: '%s' is not considered an option\n"), argv[i]);
    }

  fname = argc ? *argv : NULL;

  switch (cmd)
    {
    case aListComponents:
    default:
      /* List all components. */
      gc_component_list_components (get_outfp (&outfp));
      break;

    case aCheckPrograms:
      /* Check all programs. */
      gc_check_programs (get_outfp (&outfp));
      break;

    case aListOptions:
    case aChangeOptions:
    case aCheckOptions:
      if (!fname)
	{
	  es_fprintf (es_stderr, _("usage: %s [options] "), GPGCONF_NAME);
	  es_putc ('\n', es_stderr);
	  es_fputs (_("Need one component argument"), es_stderr);
	  es_putc ('\n', es_stderr);
	  exit (2);
	}
      else
	{
	  int idx = gc_component_find (fname);
	  if (idx < 0)
	    {
	      es_fputs (_("Component not found"), es_stderr);
	      es_putc ('\n', es_stderr);
	      exit (1);
	    }
          if (cmd == aCheckOptions)
	    gc_component_check_options (idx, get_outfp (&outfp), NULL);
          else
            {
              gc_component_retrieve_options (idx);
              if (gc_process_gpgconf_conf (NULL, 1, 0, NULL))
                exit (1);
              if (cmd == aListOptions)
                gc_component_list_options (idx, get_outfp (&outfp));
              else if (cmd == aChangeOptions)
                gc_component_change_options (idx, es_stdin, get_outfp (&outfp));
            }
	}
      break;

    case aLaunch:
    case aKill:
      if (!fname)
	{
	  es_fprintf (es_stderr, _("usage: %s [options] "), GPGCONF_NAME);
	  es_putc ('\n', es_stderr);
	  es_fputs (_("Need one component argument"), es_stderr);
	  es_putc ('\n', es_stderr);
	  exit (2);
	}
      else
        {
          /* Launch/Kill a given component.  */
          int idx;

          idx = gc_component_find (fname);
          if (idx < 0)
            {
              es_fputs (_("Component not found"), es_stderr);
              es_putc ('\n', es_stderr);
              exit (1);
            }
          else if (cmd == aLaunch)
            {
              if (gc_component_launch (idx))
                exit (1);
            }
          else
            {
              /* We don't error out if the kill failed because this
                 command should do nothing if the component is not
                 running.  */
              gc_component_kill (idx);
            }
        }
      break;

    case aReload:
      if (!fname)
	{
          /* Reload all.  */
          gc_component_reload (-1);
	}
      else
        {
          /* Reload given component.  */
          int idx;

          idx = gc_component_find (fname);
          if (idx < 0)
            {
              es_fputs (_("Component not found"), es_stderr);
              es_putc ('\n', es_stderr);
              exit (1);
            }
          else
            {
              gc_component_reload (idx);
            }
        }
      break;

    case aListConfig:
      if (gc_process_gpgconf_conf (fname, 0, 0, get_outfp (&outfp)))
        exit (1);
      break;

    case aCheckConfig:
      if (gc_process_gpgconf_conf (fname, 0, 0, NULL))
        exit (1);
      break;

    case aApplyDefaults:
      if (fname)
	{
	  es_fprintf (es_stderr, _("usage: %s [options] "), GPGCONF_NAME);
	  es_putc ('\n', es_stderr);
	  es_fputs (_("No argument allowed"), es_stderr);
	  es_putc ('\n', es_stderr);
	  exit (2);
	}
      gc_component_retrieve_options (-1);
      if (gc_process_gpgconf_conf (NULL, 1, 1, NULL))
        exit (1);
      break;

    case aListDirs:
      /* Show the system configuration directories for gpgconf.  */
      get_outfp (&outfp);
      es_fprintf (outfp, "sysconfdir:%s\n",
                  gc_percent_escape (gnupg_sysconfdir ()));
      es_fprintf (outfp, "bindir:%s\n",
                  gc_percent_escape (gnupg_bindir ()));
      es_fprintf (outfp, "libexecdir:%s\n",
                  gc_percent_escape (gnupg_libexecdir ()));
      es_fprintf (outfp, "libdir:%s\n",
                  gc_percent_escape (gnupg_libdir ()));
      es_fprintf (outfp, "datadir:%s\n",
                  gc_percent_escape (gnupg_datadir ()));
      es_fprintf (outfp, "localedir:%s\n",
                  gc_percent_escape (gnupg_localedir ()));

      if (dirmngr_user_socket_name ())
        {
          es_fprintf (outfp, "dirmngr-socket:%s\n",
                      gc_percent_escape (dirmngr_user_socket_name ()));
          es_fprintf (outfp, "dirmngr-sys-socket:%s\n",
                      gc_percent_escape (dirmngr_sys_socket_name ()));
        }
      else
        {
          es_fprintf (outfp, "dirmngr-socket:%s\n",
                      gc_percent_escape (dirmngr_sys_socket_name ()));
        }

      {
        char *tmp = make_filename (default_homedir (),
                                   GPG_AGENT_SOCK_NAME, NULL);
        es_fprintf (outfp, "agent-socket:%s\n", gc_percent_escape (tmp));
        xfree (tmp);
      }
      {
        /* We need to use make_filename to expand a possible "~/".  */
        char *tmp = make_filename (default_homedir (), NULL);
        es_fprintf (outfp, "homedir:%s\n", gc_percent_escape (tmp));
        xfree (tmp);
      }
      break;
    }

  if (outfp != es_stdout)
    if (es_fclose (outfp))
      gc_error (1, errno, "error closing '%s'", opt.outfile);

  return 0;
}
예제 #11
0
파일: ocsp.c 프로젝트: FMayzek/gnupg
/* Construct an OCSP request, send it to the configured OCSP responder
   and parse the response. On success the OCSP context may be used to
   further process the reponse. */
static gpg_error_t
do_ocsp_request (ctrl_t ctrl, ksba_ocsp_t ocsp, gcry_md_hd_t md,
                 const char *url, ksba_cert_t cert, ksba_cert_t issuer_cert)
{
  gpg_error_t err;
  unsigned char *request, *response;
  size_t requestlen, responselen;
  http_t http;
  ksba_ocsp_response_status_t response_status;
  const char *t;
  int redirects_left = 2;
  char *free_this = NULL;

  (void)ctrl;

  if (opt.disable_http)
    {
      log_error (_("OCSP request not possible due to disabled HTTP\n"));
      return gpg_error (GPG_ERR_NOT_SUPPORTED);
    }

  err = ksba_ocsp_add_target (ocsp, cert, issuer_cert);
  if (err)
    {
      log_error (_("error setting OCSP target: %s\n"), gpg_strerror (err));
      return err;
    }

  {
    size_t n;
    unsigned char nonce[32];

    n = ksba_ocsp_set_nonce (ocsp, NULL, 0);
    if (n > sizeof nonce)
      n = sizeof nonce;
    gcry_create_nonce (nonce, n);
    ksba_ocsp_set_nonce (ocsp, nonce, n);
  }

  err = ksba_ocsp_build_request (ocsp, &request, &requestlen);
  if (err)
    {
      log_error (_("error building OCSP request: %s\n"), gpg_strerror (err));
      return err;
    }

 once_more:
  err = http_open (&http, HTTP_REQ_POST, url, NULL,
                   (opt.honor_http_proxy? HTTP_FLAG_TRY_PROXY:0),
                   opt.http_proxy, NULL, NULL, NULL);
  if (err)
    {
      log_error (_("error connecting to '%s': %s\n"), url, gpg_strerror (err));
      xfree (free_this);
      return err;
    }

  es_fprintf (http_get_write_ptr (http),
	      "Content-Type: application/ocsp-request\r\n"
	      "Content-Length: %lu\r\n",
	      (unsigned long)requestlen );
  http_start_data (http);
  if (es_fwrite (request, requestlen, 1, http_get_write_ptr (http)) != 1)
    {
      err = gpg_error_from_errno (errno);
      log_error ("error sending request to '%s': %s\n", url, strerror (errno));
      http_close (http, 0);
      xfree (request);
      xfree (free_this);
      return err;
    }
  xfree (request);
  request = NULL;

  err = http_wait_response (http);
  if (err || http_get_status_code (http) != 200)
    {
      if (err)
        log_error (_("error reading HTTP response for '%s': %s\n"),
                   url, gpg_strerror (err));
      else
        {
          switch (http_get_status_code (http))
            {
            case 301:
            case 302:
              {
                const char *s = http_get_header (http, "Location");

                log_info (_("URL '%s' redirected to '%s' (%u)\n"),
                          url, s?s:"[none]", http_get_status_code (http));
                if (s && *s && redirects_left-- )
                  {
                    xfree (free_this); url = NULL;
                    free_this = xtrystrdup (s);
                    if (!free_this)
                      err = gpg_error_from_errno (errno);
                    else
                      {
                        url = free_this;
                        http_close (http, 0);
                        goto once_more;
                      }
                  }
                else
                  err = gpg_error (GPG_ERR_NO_DATA);
                log_error (_("too many redirections\n"));
              }
              break;

            default:
              log_error (_("error accessing '%s': http status %u\n"),
                         url, http_get_status_code (http));
              err = gpg_error (GPG_ERR_NO_DATA);
              break;
            }
        }
      http_close (http, 0);
      xfree (free_this);
      return err;
    }

  err = read_response (http_get_read_ptr (http), &response, &responselen);
  http_close (http, 0);
  if (err)
    {
      log_error (_("error reading HTTP response for '%s': %s\n"),
                 url, gpg_strerror (err));
      xfree (free_this);
      return err;
    }

  err = ksba_ocsp_parse_response (ocsp, response, responselen,
                                  &response_status);
  if (err)
    {
      log_error (_("error parsing OCSP response for '%s': %s\n"),
                 url, gpg_strerror (err));
      xfree (response);
      xfree (free_this);
      return err;
    }

  switch (response_status)
    {
    case KSBA_OCSP_RSPSTATUS_SUCCESS:      t = "success"; break;
    case KSBA_OCSP_RSPSTATUS_MALFORMED:    t = "malformed"; break;
    case KSBA_OCSP_RSPSTATUS_INTERNAL:     t = "internal error"; break;
    case KSBA_OCSP_RSPSTATUS_TRYLATER:     t = "try later"; break;
    case KSBA_OCSP_RSPSTATUS_SIGREQUIRED:  t = "must sign request"; break;
    case KSBA_OCSP_RSPSTATUS_UNAUTHORIZED: t = "unauthorized"; break;
    case KSBA_OCSP_RSPSTATUS_REPLAYED:     t = "replay detected"; break;
    case KSBA_OCSP_RSPSTATUS_OTHER:        t = "other (unknown)"; break;
    case KSBA_OCSP_RSPSTATUS_NONE:         t = "no status"; break;
    default:                               t = "[unknown status]"; break;
    }
  if (response_status == KSBA_OCSP_RSPSTATUS_SUCCESS)
    {
      if (opt.verbose)
        log_info (_("OCSP responder at '%s' status: %s\n"), url, t);

      err = ksba_ocsp_hash_response (ocsp, response, responselen,
                                     HASH_FNC, md);
      if (err)
        log_error (_("hashing the OCSP response for '%s' failed: %s\n"),
                   url, gpg_strerror (err));
    }
  else
    {
      log_error (_("OCSP responder at '%s' status: %s\n"), url, t);
      err = gpg_error (GPG_ERR_GENERAL);
    }

  xfree (response);
  xfree (free_this);
  return err;
}
예제 #12
0
int
main (int argc, char **argv )
{
  ARGPARSE_ARGS pargs;
  int orig_argc;
  gpg_error_t err;
  int may_coredump;
  char **orig_argv;
  FILE *configfp = NULL;
  char *configname = NULL;
  const char *shell;
  unsigned int configlineno;
  int parse_debug = 0;
  const char *debug_level = NULL;
  int default_config =1;
  int greeting = 0;
  int nogreeting = 0;
  int multi_server = 0;
  int is_daemon = 0;
  int nodetach = 0;
  int csh_style = 0;
  char *logfile = NULL;
  int debug_wait = 0;
  int gpgconf_list = 0;
  const char *config_filename = NULL;
  int allow_coredump = 0;
  int standard_socket = 0;
  struct assuan_malloc_hooks malloc_hooks;

  set_strusage (my_strusage);
  gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
  /* Please note that we may running SUID(ROOT), so be very CAREFUL
     when adding any stuff between here and the call to INIT_SECMEM()
     somewhere after the option parsing */
  log_set_prefix ("scdaemon", 1|4);

  /* Make sure that our subsystems are ready.  */
  i18n_init ();
  init_common_subsystems (&argc, &argv);


  /* Libgcrypt requires us to register the threading model first.
     Note that this will also do the pth_init. */
  gcry_threads_pth.init = fixed_gcry_pth_init;
  err = gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
  if (err)
    {
      log_fatal ("can't register GNU Pth with Libgcrypt: %s\n",
                 gpg_strerror (err));
    }

  /* Check that the libraries are suitable.  Do it here because
     the option parsing may need services of the library */
  if (!gcry_check_version (NEED_LIBGCRYPT_VERSION) )
    {
      log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
                 NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL) );
    }

  ksba_set_malloc_hooks (gcry_malloc, gcry_realloc, gcry_free);

  malloc_hooks.malloc = gcry_malloc;
  malloc_hooks.realloc = gcry_realloc;
  malloc_hooks.free = gcry_free;
  assuan_set_malloc_hooks (&malloc_hooks);
  assuan_set_gpg_err_source (GPG_ERR_SOURCE_DEFAULT);
  assuan_set_system_hooks (ASSUAN_SYSTEM_PTH);
  assuan_sock_init ();
  setup_libassuan_logging (&opt.debug);

  setup_libgcrypt_logging ();
  gcry_control (GCRYCTL_USE_SECURE_RNDPOOL);

  may_coredump = disable_core_dumps ();

  /* Set default options. */
  opt.allow_admin = 1;
  opt.pcsc_driver = DEFAULT_PCSC_DRIVER;

#ifdef HAVE_W32_SYSTEM
  standard_socket = 1;  /* Under Windows we always use a standard
                           socket.  */
#endif


  shell = getenv ("SHELL");
  if (shell && strlen (shell) >= 3 && !strcmp (shell+strlen (shell)-3, "csh") )
    csh_style = 1;

  opt.homedir = default_homedir ();

  /* Check whether we have a config file on the commandline */
  orig_argc = argc;
  orig_argv = argv;
  pargs.argc = &argc;
  pargs.argv = &argv;
  pargs.flags= 1|(1<<6);  /* do not remove the args, ignore version */
  while (arg_parse( &pargs, opts))
    {
      if (pargs.r_opt == oDebug || pargs.r_opt == oDebugAll)
        parse_debug++;
      else if (pargs.r_opt == oOptions)
        { /* yes there is one, so we do not try the default one, but
	     read the option file when it is encountered at the
	     commandline */
          default_config = 0;
	}
	else if (pargs.r_opt == oNoOptions)
          default_config = 0; /* --no-options */
	else if (pargs.r_opt == oHomedir)
          opt.homedir = pargs.r.ret_str;
    }

  /* initialize the secure memory. */
  gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
  maybe_setuid = 0;

  /*
     Now we are working under our real uid
  */


  if (default_config)
    configname = make_filename (opt.homedir, "scdaemon.conf", NULL );


  argc = orig_argc;
  argv = orig_argv;
  pargs.argc = &argc;
  pargs.argv = &argv;
  pargs.flags=  1;  /* do not remove the args */
 next_pass:
  if (configname)
    {
      configlineno = 0;
      configfp = fopen (configname, "r");
      if (!configfp)
        {
          if (default_config)
            {
              if( parse_debug )
                log_info (_("NOTE: no default option file `%s'\n"),
                          configname );
	    }
          else
            {
              log_error (_("option file `%s': %s\n"),
                         configname, strerror(errno) );
              exit(2);
	    }
          xfree (configname);
          configname = NULL;
	}
      if (parse_debug && configname )
        log_info (_("reading options from `%s'\n"), configname );
      default_config = 0;
    }

  while (optfile_parse( configfp, configname, &configlineno, &pargs, opts) )
    {
      switch (pargs.r_opt)
        {
        case aGPGConfList: gpgconf_list = 1; break;
        case aGPGConfTest: gpgconf_list = 2; break;
        case oQuiet: opt.quiet = 1; break;
        case oVerbose: opt.verbose++; break;
        case oBatch: opt.batch=1; break;

        case oDebug: opt.debug |= pargs.r.ret_ulong; break;
        case oDebugAll: opt.debug = ~0; break;
        case oDebugLevel: debug_level = pargs.r.ret_str; break;
        case oDebugWait: debug_wait = pargs.r.ret_int; break;
        case oDebugAllowCoreDump:
          enable_core_dumps ();
          allow_coredump = 1;
          break;
        case oDebugCCIDDriver:
#ifdef HAVE_LIBUSB
          ccid_set_debug_level (ccid_set_debug_level (-1)+1);
#endif /*HAVE_LIBUSB*/
          break;
        case oDebugDisableTicker: ticker_disabled = 1; break;
        case oDebugLogTid:
          log_set_pid_suffix_cb (tid_log_callback);
          break;

        case oOptions:
          /* config files may not be nested (silently ignore them) */
          if (!configfp)
            {
		xfree(configname);
		configname = xstrdup(pargs.r.ret_str);
		goto next_pass;
	    }
          break;
        case oNoGreeting: nogreeting = 1; break;
        case oNoVerbose: opt.verbose = 0; break;
        case oNoOptions: break; /* no-options */
        case oHomedir: opt.homedir = pargs.r.ret_str; break;
        case oNoDetach: nodetach = 1; break;
        case oLogFile: logfile = pargs.r.ret_str; break;
        case oCsh: csh_style = 1; break;
        case oSh: csh_style = 0; break;
        case oServer: pipe_server = 1; break;
        case oMultiServer: pipe_server = 1; multi_server = 1; break;
        case oDaemon: is_daemon = 1; break;

        case oReaderPort: opt.reader_port = pargs.r.ret_str; break;
        case octapiDriver: opt.ctapi_driver = pargs.r.ret_str; break;
        case opcscDriver: opt.pcsc_driver = pargs.r.ret_str; break;
        case oDisableCCID: opt.disable_ccid = 1; break;
        case oDisableOpenSC: break;

        case oDisableKeypad: opt.disable_keypad = 1; break;

        case oAllowAdmin: /* Dummy because allow is now the default.  */
          break;
        case oDenyAdmin: opt.allow_admin = 0; break;

        case oCardTimeout: opt.card_timeout = pargs.r.ret_ulong; break;

        case oDisableApplication:
          add_to_strlist (&opt.disabled_applications, pargs.r.ret_str);
          break;

        default:
          pargs.err = configfp? ARGPARSE_PRINT_WARNING:ARGPARSE_PRINT_ERROR;
          break;
	}
    }
  if (configfp)
    {
      fclose( configfp );
      configfp = NULL;
      /* Keep a copy of the config name for use by --gpgconf-list. */
      config_filename = configname;
      configname = NULL;
      goto next_pass;
    }
  xfree (configname);
  configname = NULL;
  if (log_get_errorcount(0))
    exit(2);
  if (nogreeting )
    greeting = 0;

  if (greeting)
    {
      es_fprintf (es_stderr, "%s %s; %s\n",
                  strusage(11), strusage(13), strusage(14) );
      es_fprintf (es_stderr, "%s\n", strusage(15) );
    }
#ifdef IS_DEVELOPMENT_VERSION
  log_info ("NOTE: this is a development version!\n");
#endif


  if (atexit (cleanup))
    {
      log_error ("atexit failed\n");
      cleanup ();
      exit (1);
    }

  set_debug (debug_level);

  initialize_module_command ();

  if (gpgconf_list == 2)
    scd_exit (0);
  if (gpgconf_list)
    {
      /* List options and default values in the GPG Conf format.  */
      char *filename = NULL;
      char *filename_esc;

      if (config_filename)
	filename = xstrdup (config_filename);
      else
        filename = make_filename (opt.homedir, "scdaemon.conf", NULL);
      filename_esc = percent_escape (filename, NULL);

      es_printf ("gpgconf-scdaemon.conf:%lu:\"%s\n",
                 GC_OPT_FLAG_DEFAULT, filename_esc);
      xfree (filename_esc);
      xfree (filename);

      es_printf ("verbose:%lu:\n"
                 "quiet:%lu:\n"
                 "debug-level:%lu:\"none:\n"
                 "log-file:%lu:\n",
                 GC_OPT_FLAG_NONE,
                 GC_OPT_FLAG_NONE,
                 GC_OPT_FLAG_DEFAULT,
                 GC_OPT_FLAG_NONE );

      es_printf ("reader-port:%lu:\n", GC_OPT_FLAG_NONE );
      es_printf ("ctapi-driver:%lu:\n", GC_OPT_FLAG_NONE );
      es_printf ("pcsc-driver:%lu:\"%s:\n",
              GC_OPT_FLAG_DEFAULT, DEFAULT_PCSC_DRIVER );
#ifdef HAVE_LIBUSB
      es_printf ("disable-ccid:%lu:\n", GC_OPT_FLAG_NONE );
#endif
      es_printf ("deny-admin:%lu:\n", GC_OPT_FLAG_NONE );
      es_printf ("disable-keypad:%lu:\n", GC_OPT_FLAG_NONE );
      es_printf ("card-timeout:%lu:%d:\n", GC_OPT_FLAG_DEFAULT, 0);

      scd_exit (0);
    }

  /* Now start with logging to a file if this is desired.  */
  if (logfile)
    {
      log_set_file (logfile);
      log_set_prefix (NULL, 1|2|4);
    }

  if (debug_wait && pipe_server)
    {
      log_debug ("waiting for debugger - my pid is %u .....\n",
                 (unsigned int)getpid());
      gnupg_sleep (debug_wait);
      log_debug ("... okay\n");
    }

  if (pipe_server)
    {
      /* This is the simple pipe based server */
      ctrl_t ctrl;
      pth_attr_t tattr;
      int fd = -1;

#ifndef HAVE_W32_SYSTEM
      {
        struct sigaction sa;

        sa.sa_handler = SIG_IGN;
        sigemptyset (&sa.sa_mask);
        sa.sa_flags = 0;
        sigaction (SIGPIPE, &sa, NULL);
      }
#endif

      /* If --debug-allow-core-dump has been given we also need to
         switch the working directory to a place where we can actually
         write. */
      if (allow_coredump)
        {
          if (chdir("/tmp"))
            log_debug ("chdir to `/tmp' failed: %s\n", strerror (errno));
          else
            log_debug ("changed working directory to `/tmp'\n");
        }

      /* In multi server mode we need to listen on an additional
         socket.  Create that socket now before starting the handler
         for the pipe connection.  This allows that handler to send
         back the name of that socket. */
      if (multi_server)
        {
          socket_name = create_socket_name (standard_socket,
                                            "S.scdaemon",
                                            "gpg-XXXXXX/S.scdaemon");

          fd = FD2INT(create_server_socket (standard_socket,
                                            socket_name, &socket_nonce));
        }

      tattr = pth_attr_new();
      pth_attr_set (tattr, PTH_ATTR_JOINABLE, 0);
      pth_attr_set (tattr, PTH_ATTR_STACK_SIZE, 512*1024);
      pth_attr_set (tattr, PTH_ATTR_NAME, "pipe-connection");

      ctrl = xtrycalloc (1, sizeof *ctrl);
      if ( !ctrl )
        {
          log_error ("error allocating connection control data: %s\n",
                     strerror (errno) );
          scd_exit (2);
        }
      ctrl->thread_startup.fd = GNUPG_INVALID_FD;
      if ( !pth_spawn (tattr, start_connection_thread, ctrl) )
        {
          log_error ("error spawning pipe connection handler: %s\n",
                     strerror (errno) );
          xfree (ctrl);
          scd_exit (2);
        }

      /* We run handle_connection to wait for the shutdown signal and
         to run the ticker stuff.  */
      handle_connections (fd);
      if (fd != -1)
        close (fd);
    }
  else if (!is_daemon)
    {
      log_info (_("please use the option `--daemon'"
                  " to run the program in the background\n"));
    }
  else
    { /* Regular server mode */
      int fd;
#ifndef HAVE_W32_SYSTEM
      pid_t pid;
      int i;
#endif

      /* Create the socket.  */
      socket_name = create_socket_name (standard_socket,
                                        "S.scdaemon",
                                        "gpg-XXXXXX/S.scdaemon");

      fd = FD2INT (create_server_socket (standard_socket,
                                         socket_name, &socket_nonce));


      fflush (NULL);
#ifndef HAVE_W32_SYSTEM
      pid = fork ();
      if (pid == (pid_t)-1)
        {
          log_fatal ("fork failed: %s\n", strerror (errno) );
          exit (1);
        }
      else if (pid)
        { /* we are the parent */
          char *infostr;

          close (fd);

          /* create the info string: <name>:<pid>:<protocol_version> */
          if (estream_asprintf (&infostr, "SCDAEMON_INFO=%s:%lu:1",
				socket_name, (ulong) pid) < 0)
            {
              log_error ("out of core\n");
              kill (pid, SIGTERM);
              exit (1);
            }
          *socket_name = 0; /* don't let cleanup() remove the socket -
                               the child should do this from now on */
          if (argc)
            { /* run the program given on the commandline */
              if (putenv (infostr))
                {
                  log_error ("failed to set environment: %s\n",
                             strerror (errno) );
                  kill (pid, SIGTERM );
                  exit (1);
                }
              execvp (argv[0], argv);
              log_error ("failed to run the command: %s\n", strerror (errno));
              kill (pid, SIGTERM);
              exit (1);
            }
          else
            {
              /* Print the environment string, so that the caller can use
                 shell's eval to set it */
              if (csh_style)
                {
                  *strchr (infostr, '=') = ' ';
                  es_printf ( "setenv %s\n", infostr);
                }
              else
                {
                  es_printf ( "%s; export SCDAEMON_INFO;\n", infostr);
                }
              xfree (infostr);
              exit (0);
            }
          /* NOTREACHED */
        } /* end parent */

      /* This is the child. */

      /* Detach from tty and put process into a new session. */
      if (!nodetach )
        {
          /* Close stdin, stdout and stderr unless it is the log stream. */
          for (i=0; i <= 2; i++)
            {
              if ( log_test_fd (i) && i != fd)
                close (i);
            }
          if (setsid() == -1)
            {
              log_error ("setsid() failed: %s\n", strerror(errno) );
              cleanup ();
              exit (1);
            }
        }

      {
        struct sigaction sa;

        sa.sa_handler = SIG_IGN;
        sigemptyset (&sa.sa_mask);
        sa.sa_flags = 0;
        sigaction (SIGPIPE, &sa, NULL);
      }

      if (chdir("/"))
        {
          log_error ("chdir to / failed: %s\n", strerror (errno));
          exit (1);
        }

#endif /*!HAVE_W32_SYSTEM*/

      handle_connections (fd);

      close (fd);
    }

  return 0;
}
예제 #13
0
/* Insert the given fpr into our trustdb.  We expect FPR to be an all
   uppercase hexstring of 40 characters. FLAG is either 'P' or 'C'.
   This function does first check whether that key has already been put
   into the trustdb and returns success in this case.  Before a FPR
   actually gets inserted, the user is asked by means of the Pinentry
   whether this is actual want he wants to do.  */
gpg_error_t
agent_marktrusted (ctrl_t ctrl, const char *name, const char *fpr, int flag)
{
  gpg_error_t err = 0;
  char *desc;
  char *fname;
  estream_t fp;
  char *fprformatted;
  char *nameformatted;
  int is_disabled;
  int yes_i_trust;

  /* Check whether we are at all allowed to modify the trustlist.
     This is useful so that the trustlist may be a symlink to a global
     trustlist with only admin priviliges to modify it.  Of course
     this is not a secure way of denying access, but it avoids the
     usual clicking on an Okay button most users are used to. */
  fname = make_filename (opt.homedir, "trustlist.txt", NULL);
  if ( access (fname, W_OK) && errno != ENOENT)
    {
      xfree (fname);
      return gpg_error (GPG_ERR_EPERM);
    }
  xfree (fname);

  if (!agent_istrusted (ctrl, fpr, &is_disabled))
    {
      return 0; /* We already got this fingerprint.  Silently return
                   success. */
    }

  /* This feature must explicitly been enabled. */
  if (!opt.allow_mark_trusted)
    return gpg_error (GPG_ERR_NOT_SUPPORTED);

  if (is_disabled)
    {
      /* There is an disabled entry in the trustlist.  Return an error
         so that the user won't be asked again for that one.  Changing
         this flag with the integrated marktrusted feature is and will
         not be made possible.  */
      return gpg_error (GPG_ERR_NOT_TRUSTED);
    }


  /* Insert a new one. */
  nameformatted = reformat_name (name, "%0A   ");
  if (!nameformatted)
    return gpg_error_from_syserror ();

  /* First a general question whether this is trusted.  */
  desc = xtryasprintf (
                /* TRANSLATORS: This prompt is shown by the Pinentry
                   and has one special property: A "%%0A" is used by
                   Pinentry to insert a line break.  The double
                   percent sign is actually needed because it is also
                   a printf format string.  If you need to insert a
                   plain % sign, you need to encode it as "%%25".  The
                   "%s" gets replaced by the name as stored in the
                   certificate. */
                _("Do you ultimately trust%%0A"
                  "  \"%s\"%%0A"
                  "to correctly certify user certificates?"),
                nameformatted);
  if (!desc)
    {
      xfree (nameformatted);
      return out_of_core ();
    }
  err = agent_get_confirmation (ctrl, desc, _("Yes"), _("No"), 1);
  xfree (desc);
  if (!err)
    yes_i_trust = 1;
  else if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED)
    yes_i_trust = 0;
  else
    {
      xfree (nameformatted);
      return err;
    }


  fprformatted = insert_colons (fpr);
  if (!fprformatted)
    {
      xfree (nameformatted);
      return out_of_core ();
    }

  /* If the user trusts this certificate he has to verify the
     fingerprint of course.  */
  if (yes_i_trust)
    {
      desc = xtryasprintf
        (
         /* TRANSLATORS: This prompt is shown by the Pinentry and has
            one special property: A "%%0A" is used by Pinentry to
            insert a line break.  The double percent sign is actually
            needed because it is also a printf format string.  If you
            need to insert a plain % sign, you need to encode it as
            "%%25".  The second "%s" gets replaced by a hexdecimal
            fingerprint string whereas the first one receives the name
            as stored in the certificate. */
         _("Please verify that the certificate identified as:%%0A"
           "  \"%s\"%%0A"
           "has the fingerprint:%%0A"
           "  %s"), nameformatted, fprformatted);
      if (!desc)
        {
          xfree (fprformatted);
          xfree (nameformatted);
          return out_of_core ();
        }

      /* TRANSLATORS: "Correct" is the label of a button and intended
         to be hit if the fingerprint matches the one of the CA.  The
         other button is "the default "Cancel" of the Pinentry. */
      err = agent_get_confirmation (ctrl, desc, _("Correct"), _("Wrong"), 1);
      xfree (desc);
      if (gpg_err_code (err) == GPG_ERR_NOT_CONFIRMED)
        yes_i_trust = 0;
      else if (err)
        {
          xfree (fprformatted);
          xfree (nameformatted);
          return err;
        }
    }


  /* Now check again to avoid duplicates.  We take the lock to make
     sure that nobody else plays with our file and force a reread.  */
  lock_trusttable ();
  agent_reload_trustlist ();
  if (!agent_istrusted (ctrl, fpr, &is_disabled) || is_disabled)
    {
      unlock_trusttable ();
      xfree (fprformatted);
      xfree (nameformatted);
      return is_disabled? gpg_error (GPG_ERR_NOT_TRUSTED) : 0;
    }

  fname = make_filename (opt.homedir, "trustlist.txt", NULL);
  if ( access (fname, F_OK) && errno == ENOENT)
    {
      fp = es_fopen (fname, "wx,mode=-rw-r");
      if (!fp)
        {
          err = gpg_error_from_syserror ();
          log_error ("can't create `%s': %s\n", fname, gpg_strerror (err));
          xfree (fname);
          unlock_trusttable ();
          xfree (fprformatted);
          xfree (nameformatted);
          return err;
        }
      es_fputs (headerblurb, fp);
      es_fclose (fp);
    }
  fp = es_fopen (fname, "a+,mode=-rw-r");
  if (!fp)
    {
      err = gpg_error_from_syserror ();
      log_error ("can't open `%s': %s\n", fname, gpg_strerror (err));
      xfree (fname);
      unlock_trusttable ();
      xfree (fprformatted);
      xfree (nameformatted);
      return err;
    }

  /* Append the key. */
  es_fputs ("\n# ", fp);
  xfree (nameformatted);
  nameformatted = reformat_name (name, "\n# ");
  if (!nameformatted || strchr (name, '\n'))
    {
      /* Note that there should never be a LF in NAME but we better
         play safe and print a sanitized version in this case.  */
      es_write_sanitized (fp, name, strlen (name), NULL, NULL);
    }
  else
    es_fputs (nameformatted, fp);
  es_fprintf (fp, "\n%s%s %c\n", yes_i_trust?"":"!", fprformatted, flag);
  if (es_ferror (fp))
    err = gpg_error_from_syserror ();

  if (es_fclose (fp))
    err = gpg_error_from_syserror ();

  agent_reload_trustlist ();
  xfree (fname);
  unlock_trusttable ();
  xfree (fprformatted);
  xfree (nameformatted);
  return err;
}
예제 #14
0
CURLcode
curl_easy_perform(CURL *curl)
{
  int rc;
  CURLcode err=CURLE_OK;
  const char *errstr=NULL;
  char *proxy=NULL;
  struct http_srv srv;

  memset(&srv,0,sizeof(srv));

  /* Emulate the libcurl proxy behavior.  If the calling program set a
     proxy, use it.  If it didn't set a proxy or set it to NULL, check
     for one in the environment.  If the calling program explicitly
     set a null-string proxy the http code doesn't use a proxy at
     all. */

  if(curl->proxy)
    proxy=curl->proxy;
  else
    proxy=getenv(HTTP_PROXY_ENV);

  if(curl->srvtag)
    srv.srvtag=curl->srvtag;

  if(curl->flags.verbose)
    {
      fprintf(curl->errors,"* HTTP proxy is \"%s\"\n",proxy?proxy:"null");
      fprintf(curl->errors,"* HTTP URL is \"%s\"\n",curl->url);
      if(srv.srvtag)
	fprintf(curl->errors,
		"* SRV tag is \"%s\": host and port may be overridden\n",
		srv.srvtag);
      fprintf(curl->errors,"* HTTP auth is \"%s\"\n",
	      curl->auth?curl->auth:"null");
      fprintf(curl->errors,"* HTTP method is %s\n",
	      curl->flags.post?"POST":"GET");
    }

  if(curl->flags.post)
    {
      rc = http_open (&curl->hd, HTTP_REQ_POST, curl->url, curl->auth,
                      0, proxy, NULL, &srv,
		      curl->headers?curl->headers->list:NULL);
      if (!rc)
	{
	  unsigned int post_len = strlen(curl->postfields);

	  if(curl->flags.verbose && srv.used_server && srv.used_port)
	    fprintf (curl->errors, "* HTTP host:port post-SRV is \"%s:%hu\"\n",
		     srv.used_server, srv.used_port);

	  es_fprintf (http_get_write_ptr (curl->hd),
                      "Content-Type: application/x-www-form-urlencoded\r\n"
                      "Content-Length: %u\r\n", post_len);
	  http_start_data (curl->hd);
	  es_write (http_get_write_ptr (curl->hd),
                    curl->postfields, post_len, NULL);

	  rc = http_wait_response (curl->hd);
          curl->status = http_get_status_code (curl->hd);
	  if (!rc && curl->flags.failonerror && curl->status>=300)
	    err = CURLE_HTTP_RETURNED_ERROR;
          http_close (curl->hd, 0);
          curl->hd = NULL;
	}
    }
  else
    {
      rc = http_open (&curl->hd, HTTP_REQ_GET, curl->url, curl->auth,
                      0, proxy, NULL, &srv,
		      curl->headers?curl->headers->list:NULL);
      if (!rc)
	{
	  if(curl->flags.verbose && srv.used_server && srv.used_port)
	    fprintf (curl->errors, "* HTTP host:port post-SRV is \"%s:%hu\"\n",
		     srv.used_server, srv.used_port);

	  rc = http_wait_response (curl->hd);
          curl->status = http_get_status_code (curl->hd);
	  if (!rc)
	    {
	      if (curl->flags.failonerror && curl->status>=300)
		err = CURLE_HTTP_RETURNED_ERROR;
	      else
		{
		  size_t maxlen = 1024;
                  size_t buflen;
                  unsigned int len;
		  char *line = NULL;

		  while ((len = es_read_line (http_get_read_ptr (curl->hd),
                                              &line, &buflen, &maxlen)))
		    {
		      size_t ret;

		      maxlen=1024;

		      ret=(curl->writer)(line,len,1,curl->file);
		      if(ret!=len)
			{
			  err=CURLE_WRITE_ERROR;
			  break;
			}
		    }

		  es_free (line);
		  http_close(curl->hd, 0);
                  curl->hd = NULL;
		}
	    }
	  else
            {
              http_close (curl->hd, 0);
              curl->hd = NULL;
            }
	}
    }

  xfree(srv.used_server);

  switch(gpg_err_code (rc))
    {
    case 0:
      break;

    case GPG_ERR_INV_URI:
      err=CURLE_UNSUPPORTED_PROTOCOL;
      break;

    default:
      errstr=gpg_strerror (rc);
      err=CURLE_COULDNT_CONNECT;
      break;
    }
      
  return handle_error(curl,err,errstr);
}
예제 #15
0
파일: export.c 프로젝트: FMayzek/gnupg
/* Export a certificate and its private key. */
void
gpgsm_p12_export (ctrl_t ctrl, const char *name, estream_t stream)
{
  gpg_error_t err = 0;
  KEYDB_HANDLE hd;
  KEYDB_SEARCH_DESC *desc = NULL;
  Base64Context b64writer = NULL;
  ksba_writer_t writer;
  ksba_cert_t cert = NULL;
  const unsigned char *image;
  size_t imagelen;
  char *keygrip = NULL;
  char *prompt;
  void *data;
  size_t datalen;


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

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

  err = classify_user_id (name, desc, 0);
  if (err)
    {
      log_error ("key '%s' not found: %s\n",
                 name, gpg_strerror (err));
      goto leave;
    }

  /* Lookup the certificate and make sure that it is unique. */
  err = keydb_search (hd, desc, 1);
  if (!err)
    {
      err = keydb_get_cert (hd, &cert);
      if (err)
        {
          log_error ("keydb_get_cert failed: %s\n", gpg_strerror (err));
          goto leave;
        }

    next_ambiguous:
      err = keydb_search (hd, desc, 1);
      if (!err)
        {
          ksba_cert_t cert2 = NULL;

          if (!keydb_get_cert (hd, &cert2))
            {
              if (gpgsm_certs_identical_p (cert, cert2))
                {
                  ksba_cert_release (cert2);
                  goto next_ambiguous;
                }
              ksba_cert_release (cert2);
            }
          err = gpg_error (GPG_ERR_AMBIGUOUS_NAME);
        }
      else if (err == -1 || gpg_err_code (err) == GPG_ERR_EOF)
        err = 0;
      if (err)
        {
          log_error ("key '%s' not found: %s\n",
                     name, gpg_strerror (err));
          goto leave;
        }
    }

  keygrip = gpgsm_get_keygrip_hexstring (cert);
  if (!keygrip || gpgsm_agent_havekey (ctrl, keygrip))
    {
      /* Note, that the !keygrip case indicates a bad certificate. */
      err = gpg_error (GPG_ERR_NO_SECKEY);
      log_error ("can't export key '%s': %s\n", name, gpg_strerror (err));
      goto leave;
    }

  image = ksba_cert_get_image (cert, &imagelen);
  if (!image)
    {
      log_error ("ksba_cert_get_image failed\n");
      goto leave;
    }

  if (ctrl->create_pem)
    {
      print_short_info (cert, stream);
      es_putc ('\n', stream);
    }

  if (opt.p12_charset && ctrl->create_pem)
    {
      es_fprintf (stream, "The passphrase is %s encoded.\n\n",
                  opt.p12_charset);
    }

  ctrl->pem_name = "PKCS12";
  err = gpgsm_create_writer (&b64writer, ctrl, stream, &writer);
  if (err)
    {
      log_error ("can't create writer: %s\n", gpg_strerror (err));
      goto leave;
    }

  prompt = gpgsm_format_keydesc (cert);
  err = export_p12 (ctrl, image, imagelen, prompt, keygrip, &data, &datalen);
  xfree (prompt);
  if (err)
    goto leave;
  err = ksba_writer_write (writer, data, datalen);
  xfree (data);
  if (err)
    {
      log_error ("write failed: %s\n", gpg_strerror (err));
      goto leave;
    }

  if (ctrl->create_pem)
    {
      /* We want one certificate per PEM block */
      err = gpgsm_finish_writer (b64writer);
      if (err)
        {
          log_error ("write failed: %s\n", gpg_strerror (err));
          goto leave;
        }
      gpgsm_destroy_writer (b64writer);
      b64writer = NULL;
    }

  ksba_cert_release (cert);
  cert = NULL;

 leave:
  gpgsm_destroy_writer (b64writer);
  ksba_cert_release (cert);
  xfree (desc);
  keydb_release (hd);
}
예제 #16
0
파일: tdbio.c 프로젝트: 0ndorio/gnupg
/*
 * Dump the trustdb record REC to stream FP.
 */
void
tdbio_dump_record (TRUSTREC *rec, estream_t fp)
{
  int i;
  ulong rnum = rec->recnum;

  es_fprintf (fp, "rec %5lu, ", rnum);

  switch (rec->rectype)
    {
    case 0:
      es_fprintf (fp, "blank\n");
      break;

    case RECTYPE_VER:
      es_fprintf (fp,
         "version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d mcl=%d nc=%lu (%s)\n",
                  rec->r.ver.trusthashtbl,
                  rec->r.ver.firstfree,
                  rec->r.ver.marginals,
                  rec->r.ver.completes,
                  rec->r.ver.cert_depth,
                  rec->r.ver.trust_model,
                  rec->r.ver.min_cert_level,
                  rec->r.ver.nextcheck,
                  strtimestamp(rec->r.ver.nextcheck)
                  );
      break;

    case RECTYPE_FREE:
      es_fprintf (fp, "free, next=%lu\n", rec->r.free.next);
      break;

    case RECTYPE_HTBL:
      es_fprintf (fp, "htbl,");
      for (i=0; i < ITEMS_PER_HTBL_RECORD; i++)
        es_fprintf (fp, " %lu", rec->r.htbl.item[i]);
      es_putc ('\n', fp);
      break;

    case RECTYPE_HLST:
      es_fprintf (fp, "hlst, next=%lu,", rec->r.hlst.next);
      for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
        es_fprintf (fp, " %lu", rec->r.hlst.rnum[i]);
      es_putc ('\n', fp);
      break;

    case RECTYPE_TRUST:
      es_fprintf (fp, "trust ");
      for (i=0; i < 20; i++)
        es_fprintf (fp, "%02X", rec->r.trust.fingerprint[i]);
      es_fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust,
                  rec->r.trust.depth, rec->r.trust.validlist);
      break;

    case RECTYPE_VALID:
      es_fprintf (fp, "valid ");
      for (i=0; i < 20; i++)
        es_fprintf(fp, "%02X", rec->r.valid.namehash[i]);
      es_fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity,
                  rec->r.valid.next);
      break;

    default:
      es_fprintf (fp, "unknown type %d\n", rec->rectype );
      break;
    }
}