示例#1
0
/* Parse the /etc/gnupg/g13tab for user USERNAME.  Return a table for
   the user on success.  Return NULL on error and print
   diagnostics. */
static tab_item_t
parse_g13tab (const char *username)
{
  gpg_error_t err;
  int c, n;
  char line[512];
  char *p;
  char *fname;
  estream_t fp;
  int lnr;
  char **words = NULL;
  tab_item_t table = NULL;
  tab_item_t *tabletail, ti;

  fname = make_filename (gnupg_sysconfdir (), G13_NAME"tab", NULL);
  fp = es_fopen (fname, "r");
  if (!fp)
    {
      err = gpg_error_from_syserror ();
      log_error (_("error opening '%s': %s\n"), fname, gpg_strerror (err));
      goto leave;
    }

  tabletail = &table;
  err = 0;
  lnr = 0;
  while (es_fgets (line, DIM(line)-1, fp))
    {
      lnr++;
      n = strlen (line);
      if (!n || line[n-1] != '\n')
        {
          /* Eat until end of line. */
          while ((c=es_getc (fp)) != EOF && c != '\n')
            ;
          err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
                           : GPG_ERR_INCOMPLETE_LINE);
          log_error (_("file '%s', line %d: %s\n"),
                     fname, lnr, gpg_strerror (err));
          continue;
        }
      line[--n] = 0; /* Chop the LF. */
      if (n && line[n-1] == '\r')
        line[--n] = 0; /* Chop an optional CR. */

      /* Allow for empty lines and spaces */
      for (p=line; spacep (p); p++)
        ;
      if (!*p || *p == '#')
        continue;

      /* Parse the line.  The format is
       * <username> <blockdev> [<label>|"-" [<mountpoint>]]
       */
      xfree (words);
      words = strtokenize (p, " \t");
      if (!words)
        {
          err = gpg_error_from_syserror ();
          break;
        }
      if (!words[0] || !words[1])
        {
          log_error (_("file '%s', line %d: %s\n"),
                     fname, lnr, gpg_strerror (GPG_ERR_SYNTAX));
          continue;
        }
      if (!(*words[1] == '/'
            || !strncmp (words[1], "PARTUUID=", 9)
            || !strncmp (words[1], "partuuid=", 9)))
        {
          log_error (_("file '%s', line %d: %s\n"),
                     fname, lnr, "Invalid block device syntax");
          continue;
        }
      if (words[2])
        {
          if (strlen (words[2]) > 16 || strchr (words[2], '/'))
            {
              log_error (_("file '%s', line %d: %s\n"),
                         fname, lnr, "Label too long or invalid syntax");
              continue;
            }

          if (words[3] && *words[3] != '/')
            {
              log_error (_("file '%s', line %d: %s\n"),
                         fname, lnr, "Invalid mountpoint syntax");
              continue;
            }
        }
      if (strcmp (words[0], username))
        continue; /* Skip entries for other usernames!  */

      ti = xtrymalloc (sizeof *ti + strlen (words[1]));
      if (!ti)
        {
          err = gpg_error_from_syserror ();
          break;
        }
      ti->next = NULL;
      ti->label = NULL;
      ti->mountpoint = NULL;
      strcpy (ti->blockdev, *words[1]=='/'? words[1] : words[1]+9);
      if (words[2])
        {
          if (strcmp (words[2], "-")
              && !(ti->label = xtrystrdup (words[2])))
            {
              err = gpg_error_from_syserror ();
              xfree (ti);
              break;
            }
          if (words[3] && !(ti->mountpoint = xtrystrdup (words[3])))
            {
              err = gpg_error_from_syserror ();
              xfree (ti->label);
              xfree (ti);
              break;
            }
        }
      *tabletail = ti;
      tabletail = &ti->next;
    }

  if (!err && !es_feof (fp))
    err = gpg_error_from_syserror ();
  if (err)
    log_error (_("error reading '%s', line %d: %s\n"),
               fname, lnr, gpg_strerror (err));

 leave:
  xfree (words);
  es_fclose (fp);
  xfree (fname);
  if (err)
    {
      release_tab_items (table);
      return NULL;
    }
  return table;
}
示例#2
0
文件: ocsp.c 项目: FMayzek/gnupg
/* Read from FP and return a newly allocated buffer in R_BUFFER with the
   entire data read from FP. */
static gpg_error_t
read_response (estream_t fp, unsigned char **r_buffer, size_t *r_buflen)
{
  gpg_error_t err;
  unsigned char *buffer;
  size_t bufsize, nbytes;

  *r_buffer = NULL;
  *r_buflen = 0;

  bufsize = 4096;
  buffer = xtrymalloc (bufsize);
  if (!buffer)
    return gpg_error_from_errno (errno);

  nbytes = 0;
  for (;;)
    {
      unsigned char *tmp;
      size_t nread = 0;

      assert (nbytes < bufsize);
      nread = es_fread (buffer+nbytes, 1, bufsize-nbytes, fp);
      if (nread < bufsize-nbytes && es_ferror (fp))
        {
          err = gpg_error_from_errno (errno);
          log_error (_("error reading from responder: %s\n"),
                     strerror (errno));
          xfree (buffer);
          return err;
        }
      if ( !(nread == bufsize-nbytes && !es_feof (fp)))
        { /* Response succesfully received. */
          nbytes += nread;
          *r_buffer = buffer;
          *r_buflen = nbytes;
          return 0;
        }

      nbytes += nread;

      /* Need to enlarge the buffer. */
      if (bufsize >= MAX_RESPONSE_SIZE)
        {
          log_error (_("response from server too large; limit is %d bytes\n"),
                     MAX_RESPONSE_SIZE);
          xfree (buffer);
          return gpg_error (GPG_ERR_TOO_LARGE);
        }

      bufsize += 4096;
      tmp = xtryrealloc (buffer, bufsize);
      if (!tmp)
        {
          err = gpg_error_from_errno (errno);
          xfree (buffer);
          return err;
        }
      buffer = tmp;
    }
}
示例#3
0
文件: wks-util.c 项目: larryv/gnupg
/* Parse the policy flags by reading them from STREAM and storing them
 * into FLAGS.  If IGNORE_UNKNOWN is iset unknown keywords are
 * ignored.  */
gpg_error_t
wks_parse_policy (policy_flags_t flags, estream_t stream, int ignore_unknown)
{
  enum tokens {
    TOK_SUBMISSION_ADDRESS,
    TOK_MAILBOX_ONLY,
    TOK_DANE_ONLY,
    TOK_AUTH_SUBMIT,
    TOK_MAX_PENDING,
    TOK_PROTOCOL_VERSION
  };
  static struct {
    const char *name;
    enum tokens token;
  } keywords[] = {
    { "submission-address", TOK_SUBMISSION_ADDRESS },
    { "mailbox-only", TOK_MAILBOX_ONLY },
    { "dane-only",    TOK_DANE_ONLY    },
    { "auth-submit",  TOK_AUTH_SUBMIT  },
    { "max-pending",  TOK_MAX_PENDING  },
    { "protocol-version", TOK_PROTOCOL_VERSION }
  };
  gpg_error_t err = 0;
  int lnr = 0;
  char line[1024];
  char *p, *keyword, *value;
  int i, n;

  memset (flags, 0, sizeof *flags);

  while (es_fgets (line, DIM(line)-1, stream) )
    {
      lnr++;
      n = strlen (line);
      if (!n || line[n-1] != '\n')
        {
          err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
                           : GPG_ERR_INCOMPLETE_LINE);
          break;
        }
      trim_trailing_spaces (line);
      /* Skip empty and comment lines. */
      for (p=line; spacep (p); p++)
        ;
      if (!*p || *p == '#')
        continue;

      if (*p == ':')
        {
          err = gpg_error (GPG_ERR_SYNTAX);
          break;
        }

      keyword = p;
      value = NULL;
      if ((p = strchr (p, ':')))
        {
          /* Colon found: Keyword with value.  */
          *p++ = 0;
          for (; spacep (p); p++)
            ;
          if (!*p)
            {
              err = gpg_error (GPG_ERR_MISSING_VALUE);
              break;
            }
          value = p;
        }

      for (i=0; i < DIM (keywords); i++)
        if (!ascii_strcasecmp (keywords[i].name, keyword))
          break;
      if (!(i < DIM (keywords)))
        {
          if (ignore_unknown)
            continue;
          err = gpg_error (GPG_ERR_INV_NAME);
          break;
	}

      switch (keywords[i].token)
        {
        case TOK_SUBMISSION_ADDRESS:
          if (!value || !*value)
            {
              err = gpg_error (GPG_ERR_SYNTAX);
              goto leave;
            }
          xfree (flags->submission_address);
          flags->submission_address = xtrystrdup (value);
          if (!flags->submission_address)
            {
              err = gpg_error_from_syserror ();
              goto leave;
            }
          break;
        case TOK_MAILBOX_ONLY: flags->mailbox_only = 1; break;
        case TOK_DANE_ONLY:    flags->dane_only = 1;    break;
        case TOK_AUTH_SUBMIT:  flags->auth_submit = 1;  break;
        case TOK_MAX_PENDING:
          if (!value)
            {
              err = gpg_error (GPG_ERR_SYNTAX);
              goto leave;
            }
          /* FIXME: Define whether these are seconds, hours, or days
           * and decide whether to allow other units.  */
          flags->max_pending = atoi (value);
          break;
        case TOK_PROTOCOL_VERSION:
          if (!value)
            {
              err = gpg_error (GPG_ERR_SYNTAX);
              goto leave;
            }
          flags->protocol_version = atoi (value);
          break;
        }
    }

  if (!err && !es_feof (stream))
    err = gpg_error_from_syserror ();

 leave:
  if (err)
    log_error ("error reading '%s', line %d: %s\n",
               es_fname_get (stream), lnr, gpg_strerror (err));

  return err;
}
示例#4
0
文件: t-poll.c 项目: cobaugh/rt-rpm
static void
test_poll (void)
{
  int ret;
  gpgrt_poll_t fds[3];
  char buffer[16];
  size_t used, nwritten;
  int c;

  memset (fds, 0, sizeof fds);
  fds[0].stream = test_stdin;
  fds[0].want_read = 1;
  fds[1].stream = test_stdout;
  fds[1].want_write = 1;
  /* FIXME: We don't use the next stream at all.  */
  fds[2].stream = test_stderr;
  fds[2].want_write = 1;
  fds[2].ignore = 1;


  used = 0;
  while (used || !fds[0].ignore)
    {
      ret = gpgrt_poll (fds, DIM(fds), -1);
      if (ret == -1)
        {
          fail ("gpgrt_poll failed: %s\n", strerror (errno));
          continue;
        }
      if (!ret)
        {
          fail ("gpgrt_poll unexpectedly timed out\n");
          continue;
        }
      show ("gpgrt_poll detected %d events\n", ret);
      if (fds[0].got_read)
        {
          /* Read from the producer.  */
          for (;;)
            {
              c = es_fgetc (fds[0].stream);
              if (c == EOF)
                {
                  if (es_feof (fds[0].stream))
                    {
                      show ("reading '%s': EOF\n", peer_stdin.name);
                      fds[0].ignore = 1; /* Not anymore needed.  */
                      peer_stdin.stop_me = 1; /* Tell the thread to stop.  */
                    }
                  else if (es_ferror (fds[0].stream))
                    {
                      fail ("error reading '%s': %s\n",
                            peer_stdin.name, strerror (errno));
                      fds[0].ignore = 1;    /* Disable.  */
                      peer_stdin.stop_me = 1; /* Tell the thread to stop.  */
                    }
                  else
                    show ("reading '%s': EAGAIN\n", peer_stdin.name);
                  break;
                }
              else
                {
                  if (used <= sizeof buffer -1)
                    buffer[used++] = c;
                  if (used == sizeof buffer)
                    {
                      show ("throttling reading from '%s'\n", peer_stdin.name);
                      fds[0].ignore = 1;
                      break;
                    }
                }
            }
          show ("read from '%s': %zu bytes\n", peer_stdin.name, used);
          if (used)
            fds[1].ignore = 0; /* Data to send.  */
        }
      if (fds[1].got_write)
        {
          if (used)
            {
              ret = es_write (fds[1].stream, buffer, used, &nwritten);
              show ("result for writing to '%s': ret=%d, n=%zu, nwritten=%zu\n",
                    peer_stdout.name, ret, used, nwritten);
              if (!ret)
                {
                  assert (nwritten <= used);
                  /* Move the remaining data to the front of buffer.  */
                  memmove (buffer, buffer + nwritten,
                           sizeof buffer - nwritten);
                  used -= nwritten;
                }
              ret = es_fflush (fds[1].stream);
              if (ret)
                fail ("Flushing for '%s' failed: %s\n",
                      peer_stdout.name, strerror (errno));
            }
          if (!used)
            fds[1].ignore = 1; /* No need to send data.  */
        }

      if (used < sizeof buffer / 2 && !peer_stdin.stop_me && fds[0].ignore)
        {
          show ("accelerate reading from '%s'\n", peer_stdin.name);
          fds[0].ignore = 0;
        }
    }
}
示例#5
0
static gpg_error_t
read_one_trustfile (const char *fname, int allow_include,
                    trustitem_t **addr_of_table,
                    size_t *addr_of_tablesize,
                    int *addr_of_tableidx)
{
  gpg_error_t err = 0;
  estream_t fp;
  int n, c;
  char *p, line[256];
  trustitem_t *table, *ti;
  int tableidx;
  size_t tablesize;
  int lnr = 0;

  table = *addr_of_table;
  tablesize = *addr_of_tablesize;
  tableidx = *addr_of_tableidx;

  fp = es_fopen (fname, "r");
  if (!fp)
    {
      err = gpg_error_from_syserror ();
      log_error (_("error opening `%s': %s\n"), fname, gpg_strerror (err));
      goto leave;
    }

  while (es_fgets (line, DIM(line)-1, fp))
    {
      lnr++;

      n = strlen (line);
      if (!n || line[n-1] != '\n')
        {
          /* Eat until end of line. */
          while ( (c=es_getc (fp)) != EOF && c != '\n')
            ;
          err = gpg_error (*line? GPG_ERR_LINE_TOO_LONG
                           : GPG_ERR_INCOMPLETE_LINE);
          log_error (_("file `%s', line %d: %s\n"),
                     fname, lnr, gpg_strerror (err));
          continue;
        }
      line[--n] = 0; /* Chop the LF. */
      if (n && line[n-1] == '\r')
        line[--n] = 0; /* Chop an optional CR. */

      /* Allow for empty lines and spaces */
      for (p=line; spacep (p); p++)
        ;
      if (!*p || *p == '#')
        continue;

      if (!strncmp (p, "include-default", 15)
          && (!p[15] || spacep (p+15)))
        {
          char *etcname;
          gpg_error_t err2;

          if (!allow_include)
            {
              log_error (_("statement \"%s\" ignored in `%s', line %d\n"),
                         "include-default", fname, lnr);
              continue;
            }
          /* fixme: Should check for trailing garbage.  */

          etcname = make_filename (gnupg_sysconfdir (), "trustlist.txt", NULL);
          if ( !strcmp (etcname, fname) ) /* Same file. */
            log_info (_("statement \"%s\" ignored in `%s', line %d\n"),
                      "include-default", fname, lnr);
          else if ( access (etcname, F_OK) && errno == ENOENT )
            {
              /* A non existent system trustlist is not an error.
                 Just print a note. */
              log_info (_("system trustlist `%s' not available\n"), etcname);
            }
          else
            {
              err2 = read_one_trustfile (etcname, 0,
                                         &table, &tablesize, &tableidx);
              if (err2)
                err = err2;
            }
          xfree (etcname);

          continue;
        }

      if (tableidx == tablesize)  /* Need more space. */
        {
          trustitem_t *tmp;
          size_t tmplen;

          tmplen = tablesize + 20;
          tmp = xtryrealloc (table, tmplen * sizeof *table);
          if (!tmp)
            {
              err = gpg_error_from_syserror ();
              goto leave;
            }
          table = tmp;
          tablesize = tmplen;
        }

      ti = table + tableidx;

      memset (&ti->flags, 0, sizeof ti->flags);
      if (*p == '!')
        {
          ti->flags.disabled = 1;
          p++;
          while (spacep (p))
            p++;
        }

      n = hexcolon2bin (p, ti->fpr, 20);
      if (n < 0)
        {
          log_error (_("bad fingerprint in `%s', line %d\n"), fname, lnr);
          err = gpg_error (GPG_ERR_BAD_DATA);
          continue;
        }
      p += n;
      for (; spacep (p); p++)
        ;

      /* Process the first flag which needs to be the first for
         backward compatibility. */
      if (!*p || *p == '*' )
        {
          ti->flags.for_smime = 1;
          ti->flags.for_pgp = 1;
        }
      else if ( *p == 'P' || *p == 'p')
        {
          ti->flags.for_pgp = 1;
        }
      else if ( *p == 'S' || *p == 's')
        {
          ti->flags.for_smime = 1;
        }
      else
        {
          log_error (_("invalid keyflag in `%s', line %d\n"), fname, lnr);
          err = gpg_error (GPG_ERR_BAD_DATA);
          continue;
        }
      p++;
      if ( *p && !spacep (p) )
        {
          log_error (_("invalid keyflag in `%s', line %d\n"), fname, lnr);
          err = gpg_error (GPG_ERR_BAD_DATA);
          continue;
        }

      /* Now check for more key-value pairs of the form NAME[=VALUE]. */
      while (*p)
        {
          for (; spacep (p); p++)
            ;
          if (!*p)
            break;
          n = strcspn (p, "= \t");
          if (p[n] == '=')
            {
              log_error ("assigning a value to a flag is not yet supported; "
                         "in `%s', line %d\n", fname, lnr);
              err = gpg_error (GPG_ERR_BAD_DATA);
              p++;
            }
          else if (n == 5 && !memcmp (p, "relax", 5))
            ti->flags.relax = 1;
          else if (n == 2 && !memcmp (p, "cm", 2))
            ti->flags.cm = 1;
          else
            log_error ("flag `%.*s' in `%s', line %d ignored\n",
                       n, p, fname, lnr);
          p += n;
        }
      tableidx++;
    }
  if ( !err && !es_feof (fp) )
    {
      err = gpg_error_from_syserror ();
      log_error (_("error reading `%s', line %d: %s\n"),
                 fname, lnr, gpg_strerror (err));
    }

 leave:
  es_fclose (fp);
  *addr_of_table = table;
  *addr_of_tablesize = tablesize;
  *addr_of_tableidx = tableidx;
  return err;
}