Exemplo n.º 1
0
/* This function will convert an attribute value, specified by the OID,
 * to a string. The result will be a null terminated string.
 *
 * res may be null. This will just return the res_size, needed to
 * hold the string.
 */
int
_gnutls_x509_oid_data2string (const char *oid, void *value,
                              int value_size, char *res, size_t * res_size)
{
  char str[MAX_STRING_LEN], tmpname[128];
  const char *ANAME = NULL;
  int CHOICE = -1, len = -1, result;
  ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY;
  char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE] = "";

  if (value == NULL || value_size <= 0 || res_size == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (_gnutls_x509_oid_data_printable (oid) == 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  ANAME = _gnutls_x509_oid2asn_string (oid);
  CHOICE = _gnutls_x509_oid_data_choice (oid);

  if (ANAME == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  if ((result =
       asn1_create_element (_gnutls_get_pkix (), ANAME,
                            &tmpasn)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  if ((result =
       asn1_der_decoding (&tmpasn, value, value_size,
                          asn1_err)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      _gnutls_debug_log ("asn1_der_decoding: %s:%s\n", str, asn1_err);
      asn1_delete_structure (&tmpasn);
      return _gnutls_asn2err (result);
    }

  /* If this is a choice then we read the choice. Otherwise it
   * is the value;
   */
  len = sizeof (str) - 1;
  if ((result = asn1_read_value (tmpasn, "", str, &len)) != ASN1_SUCCESS)
    {                           /* CHOICE */
      gnutls_assert ();
      asn1_delete_structure (&tmpasn);
      return _gnutls_asn2err (result);
    }

  if (CHOICE == 0)
    {
      str[len] = 0;

      /* Refuse to deal with strings containing NULs. */
      if (strlen (str) != len)
        return GNUTLS_E_ASN1_DER_ERROR;

      if (res)
        _gnutls_str_cpy (res, *res_size, str);
      *res_size = len;

      asn1_delete_structure (&tmpasn);
    }
  else
    {                           /* CHOICE */
      int non_printable = 0, teletex = 0;
      str[len] = 0;

      /* Note that we do not support strings other than
       * UTF-8 (thus ASCII as well).
       */
      if (strcmp (str, "printableString") != 0 &&
          strcmp (str, "ia5String") != 0 && strcmp (str, "utf8String") != 0)
        {
          non_printable = 1;
        }
      if (strcmp (str, "teletexString") == 0)
        teletex = 1;


      _gnutls_str_cpy (tmpname, sizeof (tmpname), str);

      len = sizeof (str) - 1;
      if ((result =
           asn1_read_value (tmpasn, tmpname, str, &len)) != ASN1_SUCCESS)
        {
          asn1_delete_structure (&tmpasn);
          return _gnutls_asn2err (result);
        }

      asn1_delete_structure (&tmpasn);

      if (teletex != 0)
        {
          int ascii = 0, i;
          /* HACK: if the teletex string contains only ascii
           * characters then treat it as printable.
           */
          for (i = 0; i < len; i++)
            if (!isascii (str[i]))
              ascii = 1;

          if (ascii == 0)
            non_printable = 0;
        }

      if (non_printable == 0)
        {
          str[len] = 0;

          /* Refuse to deal with strings containing NULs. */
          if (strlen (str) != len)
            return GNUTLS_E_ASN1_DER_ERROR;

          if (res)
            _gnutls_str_cpy (res, *res_size, str);
          *res_size = len;
        }
      else
        {
          result = _gnutls_x509_data2hex (str, len, res, res_size);
          if (result < 0)
            {
              gnutls_assert ();
              return result;
            }
        }
    }

  return 0;
}
Exemplo n.º 2
0
/* Parses an X509 DN in the asn1_struct, and searches for the
 * given OID in the DN.
 *
 * If raw_flag == 0, the output will be encoded in the LDAP way. (#hex for non printable)
 * Otherwise the raw DER data are returned.
 *
 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
 * That is to point in the rndSequence.
 *
 * indx specifies which OID to return. Ie 0 means return the first specified
 * OID found, 1 the second etc.
 */
int
_gnutls_x509_parse_dn_oid (ASN1_TYPE asn1_struct,
			   const char *asn1_rdn_name,
			   const char *given_oid, int indx,
			   unsigned int raw_flag,
			   void *buf, size_t * sizeof_buf)
{
  int k2, k1, result;
  char tmpbuffer1[MAX_NAME_SIZE];
  char tmpbuffer2[MAX_NAME_SIZE];
  char tmpbuffer3[MAX_NAME_SIZE];
  opaque value[256];
  char oid[128];
  int len, printable;
  int i = 0;
  char *cbuf = buf;

  if (cbuf == NULL)
    *sizeof_buf = 0;
  else
    cbuf[0] = 0;

  k1 = 0;
  do
    {

      k1++;
      /* create a string like "tbsCertList.issuer.rdnSequence.?1"
       */
      if (asn1_rdn_name[0] != 0)
        snprintf( tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name, k1);
      else
        snprintf( tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1);

      len = sizeof (value) - 1;
      result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len);

      if (result == ASN1_ELEMENT_NOT_FOUND)
	{
	  gnutls_assert ();
	  break;
	}

      if (result != ASN1_VALUE_NOT_FOUND)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      k2 = 0;

      do
	{			/* Move to the attibute type and values
				 */
	  k2++;

          if (tmpbuffer1[0] != 0)
            snprintf( tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1, k2);
          else
            snprintf( tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2);

	  /* Try to read the RelativeDistinguishedName attributes.
	   */

	  len = sizeof (value) - 1;
	  result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len);

	  if (result == ASN1_ELEMENT_NOT_FOUND)
	    {
	      break;
	    }
	  if (result != ASN1_VALUE_NOT_FOUND)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }

	  /* Read the OID 
	   */
	  _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
	  _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type");

	  len = sizeof (oid) - 1;
	  result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len);

	  if (result == ASN1_ELEMENT_NOT_FOUND)
	    break;
	  else if (result != ASN1_SUCCESS)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }

	  if (strcmp (oid, given_oid) == 0 && indx == i++)
	    {			/* Found the OID */

	      /* Read the Value 
	       */
	      _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
	      _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value");

	      len = *sizeof_buf;
	      result = asn1_read_value (asn1_struct, tmpbuffer3, buf, &len);

	      if (result != ASN1_SUCCESS)
		{
		  gnutls_assert ();
		  if (result == ASN1_MEM_ERROR)
		    *sizeof_buf = len;
		  result = _gnutls_asn2err (result);
		  goto cleanup;
		}

	      if (raw_flag != 0)
		{
		  if ((unsigned) len > *sizeof_buf)
		    {
		      *sizeof_buf = len;
		      result = GNUTLS_E_SHORT_MEMORY_BUFFER;
		      goto cleanup;
		    }
		  *sizeof_buf = len;

		  return 0;

		}
	      else
		{		/* parse data. raw_flag == 0 */
		  printable = _gnutls_x509_oid_data_printable (oid);

		  if (printable == 1)
		    result =
		      _gnutls_x509_oid_data2string (oid, buf, len,
						    cbuf, sizeof_buf);
		  else
		    result =
		      _gnutls_x509_data2hex (buf, len, cbuf, sizeof_buf);

		  if (result < 0)
		    {
		      gnutls_assert ();
		      goto cleanup;
		    }

		  return 0;

		}		/* raw_flag == 0 */
	    }
	}
      while (1);

    }
  while (1);

  gnutls_assert ();

  result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;

cleanup:
  return result;
}
Exemplo n.º 3
0
/* Parses an X509 DN in the asn1_struct, and puts the output into
 * the string buf. The output is an LDAP encoded DN.
 *
 * asn1_rdn_name must be a string in the form "tbsCertificate.issuer.rdnSequence".
 * That is to point in the rndSequence.
 */
int
_gnutls_x509_parse_dn (ASN1_TYPE asn1_struct,
		       const char *asn1_rdn_name, char *buf,
		       size_t * sizeof_buf)
{
  gnutls_string out_str;
  int k2, k1, result;
  char tmpbuffer1[MAX_NAME_SIZE];
  char tmpbuffer2[MAX_NAME_SIZE];
  char tmpbuffer3[MAX_NAME_SIZE];
  opaque value[MAX_STRING_LEN], *value2 = NULL;
  char *escaped = NULL;
  const char *ldap_desc;
  char oid[128];
  int len, printable;
  char *string = NULL;
  size_t sizeof_string, sizeof_escaped;

  if (sizeof_buf == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (buf)
    buf[0] = 0;
  else
    *sizeof_buf = 0;

  _gnutls_string_init (&out_str, gnutls_malloc, gnutls_realloc, gnutls_free);

  k1 = 0;
  do
    {

      k1++;
      /* create a string like "tbsCertList.issuer.rdnSequence.?1"
       */
      if (asn1_rdn_name[0]!=0)
        snprintf( tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", asn1_rdn_name, k1);
      else
        snprintf( tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1);
      
      len = sizeof (value) - 1;
      result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len);

      if (result == ASN1_ELEMENT_NOT_FOUND)
	{
	  break;
	}

      if (result != ASN1_VALUE_NOT_FOUND)
	{
	  gnutls_assert ();
	  result = _gnutls_asn2err (result);
	  goto cleanup;
	}

      k2 = 0;

      do
	{			/* Move to the attibute type and values
				 */
	  k2++;

          if (tmpbuffer1[0] != 0)
  	    snprintf( tmpbuffer2, sizeof (tmpbuffer2), "%s.?%u", tmpbuffer1, k2);
          else
  	    snprintf( tmpbuffer2, sizeof (tmpbuffer2), "?%u", k2);

	  /* Try to read the RelativeDistinguishedName attributes.
	   */

	  len = sizeof (value) - 1;
	  result = asn1_read_value (asn1_struct, tmpbuffer2, value, &len);

	  if (result == ASN1_ELEMENT_NOT_FOUND)
	    break;
	  if (result != ASN1_VALUE_NOT_FOUND)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }

	  /* Read the OID 
	   */
	  _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
	  _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type");

	  len = sizeof (oid) - 1;
	  result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len);

	  if (result == ASN1_ELEMENT_NOT_FOUND)
	    break;
	  else if (result != ASN1_SUCCESS)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }

	  /* Read the Value 
	   */
	  _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer2);
	  _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".value");

	  len = 0;
	  result = asn1_read_value (asn1_struct, tmpbuffer3, NULL, &len);

	  value2 = gnutls_malloc (len);
	  if (value2 == NULL)
	    {
	      gnutls_assert ();
	      result = GNUTLS_E_MEMORY_ERROR;
	      goto cleanup;
	    }

	  result = asn1_read_value (asn1_struct, tmpbuffer3, value2, &len);

	  if (result != ASN1_SUCCESS)
	    {
	      gnutls_assert ();
	      result = _gnutls_asn2err (result);
	      goto cleanup;
	    }
#define STR_APPEND(y) if ((result=_gnutls_string_append_str( &out_str, y)) < 0) { \
	gnutls_assert(); \
	goto cleanup; \
}
	  /*   The encodings of adjoining RelativeDistinguishedNames are separated
	   *   by a comma character (',' ASCII 44).
	   */

	  /*   Where there is a multi-valued RDN, the outputs from adjoining
	   *   AttributeTypeAndValues are separated by a plus ('+' ASCII 43)
	   *   character.
	   */
	  if (k1 != 1)
	    {			/* the first time do not append a comma */
	      if (k2 != 1)
		{		/* adjoining multi-value RDN */
		  STR_APPEND ("+");
		}
	      else
		{
		  STR_APPEND (",");
		}
	    }

	  ldap_desc = oid2ldap_string (oid);
	  printable = _gnutls_x509_oid_data_printable (oid);

	  sizeof_escaped = 2 * len + 1;

	  escaped = gnutls_malloc (sizeof_escaped);
	  if (escaped == NULL)
	    {
	      gnutls_assert ();
	      result = GNUTLS_E_MEMORY_ERROR;
	      goto cleanup;
	    }

	  sizeof_string = 2 * len + 2;	/* in case it is not printable */

	  string = gnutls_malloc (sizeof_string);
	  if (string == NULL)
	    {
	      gnutls_assert ();
	      result = GNUTLS_E_MEMORY_ERROR;
	      goto cleanup;
	    }

	  STR_APPEND (ldap_desc);
	  STR_APPEND ("=");
	  if (printable)
	    result =
	      _gnutls_x509_oid_data2string (oid,
					    value2, len,
					    string, &sizeof_string);
	  else
	    result =
	      _gnutls_x509_data2hex (value2, len, string, &sizeof_string);

	  if (result < 0)
	    {
	      gnutls_assert ();
	      _gnutls_x509_log
		("Found OID: '%s' with value '%s'\n",
		 oid, _gnutls_bin2hex (value2, len, escaped, sizeof_escaped));
	      goto cleanup;
	    }
	  STR_APPEND (str_escape (string, escaped, sizeof_escaped));
	  gnutls_free (string);
	  string = NULL;

	  gnutls_free (escaped);
	  escaped = NULL;
	  gnutls_free (value2);
	  value2 = NULL;

	}
      while (1);

    }
  while (1);

  if (out_str.length >= (unsigned int) *sizeof_buf)
    {
      gnutls_assert ();
      *sizeof_buf = out_str.length + 1;
      result = GNUTLS_E_SHORT_MEMORY_BUFFER;
      goto cleanup;
    }

  if (buf)
    {
      memcpy (buf, out_str.data, out_str.length);
      buf[out_str.length] = 0;
    }
  *sizeof_buf = out_str.length;

  result = 0;

cleanup:
  gnutls_free (value2);
  gnutls_free (string);
  gnutls_free (escaped);
  _gnutls_string_clear (&out_str);
  return result;
}
Exemplo n.º 4
0
/* Parses an Attribute list in the asn1_struct, and searches for the
 * given OID. The index indicates the attribute value to be returned.
 *
 * If raw==0 only printable data are returned, or GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE.
 *
 * asn1_attr_name must be a string in the form "certificationRequestInfo.attributes"
 *
 */
static int
parse_attribute (ASN1_TYPE asn1_struct,
                 const char *attr_name, const char *given_oid, int indx,
                 int raw, char *buf, size_t * sizeof_buf)
{
    int k1, result;
    char tmpbuffer1[MAX_NAME_SIZE];
    char tmpbuffer3[MAX_NAME_SIZE];
    char value[200];
    char oid[128];
    int len, printable;

    if (*sizeof_buf == 0)
    {
        gnutls_assert ();
        return GNUTLS_E_INVALID_REQUEST;
    }

    buf[0] = 0;

    k1 = 0;
    do
    {

        k1++;
        /* create a string like "attribute.?1"
         */
        if (attr_name[0] != 0)
            snprintf( tmpbuffer1, sizeof (tmpbuffer1), "%s.?%u", attr_name, k1);
        else
            snprintf( tmpbuffer1, sizeof (tmpbuffer1), "?%u", k1);

        len = sizeof (value) - 1;
        result = asn1_read_value (asn1_struct, tmpbuffer1, value, &len);

        if (result == ASN1_ELEMENT_NOT_FOUND)
        {
            gnutls_assert ();
            break;
        }

        if (result != ASN1_VALUE_NOT_FOUND)
        {
            gnutls_assert ();
            result = _gnutls_asn2err (result);
            goto cleanup;
        }

        /* Move to the attibute type and values
         */
        /* Read the OID
         */
        _gnutls_str_cpy (tmpbuffer3, sizeof (tmpbuffer3), tmpbuffer1);
        _gnutls_str_cat (tmpbuffer3, sizeof (tmpbuffer3), ".type");

        len = sizeof (oid) - 1;
        result = asn1_read_value (asn1_struct, tmpbuffer3, oid, &len);

        if (result == ASN1_ELEMENT_NOT_FOUND)
            break;
        else if (result != ASN1_SUCCESS)
        {
            gnutls_assert ();
            result = _gnutls_asn2err (result);
            goto cleanup;
        }

        if (strcmp (oid, given_oid) == 0)
        {   /* Found the OID */

            /* Read the Value
             */
            snprintf( tmpbuffer3, sizeof (tmpbuffer3), "%s.values.?%u", tmpbuffer1, indx+1);

            len = sizeof (value) - 1;
            result = asn1_read_value (asn1_struct, tmpbuffer3, value, &len);

            if (result != ASN1_SUCCESS)
            {
                gnutls_assert ();
                result = _gnutls_asn2err (result);
                goto cleanup;
            }

            if (raw == 0)
            {
                printable = _gnutls_x509_oid_data_printable (oid);
                if (printable == 1)
                {
                    if ((result =
                                _gnutls_x509_oid_data2string
                                (oid, value, len, buf, sizeof_buf)) < 0)
                    {
                        gnutls_assert ();
                        goto cleanup;
                    }
                    return 0;
                }
                else
                {
                    gnutls_assert ();
                    return GNUTLS_E_X509_UNSUPPORTED_ATTRIBUTE;
                }
            }
            else
            {   /* raw!=0 */
                if (*sizeof_buf > (size_t) len && buf != NULL)
                {
                    *sizeof_buf = len;
                    memcpy (buf, value, len);

                    return 0;
                }
                else
                {
                    *sizeof_buf = len;
                    gnutls_assert ();
                    return GNUTLS_E_SHORT_MEMORY_BUFFER;
                }
            }
        }

    }
    while (1);

    gnutls_assert ();

    result = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;

cleanup:
    return result;
}