@@ -321,6 +321,25 @@ typedef struct {
321321 PySSLContext * ctx ;
322322} PySSLSession ;
323323
324+ <<<<<<< HEAD
325+ || || || | parent of 27501 a5ce86 (Work on trust store )
326+ static PyTypeObject * PySSLContext_Type ;
327+ static PyTypeObject * PySSLSocket_Type ;
328+ static PyTypeObject * PySSLMemoryBIO_Type ;
329+ static PyTypeObject * PySSLSession_Type ;
330+ static PyTypeObject * PySSLPrivateKey_Type ;
331+ static PyTypeObject * PySSLCertificate_Type ;
332+
333+ = == == ==
334+ static PyTypeObject * PySSLContext_Type ;
335+ static PyTypeObject * PySSLSocket_Type ;
336+ static PyTypeObject * PySSLMemoryBIO_Type ;
337+ static PyTypeObject * PySSLSession_Type ;
338+ static PyTypeObject * PySSLPrivateKey_Type ;
339+ static PyTypeObject * PySSLCertificate_Type ;
340+ static PyTypeObject * PySSLTrustStore_Type ;
341+
342+ >>>>>>> 27501 a5ce86 (Work on trust store )
324343static inline _PySSLError _PySSL_errno (int failed , const SSL * ssl , int retcode )
325344{
326345 _PySSLError err = { 0 };
@@ -1692,6 +1711,11 @@ _certificate_to_der(_sslmodulestate *state, X509 *certificate)
16921711 return retval ;
16931712}
16941713
1714+ #include "_ssl/misc.c"
1715+ #include "_ssl/cert.c"
1716+ #include "_ssl/pkey.c"
1717+ #include "_ssl/truststore.c"
1718+
16951719/*[clinic input]
16961720_ssl._test_decode_cert
16971721 path: object(converter="PyUnicode_FSConverter")
@@ -1784,6 +1808,26 @@ _ssl__SSLSocket_getpeercert_impl(PySSLSocket *self, int binary_mode)
17841808 return result ;
17851809}
17861810
1811+ #if OPENSSL_VERSION_1_1
1812+ /*[clinic input]
1813+ _ssl._SSLSocket.verified_chain
1814+
1815+ [clinic start generated code]*/
1816+
1817+ static PyObject *
1818+ _ssl__SSLSocket_verified_chain_impl (PySSLSocket * self )
1819+ /*[clinic end generated code: output=3068b09c06b0a1eb input=d49eda1fa8963989]*/
1820+ {
1821+ STACK_OF (X509 ) * chain ;
1822+ /* borrowed reference */
1823+ chain = SSL_get0_verified_chain (self -> ssl );
1824+ if (chain == NULL ) {
1825+ Py_RETURN_NONE ;
1826+ }
1827+ return _PySSL_CertificateFromX509Stack (chain , 1 );
1828+ }
1829+ #endif
1830+
17871831static PyObject *
17881832cipher_to_tuple (const SSL_CIPHER * cipher )
17891833{
@@ -2799,6 +2843,7 @@ static PyMethodDef PySSLMethods[] = {
27992843 _SSL__SSLSOCKET_COMPRESSION_METHODDEF
28002844 _SSL__SSLSOCKET_SHUTDOWN_METHODDEF
28012845 _SSL__SSLSOCKET_VERIFY_CLIENT_POST_HANDSHAKE_METHODDEF
2846+ _SSL__SSLSOCKET_VERIFIED_CHAIN_METHODDEF
28022847 {NULL , NULL }
28032848};
28042849
@@ -3521,9 +3566,9 @@ typedef struct {
35213566 int error ;
35223567} _PySSLPasswordInfo ;
35233568
3524- static int
3525- _pwinfo_set ( _PySSLPasswordInfo * pw_info , PyObject * password ,
3526- const char * bad_type_error )
3569+ int
3570+ PySSL_pwinfo_set ( PySSLPasswordInfo * pw_info , PyObject * password ,
3571+ const char * bad_type_error )
35273572{
35283573 /* Set the password and size fields of a _PySSLPasswordInfo struct
35293574 from a unicode, bytes, or byte array object.
@@ -3575,13 +3620,14 @@ _pwinfo_set(_PySSLPasswordInfo *pw_info, PyObject* password,
35753620 return 0 ;
35763621}
35773622
3578- static int
3579- _password_callback (char * buf , int size , int rwflag , void * userdata )
3623+ int
3624+ PySSL_password_cb (char * buf , int size , int rwflag , void * userdata )
35803625{
3581- _PySSLPasswordInfo * pw_info = (_PySSLPasswordInfo * ) userdata ;
3626+ PySSLPasswordInfo * pw_info = (PySSLPasswordInfo * ) userdata ;
35823627 PyObject * fn_ret = NULL ;
35833628
35843629 PySSL_END_ALLOW_THREADS_S (pw_info -> thread_state );
3630+ assert (pw_info );
35853631
35863632 if (pw_info -> error ) {
35873633 /* already failed previously. OpenSSL 3.0.0-alpha14 invokes the
@@ -3598,7 +3644,7 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
35983644 goto error ;
35993645 }
36003646
3601- if (!_pwinfo_set (pw_info , fn_ret ,
3647+ if (!PySSL_pwinfo_set (pw_info , fn_ret ,
36023648 "password callback must return a string" )) {
36033649 goto error ;
36043650 }
@@ -3622,6 +3668,105 @@ _password_callback(char *buf, int size, int rwflag, void *userdata)
36223668 return -1 ;
36233669}
36243670
3671+
3672+ static PyObject *
3673+ _load_cert_privkey (PySSLContext * self , PyObject * certs , PyObject * key )
3674+ {
3675+ PyObject * seq = NULL ;
3676+ Py_ssize_t i ;
3677+ int ret ;
3678+
3679+ /* Let's start picky and only accept tuples */
3680+ if (!PyTuple_Check (certs )) {
3681+ PyErr_Format (
3682+ PyExc_TypeError ,
3683+ "Expected a tuple of Certificates, got '%.200s'." ,
3684+ Py_TYPE (certs )-> tp_name
3685+ );
3686+ return NULL ;
3687+ }
3688+ if (Py_TYPE (key ) != PySSLPrivateKey_Type ) {
3689+ PyErr_Format (
3690+ PyExc_TypeError ,
3691+ "Expected PrivateKey, got '%.200s'." ,
3692+ Py_TYPE (key )-> tp_name
3693+ );
3694+ return NULL ;
3695+ }
3696+
3697+ seq = PySequence_Fast (certs , "expected a tuple of Certificates" );
3698+ if (seq == NULL )
3699+ return NULL ;
3700+ if (PySequence_Fast_GET_SIZE (seq ) == 0 ) {
3701+ PyErr_SetString (PyExc_ValueError , "cert list is empty" );
3702+ goto error ;
3703+ }
3704+
3705+ /* validate certs */
3706+ for (i = 0 ; i < PySequence_Fast_GET_SIZE (seq ); i ++ ) {
3707+ PyObject * ob = PySequence_Fast_GET_ITEM (seq , i );
3708+ if (ob == NULL ) {
3709+ goto error ;
3710+ }
3711+ if (Py_TYPE (ob ) != PySSLCertificate_Type ) {
3712+ PyErr_Format (
3713+ PyExc_TypeError ,
3714+ "Expected Certificate, got '%.200s'." ,
3715+ Py_TYPE (ob )-> tp_name
3716+ );
3717+ goto error ;
3718+ }
3719+ }
3720+ /* add certs */
3721+ for (i = 0 ; i < PySequence_Fast_GET_SIZE (seq ); i ++ ) {
3722+ /* borrowed reference */
3723+ PySSLCertificate * cert = (PySSLCertificate * )PySequence_Fast_GET_ITEM (seq , i );
3724+ if (cert == NULL ) {
3725+ goto error ;
3726+ }
3727+ if (i == 0 ) {
3728+ PySSL_BEGIN_ALLOW_THREADS
3729+ ret = SSL_CTX_use_certificate (self -> ctx , cert -> cert );
3730+ PySSL_END_ALLOW_THREADS
3731+ if (ERR_peek_error () != 0 ) {
3732+ _setSSLError (NULL , 0 , __FILE__ , __LINE__ );
3733+ goto error ;
3734+ }
3735+ ret = SSL_CTX_clear_chain_certs (self -> ctx );
3736+ if (ret == 0 ) {
3737+ _setSSLError (NULL , 0 , __FILE__ , __LINE__ );
3738+ goto error ;
3739+ }
3740+ }
3741+ else {
3742+ /* certs 1..n are chain certs */
3743+ PySSL_BEGIN_ALLOW_THREADS
3744+ ret = SSL_CTX_add1_chain_cert (self -> ctx , cert -> cert );
3745+ PySSL_END_ALLOW_THREADS
3746+ if (ret == 0 ) {
3747+ _setSSLError (NULL , 0 , __FILE__ , __LINE__ );
3748+ goto error ;
3749+ }
3750+ }
3751+ }
3752+ /* add and verify private key */
3753+ PySSL_BEGIN_ALLOW_THREADS
3754+ ret = SSL_CTX_use_PrivateKey (self -> ctx , ((PySSLPrivateKey * )key )-> pkey );
3755+ if (ret == 1 ) {
3756+ /* OK, now match key to cert */
3757+ ret = SSL_CTX_check_private_key (self -> ctx );
3758+ }
3759+ PySSL_END_ALLOW_THREADS
3760+ if (ret != 1 ) {
3761+ _setSSLError (NULL , 0 , __FILE__ , __LINE__ );
3762+ goto error ;
3763+ }
3764+ Py_RETURN_NONE ;
3765+ error :
3766+ Py_DECREF (seq );
3767+ return NULL ;
3768+ }
3769+
36253770/*[clinic input]
36263771_ssl._SSLContext.load_cert_chain
36273772 certfile: object
@@ -3638,13 +3783,21 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
36383783 PyObject * certfile_bytes = NULL , * keyfile_bytes = NULL ;
36393784 pem_password_cb * orig_passwd_cb = SSL_CTX_get_default_passwd_cb (self -> ctx );
36403785 void * orig_passwd_userdata = SSL_CTX_get_default_passwd_cb_userdata (self -> ctx );
3641- _PySSLPasswordInfo pw_info = { NULL , NULL , NULL , 0 , 0 };
3786+ PySSLPasswordInfo pw_info = { NULL , NULL , NULL , 0 , 0 };
36423787 int r ;
36433788
36443789 errno = 0 ;
36453790 ERR_clear_error ();
36463791 if (keyfile == Py_None )
36473792 keyfile = NULL ;
3793+ if ((keyfile != NULL ) && (Py_TYPE (keyfile ) == PySSLPrivateKey_Type )) {
3794+ if (password && password != Py_None ) {
3795+ PyErr_SetString (PyExc_ValueError ,
3796+ "Cannot use password arg with PrivateKey" );
3797+ return NULL ;
3798+ }
3799+ return _load_cert_privkey (self , certfile , keyfile );
3800+ }
36483801 if (!PyUnicode_FSConverter (certfile , & certfile_bytes )) {
36493802 if (PyErr_ExceptionMatches (PyExc_TypeError )) {
36503803 PyErr_SetString (PyExc_TypeError ,
@@ -3662,11 +3815,11 @@ _ssl__SSLContext_load_cert_chain_impl(PySSLContext *self, PyObject *certfile,
36623815 if (password != Py_None ) {
36633816 if (PyCallable_Check (password )) {
36643817 pw_info .callable = password ;
3665- } else if (!_pwinfo_set (& pw_info , password ,
3818+ } else if (!PySSL_pwinfo_set (& pw_info , password ,
36663819 "password should be a string or callable" )) {
36673820 goto error ;
36683821 }
3669- SSL_CTX_set_default_passwd_cb (self -> ctx , _password_callback );
3822+ SSL_CTX_set_default_passwd_cb (self -> ctx , PySSL_password_cb );
36703823 SSL_CTX_set_default_passwd_cb_userdata (self -> ctx , & pw_info );
36713824 }
36723825 PySSL_BEGIN_ALLOW_THREADS_S (pw_info .thread_state );
@@ -3831,6 +3984,7 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self,
38313984/*[clinic end generated code: output=454c7e41230ca551 input=42ecfe258233e194]*/
38323985{
38333986 PyObject * cafile_bytes = NULL , * capath_bytes = NULL ;
3987+ PyObject * seq = NULL ;
38343988 const char * cafile_buf = NULL , * capath_buf = NULL ;
38353989 int r = 0 , ok = 1 ;
38363990
@@ -3899,6 +4053,48 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self,
38994053 goto error ;
39004054 }
39014055 }
4056+ else if (PyList_Check (cadata )) {
4057+ /* List of Certificates instances */
4058+ X509_STORE * store ;
4059+ Py_ssize_t i ;
4060+
4061+ seq = PySequence_Fast (cadata , "expected a tuple of Certificates" );
4062+ if (seq == NULL )
4063+ goto error ;
4064+ if (PySequence_Fast_GET_SIZE (seq ) == 0 ) {
4065+ PyErr_SetString (PyExc_ValueError ,
4066+ "cadata certificate list is empty" );
4067+ goto error ;
4068+ }
4069+ store = SSL_CTX_get_cert_store (self -> ctx );
4070+ /* validate and add certs */
4071+ for (i = 0 ; i < PySequence_Fast_GET_SIZE (seq ); i ++ ) {
4072+ PySSLCertificate * ob = (PySSLCertificate * )PySequence_Fast_GET_ITEM (seq , i );
4073+ if (ob == NULL ) {
4074+ goto error ;
4075+ }
4076+ if (Py_TYPE (ob ) != PySSLCertificate_Type ) {
4077+ PyErr_Format (
4078+ PyExc_TypeError ,
4079+ "Expected Certificate in cadata, got '%.200s'." ,
4080+ Py_TYPE (ob )-> tp_name
4081+ );
4082+ goto error ;
4083+ }
4084+ r = X509_STORE_add_cert (store , ob -> cert );
4085+ if (!r ) {
4086+ int err = ERR_peek_last_error ();
4087+ if ((ERR_GET_LIB (err ) == ERR_LIB_X509 ) &&
4088+ (ERR_GET_REASON (err ) == X509_R_CERT_ALREADY_IN_HASH_TABLE )) {
4089+ /* cert already in hash table, not an error */
4090+ ERR_clear_error ();
4091+ } else {
4092+ _setSSLError (NULL , 0 , __FILE__ , __LINE__ );
4093+ goto error ;
4094+ }
4095+ }
4096+ }
4097+ }
39024098 else {
39034099 invalid_cadata :
39044100 PyErr_SetString (PyExc_TypeError ,
@@ -3935,6 +4131,7 @@ _ssl__SSLContext_load_verify_locations_impl(PySSLContext *self,
39354131 end :
39364132 Py_XDECREF (cafile_bytes );
39374133 Py_XDECREF (capath_bytes );
4134+ Py_XDECREF (seq );
39384135 if (ok ) {
39394136 Py_RETURN_NONE ;
39404137 } else {
0 commit comments