@@ -20,48 +20,100 @@ import TlsLibraryModel
20
20
* Since we really want "the last unrestriction, not nullified by a restriction",
21
21
* we also disallow flow into restrictions.
22
22
*/
23
- class InsecureContextConfiguration extends DataFlow:: Configuration {
24
- TlsLibrary library ;
25
- ProtocolVersion tracked_version ;
23
+ module InsecureContextConfiguration2 implements DataFlow:: StateConfigSig {
24
+ private newtype TFlowState =
25
+ TMkFlowState ( TlsLibrary library , int bits ) {
26
+ bits in [ 0 .. max ( any ( ProtocolVersion v ) .getBit ( ) ) * 2 - 1 ]
27
+ }
26
28
27
- InsecureContextConfiguration ( ) {
28
- this = library + "Allows" + tracked_version and
29
- tracked_version .isInsecure ( )
30
- }
29
+ class FlowState extends TFlowState {
30
+ int getBits ( ) { this = TMkFlowState ( _, result ) }
31
31
32
- ProtocolVersion getTrackedVersion ( ) { result = tracked_version }
32
+ TlsLibrary getLibrary ( ) { this = TMkFlowState ( result , _ ) }
33
33
34
- override predicate isSource ( DataFlow:: Node source ) { this .isUnrestriction ( source ) }
34
+ predicate allowsInsecureVersion ( ProtocolVersion v ) {
35
+ v .isInsecure ( ) and this .getBits ( ) .bitAnd ( v .getBit ( ) ) != 0
36
+ }
35
37
36
- override predicate isSink ( DataFlow:: Node sink ) {
37
- sink = library .connection_creation ( ) .getContext ( )
38
+ string toString ( ) {
39
+ result =
40
+ "FlowState(" + this .getLibrary ( ) .toString ( ) + ", " +
41
+ concat ( ProtocolVersion v | this .allowsInsecureVersion ( v ) | v , ", " ) + ")"
42
+ }
38
43
}
39
44
40
- override predicate isBarrierIn ( DataFlow :: Node node ) {
41
- this . isRestriction ( node )
45
+ private predicate relevantState ( FlowState state ) {
46
+ isSource ( _ , state )
42
47
or
43
- this .isUnrestriction ( node )
48
+ exists ( FlowState state0 | relevantState ( state0 ) |
49
+ exists ( ProtocolRestriction r |
50
+ r = state0 .getLibrary ( ) .protocol_restriction ( ) and
51
+ state .getBits ( ) = state0 .getBits ( ) .bitAnd ( sum ( r .getRestriction ( ) .getBit ( ) ) .bitNot ( ) ) and
52
+ state0 .getLibrary ( ) = state .getLibrary ( )
53
+ )
54
+ or
55
+ exists ( ProtocolUnrestriction pu |
56
+ pu = state0 .getLibrary ( ) .protocol_unrestriction ( ) and
57
+ state .getBits ( ) = state0 .getBits ( ) .bitOr ( sum ( pu .getUnrestriction ( ) .getBit ( ) ) ) and
58
+ state0 .getLibrary ( ) = state .getLibrary ( )
59
+ )
60
+ )
61
+ }
62
+
63
+ predicate isSource ( DataFlow:: Node source , FlowState state ) {
64
+ exists ( ProtocolFamily family |
65
+ source = state .getLibrary ( ) .unspecific_context_creation ( family ) and
66
+ state .getBits ( ) = family .getBits ( )
67
+ )
68
+ }
69
+
70
+ predicate isSink ( DataFlow:: Node sink , FlowState state ) {
71
+ sink = state .getLibrary ( ) .connection_creation ( ) .getContext ( ) and
72
+ state .allowsInsecureVersion ( _)
44
73
}
45
74
46
- private predicate isRestriction ( DataFlow:: Node node ) {
47
- exists ( ProtocolRestriction r |
48
- r = library .protocol_restriction ( ) and
49
- r .getRestriction ( ) = tracked_version
50
- |
51
- node = r .getContext ( )
75
+ predicate isAdditionalFlowStep (
76
+ DataFlow:: Node node1 , FlowState state1 , DataFlow:: Node node2 , FlowState state2
77
+ ) {
78
+ DataFlow:: localFlowStep ( node1 , node2 ) and
79
+ relevantState ( state1 ) and
80
+ (
81
+ exists ( ProtocolRestriction r |
82
+ r = state1 .getLibrary ( ) .protocol_restriction ( ) and
83
+ node2 = r .getContext ( ) and
84
+ state2 .getBits ( ) = state1 .getBits ( ) .bitAnd ( sum ( r .getRestriction ( ) .getBit ( ) ) .bitNot ( ) ) and
85
+ state1 .getLibrary ( ) = state2 .getLibrary ( )
86
+ )
87
+ or
88
+ exists ( ProtocolUnrestriction pu |
89
+ pu = state1 .getLibrary ( ) .protocol_unrestriction ( ) and
90
+ node2 = pu .getContext ( ) and
91
+ state2 .getBits ( ) = state1 .getBits ( ) .bitOr ( sum ( pu .getUnrestriction ( ) .getBit ( ) ) ) and
92
+ state1 .getLibrary ( ) = state2 .getLibrary ( )
93
+ )
52
94
)
53
95
}
54
96
55
- private predicate isUnrestriction ( DataFlow:: Node node ) {
56
- exists ( ProtocolUnrestriction pu |
57
- pu = library .protocol_unrestriction ( ) and
58
- pu .getUnrestriction ( ) = tracked_version
59
- |
60
- node = pu .getContext ( )
97
+ predicate isBarrier ( DataFlow:: Node node , FlowState state ) {
98
+ relevantState ( state ) and
99
+ (
100
+ exists ( ProtocolRestriction r |
101
+ r = state .getLibrary ( ) .protocol_restriction ( ) and
102
+ node = r .getContext ( ) and
103
+ state .allowsInsecureVersion ( r .getRestriction ( ) )
104
+ )
105
+ or
106
+ exists ( ProtocolUnrestriction pu |
107
+ pu = state .getLibrary ( ) .protocol_unrestriction ( ) and
108
+ node = pu .getContext ( ) and
109
+ not state .allowsInsecureVersion ( pu .getUnrestriction ( ) )
110
+ )
61
111
)
62
112
}
63
113
}
64
114
115
+ private module InsecureContextFlow = DataFlow:: MakeWithState< InsecureContextConfiguration2 > ;
116
+
65
117
/**
66
118
* Holds if `conectionCreation` marks the creation of a connection based on the contex
67
119
* found at `contextOrigin` and allowing `insecure_version`.
@@ -74,8 +126,11 @@ predicate unsafe_connection_creation_with_context(
74
126
boolean specific
75
127
) {
76
128
// Connection created from a context allowing `insecure_version`.
77
- exists ( InsecureContextConfiguration c | c .hasFlow ( contextOrigin , connectionCreation ) |
78
- insecure_version = c .getTrackedVersion ( ) and
129
+ exists ( InsecureContextFlow:: PathNode src , InsecureContextFlow:: PathNode sink |
130
+ InsecureContextFlow:: hasFlowPath ( src , sink ) and
131
+ src .getNode ( ) = contextOrigin and
132
+ sink .getNode ( ) = connectionCreation and
133
+ sink .getState ( ) .allowsInsecureVersion ( insecure_version ) and
79
134
specific = false
80
135
)
81
136
or
0 commit comments