@@ -869,15 +869,115 @@ static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8])
869
869
}
870
870
/* }}} */
871
871
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 )
873
928
{
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
+ }
878
968
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 */
881
981
882
982
if (memchr (Z_STRVAL_P (value ), ':' , Z_STRLEN_P (value ))) {
883
983
mode = FORMAT_IPV6 ;
@@ -895,85 +995,35 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
895
995
RETURN_VALIDATION_FAILED
896
996
}
897
997
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
+ }
903
1002
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
+ }
914
1011
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
+ }
925
1016
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
+ }
938
1020
939
- break ;
1021
+ if ((flags & FILTER_FLAG_NO_PRIV_RANGE ) && flag_private == true) {
1022
+ RETURN_VALIDATION_FAILED
1023
+ }
940
1024
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
977
1027
}
978
1028
}
979
1029
/* }}} */
0 commit comments