@@ -1519,6 +1519,76 @@ cipher_to_tuple(const SSL_CIPHER *cipher)
15191519 return NULL ;
15201520}
15211521
1522+ #if OPENSSL_VERSION_NUMBER >= 0x10002000UL
1523+ static PyObject *
1524+ cipher_to_dict (const SSL_CIPHER * cipher )
1525+ {
1526+ const char * cipher_name , * cipher_protocol ;
1527+
1528+ unsigned long cipher_id ;
1529+ int alg_bits , strength_bits , len ;
1530+ char buf [512 ] = {0 };
1531+ #if OPENSSL_VERSION_1_1
1532+ int aead , nid ;
1533+ const char * skcipher = NULL , * digest = NULL , * kx = NULL , * auth = NULL ;
1534+ #endif
1535+ PyObject * retval ;
1536+
1537+ retval = PyDict_New ();
1538+ if (retval == NULL ) {
1539+ goto error ;
1540+ }
1541+
1542+ /* can be NULL */
1543+ cipher_name = SSL_CIPHER_get_name (cipher );
1544+ cipher_protocol = SSL_CIPHER_get_version (cipher );
1545+ cipher_id = SSL_CIPHER_get_id (cipher );
1546+ SSL_CIPHER_description (cipher , buf , sizeof (buf ) - 1 );
1547+ len = strlen (buf );
1548+ if (len > 1 && buf [len - 1 ] == '\n' )
1549+ buf [len - 1 ] = '\0' ;
1550+ strength_bits = SSL_CIPHER_get_bits (cipher , & alg_bits );
1551+
1552+ #if OPENSSL_VERSION_1_1
1553+ aead = SSL_CIPHER_is_aead (cipher );
1554+ nid = SSL_CIPHER_get_cipher_nid (cipher );
1555+ skcipher = nid != NID_undef ? OBJ_nid2ln (nid ) : NULL ;
1556+ nid = SSL_CIPHER_get_digest_nid (cipher );
1557+ digest = nid != NID_undef ? OBJ_nid2ln (nid ) : NULL ;
1558+ nid = SSL_CIPHER_get_kx_nid (cipher );
1559+ kx = nid != NID_undef ? OBJ_nid2ln (nid ) : NULL ;
1560+ nid = SSL_CIPHER_get_auth_nid (cipher );
1561+ auth = nid != NID_undef ? OBJ_nid2ln (nid ) : NULL ;
1562+ #endif
1563+
1564+ retval = Py_BuildValue (
1565+ "{sksssssssisi"
1566+ #if OPENSSL_VERSION_1_1
1567+ "sOssssssss"
1568+ #endif
1569+ "}" ,
1570+ "id" , cipher_id ,
1571+ "name" , cipher_name ,
1572+ "protocol" , cipher_protocol ,
1573+ "description" , buf ,
1574+ "strength_bits" , strength_bits ,
1575+ "alg_bits" , alg_bits
1576+ #if OPENSSL_VERSION_1_1
1577+ ,"aead" , aead ? Py_True : Py_False ,
1578+ "symmetric" , skcipher ,
1579+ "digest" , digest ,
1580+ "kea" , kx ,
1581+ "auth" , auth
1582+ #endif
1583+ );
1584+ return retval ;
1585+
1586+ error :
1587+ Py_XDECREF (retval );
1588+ return NULL ;
1589+ }
1590+ #endif
1591+
15221592/*[clinic input]
15231593_ssl._SSLSocket.shared_ciphers
15241594[clinic start generated code]*/
@@ -2478,6 +2548,52 @@ _ssl__SSLContext_set_ciphers_impl(PySSLContext *self, const char *cipherlist)
24782548 Py_RETURN_NONE ;
24792549}
24802550
2551+ #if OPENSSL_VERSION_NUMBER >= 0x10002000UL
2552+ /*[clinic input]
2553+ _ssl._SSLContext.get_ciphers
2554+ [clinic start generated code]*/
2555+
2556+ static PyObject *
2557+ _ssl__SSLContext_get_ciphers_impl (PySSLContext * self )
2558+ /*[clinic end generated code: output=a56e4d68a406dfc4 input=a2aadc9af89b79c5]*/
2559+ {
2560+ SSL * ssl = NULL ;
2561+ STACK_OF (SSL_CIPHER ) * sk = NULL ;
2562+ SSL_CIPHER * cipher ;
2563+ int i = 0 ;
2564+ PyObject * result = NULL , * dct ;
2565+
2566+ ssl = SSL_new (self -> ctx );
2567+ if (ssl == NULL ) {
2568+ _setSSLError (NULL , 0 , __FILE__ , __LINE__ );
2569+ goto exit ;
2570+ }
2571+ sk = SSL_get_ciphers (ssl );
2572+
2573+ result = PyList_New (sk_SSL_CIPHER_num (sk ));
2574+ if (result == NULL ) {
2575+ goto exit ;
2576+ }
2577+
2578+ for (i = 0 ; i < sk_SSL_CIPHER_num (sk ); i ++ ) {
2579+ cipher = sk_SSL_CIPHER_value (sk , i );
2580+ dct = cipher_to_dict (cipher );
2581+ if (dct == NULL ) {
2582+ Py_CLEAR (result );
2583+ goto exit ;
2584+ }
2585+ PyList_SET_ITEM (result , i , dct );
2586+ }
2587+
2588+ exit :
2589+ if (ssl != NULL )
2590+ SSL_free (ssl );
2591+ return result ;
2592+
2593+ }
2594+ #endif
2595+
2596+
24812597#ifdef OPENSSL_NPN_NEGOTIATED
24822598static int
24832599do_protocol_selection (int alpn , unsigned char * * out , unsigned char * outlen ,
@@ -3645,6 +3761,7 @@ static struct PyMethodDef context_methods[] = {
36453761 _SSL__SSLCONTEXT_SET_SERVERNAME_CALLBACK_METHODDEF
36463762 _SSL__SSLCONTEXT_CERT_STORE_STATS_METHODDEF
36473763 _SSL__SSLCONTEXT_GET_CA_CERTS_METHODDEF
3764+ _SSL__SSLCONTEXT_GET_CIPHERS_METHODDEF
36483765 {NULL , NULL } /* sentinel */
36493766};
36503767
0 commit comments