@@ -110,17 +110,18 @@ public static void RAND_add(object buf, double entropy) {
110110
111111 [ PythonType ]
112112 public class _SSLContext {
113- private readonly X509Certificate2Collection _cert_store = new X509Certificate2Collection ( ) ;
114- private string _cafile ;
113+ internal readonly X509Certificate2Collection _cert_store = new X509Certificate2Collection ( ) ;
114+ internal string _cafile ;
115115 private int _verify_mode = SSL_VERIFY_NONE ;
116116
117- public _SSLContext ( CodeContext context , int protocol = PROTOCOL_SSLv23 ) {
117+ public _SSLContext ( CodeContext context , int protocol ) {
118118 if ( protocol != PROTOCOL_SSLv2 && protocol != PROTOCOL_SSLv23 && protocol != PROTOCOL_SSLv3 &&
119119 protocol != PROTOCOL_TLSv1 && protocol != PROTOCOL_TLSv1_1 && protocol != PROTOCOL_TLSv1_2 ) {
120120 throw PythonOps . ValueError ( "invalid protocol version" ) ;
121121 }
122122
123123 this . protocol = protocol ;
124+
124125 if ( protocol != PROTOCOL_SSLv2 )
125126 options |= OP_NO_SSLv2 ;
126127 if ( protocol != PROTOCOL_SSLv3 )
@@ -176,14 +177,20 @@ public void load_cert_chain(string certfile, string keyfile = null, object passw
176177
177178 }
178179
179- public void load_verify_locations ( CodeContext context , string cafile = null , string capath = null , object cadata = null ) {
180+ public void load_verify_locations ( CodeContext context , object cafile = null , string capath = null , object cadata = null ) {
180181 if ( cafile == null && capath == null && cadata == null ) {
181182 throw PythonOps . TypeError ( "cafile, capath and cadata cannot be all omitted" ) ;
182183 }
183184
184- if ( cafile != null ) {
185- _cert_store . Add ( ReadCertificate ( context , cafile ) ) ;
186- _cafile = cafile ;
185+ if ( cafile is not null ) {
186+ if ( cafile is string s ) {
187+ _cafile = s ;
188+ } else if ( cafile is Bytes b ) {
189+ _cafile = b . MakeString ( ) ;
190+ } else {
191+ throw PythonOps . TypeError ( "cafile should be a valid filesystem path" ) ;
192+ }
193+ _cert_store . Add ( ReadCertificate ( context , _cafile ) ) ;
187194 }
188195
189196 if ( capath != null ) {
@@ -208,8 +215,8 @@ public void load_verify_locations(CodeContext context, string cafile = null, str
208215 }
209216 }
210217
211- public object _wrap_socket ( CodeContext context , PythonSocket . socket sock , bool server_side , string server_hostname = null , object ssl_sock = null ) {
212- return new _SSLSocket ( context , sock , server_side , null , _cafile , verify_mode , protocol | options , null , _cert_store ) { _serverHostName = server_hostname } ;
218+ public object _wrap_socket ( CodeContext context , PythonSocket . socket sock , bool server_side , string server_hostname = null ) {
219+ return new _SSLSocket ( context , this , sock , server_side , server_hostname ) ;
213220 }
214221 }
215222
@@ -226,34 +233,22 @@ public class _SSLSocket {
226233 private Exception _validationFailure ;
227234 internal string _serverHostName ;
228235
229- public _SSLSocket ( CodeContext context , PythonSocket . socket sock , string keyfile = null , string certfile = null , X509Certificate2Collection certs = null ) {
230- _context = context ;
231- _sslStream = new SslStream ( new NetworkStream ( sock . _socket , false ) , true , CertValidationCallback ) ;
232- _socket = sock ;
233- _protocol = PythonSsl . PROTOCOL_SSLv23 | PythonSsl . OP_NO_SSLv2 | PythonSsl . OP_NO_SSLv3 ;
234- _validate = false ;
235- _certCollection = certs ?? new X509Certificate2Collection ( ) ;
236- }
236+ public _SSLContext context { get ; }
237237
238- internal _SSLSocket ( CodeContext context ,
239- PythonSocket . socket sock ,
240- bool server_side ,
241- string keyfile = null ,
242- string certfile = null ,
243- int certs_mode = PythonSsl . CERT_NONE ,
244- int protocol = ( PythonSsl . PROTOCOL_SSLv23 | PythonSsl . OP_NO_SSLv2 | PythonSsl . OP_NO_SSLv3 ) ,
245- string cacertsfile = null ,
246- X509Certificate2Collection certs = null ) {
238+ internal _SSLSocket ( CodeContext context , _SSLContext sslcontext , PythonSocket . socket sock , bool server_side , string server_hostname ) {
247239 if ( sock == null ) {
248240 throw PythonOps . TypeError ( "expected socket object, got None" ) ;
249241 }
250242
243+ this . context = sslcontext ;
251244 _serverSide = server_side ;
252- bool validate ;
253- _certsMode = certs_mode ;
245+ _serverHostName = server_hostname ;
246+
247+ _certsMode = sslcontext . verify_mode ;
254248
249+ bool validate ;
255250 RemoteCertificateValidationCallback callback ;
256- switch ( certs_mode ) {
251+ switch ( _certsMode ) {
257252 case PythonSsl . CERT_NONE :
258253 validate = false ;
259254 callback = CertValidationCallback ;
@@ -267,28 +262,24 @@ internal _SSLSocket(CodeContext context,
267262 callback = CertValidationCallbackRequired ;
268263 break ;
269264 default :
270- throw new InvalidOperationException ( String . Format ( "bad certs_mode: {0}" , certs_mode ) ) ;
265+ throw new InvalidOperationException ( String . Format ( "bad certs_mode: {0}" , _certsMode ) ) ;
271266 }
272267
273268 _callback = callback ;
274269
275- if ( certs != null ) {
276- _certCollection = certs ;
270+ if ( sslcontext . _cert_store != null ) {
271+ _certCollection = sslcontext . _cert_store ;
277272 }
278273
279- if ( certfile != null ) {
280- _cert = PythonSsl . ReadCertificate ( context , certfile ) ;
281- }
282-
283- if ( cacertsfile != null ) {
284- _certCollection = new X509Certificate2Collection ( new [ ] { PythonSsl . ReadCertificate ( context , cacertsfile ) } ) ;
274+ if ( sslcontext . _cafile != null ) {
275+ _cert = PythonSsl . ReadCertificate ( context , sslcontext . _cafile ) ;
285276 }
286277
287278 _socket = sock ;
288279
289280 EnsureSslStream ( false ) ;
290281
291- _protocol = protocol ;
282+ _protocol = sslcontext . protocol | sslcontext . options ;
292283 _validate = validate ;
293284 _context = context ;
294285 }
@@ -522,7 +513,7 @@ public object peer_certificate(bool binary_form) {
522513
523514 if ( peerCert != null ) {
524515 if ( binary_form ) {
525- return peerCert . GetRawCertData ( ) . MakeString ( ) ;
516+ return Bytes . Make ( peerCert . GetRawCertData ( ) ) ;
526517 } else if ( _validate ) {
527518 return CertificateToPython ( _context , peerCert ) ;
528519 }
@@ -549,24 +540,23 @@ public string issuer() {
549540 return String . Empty ;
550541 }
551542
552- [ Documentation ( @"read([len]) -> string
553-
554- Read up to len bytes from the SSL socket." ) ]
555- public object read ( CodeContext /*!*/ context , int len , ByteArray buffer = null ) {
543+ [ Documentation ( @"read(size, [buffer])
544+ Read up to size bytes from the SSL socket." ) ]
545+ public object read ( CodeContext /*!*/ context , int size , ByteArray buffer = null ) {
556546 EnsureSslStream ( true ) ;
557547
558548 try {
559549 byte [ ] buf = new byte [ 2048 ] ;
560- MemoryStream result = new MemoryStream ( len ) ;
550+ MemoryStream result = new MemoryStream ( size ) ;
561551 while ( true ) {
562- int readLength = ( len < buf . Length ) ? len : buf . Length ;
552+ int readLength = ( size < buf . Length ) ? size : buf . Length ;
563553 int bytes = _sslStream . Read ( buf , 0 , readLength ) ;
564554 if ( bytes > 0 ) {
565555 result . Write ( buf , 0 , bytes ) ;
566- len -= bytes ;
556+ size -= bytes ;
567557 }
568558
569- if ( bytes == 0 || len == 0 || bytes < readLength ) {
559+ if ( bytes == 0 || size == 0 || bytes < readLength ) {
570560 var res = result . ToArray ( ) ;
571561 if ( buffer == null )
572562 return Bytes . Make ( res ) ;
@@ -594,10 +584,9 @@ public string server() {
594584 return String . Empty ;
595585 }
596586
597- [ Documentation ( @"write(s) -> len
587+ [ Documentation ( @"Writes the bytes-like object b into the SSL object.
598588
599- Writes the string s into the SSL object. Returns the number
600- of bytes written." ) ]
589+ Returns the number of bytes written." ) ]
601590 public int write ( CodeContext /*!*/ context , Bytes data ) {
602591 EnsureSslStream ( true ) ;
603592
@@ -1124,8 +1113,10 @@ private static Exception ErrorDecoding(CodeContext context, params object[] args
11241113 public const int PROTOCOL_TLSv1_1 = 4 ;
11251114 public const int PROTOCOL_TLSv1_2 = 5 ;
11261115
1127- public const uint OP_ALL = 0x80000BFF ;
1128- public const uint OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00000800 ;
1116+ public const int OP_ALL = unchecked ( ( int ) 0x800003FF ) ;
1117+ public const int OP_CIPHER_SERVER_PREFERENCE = 0x400000 ;
1118+ public const int OP_SINGLE_DH_USE = 0x100000 ;
1119+ public const int OP_SINGLE_ECDH_USE = 0x80000 ;
11291120 public const int OP_NO_SSLv2 = 0x01000000 ;
11301121 public const int OP_NO_SSLv3 = 0x02000000 ;
11311122 public const int OP_NO_TLSv1 = 0x04000000 ;
0 commit comments