@@ -1161,6 +1161,69 @@ mod _ssl {
11611161 . map ( cipher_to_tuple)
11621162 }
11631163
1164+ #[ pymethod]
1165+ fn shared_ciphers ( & self , vm : & VirtualMachine ) -> Option < PyListRef > {
1166+ #[ cfg( ossl110) ]
1167+ {
1168+ let stream = self . stream . read ( ) ;
1169+ unsafe {
1170+ let server_ciphers = SSL_get_ciphers ( stream. ssl ( ) . as_ptr ( ) ) ;
1171+ if server_ciphers. is_null ( ) {
1172+ return None ;
1173+ }
1174+
1175+ let client_ciphers = SSL_get_client_ciphers ( stream. ssl ( ) . as_ptr ( ) ) ;
1176+ if client_ciphers. is_null ( ) {
1177+ return None ;
1178+ }
1179+
1180+ let mut result = Vec :: new ( ) ;
1181+ let num_server = sys:: OPENSSL_sk_num ( server_ciphers as * const _ ) ;
1182+ let num_client = sys:: OPENSSL_sk_num ( client_ciphers as * const _ ) ;
1183+
1184+ for i in 0 ..num_server {
1185+ let server_cipher_ptr = sys:: OPENSSL_sk_value ( server_ciphers as * const _ , i)
1186+ as * const sys:: SSL_CIPHER ;
1187+
1188+ // Check if client supports this cipher by comparing pointers
1189+ let mut found = false ;
1190+ for j in 0 ..num_client {
1191+ let client_cipher_ptr =
1192+ sys:: OPENSSL_sk_value ( client_ciphers as * const _ , j)
1193+ as * const sys:: SSL_CIPHER ;
1194+
1195+ if server_cipher_ptr == client_cipher_ptr {
1196+ found = true ;
1197+ break ;
1198+ }
1199+ }
1200+
1201+ if found {
1202+ let cipher = ssl:: SslCipherRef :: from_ptr ( server_cipher_ptr as * mut _ ) ;
1203+ let ( name, version, bits) = cipher_to_tuple ( cipher) ;
1204+ let tuple = vm. new_tuple ( (
1205+ vm. ctx . new_str ( name) ,
1206+ vm. ctx . new_str ( version) ,
1207+ vm. ctx . new_int ( bits) ,
1208+ ) ) ;
1209+ result. push ( tuple. into ( ) ) ;
1210+ }
1211+ }
1212+
1213+ if result. is_empty ( ) {
1214+ None
1215+ } else {
1216+ Some ( vm. ctx . new_list ( result) )
1217+ }
1218+ }
1219+ }
1220+ #[ cfg( not( ossl110) ) ]
1221+ {
1222+ let _ = vm;
1223+ None
1224+ }
1225+ }
1226+
11641227 #[ pymethod]
11651228 fn selected_alpn_protocol ( & self ) -> Option < String > {
11661229 #[ cfg( ossl102) ]
@@ -1536,6 +1599,16 @@ mod _ssl {
15361599 unsafe impl Send for PySslMemoryBio { }
15371600 unsafe impl Sync for PySslMemoryBio { }
15381601
1602+ // OpenSSL functions not in openssl-sys
1603+ unsafe extern "C" {
1604+ fn SSL_get_ciphers ( ssl : * const sys:: SSL ) -> * const sys:: stack_st_SSL_CIPHER ;
1605+ }
1606+
1607+ #[ cfg( ossl110) ]
1608+ unsafe extern "C" {
1609+ fn SSL_get_client_ciphers ( ssl : * const sys:: SSL ) -> * const sys:: stack_st_SSL_CIPHER ;
1610+ }
1611+
15391612 // OpenSSL BIO helper functions
15401613 // These are typically macros in OpenSSL, implemented via BIO_ctrl
15411614 const BIO_CTRL_PENDING : libc:: c_int = 10 ;
0 commit comments