Now libcurl (built with OpenSSL) doesn't return error anymore if the remote
SSL-based server doesn't present a certificate when the request is told to ignore certificate verification anyway.
This commit is contained in:
parent
a1772ca406
commit
2be50baf97
4
CHANGES
4
CHANGES
@ -8,6 +8,10 @@
|
|||||||
|
|
||||||
|
|
||||||
Daniel S (3 Dec 2007)
|
Daniel S (3 Dec 2007)
|
||||||
|
- Now libcurl (built with OpenSSL) doesn't return error anymore if the remote
|
||||||
|
SSL-based server doesn't present a certificate when the request is told to
|
||||||
|
ignore certificate verification anyway.
|
||||||
|
|
||||||
- Michal Marek introduced CURLOPT_PROXY_TRANSFER_MODE which is used to control
|
- Michal Marek introduced CURLOPT_PROXY_TRANSFER_MODE which is used to control
|
||||||
the appending of the "type=" thing on FTP URLs when they are passed to a
|
the appending of the "type=" thing on FTP URLs when they are passed to a
|
||||||
HTTP proxy. Some proxies just don't like that appending (which is done
|
HTTP proxy. Some proxies just don't like that appending (which is done
|
||||||
|
183
lib/ssluse.c
183
lib/ssluse.c
@ -1569,14 +1569,105 @@ Curl_ossl_connect_step2(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode
|
/*
|
||||||
Curl_ossl_connect_step3(struct connectdata *conn,
|
* Get the server cert, verify it and show it etc, only call failf() if the
|
||||||
int sockindex)
|
* 'strict' argument is TRUE as otherwise all this is for informational
|
||||||
|
* purposes only!
|
||||||
|
*
|
||||||
|
* We check certificates to authenticate the server; otherwise we risk
|
||||||
|
* man-in-the-middle attack.
|
||||||
|
*/
|
||||||
|
static CURLcode servercert(struct connectdata *conn,
|
||||||
|
struct ssl_connect_data *connssl,
|
||||||
|
bool strict)
|
||||||
{
|
{
|
||||||
CURLcode retcode = CURLE_OK;
|
CURLcode retcode;
|
||||||
char * str;
|
char *str;
|
||||||
long lerr;
|
long lerr;
|
||||||
ASN1_TIME *certdate;
|
ASN1_TIME *certdate;
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
|
||||||
|
if(!connssl->server_cert) {
|
||||||
|
if(strict)
|
||||||
|
failf(data, "SSL: couldn't get peer certificate!");
|
||||||
|
return CURLE_PEER_FAILED_VERIFICATION;
|
||||||
|
}
|
||||||
|
infof (data, "Server certificate:\n");
|
||||||
|
|
||||||
|
str = X509_NAME_oneline(X509_get_subject_name(connssl->server_cert),
|
||||||
|
NULL, 0);
|
||||||
|
if(!str) {
|
||||||
|
if(strict)
|
||||||
|
failf(data, "SSL: couldn't get X509-subject!");
|
||||||
|
X509_free(connssl->server_cert);
|
||||||
|
connssl->server_cert = NULL;
|
||||||
|
return CURLE_SSL_CONNECT_ERROR;
|
||||||
|
}
|
||||||
|
infof(data, "\t subject: %s\n", str);
|
||||||
|
CRYPTO_free(str);
|
||||||
|
|
||||||
|
certdate = X509_get_notBefore(connssl->server_cert);
|
||||||
|
Curl_ASN1_UTCTIME_output(conn, "\t start date: ", certdate);
|
||||||
|
|
||||||
|
certdate = X509_get_notAfter(connssl->server_cert);
|
||||||
|
Curl_ASN1_UTCTIME_output(conn, "\t expire date: ", certdate);
|
||||||
|
|
||||||
|
if(data->set.ssl.verifyhost) {
|
||||||
|
retcode = verifyhost(conn, connssl->server_cert);
|
||||||
|
if(retcode) {
|
||||||
|
X509_free(connssl->server_cert);
|
||||||
|
connssl->server_cert = NULL;
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str = X509_NAME_oneline(X509_get_issuer_name(connssl->server_cert),
|
||||||
|
NULL, 0);
|
||||||
|
if(!str) {
|
||||||
|
if(strict)
|
||||||
|
failf(data, "SSL: couldn't get X509-issuer name!");
|
||||||
|
retcode = CURLE_SSL_CONNECT_ERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
infof(data, "\t issuer: %s\n", str);
|
||||||
|
CRYPTO_free(str);
|
||||||
|
|
||||||
|
/* We could do all sorts of certificate verification stuff here before
|
||||||
|
deallocating the certificate. */
|
||||||
|
|
||||||
|
lerr = data->set.ssl.certverifyresult=
|
||||||
|
SSL_get_verify_result(connssl->handle);
|
||||||
|
if(data->set.ssl.certverifyresult != X509_V_OK) {
|
||||||
|
if(data->set.ssl.verifypeer) {
|
||||||
|
/* We probably never reach this, because SSL_connect() will fail
|
||||||
|
and we return earlyer if verifypeer is set? */
|
||||||
|
if(strict)
|
||||||
|
failf(data, "SSL certificate verify result: %s (%ld)",
|
||||||
|
X509_verify_cert_error_string(lerr), lerr);
|
||||||
|
retcode = CURLE_PEER_FAILED_VERIFICATION;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
infof(data, "SSL certificate verify result: %s (%ld),"
|
||||||
|
" continuing anyway.\n",
|
||||||
|
X509_verify_cert_error_string(lerr), lerr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
infof(data, "SSL certificate verify ok.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_free(connssl->server_cert);
|
||||||
|
connssl->server_cert = NULL;
|
||||||
|
connssl->connecting_state = ssl_connect_done;
|
||||||
|
|
||||||
|
return retcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static CURLcode
|
||||||
|
Curl_ossl_connect_step3(struct connectdata *conn,
|
||||||
|
int sockindex)
|
||||||
|
{
|
||||||
|
CURLcode retcode = CURLE_OK;
|
||||||
void *ssl_sessionid=NULL;
|
void *ssl_sessionid=NULL;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
|
||||||
@ -1615,80 +1706,20 @@ Curl_ossl_connect_step3(struct connectdata *conn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Get server's certificate (note: beware of dynamic allocation) - opt */
|
/*
|
||||||
/* major serious hack alert -- we should check certificates
|
* We check certificates to authenticate the server; otherwise we risk
|
||||||
* to authenticate the server; otherwise we risk man-in-the-middle
|
* man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to
|
||||||
* attack
|
* verify the peer ignore faults and failures from the server cert
|
||||||
|
* operations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
|
if(!data->set.ssl.verifypeer)
|
||||||
if(!connssl->server_cert) {
|
(void)servercert(conn, connssl, FALSE);
|
||||||
failf(data, "SSL: couldn't get peer certificate!");
|
else
|
||||||
return CURLE_PEER_FAILED_VERIFICATION;
|
retcode = servercert(conn, connssl, TRUE);
|
||||||
}
|
|
||||||
infof (data, "Server certificate:\n");
|
|
||||||
|
|
||||||
str = X509_NAME_oneline(X509_get_subject_name(connssl->server_cert),
|
if(CURLE_OK == retcode)
|
||||||
NULL, 0);
|
connssl->connecting_state = ssl_connect_done;
|
||||||
if(!str) {
|
|
||||||
failf(data, "SSL: couldn't get X509-subject!");
|
|
||||||
X509_free(connssl->server_cert);
|
|
||||||
connssl->server_cert = NULL;
|
|
||||||
return CURLE_SSL_CONNECT_ERROR;
|
|
||||||
}
|
|
||||||
infof(data, "\t subject: %s\n", str);
|
|
||||||
CRYPTO_free(str);
|
|
||||||
|
|
||||||
certdate = X509_get_notBefore(connssl->server_cert);
|
|
||||||
Curl_ASN1_UTCTIME_output(conn, "\t start date: ", certdate);
|
|
||||||
|
|
||||||
certdate = X509_get_notAfter(connssl->server_cert);
|
|
||||||
Curl_ASN1_UTCTIME_output(conn, "\t expire date: ", certdate);
|
|
||||||
|
|
||||||
if(data->set.ssl.verifyhost) {
|
|
||||||
retcode = verifyhost(conn, connssl->server_cert);
|
|
||||||
if(retcode) {
|
|
||||||
X509_free(connssl->server_cert);
|
|
||||||
connssl->server_cert = NULL;
|
|
||||||
return retcode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
str = X509_NAME_oneline(X509_get_issuer_name(connssl->server_cert),
|
|
||||||
NULL, 0);
|
|
||||||
if(!str) {
|
|
||||||
failf(data, "SSL: couldn't get X509-issuer name!");
|
|
||||||
retcode = CURLE_SSL_CONNECT_ERROR;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
infof(data, "\t issuer: %s\n", str);
|
|
||||||
CRYPTO_free(str);
|
|
||||||
|
|
||||||
/* We could do all sorts of certificate verification stuff here before
|
|
||||||
deallocating the certificate. */
|
|
||||||
|
|
||||||
lerr = data->set.ssl.certverifyresult=
|
|
||||||
SSL_get_verify_result(connssl->handle);
|
|
||||||
if(data->set.ssl.certverifyresult != X509_V_OK) {
|
|
||||||
if(data->set.ssl.verifypeer) {
|
|
||||||
/* We probably never reach this, because SSL_connect() will fail
|
|
||||||
and we return earlyer if verifypeer is set? */
|
|
||||||
failf(data, "SSL certificate verify result: %s (%ld)",
|
|
||||||
X509_verify_cert_error_string(lerr), lerr);
|
|
||||||
retcode = CURLE_PEER_FAILED_VERIFICATION;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
infof(data, "SSL certificate verify result: %s (%ld),"
|
|
||||||
" continuing anyway.\n",
|
|
||||||
X509_verify_cert_error_string(lerr), lerr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
infof(data, "SSL certificate verify ok.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
X509_free(connssl->server_cert);
|
|
||||||
connssl->server_cert = NULL;
|
|
||||||
connssl->connecting_state = ssl_connect_done;
|
|
||||||
return retcode;
|
return retcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user