# HG changeset patch # User Sebastien Decugis # Date 1362840213 -3600 # Node ID 6072619402a3a2dc6c5cc8efccaefdd9e08a8cd1 # Parent 977a5375543cf8a22fab448fa0c927fe83b3b80e New CMake option WORKAROUND_ACCEPT_INVALID_VSAI for those invalids Vendor-Specific-Application-Id out there diff -r 977a5375543c -r 6072619402a3 include/freeDiameter/CMakeLists.txt --- a/include/freeDiameter/CMakeLists.txt Thu Mar 07 16:13:50 2013 +0100 +++ b/include/freeDiameter/CMakeLists.txt Sat Mar 09 15:43:33 2013 +0100 @@ -28,8 +28,12 @@ # Note: if someone needs, we could also make the delay configurable here... OPTION(DISABLE_PEER_EXPIRY "Disable RFC3539 Peers Connections Expiration after inactivity?" OFF) +# The following workaround increases compatibility with some implementations without breaking anything in freeDiameter, +# so it can be enabled without risk. We keep it disabled by default anyway for those people who use freeDiameter to check the +# compliancy of their implementation with the Diameter RFC... +OPTION(WORKAROUND_ACCEPT_INVALID_VSAI "Do not reject a CER/CEA with a Vendor-Specific-Application-Id AVP containing both Auth- and Acct- application AVPs?" OFF) -MARK_AS_ADVANCED(DISABLE_SCTP DEBUG_SCTP SCTP_USE_MAPPED_ADDRESSES ERRORS_ON_TODO DIAMID_IDNA_IGNORE DIAMID_IDNA_REJECT DISABLE_PEER_EXPIRY) +MARK_AS_ADVANCED(DISABLE_SCTP DEBUG_SCTP SCTP_USE_MAPPED_ADDRESSES ERRORS_ON_TODO DIAMID_IDNA_IGNORE DIAMID_IDNA_REJECT DISABLE_PEER_EXPIRY WORKAROUND_ACCEPT_INVALID_VSAI) ######################## ### System checks part diff -r 977a5375543c -r 6072619402a3 include/freeDiameter/freeDiameter-host.h.in --- a/include/freeDiameter/freeDiameter-host.h.in Thu Mar 07 16:13:50 2013 +0100 +++ b/include/freeDiameter/freeDiameter-host.h.in Sat Mar 09 15:43:33 2013 +0100 @@ -59,6 +59,7 @@ #cmakedefine DIAMID_IDNA_IGNORE #cmakedefine DIAMID_IDNA_REJECT #cmakedefine DISABLE_PEER_EXPIRY +#cmakedefine WORKAROUND_ACCEPT_INVALID_VSAI #cmakedefine GNUTLS_VERSION_210 #cmakedefine GNUTLS_VERSION_300 #cmakedefine GNUTLS_VERSION_310 diff -r 977a5375543c -r 6072619402a3 libfdcore/p_ce.c --- a/libfdcore/p_ce.c Thu Mar 07 16:13:50 2013 +0100 +++ b/libfdcore/p_ce.c Sat Mar 09 15:43:33 2013 +0100 @@ -454,10 +454,10 @@ case AC_VENDOR_SPECIFIC_APPLICATION_ID: /* Vendor-Specific-Application-Id (grouped)*/ { struct avp * inavp = NULL; - application_id_t aid = 0; vendor_id_t vid = 0; - int auth = 0; - int acct = 0; + application_id_t auth_aid = 0; + application_id_t acct_aid = 0; + int invalid=0; /* get the first child AVP */ CHECK_FCT( fd_msg_browse(avp, MSG_BRW_FIRST_CHILD, &inavp, NULL) ); @@ -481,33 +481,50 @@ } switch (inhdr->avp_code) { case AC_VENDOR_ID: /* Vendor-Id */ + if (vid != 0) + invalid++; /* We already had one such AVP */ vid = inhdr->avp_value->u32; break; case AC_AUTH_APPLICATION_ID: /* Auth-Application-Id */ - aid = inhdr->avp_value->u32; - auth += 1; + if (auth_aid != 0) + invalid++; /* We already had one such AVP */ +#ifndef WORKAROUND_ACCEPT_INVALID_VSAI + if (acct_aid != 0) + invalid++; /* Only 1 *-Application-Id AVP is allowed */ +#endif /* WORKAROUND_ACCEPT_INVALID_VSAI */ + auth_aid = inhdr->avp_value->u32; break; case AC_ACCT_APPLICATION_ID: /* Acct-Application-Id */ - aid = inhdr->avp_value->u32; - acct += 1; + if (acct_aid != 0) + invalid++; /* We already had one such AVP */ +#ifndef WORKAROUND_ACCEPT_INVALID_VSAI + if (auth_aid != 0) + invalid++; /* Only 1 *-Application-Id AVP is allowed */ +#endif /* WORKAROUND_ACCEPT_INVALID_VSAI */ + acct_aid = inhdr->avp_value->u32; break; /* ignore other AVPs */ } + + if (invalid) { + TRACE_DEBUG(FULL, "Invalid Vendor-Specific-Application-Id AVP received, ignored"); + fd_msg_dump_one(FULL, avp); + error->pei_errcode = "DIAMETER_INVALID_AVP_VALUE"; + error->pei_avp = avp; + return EINVAL; + } innext: /* Go to next in AVP */ CHECK_FCT( fd_msg_browse(inavp, MSG_BRW_NEXT, &inavp, NULL) ); } - if (auth + acct != 1) { - TRACE_DEBUG(FULL, "Invalid Vendor-Specific-Application-Id AVP received, ignored"); - fd_msg_dump_one(FULL, avp); - error->pei_errcode = "DIAMETER_INVALID_AVP_VALUE"; - error->pei_avp = avp; - return EINVAL; - } else { - /* Add an entry in the list */ - CHECK_FCT( fd_app_merge(&peer->p_hdr.info.runtime.pir_apps, aid, vid, auth, acct) ); + /* Add entry in the list */ + if (auth_aid) { + CHECK_FCT( fd_app_merge(&peer->p_hdr.info.runtime.pir_apps, auth_aid, vid, 1, 0) ); + } + if (acct_aid) { + CHECK_FCT( fd_app_merge(&peer->p_hdr.info.runtime.pir_apps, acct_aid, vid, 0, 1) ); } } break;