zeep lib bad handshake error

I try to create SOAP client using zeep lilb
```
import os
from zeep import Client
from zeep.wsse.signature import Signature

key_filename = "/etc/ssl/certs/cert.key.pem"
cert_filename = "/etc/ssl/certs/cert.crt.pem"

client = Client('https://37.230.149.6:10004/emias-soap-service/PGUServicesInfo2?wsdl', wsse=Signature(key_filename, cert_filename))
```
And have this exception:
```
Traceback (most recent call last):
  File "/home/max/bot_project/Bots_Django/TelegramBot/bot/simple_soap_client.py", line 19, in <module>
    wsse=Signature(key_filename, cert_filename))
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/client.py", line 120, in __init__
    self.wsdl = Document(wsdl, self.transport, strict=strict)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/wsdl/wsdl.py", line 76, in __init__
    document = self._get_xml_document(location)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/wsdl/wsdl.py", line 137, in _get_xml_document
    location, self.transport, self.location, strict=self.strict)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/loader.py", line 66, in load_external
    content = transport.load(url)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/transports.py", line 111, in load
    content = self._load_remote_data(url)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/transports.py", line 126, in _load_remote_data
    response = self.session.get(url, timeout=self.load_timeout)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/sessions.py", line 501, in get
    return self.request('GET', url, **kwargs)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)
```
How can I fix this exception and what's wrong with my code?

I also try something like this:
```
import os
from requests import Session
from zeep import Client
from zeep.transports import Transport
from zeep.wsse.signature import Signature

key_filename = "/etc/ssl/certs/cert.key.pem"
cert_filename = "/etc/ssl/certs/cert.crt.pem"

session = Session()
session.verify = False
transport = Transport(session=session)

client = Client('https://37.230.149.6:10004/emias-soap-service/PGUServicesInfo2?wsdl',
                       , transport=transport,  wsse=Signature(key_filename, cert_filename))
```
But it doesn't solved my problem

So that second example should work. You're sure you got exactly the same error in both cases?

Either way: the core problem is that we can't validate the TLS certificate. Setting `verify` to `False` should fix that problem, so this is really a bug report on zeep to ask how to get that setting to apply in their library.

Yes, absolutely the same. But there is one thing when I try do this
`curl https://37.230.149.6:10004/emias-soap-service/PGUServicesInfo2?wsdl --cert /etc/ssl/certs/cert.crt.pem --key /etc/ssl/certs/cert.key.pem`
I get this message:
```
 curl: (60) server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.
```


Yes, this is curl telling you to do the same thing that I just told you to do: disable verification. Setting `verify` to `False` is how you do that in Requests, and you say that that didn't help: that means that zeep must be ignoring or controlling that setting somehow. You need to take that up with them.

About bug report to zeep, they replied me

> 
See http://docs.python-zeep.org/en/master/transport.html#transports (the verify option). If that doesn't solve it then perhaps the requests docs have more info. Basically zeep uses requests for the http communication with the server
> 

Yup, so that code demonstrates the same thing as you showed. That is exactly how you disable cert validation. Can you please show me the traceback your *second* example produces?

```
Traceback (most recent call last):
  File "/home/max/bot_project/Bots_Django/TelegramBot/bot/simple_soap_client.py", line 19, in <module>
    wsse=Signature(key_filename, cert_filename), transport=transport)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/client.py", line 120, in __init__
    self.wsdl = Document(wsdl, self.transport, strict=strict)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/wsdl/wsdl.py", line 76, in __init__
    document = self._get_xml_document(location)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/wsdl/wsdl.py", line 137, in _get_xml_document
    location, self.transport, self.location, strict=self.strict)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/loader.py", line 66, in load_external
    content = transport.load(url)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/transports.py", line 111, in load
    content = self._load_remote_data(url)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/zeep/transports.py", line 126, in _load_remote_data
    response = self.session.get(url, timeout=self.load_timeout)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/sessions.py", line 501, in get
    return self.request('GET', url, **kwargs)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_read_bytes', 'sslv3 alert handshake failure')],)",)
```

So, that is *not* the exact same error: that error is different. :) Specifically, it's telling you that at this point the remote server is erroring out about some part of the handshake. This is likely because the remote server has incompatible TLS settings.

The only way I can help debug that at this point is to see a packet capture from the connection, captured using a tool like Wireshark or tcpdump. Are you familiar with either tool?

No I don't:( If I'll do something like this:
 `openssl s_client -connect 37.230.149.6:10004 -cert /etc/ssl/certs/cert.crt.pem -key /etc/ssl/certs/cert.key.pem`
Does this help me?

The output of that would certainly be very helpful.

Is it confidential information? Can I place it here? 


It should not be confidential information, no. If it is, I can edit your comment and will remove it.

Ok here it is:
```
CONNECTED(00000003)
depth=0 C = RU, ST = RU, CN = TST.MPGU
verify error:num=18:self signed certificate
verify return:1
depth=0 C = RU, ST = RU, CN = TST.MPGU
verify return:1
---
Certificate chain
 0 s:/C=RU/ST=RU/CN=TST.MPGU
   i:/C=RU/ST=RU/CN=TST.MPGU
---
Server certificate
-----BEGIN CERTIFICATE-----
MIICczCCAdygAwIBAgIIertkcbUl3AEwDQYJKoZIhvcNAQEFBQAwLTELMAkGA1UE
BhMCUlUxCzAJBgNVBAgTAlJVMREwDwYDVQQDEwhUU1QuTVBHVTAeFw0xNjA1MTMx
MzEyMDdaFw0yNjA1MTExMzEyMDdaMC0xCzAJBgNVBAYTAlJVMQswCQYDVQQIEwJS
VTERMA8GA1UEAxMIVFNULk1QR1UwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
AK9apLncyd3UKWrfTQUOZjMBa7M+ZKTgsNkeT4u8+dv0uWwJrYtGlQRa7Z2l1eMC
OKt9M8DCZ+9UskHZ7PStBNbCIBsVCC2G6ohNMWtv1wN0WWM23934/w2rzMzDeb1i
H0o41kHiwUBOmro+6PDHOg9mycY8Ci20vTj7v7nijWGtAgMBAAGjgZswgZgwDAYD
VR0TBAUwAwEB/zAdBgNVHQ4EFgQU8sAoYxenXmdHScV2xcK4R5SYusIwXAYDVR0j
BFUwU4AU8sAoYxenXmdHScV2xcK4R5SYusKhMaQvMC0xCzAJBgNVBAYTAlJVMQsw
CQYDVQQIEwJSVTERMA8GA1UEAxMIVFNULk1QR1WCCHq7ZHG1JdwBMAsGA1UdDwQE
AwICvDANBgkqhkiG9w0BAQUFAAOBgQCUQ8kzsOrItNMVoqDpVflDhshoLL9UN7IA
/dzQy0rlrt40vAmwhrLu3qaSOwKJZYzqXCGhnBudU60iAYOUYqxIx0Ea2H7PmYYH
VoYM3iPEhCE+9TMDi9BZGDOH4KHewHiHOJ1qBskDaMyLwc+NZCDykUqRIvSuhUmw
bBEk2NE7PQ==
-----END CERTIFICATE-----
subject=/C=RU/ST=RU/CN=TST.MPGU
issuer=/C=RU/ST=RU/CN=TST.MPGU
---
No client certificate CA names sent
Client Certificate Types: RSA sign, DSA sign
Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:RSA+SHA384:DSA+SHA384:RSA+SHA256:DSA+SHA256:RSA+SHA224:DSA+SHA224:RSA+SHA1:DSA+SHA1:RSA+MD5
Shared Requested Signature Algorithms: RSA+SHA512:DSA+SHA512:RSA+SHA384:DSA+SHA384:RSA+SHA256:DSA+SHA256:RSA+SHA224:DSA+SHA224:RSA+SHA1:DSA+SHA1
---
SSL handshake has read 825 bytes and written 1416 bytes
---
New, TLSv1/SSLv3, Cipher is AES256-GCM-SHA384
Server public key is 1024 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : AES256-GCM-SHA384
    Session-ID: 5D9660F74AF22F3583C850702A24E4059B48594D6003D87FED6F9F4B67A68848
    Session-ID-ctx: 
    Master-Key: 38953C1D2A52B36665A009B40AB906E773ABC924F0DE2C54E0D837E1012749500C4980A63CACE1A7C09814D16ECBDE2D
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1490280114
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
```

Hrm. Those TLS settings largely seem to be ok. I wonder if you're not sending your client cert properly. :(

Can I also ask what system you're running on?

Linux max12 4.4.0-64-generic #85-Ubuntu SMP Mon Feb 20 11:50:30 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux


Ok, so that OpenSSL should be representative of what's actually being used. Hrm.

We definitely need to be able to see the handshake here, I'm afraid, because everything seems fine.

I generate my ssl cert and key:
```
openssl pkcs12 -in testSSLClient.p12 -out cert.crt.pem -clcerts -nokeys
openssl pkcs12 -in testSSLClient.p12 -out cert.key.pem -nodes -nocerts
```

testSSLClient.p12 has password and I know it's OK
But I have RootMedCA.cer and I don't how can I used it?

You could try doing `cat cert.crt.pem RootMedCA.cer > cert.crt.pem` and see if that helps.

Yes, my cert.crt.pem already contains RootMedCA.cer. 

And now I have no idea how can I fix it :( 

Yeah, I'm really uncertain either. :( It doesn't seem like there's any specific problem other than the server not liking what you're sending. Without seeing the handshake, again, I'm not sure.

Ok, thanks you!:)

Sorry I couldn't be more help!

Hi, I have some more information about my problem. What do you think about it?

http://docs.python-requests.org/en/master/user/advanced/#ssl-cert-verification
When I try this:
```
import os
import requests
from requests import Session

key_filename = "/etc/ssl/certs/cert.key.pem"
cert_filename = "/etc/ssl/certs/cert.crt.pem"
session = Session()
session.verify = False

r = requests.get('https://37.230.149.6:10004/emias-soap-service/PGUServicesInfo2?wsdl',
                 cert=(cert_filename, key_filename))
print r
```
I have this Error:
```
Traceback (most recent call last):
  File "/home/max/bot_project/Bots_Django/TelegramBot/bot/simple_soap_client.py", line 17, in <module>
    cert=(cert_filename, key_filename))
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/adapters.py", line 497, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",)
```

But if I use this:

```
import os
import requests

key_filename = "/etc/ssl/certs/cert.key.pem"
cert_filename = "/etc/ssl/certs/cert.crt.pem"

r = requests.get('https://37.230.149.6:10004/emias-soap-service/PGUServicesInfo2?wsdl',
                 cert=(cert_filename, key_filename), verify=False)
print r
```
I have this... seems like OK

```
/home/max/bot_project/Bots_Django/venv/local/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py:852: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  InsecureRequestWarning)
<Response [200]>
```

I think, when I use code:

```
import os
from requests import Session
from zeep import Client
from zeep.transports import Transport
from zeep.wsse.signature import Signature

key_filename = "/etc/ssl/certs/cert.key.pem"
cert_filename = "/etc/ssl/certs/cert.crt.pem"

session = Session()
session.verify = False
transport = Transport(session=session)

client = Client('https://37.230.149.6:10004/emias-soap-service/PGUServicesInfo2?wsdl',
                       , transport=transport,  wsse=Signature(key_filename, cert_filename))
```
This the same error.

Your code in your first example was wrong. You have to change it to this:

```python
import os
import requests
from requests import Session

key_filename = "/etc/ssl/certs/cert.key.pem"
cert_filename = "/etc/ssl/certs/cert.crt.pem"
session = Session()
session.verify = False

r = session.get('https://37.230.149.6:10004/emias-soap-service/PGUServicesInfo2?wsdl',
                 cert=(cert_filename, key_filename))
print r
```

Note that I changed `requests.get` to `session.get`.

Sorry, my bad! It was my last hope...Can you advice me any SOAP client with ssl, not zeep and suds?