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