Relocate CERT_INFO_PREFIX to ssl.c
[privoxy.git] / openssl.c
index ecfb6bf..d27f918 100644 (file)
--- a/openssl.c
+++ b/openssl.c
@@ -58,7 +58,7 @@
 #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);
@@ -229,6 +229,11 @@ extern int ssl_recv_data(struct ssl_attr *ssl_attr, unsigned char *buf, size_t m
       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,
@@ -237,11 +242,6 @@ extern int ssl_recv_data(struct ssl_attr *ssl_attr, unsigned char *buf, size_t m
       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);
 
@@ -308,7 +308,7 @@ static int ssl_store_cert(struct client_state *csp, X509* crt)
     */
    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;
    }
@@ -654,6 +654,13 @@ static int ssl_store_cert(struct client_state *csp, X509* crt)
    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 %d "
+         "while gathering certificate information", len);
+      ret = -1;
+      goto exit;
+   }
    encoded_text = html_encode(bio_mem_data);
    if (encoded_text == NULL)
    {
@@ -776,11 +783,11 @@ extern int create_client_ssl_connection(struct client_state *csp)
     */
    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;
@@ -1280,7 +1287,7 @@ 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)
+   if (*olen > dlen)
    {
       return ENOBUFS;
    }
@@ -1465,39 +1472,41 @@ exit:
 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;
    }
 
@@ -1609,8 +1618,6 @@ static int ssl_certificate_is_invalid(const char *cert_file)
 
    if (!(cert = ssl_certificate_load(cert_file)))
    {
-      log_ssl_errors(LOG_LEVEL_ERROR,
-         "Error reading certificate file %s", cert_file);
       return 1;
    }
 
@@ -1640,7 +1647,7 @@ static int ssl_certificate_is_invalid(const char *cert_file)
  *          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
  *
  *********************************************************************/
@@ -1702,7 +1709,7 @@ static int set_subject_alternative_name(X509 *cert, X509 *issuer, const char *ho
 
 /*********************************************************************
  *
- * Function    :  generate_webpage_certificate
+ * Function    :  generate_host_certificate
  *
  * Description :  Creates certificate file in presetted directory.
  *                If certificate already exists, no other certificate
@@ -1718,7 +1725,7 @@ static int set_subject_alternative_name(X509 *cert, X509 *issuer, const char *ho
  *                 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;
@@ -1757,6 +1764,15 @@ static int generate_webpage_certificate(struct client_state *csp)
       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? */
@@ -1795,25 +1811,6 @@ static int generate_webpage_certificate(struct client_state *csp)
       }
    }
 
-   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
     */
@@ -1935,7 +1932,7 @@ static int generate_webpage_certificate(struct client_state *csp)
    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;
    }