19
19
from collections import namedtuple
20
20
from datetime import datetime as _datetime
21
21
from datetime import timezone
22
- from typing import TYPE_CHECKING , Any
22
+ from typing import TYPE_CHECKING , Any , Optional
23
23
24
24
from pymongo .lock import _create_lock
25
25
26
26
if TYPE_CHECKING :
27
27
from cryptography .x509 .ocsp import OCSPRequest , OCSPResponse
28
28
29
29
30
+ def _next_update (value : OCSPResponse ) -> Optional [_datetime ]:
31
+ """Compat helper to return the response's next_update_utc."""
32
+ # Added in cryptography 43.0.0.
33
+ if hasattr (value , "next_update_utc" ):
34
+ return value .next_update_utc
35
+ return value .next_update
36
+
37
+
38
+ def _this_update (value : OCSPResponse ) -> Optional [_datetime ]:
39
+ """Compat helper to return the response's this_update_utc."""
40
+ # Added in cryptography 43.0.0.
41
+ if hasattr (value , "this_update_utc" ):
42
+ return value .this_update_utc
43
+ return value .this_update
44
+
45
+
30
46
class _OCSPCache :
31
47
"""A cache for OCSP responses."""
32
48
@@ -62,25 +78,30 @@ def __setitem__(self, key: OCSPRequest, value: OCSPResponse) -> None:
62
78
# As per the OCSP protocol, if the response's nextUpdate field is
63
79
# not set, the responder is indicating that newer revocation
64
80
# information is available all the time.
65
- if value .next_update is None :
81
+ next_update = _next_update (value )
82
+ if next_update is None :
66
83
self ._data .pop (cache_key , None )
67
84
return
68
85
86
+ this_update = _this_update (value )
87
+ if this_update is None :
88
+ return
89
+ now = _datetime .now (tz = timezone .utc )
90
+ if this_update .tzinfo is None :
91
+ # Make naive to match cryptography.
92
+ now = now .replace (tzinfo = None )
69
93
# Do nothing if the response is invalid.
70
- if not (
71
- value .this_update
72
- <= _datetime .now (tz = timezone .utc ).replace (tzinfo = None )
73
- < value .next_update
74
- ):
94
+ if not (this_update <= now < next_update ):
75
95
return
76
96
77
97
# Cache new response OR update cached response if new response
78
98
# has longer validity.
79
99
cached_value = self ._data .get (cache_key , None )
80
- if cached_value is None or (
81
- cached_value .next_update is not None
82
- and cached_value .next_update < value .next_update
83
- ):
100
+ if cached_value is None :
101
+ self ._data [cache_key ] = value
102
+ return
103
+ cached_next_update = _next_update (cached_value )
104
+ if cached_next_update is not None and cached_next_update < next_update :
84
105
self ._data [cache_key ] = value
85
106
86
107
def __getitem__ (self , item : OCSPRequest ) -> OCSPResponse :
@@ -95,13 +116,15 @@ def __getitem__(self, item: OCSPRequest) -> OCSPResponse:
95
116
value = self ._data [cache_key ]
96
117
97
118
# Return cached response if it is still valid.
98
- assert value .this_update is not None
99
- assert value .next_update is not None
100
- if (
101
- value .this_update
102
- <= _datetime .now (tz = timezone .utc ).replace (tzinfo = None )
103
- < value .next_update
104
- ):
119
+ this_update = _this_update (value )
120
+ next_update = _next_update (value )
121
+ assert this_update is not None
122
+ assert next_update is not None
123
+ now = _datetime .now (tz = timezone .utc )
124
+ if this_update .tzinfo is None :
125
+ # Make naive to match cryptography.
126
+ now = now .replace (tzinfo = None )
127
+ if this_update <= now < next_update :
105
128
return value
106
129
107
130
self ._data .pop (cache_key , None )
0 commit comments