#define VALID_DATETIME_FMT "%y%m%d%H%M%SZ"
#define VALID_DATETIME_BUFLEN 16
-static int generate_webpage_certificate(struct client_state *csp);
+static int generate_host_certificate(struct client_state *csp);
static void free_client_ssl_structures(struct client_state *csp);
static void free_server_ssl_structures(struct client_state *csp);
-static int ssl_store_cert(struct client_state *csp, X509* crt);
+static int ssl_store_cert(struct client_state *csp, X509 *crt);
static void log_ssl_errors(int debuglevel, const char* fmt, ...) __attribute__((format(printf, 2, 3)));
static int ssl_inited = 0;
ret = BIO_read(bio, buf, (int)max_length);
} while (ret <= 0 && BIO_should_retry(bio));
+ if (BIO_get_ssl(bio, &ssl) == 1)
+ {
+ fd = SSL_get_fd(ssl);
+ }
+
if (ret < 0)
{
log_ssl_errors(LOG_LEVEL_ERROR,
return -1;
}
- if (BIO_get_ssl(bio, &ssl) == 1)
- {
- fd = SSL_get_fd(ssl);
- }
-
log_error(LOG_LEVEL_RECEIVED, "TLS from socket %d: %N",
fd, ret, buf);
* Returns : 0 on success and negative value on error
*
*********************************************************************/
-static int ssl_store_cert(struct client_state *csp, X509* crt)
+static int ssl_store_cert(struct client_state *csp, X509 *crt)
{
long len = 0;
struct certs_chain *last = &(csp->server_certs_chain);
if (!bio)
{
- log_ssl_errors(LOG_LEVEL_ERROR, "BIO_new_mem_buf() failed");
+ log_ssl_errors(LOG_LEVEL_ERROR, "BIO_new() failed");
return -1;
}
*/
if (!PEM_write_bio_X509(bio, crt))
{
- log_ssl_errors(LOG_LEVEL_ERROR, "PEM_write_X509() failed");
+ log_ssl_errors(LOG_LEVEL_ERROR, "PEM_write_bio_X509() failed");
ret = -1;
goto exit;
}
bio = BIO_new(BIO_s_mem());
if (!bio)
{
- log_ssl_errors(LOG_LEVEL_ERROR, "BIO_new_mem_buf() failed");
+ log_ssl_errors(LOG_LEVEL_ERROR, "BIO_new() failed");
ret = -1;
goto exit;
}
ul = (unsigned long)l;
neg = "";
}
- if (BIO_printf(bio, " %s%lu (%s0x%lx)\n", neg, ul, neg, ul) <= 0)
+ if (BIO_printf(bio, "%s%lu (%s0x%lx)\n", neg, ul, neg, ul) <= 0)
{
log_ssl_errors(LOG_LEVEL_ERROR, "BIO_printf() for serial failed");
ret = -1;
}
else
{
+ int i;
if (bs->type == V_ASN1_NEG_INTEGER)
{
if (BIO_puts(bio, " (Negative)") < 0)
goto exit;
}
}
- for (int i = 0; i < bs->length; i++)
+ for (i = 0; i < bs->length; i++)
{
if (BIO_printf(bio, "%02x%c", bs->data[i],
((i + 1 == bs->length) ? '\n' : ':')) <= 0)
BIO_write(bio, &zero, 1);
len = BIO_get_mem_data(bio, &bio_mem_data);
+ if (len <= 0)
+ {
+ log_error(LOG_LEVEL_ERROR, "BIO_get_mem_data() returned %ld "
+ "while gathering certificate information", len);
+ ret = -1;
+ goto exit;
+ }
encoded_text = html_encode(bio_mem_data);
if (encoded_text == NULL)
{
* Parameters :
* 1 : csp = Current client state (buffers, headers, etc...)
*
- * Returns : 1 => Error while creating hash
+ * Returns : -1 => Error while creating hash
* 0 => Hash created successfully
*
*********************************************************************/
*/
privoxy_mutex_lock(&certificate_mutex);
- ret = generate_webpage_certificate(csp);
+ ret = generate_host_certificate(csp);
if (ret < 0)
{
log_error(LOG_LEVEL_ERROR,
- "Generate_webpage_certificate failed: %d", ret);
+ "generate_host_certificate failed: %d", ret);
privoxy_mutex_unlock(&certificate_mutex);
ret = -1;
goto exit;
goto exit;
}
- log_error(LOG_LEVEL_CONNECT, "Client successfully connected over TLS/SSL");
+ log_error(LOG_LEVEL_CONNECT, "Client successfully connected over %s (%s).",
+ SSL_get_version(ssl), SSL_get_cipher_name(ssl));
+
csp->ssl_with_client_is_opened = 1;
ret = 0;
chain = SSL_get_peer_cert_chain(ssl);
if (chain)
{
- for (int i = 0; i < sk_X509_num(chain); i++)
+ int i;
+ for (i = 0; i < sk_X509_num(chain); i++)
{
if (ssl_store_cert(csp, sk_X509_value(chain, i)) != 0)
{
}
}
- log_error(LOG_LEVEL_CONNECT, "Server successfully connected over TLS/SSL");
+ log_error(LOG_LEVEL_CONNECT, "Server successfully connected over %s (%s).",
+ SSL_get_version(ssl), SSL_get_cipher_name(ssl));
/*
* Server certificate chain is valid, so we can clean
extern int ssl_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen)
{
- *olen = 4 * ((slen/3) + ((slen%3) ? 1 : 0)) + 1;
- if (*olen < dlen)
+ *olen = 4 * ((slen/3) + ((slen%3) ? 1 : 0)) + 1;
+ if (*olen > dlen)
{
return ENOBUFS;
}
static int generate_key(struct client_state *csp, char **key_buf)
{
int ret = 0;
- char* key_file_path = NULL;
- BIGNUM *exp = BN_new();
- RSA *rsa = RSA_new();
- EVP_PKEY *key = EVP_PKEY_new();
+ char* key_file_path;
+ BIGNUM *exp;
+ RSA *rsa;
+ EVP_PKEY *key;
- if (exp == NULL || rsa == NULL || key == NULL)
+ key_file_path = make_certs_path(csp->config->certificate_directory,
+ (char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE);
+ if (key_file_path == NULL)
{
- log_ssl_errors(LOG_LEVEL_ERROR, "RSA key memory allocation failure");
- ret = -1;
- goto exit;
+ return -1;
}
- if (BN_set_word(exp, RSA_KEY_PUBLIC_EXPONENT) != 1)
+ /*
+ * Test if key already exists. If so, we don't have to create it again.
+ */
+ if (file_exists(key_file_path) == 1)
{
- log_ssl_errors(LOG_LEVEL_ERROR, "Setting RSA key exponent failed");
- ret = -1;
- goto exit;
+ freez(key_file_path);
+ return 0;
}
- key_file_path = make_certs_path(csp->config->certificate_directory,
- (char *)csp->http->hash_of_host_hex, KEY_FILE_TYPE);
- if (key_file_path == NULL)
+ exp = BN_new();
+ rsa = RSA_new();
+ key = EVP_PKEY_new();
+ if (exp == NULL || rsa == NULL || key == NULL)
{
+ log_ssl_errors(LOG_LEVEL_ERROR, "RSA key memory allocation failure");
ret = -1;
goto exit;
}
- /*
- * Test if key already exists. If so, we don't have to create it again.
- */
- if (file_exists(key_file_path) == 1)
+ if (BN_set_word(exp, RSA_KEY_PUBLIC_EXPONENT) != 1)
{
- ret = 0;
+ log_ssl_errors(LOG_LEVEL_ERROR, "Setting RSA key exponent failed");
+ ret = -1;
goto exit;
}
* pointer to certificate instance otherwise
*
*********************************************************************/
-static X509* ssl_certificate_load(const char *cert_path)
+static X509 *ssl_certificate_load(const char *cert_path)
{
X509 *cert = NULL;
FILE *cert_f = NULL;
if (!(cert = ssl_certificate_load(cert_file)))
{
- log_ssl_errors(LOG_LEVEL_ERROR,
- "Error reading certificate file %s", cert_file);
return 1;
}
* 3 : nid = OpenSSL NID
* 4 : value = extension value
*
- * Returns : 0 => Error while setting extensuon data
+ * Returns : 0 => Error while setting extension data
* 1 => It worked
*
*********************************************************************/
/*********************************************************************
*
- * Function : generate_webpage_certificate
+ * Function : generate_host_certificate
*
* Description : Creates certificate file in presetted directory.
* If certificate already exists, no other certificate
* 1 => Certificate created
*
*********************************************************************/
-static int generate_webpage_certificate(struct client_state *csp)
+static int generate_host_certificate(struct client_state *csp)
{
char *key_buf = NULL; /* Buffer for created key */
X509 *issuer_cert = NULL;
return -1;
}
+ if (enforce_sane_certificate_state(cert_opt.output_file,
+ cert_opt.subject_key))
+ {
+ freez(cert_opt.output_file);
+ freez(cert_opt.subject_key);
+
+ return -1;
+ }
+
if (file_exists(cert_opt.output_file) == 1)
{
/* The file exists, but is it valid? */
}
}
- if (file_exists(cert_opt.output_file) == 0 &&
- file_exists(cert_opt.subject_key) == 1)
- {
- log_error(LOG_LEVEL_ERROR,
- "A website key already exists but there's no matching certificate. "
- "Removing %s before creating a new key and certificate.",
- cert_opt.subject_key);
- if (unlink(cert_opt.subject_key))
- {
- log_error(LOG_LEVEL_ERROR, "Failed to unlink %s: %E",
- cert_opt.subject_key);
-
- freez(cert_opt.output_file);
- freez(cert_opt.subject_key);
-
- return -1;
- }
- }
-
/*
* Create key for requested host
*/
serial_num = BN_new();
if (!serial_num)
{
- log_error(LOG_LEVEL_ERROR, "generate_webpage_certificate: memory error");
+ log_error(LOG_LEVEL_ERROR, "generate_host_certificate: memory error");
ret = -1;
goto exit;
}
}
+#ifdef FEATURE_GRACEFUL_TERMINATION
/*********************************************************************
*
* Function : ssl_release
{
if (ssl_inited == 1)
{
+#if OPENSSL_VERSION_NUMBER >= 0x1000200fL
+#ifndef LIBRESSL_VERSION_NUMBER
#ifndef OPENSSL_NO_COMP
SSL_COMP_free_compression_methods();
+#endif
+#endif
#endif
CONF_modules_free();
CONF_modules_unload(1);
CRYPTO_cleanup_all_ex_data();
}
}
-
+#endif /* def FEATURE_GRACEFUL_TERMINATION */