Пример #1
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;
}
Пример #2
0
static gpg_error_t
learn_status_cb (void *opaque, const char *line)
{
  struct learn_parm_s *parm = opaque;
  const char *keyword = line;
  int keywordlen;

  for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
    ;
  while (spacep (line))
    line++;
  if (keywordlen == 8 && !memcmp (keyword, "CERTINFO", keywordlen))
    {
      parm->certinfo_cb (parm->certinfo_cb_arg, line);
    }
  else if (keywordlen == 11 && !memcmp (keyword, "KEYPAIRINFO", keywordlen))
    {
      parm->kpinfo_cb (parm->kpinfo_cb_arg, line);
    }
  else if (keywordlen && *line)
    {
      parm->sinfo_cb (parm->sinfo_cb_arg, keyword, keywordlen, line);
    }

  return 0;
}
Пример #3
0
static gpg_error_t
pass_status_thru (void *opaque, const char *line)
{
  assuan_context_t ctx = opaque;
  char keyword[200];
  int i;

  if (line[0] == '#' && (!line[1] || spacep (line+1)))
    {
      /* We are called in convey comments mode.  Now, if we see a
         comment marker as keyword we forward the line verbatim to the
         the caller.  This way the comment lines from scdaemon won't
         appear as status lines with keyword '#'.  */
      assuan_write_line (ctx, line);
    }
  else
    {
      for (i=0; *line && !spacep (line) && i < DIM(keyword)-1; line++, i++)
        keyword[i] = *line;
      keyword[i] = 0;

      /* Truncate any remaining keyword stuff.  */
      for (; *line && !spacep (line); line++)
        ;
      while (spacep (line))
        line++;

      assuan_write_status (ctx, keyword, line);
    }
  return 0;
}
Пример #4
0
/* Callback function for agent_card_getattr.  */
static gpg_error_t
card_getattr_cb (void *opaque, const char *line)
{
  struct card_getattr_parm_s *parm = opaque;
  const char *keyword = line;
  int keywordlen;

  if (parm->data)
    return 0; /* We want only the first occurrence.  */

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

  if (keywordlen == parm->keywordlen
      && !memcmp (keyword, parm->keyword, keywordlen))
    {
      parm->data = percent_plus_unescape ((const unsigned char*)line, 0xff);
      if (!parm->data)
        parm->error = errno;
    }

  return 0;
}
Пример #5
0
/* Status callback for the SCD GENKEY command. */
static gpg_error_t
scd_genkey_cb (void *opaque, const char *line)
{
    struct agent_card_genkey_s *parm = opaque;
    const char *keyword = line;
    int keywordlen;

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

    if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
    {
        parm->fprvalid = unhexify_fpr (line, parm->fpr);
    }
    else if (keywordlen == 14 && !memcmp (keyword,"KEY-CREATED-AT", keywordlen))
    {
        parm->created_at = (u32)strtoul (line, NULL, 10);
    }
    else if (keywordlen == 8 && !memcmp (keyword, "PROGRESS", keywordlen))
    {
        write_status_text (STATUS_PROGRESS, line);
    }

    return 0;
}
Пример #6
0
/* Check whether the option NAME appears in LINE */
static int
has_option (const char *line, const char *name)
{
  const char *s;
  int n = strlen (name);

  s = strstr (line, name);
  if (s && s >= skip_options (line))
    return 0;
  return (s && (s == line || spacep (s-1)) && (!s[n] || spacep (s+n)));
}
Пример #7
0
/* Skip over options.
   Blanks after the options are also removed. */
static char *
skip_options (const char *line)
{
  while (spacep (line))
    line++;
  while ( *line == '-' && line[1] == '-' )
    {
      while (*line && !spacep (line))
        line++;
      while (spacep (line))
        line++;
    }
  return (char*)line;
}
Пример #8
0
gpg_error_t
assuan_command_parse_fd (assuan_context_t ctx, char *line, assuan_fd_t *rfd)
{
  char *endp;

  if ((strncmp (line, "FD", 2) && strncmp (line, "fd", 2))
      || (line[2] != '=' && line[2] != '\0' && !spacep(&line[2])))
    return set_error (ctx, GPG_ERR_ASS_SYNTAX, "FD[=<n>] expected");
  line += 2;
  if (*line == '=')
    {
      line ++;
      if (!digitp (*line))
	return set_error (ctx, GPG_ERR_ASS_SYNTAX, "number required");
#ifdef HAVE_W32_SYSTEM
      /* Fixme: For a W32/64bit system we will need to change the cast
         and the conversion function.  */
      *rfd = (void*)strtoul (line, &endp, 10);
#else
      *rfd = strtoul (line, &endp, 10);
#endif
      /* Remove that argument so that a notify handler won't see it. */
      memset (line, ' ', endp? (endp-line):strlen(line));

      if (*rfd == ctx->inbound.fd)
	return set_error (ctx, GPG_ERR_ASS_PARAMETER, "fd same as inbound fd");
      if (*rfd == ctx->outbound.fd)
	return set_error (ctx, GPG_ERR_ASS_PARAMETER, "fd same as outbound fd");
      return 0;
    }
  else
    /* Our peer has sent the file descriptor.  */
    return assuan_receivefd (ctx, rfd);
}
Пример #9
0
/* Return a new malloced string by unescaping the string S.  Escaping
   is percent escaping and '+'/space mapping.  A binary Nul will
   silently be replaced by a 0xFF.  Function returns NULL to indicate
   an out of memory status.  PArsing stops at the end of the string or
   a white space character. */
static char *
unescape_passphrase_string (const unsigned char *s)
{
  char *buffer, *d;

  buffer = d = xtrymalloc_secure (strlen ((const char*)s)+1);
  if (!buffer)
    return NULL;
  while (*s && !spacep (s))
    {
      if (*s == '%' && s[1] && s[2])
        {
          s++;
          *d = xtoi_2 (s);
          if (!*d)
            *d = '\xff';
          d++;
          s += 2;
        }
      else if (*s == '+')
        {
          *d++ = ' ';
          s++;
        }
      else
        *d++ = *s++;
    }
  *d = 0;
  return buffer;
}
Пример #10
0
/* Convert a standard isotime or a human readable variant into an
   isotime structure.  The allowed formats are those described by
   isotime_p and isotime_human_p.  The function returns 0 on failure
   or the length of the scanned string on success.  */
static int
string2isotime (my_isotime_t atime, const char *string)
{
  my_isotime_t dummyatime;

  if (!atime)
    atime = dummyatime;

  atime[0] = 0;
  if (isotime_p (string))
    {
      memcpy (atime, string, 15);
      atime[15] = 0;
      return 15;
    }
  if (!isotime_human_p (string))
    return 0;
  atime[0] = string[0];
  atime[1] = string[1];
  atime[2] = string[2];
  atime[3] = string[3];
  atime[4] = string[5];
  atime[5] = string[6];
  atime[6] = string[8];
  atime[7] = string[9];
  atime[8] = 'T';
  memset (atime+9, '0', 6);
  atime[15] = 0;
  if (!spacep (string+10))
    return 10;
  if (spacep (string+11))
    return 11; /* As per def, second space stops scanning.  */
  atime[9] = string[11];
  atime[10] = string[12];
  if (string[13] != ':')
    return 13;
  atime[11] = string[14];
  atime[12] = string[15];
  if (string[16] != ':')
    return 16;
  atime[13] = string[17];
  atime[14] = string[18];
  return 19;
}
Пример #11
0
/* Check the button_info line for a close action.  */
static gpg_error_t
close_button_status_cb (void *opaque, const char *line)
{
  int *flag = opaque;
  const char *keyword = line;
  int keywordlen;

  for (keywordlen=0; *line && !spacep (line); line++, keywordlen++)
    ;
  while (spacep (line))
    line++;
  if (keywordlen == 11 && !memcmp (keyword, "BUTTON_INFO", keywordlen))
    {
      if ( !strcmp (line, "close") )
        *flag = 1;
    }

  return 0;
}
Пример #12
0
/* Return a pointer to the argument of the option with NAME.  If such
   an option is not given, NULL is returned. */
char *
option_value (const char *line, const char *name)
{
  char *s;
  int n = strlen (name);

  s = strstr (line, name);
  if (s && s >= skip_options (line))
    return NULL;
  if (s && (s == line || spacep (s-1))
      && s[n] && (spacep (s+n) || s[n] == '='))
    {
      s += n + 1;
      s += strspn (s, " ");
      if (*s && !spacep(s))
        return s;
    }
  return NULL;
}
Пример #13
0
static gpg_error_t
std_handler_option (assuan_context_t ctx, char *line)
{
  char *key, *value, *p;

  for (key=line; spacep (key); key++)
    ;
  if (!*key)
    return
      PROCESS_DONE (ctx, set_error (ctx, GPG_ERR_ASS_SYNTAX, "argument required"));
  if (*key == '=')
    return
      PROCESS_DONE (ctx, set_error (ctx, GPG_ERR_ASS_SYNTAX,
				    "no option name given"));
  for (value=key; *value && !spacep (value) && *value != '='; value++)
    ;
  if (*value)
    {
      if (spacep (value))
        *value++ = 0; /* terminate key */
      for (; spacep (value); value++)
        ;
      if (*value == '=')
        {
          *value++ = 0; /* terminate key */
          for (; spacep (value); value++)
            ;
          if (!*value)
            return
	      PROCESS_DONE (ctx, set_error (ctx, GPG_ERR_ASS_SYNTAX,
					    "option argument expected"));
        }
      if (*value)
        {
          for (p = value + strlen(value) - 1; p > value && spacep (p); p--)
            ;
          if (p > value)
            *++p = 0; /* strip trailing spaces */
        }
    }

  if (*key == '-' && key[1] == '-' && key[2])
    key += 2; /* the double dashes are optional */
  if (*key == '-')
    return PROCESS_DONE (ctx,
			 set_error (ctx, GPG_ERR_ASS_SYNTAX,
				    "option should not begin with one dash"));

  if (ctx->option_handler_fnc)
    return PROCESS_DONE (ctx, ctx->option_handler_fnc (ctx, key, value));
  return PROCESS_DONE (ctx, 0);
}
Пример #14
0
/* Estimate the quality of the passphrase PW and return a value in the
   range 0..100.  */
static int
estimate_passphrase_quality (const char *pw)
{
  int goodlength = opt.min_passphrase_len + opt.min_passphrase_len/3;
  int length;
  const char *s;

  if (goodlength < 1)
    return 0;

  for (length = 0, s = pw; *s; s++)
    if (!spacep (s))
      length ++;

  if (length > goodlength)
    return 100;
  return ((length*10) / goodlength)*10;
}
Пример #15
0
/* Helper to notify the client about Pinentry events.  Because that
   might disturb some older clients, this is only done when enabled
   via an option.  If it is not enabled we tell Windows to allow
   setting the foreground window right here.  Returns an gpg error
   code. */
gpg_error_t
gpg_proxy_pinentry_notify (ctrl_t ctrl, const unsigned char *line)
{
  if (!ctrl || !ctrl->server_local
      || !ctrl->server_local->allow_pinentry_notify)
    {
      gnupg_allow_set_foregound_window ((pid_t)strtoul (line+17, NULL, 10));
      /* Client might be interested in that event - send as status line.  */
      if (!strncmp (line, "PINENTRY_LAUNCHED", 17)
          && (line[17]==' '||!line[17]))
        {
          for (line += 17; *line && spacep (line); line++)
            ;
          write_status_text (STATUS_PINENTRY_LAUNCHED, line);
        }
      return 0;
    }
  return assuan_inquire (ctrl->server_local->assuan_ctx, line, NULL, NULL, 0);
}
Пример #16
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;
}
Пример #17
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;
}
Пример #18
0
/* 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;
}
Пример #19
0
/* Try to find KEY in the file FNAME.  */
static char *
findkey_fname (const char *key, const char *fname)
{
  gpg_error_t err = 0;
  FILE *fp;
  int lnr = 0;
  int c;
  char *p, line[256];
  int in_item = 0;
  membuf_t mb = MEMBUF_ZERO;

  fp = fopen (fname, "r");
  if (!fp)
    {
      if (errno != ENOENT)
        {
          err = gpg_error_from_syserror ();
          log_error (_("can't open `%s': %s\n"), fname, gpg_strerror (err));
        }
      return NULL;
    }

  while (fgets (line, DIM(line)-1, fp))
    {
      lnr++;
      
      if (!*line || line[strlen(line)-1] != '\n')
        {
          /* Eat until end of line. */
          while ( (c=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));
        }
      else
        line[strlen(line)-1] = 0; /* Chop the LF. */
      
    again:
      if (!in_item)
        {
          /* Allow for empty lines and spaces while not in an item. */
          for (p=line; spacep (p); p++)
            ;
          if (!*p || *p == '#')
            continue;
          if (*line != '.' || spacep(line+1))
            {
              log_info (_("file `%s', line %d: %s\n"),
                        fname, lnr, _("ignoring garbage line"));
              continue;
            }
          trim_trailing_spaces (line);
          in_item = 1;
          if (!strcmp (line+1, key))
            {
              /* Found.  Start collecting.  */
              init_membuf (&mb, 1024);
            }
          continue;
        }

      /* If in an item only allow for comments in the first column
         and provide ". " as an escape sequence to allow for
         leading dots and hash marks in the actual text.  */
      if (*line == '#')
        continue;
      if (*line == '.')
        { 
          if (spacep(line+1))
            p = line + 2;
          else
            {
              trim_trailing_spaces (line);
              in_item = 0;
              if (is_membuf_ready (&mb))
                break;        /* Yep, found and collected the item.  */
              if (!line[1])
                continue;     /* Just an end of text dot. */
              goto again;     /* A new key line.  */
            }
        }
      else
        p = line;

      if (is_membuf_ready (&mb))
        {
          put_membuf_str (&mb, p);
          put_membuf (&mb, "\n", 1);
        }

    }
  if ( !err && ferror (fp) )
    {
      err = gpg_error_from_syserror ();
      log_error (_("error reading `%s', line %d: %s\n"),
                 fname, lnr, gpg_strerror (err));
    }
  
  fclose (fp);
  if (is_membuf_ready (&mb))
    {
      /* We have collected something.  */
      if (err)
        {
          xfree (get_membuf (&mb, NULL));
          return NULL;
        }
      else
        {
          put_membuf (&mb, "", 1);  /* Terminate string.  */
          return get_membuf (&mb, NULL);
        }
    }
  else
    return NULL;
}
Пример #20
0
/* Return a value describing the the class of PATTERN.  The offset of
   the actual string to be used for the comparison is stored at
   R_OFFSET.  The offset of the serialnumer is stored at R_SN_OFFSET. */
static enum pattern_class
classify_pattern (const char *pattern, size_t *r_offset, size_t *r_sn_offset)
{
  enum pattern_class result;
  const char *s;
  int hexprefix = 0;
  int hexlength;

  *r_offset = *r_sn_offset = 0;

  /* Skip leading spaces. */
  for(s = pattern; *s && spacep (s); s++ )
    ;

  switch (*s)
    {
    case 0:  /* Empty string is an error. */
      result = PATTERN_UNKNOWN;
      break;

    case '.': /* An email address, compare from end.  */
      result = PATTERN_UNKNOWN;  /* Not implemented.  */
      break;

    case '<': /* An email address.  */
      result = PATTERN_EMAIL;
      s++;
      break;

    case '@': /* Part of an email address.  */
      result = PATTERN_EMAIL_SUBSTR;
      s++;
      break;

    case '=':  /* Exact compare. */
      result = PATTERN_UNKNOWN; /* Does not make sense for X.509.  */
      break;

    case '*':  /* Case insensitive substring search.  */
      result = PATTERN_SUBSTR;
      s++;
      break;

    case '+':  /* Compare individual words. */
      result = PATTERN_UNKNOWN;  /* Not implemented.  */
      break;

    case '/': /* Subject's DN. */
      s++;
      if (!*s || spacep (s))
        result = PATTERN_UNKNOWN; /* No DN or prefixed with a space. */
      else
        result = PATTERN_SUBJECT;
      break;

    case '#': /* Serial number or issuer DN. */
      {
        const char *si;

        s++;
        if ( *s == '/')
          {
            /* An issuer's DN is indicated by "#/" */
            s++;
            if (!*s || spacep (s))
              result = PATTERN_UNKNOWN; /* No DN or prefixed with a space. */
            else
              result = PATTERN_ISSUER;
          }
        else
          { /* Serialnumber + optional issuer ID. */
            for (si=s; *si && *si != '/'; si++)
              if (!strchr("01234567890abcdefABCDEF", *si))
                break;
            if (*si && *si != '/')
              result = PATTERN_UNKNOWN; /* Invalid digit in serial number. */
            else
              {
                *r_sn_offset = s - pattern;
                if (!*si)
                  result = PATTERN_SERIALNO;
                else
                  {
                    s = si+1;
                    if (!*s || spacep (s))
                      result = PATTERN_UNKNOWN; /* No DN or prefixed
                                                   with a space. */
                    else
                      result = PATTERN_SERIALNO_ISSUER;
                  }
              }
          }
      }
      break;

    case ':': /* Unified fingerprint. */
      {
        const char *se, *si;
        int i;

        se = strchr (++s, ':');
        if (!se)
          result = PATTERN_UNKNOWN;
        else
          {
            for (i=0, si=s; si < se; si++, i++ )
              if (!strchr("01234567890abcdefABCDEF", *si))
                break;
            if ( si < se )
              result = PATTERN_UNKNOWN; /* Invalid digit. */
            else if (i == 32)
              result = PATTERN_FINGERPRINT16;
            else if (i == 40)
              result = PATTERN_FINGERPRINT20;
            else
              result = PATTERN_UNKNOWN; /* Invalid length for a fingerprint. */
          }
      }
      break;

    case '&': /* Keygrip. */
      result = PATTERN_UNKNOWN;  /* Not implemented.  */
      break;

    default:
      if (s[0] == '0' && s[1] == 'x')
        {
          hexprefix = 1;
          s += 2;
        }

      hexlength = strspn(s, "0123456789abcdefABCDEF");

      /* Check if a hexadecimal number is terminated by EOS or blank. */
      if (hexlength && s[hexlength] && !spacep (s+hexlength))
        {
          /* If the "0x" prefix is used a correct termination is required. */
          if (hexprefix)
            {
              result = PATTERN_UNKNOWN;
              break; /* switch */
            }
          hexlength = 0;  /* Not a hex number.  */
        }

      if (hexlength == 8 || (!hexprefix && hexlength == 9 && *s == '0'))
        {
          if (hexlength == 9)
            s++;
          result = PATTERN_SHORT_KEYID;
        }
      else if (hexlength == 16 || (!hexprefix && hexlength == 17 && *s == '0'))
        {
          if (hexlength == 17)
            s++;
          result = PATTERN_LONG_KEYID;
        }
      else if (hexlength == 32 || (!hexprefix && hexlength == 33 && *s == '0'))
        {
          if (hexlength == 33)
            s++;
          result = PATTERN_FINGERPRINT16;
        }
      else if (hexlength == 40 || (!hexprefix && hexlength == 41 && *s == '0'))
        {
          if (hexlength == 41)
            s++;
          result = PATTERN_FINGERPRINT20;
        }
      else if (!hexprefix)
        {
          /* The fingerprints used with X.509 are often delimited by
             colons, so we try to single this case out. */
          result = PATTERN_UNKNOWN;
          hexlength = strspn (s, ":0123456789abcdefABCDEF");
          if (hexlength == 59 && (!s[hexlength] || spacep (s+hexlength)))
            {
              int i, c;

              for (i=0; i < 20; i++, s += 3)
                {
                  c = hextobyte(s);
                  if (c == -1 || (i < 19 && s[2] != ':'))
                    break;
                }
              if (i == 20)
                result = PATTERN_FINGERPRINT20;
            }
          if (result == PATTERN_UNKNOWN) /* Default to substring match. */
            {
              result = PATTERN_SUBSTR;
            }
        }
      else /* A hex number with a prefix but with a wrong length.  */
        result = PATTERN_UNKNOWN;
    }

  if (result != PATTERN_UNKNOWN)
    *r_offset = s - pattern;
  return result;
}
Пример #21
0
int
main (int argc, char **argv)
{
  char *args;
  char *logfile;
  char *passphrasefile;
  char *passphrase;

  /* We get our options via PINENTRY_USER_DATA.  */
  (void) argc, (void) argv;

  setvbuf (stdin, NULL, _IOLBF, BUFSIZ);
  setvbuf (stdout, NULL, _IOLBF, BUFSIZ);

  args = getenv ("PINENTRY_USER_DATA");
  if (! args)
    args = "";

  logfile = option_value (args, "--logfile");
  if (logfile)
    {
      char *p = logfile, more;
      while (*p && ! spacep (p))
        p++;
      more = !! *p;
      *p = 0;
      args = more ? p+1 : p;

      log_stream = fopen (logfile, "a");
      if (! log_stream)
        {
          perror (logfile);
          return 1;
        }
    }

  passphrasefile = option_value (args, "--passphrasefile");
  if (passphrasefile)
    {
      char *p = passphrasefile, more;
      while (*p && ! spacep (p))
        p++;
      more = !! *p;
      *p = 0;
      args = more ? p+1 : p;

      passphrase = get_passphrase (passphrasefile);
      if (! passphrase)
        {
          reply ("# Passphrasefile '%s' is empty.  Terminating.\n",
                 passphrasefile);
          return 1;
        }

      p = passphrase + strlen (passphrase) - 1;
      if (*p == '\n')
        *p = 0;
    }
  else
    passphrase = skip_options (args);

  reply ("# fake-pinentry started.  Passphrase='%s'.\n", passphrase);
  reply ("OK - what's up?\n");

  while (! feof (stdin))
    {
      char buffer[1024];

      if (fgets (buffer, sizeof buffer, stdin) == NULL)
	break;

      if (log_stream)
        fprintf (log_stream, "< %s", buffer);

      if (strncmp (buffer, "GETPIN", 6) == 0)
        reply ("D %s\n", passphrase);
      else if (strncmp (buffer, "BYE", 3) == 0)
	{
	  reply ("OK\n");
	  break;
	}

      reply ("OK\n");
    }

  reply ("# Connection terminated.\n");
  if (log_stream)
    fclose (log_stream);

  return 0;
}
Пример #22
0
static int
classify_user_id (const char *name,
                  KEYDB_SEARCH_DESC *desc,
                  int *force_exact )
{
  const char *s;
  int hexprefix = 0;
  int hexlength;
  int mode = 0;

  /* clear the structure so that the mode field is set to zero unless
   * we set it to the correct value right at the end of this function */
  memset (desc, 0, sizeof *desc);
  *force_exact = 0;
  /* Skip leading spaces.  Fixme: what about trailing white space? */
  for(s = name; *s && spacep (s); s++ )
    ;

  switch (*s)
    {
    case 0:  /* empty string is an error */
      return 0;

    case '.': /* an email address, compare from end */
      mode = KEYDB_SEARCH_MODE_MAILEND;
      s++;
      desc->u.name = s;
      break;

    case '<': /* an email address */
      mode = KEYDB_SEARCH_MODE_MAIL;
      s++;
      desc->u.name = s;
      break;

    case '@':  /* part of an email address */
      mode = KEYDB_SEARCH_MODE_MAILSUB;
      s++;
      desc->u.name = s;
      break;

    case '=':  /* exact compare */
      mode = KEYDB_SEARCH_MODE_EXACT;
      s++;
      desc->u.name = s;
      break;

    case '*':  /* case insensitive substring search */
      mode = KEYDB_SEARCH_MODE_SUBSTR;
      s++;
      desc->u.name = s;
      break;

    case '+':  /* compare individual words */
      mode = KEYDB_SEARCH_MODE_WORDS;
      s++;
      desc->u.name = s;
      break;

    case '/': /* subject's DN */
      s++;
      if (!*s || spacep (s))
        return 0; /* no DN or prefixed with a space */
      desc->u.name = s;
      mode = KEYDB_SEARCH_MODE_SUBJECT;
      break;

    case '#':
      {
        const char *si;

        s++;
        if ( *s == '/')
          { /* "#/" indicates an issuer's DN */
            s++;
            if (!*s || spacep (s))
              return 0; /* no DN or prefixed with a space */
            desc->u.name = s;
            mode = KEYDB_SEARCH_MODE_ISSUER;
          }
        else
          { /* serialnumber + optional issuer ID */
            for (si=s; *si && *si != '/'; si++)
              {
                if (!strchr("01234567890abcdefABCDEF", *si))
                  return 0; /* invalid digit in serial number*/
              }
            desc->sn = (const unsigned char*)s;
            desc->snlen = -1;
            if (!*si)
              mode = KEYDB_SEARCH_MODE_SN;
            else
              {
                s = si+1;
                if (!*s || spacep (s))
                  return 0; /* no DN or prefixed with a space */
                desc->u.name = s;
                mode = KEYDB_SEARCH_MODE_ISSUER_SN;
              }
          }
      }
      break;

    case ':': /*Unified fingerprint */
      {
        const char *se, *si;
        int i;

        se = strchr (++s,':');
        if (!se)
          return 0;
        for (i=0,si=s; si < se; si++, i++ )
          {
            if (!strchr("01234567890abcdefABCDEF", *si))
              return 0; /* invalid digit */
          }
        if (i != 32 && i != 40)
          return 0; /* invalid length of fpr*/
        for (i=0,si=s; si < se; i++, si +=2)
          desc->u.fpr[i] = hextobyte(si);
        for (; i < 20; i++)
          desc->u.fpr[i]= 0;
        s = se + 1;
        mode = KEYDB_SEARCH_MODE_FPR;
      }
      break;

    case '&': /* Keygrip*/
      {
        if (hex2bin (s+1, desc->u.grip, 20) < 0)
          return 0; /* Invalid. */
        mode = KEYDB_SEARCH_MODE_KEYGRIP;
      }
      break;

    default:
      if (s[0] == '0' && s[1] == 'x')
        {
          hexprefix = 1;
          s += 2;
        }

      hexlength = strspn(s, "0123456789abcdefABCDEF");
      if (hexlength >= 8 && s[hexlength] =='!')
        {
          *force_exact = 1;
          hexlength++; /* just for the following check */
        }

      /* check if a hexadecimal number is terminated by EOS or blank */
      if (hexlength && s[hexlength] && !spacep (s+hexlength))
        {
          if (hexprefix) /* a "0x" prefix without correct */
            return 0;	 /* termination is an error */
          /* The first chars looked like a hex number, but really is
             not */
          hexlength = 0;
        }

      if (*force_exact)
        hexlength--; /* remove the bang */

      if (hexlength == 8
          || (!hexprefix && hexlength == 9 && *s == '0'))
        { /* short keyid */
          unsigned long kid;
          if (hexlength == 9)
            s++;
          kid = strtoul( s, NULL, 16 );
          desc->u.kid[4] = kid >> 24;
          desc->u.kid[5] = kid >> 16;
          desc->u.kid[6] = kid >>  8;
          desc->u.kid[7] = kid;
          mode = KEYDB_SEARCH_MODE_SHORT_KID;
        }
      else if (hexlength == 16
Пример #23
0
/* skip_spaces - skip leading spaces */
int skip_spaces()
{
    while (spacep(*lptr))
	lptr++;
    return (*lptr != EOS);
}
Пример #24
0
/* Scan a string and return true if the string represents the human
   readable format of an ISO time.  This format is:
      yyyy-mm-dd[ hh[:mm[:ss]]]
   Scanning stops at the second space or at a comma.  */
static int
isotime_human_p (const char *string)
{
  const char *s;
  int i;

  if (!*string)
    return 0;
  for (s=string, i=0; i < 4; i++, s++)
    if (!digitp (s))
      return 0;
  if (*s != '-')
    return 0;
  s++;
  if (!digitp (s) || !digitp (s+1) || s[2] != '-')
    return 0;
  i = atoi_2 (s);
  if (i < 1 || i > 12)
    return 0;
  s += 3;
  if (!digitp (s) || !digitp (s+1))
    return 0;
  i = atoi_2 (s);
  if (i < 1 || i > 31)
    return 0;
  s += 2;
  if (!*s || *s == ',')
    return 1; /* Okay; only date given.  */
  if (!spacep (s))
    return 0;
  s++;
  if (spacep (s))
    return 1; /* Okay, second space stops scanning.  */
  if (!digitp (s) || !digitp (s+1))
    return 0;
  i = atoi_2 (s);
  if (i < 0 || i > 23)
    return 0;
  s += 2;
  if (!*s || *s == ',')
    return 1; /* Okay; only date and hour given.  */
  if (*s != ':')
    return 0;
  s++;
  if (!digitp (s) || !digitp (s+1))
    return 0;
  i = atoi_2 (s);
  if (i < 0 || i > 59)
    return 0;
  s += 2;
  if (!*s || *s == ',')
    return 1; /* Okay; only date, hour and minute given.  */
  if (*s != ':')
    return 0;
  s++;
  if (!digitp (s) || !digitp (s+1))
    return 0;
  i = atoi_2 (s);
  if (i < 0 || i > 60)
    return 0;
  s += 2;
  if (!*s || *s == ',' || spacep (s))
    return 1; /* Okay; date, hour and minute and second given.  */

  return 0; /* Unexpected delimiter.  */
}
Пример #25
0
static gpg_error_t
learn_status_cb (void *opaque, const char *line)
{
    struct agent_card_info_s *parm = opaque;
    const char *keyword = line;
    int keywordlen;
    int i;

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

    if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen))
    {
        xfree (parm->serialno);
        parm->serialno = store_serialno (line);
        parm->is_v2 = (strlen (parm->serialno) >= 16
                       && xtoi_2 (parm->serialno+12) >= 2 );
    }
    else if (keywordlen == 7 && !memcmp (keyword, "APPTYPE", keywordlen))
    {
        xfree (parm->apptype);
        parm->apptype = unescape_status_string (line);
    }
    else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen))
    {
        xfree (parm->disp_name);
        parm->disp_name = unescape_status_string (line);
    }
    else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen))
    {
        xfree (parm->disp_lang);
        parm->disp_lang = unescape_status_string (line);
    }
    else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen))
    {
        parm->disp_sex = *line == '1'? 1 : *line == '2' ? 2: 0;
    }
    else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen))
    {
        xfree (parm->pubkey_url);
        parm->pubkey_url = unescape_status_string (line);
    }
    else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen))
    {
        xfree (parm->login_data);
        parm->login_data = unescape_status_string (line);
    }
    else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen))
    {
        parm->sig_counter = strtoul (line, NULL, 0);
    }
    else if (keywordlen == 10 && !memcmp (keyword, "CHV-STATUS", keywordlen))
    {
        char *p, *buf;

        buf = p = unescape_status_string (line);
        if (buf)
        {
            while (spacep (p))
                p++;
            parm->chv1_cached = atoi (p);
            while (*p && !spacep (p))
                p++;
            while (spacep (p))
                p++;
            for (i=0; *p && i < 3; i++)
            {
                parm->chvmaxlen[i] = atoi (p);
                while (*p && !spacep (p))
                    p++;
                while (spacep (p))
                    p++;
            }
            for (i=0; *p && i < 3; i++)
            {
                parm->chvretry[i] = atoi (p);
                while (*p && !spacep (p))
                    p++;
                while (spacep (p))
                    p++;
            }
            xfree (buf);
        }
    }
    else if (keywordlen == 6 && !memcmp (keyword, "EXTCAP", keywordlen))
    {
        char *p, *p2, *buf;
        int abool;

        buf = p = unescape_status_string (line);
        if (buf)
        {
            for (p = strtok (buf, " "); p; p = strtok (NULL, " "))
            {
                p2 = strchr (p, '=');
                if (p2)
                {
                    *p2++ = 0;
                    abool = (*p2 == '1');
                    if (!strcmp (p, "ki"))
                        parm->extcap.ki = abool;
                    else if (!strcmp (p, "aac"))
                        parm->extcap.aac = abool;
                }
            }
            xfree (buf);
        }
    }
    else if (keywordlen == 7 && !memcmp (keyword, "KEY-FPR", keywordlen))
    {
        int no = atoi (line);
        while (*line && !spacep (line))
            line++;
        while (spacep (line))
            line++;
        if (no == 1)
            parm->fpr1valid = unhexify_fpr (line, parm->fpr1);
        else if (no == 2)
            parm->fpr2valid = unhexify_fpr (line, parm->fpr2);
        else if (no == 3)
            parm->fpr3valid = unhexify_fpr (line, parm->fpr3);
    }
    else if (keywordlen == 8 && !memcmp (keyword, "KEY-TIME", keywordlen))
    {
        int no = atoi (line);
        while (* line && !spacep (line))
            line++;
        while (spacep (line))
            line++;
        if (no == 1)
            parm->fpr1time = strtoul (line, NULL, 10);
        else if (no == 2)
            parm->fpr2time = strtoul (line, NULL, 10);
        else if (no == 3)
            parm->fpr3time = strtoul (line, NULL, 10);
    }
    else if (keywordlen == 6 && !memcmp (keyword, "CA-FPR", keywordlen))
    {
        int no = atoi (line);
        while (*line && !spacep (line))
            line++;
        while (spacep (line))
            line++;
        if (no == 1)
            parm->cafpr1valid = unhexify_fpr (line, parm->cafpr1);
        else if (no == 2)
            parm->cafpr2valid = unhexify_fpr (line, parm->cafpr2);
        else if (no == 3)
            parm->cafpr3valid = unhexify_fpr (line, parm->cafpr3);
    }
    else if (keywordlen == 8 && !memcmp (keyword, "KEY-ATTR", keywordlen))
    {
        int keyno, algo, nbits;

        sscanf (line, "%d %d %d", &keyno, &algo, &nbits);
        keyno--;
        if (keyno >= 0 && keyno < DIM (parm->key_attr))
        {
            parm->key_attr[keyno].algo = algo;
            parm->key_attr[keyno].nbits = nbits;
        }
    }

    return 0;
}
Пример #26
0
void
read_exchange_rates (void)
{
    gpg_error_t err = 0;
    estream_t fp;
    int lnr = 0;
    int n, c, idx;
    char line[256];
    char *p, *pend;
    double rate;

    fp = es_fopen (euroxref_fname, "r");
    if (!fp)
    {
        err = gpg_error_from_syserror ();
        log_error ("error opening '%s': %s\n",
                   euroxref_fname, gpg_strerror (err));
        return;
    }

    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 ("error reading '%s', line %d: %s\n",
                       euroxref_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 leading spaces and skip empty and comment lines. */
        for (p=line; spacep (p); p++)
            ;
        if (!*p || *p == '#')
            continue;

        /* Parse the currency name. */
        pend = strchr (p, '=');
        if (!pend)
        {
            log_error ("error parsing '%s', line %d: %s\n",
                       euroxref_fname, lnr, "missing '='");
            continue;
        }
        *pend++ = 0;
        trim_spaces (p);
        if (!*p)
        {
            log_error ("error parsing '%s', line %d: %s\n",
                       euroxref_fname, lnr, "currency name missing");
            continue;
        }

        /* Note that we start at 1 to skip the first entry which is
           EUR.  */
        for (idx=1; idx < DIM(currency_table); idx++)
            if (!strcasecmp (currency_table[idx].name, p))
                break;
        if (!(idx < DIM(currency_table)))
            continue; /* Currency not supported.  */

        /* Parse the rate. */
        p = pend;
        errno = 0;
        rate = strtod (p, &pend);
        if ((!rate && p == pend) || errno || rate <= 0.0 || rate > 10000.0)
        {
            log_error ("error parsing '%s', line %d: %s\n",
                       euroxref_fname, lnr, "invalid exchange rate");
            continue;
        }
        p = pend;
        trim_spaces (p);
        if (*p)
        {
            log_error ("error parsing '%s', line %d: %s\n",
                       euroxref_fname, lnr, "garbage after exchange rate");
            continue;
        }

        /* Update the tbale.  */
        if (currency_table[idx].rate != rate)
        {
            if (!currency_table[idx].rate)
                log_info ("setting exchange rate for %s to %.4f\n",
                          currency_table[idx].name, rate);
            else
                log_info ("changing exchange rate for %s from %.4f to %.4f\n",
                          currency_table[idx].name, currency_table[idx].rate, rate);

            currency_table[idx].rate = rate;
            jrnl_store_exchange_rate_record (currency_table[idx].name, rate);
        }
    }

    es_fclose (fp);
}
Пример #27
0
/* Handle one line of the encfs tool's output.  This function is
   allowed to modify the content of BUFFER.  */
static gpg_error_t
handle_status_line (runner_t runner, const char *line,
                    enum encfs_cmds cmd, tupledesc_t tuples)
{
  gpg_error_t err;

  /* Check that encfs understands our new options.  */
  if (!strncmp (line, "$STATUS$", 8))
    {
      for (line +=8; *line && spacep (line); line++)
        ;
      log_info ("got status '%s'\n", line);
      if (!strcmp (line, "fuse_main_start"))
        {
          /* Send a special error code back to let the caller know
             that everything has been setup by encfs.  */
          err = gpg_error (GPG_ERR_UNFINISHED);
        }
      else
        err = 0;
    }
  else if (!strncmp (line, "$PROMPT$", 8))
    {
      for (line +=8; *line && spacep (line); line++)
        ;
      log_info ("got prompt '%s'\n", line);
      if (!strcmp (line, "create_root_dir"))
        err = send_cmd (runner, cmd == ENCFS_CMD_CREATE? "y":"n");
      else if (!strcmp (line, "create_mount_point"))
        err = send_cmd (runner, "y");
      else if (!strcmp (line, "passwd")
               || !strcmp (line, "new_passwd"))
        {
          if (tuples)
            {
              size_t n;
              const void *value;

              value = find_tuple (tuples, KEYBLOB_TAG_ENCKEY, &n);
              if (!value)
                err = gpg_error (GPG_ERR_INV_SESSION_KEY);
              else if ((err = send_cmd_bin (runner, value, n)))
                {
                  if (gpg_err_code (err) == GPG_ERR_BUG
                      && gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT)
                    err = gpg_error (GPG_ERR_INV_SESSION_KEY);
                }
            }
          else
            err = gpg_error (GPG_ERR_NO_DATA);
        }
      else
        err = send_cmd (runner, ""); /* Default to send an empty line.  */
    }
  else if (strstr (line, "encfs: unrecognized option '"))
    err = gpg_error (GPG_ERR_INV_ENGINE);
  else
    err = 0;

  return err;
}