Navigation


Changeset 707:e387d5c6b6f5 in freeDiameter


Ignore:
Timestamp:
Feb 9, 2011, 6:08:54 PM (10 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Added support for Internationalized Domain Names (IDNA) using GNU libidn

Files:
3 added
12 edited

Legend:

Unmodified
Added
Removed
  • INSTALL.Fedora

    r643 r707  
    44
    55Dependencies on Fedora 13 (from minimal system):
    6 # yum install cmake make gcc flex bison lksctp-tools-devel gnutls-devel libgcrypt-devel
     6# yum install cmake make gcc flex bison lksctp-tools-devel gnutls-devel libgcrypt-devel libidn-devel
    77
    88In addition, if you have not already retrieved the latest source:
  • INSTALL.FreeBSD

    r696 r707  
    2020
    2121
    22 2) Install cmake
     222) Install 'cmake'
    2323
    2424 a) from sources:
     
    3030       
    3131 
    32 3) Install mercurial (optional)
    33   (replace "cmake" by "mercurial" in the previous command)
     323) Install 'mercurial' (optional)
     33  (replace 'cmake' by 'mercurial' in the previous command)
    3434
    35 4) Install flex and bison, same way.
     354) Install 'flex' and 'bison', same way.
    3636
    37 5) Install gnutls, same way also.
     375) Install 'gnutls' and 'libidn', same way also.
    3838
    39396) Retrieve freeDiameter source code:
  • INSTALL.OpenSUSE

    r643 r707  
    44
    55Dependencies on OpenSUSE 11.3 (from minimal server system installation):
    6 # zypper install cmake make gcc flex bison lksctp-tools-devel libgnutls-devel libgcrypt-devel
     6# zypper install cmake make gcc flex bison lksctp-tools-devel libgnutls-devel libgcrypt-devel libidn-devel
    77# zypper install mercurial
    88
  • INSTALL.Ubuntu

    r660 r707  
    1818
    1919The following packages are required to compile freeDiameter from source:
    20  cmake make gcc flex bison libsctp1 libsctp-dev libgnutls-dev libgcrypt-dev
     20 cmake make gcc flex bison libsctp1 libsctp-dev libgnutls-dev libgcrypt-dev libidn11-dev
     21 
     22(note that libidn and libsctp can be avoided by defining DISABLE_SCTP and DIAMID_IDNA_REJECT)
    2123 
    2224Additionnaly, these ones may be useful:
     
    4345
    4446# Install the dependencies for building the source:
    45 sudo apt-get -y install mercurial cmake make gcc bison flex libsctp-dev libgnutls-dev libgcrypt-dev ssl-cert debhelper fakeroot \
     47sudo apt-get -y install mercurial cmake make gcc bison flex libsctp-dev libgnutls-dev libgcrypt-dev libidn11-dev ssl-cert debhelper fakeroot \
    4648   libpq-dev libmysqlclient-dev libxml2-dev swig python-dev
    4749
     
    8486
    85871) Install all packages dependencies
    86 # sudo apt-get install mercurial cmake make gcc bison flex libsctp-dev libgnutls-dev libgcrypt-dev
     88# sudo apt-get install mercurial cmake make gcc bison flex libsctp-dev libgnutls-dev libgcrypt-dev libidn11-dev
    8789
    88902) (OPTION) If you will compile modules that require postgresql, also install:
  • contrib/OpenWRT/packages/freeDiameter/Makefile

    r698 r707  
    7676                -DCMAKE_PREFIX_PATH:PATH=$(STAGING_DIR)/usr \
    7777                -DCMAKE_INSTALL_PREFIX:PATH=/usr \
     78                -DDIAMID_IDNA_REJECT:BOOL=ON \
    7879                -DBUILD_TESTING:BOOL=OFF \
    7980                -DCMAKE_BUILD_TYPE:STRING=DebianPackage \
  • contrib/debian/control

    r668 r707  
    55Build-Depends: debhelper ( >= 7.3.9),
    66 cmake, make, gcc, bison, flex,
    7  libsctp-dev, libgnutls-dev, libgcrypt-dev,
     7 libsctp-dev, libgnutls-dev, libgcrypt-dev, libidn11-dev,
    88 libpq-dev, libmysqlclient-dev, libxml2-dev, swig, python-dev
    99Standards-Version: 3.8.3
  • contrib/nightly_tests/tests.list

    r352 r707  
    22alldefault
    33nosctp
     4idnaignore
     5idnareject
    46#noext
  • include/freeDiameter/CMakeLists.txt

    r677 r707  
    1919SET(DEFAULT_EXTENSIONS_PATH ${CMAKE_INSTALL_PREFIX}/${INSTALL_EXTENSIONS_SUFFIX})
    2020
     21# IDNA considerations
     22OPTION(DIAMID_IDNA_IGNORE "Ignore completly invalid characters in Diameter Identities (process blindly)?" OFF)
     23IF (NOT DIAMID_IDNA_IGNORE)
     24        OPTION (DIAMID_IDNA_REJECT "Reject internationalized Diameter Identities, do not attempt to convert it (stringprep) ?" OFF)
     25ENDIF (NOT DIAMID_IDNA_IGNORE)
    2126
    22 MARK_AS_ADVANCED(DISABLE_SCTP DEBUG_SCTP SCTP_USE_MAPPED_ADDRESSES ERRORS_ON_TODO)
     27MARK_AS_ADVANCED(DISABLE_SCTP DEBUG_SCTP SCTP_USE_MAPPED_ADDRESSES ERRORS_ON_TODO DIAMID_IDNA_IGNORE DIAMID_IDNA_REJECT)
    2328
    2429########################
     
    109114SET(SCTP_LIBRARIES ${SCTP_LIBRARIES} PARENT_SCOPE)
    110115
     116# IDNA process: we use libidn from GNU (unless the function & header files are included in libc)
     117IF(NOT DIAMID_IDNA_IGNORE  AND NOT DIAMID_IDNA_REJECT)
     118        FIND_PACKAGE(IDNA)
     119        SET(CHECK_IDNA_SOURCE_CODE "
     120                #include <idna.h>
     121                int main() {
     122                   return idna_to_ascii_8z(NULL, NULL, 0);
     123                }
     124                ")
     125        SET(CMAKE_REQUIRED_INCLUDES ${IDNA_INCLUDE_DIR})
     126        SET(CMAKE_REQUIRED_LIBRARIES ${IDNA_LIBRARIES})
     127        CHECK_C_SOURCE_COMPILES("${CHECK_IDNA_SOURCE_CODE}" HAS_IDNA_SUPPORT)
     128        IF(NOT HAS_IDNA_SUPPORT)
     129                MESSAGE(SEND_ERROR "Unable to find idna.h header or idna_to_ascii_8z function, please install libidn-dev or equivalent, or set DIAMID_IDNA_IGNORE or DIAMID_IDNA_REJECT")
     130        ENDIF(NOT HAS_IDNA_SUPPORT)
     131ELSE (NOT DIAMID_IDNA_IGNORE  AND NOT DIAMID_IDNA_REJECT)
     132        MESSAGE(STATUS "Non-default Internationalized Domain Names (IDN) behavior selected (no stringprep).")
     133ENDIF(NOT DIAMID_IDNA_IGNORE  AND NOT DIAMID_IDNA_REJECT)
     134SET(IDNA_INCLUDE_DIR ${IDNA_INCLUDE_DIR} PARENT_SCOPE)
     135SET(IDNA_LIBRARIES ${IDNA_LIBRARIES} PARENT_SCOPE)
     136
    111137
    112138# Require GNU TLS for building the library
     
    135161
    136162# LFDPROTO_LIBS = libraries required by the libfdproto.
    137 SET(LFDPROTO_LIBS ${CLOCK_GETTIME_LIBS} ${CMAKE_THREAD_LIBS_INIT} PARENT_SCOPE)
     163SET(LFDPROTO_LIBS ${CLOCK_GETTIME_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${IDNA_LIBRARIES} PARENT_SCOPE)
     164# And includes paths
     165SET(LFDPROTO_INCLUDES ${IDNA_INCLUDE_DIR} PARENT_SCOPE)
    138166# Dependencies: the libraries required by any code linking to libfdproto.
    139167SET(LFDPROTO_LINK_INTERFACES ${CMAKE_THREAD_LIBS_INIT} PARENT_SCOPE)
  • include/freeDiameter/freeDiameter-host.h.in

    r695 r707  
    4949#cmakedefine SCTP_CONNECTX_4_ARGS
    5050#cmakedefine SKIP_DLCLOSE
     51#cmakedefine DIAMID_IDNA_IGNORE
     52#cmakedefine DIAMID_IDNA_REJECT
    5153
    5254#cmakedefine ERRORS_ON_TODO
  • libfdproto/CMakeLists.txt

    r706 r707  
    2121SET(LFDPROTO_SRC ${LFDPROTO_SRC} PARENT_SCOPE)
    2222
     23# Include path
     24INCLUDE_DIRECTORIES(${LFDPROTO_INCLUDES})
     25
    2326# Build as a shared library
    2427ADD_LIBRARY(libfdproto SHARED ${LFDPROTO_SRC})
  • libfdproto/ostr.c

    r706 r707  
    3636#include "fdproto-internal.h"
    3737
     38#if (!defined(DIAMID_IDNA_IGNORE) && !defined(DIAMID_IDNA_REJECT))
     39/* Process IDNA with stringprep -- See RFC5890 -- and libidn documentation... */
     40#include <idna.h> /* idna_to_ascii_8z() */
     41#endif /* !defined(DIAMID_IDNA_IGNORE) && !defined(DIAMID_IDNA_REJECT) */
     42
    3843/* Similar to strdup with (must be verified) os0_t */
    3944os0_t os0dup_int(os0_t s, size_t l) {
     
    8994int fd_os_is_valid_DiameterIdentity(uint8_t * os, size_t ossz)
    9095{
     96#ifdef DIAMID_IDNA_IGNORE
     97       
     98        /* Allow anything */
     99       
     100#else /* DIAMID_IDNA_IGNORE */
     101       
    91102        int i;
    92103       
    93         /* Allow letters, digits, hyphen, dot */
     104        /* Allow only letters, digits, hyphen, dot */
    94105        for (i=0; i < ossz; i++) {
    95106                if (os[i] > 'z')
     
    106117        }
    107118        if (i < ossz) {
    108                 TRACE_DEBUG(INFO, "Invalid character '%c' in DiameterIdentity '%.*s'", os[i], ossz, os);
     119                int nb = 1;
     120                /* To get a better display, check if the invalid char is UTF-8 */
     121                if ((os[i] & 0xE0) == 0xC0 /* 110xxxxx */) {
     122                        if ((i < ossz - 1) && ((os[i + 1] & 0xC0) == 0x80 /* 10xxxxxx */))
     123                                nb = 2;
     124                        goto disp;
     125                }
     126                if ((os[i] & 0xF0) == 0xE0 /* 1110xxxx */) {
     127                        if ((i < ossz - 2) && ((os[i + 1] & 0xC0) == 0x80 /* 10xxxxxx */)
     128                                           && ((os[i + 2] & 0xC0) == 0x80 /* 10xxxxxx */))
     129                                nb = 3;
     130                        goto disp;
     131                }
     132                if ((os[i] & 0xF8) == 0xF0 /* 11110xxx */) {
     133                        if ((i < ossz - 3) && ((os[i + 1] & 0xC0) == 0x80 /* 10xxxxxx */)
     134                                           && ((os[i + 2] & 0xC0) == 0x80 /* 10xxxxxx */)
     135                                           && ((os[i + 3] & 0xC0) == 0x80 /* 10xxxxxx */))
     136                                nb = 4;
     137                        goto disp;
     138                }
     139                if ((os[i] & 0xFC) == 0xF8 /* 111110xx */) {
     140                        if ((i < ossz - 4) && ((os[i + 1] & 0xC0) == 0x80 /* 10xxxxxx */)
     141                                           && ((os[i + 2] & 0xC0) == 0x80 /* 10xxxxxx */)
     142                                           && ((os[i + 3] & 0xC0) == 0x80 /* 10xxxxxx */)
     143                                           && ((os[i + 4] & 0xC0) == 0x80 /* 10xxxxxx */))
     144                                nb = 5;
     145                        goto disp;
     146                }
     147                if ((os[i] & 0xFE) == 0xFC /* 1111110x */) {
     148                        if ((i < ossz - 5) && ((os[i + 1] & 0xC0) == 0x80 /* 10xxxxxx */)
     149                                           && ((os[i + 2] & 0xC0) == 0x80 /* 10xxxxxx */)
     150                                           && ((os[i + 3] & 0xC0) == 0x80 /* 10xxxxxx */)
     151                                           && ((os[i + 4] & 0xC0) == 0x80 /* 10xxxxxx */)
     152                                           && ((os[i + 5] & 0xC0) == 0x80 /* 10xxxxxx */))
     153                                nb = 6;
     154                        goto disp;
     155                }
     156                /* otherwise, we just display the hex code */
     157                TRACE_DEBUG(INFO, "Invalid character (0xhhX) at offset %d in DiameterIdentity '%.*s'", os[i], i+1, ossz, os);
    109158                return 0;
    110         }
     159disp:
     160                TRACE_DEBUG(INFO, "Invalid character '%.*s' at offset %d in DiameterIdentity '%.*s'", nb, os + i, i+1, ossz, os);
     161                return 0;
     162        }
     163       
     164#endif /* DIAMID_IDNA_IGNORE */
     165       
    111166        return 1;
    112167}
     
    119174        *outsz = strlen(*id);
    120175       
     176#ifndef DIAMID_IDNA_IGNORE
     177       
    121178        if (!fd_os_is_valid_DiameterIdentity((os0_t)*id, *outsz)) {
    122                 char buf[HOST_NAME_MAX];
    123                
    124                 TODO("Stringprep in into buf");
    125                 TRACE_DEBUG(INFO, "The string '%s' is not a valid DiameterIdentity, it was changed to '%s'", *id, buf);
    126                 TODO("Realloc *id if !memory");
    127                 /* copy buf */
    128                 /* update the size */
    129                 return ENOTSUP;
    130         } else {
     179       
     180#ifdef DIAMID_IDNA_REJECT
     181               
     182                TRACE_DEBUG(INFO, "The string '%s' is not a valid DiameterIdentity!", *id);
     183                TRACE_DEBUG(INFO, "Returning EINVAL since fD is compiled with option DIAMID_IDNA_REJECT.");
     184                return EINVAL;
     185       
     186#else /* DIAMID_IDNA_REJECT */
     187       
     188                char *processed;
     189                int ret;
     190               
     191                ret = idna_to_ascii_8z ( *id, &processed, IDNA_USE_STD3_ASCII_RULES );
     192                if (ret == IDNA_SUCCESS) {
     193                        TRACE_DEBUG(INFO, "The string '%s' is not a valid DiameterIdentity, it was changed to '%s'", *id, processed);
     194                        if (memory == 0)
     195                                free(*id);
     196                        *id = processed;
     197                        *outsz = strlen(processed);
     198                        /* Done! */
     199                } else {
     200                        TRACE_DEBUG(INFO, "The string '%s' is not a valid DiameterIdentity and cannot be sanitanized: %s", *id, idna_strerror (ret));
     201                        return EINVAL;
     202                }
     203       
     204#endif /* DIAMID_IDNA_REJECT */
     205        } else
     206#endif /* ! DIAMID_IDNA_IGNORE */
     207        {
    131208                if (memory == 1) {
    132209                        CHECK_MALLOC( *id = os0dup(*id, *outsz) );
     
    135212        return 0;
    136213}
    137 
    138 
    139214
    140215
  • tests/testostr.c

    r706 r707  
    3838#define TEST_STR (os0_t)"This is my test string (with extra unused data)"
    3939
     40/* The following string contains UTF-8 encoded characters (Chinese characters) */
     41#define TEST_IDN_UTF8  "freeDiameter.中国"
     42#define TEST_IDN_CONV  "freeDiameter.xn--fiqs8s"
     43
    4044/* Main test routine */
    4145int main(int argc, char *argv[])
     
    6771                CHECK( hash, fd_os_hash(buf + 1, CONSTSTRLEN(TEST_STR)) );
    6872        }
     73       
     74        /* Check the Diameter Identity functions */
     75        {
     76                char * res;
     77                size_t len;
     78               
     79                /* A valid ASCII domain name */
     80                res = TEST_IDN_CONV;
     81                CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 1) );
     82                CHECK( 0, strcasecmp(res, TEST_IDN_CONV) ); /* the function does not change a valid DN */
     83                CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 0) );
     84                CHECK( 0, strcasecmp(res, TEST_IDN_CONV) );
     85                CHECK( CONSTSTRLEN(TEST_IDN_CONV), len );
     86                free(res);
     87               
     88                /* Now, an invalid string */
     89                res = TEST_IDN_UTF8;
     90               
     91                #ifdef DIAMID_IDNA_IGNORE
     92               
     93                /* The UTF-8 chars are considered valid */
     94                CHECK( 1, fd_os_is_valid_DiameterIdentity((os0_t)TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8) );
     95               
     96                /* The string should be passed unmodified */
     97                CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 1) );
     98                CHECK( 0, strcasecmp(res, TEST_IDN_UTF8) );
     99                CHECK( 0, fd_os_cmp(res, len, TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8)) );
     100                CHECK( 0, fd_os_almostcasecmp(res, len, TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8)) );
     101                CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 0) );
     102                CHECK( 0, strcasecmp(res, TEST_IDN_UTF8) );
     103                CHECK( CONSTSTRLEN(TEST_IDN_UTF8), len );
     104                free(res);
     105               
     106                #else /* DIAMID_IDNA_IGNORE */
     107               
     108                /* The UTF-8 chars are recognized as invalid DiameterIdentity */
     109                CHECK( 0, fd_os_is_valid_DiameterIdentity((os0_t)TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8) ));
     110               
     111                # ifdef DIAMID_IDNA_REJECT
     112               
     113                /* The string must be rejected */
     114                CHECK( EINVAL, fd_os_validate_DiameterIdentity(&res, &len, 1) );
     115               
     116                # else /* DIAMID_IDNA_REJECT */
     117               
     118                /* The string should be transformed into TEST_IDN_CONV */
     119                CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 1) );
     120                CHECK( 0, strcasecmp(res, TEST_IDN_CONV) );
     121                CHECK( CONSTSTRLEN(TEST_IDN_CONV), len );
     122                free(res);
     123               
     124                # endif /* DIAMID_IDNA_REJECT */
     125                #endif /* DIAMID_IDNA_IGNORE */
    69126
     127        }
     128       
    70129        /* That's all for the tests yet */
    71130        PASSTEST();
Note: See TracChangeset for help on using the changeset viewer.