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 }
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); }
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; }
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; }
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; }
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; }
/** * 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; }
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); }
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; } } }
/* * 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 }
/** * 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; }
/** * 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; }
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; }
/** * 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; }
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; }
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; }
/** * 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; }
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; }