Esempio n. 1
0
File: utf8.c Progetto: Exim/exim
uschar *
string_domain_alabel_to_utf8(const uschar * alabel, uschar ** err)
{
#ifdef SUPPORT_I18N_2008
const uschar * label;
int sep = '.';
gstring * g = NULL;

while (label = string_nextinlist(&alabel, &sep, NULL, 0))
  if (  string_is_alabel(label)
     && !(label = string_localpart_alabel_to_utf8_(label, err))
     )
    return NULL;
  else
    g = string_append_listele(g, '.', label);
return string_from_gstring(g);

#else

uschar * s1, * s;
int rc;

if (  (rc = idna_to_unicode_8z8z(CCS alabel, CSS &s1, IDNA_USE_STD3_ASCII_RULES))
   != IDNA_SUCCESS)
  {
  if (err) *err = US idna_strerror(rc);
  return NULL;
  }
s = string_copy(s1);
free(s1);
return s;
#endif
}
Esempio n. 2
0
File: params.c Progetto: dnstap/knot
char* name_from_idn(const char *idn_name) {
#ifdef LIBIDN
	char *name = NULL;

	int rc = idna_to_ascii_lz(idn_name, &name, 0);
	if (rc != IDNA_SUCCESS) {
		ERR("IDNA (%s)\n", idna_strerror(rc));
		return NULL;
	}

	return name;
#endif
	return strdup(idn_name);
}
Esempio n. 3
0
uschar *
string_domain_alabel_to_utf8(const uschar * alabel, uschar ** err)
{
uschar * s1;
uschar * s;
int rc;

if (  (rc = idna_to_unicode_8z8z(CCS alabel, CSS &s1, IDNA_USE_STD3_ASCII_RULES))
   != IDNA_SUCCESS)
  {
  if (err) *err = US idna_strerror(rc);
  return NULL;
  }
s = string_copy(s1);
free(s1);
return s;
}
Esempio n. 4
0
File: utf8.c Progetto: 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;
}
Esempio n. 5
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;
}
Esempio n. 6
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;
}
Esempio n. 7
0
/**
 * Encode a native string to IDN.  Handle the full string and do not split
 * off a namespace prefix.
 * @param in Input string in native locale encoding.
 * @return IDN encoded output string.
 */
std::string
IdnTool::encodeFull (const std::string& in) const
{
  char* buf = nullptr;

  const Idna_flags flags = static_cast<Idna_flags> (0);
  Idna_rc rc;
  rc = static_cast<Idna_rc> (idna_to_ascii_lz (in.c_str (), &buf, flags));

  if (rc != IDNA_SUCCESS)
    {
      std::free (buf);
      std::ostringstream msg;
      msg << "IDNA encoding failed: " << idna_strerror (rc);
      throw std::runtime_error (msg.str ());
    }
  assert (buf);

  const std::string res(buf);
  std::free (buf);

  return res;
}
Esempio n. 8
0
int
main (void)
{
  char buf[BUFSIZ];
  char *p;
  int rc;
  size_t i;

  setlocale (LC_ALL, "");

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

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

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

  printf ("ACE label (length %ld): '%s'\n", (long int) strlen (p), p);
  for (i = 0; i < strlen (p); i++)
    printf ("%02x ", p[i] & 0xFF);
  printf ("\n");

  free (p);

  return 0;
}
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);
}
Esempio n. 10
0
void
doit (void)
{
  const char *p;

  /* Test success. */

  p = idna_strerror (0);
  if (strcmp (p, SUCCESS) != 0)
    fail ("idna_strerror (0) failed: %s\n", p);
  if (debug)
    printf ("idna_strerror (0) OK\n");

  p = pr29_strerror (0);
  if (strcmp (p, SUCCESS) != 0)
    fail ("pr29_strerror (0) failed: %s\n", p);
  if (debug)
    printf ("pr29_strerror (0) OK\n");

  p = punycode_strerror (0);
  if (strcmp (p, SUCCESS) != 0)
    fail ("punycode_strerror (0) failed: %s\n", p);
  if (debug)
    printf ("punycode_strerror (0) OK\n");

  p = stringprep_strerror (0);
  if (strcmp (p, SUCCESS) != 0)
    fail ("stringprep_strerror (0) failed: %s\n", p);
  if (debug)
    printf ("stringprep_strerror (0) OK\n");

  p = tld_strerror (0);
  if (strcmp (p, SUCCESS) != 0)
    fail ("tld_strerror (0) failed: %s\n", p);
  if (debug)
    printf ("tld_strerror (0) OK\n");

  /* Test unknown error. */

  p = idna_strerror (42);
  if (strcmp (p, UNKNOWN) != 0)
    fail ("idna_strerror (42) failed: %s\n", p);
  if (debug)
    printf ("idna_strerror (42) OK\n");

  p = pr29_strerror (42);
  if (strcmp (p, UNKNOWN) != 0)
    fail ("pr29_strerror (42) failed: %s\n", p);
  if (debug)
    printf ("pr29_strerror (42) OK\n");

  p = punycode_strerror (42);
  if (strcmp (p, UNKNOWN) != 0)
    fail ("punycode_strerror (42) failed: %s\n", p);
  if (debug)
    printf ("punycode_strerror (42) OK\n");

  p = stringprep_strerror (42);
  if (strcmp (p, UNKNOWN) != 0)
    fail ("stringprep_strerror (42) failed: %s\n", p);
  if (debug)
    printf ("stringprep_strerror (42) OK\n");

  p = tld_strerror (42);
  if (strcmp (p, UNKNOWN) != 0)
    fail ("tld_strerror (42) failed: %s\n", p);
  if (debug)
    printf ("tld_strerror (42) OK\n");

  /* Iterate through all error codes. */

  {
    size_t i;
    const char *last_p = NULL;

    for (i = 0;; i++)
      {
	p = idna_strerror (i);
	if (p == last_p)
	  {
	    if (i == 11)
	      {
		i = 200;
		continue;
	      }
	    break;
	  }
	if (debug)
	  printf ("idna %ld: %s\n", i, p);
	last_p = p;
      }
  }

  {
    size_t i;
    const char *last_p = NULL;

    for (i = 0;; i++)
      {
	p = pr29_strerror (i);
	if (p == last_p)
	  break;
	if (debug)
	  printf ("pr29 %ld: %s\n", i, p);
	last_p = p;
      }
  }

  {
    size_t i;
    const char *last_p = NULL;

    for (i = 0;; i++)
      {
	p = punycode_strerror (i);
	if (p == last_p)
	  break;
	if (debug)
	  printf ("punycode %ld: %s\n", i, p);
	last_p = p;
      }
  }

  {
    size_t i;
    const char *last_p = NULL;

    for (i = 0;; i++)
      {
	p = stringprep_strerror (i);
	if (p == last_p)
	  {
	    if (i == 7)
	      {
		i = 99;
		continue;
	      }
	    else if (i == 105)
	      {
		i = 199;
		continue;
	      }
	    break;
	  }
	if (debug)
	  printf ("stringprep %ld: %s\n", i, p);
	last_p = p;
      }
  }

  {
    size_t i;
    const char *last_p = NULL;

    for (i = 0;; i++)
      {
	p = tld_strerror (i);
	if (p == last_p)
	  break;
	if (debug)
	  printf ("tld %ld: %s\n", i, p);
	last_p = p;
      }
  }
}
Esempio n. 11
0
/*
 * Return error-string for libidn status as returned from idna_to_ascii_lz().
 */
const char *Curl_idn_strerror (struct connectdata *conn, int err)
{
#ifdef HAVE_IDNA_STRERROR
  (void)conn;
  return idna_strerror((Idna_rc) err);
#else
  const char *str;
  char *buf;
  size_t max;

  DEBUGASSERT(conn);

  buf = conn->syserr_buf;
  max = sizeof(conn->syserr_buf)-1;
  *buf = '\0';

#ifndef CURL_DISABLE_VERBOSE_STRINGS
  switch ((Idna_rc)err) {
    case IDNA_SUCCESS:
      str = "No error";
      break;
    case IDNA_STRINGPREP_ERROR:
      str = "Error in string preparation";
      break;
    case IDNA_PUNYCODE_ERROR:
      str = "Error in Punycode operation";
      break;
    case IDNA_CONTAINS_NON_LDH:
      str = "Illegal ASCII characters";
      break;
    case IDNA_CONTAINS_MINUS:
      str = "Contains minus";
      break;
    case IDNA_INVALID_LENGTH:
      str = "Invalid output length";
      break;
    case IDNA_NO_ACE_PREFIX:
      str = "No ACE prefix (\"xn--\")";
      break;
    case IDNA_ROUNDTRIP_VERIFY_ERROR:
      str = "Round trip verify error";
      break;
    case IDNA_CONTAINS_ACE_PREFIX:
      str = "Already have ACE prefix (\"xn--\")";
      break;
    case IDNA_ICONV_ERROR:
      str = "Locale conversion failed";
      break;
    case IDNA_MALLOC_ERROR:
      str = "Allocation failed";
      break;
    case IDNA_DLOPEN_ERROR:
      str = "dlopen() error";
      break;
    default:
      snprintf(buf, max, "error %d", err);
      str = NULL;
      break;
  }
#else
  if((Idna_rc)err == IDNA_SUCCESS)
    str = "No error";
  else
    str = "Error";
#endif
  if(str)
    strncpy(buf, str, max);
  buf[max] = '\0';
  return (buf);
#endif
}
Esempio n. 12
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;
}
Esempio n. 13
0
/**
 * Parse name inside of a DNS query or record.
 *
 * @param udp_payload entire UDP payload
 * @param udp_payload_length length of @a udp_payload
 * @param off pointer to the offset of the name to parse in the udp_payload (to be
 *                    incremented by the size of the name)
 * @param depth current depth of our recursion (to prevent stack overflow)
 * @return name as 0-terminated C string on success, NULL if the payload is malformed
 */
static char *
parse_name (const char *udp_payload,
	    size_t udp_payload_length,
	    size_t *off,
	    unsigned int depth)
{
  const uint8_t *input = (const uint8_t *) udp_payload;
  char *ret;
  char *tmp;
  char *xstr;
  uint8_t len;
  size_t xoff;
  char *utf8;
  Idna_rc rc;

  ret = GNUNET_strdup ("");
  while (1)
  {
    if (*off >= udp_payload_length)
    {
      GNUNET_break_op (0);
      goto error;
    }
    len = input[*off];
    if (0 == len)
    {
      (*off)++;
      break;
    }
    if (len < 64)
    {
      if (*off + 1 + len > udp_payload_length)
      {
	GNUNET_break_op (0);
	goto error;
      }
      GNUNET_asprintf (&tmp,
		       "%.*s",
		       (int) len,
		       &udp_payload[*off + 1]);
      if (IDNA_SUCCESS !=
	  (rc = idna_to_unicode_8z8z (tmp, &utf8, IDNA_ALLOW_UNASSIGNED)))
      {
	GNUNET_log (GNUNET_ERROR_TYPE_INFO,
		    _("Failed to convert DNS IDNA name `%s' to UTF-8: %s\n"),
		    tmp,
		    idna_strerror (rc));
	GNUNET_free (tmp);
	GNUNET_asprintf (&tmp,
			 "%s%.*s.",
			 ret,
			 (int) len,
			 &udp_payload[*off + 1]);
      }
      else
      {
	GNUNET_free (tmp);
	GNUNET_asprintf (&tmp,
			 "%s%s.",
			 ret,
			 utf8);
#if WINDOWS
	idn_free (utf8);
#else
	free (utf8);
#endif
      }
      GNUNET_free (ret);
      ret = tmp;
      *off += 1 + len;
    }
    else if ((64 | 128) == (len & (64 | 128)) )
    {
      if (depth > 32)
      {
	GNUNET_break_op (0);
	goto error; /* hard bound on stack to prevent "infinite" recursion, disallow! */
      }
      /* pointer to string */
      if (*off + 1 > udp_payload_length)
      {
	GNUNET_break_op (0);
	goto error;
      }
      xoff = ((len - (64 | 128)) << 8) + input[*off+1];
      xstr = parse_name (udp_payload,
			 udp_payload_length,
			 &xoff,
			 depth + 1);
      if (NULL == xstr)
      {
	GNUNET_break_op (0);
	goto error;
      }
      GNUNET_asprintf (&tmp,
		       "%s%s.",
		       ret,
		       xstr);
      GNUNET_free (ret);
      GNUNET_free (xstr);
      ret = tmp;
      if (strlen (ret) > udp_payload_length)
      {
	GNUNET_break_op (0);
	goto error; /* we are looping (building an infinite string) */
      }
      *off += 2;
      /* pointers always terminate names */
      break;
    }
    else
    {
      /* neither pointer nor inline string, not supported... */
      GNUNET_break_op (0);
      goto error;
    }
  }
  if (0 < strlen(ret))
    ret[strlen(ret)-1] = '\0'; /* eat tailing '.' */
  return ret;
 error:
  GNUNET_break_op (0);
  GNUNET_free (ret);
  return NULL;
}
Esempio n. 14
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;
}
Esempio n. 15
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;
}
Esempio n. 16
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;
}
Esempio n. 17
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;
}
Esempio n. 18
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;
}
Esempio n. 19
0
int
get_addrs (char *my_machine_name, char *his_machine_name)
{
#if HAVE_DECL_GETADDRINFO || defined HAVE_IDN
  int err;
#endif
  char *lhost, *rhost;
#if HAVE_DECL_GETADDRINFO
  struct addrinfo hints, *res, *ai;
#else /* !HAVE_DECL_GETADDRINFO */
  struct hostent *hp;
#endif
  struct servent *sp;

#ifdef HAVE_IDN
  err = idna_to_ascii_lz (my_machine_name, &lhost, 0);
  if (err)
    {
      fprintf (stderr, "talk: %s: %s\n",
	       my_machine_name, idna_strerror (err));
      exit (-1);
    }

  err = idna_to_ascii_lz (his_machine_name, &rhost, 0);
  if (err)
    {
      fprintf (stderr, "talk: %s: %s\n",
	       his_machine_name, idna_strerror (err));
      exit (-1);
    }
#else /* !HAVE_IDN */
  lhost = my_machine_name;
  rhost = his_machine_name;
#endif

  msg.pid = htonl (getpid ());

  /* Look up the address of the local host.  */

#if HAVE_DECL_GETADDRINFO
  memset (&hints, 0, sizeof (hints));

  /* The talk-protocol is IPv4 only!  */
  hints.ai_family = AF_INET;
  hints.ai_socktype = SOCK_DGRAM;
# ifdef AI_IDN
  hints.ai_flags |= AI_IDN;
# endif

  err = getaddrinfo (lhost, NULL, &hints, &res);
  if (err)
    {
      fprintf (stderr, "talk: %s: %s\n", lhost, gai_strerror (err));
      exit (-1);
    }

  /* Perform all sanity checks available.
   * Reduction of tests?
   */
  for (ai = res; ai; ai = ai->ai_next)
    {
      int f;

      if (ai->ai_family != AF_INET)
	continue;

      f = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
      if (f < 0)
	continue;

      /* Attempt binding to this local address.  */
      if (bind (f, ai->ai_addr, ai->ai_addrlen))
        {
	  close (f);
	  f = -1;
	  continue;
	}

      /* We have a usable address.  */
      close (f);
      break;
    }

  if (ai)
    memcpy (&my_machine_addr,
	    &((struct sockaddr_in *) ai->ai_addr)->sin_addr,
	    sizeof (my_machine_addr));

  freeaddrinfo (res);
  if (!ai)
    {
      fprintf (stderr, "talk: %s: %s\n", lhost, "address not found");
      exit (-1);
    }

#else /* !HAVE_DECL_GETADDRINFO */
  hp = gethostbyname (lhost);
  if (hp == NULL)
    {
      fprintf (stderr, "talk: %s(%s): ", lhost, my_machine_name);
      herror ((char *) NULL);
      exit (-1);
    }
  memmove (&my_machine_addr, hp->h_addr, hp->h_length);
#endif /* !HAVE_DECL_GETADDRINFO */

  /*
   * If the callee is on-machine, just copy the
   * network address, otherwise do a lookup...
   */
  if (strcmp (rhost, lhost))
    {
#if HAVE_DECL_GETADDRINFO
      err = getaddrinfo (rhost, NULL, &hints, &res);
      if (err)
	{
	  fprintf (stderr, "talk: %s: %s\n", rhost, gai_strerror (err));
	  exit (-1);
	}

      /* Perform all sanity checks available.  */
      for (ai = res; ai; ai = ai->ai_next)
	{
	  int f;

	  if (ai->ai_family != AF_INET)
	    continue;

	  f = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
	  if (f < 0)
	    continue;

	  /* We have a usable address family!  */
	  close (f);
	  break;
	}

      if (ai)
	memcpy (&his_machine_addr,
		&((struct sockaddr_in *) ai->ai_addr)->sin_addr,
		sizeof (his_machine_addr));

      freeaddrinfo (res);
      if (!ai)
	{
	  fprintf (stderr, "talk: %s: %s\n", rhost, "address not found");
	  exit (-1);
	}

#else /* !HAVE_DECL_GETADDRINFO */
      hp = gethostbyname (rhost);
      if (hp == NULL)
	{
	  fprintf (stderr, "talk: %s(%s): ", rhost, his_machine_name);
	  herror ((char *) NULL);
	  exit (-1);
	}
      memmove (&his_machine_addr, hp->h_addr, hp->h_length);
#endif /* !HAVE_DECL_GETADDRINFO */
    }
  else
    his_machine_addr = my_machine_addr;

  /* Find the server's port.  */
  sp = getservbyname ("ntalk", "udp");
  if (sp == 0)
    {
      fprintf (stderr, "talk: %s/%s: service is not registered.\n",
	       "ntalk", "udp");
      exit (-1);
    }
  daemon_port = ntohs (sp->s_port);

#ifdef HAVE_IDN
  free (lhost);
  free (rhost);
#endif

  return 0;
}