Ejemplo n.º 1
0
bool local_idna( const std::string& domain, std::string& out )
    {
#define JID_PORTION_SIZE 1023

#ifdef HAVE_LIBIDN
      if( domain.empty() || domain.length() > JID_PORTION_SIZE )
        return false;

      char* prepped;
      int rc = idna_to_ascii_8z( domain.c_str(), &prepped, (Idna_flags)IDNA_USE_STD3_ASCII_RULES );
      if( rc == IDNA_SUCCESS )
      {
        out = prepped;
        return true;
      }
      if( rc != IDNA_MALLOC_ERROR )
        free( prepped );
      return false;
#else
      if( domain.length() > JID_PORTION_SIZE )
        return false;
      out = domain;
      return true;
#endif
    }
Ejemplo n.º 2
0
static int mutt_local_to_idna (const char *in, char **out)
{
  int rv = 0;
  char *tmp = safe_strdup (in);
  *out = NULL;

  if (!in)
  {
    *out = NULL;
    return -1;
  }
  
  /* we don't want charset-hook effects, so we set flags to 0 */
  if (mutt_convert_string (&tmp, Charset, "utf-8", 0) == -1)
    rv = -1;
  if (!rv && idna_to_ascii_8z (tmp, out, IDNA_ALLOW_UNASSIGNED) != IDNA_SUCCESS)
    rv = -2;
  
  FREE (&tmp);
  if (rv < 0)
  {
    FREE (out);		/* __FREE_CHECKED__ */
    *out = safe_strdup (in);
  }
  return rv;
}
Ejemplo n.º 3
0
wxString CControlSocket::ConvertDomainName(wxString domain)
{
	const wxWCharBuffer buffer = wxConvCurrent->cWX2WC(domain);

	int len = 0;
	while (buffer.data()[len])
		len++;

	char *utf8 = new char[len * 2 + 2];
	wxMBConvUTF8 conv;
	conv.WC2MB(utf8, buffer, len * 2 + 2);

	char *output;
	if (idna_to_ascii_8z(utf8, &output, IDNA_ALLOW_UNASSIGNED))
	{
		delete [] utf8;
		LogMessage(::Debug_Warning, _T("Could not convert domain name"));
		return domain;
	}
	delete [] utf8;

	wxString result = wxConvCurrent->cMB2WX(output);
	free(output);
	return result;
}
Ejemplo n.º 4
0
/**
 * Check if a label in UTF-8 format can be coded into valid IDNA.
 * This can fail if the ASCII-conversion becomes longer than 253 characters.
 *
 * @param name name to check (UTF-8 string)
 * @return #GNUNET_OK if the label can be converted to IDNA,
 *         #GNUNET_SYSERR if the label is not valid for DNS names
 */
int
GNUNET_DNSPARSER_check_name (const char *name)
{
  char *ldup;
  char *output;
  size_t slen;
  char *tok;

  ldup = GNUNET_strdup (name);
  for (tok = strtok (ldup, "."); NULL != tok; tok = strtok (NULL, "."))
    if (GNUNET_OK !=
	GNUNET_DNSPARSER_check_label (tok))
    {
      GNUNET_free (ldup);
      return GNUNET_SYSERR;
    }
  GNUNET_free (ldup);
  if (IDNA_SUCCESS !=
      idna_to_ascii_8z (name, &output, IDNA_ALLOW_UNASSIGNED))
    return GNUNET_SYSERR;
  slen = strlen (output);
#if WINDOWS
  idn_free (output);
#else
  free (output);
#endif
  return (slen > 253) ? GNUNET_SYSERR : GNUNET_OK;
}
Ejemplo n.º 5
0
wxString CControlSocket::ConvertDomainName(wxString const& domain)
{
#ifdef __WXMSW__
	int len = IdnToAscii(IDN_ALLOW_UNASSIGNED, domain, domain.size() + 1, 0, 0);
	if( !len ) {
		LogMessage(MessageType::Debug_Warning, _T("Could not convert domain name"));
		return domain;
	}

	wchar_t* output = new wchar_t[len];
	int res = IdnToAscii(IDN_ALLOW_UNASSIGNED, domain, domain.size() + 1, output, len);
	if( !res ) {
		LogMessage(MessageType::Debug_Warning, _T("Could not convert domain name"));
		return domain;
	}

	wxString ret(output);
	delete [] output;
	return ret;
#else

	wxScopedCharBuffer const utf8 = domain.utf8_str();

	char *output = 0;
	if (idna_to_ascii_8z(utf8, &output, IDNA_ALLOW_UNASSIGNED)) {
		LogMessage(MessageType::Debug_Warning, _T("Could not convert domain name"));
		return domain;
	}

	wxString result = wxConvCurrent->cMB2WX(output);
	idn_free(output);
	return result;
#endif
}
Ejemplo n.º 6
0
void
doit (void)
{
  int rc;
  char *out = NULL;

  rc = idna_to_ascii_8z("search...", &out, 0);
  if (rc != IDNA_INVALID_LENGTH)
    fail ("unexpected rc %d\n", rc);

  rc = idna_to_ascii_8z("google.com................point", &out, 0);
  if (rc != IDNA_INVALID_LENGTH)
    fail ("unexpected rc %d\n", rc);

  rc = idna_to_ascii_8z("Loading...같같같같같같같]", &out, 0);
  if (rc != IDNA_INVALID_LENGTH)
    fail ("unexpected rc %d\n", rc);
}
Ejemplo n.º 7
0
static int mutt_idna_to_local (const char *in, char **out, int flags)
{
  *out = NULL;

  if (!option (OPTUSEIDN))
    goto notrans;

  if (!in)
    goto notrans;

  /* Is this the right function?  Interesting effects with some bad identifiers! */
  if (idna_to_unicode_8z8z (in, out, IDNA_ALLOW_UNASSIGNED) != IDNA_SUCCESS)
    goto notrans;

  /* we don't want charset-hook effects, so we set flags to 0 */
  if (mutt_convert_string (out, "utf-8", Charset, 0) == -1)
    goto notrans;

  /* 
   * make sure that we can convert back and come out with the same
   * domain name. 
   */
  
  if ((flags & MI_MAY_BE_IRREVERSIBLE) == 0)
  {
    int irrev = 0;
    char *t2 = NULL;
    char *tmp = safe_strdup (*out);

    /* we don't want charset-hook effects, so we set flags to 0 */
    if (mutt_convert_string (&tmp, Charset, "utf-8", 0) == -1)
      irrev = 1;
    if (!irrev && idna_to_ascii_8z (tmp, &t2, IDNA_ALLOW_UNASSIGNED) != IDNA_SUCCESS)
      irrev = 1;
    if (!irrev && ascii_strcasecmp (t2, in))
    {
      dprint (1, (debugfile, "mutt_idna_to_local: Not reversible. in = '%s', t2 = '%s'.\n",
		  in, t2));
      irrev = 1;
    }
    
    FREE (&t2);
    FREE (&tmp);

    if (irrev)
      goto notrans;
  }

  return 0;
  
 notrans:
  FREE (out);		/* __FREE_CHECKED__ */
  *out = safe_strdup (in);
  return 1;
}
Ejemplo n.º 8
0
/**
 * idna_to_ascii_lz:
 * @input: zero terminated input UTF-8 string.
 * @output: pointer to newly allocated output string.
 * @flags: IDNA flags, e.g. IDNA_ALLOW_UNASSIGNED or IDNA_USE_STD3_ASCII_RULES.
 *
 * Convert domain name in the locale's encoding to ASCII string.  The
 * domain name may contain several labels, separated by dots.  The
 * output buffer must be deallocated by the caller.
 *
 * Return value: Returns IDNA_SUCCESS on success, or error code.
 **/
int
idna_to_ascii_lz (const char *input, char **output, int flags)
{
  char *utf8;
  int rc;

  utf8 = stringprep_locale_to_utf8 (input);
  if (!utf8)
    return IDNA_ICONV_ERROR;

  rc = idna_to_ascii_8z (utf8, output, flags);

  free (utf8);

  return rc;
}
Ejemplo n.º 9
0
void
doit (void)
{
  char *badutf8 = strdup ("\x7e\x64\x61\x72\x10\x2f\x2f\xf9\x2b\x71"
			  "\x60\x79\x7b\x2e\x63\x75\x2b\x61\x65\x72"
			  "\x75\x65\x56\x66\x7f\x62\xc5\x76\xe5\x00");
  char *s = NULL;
  int rc;

  rc = idna_to_ascii_8z (badutf8, &s, 0);
  free (badutf8);
  if (rc != IDNA_ICONV_ERROR)
    fail ("rc %d\n", rc);

  idn_free (s);
}
Ejemplo n.º 10
0
char *
getdns_convert_ulabel_to_alabel(const char *ulabel)
{
#ifdef HAVE_LIBIDN
    int ret;
    char *buf;
    char *prepped;
    char *prepped2;

    if (ulabel == NULL)
	return 0;
    prepped2 = malloc(BUFSIZ);
    if(!prepped2)
	    return 0;
    setlocale(LC_ALL, "");
    if ((prepped = stringprep_locale_to_utf8(ulabel)) == 0) {
	/* convert to utf8 fails, which it can, but continue anyway */
	if(strlen(ulabel)+1 > BUFSIZ) {
	    free(prepped2);
	    return 0;
	}
	memcpy(prepped2, ulabel, strlen(ulabel)+1);
    } else {
	if(strlen(prepped)+1 > BUFSIZ) {
	    free(prepped);
	    free(prepped2);
	    return 0;
	}
	memcpy(prepped2, prepped, strlen(prepped)+1);
	free(prepped);
    }
    if ((ret = stringprep(prepped2, BUFSIZ, 0, stringprep_nameprep)) != STRINGPREP_OK) {
	free(prepped2);
	return 0;
    }
    if ((ret = idna_to_ascii_8z(prepped2, &buf, 0)) != IDNA_SUCCESS)  {
	free(prepped2);
	return 0;
    }
    free(prepped2);
    return buf;
#else
    return NULL;
#endif
}
Ejemplo n.º 11
0
Archivo: utf8.c Proyecto: Exim/exim
uschar *
string_domain_utf8_to_alabel(const uschar * utf8, uschar ** err)
{
uschar * s1, * s;
int rc;

#ifdef SUPPORT_I18N_2008
/* Avoid lowercasing plain-ascii domains */
if (!string_is_utf8(utf8))
  return string_copy(utf8);

/* Only lowercase is accepted by the library call.  A pity since we lose
any mixed-case annotation.  This does not really matter for a domain. */
  {
  uschar c;
  for (s1 = s = US utf8; (c = *s1); s1++) if (!(c & 0x80) && isupper(c))
    {
    s = string_copy(utf8);
    for (s1 = s + (s1 - utf8); (c = *s1); s1++) if (!(c & 0x80) && isupper(c))
      *s1 = tolower(c);
    break;
    }
  }
if ((rc = idn2_lookup_u8((const uint8_t *) s, &s1, IDN2_NFC_INPUT)) != IDN2_OK)
  {
  if (err) *err = US idn2_strerror(rc);
  return NULL;
  }
#else
s = US stringprep_utf8_nfkc_normalize(CCS utf8, -1);
if (  (rc = idna_to_ascii_8z(CCS s, CSS &s1, IDNA_ALLOW_UNASSIGNED))
   != IDNA_SUCCESS)
  {
  free(s);
  if (err) *err = US idna_strerror(rc);
  return NULL;
  }
free(s);
#endif
s = string_copy(s1);
free(s1);
return s;
}
Ejemplo n.º 12
0
/**
 * Check if a label in UTF-8 format can be coded into valid IDNA.
 * This can fail if the ASCII-conversion becomes longer than 63 characters.
 *
 * @param label label to check (UTF-8 string)
 * @return #GNUNET_OK if the label can be converted to IDNA,
 *         #GNUNET_SYSERR if the label is not valid for DNS names
 */
int
GNUNET_DNSPARSER_check_label (const char *label)
{
  char *output;
  size_t slen;

  if (NULL != strchr (label, '.'))
    return GNUNET_SYSERR; /* not a label! Did you mean GNUNET_DNSPARSER_check_name? */
  if (IDNA_SUCCESS !=
      idna_to_ascii_8z (label, &output, IDNA_ALLOW_UNASSIGNED))
    return GNUNET_SYSERR;
  slen = strlen (output);
#if WINDOWS
  idn_free (output);
#else
  free (output);
#endif
  return (slen > 63) ? GNUNET_SYSERR : GNUNET_OK;
}
Ejemplo n.º 13
0
static ssize_t xlat_idna(void *instance, UNUSED REQUEST *request, char const *fmt, char *out, size_t freespace)
{
	rlm_idn_t *inst = instance;
	char *idna = NULL;
	int res;
	size_t len;
        int flags = 0;

        if (inst->use_std3_ascii_rules) {
        	flags |= IDNA_USE_STD3_ASCII_RULES;
        }
        if (inst->allow_unassigned) {
        	flags |= IDNA_ALLOW_UNASSIGNED;
	}
	
        res = idna_to_ascii_8z(fmt, &idna, flags);
	if (res) {
		if (idna) { 
			free (idna); /* Docs unclear, be safe. */
		}

		REDEBUG("%s", idna_strerror(res));
		return -1;
	}

        len = strlen(idna);

	/* 253 is max DNS length */
        if (!((len < (freespace - 1)) && (len <= 253))) {
	        /* Never provide a truncated result, as it may be queried. */
		REDEBUG("Conversion was truncated");
		
		free(idna);
		return -1;

	}

	strlcpy(out, idna, freespace);
	free(idna);
	
	return len;
}
Ejemplo n.º 14
0
uschar *
string_domain_utf8_to_alabel(const uschar * utf8, uschar ** err)
{
uschar * s1;
uschar * s;
int rc;

s = US stringprep_utf8_nfkc_normalize(CCS utf8, -1);
if (  (rc = idna_to_ascii_8z(CCS s, CSS &s1, IDNA_ALLOW_UNASSIGNED))
   != IDNA_SUCCESS)
  {
  free(s);
  if (err) *err = US idna_strerror(rc);
  return NULL;
  }
free(s);
s = string_copy(s1);
free(s1);
return s;
}
Ejemplo n.º 15
0
Archivo: psl.c Proyecto: jcajka/libpsl
static void _add_punycode_if_needed(_psl_vector_t *v, _psl_entry_t *e)
{
	char *lookupname = NULL;
	int rc;

	if (_str_is_ascii(e->label_buf))
		return;

	/* idna_to_ascii_8z() automatically converts UTF-8 to lowercase */

	if ((rc = idna_to_ascii_8z(e->label_buf, &lookupname, IDNA_USE_STD3_ASCII_RULES)) == IDNA_SUCCESS) {
		if (strcmp(e->label_buf, lookupname)) {
			_psl_entry_t suffix, *suffixp;

			/* fprintf(stderr, "libidn '%s' -> '%s'\n", e->label_buf, lookupname); */
			_suffix_init(&suffix, lookupname, strlen(lookupname));
			suffix.wildcard = e->wildcard;
			suffixp = _vector_get(v, _vector_add(v, &suffix));
			suffixp->label = suffixp->label_buf; /* set label to changed address */
		} /* else ignore */
	} /* else
		fprintf(_(stderr, "toASCII failed (%d): %s\n"), rc, idna_strerror(rc)); */
}
Ejemplo n.º 16
0
static char *udomainace2(const char *c)
{
	const char *d;
	char *ud;
	char *s;

	d=strchr(c, '@');

	if (!d)
		return courier_strdup(c);

	++d;
	if (idna_to_ascii_8z(d, &s, 0) != IDNA_SUCCESS)
	{
		return courier_strdup(c);
	}

	ud=courier_malloc((d-c+1)+strlen(s));

	memcpy(ud, c, d-c);
	strcpy(ud+(d-c), s);
	free(s);
	return ud;
}
Ejemplo n.º 17
0
/**
 * gnutls_server_name_get:
 * @session: is a #gnutls_session_t type.
 * @data: will hold the data
 * @data_length: will hold the data length. Must hold the maximum size of data.
 * @type: will hold the server name indicator type
 * @indx: is the index of the server_name
 *
 * This function will allow you to get the name indication (if any), a
 * client has sent.  The name indication may be any of the enumeration
 * gnutls_server_name_type_t.
 *
 * If @type is GNUTLS_NAME_DNS, then this function is to be used by
 * servers that support virtual hosting, and the data will be a null
 * terminated IDNA ACE string (prior to GnuTLS 3.4.0 it was a UTF-8 string).
 *
 * If @data has not enough size to hold the server name
 * GNUTLS_E_SHORT_MEMORY_BUFFER is returned, and @data_length will
 * hold the required size.
 *
 * @index is used to retrieve more than one server names (if sent by
 * the client).  The first server name has an index of 0, the second 1
 * and so on.  If no name with the given index exists
 * GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE is returned.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int
gnutls_server_name_get(gnutls_session_t session, void *data,
		       size_t * data_length,
		       unsigned int *type, unsigned int indx)
{
	char *_data = data;
	server_name_ext_st *priv;
	int ret;
#ifdef HAVE_LIBIDN
	int rc;
	char *idn_name = NULL;
#endif
	extension_priv_data_t epriv;
	gnutls_datum name;

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SERVER_NAME,
					 &epriv);
	if (ret < 0) {
		gnutls_assert();
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	priv = epriv;

	if (indx + 1 > priv->server_names_size) {
		return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
	}

	*type = priv->server_names[indx].type;

#ifdef HAVE_LIBIDN
	rc = idna_to_ascii_8z ((char*)priv->server_names[indx].name, &idn_name, IDNA_ALLOW_UNASSIGNED);
	if (rc != IDNA_SUCCESS) {
		 _gnutls_debug_log("unable to convert name %s to IDNA format: %s\n", (char*)priv->server_names[indx].name, idna_strerror(rc));
		 return GNUTLS_E_IDNA_ERROR;
	}
	name.data = (unsigned char*)idn_name;
	name.size = strlen(idn_name);
#else
	name.data = priv->server_names[indx].name;
	name.size = priv->server_names[indx].name_length;
#endif

	if (*data_length >	/* greater since we need one extra byte for the null */
	    name.size) {
		*data_length = name.size;
		memcpy(data, name.data, *data_length);

		if (*type == GNUTLS_NAME_DNS)	/* null terminate */
			_data[(*data_length)] = 0;

	} else {
		*data_length = name.size + 1;
		ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
		goto cleanup;
	}

	ret = 0;
 cleanup:
#ifdef HAVE_LIBIDN
	idn_free(idn_name);
#endif
	return ret;
}
Ejemplo n.º 18
0
/**
 * Add a DNS name to the UDP packet at the given location, converting
 * the name to IDNA notation as necessary.
 *
 * @param dst where to write the name (UDP packet)
 * @param dst_len number of bytes in @a dst
 * @param off pointer to offset where to write the name (increment by bytes used)
 *            must not be changed if there is an error
 * @param name name to write
 * @return #GNUNET_SYSERR if @a name is invalid
 *         #GNUNET_NO if @a name did not fit
 *         #GNUNET_OK if @a name was added to @a dst
 */
int
GNUNET_DNSPARSER_builder_add_name (char *dst,
				   size_t dst_len,
				   size_t *off,
				   const char *name)
{
  const char *dot;
  const char *idna_name;
  char *idna_start;
  size_t start;
  size_t pos;
  size_t len;
  Idna_rc rc;

  if (NULL == name)
    return GNUNET_SYSERR;

  if (IDNA_SUCCESS !=
      (rc = idna_to_ascii_8z (name, &idna_start, IDNA_ALLOW_UNASSIGNED)))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
		_("Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n"),
		name,
		idna_strerror (rc));
    return GNUNET_NO;
  }
  idna_name = idna_start;
  start = *off;
  if (start + strlen (idna_name) + 2 > dst_len)
    goto fail;
  pos = start;
  do
  {
    dot = strchr (idna_name, '.');
    if (NULL == dot)
      len = strlen (idna_name);
    else
      len = dot - idna_name;
    if ( (len >= 64) || (0 == len) )
    {
      GNUNET_break (0);
      goto fail; /* segment too long or empty */
    }
    dst[pos++] = (char) (uint8_t) len;
    GNUNET_memcpy (&dst[pos], idna_name, len);
    pos += len;
    idna_name += len + 1; /* also skip dot */
  }
  while (NULL != dot);
  dst[pos++] = '\0'; /* terminator */
  *off = pos;
#if WINDOWS
  idn_free (idna_start);
#else
  free (idna_start);
#endif
  return GNUNET_OK;
 fail:
#if WINDOWS
  idn_free (idna_start);
#else
  free (idna_start);
#endif
  return GNUNET_NO;
}
Ejemplo n.º 19
0
int
main (int argc, char *argv[])
{
  char buf[BUFSIZ];
  char *p;
  uint32_t *r;
  int rc;
  size_t errpos, i;

  printf ("Input domain encoded as `%s': ", stringprep_locale_charset ());
  fflush (stdout);
  fgets (buf, BUFSIZ, stdin);
  buf[strlen (buf) - 1] = '\0';

  printf ("Read string (length %d): ", strlen (buf));
  for (i = 0; i < strlen (buf); i++)
    printf ("%02x ", buf[i] & 0xFF);
  printf ("\n");

  p = stringprep_locale_to_utf8 (buf);
  if (p)
    {
      strcpy (buf, p);
      free (p);
    }
  else
    printf ("Could not convert string to UTF-8, continuing anyway...\n");

  rc = idna_to_ascii_8z (buf, &p, 0);
  if (rc != IDNA_SUCCESS)
    {
      printf ("idna_to_ascii_8z failed (%d): %s\n", rc, idna_strerror (rc));
      return 2;
    }

  printf ("ToASCII string (length %d): %s\n", strlen (p), p);

  rc = idna_to_unicode_8z4z (p, &r, 0);
  free (p);
  if (rc != IDNA_SUCCESS)
    {
      printf ("idna_to_unicode_8z4z failed (%d): %s\n",
	      rc, idna_strerror (rc));
      return 2;
    }

  printf ("ToUnicode string: ");
  for (i = 0; r[i]; i++)
    printf ("U+%04x ", r[i]);
  printf ("\n");

  rc = tld_check_4z (r, &errpos, NULL);
  free (r);
  if (rc == TLD_INVALID)
    {
      printf ("Domain rejected by TLD check, Unicode position %d\n", errpos);
      return 1;
    }
  else if (rc != TLD_SUCCESS)
    {
      printf ("tld_check_4z() failed (%d): %s\n", rc, tld_strerror (rc));
      return 2;
    }

  printf ("Domain accepted by TLD check\n");

  return 0;
}
Ejemplo n.º 20
0
MGET_IRI *mget_iri_parse(const char *s_uri, const char *encoding)
{
	MGET_IRI *iri;
	const char *default_port = NULL;
	char *p, *s, *authority, c;
	size_t slen, it;

	if (!s_uri)
		return NULL;

	/*
		URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
		hier-part   = "//" authority path-abempty / path-absolute / path-rootless / path-empty
		scheme      =  ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
	 */
	while (isspace(*s_uri)) s_uri++;
	if (!*s_uri) return NULL;

	// just use one block of memory for all parsed URI parts
	slen = strlen(s_uri);
	iri = xmalloc(sizeof(MGET_IRI) + slen * 2 + 2);
	memset(iri, 0, sizeof(MGET_IRI));
	strcpy(((char *)iri) + sizeof(MGET_IRI), s_uri);
	iri->uri = ((char *)iri) + sizeof(MGET_IRI);
	s = ((char *)iri) + sizeof(MGET_IRI) + slen + 1;
	strcpy(s, s_uri);

	p = s;
	while (*s && !_iri_isgendelim(*s))
		s++;

	if (*s == ':' && s[1]=='/') {
		// found a scheme
		*s++ = 0;

		// find the scheme in our static list of supported schemes
		// for later comparisons we compare pointers (avoiding strcasecmnp())
		iri->scheme = p;
		for (it = 0; iri_schemes[it]; it++) {
			if (!strcasecmp(iri_schemes[it], p)) {
				iri->scheme = iri_schemes[it];
				default_port = iri_ports[it];
				break;
			}
		}

		if (iri->scheme == p) {
			// convert scheme to lowercase
			for (; *p; p++)
				if (isupper(*p))
					*p = tolower(*p);
		}

	} else {
		iri->scheme = IRI_SCHEME_DEFAULT;
		default_port = iri_ports[0]; // port 80
		s = p; // rewind
	}

	// this is true for http, https, ftp, file
	if (s[0] == '/' && s[1] == '/')
		s += 2;

	// authority
	authority = s;
	while (*s && *s != '/' && *s != '?' && *s != '#')
		s++;
	c = *s;
	if (c) *s++ = 0;

	// left over: [path][?query][#fragment]
	if (c == '/') {
		iri->path = s;
		while (*s && *s != '?' && *s != '#')
			s++;
		c = *s;
		if (c) *s++ = 0;
	}

	if (c == '?') {
		iri->query = s;
		while (*s && *s != '#')
			s++;
		c = *s;
		if (c) *s++ = 0;
	}

	if (c == '#') {
		iri->fragment = s;
		while (*s)
			s++;
	}

	if (*s) {
		debug_printf("unparsed rest '%s'\n", s);
	}

	if (*authority) {
		s = authority;
		p = strchr(authority, '@');
		if (p) {
			iri->userinfo = s;
			*p = 0;
			s = p + 1;
		}
		if (*s == '[') {
			p = strrchr(s, ']');
			if (p) {
				iri->host = s + 1;
				*p = 0;
				s = p + 1;
			} else {
				// something is broken
				iri->host = s + 1;
				while (*s) s++;
			}
		} else {
			iri->host = s;
			while (*s && *s != ':')
				s++;
		}
		if (*s == ':') {
			if (s[1]) {
				if (!default_port || (strcmp(s + 1, default_port) && atoi(s + 1) != atoi(default_port)))
					iri->port = s + 1;
			}
		}
		*s = 0;
/*
		for (p = (char *)iri->host; *p; p++)
			if (*p >= 'A' && *p <= 'Z') // isupper() also returns true for chars > 0x7f, the test is not EBCDIC compatible ;-)
				*p = tolower(*p);
*/
 	}

	iri->resolv_port = iri->port ? iri->port : default_port;

	// now unescape all components (not interested in display, userinfo, password
	if (iri->host) {
		const char *host_utf;
		char *p;

		_unescape((unsigned char *)iri->host);

		host_utf = mget_str_to_utf8(iri->host, encoding);

		if (host_utf) {
			char *host_asc = NULL;
			int rc;

			if ((rc = idna_to_ascii_8z(host_utf, &host_asc, IDNA_USE_STD3_ASCII_RULES)) == IDNA_SUCCESS) {
				// log_printf("toASCII '%s' -> '%s'\n", host_utf, host_asc);
				iri->host = host_asc;
				iri->host_allocated = 1;
			} else
				error_printf(_("toASCII failed (%d): %s\n"), rc, idna_strerror(rc));

			xfree(host_utf);
		}

		for (p = (char *)iri->host; *p; p++)
			if (*p >= 'A' && *p <= 'Z') // isupper() also returns true for chars > 0x7f, the test is not EBCDIC compatible ;-)
				*p = tolower(*p);
	}
	else {
		if (iri->scheme == IRI_SCHEME_HTTP || iri->scheme == IRI_SCHEME_HTTPS) {
			error_printf(_("Missing host/domain in URI '%s'\n"), iri->uri);
			mget_iri_free(&iri);
			return NULL;
		}
	}
	if (iri->path)
		_unescape((unsigned char *)iri->path);
	if (iri->query)
		_unescape((unsigned char *)iri->query);
	if (iri->fragment)
		_unescape((unsigned char *)iri->fragment);

//	info_printf("%s: path '%s'\n", iri->uri, iri->path);

	return iri;
}
Ejemplo n.º 21
0
void
doit (void)
{
  size_t i;
  char *out;
  int rc;

  for (i = 0; i < sizeof (idna) / sizeof (idna[0]); i++)
    {
      if (debug)
	printf ("IDNA2 entry %ld\n", i);

      if (debug)
	{
	  uint32_t *p;
	  size_t len;
	  printf ("in: %s\n", idna[i].in);
	  hexprint (idna[i].in, strlen (idna[i].in));
	  escapeprint (idna[i].in, strlen (idna[i].in));
	  p = stringprep_utf8_to_ucs4 (idna[i].in, -1, &len);
	  ucs4print (p, len);
	  free (p);
	}

      rc = idna_to_ascii_8z (idna[i].in, &out,
			     IDNA_ALLOW_UNASSIGNED |
			     IDNA_USE_STD3_ASCII_RULES);
      if (rc != IDNA_SUCCESS && strlen (idna[i].out) > 0)
	{
	  fail ("IDNA2 entry %ld failed: %d\n", i, rc);
	  continue;
	}

      if (debug && rc == IDNA_SUCCESS)
	{
	  printf ("computed out: %s\n", out);
	  printf ("expected out: %s\n", idna[i].out);
	}
      else if (debug)
	printf ("returned %d\n", rc);

      if (rc == IDNA_SUCCESS)
	{
	  if (strlen (idna[i].out) != strlen (out) ||
	      strcasecmp (idna[i].out, out) != 0)
	    {
	      fail ("IDNA2 entry %ld failed\n", i);
	      if (debug)
		printf ("ERROR\n");
	    }
	  else if (debug)
	    printf ("OK\n");

	  free (out);
	  out = NULL;
	}
      else if (rc != IDNA_SUCCESS && strlen (idna[i].out) == 0 && debug)
	printf ("OK (fail)\n");
      else if (debug)
	printf ("OK\n");
    }
}
static int niquery_option_subject_name_handler(int index, const char *arg)
{
	static char nigroup_buf[INET6_ADDRSTRLEN + 1 + IFNAMSIZ];
	unsigned char *dnptrs[2], **dpp, **lastdnptr;
	int n;
	int i;
	char *name, *p;
	char *canonname = NULL, *idn = NULL;
	unsigned char *buf = NULL;
	size_t namelen;
	size_t buflen;
	int dots, fqdn = niquery_options[index].data;
	MD5_CTX ctxt;
	__u8 digest[MD5_DIGEST_LENGTH];
#ifdef USE_IDN
	int rc;
#endif

	if (niquery_set_subject_type(NI_SUBJ_NAME) < 0)
		return -1;

#ifdef USE_IDN
	name = stringprep_locale_to_utf8(arg);
	if (!name) {
		fprintf(stderr, "ping6: IDN support failed.\n");
		exit(2);
	}
#else
	name = strdup(arg);
	if (!name)
		goto oomexit;
#endif

	p = strchr(name, SCOPE_DELIMITER);
	if (p) {
		*p = '\0';
		if (strlen(p + 1) >= IFNAMSIZ) {
			fprintf(stderr, "ping6: too long scope name.\n");
			exit(1);
		}
	}

#ifdef USE_IDN
	rc = idna_to_ascii_8z(name, &idn, 0);
	if (rc) {
		fprintf(stderr, "ping6: IDN encoding error: %s\n",
			idna_strerror(rc));
		exit(2);
	}
#else
	idn = strdup(name);
	if (!idn)
		goto oomexit;
#endif

	namelen = strlen(idn);
	canonname = malloc(namelen + 1);
	if (!canonname)
		goto oomexit;

	dots = 0;
	for (i = 0; i < namelen + 1; i++) {
		canonname[i] = isupper(idn[i]) ? tolower(idn[i]) : idn[i];
		if (idn[i] == '.')
			dots++;
	}

	if (fqdn == 0) {
		/* guess if hostname is FQDN */
		fqdn = dots ? 1 : -1;
	}

	buflen = namelen + 3 + 1;	/* dn_comp() requrires strlen() + 3,
					   plus non-fqdn indicator. */
	buf = malloc(buflen);
	if (!buf) {
		fprintf(stderr, "ping6: out of memory.\n");
		goto errexit;
	}

	dpp = dnptrs;
	lastdnptr = &dnptrs[ARRAY_SIZE(dnptrs)];

	*dpp++ = (unsigned char *)buf;
	*dpp++ = NULL;

	n = dn_comp(canonname, (unsigned char *)buf, buflen, dnptrs, lastdnptr);
	if (n < 0) {
		fprintf(stderr, "ping6: Inappropriate subject name: %s\n", canonname);
		goto errexit;
	} else if (n >= buflen) {
		fprintf(stderr, "ping6: dn_comp() returned too long result.\n");
		goto errexit;
	}

	MD5_Init(&ctxt);
	MD5_Update(&ctxt, buf, buf[0]);
	MD5_Final(digest, &ctxt);

	sprintf(nigroup_buf, "ff02::2:%02x%02x:%02x%02x%s%s",
		digest[0], digest[1], digest[2], digest[3],
		p ? "%" : "",
		p ? p + 1 : "");

	if (fqdn < 0)
		buf[n] = 0;

	free(ni_subject);

	ni_group = nigroup_buf;
	ni_subject = buf;
	ni_subject_len = n + (fqdn < 0);
	ni_group = nigroup_buf;

	free(canonname);
	free(idn);
	free(name);

	return 0;
oomexit:
	fprintf(stderr, "ping6: out of memory.\n");
errexit:
	free(buf);
	free(canonname);
	free(idn);
	free(name);
	exit(1);
}
Ejemplo n.º 23
0
/**
 * gnutls_server_name_set:
 * @session: is a #gnutls_session_t type.
 * @type: specifies the indicator type
 * @name: is a string that contains the server name.
 * @name_length: holds the length of name
 *
 * This function is to be used by clients that want to inform (via a
 * TLS extension mechanism) the server of the name they connected to.
 * This should be used by clients that connect to servers that do
 * virtual hosting.
 *
 * The value of @name depends on the @type type.  In case of
 * %GNUTLS_NAME_DNS, a UTF-8 null-terminated domain name string,
 * without the trailing dot, is expected.
 *
 * IPv4 or IPv6 addresses are not permitted.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
 *   otherwise a negative error code is returned.
 **/
int
gnutls_server_name_set(gnutls_session_t session,
		       gnutls_server_name_type_t type,
		       const void *name, size_t name_length)
{
	int server_names, ret;
	server_name_ext_st *priv;
	extension_priv_data_t epriv;
	char *idn_name = NULL;
	int set = 0, rc;

	if (session->security_parameters.entity == GNUTLS_SERVER) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	if (name_length == 0) { /* unset extension */
		_gnutls_ext_unset_session_data(session, GNUTLS_EXTENSION_SERVER_NAME);
		return 0;
	}

#ifdef HAVE_LIBIDN
	rc = idna_to_ascii_8z (name, &idn_name, IDNA_ALLOW_UNASSIGNED);
	if (rc != IDNA_SUCCESS) {
		 _gnutls_debug_log("unable to convert name %s to IDNA format: %s\n", (char*)name, idna_strerror(rc));
		 return GNUTLS_E_IDNA_ERROR;
	}
	name = idn_name;
	name_length = strlen(idn_name);
#endif

	if (name_length > MAX_SERVER_NAME_SIZE) {
		ret = GNUTLS_E_SHORT_MEMORY_BUFFER;
		goto cleanup;
	}

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_SERVER_NAME,
					 &epriv);
	if (ret < 0) {
		set = 1;
	}

	if (set != 0) {
		priv = gnutls_calloc(1, sizeof(*priv));
		if (priv == NULL) {
			gnutls_assert();
			return GNUTLS_E_MEMORY_ERROR;
		}
		epriv = priv;
	} else
		priv = epriv;

	server_names = priv->server_names_size + 1;

	if (server_names > MAX_SERVER_NAME_EXTENSIONS)
		server_names = MAX_SERVER_NAME_EXTENSIONS;

	priv->server_names[server_names - 1].type = type;
	memcpy(priv->server_names[server_names - 1].name, name,
	       name_length);
	priv->server_names[server_names - 1].name_length = name_length;

	priv->server_names_size = server_names;

	if (set != 0)
		_gnutls_ext_set_session_data(session,
					     GNUTLS_EXTENSION_SERVER_NAME,
					     epriv);

	ret = 0;
 cleanup:
#ifdef HAVE_LIBIDN
	idn_free(idn_name);
#endif
	return ret;
}
Ejemplo n.º 24
0
const char *wget_str_to_ascii(const char *src)
{
#ifdef WITH_LIBIDN2
	if (wget_str_needs_encoding(src)) {
		char *asc = NULL;
		int rc;
#ifdef WITH_LIBUNISTRING
		uint8_t *lower, resbuf[256];
		size_t len = sizeof(resbuf) - 1; // leave space for additional \0 byte

		// we need a conversion to lowercase
		lower = u8_tolower((uint8_t *)src, u8_strlen((uint8_t *)src), 0, UNINORM_NFKC, resbuf, &len);
		if (!lower) {
			error_printf("u8_tolower(%s) failed (%d)\n", src, errno);
			return src;
		}

		// u8_tolower() does not terminate the result string
		if (lower == resbuf) {
			lower[len]=0;
		} else {
			uint8_t *tmp = lower;
			lower = (uint8_t *)wget_strmemdup((char *)lower, len);
			xfree(tmp);
		}

		if ((rc = idn2_lookup_u8(lower, (uint8_t **)&asc, 0)) == IDN2_OK) {
			debug_printf("idn2 '%s' -> '%s'\n", src, asc);
			src = asc;
		} else
			error_printf(_("toASCII(%s) failed (%d): %s\n"), lower, rc, idn2_strerror(rc));

		if (lower != resbuf)
			xfree(lower);
#else
		if ((rc = idn2_lookup_u8((uint8_t *)src, (uint8_t **)&asc, 0)) == IDN2_OK) {
			debug_printf("idn2 '%s' -> '%s'\n", src, asc);
			src = asc;
		} else
			error_printf(_("toASCII(%s) failed (%d): %s\n"), src, rc, idn2_strerror(rc));
#endif
	}
#elif WITH_LIBIDN
	if (wget_str_needs_encoding(src)) {
		char *asc = NULL;
		int rc;

		if (_utf8_is_valid(src)) {
			// idna_to_ascii_8z() automatically converts UTF-8 to lowercase

			if ((rc = idna_to_ascii_8z(src, &asc, IDNA_USE_STD3_ASCII_RULES)) == IDNA_SUCCESS) {
				// debug_printf("toASCII '%s' -> '%s'\n", src, asc);
				src = asc;
			} else
				error_printf(_("toASCII failed (%d): %s\n"), rc, idna_strerror(rc));
		}
		else
			error_printf(_("Invalid UTF-8 sequence not converted: '%s'\n"), src);
	}
#else
	if (wget_str_needs_encoding(src)) {
		error_printf(_("toASCII not available: '%s'\n"), src);
	}
#endif

	return src;
}
Ejemplo n.º 25
0
static JabberID*
jabber_idn_validate(const char *str, const char *at, const char *slash,
                    const char *null)
{
	const char *node = NULL;
	const char *domain = NULL;
	const char *resource = NULL;
	int node_len = 0;
	int domain_len = 0;
	int resource_len = 0;
	char *out;
	JabberID *jid;

	/* Ensure no parts are > 1023 bytes */
	if (at) {
		node = str;
		node_len = at - str;

		domain = at + 1;
		if (slash) {
			domain_len = slash - (at + 1);
			resource = slash + 1;
			resource_len = null - (slash + 1);
		} else {
			domain_len = null - (at + 1);
		}
	} else {
		domain = str;

		if (slash) {
			domain_len = slash - str;
			resource = slash;
			resource_len = null - (slash + 1);
		} else {
			domain_len = null - (str + 1);
		}
	}

	if (node && node_len > 1023)
		return NULL;
	if (domain_len > 1023)
		return NULL;
	if (resource && resource_len > 1023)
		return NULL;

	jid = g_new0(JabberID, 1);

	if (node) {
		strncpy(idn_buffer, node, node_len);
		idn_buffer[node_len] = '\0';

		if (!jabber_nodeprep(idn_buffer, sizeof(idn_buffer))) {
			jabber_id_free(jid);
			jid = NULL;
			goto out;
		}

		jid->node = g_strdup(idn_buffer);
	}

	/* domain *must* be here */
	strncpy(idn_buffer, domain, domain_len);
	idn_buffer[domain_len] = '\0';
	if (domain[0] == '[') { /* IPv6 address */
		gboolean valid = FALSE;

		if (idn_buffer[domain_len - 1] == ']') {
			idn_buffer[domain_len - 1] = '\0';
			valid = purple_ipv6_address_is_valid(idn_buffer + 1);
		}

		if (!valid) {
			jabber_id_free(jid);
			jid = NULL;
			goto out;
		}
	} else {
		/* Apply nameprep */
		if (stringprep_nameprep(idn_buffer, sizeof(idn_buffer)) != STRINGPREP_OK) {
			jabber_id_free(jid);
			jid = NULL;
			goto out;
		}

		/* And now ToASCII */
		if (idna_to_ascii_8z(idn_buffer, &out, IDNA_USE_STD3_ASCII_RULES) != IDNA_SUCCESS) {
			jabber_id_free(jid);
			jid = NULL;
			goto out;
		}

		/* This *MUST* be freed using 'free', not 'g_free' */
		free(out);
		jid->domain = g_strdup(idn_buffer);
	}

	if (resource) {
		strncpy(idn_buffer, resource, resource_len);
		idn_buffer[resource_len] = '\0';

		if (!jabber_resourceprep(idn_buffer, sizeof(idn_buffer))) {
			jabber_id_free(jid);
			jid = NULL;
			goto out;
		} else
			jid->resource = g_strdup(idn_buffer);
	}

out:
	return jid;
}