#include "mbedtls/pem.h"
#include "mbedtls/base64.h"
#include "mbedtls/error.h"
+#include "mbedtls/oid.h"
+#include "mbedtls/asn1write.h"
#include "config.h"
#include "project.h"
*
* Function : is_ssl_pending
*
- * Description : Tests if there are some waiting data on ssl connection
+ * Description : Tests if there are some waiting data on ssl connection.
+ * Only considers data that has actually been received
+ * locally and ignores data that is still on the fly
+ * or has not yet been sent by the remote end.
*
* Parameters :
* 1 : ssl = SSL context to test
{
log_error(LOG_LEVEL_ERROR,
"mbedtls_ssl_handshake with server failed: %s", err_buf);
+ free_certificate_chain(csp);
ret = -1;
}
goto exit;
}
+/*********************************************************************
+ *
+ * Function : set_subject_alternative_name
+ *
+ * Description : Sets the Subject Alternative Name extension to a cert
+ *
+ * Parameters :
+ * 1 : cert = The certificate to modify
+ * 2 : hostname = The hostname to add
+ *
+ * Returns : <0 => Error while creating certificate.
+ * 0 => It worked
+ *
+ *********************************************************************/
+static int set_subject_alternative_name(mbedtls_x509write_cert *cert, const char *hostname)
+{
+ char err_buf[ERROR_BUF_SIZE];
+ int ret;
+ char *subject_alternative_name;
+ size_t subject_alternative_name_len;
+#define MBEDTLS_SUBJECT_ALTERNATIVE_NAME_MAX_LEN 255
+ unsigned char san_buf[MBEDTLS_SUBJECT_ALTERNATIVE_NAME_MAX_LEN + 1];
+ unsigned char *c;
+ int len;
+
+ subject_alternative_name_len = strlen(hostname) + 1;
+ subject_alternative_name = zalloc_or_die(subject_alternative_name_len);
+
+ strlcpy(subject_alternative_name, hostname, subject_alternative_name_len);
+
+ memset(san_buf, 0, sizeof(san_buf));
+
+ c = san_buf + sizeof(san_buf);
+ len = 0;
+
+ ret = mbedtls_asn1_write_raw_buffer(&c, san_buf,
+ (const unsigned char *)subject_alternative_name,
+ strlen(subject_alternative_name));
+ if (ret < 0)
+ {
+ mbedtls_strerror(ret, err_buf, sizeof(err_buf));
+ log_error(LOG_LEVEL_ERROR,
+ "mbedtls_asn1_write_raw_buffer() failed: %s", err_buf);
+ goto exit;
+ }
+ len += ret;
+
+ ret = mbedtls_asn1_write_len(&c, san_buf, strlen(subject_alternative_name));
+ if (ret < 0)
+ {
+ mbedtls_strerror(ret, err_buf, sizeof(err_buf));
+ log_error(LOG_LEVEL_ERROR,
+ "mbedtls_asn1_write_len() failed: %s", err_buf);
+ goto exit;
+ }
+ len += ret;
+
+ ret = mbedtls_asn1_write_tag(&c, san_buf, MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2);
+ if (ret < 0)
+ {
+ mbedtls_strerror(ret, err_buf, sizeof(err_buf));
+ log_error(LOG_LEVEL_ERROR,
+ "mbedtls_asn1_write_tag() failed: %s", err_buf);
+ goto exit;
+ }
+ len += ret;
+
+ ret = mbedtls_asn1_write_len(&c, san_buf, (size_t)len);
+ if (ret < 0)
+ {
+ mbedtls_strerror(ret, err_buf, sizeof(err_buf));
+ log_error(LOG_LEVEL_ERROR,
+ "mbedtls_asn1_write_len() failed: %s", err_buf);
+ goto exit;
+ }
+ len += ret;
+
+ ret = mbedtls_asn1_write_tag(&c, san_buf,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ if (ret < 0)
+ {
+ mbedtls_strerror(ret, err_buf, sizeof(err_buf));
+ log_error(LOG_LEVEL_ERROR,
+ "mbedtls_asn1_write_tag() failed: %s", err_buf);
+ goto exit;
+ }
+ len += ret;
+
+ ret = mbedtls_x509write_crt_set_extension(cert,
+ MBEDTLS_OID_SUBJECT_ALT_NAME,
+ MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME),
+ 0, san_buf + sizeof(san_buf) - len, (size_t)len);
+ if (ret < 0)
+ {
+ mbedtls_strerror(ret, err_buf, sizeof(err_buf));
+ log_error(LOG_LEVEL_ERROR,
+ "mbedtls_x509write_crt_set_extension() failed: %s", err_buf);
+ }
+
+exit:
+ freez(subject_alternative_name);
+
+ return ret;
+
+}
+
/*********************************************************************
*
* Function : generate_webpage_certificate
}
#endif /* MBEDTLS_SHA1_C */
+ if (set_subject_alternative_name(&cert, csp->http->host))
+ {
+ /* Errors are already logged by set_subject_alternative_name() */
+ ret = -1;
+ goto exit;
+ }
+
/*
* Writing certificate into file
*/
unsigned long serial = 0;
int i = CERT_SERIAL_NUM_LENGTH;
- /* Length of hash is 16 bytes, we must avoid to read next chars */
- if (i > 16)
- {
- i = 16;
- }
- if (i < 2)
- {
- i = 2;
- }
for (; i >= 0; i--)
{
* Function : ssl_verify_callback
*
* Description : This is a callback function for certificate verification.
- * It's called for all certificates in server certificate
- * trusted chain and it's preparing information about this
- * certificates. Prepared informations can be used to inform
- * user about invalid certificates.
+ * It's called once for each certificate in the server's
+ * certificate trusted chain and prepares information about
+ * the certificate. The information can be used to inform
+ * the user about invalid certificates.
*
* Parameters :
* 1 : csp_void = Current client state (buffers, headers, etc...)
crt->raw.p, crt->raw.len, (unsigned char *)last->file_buf,
sizeof(last->file_buf)-1, &olen)) != 0)
{
+ char err_buf[ERROR_BUF_SIZE];
+
+ mbedtls_strerror(ret, err_buf, sizeof(err_buf));
+ log_error(LOG_LEVEL_ERROR, "mbedtls_pem_write_buffer() failed: %s",
+ err_buf);
+
return(ret);
}
csp->server_certs_chain.next = NULL;
/* Freeing memory in whole linked list */
- if (cert != NULL)
+ while (cert != NULL)
{
- do
- {
- struct certs_chain *cert_for_free = cert;
- cert = cert->next;
- freez(cert_for_free);
- } while (cert != NULL);
+ struct certs_chain *cert_for_free = cert;
+ cert = cert->next;
+ freez(cert_for_free);
}
}