Support decrypting a server CA certificate so we can get its expiration (valid-before...
authorDan Breslau <dbreslau@painless-security.com>
Fri, 12 Aug 2016 02:44:21 +0000 (22:44 -0400)
committerDan Breslau <dbreslau@painless-security.com>
Fri, 12 Aug 2016 02:44:21 +0000 (22:44 -0400)
Makefile.am
src/moonshot-crypto-utils.c [new file with mode: 0644]
src/moonshot-id.vala
src/moonshot-provisioning-common.vala

index 4f40dd4..a578f76 100644 (file)
@@ -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 (file)
index 0000000..c28e835
--- /dev/null
@@ -0,0 +1,34 @@
+#include <string.h>
+#include <openssl/bio.h>
+#include <openssl/pem.h>
+
+
+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 "";
+}
index 0895d1e..df5dd18 100644 (file)
 
 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";
 
index 87d7630..b18cd8b 100644 (file)
@@ -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)
             {