Status: | Merged |
---|---|
Merged at revision: | 493 |
Proposed branch: | lp:~jderose/degu/py3.10 |
Merge into: | lp:degu |
Diff against target: |
439 lines (+61/-52) 9 files modified
debian/control (+1/-0) degu/client.py (+3/-3) degu/server.py (+3/-3) degu/tests/test_base.py (+22/-16) degu/tests/test_client.py (+10/-10) degu/tests/test_server.py (+12/-12) degu/tests/test_sslhelpers.py (+8/-5) doc/degu.client.rst (+1/-1) setup.py (+1/-2) |
To merge this branch: | bzr merge lp:~jderose/degu/py3.10 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jeremy Soller (community) | Approve | ||
Review via email: mp+424913@code.launchpad.net |
Commit message
Support Python 3.10
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/control' | |||
2 | --- debian/control 2021-01-13 13:00:43 +0000 | |||
3 | +++ debian/control 2022-06-16 23:17:03 +0000 | |||
4 | @@ -6,6 +6,7 @@ | |||
5 | 6 | dh-python, | 6 | dh-python, |
6 | 7 | python3-all-dev (>= 3.8), | 7 | python3-all-dev (>= 3.8), |
7 | 8 | python3-all-dbg (>= 3.8), | 8 | python3-all-dbg (>= 3.8), |
8 | 9 | python3-setuptools, | ||
9 | 9 | python3-sphinx, | 10 | python3-sphinx, |
10 | 10 | pyflakes3, | 11 | pyflakes3, |
11 | 11 | clang-tools, | 12 | clang-tools, |
12 | 12 | 13 | ||
13 | === modified file 'degu/client.py' | |||
14 | --- degu/client.py 2016-05-18 04:00:39 +0000 | |||
15 | +++ degu/client.py 2022-06-16 23:17:03 +0000 | |||
16 | @@ -82,7 +82,7 @@ | |||
17 | 82 | ) | 82 | ) |
18 | 83 | ) | 83 | ) |
19 | 84 | 84 | ||
21 | 85 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | 85 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) |
22 | 86 | sslctx.verify_mode = ssl.CERT_REQUIRED | 86 | sslctx.verify_mode = ssl.CERT_REQUIRED |
23 | 87 | sslctx.set_ciphers( | 87 | sslctx.set_ciphers( |
24 | 88 | 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384' | 88 | 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384' |
25 | @@ -116,8 +116,8 @@ | |||
26 | 116 | 116 | ||
27 | 117 | if not isinstance(sslctx, ssl.SSLContext): | 117 | if not isinstance(sslctx, ssl.SSLContext): |
28 | 118 | raise TypeError('sslctx must be an ssl.SSLContext') | 118 | raise TypeError('sslctx must be an ssl.SSLContext') |
31 | 119 | if sslctx.protocol != ssl.PROTOCOL_TLSv1_2: | 119 | if sslctx.protocol != ssl.PROTOCOL_TLS_CLIENT: |
32 | 120 | raise ValueError('sslctx.protocol must be ssl.PROTOCOL_TLSv1_2') | 120 | raise ValueError('sslctx.protocol must be ssl.PROTOCOL_TLS_CLIENT') |
33 | 121 | if not (sslctx.options & ssl.OP_NO_COMPRESSION): | 121 | if not (sslctx.options & ssl.OP_NO_COMPRESSION): |
34 | 122 | raise ValueError('sslctx.options must include ssl.OP_NO_COMPRESSION') | 122 | raise ValueError('sslctx.options must include ssl.OP_NO_COMPRESSION') |
35 | 123 | if sslctx.verify_mode != ssl.CERT_REQUIRED: | 123 | if sslctx.verify_mode != ssl.CERT_REQUIRED: |
36 | 124 | 124 | ||
37 | === modified file 'degu/server.py' | |||
38 | --- degu/server.py 2019-11-26 01:04:54 +0000 | |||
39 | +++ degu/server.py 2022-06-16 23:17:03 +0000 | |||
40 | @@ -69,7 +69,7 @@ | |||
41 | 69 | ) | 69 | ) |
42 | 70 | ) | 70 | ) |
43 | 71 | 71 | ||
45 | 72 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | 72 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
46 | 73 | sslctx.set_ciphers( | 73 | sslctx.set_ciphers( |
47 | 74 | 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384' | 74 | 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384' |
48 | 75 | ) | 75 | ) |
49 | @@ -109,8 +109,8 @@ | |||
50 | 109 | 109 | ||
51 | 110 | if not isinstance(sslctx, ssl.SSLContext): | 110 | if not isinstance(sslctx, ssl.SSLContext): |
52 | 111 | raise TypeError('sslctx must be an ssl.SSLContext') | 111 | raise TypeError('sslctx must be an ssl.SSLContext') |
55 | 112 | if sslctx.protocol != ssl.PROTOCOL_TLSv1_2: | 112 | if sslctx.protocol != ssl.PROTOCOL_TLS_SERVER: |
56 | 113 | raise ValueError('sslctx.protocol must be ssl.PROTOCOL_TLSv1_2') | 113 | raise ValueError('sslctx.protocol must be ssl.PROTOCOL_TLS_SERVER') |
57 | 114 | 114 | ||
58 | 115 | # We consider ssl.CERT_OPTIONAL to be a bad grey area: | 115 | # We consider ssl.CERT_OPTIONAL to be a bad grey area: |
59 | 116 | if sslctx.verify_mode == ssl.CERT_OPTIONAL: | 116 | if sslctx.verify_mode == ssl.CERT_OPTIONAL: |
60 | 117 | 117 | ||
61 | === modified file 'degu/tests/test_base.py' | |||
62 | --- degu/tests/test_base.py 2021-01-11 18:50:42 +0000 | |||
63 | +++ degu/tests/test_base.py 2022-06-16 23:17:03 +0000 | |||
64 | @@ -425,9 +425,9 @@ | |||
65 | 425 | if self.backend is _base: | 425 | if self.backend is _base: |
66 | 426 | msg = ARG_MSG_C.format(fullname, number, len(args)) | 426 | msg = ARG_MSG_C.format(fullname, number, len(args)) |
67 | 427 | elif len(args) < number: | 427 | elif len(args) < number: |
69 | 428 | msg = ARG_MSG_Py_1.format(name, missing) | 428 | msg = ARG_MSG_Py_1.format(fullname, missing) |
70 | 429 | else: | 429 | else: |
72 | 430 | msg = ARG_MSG_Py_2.format(name, number + 1, number + 2) | 430 | msg = ARG_MSG_Py_2.format(fullname, number + 1, number + 2) |
73 | 431 | self.assertEqual(str(cm.exception), msg) | 431 | self.assertEqual(str(cm.exception), msg) |
74 | 432 | 432 | ||
75 | 433 | def check_method_args(self, inst, name, number, missing): | 433 | def check_method_args(self, inst, name, number, missing): |
76 | @@ -803,10 +803,6 @@ | |||
77 | 803 | self.assertEqual(str(r), 'bytes=0-9999999999999998') | 803 | self.assertEqual(str(r), 'bytes=0-9999999999999998') |
78 | 804 | 804 | ||
79 | 805 | # Check reference counting: | 805 | # Check reference counting: |
80 | 806 | if self.backend is _base: | ||
81 | 807 | delmsg = 'readonly attribute' | ||
82 | 808 | else: | ||
83 | 809 | delmsg = "can't delete attribute" | ||
84 | 810 | for i in range(1000): | 806 | for i in range(1000): |
85 | 811 | stop = random.randrange(1, MAX_LENGTH + 1) | 807 | stop = random.randrange(1, MAX_LENGTH + 1) |
86 | 812 | start = random.randrange(0, stop) | 808 | start = random.randrange(0, stop) |
87 | @@ -827,6 +823,10 @@ | |||
88 | 827 | # start, stop should be read-only: | 823 | # start, stop should be read-only: |
89 | 828 | r = self.Range(start, stop) | 824 | r = self.Range(start, stop) |
90 | 829 | for name in ('start', 'stop'): | 825 | for name in ('start', 'stop'): |
91 | 826 | if self.backend is _base: | ||
92 | 827 | delmsg = 'readonly attribute' | ||
93 | 828 | else: | ||
94 | 829 | delmsg = "can't delete attribute '" + name + "'" | ||
95 | 830 | with self.assertRaises(AttributeError) as cm: | 830 | with self.assertRaises(AttributeError) as cm: |
96 | 831 | delattr(r, name) | 831 | delattr(r, name) |
97 | 832 | self.assertEqual(str(cm.exception), delmsg) | 832 | self.assertEqual(str(cm.exception), delmsg) |
98 | @@ -1139,10 +1139,6 @@ | |||
99 | 1139 | ) | 1139 | ) |
100 | 1140 | 1140 | ||
101 | 1141 | # Check reference counting: | 1141 | # Check reference counting: |
102 | 1142 | if self.backend is _base: | ||
103 | 1143 | delmsg = 'readonly attribute' | ||
104 | 1144 | else: | ||
105 | 1145 | delmsg = "can't delete attribute" | ||
106 | 1146 | for i in range(1000): | 1142 | for i in range(1000): |
107 | 1147 | stop = random.randrange(1, MAX_LENGTH + 1) | 1143 | stop = random.randrange(1, MAX_LENGTH + 1) |
108 | 1148 | start = random.randrange(0, stop) | 1144 | start = random.randrange(0, stop) |
109 | @@ -1172,6 +1168,10 @@ | |||
110 | 1172 | # start, stop, total should be read-only: | 1168 | # start, stop, total should be read-only: |
111 | 1173 | r = self.ContentRange(start, stop, total) | 1169 | r = self.ContentRange(start, stop, total) |
112 | 1174 | for name in ('start', 'stop', 'total'): | 1170 | for name in ('start', 'stop', 'total'): |
113 | 1171 | if self.backend is _base: | ||
114 | 1172 | delmsg = 'readonly attribute' | ||
115 | 1173 | else: | ||
116 | 1174 | delmsg = "can't delete attribute '" + name + "'" | ||
117 | 1175 | with self.assertRaises(AttributeError) as cm: | 1175 | with self.assertRaises(AttributeError) as cm: |
118 | 1176 | delattr(r, name) | 1176 | delattr(r, name) |
119 | 1177 | self.assertEqual(str(cm.exception), delmsg) | 1177 | self.assertEqual(str(cm.exception), delmsg) |
120 | @@ -2170,6 +2170,7 @@ | |||
121 | 2170 | self.assertEqual(str(cm.exception), | 2170 | self.assertEqual(str(cm.exception), |
122 | 2171 | "'MissingReadline' object has no attribute 'readline'" | 2171 | "'MissingReadline' object has no attribute 'readline'" |
123 | 2172 | ) | 2172 | ) |
124 | 2173 | del cm # Must del context manager before testing refcount (py 3.10+): | ||
125 | 2173 | self.assertEqual(sys.getrefcount(rfile), 2) | 2174 | self.assertEqual(sys.getrefcount(rfile), 2) |
126 | 2174 | 2175 | ||
127 | 2175 | # rfile.readline() not callable: | 2176 | # rfile.readline() not callable: |
128 | @@ -2195,6 +2196,7 @@ | |||
129 | 2195 | self.assertEqual(str(cm.exception), | 2196 | self.assertEqual(str(cm.exception), |
130 | 2196 | "'MissingRead' object has no attribute 'readinto'" | 2197 | "'MissingRead' object has no attribute 'readinto'" |
131 | 2197 | ) | 2198 | ) |
132 | 2199 | del cm # Must del context manager before testing refcount (py 3.10+): | ||
133 | 2198 | self.assertEqual(sys.getrefcount(rfile), 2) | 2200 | self.assertEqual(sys.getrefcount(rfile), 2) |
134 | 2199 | 2201 | ||
135 | 2200 | # rfile.readinto() not callable: | 2202 | # rfile.readinto() not callable: |
136 | @@ -3505,13 +3507,13 @@ | |||
137 | 3505 | Check body instance attributes that should be read-only. | 3507 | Check body instance attributes that should be read-only. |
138 | 3506 | """ | 3508 | """ |
139 | 3507 | assert len(members) >= 2 | 3509 | assert len(members) >= 2 |
140 | 3508 | if self.backend is _basepy: | ||
141 | 3509 | setmsg = "can't set attribute" | ||
142 | 3510 | delmsg = "can't delete attribute" | ||
143 | 3511 | else: | ||
144 | 3512 | setmsg = 'readonly attribute' | ||
145 | 3513 | delmsg = 'readonly attribute' | ||
146 | 3514 | for name in members: | 3510 | for name in members: |
147 | 3511 | if self.backend is _basepy: | ||
148 | 3512 | setmsg = "can't set attribute '" + name + "'" | ||
149 | 3513 | delmsg = "can't delete attribute '" + name + "'" | ||
150 | 3514 | else: | ||
151 | 3515 | setmsg = 'readonly attribute' | ||
152 | 3516 | delmsg = 'readonly attribute' | ||
153 | 3515 | value = getattr(body, name) | 3517 | value = getattr(body, name) |
154 | 3516 | with self.assertRaises(AttributeError) as cm: | 3518 | with self.assertRaises(AttributeError) as cm: |
155 | 3517 | setattr(body, name, value) | 3519 | setattr(body, name, value) |
156 | @@ -3993,6 +3995,7 @@ | |||
157 | 3993 | self.assertEqual(str(cm.exception), | 3995 | self.assertEqual(str(cm.exception), |
158 | 3994 | "'MissingReadline' object has no attribute 'readline'" | 3996 | "'MissingReadline' object has no attribute 'readline'" |
159 | 3995 | ) | 3997 | ) |
160 | 3998 | del cm # Must del context manager before testing refcount (py 3.10+): | ||
161 | 3996 | self.assertEqual(sys.getrefcount(rfile), 2) | 3999 | self.assertEqual(sys.getrefcount(rfile), 2) |
162 | 3997 | 4000 | ||
163 | 3998 | # Not a backend.SocketWrapper, rfile.readline() not callable: | 4001 | # Not a backend.SocketWrapper, rfile.readline() not callable: |
164 | @@ -4018,6 +4021,7 @@ | |||
165 | 4018 | self.assertEqual(str(cm.exception), | 4021 | self.assertEqual(str(cm.exception), |
166 | 4019 | "'MissingRead' object has no attribute 'readinto'" | 4022 | "'MissingRead' object has no attribute 'readinto'" |
167 | 4020 | ) | 4023 | ) |
168 | 4024 | del cm # Must del context manager before testing refcount (py 3.10+): | ||
169 | 4021 | self.assertEqual(sys.getrefcount(rfile), 2) | 4025 | self.assertEqual(sys.getrefcount(rfile), 2) |
170 | 4022 | 4026 | ||
171 | 4023 | # Not a backend.SocketWrapper, rfile.readinto() not callable: | 4027 | # Not a backend.SocketWrapper, rfile.readinto() not callable: |
172 | @@ -6245,6 +6249,7 @@ | |||
173 | 6245 | self.assertEqual(str(cm.exception), | 6249 | self.assertEqual(str(cm.exception), |
174 | 6246 | "'BadSocket1' object has no attribute 'recv_into'" | 6250 | "'BadSocket1' object has no attribute 'recv_into'" |
175 | 6247 | ) | 6251 | ) |
176 | 6252 | del cm # Must del context manager before testing refcount (py 3.10+): | ||
177 | 6248 | self.assertEqual(sys.getrefcount(sock), 2) | 6253 | self.assertEqual(sys.getrefcount(sock), 2) |
178 | 6249 | self.assertEqual(sock._calls, ['close']) | 6254 | self.assertEqual(sock._calls, ['close']) |
179 | 6250 | 6255 | ||
180 | @@ -6259,6 +6264,7 @@ | |||
181 | 6259 | self.assertEqual(str(cm.exception), | 6264 | self.assertEqual(str(cm.exception), |
182 | 6260 | "'BadSocket2' object has no attribute 'send'" | 6265 | "'BadSocket2' object has no attribute 'send'" |
183 | 6261 | ) | 6266 | ) |
184 | 6267 | del cm # Must del context manager before testing refcount (py 3.10+): | ||
185 | 6262 | self.assertEqual(sys.getrefcount(sock), 2) | 6268 | self.assertEqual(sys.getrefcount(sock), 2) |
186 | 6263 | self.assertEqual(sock._calls, ['close']) | 6269 | self.assertEqual(sock._calls, ['close']) |
187 | 6264 | 6270 | ||
188 | 6265 | 6271 | ||
189 | === modified file 'degu/tests/test_client.py' | |||
190 | --- degu/tests/test_client.py 2017-09-04 23:38:30 +0000 | |||
191 | +++ degu/tests/test_client.py 2022-06-16 23:17:03 +0000 | |||
192 | @@ -142,7 +142,7 @@ | |||
193 | 142 | for func in client_sslctx_funcs: | 142 | for func in client_sslctx_funcs: |
194 | 143 | sslctx = func({}) | 143 | sslctx = func({}) |
195 | 144 | self.assertIsInstance(sslctx, ssl.SSLContext) | 144 | self.assertIsInstance(sslctx, ssl.SSLContext) |
197 | 145 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLSv1_2) | 145 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLS_CLIENT) |
198 | 146 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) | 146 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) |
199 | 147 | self.assertIs(sslctx.check_hostname, True) | 147 | self.assertIs(sslctx.check_hostname, True) |
200 | 148 | 148 | ||
201 | @@ -159,7 +159,7 @@ | |||
202 | 159 | for func in client_sslctx_funcs: | 159 | for func in client_sslctx_funcs: |
203 | 160 | sslctx = func({'check_hostname': True}) | 160 | sslctx = func({'check_hostname': True}) |
204 | 161 | self.assertIsInstance(sslctx, ssl.SSLContext) | 161 | self.assertIsInstance(sslctx, ssl.SSLContext) |
206 | 162 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLSv1_2) | 162 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLS_CLIENT) |
207 | 163 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) | 163 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) |
208 | 164 | self.assertIs(sslctx.check_hostname, True) | 164 | self.assertIs(sslctx.check_hostname, True) |
209 | 165 | 165 | ||
210 | @@ -173,7 +173,7 @@ | |||
211 | 173 | for func in client_sslctx_funcs: | 173 | for func in client_sslctx_funcs: |
212 | 174 | sslctx = func(sslconfig) | 174 | sslctx = func(sslconfig) |
213 | 175 | self.assertIsInstance(sslctx, ssl.SSLContext) | 175 | self.assertIsInstance(sslctx, ssl.SSLContext) |
215 | 176 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLSv1_2) | 176 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLS_CLIENT) |
216 | 177 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) | 177 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) |
217 | 178 | self.assertIs(sslctx.check_hostname, False) | 178 | self.assertIs(sslctx.check_hostname, False) |
218 | 179 | 179 | ||
219 | @@ -182,7 +182,7 @@ | |||
220 | 182 | for func in client_sslctx_funcs: | 182 | for func in client_sslctx_funcs: |
221 | 183 | sslctx = func(sslconfig) | 183 | sslctx = func(sslconfig) |
222 | 184 | self.assertIsInstance(sslctx, ssl.SSLContext) | 184 | self.assertIsInstance(sslctx, ssl.SSLContext) |
224 | 185 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLSv1_2) | 185 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLS_CLIENT) |
225 | 186 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) | 186 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) |
226 | 187 | self.assertIs(sslctx.check_hostname, True) | 187 | self.assertIs(sslctx.check_hostname, True) |
227 | 188 | 188 | ||
228 | @@ -193,7 +193,7 @@ | |||
229 | 193 | for func in client_sslctx_funcs: | 193 | for func in client_sslctx_funcs: |
230 | 194 | sslctx = func(sslconfig) | 194 | sslctx = func(sslconfig) |
231 | 195 | self.assertIsInstance(sslctx, ssl.SSLContext) | 195 | self.assertIsInstance(sslctx, ssl.SSLContext) |
233 | 196 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLSv1_2) | 196 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLS_CLIENT) |
234 | 197 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) | 197 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) |
235 | 198 | self.assertIs(sslctx.check_hostname, False) | 198 | self.assertIs(sslctx.check_hostname, False) |
236 | 199 | 199 | ||
237 | @@ -202,7 +202,7 @@ | |||
238 | 202 | for func in client_sslctx_funcs: | 202 | for func in client_sslctx_funcs: |
239 | 203 | sslctx = func(sslconfig) | 203 | sslctx = func(sslconfig) |
240 | 204 | self.assertIsInstance(sslctx, ssl.SSLContext) | 204 | self.assertIsInstance(sslctx, ssl.SSLContext) |
242 | 205 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLSv1_2) | 205 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLS_CLIENT) |
243 | 206 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) | 206 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) |
244 | 207 | self.assertIs(sslctx.check_hostname, True) | 207 | self.assertIs(sslctx.check_hostname, True) |
245 | 208 | 208 | ||
246 | @@ -470,11 +470,11 @@ | |||
247 | 470 | self.assertEqual(str(cm.exception), 'sslctx must be an ssl.SSLContext') | 470 | self.assertEqual(str(cm.exception), 'sslctx must be an ssl.SSLContext') |
248 | 471 | 471 | ||
249 | 472 | # Bad SSL protocol version: | 472 | # Bad SSL protocol version: |
251 | 473 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) | 473 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
252 | 474 | with self.assertRaises(ValueError) as cm: | 474 | with self.assertRaises(ValueError) as cm: |
253 | 475 | client.SSLClient(sslctx, None) | 475 | client.SSLClient(sslctx, None) |
254 | 476 | self.assertEqual(str(cm.exception), | 476 | self.assertEqual(str(cm.exception), |
256 | 477 | 'sslctx.protocol must be ssl.PROTOCOL_TLSv1_2' | 477 | 'sslctx.protocol must be ssl.PROTOCOL_TLS_CLIENT' |
257 | 478 | ) | 478 | ) |
258 | 479 | 479 | ||
259 | 480 | # Note: Python 3.3.4 (and presumably 3.4.0) now disables SSLv2 by | 480 | # Note: Python 3.3.4 (and presumably 3.4.0) now disables SSLv2 by |
260 | @@ -482,7 +482,7 @@ | |||
261 | 482 | # we cannot unset the ssl.OP_NO_SSLv2 bit, we can't unit test to check | 482 | # we cannot unset the ssl.OP_NO_SSLv2 bit, we can't unit test to check |
262 | 483 | # that Degu enforces this, so for now, we set the bit here so it works | 483 | # that Degu enforces this, so for now, we set the bit here so it works |
263 | 484 | # with Python 3.3.3 still; see: http://bugs.python.org/issue20207 | 484 | # with Python 3.3.3 still; see: http://bugs.python.org/issue20207 |
265 | 485 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | 485 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) |
266 | 486 | sslctx.options |= ssl.OP_NO_SSLv2 | 486 | sslctx.options |= ssl.OP_NO_SSLv2 |
267 | 487 | 487 | ||
268 | 488 | # not (options & ssl.OP_NO_COMPRESSION) | 488 | # not (options & ssl.OP_NO_COMPRESSION) |
269 | @@ -494,7 +494,7 @@ | |||
270 | 494 | ) | 494 | ) |
271 | 495 | 495 | ||
272 | 496 | # verify_mode is not ssl.CERT_REQUIRED: | 496 | # verify_mode is not ssl.CERT_REQUIRED: |
274 | 497 | sslctx.options |= ssl.OP_NO_COMPRESSION | 497 | sslctx.verify_mode = ssl.CERT_OPTIONAL |
275 | 498 | with self.assertRaises(ValueError) as cm: | 498 | with self.assertRaises(ValueError) as cm: |
276 | 499 | client.SSLClient(sslctx, None) | 499 | client.SSLClient(sslctx, None) |
277 | 500 | self.assertEqual(str(cm.exception), | 500 | self.assertEqual(str(cm.exception), |
278 | 501 | 501 | ||
279 | === modified file 'degu/tests/test_server.py' | |||
280 | --- degu/tests/test_server.py 2019-11-26 01:04:54 +0000 | |||
281 | +++ degu/tests/test_server.py 2022-06-16 23:17:03 +0000 | |||
282 | @@ -120,7 +120,7 @@ | |||
283 | 120 | ) | 120 | ) |
284 | 121 | for func in server_sslctx_funcs: | 121 | for func in server_sslctx_funcs: |
285 | 122 | sslctx = func(pki.server_sslconfig) | 122 | sslctx = func(pki.server_sslconfig) |
287 | 123 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLSv1_2) | 123 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLS_SERVER) |
288 | 124 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) | 124 | self.assertEqual(sslctx.verify_mode, ssl.CERT_REQUIRED) |
289 | 125 | 125 | ||
290 | 126 | # New in Degu 0.3: should not be able to accept connections from | 126 | # New in Degu 0.3: should not be able to accept connections from |
291 | @@ -138,7 +138,7 @@ | |||
292 | 138 | sslconfig['allow_unauthenticated_clients'] = True | 138 | sslconfig['allow_unauthenticated_clients'] = True |
293 | 139 | for func in server_sslctx_funcs: | 139 | for func in server_sslctx_funcs: |
294 | 140 | sslctx = func(sslconfig) | 140 | sslctx = func(sslconfig) |
296 | 141 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLSv1_2) | 141 | self.assertEqual(sslctx.protocol, ssl.PROTOCOL_TLS_SERVER) |
297 | 142 | self.assertEqual(sslctx.verify_mode, ssl.CERT_NONE) | 142 | self.assertEqual(sslctx.verify_mode, ssl.CERT_NONE) |
298 | 143 | 143 | ||
299 | 144 | # Cannot mix ca_file/ca_path with allow_unauthenticated_clients: | 144 | # Cannot mix ca_file/ca_path with allow_unauthenticated_clients: |
300 | @@ -176,13 +176,13 @@ | |||
301 | 176 | 176 | ||
302 | 177 | # Wrong protocol: | 177 | # Wrong protocol: |
303 | 178 | with self.assertRaises(ValueError) as cm: | 178 | with self.assertRaises(ValueError) as cm: |
305 | 179 | server._validate_server_sslctx(ssl.SSLContext(ssl.PROTOCOL_TLSv1)) | 179 | server._validate_server_sslctx(ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)) |
306 | 180 | self.assertEqual(str(cm.exception), | 180 | self.assertEqual(str(cm.exception), |
308 | 181 | 'sslctx.protocol must be ssl.PROTOCOL_TLSv1_2' | 181 | 'sslctx.protocol must be ssl.PROTOCOL_TLS_SERVER' |
309 | 182 | ) | 182 | ) |
310 | 183 | 183 | ||
311 | 184 | # Don't allow ssl.CERT_OPTIONAL: | 184 | # Don't allow ssl.CERT_OPTIONAL: |
313 | 185 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | 185 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
314 | 186 | sslctx.verify_mode = ssl.CERT_OPTIONAL | 186 | sslctx.verify_mode = ssl.CERT_OPTIONAL |
315 | 187 | with self.assertRaises(ValueError) as cm: | 187 | with self.assertRaises(ValueError) as cm: |
316 | 188 | server._validate_server_sslctx(sslctx) | 188 | server._validate_server_sslctx(sslctx) |
317 | @@ -191,13 +191,13 @@ | |||
318 | 191 | ) | 191 | ) |
319 | 192 | 192 | ||
320 | 193 | # All good: | 193 | # All good: |
322 | 194 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | 194 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
323 | 195 | self.assertIs(sslctx.verify_mode, ssl.CERT_NONE) | 195 | self.assertIs(sslctx.verify_mode, ssl.CERT_NONE) |
324 | 196 | self.assertIs(server._validate_server_sslctx(sslctx), sslctx) | 196 | self.assertIs(server._validate_server_sslctx(sslctx), sslctx) |
325 | 197 | 197 | ||
326 | 198 | # Now again, this time with CERT_REQUIRED: | 198 | # Now again, this time with CERT_REQUIRED: |
327 | 199 | # options missing OP_NO_COMPRESSION: | 199 | # options missing OP_NO_COMPRESSION: |
329 | 200 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | 200 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
330 | 201 | sslctx.verify_mode = ssl.CERT_REQUIRED | 201 | sslctx.verify_mode = ssl.CERT_REQUIRED |
331 | 202 | self.assertIs(sslctx.verify_mode, ssl.CERT_REQUIRED) | 202 | self.assertIs(sslctx.verify_mode, ssl.CERT_REQUIRED) |
332 | 203 | self.assertIs(server._validate_server_sslctx(sslctx), sslctx) | 203 | self.assertIs(server._validate_server_sslctx(sslctx), sslctx) |
333 | @@ -426,15 +426,15 @@ | |||
334 | 426 | self.assertEqual(str(cm.exception), 'sslctx must be an ssl.SSLContext') | 426 | self.assertEqual(str(cm.exception), 'sslctx must be an ssl.SSLContext') |
335 | 427 | 427 | ||
336 | 428 | # Bad SSL protocol version: | 428 | # Bad SSL protocol version: |
338 | 429 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1) | 429 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) |
339 | 430 | with self.assertRaises(ValueError) as cm: | 430 | with self.assertRaises(ValueError) as cm: |
340 | 431 | server.SSLServer(sslctx, degu.IPv6_LOOPBACK, good_app) | 431 | server.SSLServer(sslctx, degu.IPv6_LOOPBACK, good_app) |
341 | 432 | self.assertEqual(str(cm.exception), | 432 | self.assertEqual(str(cm.exception), |
343 | 433 | 'sslctx.protocol must be ssl.PROTOCOL_TLSv1_2' | 433 | 'sslctx.protocol must be ssl.PROTOCOL_TLS_SERVER' |
344 | 434 | ) | 434 | ) |
345 | 435 | 435 | ||
346 | 436 | # Good sslctx from here on: | 436 | # Good sslctx from here on: |
348 | 437 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) | 437 | sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) |
349 | 438 | 438 | ||
350 | 439 | # Bad address type: | 439 | # Bad address type: |
351 | 440 | with self.assertRaises(TypeError) as cm: | 440 | with self.assertRaises(TypeError) as cm: |
352 | @@ -1003,7 +1003,7 @@ | |||
353 | 1003 | with self.assertRaises(ssl.SSLError) as cm: | 1003 | with self.assertRaises(ssl.SSLError) as cm: |
354 | 1004 | client.connect() | 1004 | client.connect() |
355 | 1005 | self.assertTrue( | 1005 | self.assertTrue( |
357 | 1006 | str(cm.exception).startswith('[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE]') | 1006 | str(cm.exception).startswith('[SSL: CERTIFICATE_VERIFY_FAILED]') |
358 | 1007 | ) | 1007 | ) |
359 | 1008 | self.assertIs(conn.closed, True) | 1008 | self.assertIs(conn.closed, True) |
360 | 1009 | 1009 | ||
361 | @@ -1017,7 +1017,7 @@ | |||
362 | 1017 | with self.assertRaises(ssl.SSLError) as cm: | 1017 | with self.assertRaises(ssl.SSLError) as cm: |
363 | 1018 | client.connect() | 1018 | client.connect() |
364 | 1019 | self.assertTrue( | 1019 | self.assertTrue( |
366 | 1020 | str(cm.exception).startswith('[SSL: TLSV1_ALERT_UNKNOWN_CA]') | 1020 | str(cm.exception).startswith('[SSL: CERTIFICATE_VERIFY_FAILED]') |
367 | 1021 | ) | 1021 | ) |
368 | 1022 | self.assertIs(conn.closed, True) | 1022 | self.assertIs(conn.closed, True) |
369 | 1023 | 1023 | ||
370 | 1024 | 1024 | ||
371 | === modified file 'degu/tests/test_sslhelpers.py' | |||
372 | --- degu/tests/test_sslhelpers.py 2016-03-13 18:28:18 +0000 | |||
373 | +++ degu/tests/test_sslhelpers.py 2022-06-16 23:17:03 +0000 | |||
374 | @@ -36,22 +36,26 @@ | |||
375 | 36 | def test_create_key(self): | 36 | def test_create_key(self): |
376 | 37 | # 1024 bit: | 37 | # 1024 bit: |
377 | 38 | key_data = sslhelpers.create_key(1024) | 38 | key_data = sslhelpers.create_key(1024) |
379 | 39 | self.assertIn(len(key_data), [883, 887, 891]) | 39 | self.assertGreater(len(key_data), 512) |
380 | 40 | self.assertLess(len(key_data), 1024) | ||
381 | 40 | sslhelpers.get_pubkey(key_data) | 41 | sslhelpers.get_pubkey(key_data) |
382 | 41 | 42 | ||
383 | 42 | # 2048 bit: | 43 | # 2048 bit: |
384 | 43 | key_data = sslhelpers.create_key(2048) | 44 | key_data = sslhelpers.create_key(2048) |
386 | 44 | self.assertIn(len(key_data), [1671, 1675, 1679]) | 45 | self.assertGreater(len(key_data), 1024) |
387 | 46 | self.assertLess(len(key_data), 2048) | ||
388 | 45 | sslhelpers.get_pubkey(key_data) | 47 | sslhelpers.get_pubkey(key_data) |
389 | 46 | 48 | ||
390 | 47 | # 3072 bit: | 49 | # 3072 bit: |
391 | 48 | key_data = sslhelpers.create_key(3072) | 50 | key_data = sslhelpers.create_key(3072) |
393 | 49 | self.assertIn(len(key_data), [2455, 2459]) | 51 | self.assertGreater(len(key_data), 2048) |
394 | 52 | self.assertLess(len(key_data), 3072) | ||
395 | 50 | sslhelpers.get_pubkey(key_data) | 53 | sslhelpers.get_pubkey(key_data) |
396 | 51 | 54 | ||
397 | 52 | # 4096 bit: | 55 | # 4096 bit: |
398 | 53 | key_data = sslhelpers.create_key(4096) | 56 | key_data = sslhelpers.create_key(4096) |
400 | 54 | self.assertIn(len(key_data), [3239, 3243, 3247]) | 57 | self.assertGreater(len(key_data), 3072) |
401 | 58 | self.assertLess(len(key_data), 4096) | ||
402 | 55 | sslhelpers.get_pubkey(key_data) | 59 | sslhelpers.get_pubkey(key_data) |
403 | 56 | 60 | ||
404 | 57 | def test_create_ca(self): | 61 | def test_create_ca(self): |
405 | @@ -179,7 +183,6 @@ | |||
406 | 179 | set([ | 183 | set([ |
407 | 180 | ca_id + '.key', | 184 | ca_id + '.key', |
408 | 181 | ca_id + '.ca', | 185 | ca_id + '.ca', |
409 | 182 | ca_id + '.srl', | ||
410 | 183 | cert_id + '.csr', | 186 | cert_id + '.csr', |
411 | 184 | cert_id + '.cert', | 187 | cert_id + '.cert', |
412 | 185 | ]) | 188 | ]) |
413 | 186 | 189 | ||
414 | === modified file 'doc/degu.client.rst' | |||
415 | --- doc/degu.client.rst 2017-07-18 18:07:33 +0000 | |||
416 | +++ doc/degu.client.rst 2022-06-16 23:17:03 +0000 | |||
417 | @@ -42,7 +42,7 @@ | |||
418 | 42 | server certificate (more or less how a browser would configure SSL): | 42 | server certificate (more or less how a browser would configure SSL): |
419 | 43 | 43 | ||
420 | 44 | >>> import ssl | 44 | >>> import ssl |
422 | 45 | >>> sslclient.sslctx.protocol == ssl.PROTOCOL_TLSv1_2 | 45 | >>> sslclient.sslctx.protocol == ssl.PROTOCOL_TLS_CLIENT |
423 | 46 | True | 46 | True |
424 | 47 | >>> sslclient.sslctx.verify_mode == ssl.CERT_REQUIRED | 47 | >>> sslclient.sslctx.verify_mode == ssl.CERT_REQUIRED |
425 | 48 | True | 48 | True |
426 | 49 | 49 | ||
427 | === modified file 'setup.py' | |||
428 | --- setup.py 2021-01-13 13:00:43 +0000 | |||
429 | +++ setup.py 2022-06-16 23:17:03 +0000 | |||
430 | @@ -33,8 +33,7 @@ | |||
431 | 33 | import os | 33 | import os |
432 | 34 | from os import path | 34 | from os import path |
433 | 35 | import subprocess | 35 | import subprocess |
436 | 36 | from distutils.core import setup, Extension | 36 | from setuptools import setup, Command, Extension |
435 | 37 | from distutils.cmd import Command | ||
437 | 38 | 37 | ||
438 | 39 | import degu | 38 | import degu |
439 | 40 | from degu.tests.run import run_tests | 39 | from degu.tests.run import run_tests |
Changes all look good to me