summaryrefslogtreecommitdiff
path: root/plugins/FTPFileYM/curl/lib/ssluse.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/FTPFileYM/curl/lib/ssluse.c')
-rw-r--r--plugins/FTPFileYM/curl/lib/ssluse.c272
1 files changed, 121 insertions, 151 deletions
diff --git a/plugins/FTPFileYM/curl/lib/ssluse.c b/plugins/FTPFileYM/curl/lib/ssluse.c
index 4a0dba734d..c747420f60 100644
--- a/plugins/FTPFileYM/curl/lib/ssluse.c
+++ b/plugins/FTPFileYM/curl/lib/ssluse.c
@@ -43,6 +43,7 @@
#include "inet_pton.h"
#include "ssluse.h"
#include "connect.h"
+#include "slist.h"
#include "strequal.h"
#include "select.h"
#include "sslgen.h"
@@ -236,27 +237,12 @@ static int ossl_seed(struct SessionHandle *data)
/* If we get here, it means we need to seed the PRNG using a "silly"
approach! */
- {
- int len;
- char *area;
-
- /* Changed call to RAND_seed to use the underlying RAND_add implementation
- * directly. Do this in a loop, with the amount of additional entropy
- * being dependent upon the algorithm used by Curl_FormBoundary(): N bytes
- * of a 7-bit ascii set. -- Richard Gorton, March 11 2003.
- */
-
- do {
- area = Curl_FormBoundary();
- if(!area)
- return 3; /* out of memory */
-
- len = curlx_uztosi(strlen(area));
- RAND_add(area, len, (len >> 1));
-
- free(area); /* now remove the random junk */
- } while(!RAND_status());
- }
+ do {
+ unsigned char randb[64];
+ int len = sizeof(randb);
+ RAND_bytes(randb, len);
+ RAND_add(randb, len, (len >> 1));
+ } while(!RAND_status());
/* generates a default path for the random seed file */
buf[0]=0; /* blank it first */
@@ -308,6 +294,49 @@ static int do_file_type(const char *type)
return -1;
}
+#if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_LOAD_FOUR_ARGS)
+/*
+ * Supply default password to the engine user interface conversation.
+ * The password is passed by OpenSSL engine from ENGINE_load_private_key()
+ * last argument to the ui and can be obtained by UI_get0_user_data(ui) here.
+ */
+static int ssl_ui_reader(UI *ui, UI_STRING *uis)
+{
+ const char *password;
+ switch(UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ password = (const char*)UI_get0_user_data(ui);
+ if(NULL != password &&
+ UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD) {
+ UI_set_result(ui, uis, password);
+ return 1;
+ }
+ default:
+ break;
+ }
+ return (UI_method_get_reader(UI_OpenSSL()))(ui, uis);
+}
+
+/*
+ * Suppress interactive request for a default password if available.
+ */
+static int ssl_ui_writer(UI *ui, UI_STRING *uis)
+{
+ switch(UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ if(NULL != UI_get0_user_data(ui) &&
+ UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD) {
+ return 1;
+ }
+ default:
+ break;
+ }
+ return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
+}
+#endif
+
static
int cert_stuff(struct connectdata *conn,
SSL_CTX* ctx,
@@ -450,7 +479,7 @@ int cert_stuff(struct connectdata *conn,
PKCS12_PBE_add();
if(!PKCS12_parse(p12, data->set.str[STRING_KEY_PASSWD], &pri, &x509,
- &ca)) {
+ &ca)) {
failf(data,
"could not parse PKCS12 file, check password, OpenSSL error %s",
ERR_error_string(ERR_get_error(), NULL) );
@@ -462,54 +491,53 @@ int cert_stuff(struct connectdata *conn,
if(SSL_CTX_use_certificate(ctx, x509) != 1) {
failf(data, SSL_CLIENT_CERT_ERR);
- EVP_PKEY_free(pri);
- X509_free(x509);
- sk_X509_pop_free(ca, X509_free);
- return 0;
+ goto fail;
}
if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) {
failf(data, "unable to use private key from PKCS12 file '%s'",
cert_file);
- EVP_PKEY_free(pri);
- X509_free(x509);
- sk_X509_pop_free(ca, X509_free);
- return 0;
+ goto fail;
}
if(!SSL_CTX_check_private_key (ctx)) {
failf(data, "private key from PKCS12 file '%s' "
"does not match certificate in same file", cert_file);
- EVP_PKEY_free(pri);
- X509_free(x509);
- sk_X509_pop_free(ca, X509_free);
- return 0;
+ goto fail;
}
/* Set Certificate Verification chain */
if(ca && sk_X509_num(ca)) {
for(i = 0; i < sk_X509_num(ca); i++) {
- if(!SSL_CTX_add_extra_chain_cert(ctx,sk_X509_value(ca, i))) {
+ /*
+ * Note that sk_X509_pop() is used below to make sure the cert is
+ * removed from the stack properly before getting passed to
+ * SSL_CTX_add_extra_chain_cert(). Previously we used
+ * sk_X509_value() instead, but then we'd clean it in the subsequent
+ * sk_X509_pop_free() call.
+ */
+ X509 *x = sk_X509_pop(ca);
+ if(!SSL_CTX_add_extra_chain_cert(ctx, x)) {
failf(data, "cannot add certificate to certificate chain");
- EVP_PKEY_free(pri);
- X509_free(x509);
- sk_X509_pop_free(ca, X509_free);
- return 0;
+ goto fail;
}
- if(!SSL_CTX_add_client_CA(ctx, sk_X509_value(ca, i))) {
+ /* SSL_CTX_add_client_CA() seems to work with either sk_* function,
+ * presumably because it duplicates what we pass to it.
+ */
+ if(!SSL_CTX_add_client_CA(ctx, x)) {
failf(data, "cannot add certificate to client CA list");
- EVP_PKEY_free(pri);
- X509_free(x509);
- sk_X509_pop_free(ca, X509_free);
- return 0;
+ goto fail;
}
}
}
+ cert_done = 1;
+ fail:
EVP_PKEY_free(pri);
X509_free(x509);
sk_X509_pop_free(ca, X509_free);
- cert_done = 1;
- break;
+
+ if(!cert_done)
+ return 0; /* failure! */
#else
failf(data, "file type P12 for certificate not supported");
return 0;
@@ -542,7 +570,16 @@ int cert_stuff(struct connectdata *conn,
EVP_PKEY *priv_key = NULL;
if(data->state.engine) {
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
- UI_METHOD *ui_method = UI_OpenSSL();
+ UI_METHOD *ui_method =
+ UI_create_method((char *)"cURL user interface");
+ if(NULL == ui_method) {
+ failf(data, "unable do create OpenSSL user-interface method");
+ return 0;
+ }
+ UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
+ UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
+ UI_method_set_reader(ui_method, ssl_ui_reader);
+ UI_method_set_writer(ui_method, ssl_ui_writer);
#endif
/* the typecast below was added to please mingw32 */
priv_key = (EVP_PKEY *)
@@ -551,6 +588,9 @@ int cert_stuff(struct connectdata *conn,
ui_method,
#endif
data->set.str[STRING_KEY_PASSWD]);
+#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
+ UI_destroy_method(ui_method);
+#endif
if(!priv_key) {
failf(data, "failed to load private key from crypto engine");
return 0;
@@ -1152,6 +1192,8 @@ static CURLcode verifyhost(struct connectdata *conn,
/* an alternative name field existed, but didn't match and then
we MUST fail */
infof(data, "\t subjectAltName does not match %s\n", conn->host.dispname);
+ failf(data, "SSL: no alternative certificate subject name matches "
+ "target host name '%s'", conn->host.dispname);
res = CURLE_PEER_FAILED_VERIFICATION;
}
else {
@@ -1770,7 +1812,7 @@ ossl_connect_step2(struct connectdata *conn, int sockindex)
*/
if(CURLE_SSL_CONNECT_ERROR == rc && errdetail == 0) {
failf(data, "Unknown SSL protocol error in connection to %s:%ld ",
- conn->host.name, conn->port);
+ conn->host.name, conn->remote_port);
return rc;
}
/* Could be a CERT problem */
@@ -1806,60 +1848,6 @@ static int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len)
return 0;
}
-static CURLcode push_certinfo_len(struct SessionHandle *data,
- int certnum,
- const char *label,
- const char *value,
- size_t valuelen)
-{
- struct curl_certinfo *ci = &data->info.certs;
- char *output;
- struct curl_slist *nl;
- CURLcode res = CURLE_OK;
- size_t labellen = strlen(label);
- size_t outlen = labellen + 1 + valuelen + 1; /* label:value\0 */
-
- output = malloc(outlen);
- if(!output)
- return CURLE_OUT_OF_MEMORY;
-
- /* sprintf the label and colon */
- snprintf(output, outlen, "%s:", label);
-
- /* memcpy the value (it might not be zero terminated) */
- memcpy(&output[labellen+1], value, valuelen);
-
- /* zero terminate the output */
- output[labellen + 1 + valuelen] = 0;
-
- /* TODO: we should rather introduce an internal API that can do the
- equivalent of curl_slist_append but doesn't strdup() the given data as
- like in this place the extra malloc/free is totally pointless */
- nl = curl_slist_append(ci->certinfo[certnum], output);
- free(output);
- if(!nl) {
- curl_slist_free_all(ci->certinfo[certnum]);
- ci->certinfo[certnum] = NULL;
- res = CURLE_OUT_OF_MEMORY;
- }
- else
- ci->certinfo[certnum] = nl;
-
- return res;
-}
-
-/* this is a convenience function for push_certinfo_len that takes a zero
- terminated value */
-static CURLcode push_certinfo(struct SessionHandle *data,
- int certnum,
- const char *label,
- const char *value)
-{
- size_t valuelen = strlen(value);
-
- return push_certinfo_len(data, certnum, label, value, valuelen);
-}
-
static void pubkey_show(struct SessionHandle *data,
int num,
const char *type,
@@ -1883,7 +1871,7 @@ static void pubkey_show(struct SessionHandle *data,
left -= 3;
}
infof(data, " %s: %s\n", namebuf, buffer);
- push_certinfo(data, num, namebuf, buffer);
+ Curl_ssl_push_certinfo(data, num, namebuf, buffer);
free(buffer);
}
}
@@ -1952,7 +1940,7 @@ static int X509V3_ext(struct SessionHandle *data,
}
infof(data, " %s\n", buf);
- push_certinfo(data, certnum, namebuf, buf);
+ Curl_ssl_push_certinfo(data, certnum, namebuf, buf);
BIO_free(bio_out);
@@ -1972,7 +1960,7 @@ static void X509_signature(struct SessionHandle *data,
ptr+=snprintf(ptr, sizeof(buf)-(ptr-buf), "%02x:", sig->data[i]);
infof(data, " Signature: %s\n", buf);
- push_certinfo(data, numcert, "Signature", buf);
+ Curl_ssl_push_certinfo(data, numcert, "Signature", buf);
}
static void dumpcert(struct SessionHandle *data, X509 *x, int numcert)
@@ -1988,30 +1976,13 @@ static void dumpcert(struct SessionHandle *data, X509 *x, int numcert)
infof(data, "%s\n", biomem->data);
- push_certinfo_len(data, numcert, "Cert", biomem->data, biomem->length);
+ Curl_ssl_push_certinfo_len(data, numcert,
+ "Cert", biomem->data, biomem->length);
BIO_free(bio_out);
}
-
-static int init_certinfo(struct SessionHandle *data,
- int num)
-{
- struct curl_certinfo *ci = &data->info.certs;
- struct curl_slist **table;
-
- Curl_ssl_free_certinfo(data);
-
- ci->num_of_certs = num;
- table = calloc((size_t)num, sizeof(struct curl_slist *));
- if(!table)
- return 1;
-
- ci->certinfo = table;
- return 0;
-}
-
/*
* This size was previously 512 which has been reported "too small" without
* any specifics, so it was enlarged to allow more data to get shown uncut.
@@ -2040,7 +2011,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
}
numcerts = sk_X509_num(sk);
- if(init_certinfo(data, numcerts)) {
+ if(Curl_ssl_init_certinfo(data, numcerts)) {
free(bufp);
return CURLE_OUT_OF_MEMORY;
}
@@ -2065,16 +2036,16 @@ static CURLcode get_cert_chain(struct connectdata *conn,
(void)x509_name_oneline(X509_get_subject_name(x), bufp, CERTBUFFERSIZE);
infof(data, "%2d Subject: %s\n", i, bufp);
- push_certinfo(data, i, "Subject", bufp);
+ Curl_ssl_push_certinfo(data, i, "Subject", bufp);
(void)x509_name_oneline(X509_get_issuer_name(x), bufp, CERTBUFFERSIZE);
infof(data, " Issuer: %s\n", bufp);
- push_certinfo(data, i, "Issuer", bufp);
+ Curl_ssl_push_certinfo(data, i, "Issuer", bufp);
value = X509_get_version(x);
infof(data, " Version: %lu (0x%lx)\n", value+1, value);
snprintf(bufp, CERTBUFFERSIZE, "%lx", value);
- push_certinfo(data, i, "Version", bufp); /* hex */
+ Curl_ssl_push_certinfo(data, i, "Version", bufp); /* hex */
num=X509_get_serialNumber(x);
if(num->length <= 4) {
@@ -2103,30 +2074,30 @@ static CURLcode get_cert_chain(struct connectdata *conn,
bufp[0]=0;
}
if(bufp[0])
- push_certinfo(data, i, "Serial Number", bufp); /* hex */
+ Curl_ssl_push_certinfo(data, i, "Serial Number", bufp); /* hex */
cinf = x->cert_info;
j = asn1_object_dump(cinf->signature->algorithm, bufp, CERTBUFFERSIZE);
if(!j) {
infof(data, " Signature Algorithm: %s\n", bufp);
- push_certinfo(data, i, "Signature Algorithm", bufp);
+ Curl_ssl_push_certinfo(data, i, "Signature Algorithm", bufp);
}
certdate = X509_get_notBefore(x);
asn1_output(certdate, bufp, CERTBUFFERSIZE);
infof(data, " Start date: %s\n", bufp);
- push_certinfo(data, i, "Start date", bufp);
+ Curl_ssl_push_certinfo(data, i, "Start date", bufp);
certdate = X509_get_notAfter(x);
asn1_output(certdate, bufp, CERTBUFFERSIZE);
infof(data, " Expire date: %s\n", bufp);
- push_certinfo(data, i, "Expire date", bufp);
+ Curl_ssl_push_certinfo(data, i, "Expire date", bufp);
j = asn1_object_dump(cinf->key->algor->algorithm, bufp, CERTBUFFERSIZE);
if(!j) {
infof(data, " Public Key Algorithm: %s\n", bufp);
- push_certinfo(data, i, "Public Key Algorithm", bufp);
+ Curl_ssl_push_certinfo(data, i, "Public Key Algorithm", bufp);
}
pubkey = X509_get_pubkey(x);
@@ -2138,7 +2109,7 @@ static CURLcode get_cert_chain(struct connectdata *conn,
infof(data, " RSA Public Key (%d bits)\n",
BN_num_bits(pubkey->pkey.rsa->n));
snprintf(bufp, CERTBUFFERSIZE, "%d", BN_num_bits(pubkey->pkey.rsa->n));
- push_certinfo(data, i, "RSA Public Key", bufp);
+ Curl_ssl_push_certinfo(data, i, "RSA Public Key", bufp);
print_pubkey_BN(rsa, n, i);
print_pubkey_BN(rsa, e, i);
@@ -2220,14 +2191,7 @@ static CURLcode servercert(struct connectdata *conn,
rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
buffer, BUFSIZE);
- if(rc) {
- 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", buffer);
+ infof(data, "\t subject: %s\n", rc?"[NONE]":buffer);
certdate = X509_get_notBefore(connssl->server_cert);
asn1_output(certdate, buffer, BUFSIZE);
@@ -2389,7 +2353,7 @@ ossl_connect_step3(struct connectdata *conn,
* operations.
*/
- if(!data->set.ssl.verifypeer)
+ if(!data->set.ssl.verifypeer && !data->set.ssl.verifyhost)
(void)servercert(conn, connssl, FALSE);
else
retcode = servercert(conn, connssl, TRUE);
@@ -2568,7 +2532,7 @@ static ssize_t ossl_send(struct connectdata *conn,
memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
- if(rc < 0) {
+ if(rc <= 0) {
err = SSL_get_error(conn->ssl[sockindex].handle, rc);
switch(err) {
@@ -2617,7 +2581,7 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
nread = (ssize_t)SSL_read(conn->ssl[num].handle, buf, buffsize);
- if(nread < 0) {
+ if(nread <= 0) {
/* failed SSL_read */
int err = SSL_get_error(conn->ssl[num].handle, (int)nread);
@@ -2631,13 +2595,19 @@ static ssize_t ossl_recv(struct connectdata *conn, /* connection data */
*curlcode = CURLE_AGAIN;
return -1;
default:
- /* openssl/ssl.h says "look at error stack/return value/errno" */
+ /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return
+ value/errno" */
+ /* http://www.openssl.org/docs/crypto/ERR_get_error.html */
sslerror = ERR_get_error();
- failf(conn->data, "SSL read: %s, errno %d",
- ERR_error_string(sslerror, error_buffer),
- SOCKERRNO);
- *curlcode = CURLE_RECV_ERROR;
- return -1;
+ if((nread < 0) || sslerror) {
+ /* If the return code was negative or there actually is an error in the
+ queue */
+ failf(conn->data, "SSL read: %s, errno %d",
+ ERR_error_string(sslerror, error_buffer),
+ SOCKERRNO);
+ *curlcode = CURLE_RECV_ERROR;
+ return -1;
+ }
}
}
return nread;