@@ -869,15 +869,115 @@ static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8])
869869}
870870/* }}} */
871871
872- void php_filter_validate_ip (PHP_INPUT_FILTER_PARAM_DECL ) /* {{{ */
872+ /* From the tables in RFC 6890 - Special-Purpose IP Address Registries */
873+ static bool ipv4_get_status_flags (const int ip [8 ], bool * global , bool * reserved , bool * private )
874+ {
875+ * global = false;
876+ * reserved = false;
877+ * private = false;
878+
879+ if (ip [0 ] == 0 ) {
880+ /* RFC 1122 - This host on this network */
881+ * reserved = true;
882+ } else if (ip [0 ] == 10 ) {
883+ /* RFC 1918 - Private Use */
884+ * private = true;
885+ } else if (ip [0 ] == 100 && ip [1 ] >= 64 && ip [1 ] <= 127 ) {
886+ /* RFC 6598 - Shared Address Space */
887+ } else if (ip [0 ] == 127 ) {
888+ /* RFC 1122 - Loopback */
889+ * reserved = true;
890+ } else if (ip [0 ] == 169 && ip [1 ] == 254 ) {
891+ /* RFC 3927 - Link Local */
892+ * reserved = true;
893+ } else if (ip [0 ] == 172 && ip [1 ] >= 16 && ip [1 ] <= 31 ) {
894+ /* RFC 1918 - Private Use */
895+ * private = true;
896+ } else if (ip [0 ] == 192 && ip [1 ] == 0 && ip [2 ] == 0 ) {
897+ /* RFC 6890 - IETF Protocol Assignments */
898+ } else if (ip [0 ] == 192 && ip [1 ] == 0 && ip [2 ] == 0 && ip [3 ] >= 0 && ip [3 ] <= 7 ) {
899+ /* RFC 6333 - DS-Lite */
900+ } else if (ip [0 ] == 192 && ip [1 ] == 0 && ip [2 ] == 2 ) {
901+ /* RFC 5737 - Documentation */
902+ } else if (ip [0 ] == 192 && ip [1 ] == 88 && ip [2 ] == 99 ) {
903+ /* RFC 3068 - 6to4 Relay Anycast */
904+ * global = true;
905+ } else if (ip [0 ] == 192 && ip [1 ] == 168 ) {
906+ /* RFC 1918 - Private Use */
907+ * private = true;
908+ } else if (ip [0 ] == 198 && ip [1 ] >= 18 && ip [1 ] <= 19 ) {
909+ /* RFC 2544 - Benchmarking */
910+ } else if (ip [0 ] == 198 && ip [1 ] == 51 && ip [2 ] == 100 ) {
911+ /* RFC 5737 - Documentation */
912+ } else if (ip [0 ] == 203 && ip [1 ] == 0 && ip [2 ] == 113 ) {
913+ /* RFC 5737 - Documentation */
914+ } else if (ip [0 ] >= 240 && ip [1 ] <= 255 ) {
915+ /* RFC 1122 - Reserved */
916+ * reserved = true;
917+ } else if (ip [0 ] == 255 && ip [1 ] == 255 && ip [2 ] == 255 && ip [3 ] == 255 ) {
918+ /* RFC 0919 - Limited Broadcast */
919+ } else {
920+ return false;
921+ }
922+
923+ return true;
924+ }
925+
926+ /* From the tables in RFC 6890 - Special-Purpose IP Address Registries */
927+ static bool ipv6_get_status_flags (const int ip [8 ], bool * global , bool * reserved , bool * private )
873928{
874- /* validates an ipv4 or ipv6 IP, based on the flag (4, 6, or both) add a
875- * flag to throw out reserved ranges; multicast ranges... etc. If both
876- * allow_ipv4 and allow_ipv6 flags flag are used, then the first dot or
877- * colon determine the format */
929+ * global = false;
930+ * reserved = false;
931+ * private = false;
932+
933+ if (ip [0 ] == 0 && ip [1 ] == 0 && ip [2 ] == 0 && ip [3 ] == 0 && ip [4 ] == 0 && ip [5 ] == 0 && ip [6 ] == 0 && ip [7 ] == 0 ) {
934+ /* RFC 4291 - Unspecified Address */
935+ * reserved = true;
936+ } else if (ip [0 ] == 0 && ip [1 ] == 0 && ip [2 ] == 0 && ip [3 ] == 0 && ip [4 ] == 0 && ip [5 ] == 0 && ip [6 ] == 0 && ip [7 ] == 1 ) {
937+ /* RFC 4291 - Loopback Address */
938+ * reserved = true;
939+ } else if (ip [0 ] == 0x0064 && ip [1 ] == 0xff9b ) {
940+ /* RFC 6052 - IPv4-IPv6 Translation */
941+ * global = true;
942+ } else if (ip [0 ] == 0 && ip [1 ] == 0 && ip [2 ] == 0 && ip [3 ] == 0 && ip [4 ] == 0 && ip [5 ] == 0xffff ) {
943+ /* RFC 4291 - IPv4-mapped Address */
944+ * reserved = true;
945+ } else if (ip [0 ] == 0x0100 && ip [1 ] == 0 && ip [2 ] == 0 && ip [3 ] == 0 ) {
946+ /* RFC 6666 - Discard-Only Address Block */
947+ } else if (ip [0 ] == 0x2001 && ip [1 ] == 0x0000 ) {
948+ /* RFC 4380 - TEREDO */
949+ } else if (ip [0 ] == 0x2001 && ip [1 ] <= 0x01ff ) {
950+ /* RFC 2928 - IETF Protocol Assignments */
951+ } else if (ip [0 ] == 0x2001 && ip [1 ] == 0x0002 && ip [2 ] == 0 ) {
952+ /* RFC 5180 - Benchmarking */
953+ } else if (ip [0 ] == 0x2001 && ip [1 ] == 0x0db8 ) {
954+ /* RFC 3849 - Documentation */
955+ } else if (ip [0 ] == 0x2001 && ip [1 ] >= 0x0010 && ip [1 ] <= 0x001f ) {
956+ /* RFC 4843 - ORCHID */
957+ } else if (ip [0 ] == 0x2002 ) {
958+ /* RFC 3056 - 6to4 */
959+ } else if (ip [0 ] >= 0xfc00 && ip [0 ] <= 0xfdff ) {
960+ /* RFC 4193 - Unique-Local */
961+ * private = true;
962+ } else if (ip [0 ] >= 0xfe80 && ip [0 ] <= 0xfebf ) {
963+ /* RFC 4291 - Linked-Scoped Unicast */
964+ * reserved = true;
965+ } else {
966+ return false;
967+ }
878968
879- int ip [8 ];
880- int mode ;
969+ return true;
970+ }
971+
972+ /* Validates an ipv4 or ipv6 IP, based on the flag (4, 6, or both) add a flag
973+ * to throw out reserved ranges; multicast ranges... etc. If both allow_ipv4
974+ * and allow_ipv6 flags flag are used, then the first dot or colon determine
975+ * the format */
976+ void php_filter_validate_ip (PHP_INPUT_FILTER_PARAM_DECL ) /* {{{ */
977+ {
978+ int ip [8 ];
979+ int mode ;
980+ bool flag_global , flag_reserved , flag_private ; /* flags for ranges as determined by RFC 6890 */
881981
882982 if (memchr (Z_STRVAL_P (value ), ':' , Z_STRLEN_P (value ))) {
883983 mode = FORMAT_IPV6 ;
@@ -895,85 +995,35 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
895995 RETURN_VALIDATION_FAILED
896996 }
897997
898- switch (mode ) {
899- case FORMAT_IPV4 :
900- if (!_php_filter_validate_ipv4 (Z_STRVAL_P (value ), Z_STRLEN_P (value ), ip )) {
901- RETURN_VALIDATION_FAILED
902- }
998+ if (mode == FORMAT_IPV4 ) {
999+ if (!_php_filter_validate_ipv4 (Z_STRVAL_P (value ), Z_STRLEN_P (value ), ip )) {
1000+ RETURN_VALIDATION_FAILED
1001+ }
9031002
904- /* Check flags */
905- if (flags & FILTER_FLAG_NO_PRIV_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE ) {
906- if (
907- (ip [0 ] == 10 ) ||
908- (ip [0 ] == 172 && ip [1 ] >= 16 && ip [1 ] <= 31 ) ||
909- (ip [0 ] == 192 && ip [1 ] == 168 )
910- ) {
911- RETURN_VALIDATION_FAILED
912- }
913- }
1003+ if (!ipv4_get_status_flags (ip , & flag_global , & flag_reserved , & flag_private )) {
1004+ return ; /* no special block */
1005+ }
1006+ }
1007+ else if (mode == FORMAT_IPV6 ) {
1008+ if (_php_filter_validate_ipv6 (Z_STRVAL_P (value ), Z_STRLEN_P (value ), ip ) < 1 ) {
1009+ RETURN_VALIDATION_FAILED
1010+ }
9141011
915- if (flags & FILTER_FLAG_NO_RES_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE ) {
916- if (
917- (ip [0 ] == 0 ) ||
918- (ip [0 ] >= 240 ) ||
919- (ip [0 ] == 127 ) ||
920- (ip [0 ] == 169 && ip [1 ] == 254 )
921- ) {
922- RETURN_VALIDATION_FAILED
923- }
924- }
1012+ if (!ipv6_get_status_flags (ip , & flag_global , & flag_reserved , & flag_private )) {
1013+ return ; /* no special block */
1014+ }
1015+ }
9251016
926- if (flags & FILTER_FLAG_GLOBAL_RANGE ) {
927- if (
928- (ip [0 ] == 100 && ip [1 ] >= 64 && ip [1 ] <= 127 ) ||
929- (ip [0 ] == 192 && ip [1 ] == 0 && ip [2 ] == 0 ) ||
930- (ip [0 ] == 192 && ip [1 ] == 0 && ip [2 ] == 2 ) ||
931- (ip [0 ] == 198 && ip [1 ] >= 18 && ip [1 ] <= 19 ) ||
932- (ip [0 ] == 198 && ip [1 ] == 51 && ip [2 ] == 100 ) ||
933- (ip [0 ] == 203 && ip [1 ] == 0 && ip [2 ] == 113 )
934- ) {
935- RETURN_VALIDATION_FAILED
936- }
937- }
1017+ if ((flags & FILTER_FLAG_GLOBAL_RANGE ) && flag_global != true) {
1018+ RETURN_VALIDATION_FAILED
1019+ }
9381020
939- break ;
1021+ if ((flags & FILTER_FLAG_NO_PRIV_RANGE ) && flag_private == true) {
1022+ RETURN_VALIDATION_FAILED
1023+ }
9401024
941- case FORMAT_IPV6 :
942- {
943- int res = 0 ;
944- res = _php_filter_validate_ipv6 (Z_STRVAL_P (value ), Z_STRLEN_P (value ), ip );
945- if (res < 1 ) {
946- RETURN_VALIDATION_FAILED
947- }
948- /* Check flags */
949- if (flags & FILTER_FLAG_NO_PRIV_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE ) {
950- if (ip [0 ] >= 0xfc00 && ip [0 ] <= 0xfdff ) {
951- RETURN_VALIDATION_FAILED
952- }
953- }
954- if (flags & FILTER_FLAG_NO_RES_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE ) {
955- if (
956- (ip [0 ] == 0 && ip [1 ] == 0 && ip [2 ] == 0 && ip [3 ] == 0 && ip [4 ] == 0 && ip [5 ] == 0 && ip [6 ] == 0 && (ip [7 ] == 0 || ip [7 ] == 1 )) ||
957- (ip [0 ] >= 0xfe80 && ip [0 ] <= 0xfebf ) ||
958- (ip [0 ] == 0x2001 && (ip [1 ] == 0x0db8 || (ip [1 ] >= 0x0010 && ip [1 ] <= 0x001f )))
959-
960- ) {
961- RETURN_VALIDATION_FAILED
962- }
963- }
964- if (flags & FILTER_FLAG_GLOBAL_RANGE ) {
965- if (
966- (ip [0 ] == 0 && ip [1 ] == 0 && ip [2 ] == 0 && ip [3 ] == 0 && ip [4 ] == 0 && ip [5 ] == 0xffff ) ||
967- (ip [0 ] == 0x0100 && ip [1 ] == 0 && ip [2 ] == 0 && ip [3 ] == 0 ) ||
968- (ip [0 ] == 0x2001 && ip [1 ] <= 0x01ff ) ||
969- (ip [0 ] == 0x2001 && ip [1 ] == 0x0002 && ip [2 ] == 0 ) ||
970- (ip [0 ] >= 0xfc00 && ip [0 ] <= 0xfdff )
971- ) {
972- RETURN_VALIDATION_FAILED
973- }
974- }
975- }
976- break ;
1025+ if ((flags & FILTER_FLAG_NO_RES_RANGE ) && flag_reserved == true) {
1026+ RETURN_VALIDATION_FAILED
9771027 }
9781028}
9791029/* }}} */
0 commit comments