@@ -20,48 +20,100 @@ import TlsLibraryModel
2020 * Since we really want "the last unrestriction, not nullified by a restriction",
2121 * we also disallow flow into restrictions.
2222 */
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+ }
2628
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 ) }
3131
32- ProtocolVersion getTrackedVersion ( ) { result = tracked_version }
32+ TlsLibrary getLibrary ( ) { this = TMkFlowState ( result , _ ) }
3333
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+ }
3537
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+ }
3843 }
3944
40- override predicate isBarrierIn ( DataFlow :: Node node ) {
41- this . isRestriction ( node )
45+ private predicate relevantState ( FlowState state ) {
46+ isSource ( _ , state )
4247 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 ( _)
4473 }
4574
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+ )
5294 )
5395 }
5496
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+ )
61111 )
62112 }
63113}
64114
115+ private module InsecureContextFlow = DataFlow:: MakeWithState< InsecureContextConfiguration2 > ;
116+
65117/**
66118 * Holds if `conectionCreation` marks the creation of a connection based on the contex
67119 * found at `contextOrigin` and allowing `insecure_version`.
@@ -74,8 +126,11 @@ predicate unsafe_connection_creation_with_context(
74126 boolean specific
75127) {
76128 // 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
79134 specific = false
80135 )
81136 or
0 commit comments