Esempio n. 1
0
static HRESULT parse_pubkey(IAssemblyNameImpl *name, LPCWSTR pubkey)
{
    int i;
    BYTE val;
    static const WCHAR nullstr[] = {'n','u','l','l',0};

    if(lstrcmpiW(pubkey, nullstr) == 0)
        return FUSION_E_PRIVATE_ASM_DISALLOWED;

    if (lstrlenW(pubkey) < CHARS_PER_PUBKEY)
        return FUSION_E_INVALID_NAME;

    for (i = 0; i < CHARS_PER_PUBKEY; i++)
        if (!is_hex(pubkey[i]))
            return FUSION_E_INVALID_NAME;

    name->haspubkey = TRUE;

    for (i = 0; i < CHARS_PER_PUBKEY; i += 2)
    {
        val = (hextobyte(pubkey[i]) << 4) + hextobyte(pubkey[i + 1]);
        name->pubkey[i / 2] = val;
    }

    return S_OK;
}
Esempio n. 2
0
/****************
 * Get the session key from the given string.
 * String is supposed to be formatted as this:
 *  <algo-id>:<even-number-of-hex-digits>
 */
int
get_override_session_key( DEK *dek, const char *string )
{
    const char *s;
    int i;

    if ( !string )
	return G10ERR_BAD_KEY;
    dek->algo = atoi(string);
    if ( dek->algo < 1 )
	return G10ERR_BAD_KEY;
    if ( !(s = strchr ( string, ':' )) )
	return G10ERR_BAD_KEY;
    s++;
    for(i=0; i < DIM(dek->key) && *s; i++, s +=2 ) {
	int c = hextobyte ( s );
	if (c == -1)
	    return G10ERR_BAD_KEY;
	dek->key[i] = c;
    }
    if ( *s )
	return G10ERR_BAD_KEY;
    dek->keylen = i;
    return 0;
}
Esempio n. 3
0
BOOL hitag2_config_block_show(BYTE *config, BYTE *password, BYTE *key)
{
    BYTE    value= hextobyte(config); // first byte only used as config

    UserMessage("     PWD Block (1): %.8s    ", password);
    printhexreadable(password, 4);

    UserMessage("\r\n\r\n     Key Block (2): %.8s    ", key);
    printhexreadable(key, 4);

    UserMessage("\r\n\r\n  Config Block (3): %.8s\r\n\r\n", config);
    UserMessageNum("        Page 1 & 2: %d = ", GET_CONFIG(value, HITAG2_MASK_PAGE_1_2_OTP_PROTECT, HITAG2_SHIFT_PAGE_1_2_OTP_PROTECT));
    if(GET_CONFIG(value, HITAG2_MASK_SECURITY, HITAG2_SHIFT_SECURITY))
        UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_PAGE_1_2_OTP_PROTECT, HITAG2_SHIFT_PAGE_1_2_OTP_PROTECT) ? "No Read / No Write" : "Read / Write");
    else
        UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_PAGE_1_2_OTP_PROTECT, HITAG2_SHIFT_PAGE_1_2_OTP_PROTECT) ? "Page 1: No Read / No Write, Page 2: Read Only" : "Read / Write");
    UserMessageNum("            Page 3: %d = ", GET_CONFIG(value, HITAG2_MASK_PAGE_3_OTP_PROTECT, HITAG2_SHIFT_PAGE_3_OTP_PROTECT));
    UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_PAGE_3_OTP_PROTECT, HITAG2_SHIFT_PAGE_3_OTP_PROTECT) ? "Read Only" : "Read / Write");
    UserMessageNum("        Page 4 & 5: %d = ", GET_CONFIG(value, HITAG2_MASK_PAGE_4_5_PROTECT, HITAG2_SHIFT_PAGE_4_5_PROTECT));
    UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_PAGE_4_5_PROTECT, HITAG2_SHIFT_PAGE_4_5_PROTECT) ? "Read Only" : "Read / Write");
    UserMessageNum("        Page 6 & 7: %d = ", GET_CONFIG(value, HITAG2_MASK_PAGE_6_7_PROTECT, HITAG2_SHIFT_PAGE_6_7_PROTECT));
    UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_PAGE_6_7_PROTECT, HITAG2_SHIFT_PAGE_6_7_PROTECT) ? "Read Only" : "Read / Write");
    UserMessageNum("          Security: %d = ", GET_CONFIG(value, HITAG2_MASK_SECURITY, HITAG2_SHIFT_SECURITY));
    UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_SECURITY, HITAG2_SHIFT_SECURITY) ? "Crypto" : "Password");
    UserMessageNum("              Mode: %d = ", GET_CONFIG(value, HITAG2_MASK_MODE, HITAG2_SHIFT_MODE));
    UserMessage("%s\r\n", (BYTE *) Hitag2_Modes[GET_CONFIG(value, HITAG2_MASK_MODE, HITAG2_SHIFT_MODE)]);
    UserMessageNum("        Modulation: %d = ", GET_CONFIG(value, HITAG2_MASK_MODULATION, HITAG2_SHIFT_MODULATION));
    UserMessage("%s\r\n", GET_CONFIG(value, HITAG2_MASK_MODULATION, HITAG2_SHIFT_MODULATION) ? "BiPhase" : "Manchester");

    UserMessage("\r\n     PWD Block (3): %.6s      ", config + 2);
    printhexreadable(config + 2, 3);
    UserMessage("%s", "\r\n");
    return TRUE;
}
Esempio n. 4
0
float hextofloat(std::string data) {
    if (data.find(',') < 8 || data.length() != 8) {
        return NAN;
    }

    unsigned char chdata[4];
    for (int i=0; i<4; i++) {
        std::string substr = data.substr(i*2, (i*2)+2);
        chdata[i] = hextobyte(substr);
    }

    float output = *(float *)((void *)chdata); //floating point bit level hack
    return output;
}
Esempio n. 5
0
static char *
format_fingerprint ( const char *s )
{
    int i, c;
    byte fpr[20];

    for (i=0; i < 20 && *s; ) {
        if ( *s == ' ' || *s == '\t' ) {
            s++;
            continue;
        }
        c = hextobyte(s);
        if (c == -1) {
            return NULL;
        }
        fpr[i++] = c;
        s += 2;
    }
    return gcry_xstrdup ( fpr );
}
Esempio n. 6
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;
}
Esempio n. 7
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
Esempio n. 8
0
unsigned char
fromhex(const std::string& x,
        size_t idx)
{
  return (hextobyte(x[idx * 2]) << 4) | (hextobyte(x[idx * 2 + 1]));
}
Esempio n. 9
0
/****************
 * Scan the provided buffer and return the S expression in our internal
 * format.  Returns a newly allocated expression.  If erroff is not NULL and
 * a parsing error has occured, the offset into buffer will be returned.
 * If ARGFLAG is true, the function supports some printf like
 * expressions.
 *  These are:
 *	%m - MPI
 *	%s - string (no autoswitch to secure allocation)
 *	%d - integer stored as string (no autoswitch to secure allocation)
 *      %b - memory buffer; this takes _two_ arguments: an integer with the 
 *           length of the buffer and a pointer to the buffer.
 *  all other format elements are currently not defined and return an error.
 *  this includes the "%%" sequence becauce the percent sign is not an
 *  allowed character.
 * FIXME: We should find a way to store the secure-MPIs not in the string
 * but as reference to somewhere - this can help us to save huge amounts
 * of secure memory.  The problem is, that if only one element is secure, all
 * other elements are automagicaly copied to secure memory too, so the most
 * common operation gcry_sexp_cdr_mpi() will always return a secure MPI
 * regardless whether it is needed or not.
 */
static gcry_error_t
sexp_sscan (gcry_sexp_t *retsexp, size_t *erroff,
	    const char *buffer, size_t length, int argflag,
	    va_list arg_ptr, void **arg_list)
{
  gcry_err_code_t err = GPG_ERR_NO_ERROR;
  static const char tokenchars[] =
    "abcdefghijklmnopqrstuvwxyz"
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "0123456789-./_:*+=";
  const char *p;
  size_t n;
  const char *digptr = NULL;
  const char *quoted = NULL;
  const char *tokenp = NULL;
  const char *hexfmt = NULL;
  const char *base64 = NULL;
  const char *disphint = NULL;
  const char *percent = NULL;
  int hexcount = 0;
  int quoted_esc = 0;
  int datalen = 0;
  size_t dummy_erroff;
  struct make_space_ctx c;
  int arg_counter = 0;
  int level = 0;

  /* FIXME: invent better error codes (?).  */

  if (! erroff)
    erroff = &dummy_erroff;

  /* Depending on wether ARG_LIST is non-zero or not, this macro gives
     us the next argument, either from the variable argument list as
     specified by ARG_PTR or from the argument array ARG_LIST.  */
#define ARG_NEXT(storage, type)                          \
  do                                                     \
    {                                                    \
      if (! arg_list)                                    \
	storage = va_arg (arg_ptr, type);                \
      else                                               \
	storage = *((type *) (arg_list[arg_counter++])); \
    }                                                    \
  while (0)

#define MAKE_SPACE(n)  do { make_space ( &c, (n) ); } while (0)
#define STORE_LEN(p,n) do {						   \
			    DATALEN ashort = (n);			   \
			    memcpy ( (p), &ashort, sizeof(ashort) );	   \
			    (p) += sizeof (ashort);			   \
			} while (0)

  /* We assume that the internal representation takes less memory
   * than the provided one.  However, we add space for one extra datalen
   * so that the code which does the ST_CLOSE can use MAKE_SPACE */
  c.allocated = length + sizeof(DATALEN);
  if (buffer && length && gcry_is_secure (buffer))
    c.sexp = gcry_xmalloc_secure (sizeof *c.sexp + c.allocated - 1);
  else
    c.sexp = gcry_xmalloc (sizeof *c.sexp + c.allocated - 1);
  c.pos = c.sexp->d;

  for (p = buffer, n = length; n; p++, n--)
    {
      if (tokenp && (! hexfmt))
	{
	  if (strchr (tokenchars, *p))
	    continue;
	  else
	    {
	      datalen = p - tokenp;
	      MAKE_SPACE (datalen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, datalen);
	      memcpy (c.pos, tokenp, datalen);
	      c.pos += datalen;
	      tokenp = NULL;
	    }
	}

      if (quoted)
	{
	  if (quoted_esc)
	    {
	      switch (*p)
		{
		case 'b': case 't': case 'v': case 'n': case 'f':
		case 'r': case '"': case '\'': case '\\':
		  quoted_esc = 0;
		  break;

		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7':
		  if (! ((n > 2)
			 && (p[1] >= '0') && (p[1] <= '7')
			 && (p[2] >= '0') && (p[2] <= '7')))
		    {
		      *erroff = p - buffer;
		      /* Invalid octal value.  */
		      err = GPG_ERR_SEXP_BAD_QUOTATION;
		      //return gcry_error (GPG_ERR_SEXP_BAD_QUOTATION);
		    }
		  p += 2;
		  n -= 2;
		  quoted_esc = 0;
		  break;
		  
		case 'x':
		  if (! ((n > 2) && isxdigit(p[1]) && isxdigit(p[2])))
		    {
		      *erroff = p - buffer;
		      /* Invalid hex value.  */
		      err = GPG_ERR_SEXP_BAD_QUOTATION;
		      //return gcry_error (GPG_ERR_SEXP_BAD_QUOTATION);
		    }
		  p += 2;
		  n -= 2;
		  quoted_esc = 0;
		  break;

		case '\r':
		  /* ignore CR[,LF] */
		  if (n && (p[1] == '\n'))
		    {
		      p++;
		      n--;
		    }
		  quoted_esc = 0;
		  break;

		case '\n':
		  /* ignore LF[,CR] */
		  if (n && (p[1] == '\r'))
		    {
		      p++;
		      n--;
		    }
		  quoted_esc = 0;
		  break;

		default:
		  *erroff = p - buffer;
		  /* Invalid quoted string escape.  */
		  err = GPG_ERR_SEXP_BAD_QUOTATION;
		}
	    }
	  else if (*p == '\\')
	    quoted_esc = 1;
	  else if (*p == '\"')
	    {
	      /* Keep it easy - we know that the unquoted string will
		 never be larger. */
	      char *save;
	      size_t len;
	      
	      quoted++; /* Skip leading quote.  */
	      MAKE_SPACE (p - quoted);
	      *c.pos++ = ST_DATA;
	      save = c.pos;
	      STORE_LEN (c.pos, 0); /* Will be fixed up later.  */
	      len = unquote_string (quoted, p - quoted, c.pos);
	      c.pos += len;
	      STORE_LEN (save, len);
	      quoted = NULL;
	    }
	}
      else if (hexfmt)
	{
	  if (isxdigit (*p))
	    hexcount++;
	  else if (*p == '#')
	    {
	      if ((hexcount & 1))
		{
		  *erroff = p - buffer;
		  err = GPG_ERR_SEXP_ODD_HEX_NUMBERS;
		}

	      datalen = hexcount / 2;
	      MAKE_SPACE (datalen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, datalen);
	      for (hexfmt++; hexfmt < p; hexfmt++)
		{
		  if (isspace (*hexfmt))
		    continue;
		  *c.pos++ = hextobyte (hexfmt);
		  hexfmt++;
		}
	      hexfmt = NULL;
	    }
	  else if (! isspace (*p))
	    {
	      *erroff = p - buffer;
	      err = GPG_ERR_SEXP_BAD_HEX_CHAR;
	    }
	}
      else if (base64)
	{
	  if (*p == '|')
	    base64 = NULL;
	}
      else if (digptr)
	{
	  if (isdigit (*p))
	    ;
	  else if (*p == ':')
	    {
	      datalen = atoi (digptr); /* FIXME: check for overflow.  */
	      digptr = NULL;
	      if (datalen > n - 1)
		{
		  *erroff = p - buffer;
		  /* Buffer too short.  */
		  err = GPG_ERR_SEXP_STRING_TOO_LONG;
		}
	      /* Make a new list entry.  */
	      MAKE_SPACE (datalen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, datalen);
	      memcpy (c.pos, p + 1, datalen);
	      c.pos += datalen;
	      n -= datalen;
	      p += datalen;
	    }
	  else if (*p == '\"')
	    {
	      digptr = NULL; /* We ignore the optional length.  */
	      quoted = p;
	      quoted_esc = 0;
	    }
	  else if (*p == '#')
	    {
	      digptr = NULL; /* We ignore the optional length.  */
	      hexfmt = p;
	      hexcount = 0;
	    }
	  else if (*p == '|')
	    {
	      digptr = NULL; /* We ignore the optional length.  */
	      base64 = p;
	    }
	  else
	    {
	      *erroff = p - buffer;
	      err = GPG_ERR_SEXP_INV_LEN_SPEC;
	    }
	}
      else if (percent)
	{
	  if (*p == 'm')
	    {
	      /* Insert an MPI.  */
	      gcry_mpi_t m;
	      size_t nm = 0;

	      ARG_NEXT (m, gcry_mpi_t);
	      
	      if (gcry_mpi_print (GCRYMPI_FMT_STD, NULL, 0, &nm, m))
		BUG ();

	      MAKE_SPACE (nm);
	      if ((! gcry_is_secure (c.sexp->d))
		  &&  gcry_mpi_get_flag ( m, GCRYMPI_FLAG_SECURE))
		{
		  /* We have to switch to secure allocation.  */
		  gcry_sexp_t newsexp;
		  byte *newhead;

		  newsexp = gcry_xmalloc_secure (sizeof *newsexp
						 + c.allocated - 1);
		  newhead = newsexp->d;
		  memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
		  c.pos = newhead + (c.pos - c.sexp->d);
		  gcry_free (c.sexp);
		  c.sexp = newsexp;
		}

	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, nm);
	      if (gcry_mpi_print (GCRYMPI_FMT_STD, c.pos, nm, &nm, m))
		BUG ();
	      c.pos += nm;
	    }
	  else if (*p == 's')
	    {
	      /* Insert an string.  */
	      const char *astr;
	      size_t alen;

	      ARG_NEXT (astr, const char *);
	      alen = strlen (astr);
	      
	      MAKE_SPACE (alen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, astr, alen);
	      c.pos += alen;
	    }
	  else if (*p == 'b')
	    {
	      /* Insert a memory buffer.  */
	      const char *astr;
	      int alen;

	      ARG_NEXT (alen, int);
	      ARG_NEXT (astr, const char *);
	      
	      MAKE_SPACE (alen);
	      if (alen
                  && !gcry_is_secure (c.sexp->d)
		  && gcry_is_secure (astr))
              {
		  /* We have to switch to secure allocation.  */
		  gcry_sexp_t newsexp;
		  byte *newhead;

		  newsexp = gcry_xmalloc_secure (sizeof *newsexp
 						 + c.allocated - 1);
		  newhead = newsexp->d;
		  memcpy (newhead, c.sexp->d, (c.pos - c.sexp->d));
		  c.pos = newhead + (c.pos - c.sexp->d);
		  gcry_free (c.sexp);
		  c.sexp = newsexp;
		}

	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, astr, alen);
	      c.pos += alen;
	    }
	  else if (*p == 'd')
	    {
	      /* Insert an integer as string.  */
	      int aint;
	      size_t alen;
	      char buf[20];
	      
	      ARG_NEXT (aint, int);
	      sprintf (buf, "%d", aint);
	      alen = strlen (buf);
	      MAKE_SPACE (alen);
	      *c.pos++ = ST_DATA;
	      STORE_LEN (c.pos, alen);
	      memcpy (c.pos, buf, alen);
	      c.pos += alen;
	    }
	  else
	    {
	      *erroff = p - buffer;
	      /* Invalid format specifier.  */
	      err = GPG_ERR_SEXP_INV_LEN_SPEC;
	    }
	  percent = NULL;
	}
      else if (*p == '(')
	{
	  if (disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_UNMATCHED_DH;
	    }
	  MAKE_SPACE (0);
	  *c.pos++ = ST_OPEN;
	  level++;
	}
      else if (*p == ')')
	{
	  /* Walk up.  */
	  if (disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_UNMATCHED_DH;
	    }
	  MAKE_SPACE (0);
	  *c.pos++ = ST_CLOSE;
	  level--;
	}
      else if (*p == '\"')
	{
	  quoted = p;
	  quoted_esc = 0;
	}
      else if (*p == '#')
	{
	  hexfmt = p;
	  hexcount = 0;
	}
      else if (*p == '|')
	base64 = p;
      else if (*p == '[')
	{
	  if (disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_NESTED_DH;
	    }
	  disphint = p;
	}
      else if (*p == ']')
	{
	  if (! disphint)
	    {
	      *erroff = p - buffer;
	      /* Open display hint.  */
	      err = GPG_ERR_SEXP_UNMATCHED_DH;
	    }
	  disphint = NULL;
	}
      else if (isdigit (*p))
	{
	  if (*p == '0')
	    {
	      /* A length may not begin with zero.  */
	      *erroff = p - buffer;
	      err = GPG_ERR_SEXP_ZERO_PREFIX;
	    }
	  digptr = p;
	}
      else if (strchr (tokenchars, *p))
	tokenp = p;
      else if (isspace (*p))
	;
      else if (*p == '{')
	{
	  /* fixme: handle rescanning: we can do this by saving our
	     current state and start over at p+1 -- Hmmm. At this
	     point here we are in a well defined state, so we don't
	     need to save it.  Great.  */
	  *erroff = p - buffer;
	  err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
	}
      else if (strchr ("&\\", *p))
	{
	  /* Reserved punctuation.  */
	  *erroff = p - buffer;
	  err = GPG_ERR_SEXP_UNEXPECTED_PUNC;
	}
      else if (argflag && (*p == '%'))
	percent = p;
      else
	{
	  /* Bad or unavailable.  */
	  *erroff = p - buffer;
	  err = GPG_ERR_SEXP_BAD_CHARACTER;
	}
    }
  MAKE_SPACE (0);
  *c.pos++ = ST_STOP;

  if (level)
    err = GPG_ERR_SEXP_UNMATCHED_PAREN;

  if (err)
    {
      /* Error -> deallocate.  */
      if (c.sexp)
        {
          /* Extra paranoid wipe on error. */
          if (gcry_is_secure (c.sexp))
            wipememory (c.sexp, sizeof (struct gcry_sexp) + c.allocated - 1);
          gcry_free (c.sexp);
        }
      /* This might be expected by existing code...  */
      *retsexp = NULL;
    }
  else
    *retsexp = normalize (c.sexp);

  return gcry_error (err);
#undef MAKE_SPACE
#undef STORE_LEN
}
Esempio n. 10
0
/* Returns a keyrec (which must be freed) once a key is complete, and
   NULL otherwise.  Call with a NULL keystring once key parsing is
   complete to return any unfinished keys. */
static struct keyrec *
parse_keyrec(char *keystring)
{
  /* FIXME: Remove the static and put the data into the parms we use
     for the caller anyway.  */
  static struct keyrec *work=NULL;
  struct keyrec *ret=NULL;
  char *record;
  int i;

  if(keystring==NULL)
    {
      if(work==NULL)
	return NULL;
      else if(work->desc.mode==KEYDB_SEARCH_MODE_NONE)
	{
	  xfree(work);
	  return NULL;
	}
      else
	{
	  ret=work;
	  work=NULL;
	  return ret;
	}
    }

  if(work==NULL)
    {
      work=xmalloc_clear(sizeof(struct keyrec));
      work->uidbuf=iobuf_temp();
    }

  trim_trailing_ws (keystring, strlen (keystring));

  if((record=strsep(&keystring,":"))==NULL)
    return ret;

  if(ascii_strcasecmp("pub",record)==0)
    {
      char *tok;
      gpg_error_t err;

      if(work->desc.mode)
	{
	  ret=work;
	  work=xmalloc_clear(sizeof(struct keyrec));
	  work->uidbuf=iobuf_temp();
	}

      if((tok=strsep(&keystring,":"))==NULL)
	return ret;

      err = classify_user_id (tok, &work->desc, 1);
      if (err || (work->desc.mode    != KEYDB_SEARCH_MODE_SHORT_KID
                  && work->desc.mode != KEYDB_SEARCH_MODE_LONG_KID
                  && work->desc.mode != KEYDB_SEARCH_MODE_FPR16
                  && work->desc.mode != KEYDB_SEARCH_MODE_FPR20))
	{
	  work->desc.mode=KEYDB_SEARCH_MODE_NONE;
	  return ret;
	}

      /* Note all items after this are optional.  This allows us to
         have a pub line as simple as pub:keyid and nothing else. */

      work->lines++;

      if((tok=strsep(&keystring,":"))==NULL)
	return ret;

      work->type=atoi(tok);

      if((tok=strsep(&keystring,":"))==NULL)
	return ret;

      work->size=atoi(tok);

      if((tok=strsep(&keystring,":"))==NULL)
	return ret;

      if(atoi(tok)<=0)
	work->createtime=0;
      else
	work->createtime=atoi(tok);

      if((tok=strsep(&keystring,":"))==NULL)
	return ret;

      if(atoi(tok)<=0)
	work->expiretime=0;
      else
	{
	  work->expiretime=atoi(tok);
	  /* Force the 'e' flag on if this key is expired. */
	  if(work->expiretime<=make_timestamp())
	    work->flags|=4;
	}

      if((tok=strsep(&keystring,":"))==NULL)
	return ret;

      while(*tok)
	switch(*tok++)
	  {
	  case 'r':
	  case 'R':
	    work->flags|=1;
	    break;

	  case 'd':
	  case 'D':
	    work->flags|=2;
	    break;

	  case 'e':
	  case 'E':
	    work->flags|=4;
	    break;
	  }
    }
  else if(ascii_strcasecmp("uid",record)==0 && work->desc.mode)
    {
      char *userid,*tok,*decoded;

      if((tok=strsep(&keystring,":"))==NULL)
	return ret;

      if(strlen(tok)==0)
	return ret;

      userid=tok;

      /* By definition, de-%-encoding is always smaller than the
         original string so we can decode in place. */

      i=0;

      while(*tok)
	if(tok[0]=='%' && tok[1] && tok[2])
	  {
            int c;

	    userid[i] = (c=hextobyte(&tok[1])) == -1 ? '?' : c;
	    i++;
	    tok+=3;
	  }
	else
	  userid[i++]=*tok++;

      /* We don't care about the other info provided in the uid: line
         since no keyserver supports marking userids with timestamps
         or revoked/expired/disabled yet. */

      /* No need to check for control characters, as utf8_to_native
	 does this for us. */

      decoded=utf8_to_native(userid,i,0);
      if(strlen(decoded)>opt.screen_columns-10)
	decoded[opt.screen_columns-10]='\0';
      iobuf_writestr(work->uidbuf,decoded);
      xfree(decoded);
      iobuf_writestr(work->uidbuf,"\n\t");
      work->lines++;
    }

  /* Ignore any records other than "pri" and "uid" for easy future
     growth. */

  return ret;
}