15
15
16
16
namespace System . Net . Security . Tests ;
17
17
18
+ [ PlatformSpecific ( TestPlatforms . Linux ) ]
18
19
public class SslStreamCertificateContextOcspLinuxTests
19
20
{
20
21
[ Fact ]
@@ -101,7 +102,8 @@ await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity
101
102
intermediate . RevocationExpiration = DateTimeOffset . UtcNow . Add ( SslStreamCertificateContext . MinRefreshBeforeExpirationInterval ) ;
102
103
103
104
SslStreamCertificateContext ctx = ctxFactory ( false ) ;
104
- byte [ ] ocsp = await ctx . GetOcspResponseAsync ( ) ;
105
+ byte [ ] ocsp = await ctx . WaitForPendingOcspFetchAsync ( ) ;
106
+
105
107
Assert . NotNull ( ocsp ) ;
106
108
107
109
intermediate . RevocationExpiration = DateTimeOffset . UtcNow . AddDays ( 1 ) ;
@@ -111,12 +113,10 @@ await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity
111
113
byte [ ] ocsp2 = ctx . GetOcspResponseNoWaiting ( ) ;
112
114
Assert . Equal ( ocsp , ocsp2 ) ;
113
115
114
- await RetryHelper . ExecuteAsync ( async ( ) =>
115
- {
116
- byte [ ] ocsp3 = await ctx . GetOcspResponseAsync ( ) ;
117
- Assert . NotNull ( ocsp3 ) ;
118
- Assert . NotEqual ( ocsp , ocsp3 ) ;
119
- } , maxAttempts : 5 , backoffFunc : i => ( i + 1 ) * 200 /* ms */ ) ;
116
+ // The download should succeed
117
+ byte [ ] ocsp3 = await ctx . WaitForPendingOcspFetchAsync ( ) ;
118
+ Assert . NotNull ( ocsp3 ) ;
119
+ Assert . NotEqual ( ocsp , ocsp3 ) ;
120
120
} ) ;
121
121
}
122
122
@@ -128,7 +128,10 @@ await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity
128
128
intermediate . RevocationExpiration = DateTimeOffset . UtcNow . AddSeconds ( 1 ) ;
129
129
130
130
SslStreamCertificateContext ctx = ctxFactory ( false ) ;
131
+ // Make sure the inner OCSP fetch finished
132
+ await ctx . WaitForPendingOcspFetchAsync ( ) ;
131
133
134
+ // wait until the cached OCSP response expires
132
135
await Task . Delay ( 2000 ) ;
133
136
134
137
intermediate . RevocationExpiration = DateTimeOffset . UtcNow . AddDays ( 1 ) ;
@@ -137,8 +140,8 @@ await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity
137
140
byte [ ] ocsp = ctx . GetOcspResponseNoWaiting ( ) ;
138
141
Assert . Null ( ocsp ) ;
139
142
140
- // subsequent call will return the new response
141
- byte [ ] ocsp2 = await ctx . GetOcspResponseAsync ( ) ;
143
+ // The download should succeed
144
+ byte [ ] ocsp2 = await ctx . WaitForPendingOcspFetchAsync ( ) ;
142
145
Assert . NotNull ( ocsp2 ) ;
143
146
} ) ;
144
147
}
@@ -155,25 +158,34 @@ await SimpleTest(PkiOptions.OcspEverywhere, async (root, intermediate, endEntity
155
158
intermediate . RevocationExpiration = DateTimeOffset . UtcNow . Add ( SslStreamCertificateContext . MinRefreshBeforeExpirationInterval ) ;
156
159
157
160
SslStreamCertificateContext ctx = ctxFactory ( false ) ;
158
- byte [ ] ocsp = await ctx . GetOcspResponseAsync ( ) ;
161
+ // Make sure the inner OCSP fetch finished
162
+ byte [ ] ocsp = await ctx . WaitForPendingOcspFetchAsync ( ) ;
159
163
Assert . NotNull ( ocsp ) ;
160
164
161
165
responder . RespondKind = RespondKind . Invalid ;
162
- for ( int i = 0 ; i < 3 ; i ++ )
166
+ for ( int i = 0 ; i < 2 ; i ++ )
163
167
{
164
- await Task . Delay ( SslStreamCertificateContext . RefreshAfterFailureBackOffInterval ) ;
165
168
byte [ ] ocsp2 = await ctx . GetOcspResponseAsync ( ) ;
169
+ await ctx . WaitForPendingOcspFetchAsync ( ) ;
166
170
Assert . Equal ( ocsp , ocsp2 ) ;
171
+ await Task . Delay ( SslStreamCertificateContext . RefreshAfterFailureBackOffInterval . Add ( TimeSpan . FromSeconds ( 1 ) ) ) ;
167
172
}
168
173
174
+ // make sure we try again only after backoff expires
175
+ await ctx . WaitForPendingOcspFetchAsync ( ) ;
176
+ await Task . Delay ( SslStreamCertificateContext . RefreshAfterFailureBackOffInterval . Add ( TimeSpan . FromSeconds ( 1 ) ) ) ;
177
+
169
178
// after responder comes back online, the staple is eventually refreshed
179
+ intermediate . RevocationExpiration = DateTimeOffset . UtcNow . AddDays ( 1 ) ;
170
180
responder . RespondKind = RespondKind . Normal ;
171
- await RetryHelper . ExecuteAsync ( async ( ) =>
172
- {
173
- byte [ ] ocsp3 = await ctx . GetOcspResponseAsync ( ) ;
174
- Assert . NotNull ( ocsp3 ) ;
175
- Assert . NotEqual ( ocsp , ocsp3 ) ;
176
- } , maxAttempts : 5 , backoffFunc : i => ( i + 1 ) * 200 /* ms */ ) ;
181
+
182
+ // dispatch background refresh (first call still returns the old cached value)
183
+ await ctx . GetOcspResponseAsync ( ) ;
184
+
185
+ // after refresh we should have a new staple
186
+ byte [ ] ocsp3 = await ctx . WaitForPendingOcspFetchAsync ( ) ;
187
+ Assert . NotNull ( ocsp3 ) ;
188
+ Assert . NotEqual ( ocsp , ocsp3 ) ;
177
189
} ) ;
178
190
}
179
191
0 commit comments