[rs-commit] r73 - in /redwax-signtext/trunk/src/linux: crypto.c crypto.h message.c signtext.c signtext.h
rs-commit at redwax.eu
rs-commit at redwax.eu
Tue Sep 20 14:28:10 CEST 2022
Author: minfrin at redwax.eu
Date: Tue Sep 20 14:28:08 2022
New Revision: 73
Log:
Wire in support for the CA strings.
Modified:
redwax-signtext/trunk/src/linux/crypto.c
redwax-signtext/trunk/src/linux/crypto.h
redwax-signtext/trunk/src/linux/message.c
redwax-signtext/trunk/src/linux/signtext.c
redwax-signtext/trunk/src/linux/signtext.h
Modified: redwax-signtext/trunk/src/linux/crypto.c
==============================================================================
--- redwax-signtext/trunk/src/linux/crypto.c (original)
+++ redwax-signtext/trunk/src/linux/crypto.c Tue Sep 20 14:28:08 2022
@@ -27,67 +27,67 @@
#define CK_CERTIFICATE_CATEGORY_TOKEN_USER 0x00000001UL
#endif
+gboolean
+crypto_instance_append_ca(SignTextInstance *instance, const gchar *ca, GError **gerror)
+{
+ GBytes *bytes;
+ unsigned char *rder;
+ size_t rder_len;
+ gpg_error_t err;
+
+ g_printerr("crypto_instance_append_ca: %s\n", ca);
+
+ err = ksba_dn_str2der(ca, &rder, &rder_len);
+ if (err) {
+ *gerror = g_error_new(RST_CORE_ERROR, RST_CORE_ERROR_INVALID_CA, "Requested issuer '%s' cannot be parsed.", ca);
+ return FALSE;
+ }
+
+#if 0
+ g_printerr("crypto_instance_append_ca: len %d: ", (int)rder_len);
+for (size_t i = 0; i < rder_len; i++)
+ g_printerr("%02x", rder[i]);
+g_printerr("\n");
+
+char *str;
+ksba_dn_der2str(rder, rder_len, &str);
+ g_printerr("crypto_instance_append_ca: der2str %s\n", str);
+#endif
+
+ bytes = g_bytes_new_with_free_func(rder, rder_len, (GDestroyNotify)g_free, rder);
+
+ instance->cas = g_list_append(instance->cas, bytes);
+
+ return TRUE;
+}
+
static gboolean
crypto_filter_match (GObject *obj,
gpointer data)
{
+ SignTextInstance *instance = data;
GckAttributes *attrs;
-
- ksba_cert_t cert;
-
- const guint8 *der;
- gsize der_len;
+ GcrCertificateChain *chain;
gulong category;
- gboolean is_ca;
- unsigned int usage;
-
- gpg_error_t err;
-
- if (!GCR_IS_PKCS11_CERTIFICATE(obj)) {
+ GcrCertificateChainStatus status;
+
+ g_assert(GCR_IS_PKCS11_CERTIFICATE(obj));
+
+ g_printerr("crypto_filter_match\n");
+
+ chain = g_object_get_data(G_OBJECT (obj), "chain");
+
+ g_assert(GCR_IS_CERTIFICATE_CHAIN(chain));
+
+ status = gcr_certificate_chain_get_status(chain);
+
+ switch (status) {
+ case GCR_CERTIFICATE_CHAIN_ANCHORED:
+ break;
+ default:
return FALSE;
}
-
-
- der = gcr_certificate_get_der_data(GCR_CERTIFICATE(obj), &der_len);
- if (!der) {
- return FALSE;
- }
-
- err = ksba_cert_new(&cert);
- if (err) {
- return FALSE;
- }
-
- err = ksba_cert_init_from_mem(cert, der, der_len);
- if (err) {
- ksba_cert_release(cert);
- return FALSE;
- }
-
- /*
- * Is the key usage section missing?
- *
- * If so, ignore this cert.
- */
- err = ksba_cert_get_key_usage(cert, &usage);
- if (err) {
- ksba_cert_release(cert);
- return FALSE;
- }
-
- /*
- * Does our certificate report a key usage of KSBA_KEYUSAGE_DIGITAL_SIGNATURE?
- *
- * If not, the cert needs to be ignored.
- */
- if (!(usage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE)) {
- ksba_cert_release(cert);
- return FALSE;
- }
-
- ksba_cert_release(cert);
-
attrs = gcr_pkcs11_certificate_get_attributes(GCR_PKCS11_CERTIFICATE(obj));
@@ -102,26 +102,66 @@
}
}
- /*
- * Is our certificate an intermediate? Filter them out at this stage.
- */
- if (gcr_certificate_get_basic_constraints(GCR_CERTIFICATE(obj), &is_ca, NULL)) {
- if (is_ca) {
- return FALSE;
- }
+ g_printerr("crypto_filter_match: len %d\n", g_list_length(instance->cas));
+
+ if (instance->cas && g_list_length(instance->cas)) {
+
+ int i, len;
+
+ len = gcr_certificate_chain_get_length(chain);
+
+ for (i = 0; i < len; i++) {
+
+ GcrCertificate *certificate;
+ guchar *der;
+ gsize der_len;
+
+ GBytes *dn;
+
+ certificate = gcr_certificate_chain_get_certificate(chain, i);
+
+// g_printerr("crypto_filter_match: consider cert issuer %s\n", gcr_certificate_get_issuer_dn(certificate));
+
+
+ der = gcr_certificate_get_issuer_raw(certificate, &der_len);
+ dn = g_bytes_new_with_free_func(der, der_len, (GDestroyNotify)g_free, der);
+
+#if 0
+ g_printerr("crypto_filter_match: len %d: ", (int)der_len);
+for (size_t i = 0; i < der_len; i++)
+ g_printerr("%02x", der[i]);
+g_printerr("\n");
+
+char *str;
+ksba_dn_der2str(der, der_len, &str);
+ g_printerr("crypto_filter_match: der2str %s\n", str);
+#endif
+
+ if (g_list_find_custom(instance->cas, dn, g_bytes_compare)) {
+ g_bytes_unref(dn);
+ g_printerr("crypto_filter_match: found\n");
+ return TRUE;
+ }
+
+ g_bytes_unref(dn);
+ }
+
+ g_printerr("crypto_filter_match: not found\n");
+
+ return FALSE;
}
return TRUE;
}
GcrCollection *
-crypto_filter(GcrCollection *certificates)
+crypto_filter(SignTextInstance *instance, GcrCollection *certificates)
{
GcrCollection *collection;
collection = gcr_filter_collection_new_with_callback (GCR_COLLECTION (certificates),
crypto_filter_match,
- NULL, NULL);
+ instance, NULL);
return collection;
@@ -151,6 +191,108 @@
static gboolean
crypto_slot_do (gpointer user_data);
+static gboolean
+crypto_chain_do (gpointer user_data);
+
+static void
+crypto_chain_done (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ SignTextData *signtext = user_data;
+ GcrCertificateChain *chain = GCR_CERTIFICATE_CHAIN(source_object);
+ GcrCertificate *certificate;
+ GError *gerror = NULL;
+ GcrCertificateChainStatus status;
+
+ g_printerr("crypto_chain_done\n");
+
+ if (!gcr_certificate_chain_build_finish(chain, res, &gerror)) {
+ goto fatal;
+ }
+
+ certificate = gcr_certificate_chain_get_endpoint(chain);
+
+ g_object_set_data_full(G_OBJECT(certificate), "chain",
+ g_object_ref(chain),
+ (GDestroyNotify)g_object_unref);
+
+ status = gcr_certificate_chain_get_status(chain);
+
+ switch (status) {
+ case GCR_CERTIFICATE_CHAIN_ANCHORED:
+ g_printerr("crypto_chain_done: anchored\n");
+ break;
+ default:
+ g_printerr("crypto_chain_done: not anchored\n");
+ break;
+ }
+
+ signtext->incoming_len++;
+
+ if (signtext->incoming_len < gcr_collection_get_length(signtext->incoming)) {
+ g_idle_add((GSourceFunc)crypto_chain_do, signtext);
+ }
+ else {
+
+ GList *incoming, *current, *l;
+
+ incoming = gcr_collection_get_objects(signtext->incoming);
+
+ for (l = incoming; l; l = g_list_next (l)) {
+ if (!gcr_collection_contains(signtext->certificates, l->data)) {
+ g_object_ref(l->data);
+ gcr_simple_collection_add(GCR_SIMPLE_COLLECTION(signtext->certificates), l->data);
+g_printerr("crypto_chain_done: add\n");
+ }
+ }
+
+ current = gcr_collection_get_objects(signtext->certificates);
+
+ for (l = current; l; l = g_list_next (l)) {
+ if (!gcr_collection_contains(signtext->incoming, l->data)) {
+ gcr_simple_collection_remove(GCR_SIMPLE_COLLECTION(signtext->certificates), l->data);
+ g_object_unref(l->data);
+g_printerr("crypto_chain_done: remove\n");
+ }
+ }
+
+ g_object_unref(signtext->incoming);
+ signtext->incoming = gcr_simple_collection_new();
+
+ g_timeout_add_seconds(2, crypto_slots_do, signtext);
+ }
+
+ if (gerror) {
+fatal:
+ signtext_error (NULL, gerror);
+ g_error_free (gerror);
+ }
+
+}
+
+static gboolean
+crypto_chain_do (gpointer user_data)
+{
+ SignTextData *signtext = user_data;
+
+ GList *incoming = gcr_collection_get_objects (signtext->incoming);
+
+ GList *current = g_list_nth (incoming, signtext->incoming_len);
+
+ GcrCertificateChain *chain = gcr_certificate_chain_new();
+
+ g_printerr("crypto_chain_do\n");
+
+ gcr_certificate_chain_add (chain, current->data);
+
+ gcr_certificate_chain_build_async(chain, GCR_PURPOSE_CLIENT_AUTH, NULL, GCR_CERTIFICATE_CHAIN_NONE, signtext->cancellable, crypto_chain_done, signtext);
+
+ g_list_free(incoming);
+
+ return FALSE;
+}
+
static void
crypto_slot_done (GObject *source_object,
GAsyncResult *res,
@@ -158,7 +300,7 @@
{
SignTextToken *signtext_token = user_data;
SignTextData *signtext = signtext_token->signtext;
- GList *incoming, *current, *l;
+ GList *incoming, *l;
GError *gerror = NULL;
guint certificates_len;
@@ -167,6 +309,18 @@
incoming = gck_enumerator_next_finish(GCK_ENUMERATOR(source_object), res, &gerror);
for (l = incoming, certificates_len = 0; l; l = g_list_next (l), certificates_len++) {
+
+ gboolean is_ca;
+
+ /*
+ * Is our certificate an intermediate? Filter them out at this stage.
+ */
+ if (gcr_certificate_get_basic_constraints(GCR_CERTIFICATE(l->data), &is_ca, NULL)) {
+ if (is_ca) {
+ continue;
+ }
+ }
+
if (!gcr_collection_contains(signtext->incoming, l->data)) {
g_object_ref(l->data);
@@ -190,29 +344,7 @@
g_idle_add((GSourceFunc)crypto_slot_do, signtext_token->next);
}
else {
-
- incoming = gcr_collection_get_objects(signtext->incoming);
-
- for (l = incoming; l; l = g_list_next (l)) {
- if (!gcr_collection_contains(signtext->certificates, l->data)) {
- g_object_ref(l->data);
- gcr_simple_collection_add(GCR_SIMPLE_COLLECTION(signtext->certificates), l->data);
- }
- }
-
- current = gcr_collection_get_objects(signtext->certificates);
-
- for (l = current; l; l = g_list_next (l)) {
- if (!gcr_collection_contains(signtext->incoming, l->data)) {
- gcr_simple_collection_remove(GCR_SIMPLE_COLLECTION(signtext->certificates), l->data);
- g_object_unref(l->data);
- }
- }
-
- g_object_unref(signtext->incoming);
- signtext->incoming = gcr_simple_collection_new();
-
- g_timeout_add_seconds(2, crypto_slots_do, signtext_token->signtext);
+ g_idle_add((GSourceFunc)crypto_chain_do, signtext);
}
signtext_token_free(signtext_token);
@@ -293,6 +425,7 @@
signtext->slots_len = slots_len;
signtext->certificates_len = 0;
+ signtext->incoming_len = 0;
return FALSE;
}
Modified: redwax-signtext/trunk/src/linux/crypto.h
==============================================================================
--- redwax-signtext/trunk/src/linux/crypto.h (original)
+++ redwax-signtext/trunk/src/linux/crypto.h Tue Sep 20 14:28:08 2022
@@ -26,10 +26,13 @@
crypto_start(SignTextData *signtext);
GcrCollection *
-crypto_filter(GcrCollection *certificates);
+crypto_filter(SignTextInstance *instance, GcrCollection *certificates);
void
crypto_instance_start(SignTextInstance *instance, GcrCollection *certificates);
+
+gboolean
+crypto_instance_append_ca(SignTextInstance *instance, const gchar *ca, GError **gerror);
void
crypto_sign(SignTextInstance *instance);
Modified: redwax-signtext/trunk/src/linux/message.c
==============================================================================
--- redwax-signtext/trunk/src/linux/message.c (original)
+++ redwax-signtext/trunk/src/linux/message.c Tue Sep 20 14:28:08 2022
@@ -47,7 +47,7 @@
/*
* Send an error to show we cancelled.
*/
- message_send_error(instance, "error:cancelled");
+ message_send_error(instance, "error:userCancel");
signtext_instance_free(instance);
@@ -163,7 +163,23 @@
*/
else if (json_node_get_node_type(request) == JSON_NODE_OBJECT) {
- GcrCollection *certificates = crypto_filter(signtext->certificates);
+ GcrCollection *certificates;
+
+ JsonArray *cas = json_object_get_array_member(json_node_get_object(request), "CAs");
+
+ if (cas) {
+ guint len = json_array_get_length(cas);
+ guint i;
+
+ for (i = 0; i < len; i++) {
+ const gchar *ca = json_array_get_string_element(cas, i);
+
+ crypto_instance_append_ca(instance, ca, &gerror);
+ }
+
+ }
+
+ certificates = crypto_filter(instance, signtext->certificates);
crypto_instance_start(instance, certificates);
@@ -470,7 +486,7 @@
json_builder_set_member_name(builder, "id");
json_builder_add_int_value(builder, instance->id);
json_builder_set_member_name(builder, "error");
- json_builder_add_string_value(builder, "error:cancelled");
+ json_builder_add_string_value(builder, "error:userCancel");
json_builder_end_object(builder);
root = json_builder_get_root(builder);
Modified: redwax-signtext/trunk/src/linux/signtext.c
==============================================================================
--- redwax-signtext/trunk/src/linux/signtext.c (original)
+++ redwax-signtext/trunk/src/linux/signtext.c Tue Sep 20 14:28:08 2022
@@ -173,6 +173,12 @@
if (instance->w) {
ksba_writer_release(instance->w);
}
+
+ if (instance->cas) {
+ g_list_foreach(instance->cas, (GFunc)g_bytes_unref, NULL);
+ g_list_free (instance->cas);
+ }
+
}
g_free(instance);
}
Modified: redwax-signtext/trunk/src/linux/signtext.h
==============================================================================
--- redwax-signtext/trunk/src/linux/signtext.h (original)
+++ redwax-signtext/trunk/src/linux/signtext.h Tue Sep 20 14:28:08 2022
@@ -44,6 +44,7 @@
RST_CORE_ERROR_MISSING_REQUEST,
RST_CORE_ERROR_MISSING_CONTENT_TYPE,
RST_CORE_ERROR_REQUEST_NOT_RECOGNISED,
+ RST_CORE_ERROR_INVALID_CA,
RST_CORE_ERROR_NO_MODULES,
RST_CORE_ERROR_SIGN_ERROR,
} SignTextCoreError;
@@ -61,6 +62,7 @@
guint modules_len;
guint slots_len;
guint certificates_len;
+ guint incoming_len;
} SignTextData;
typedef struct SignTextToken SignTextToken;
@@ -78,6 +80,8 @@
gchar *uuid;
gint64 id;
gboolean detached;
+
+ GList *cas;
GtkStack *stack;
GtkProgressBar *progress;
More information about the rs-commit
mailing list