@@ -1998,24 +1998,44 @@ static PyObject *
19981998_ssl__SSLSocket_shared_ciphers_impl (PySSLSocket * self )
19991999/*[clinic end generated code: output=3d174ead2e42c4fd input=0bfe149da8fe6306]*/
20002000{
2001- STACK_OF (SSL_CIPHER ) * ciphers ;
2002- int i ;
2001+ STACK_OF (SSL_CIPHER ) * server_ciphers ;
2002+ STACK_OF (SSL_CIPHER ) * client_ciphers ;
2003+ int i , len ;
20032004 PyObject * res ;
2005+ const SSL_CIPHER * cipher ;
2006+
2007+ /* Rather than use SSL_get_shared_ciphers, we use an equivalent algorithm because:
2008+
2009+ 1) It returns a colon seperated list of strings, in an undefined
2010+ order, that we would have to post process back into tuples.
2011+ 2) It will return a truncated string with no indication that it has
2012+ done so, if the buffer is too small.
2013+ */
20042014
2005- ciphers = SSL_get_ciphers (self -> ssl );
2006- if (!ciphers )
2015+ server_ciphers = SSL_get_ciphers (self -> ssl );
2016+ if (!server_ciphers )
20072017 Py_RETURN_NONE ;
2008- res = PyList_New (sk_SSL_CIPHER_num (ciphers ));
2018+ client_ciphers = SSL_get_client_ciphers (self -> ssl );
2019+ if (!client_ciphers )
2020+ Py_RETURN_NONE ;
2021+
2022+ res = PyList_New (sk_SSL_CIPHER_num (server_ciphers ));
20092023 if (!res )
20102024 return NULL ;
2011- for (i = 0 ; i < sk_SSL_CIPHER_num (ciphers ); i ++ ) {
2012- PyObject * tup = cipher_to_tuple (sk_SSL_CIPHER_value (ciphers , i ));
2025+ len = 0 ;
2026+ for (i = 0 ; i < sk_SSL_CIPHER_num (server_ciphers ); i ++ ) {
2027+ cipher = sk_SSL_CIPHER_value (server_ciphers , i );
2028+ if (sk_SSL_CIPHER_find (client_ciphers , cipher ) < 0 )
2029+ continue ;
2030+
2031+ PyObject * tup = cipher_to_tuple (cipher );
20132032 if (!tup ) {
20142033 Py_DECREF (res );
20152034 return NULL ;
20162035 }
2017- PyList_SET_ITEM (res , i , tup );
2036+ PyList_SET_ITEM (res , len ++ , tup );
20182037 }
2038+ Py_SET_SIZE (res , len );
20192039 return res ;
20202040}
20212041
0 commit comments