From 133e43a14fb57c62771186d4edb42fbab9e8fcf0 Mon Sep 17 00:00:00 2001 From: Dan Breslau Date: Thu, 11 Aug 2016 22:44:21 -0400 Subject: [PATCH] Support decrypting a server CA certificate so we can get its expiration (valid-before) date. --- Makefile.am | 6 ++++-- src/moonshot-crypto-utils.c | 34 ++++++++++++++++++++++++++++++++++ src/moonshot-id.vala | 34 +++++++++++++++++++++++++++++++--- src/moonshot-provisioning-common.vala | 10 +++++++++- 4 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 src/moonshot-crypto-utils.c diff --git a/Makefile.am b/Makefile.am index 4f40dd4..a578f76 100644 --- a/Makefile.am +++ b/Makefile.am @@ -71,10 +71,12 @@ src_moonshot_SOURCES = \ src/moonshot-trust-anchor-dialog.vala \ src/moonshot-utils.vala \ src/moonshot-futils.c \ + src/moonshot-crypto-utils.c \ src/moonshot-logger.vala \ src/moonshot-warning-dialog.vala src_moonshot_webp_SOURCES = \ + src/moonshot-crypto-utils.c \ src/moonshot-webp-parser.vala \ src/moonshot-provisioning-common.vala \ src/moonshot-id.vala \ @@ -121,8 +123,8 @@ if OS_LINUX AM_CPPFLAGS += -I/usr/include/gnome-keyring-1 AM_VALAFLAGS += --pkg moonshot-gnome-keyring --define=GNOME_KEYRING -src_moonshot_LDFLAGS += -lgnome-keyring -src_moonshot_webp_LDFLAGS += -lgnome-keyring +src_moonshot_LDFLAGS += -lgnome-keyring -lcrypto +src_moonshot_webp_LDFLAGS += -lgnome-keyring -lcrypto ## Installing mime type data mimedir = $(datadir)/mime/packages diff --git a/src/moonshot-crypto-utils.c b/src/moonshot-crypto-utils.c new file mode 100644 index 0000000..c28e835 --- /dev/null +++ b/src/moonshot-crypto-utils.c @@ -0,0 +1,34 @@ +#include +#include +#include + + +char* get_cert_valid_before(const char* cert_string, int cert_string_len, char* datebuf, int len) +{ + datebuf[0]='\0'; + + BIO* cert_bio = BIO_new_mem_buf(cert_string, cert_string_len); + + if (cert_bio == NULL) { + return "Error calling PEM_new_mem_buf!"; + } + + X509 *x = PEM_read_bio_X509(cert_bio, NULL, 0, NULL); + if (x == NULL) { + return "Error calling PEM_read_bio_X509!"; + } + + BIO* out_bio = BIO_new(BIO_s_mem()); + ASN1_TIME* time = X509_get_notAfter(x); + + if (ASN1_TIME_print(out_bio, time)) { + int write = BIO_read(out_bio, datebuf, len - 1); + datebuf[write]='\0'; + } + + datebuf[len - 1] = '\0'; + BIO_free(out_bio); + BIO_free(cert_bio); + X509_free(x); + return ""; +} diff --git a/src/moonshot-id.vala b/src/moonshot-id.vala index 0895d1e..df5dd18 100644 --- a/src/moonshot-id.vala +++ b/src/moonshot-id.vala @@ -32,8 +32,14 @@ using Gee; +extern char* get_cert_valid_before(char* cert, int certlen, char* datebuf, int buflen); + + public class TrustAnchor : Object { + private static const string CERT_HEADER = "-----BEGIN CERTIFICATE-----"; + private static const string CERT_FOOTER = "-----END CERTIFICATE-----"; + public enum TrustAnchorType { CA_CERT, SERVER_CERT @@ -108,11 +114,33 @@ public class TrustAnchor : Object return null; } - //!!TODO read expiration date - return ""; + string cert = this.ca_cert; + cert.chomp(); + if (cert.substring(0, CERT_HEADER.length) != CERT_HEADER) { + cert = CERT_HEADER + "\n" + cert; + } + if (cert.substring(0, -CERT_FOOTER.length) != CERT_FOOTER) { + cert += "\n" + CERT_FOOTER; + } + cert += "\n"; + + IdCard.logger.trace(@"get_expiration_date: Sending " + cert); + + char buf[64]; + string err = (string) read_cert_expiration(cert, cert.length, buf, 64); + if (err != "") { + IdCard.logger.error(@"get_expiration_date: got back '$err'"); + return err; + } + + string date = (string) buf; + IdCard.logger.trace(@"get_expiration_date: got back '$date'"); + + return date; } } + public struct Rule { public string pattern; @@ -128,7 +156,7 @@ public struct Rule public class IdCard : Object { - static MoonshotLogger logger = get_logger("IdCard"); + internal static MoonshotLogger logger = get_logger("IdCard"); public const string NO_IDENTITY = "No Identity"; diff --git a/src/moonshot-provisioning-common.vala b/src/moonshot-provisioning-common.vala index 87d7630..b18cd8b 100644 --- a/src/moonshot-provisioning-common.vala +++ b/src/moonshot-provisioning-common.vala @@ -238,8 +238,16 @@ namespace WebProvisioning { var dis = new DataInputStream(file.read()); string line; - while ((line = dis.read_line(null)) != null) + while ((line = dis.read_line(null)) != null) { text += line; + + // Preserve newlines -- important for certificate import. + // (X509 certs can't be parsed without the newlines.) + // + // This may add an extra newline at EOF. Maybe use + // dis.read_upto("\n", ...) followed by dis.read_byte() instead? + text += "\n"; + } } catch(GLib.Error e) { -- 2.1.4