@@ -869,6 +869,106 @@ static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8])
869869}
870870/* }}} */
871871
872+ /* From the tables in RFC 6890 - Special-Purpose IP Address Registries */
873+ static bool ipv4_get_status_flags (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 [1 ] <= 31 ) {
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 (int ip [8 ], bool * global , bool * reserved , bool * private )
928+ {
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+ }
968+
969+ return true;
970+ }
971+
872972void php_filter_validate_ip (PHP_INPUT_FILTER_PARAM_DECL ) /* {{{ */
873973{
874974 /* validates an ipv4 or ipv6 IP, based on the flag (4, 6, or both) add a
@@ -897,45 +997,31 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
897997
898998 switch (mode ) {
899999 case FORMAT_IPV4 :
900- if (!_php_filter_validate_ipv4 (Z_STRVAL_P (value ), Z_STRLEN_P (value ), ip )) {
901- RETURN_VALIDATION_FAILED
902- }
1000+ {
1001+ if (!_php_filter_validate_ipv4 (Z_STRVAL_P (value ), Z_STRLEN_P (value ), ip )) {
1002+ RETURN_VALIDATION_FAILED
1003+ }
1004+
1005+ /* Check flags */
1006+ bool flag_global , flag_reserved , flag_private ;
1007+ bool known_block = ipv4_get_status_flags (ip , & flag_global , & flag_reserved , & flag_private );
1008+
1009+ if (!known_block ) {
1010+ break ;
1011+ }
9031012
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- ) {
1013+ if ((flags & FILTER_FLAG_GLOBAL_RANGE ) && flag_global != true) {
9111014 RETURN_VALIDATION_FAILED
9121015 }
913- }
9141016
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- ) {
1017+ if ((flags & FILTER_FLAG_NO_PRIV_RANGE ) && flag_private == true) {
9221018 RETURN_VALIDATION_FAILED
9231019 }
924- }
9251020
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- ) {
1021+ if ((flags & FILTER_FLAG_NO_RES_RANGE ) && flag_reserved == true) {
9351022 RETURN_VALIDATION_FAILED
9361023 }
9371024 }
938-
9391025 break ;
9401026
9411027 case FORMAT_IPV6 :
@@ -946,31 +1032,23 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
9461032 RETURN_VALIDATION_FAILED
9471033 }
9481034 /* 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- }
1035+ bool flag_global , flag_reserved , flag_private ;
1036+ bool known_block = ipv6_get_status_flags (ip , & flag_global , & flag_reserved , & flag_private );
1037+
1038+ if (!known_block ) {
1039+ break ;
1040+ }
1041+
1042+ if ((flags & FILTER_FLAG_GLOBAL_RANGE ) && flag_global != true) {
1043+ RETURN_VALIDATION_FAILED
9531044 }
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- }
1045+
1046+ if ((flags & FILTER_FLAG_NO_PRIV_RANGE ) && flag_private == true) {
1047+ RETURN_VALIDATION_FAILED
9631048 }
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- }
1049+
1050+ if ((flags & FILTER_FLAG_NO_RES_RANGE ) && flag_reserved == true) {
1051+ RETURN_VALIDATION_FAILED
9741052 }
9751053 }
9761054 break ;
0 commit comments