#include "gtlscertificate-gnutls.h"
#include <glib/gi18n-lib.h>
+#include "TIZEN.h"
static void g_tls_certificate_gnutls_initable_iface_init (GInitableIface *iface);
}
}
+#if ENABLE(TIZEN_TV_ADJUST_TIME)
+extern double soupTimeOffset;
+
+static time_t
+correct_time_func(time_t *t)
+{
+ return time(NULL) + (time_t)(soupTimeOffset / 1000);
+}
+#endif
+
static void
g_tls_certificate_gnutls_init (GTlsCertificateGnutls *gnutls)
{
GTlsCertificateGnutlsPrivate);
gnutls_x509_crt_init (&gnutls->priv->cert);
+#if ENABLE(TIZEN_TV_ADJUST_TIME)
+ gnutls_global_set_time_function(correct_time_func);
+#endif
}
static gboolean
gnutls_x509_crt_t *chain;
GTlsCertificateFlags gtls_flags;
time_t t, now;
+#if ENABLE(TIZEN_TV_DLOG)
+ char timebuf[256];
+#endif
+
cert_gnutls = G_TLS_CERTIFICATE_GNUTLS (cert);
for (num_certs = 0; cert_gnutls; cert_gnutls = cert_gnutls->priv->issuer)
* won't bother if it gets an UNKNOWN_CA.
*/
now = time (NULL);
+#if ENABLE(TIZEN_TV_ADJUST_TIME)
+ now = time (NULL) + (time_t)(soupTimeOffset / 1000);
+#endif
for (i = 0; i < num_certs; i++)
{
t = gnutls_x509_crt_get_activation_time (chain[i]);
+
+#if ENABLE(TIZEN_TV_DLOG)
+ ctime_r(&now, timebuf);
+ TIZEN_LOGI("[Certificate] TV borad time is: %s", timebuf);
+ if (t != (time_t) -1) {
+ ctime_r(&t, timebuf);
+ TIZEN_LOGI("[Certificate] CA activation time is: %s", timebuf);
+ }
+ else
+ TIZEN_LOGI("[Certificate] gnutls_x509_crt_get_activation_time ERROR");
+#endif
+
if (t == (time_t) -1 || t > now)
gtls_flags |= G_TLS_CERTIFICATE_NOT_ACTIVATED;
t = gnutls_x509_crt_get_expiration_time (chain[i]);
+
+#if ENABLE(TIZEN_TV_DLOG)
+ if (t != (time_t) -1) {
+ ctime_r(&t, timebuf);
+ TIZEN_LOGI("[Certificate] CA expiration time is: %s", timebuf);
+ }
+ else
+ TIZEN_LOGI("[Certificate] gnutls_x509_crt_get_expiration_time ERROR");
+#endif
+
if (t == (time_t) -1 || t < now)
gtls_flags |= G_TLS_CERTIFICATE_EXPIRED;
}
const gchar *interaction_id,
gnutls_retr2_st *st)
{
+ GTlsCertificateGnutls *chain;
gnutls_x509_crt_t cert;
gnutls_datum_t data;
+ guint num_certs = 0;
size_t size = 0;
- gnutls_x509_crt_export (gnutls->priv->cert, GNUTLS_X509_FMT_DER,
- NULL, &size);
- data.data = g_malloc (size);
- data.size = size;
- gnutls_x509_crt_export (gnutls->priv->cert, GNUTLS_X509_FMT_DER,
- data.data, &size);
+ /* We will do this loop twice. It's probably more efficient than
+ * re-allocating memory.
+ */
+ chain = gnutls;
+ while (chain != NULL)
+ {
+ num_certs++;
+ chain = chain->priv->issuer;
+ }
+
+ st->ncerts = 0;
+ st->cert.x509 = gnutls_malloc (sizeof (gnutls_x509_crt_t) * num_certs);
+
+/* Now do the actual copy of the whole chain. */
+ chain = gnutls;
+ while (chain != NULL)
+ {
+ gnutls_x509_crt_export (chain->priv->cert, GNUTLS_X509_FMT_DER,
+ NULL, &size);
+ data.data = g_malloc (size);
+ data.size = size;
+ gnutls_x509_crt_export (chain->priv->cert, GNUTLS_X509_FMT_DER,
+ data.data, &size);
- gnutls_x509_crt_init (&cert);
- gnutls_x509_crt_import (cert, &data, GNUTLS_X509_FMT_DER);
- g_free (data.data);
+ gnutls_x509_crt_init (&cert);
+ gnutls_x509_crt_import (cert, &data, GNUTLS_X509_FMT_DER);
+ g_free (data.data);
- st->ncerts = 1;
- st->cert.x509 = gnutls_malloc (sizeof (gnutls_x509_crt_t));
- st->cert.x509[0] = cert;
+ st->cert.x509[st->ncerts] = cert;
+ st->ncerts++;
+
+ chain = chain->priv->issuer;
+ }
if (gnutls->priv->key != NULL)
{
/* FIXME: check sRVName and uniformResourceIdentifier
* subjectAltNames, if appropriate for @identity.
*/
+#if ENABLE(TIZEN_TV_DLOG)
+ TIZEN_LOGI("[Network] SSL HandShake - Bad Identity");
+#endif
return G_TLS_CERTIFICATE_BAD_IDENTITY;
}
g_object_get (gnutls, "certificate", &array, NULL);
return g_byte_array_free_to_bytes (array);
}
+
+static gnutls_x509_crt_t *
+convert_data_to_gnutls_certs (const gnutls_datum_t *certs,
+ guint num_certs,
+ gnutls_x509_crt_fmt_t format)
+{
+ gnutls_x509_crt_t *gnutls_certs;
+ guint i;
+
+ gnutls_certs = g_new (gnutls_x509_crt_t, num_certs);
+
+ for (i = 0; i < num_certs; i++)
+ {
+ if (gnutls_x509_crt_init (&gnutls_certs[i]) < 0)
+ {
+ i--;
+ goto error;
+ }
+ }
+
+ for (i = 0; i < num_certs; i++)
+ {
+ if (gnutls_x509_crt_import (gnutls_certs[i], &certs[i], format) < 0)
+ {
+ i = num_certs - 1;
+ goto error;
+ }
+ }
+
+ return gnutls_certs;
+
+error:
+ for (; i != G_MAXUINT; i--)
+ gnutls_x509_crt_deinit (gnutls_certs[i]);
+ g_free (gnutls_certs);
+ return NULL;
+}
+
+GTlsCertificateGnutls *
+g_tls_certificate_gnutls_build_chain (const gnutls_datum_t *certs,
+ guint num_certs,
+ gnutls_x509_crt_fmt_t format)
+{
+ GPtrArray *glib_certs;
+ gnutls_x509_crt_t *gnutls_certs;
+ GTlsCertificateGnutls *issuer;
+ GTlsCertificateGnutls *result;
+ guint i, j;
+
+ g_return_val_if_fail (certs, NULL);
+
+ gnutls_certs = convert_data_to_gnutls_certs (certs, num_certs, format);
+ if (!gnutls_certs)
+ return NULL;
+
+ glib_certs = g_ptr_array_new_full (num_certs, g_object_unref);
+ for (i = 0; i < num_certs; i++)
+ g_ptr_array_add (glib_certs, g_tls_certificate_gnutls_new (&certs[i], NULL));
+
+ /* Some servers send certs out of order, or will send duplicate
+ * certs, so we need to be careful when assigning the issuer of
+ * our new GTlsCertificateGnutls.
+ */
+ for (i = 0; i < num_certs; i++)
+ {
+ issuer = NULL;
+
+ if (i < num_certs - 1 &&
+ gnutls_x509_crt_check_issuer (gnutls_certs[i], gnutls_certs[i + 1]))
+ {
+ issuer = glib_certs->pdata[i + 1];
+ }
+ else
+ {
+ for (j = 0; j < num_certs; j++)
+ {
+ if (j != i &&
+ gnutls_x509_crt_check_issuer (gnutls_certs[i], gnutls_certs[j]))
+ {
+ issuer = glib_certs->pdata[j];
+ break;
+ }
+ }
+ }
+
+ if (issuer)
+ g_tls_certificate_gnutls_set_issuer (glib_certs->pdata[i], issuer);
+ }
+
+ result = g_object_ref (glib_certs->pdata[0]);
+ g_ptr_array_unref (glib_certs);
+
+ for (i = 0; i < num_certs; i++)
+ gnutls_x509_crt_deinit (gnutls_certs[i]);
+ g_free (gnutls_certs);
+
+ return result;
+}