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