Split X509 decoding into a separate module, ssl.x509

Fri, 05 Nov 2010 20:48:06 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Fri, 05 Nov 2010 20:48:06 +0000
changeset 14
1927b7b32faf
parent 13
ebe0d286481c
child 15
f1de983ff659

Split X509 decoding into a separate module, ssl.x509

src/Makefile file | annotate | diff | comparison | revisions
src/ssl.c file | annotate | diff | comparison | revisions
src/ssl.lua file | annotate | diff | comparison | revisions
src/x509.c file | annotate | diff | comparison | revisions
src/x509.h file | annotate | diff | comparison | revisions
--- a/src/Makefile	Fri Nov 05 20:47:20 2010 +0000
+++ b/src/Makefile	Fri Nov 05 20:48:06 2010 +0000
@@ -7,6 +7,7 @@
  io.o \
  usocket.o \
  context.o \
+ x509.o \
  ssl.o
 
 LIBS=-lssl -lcrypto
@@ -59,4 +60,5 @@
 timeout.o: timeout.c timeout.h
 usocket.o: usocket.c socket.h io.h timeout.h usocket.h
 context.o: context.c context.h
+x509.o: x509.c x509.h
 ssl.o: ssl.c socket.h io.h timeout.h usocket.h buffer.h context.h context.c
--- a/src/ssl.c	Fri Nov 05 20:47:20 2010 +0000
+++ b/src/ssl.c	Fri Nov 05 20:48:06 2010 +0000
@@ -418,128 +418,17 @@
 static int meth_getpeercertificate(lua_State *L)
 {
   X509 *peer;
-  int i, j;
   p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
   peer = SSL_get_peer_certificate(ssl->ssl);
   if (peer == NULL) {
     /* No client certificate available */
-    lua_pushboolean(L, 0);
-    return 1;
+    lua_pushnil(L);
   }
   else
   {
-    X509_NAME *subject;
-    int n_entries;
-
-    lua_newtable(L); /* ret */
-
-    lua_pushboolean(L, (SSL_get_verify_result(ssl->ssl) == X509_V_OK));
-    lua_setfield(L, -2, "trusted");
-
-    subject = X509_get_subject_name(peer);
-
-    n_entries = X509_NAME_entry_count(subject);
-
-    lua_newtable(L); /* {} */
-    lua_pushvalue(L, -1);
-    lua_setfield(L, -3, "subject"); /* ret.subject = {} */
-    for(i = 0; i <= n_entries; i++)
-    {
-      X509_NAME_ENTRY *entry;
-      ASN1_OBJECT *object;
-
-      entry = X509_NAME_get_entry(subject, i);
-      object = X509_NAME_ENTRY_get_object(entry);
-
-      luasec_push_asn1_objname(L, object, 1);
-
-      if(luasec_push_subtable(L, -2))
-      {
-        /* Get short/long name of the entry */
-        luasec_push_asn1_objname(L, object, 0);
-        lua_setfield(L, -2, "name");
-      }
-
-      luasec_push_asn1_string(L, X509_NAME_ENTRY_get_data(entry));
-      lua_rawseti(L, -2, lua_objlen(L, -2)+1);
-
-      lua_pop(L, 1);
-    }
+    /* Push metatabled peer */
+    luasec_push_x509(L, peer);
   }
-  lua_pop(L, 1); /* ret.subject */
-
-  lua_newtable(L); /* {} */
-  lua_pushvalue(L, -1);
-  lua_setfield(L, -3, "extensions"); /* ret.extensions = {} */
-
-  i = -1;
-  while((i = X509_get_ext_by_NID(peer, NID_subject_alt_name, i)) != -1)
-  {
-    X509_EXTENSION *extension;
-    STACK_OF(GENERAL_NAME) *values;
-    int n_general_names;
-
-    extension = X509_get_ext(peer, i);
-    if(extension == NULL)
-      break;
-
-    values = X509V3_EXT_d2i(extension);
-    if(values == NULL)
-      break;
-
-    /* Push ret.extensions[oid] */
-    luasec_push_asn1_objname(L, extension->object, 1);
-    luasec_push_subtable(L, -2);
-    /* Set ret.extensions[oid].name = name */
-    luasec_push_asn1_objname(L, extension->object, 0);
-    lua_setfield(L, -2, "name");
-
-    n_general_names = sk_GENERAL_NAME_num(values);
-    for(j = 0; j < n_general_names; j++)
-    {
-      GENERAL_NAME *general_name;
-
-      general_name = sk_GENERAL_NAME_value(values, j);
-
-      switch(general_name->type)
-      {
-      case GEN_OTHERNAME:
-      {
-        OTHERNAME *otherName = general_name->d.otherName;
-
-        luasec_push_asn1_objname(L, otherName->type_id, 1);
-
-        if(luasec_push_subtable(L, -2))
-        {
-          luasec_push_asn1_objname(L, otherName->type_id, 0);
-          lua_setfield(L, -2, "name");
-        }
-
-        luasec_push_asn1_string(L, otherName->value->value.asn1_string);
-        lua_rawseti(L, -2, lua_objlen(L, -2)+1);
-
-        lua_pop(L, 1);
-        break;
-      }
-      case GEN_DNS:
-      {
-        lua_pushstring(L, "dNSName");
-	luasec_push_subtable(L, -2);
-        luasec_push_asn1_string(L, general_name->d.dNSName);
-        lua_rawseti(L, -2, lua_objlen(L, -2)+1);
-        lua_pop(L, 1);
-        break;
-      }
-      default:
-        break;
-      }
-    }
-
-    lua_pop(L, 1); /* array */
-    i++; /* Next extension */
-  }
-  lua_pop(L, 1); /* ret.extensions */
-
   return 1;
 }
 
--- a/src/ssl.lua	Fri Nov 05 20:47:20 2010 +0000
+++ b/src/ssl.lua	Fri Nov 05 20:48:06 2010 +0000
@@ -8,6 +8,7 @@
 
 require("ssl.core")
 require("ssl.context")
+require("ssl.x509")
 
 
 _VERSION   = "0.4"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/x509.c	Fri Nov 05 20:48:06 2010 +0000
@@ -0,0 +1,169 @@
+/*--------------------------------------------------------------------------
+ * LuaSec 0.4
+ * Copyright (C) 2006-2009 Bruno Silvestre
+ *
+ *--------------------------------------------------------------------------*/
+
+#include <string.h>
+
+#include <openssl/ssl.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+
+#include <lua.h>
+#include <lauxlib.h>
+
+#include "io.h"
+#include "buffer.h"
+#include "timeout.h"
+#include "socket.h"
+#include "ssl.h"
+#include "x509.h"
+
+#define min(a, b) (a<b)?a:b
+
+void luasec_push_x509(lua_State* L, X509 *cert)
+{
+  p_x509 cert_obj = (p_x509) lua_newuserdata(L, sizeof(t_x509));
+  cert_obj->cert = cert;
+  luaL_getmetatable(L, "SSL:Certificate");
+  lua_setmetatable(L, -2);
+}
+
+X509* luasec_to_x509(lua_State* L, int idx)
+{
+  return ((p_x509)luaL_checkudata(L, idx, "SSL:Certificate"))->cert;
+}
+
+int meth_decode(lua_State* L)
+{
+  X509 *peer;
+  X509_NAME *subject;
+  int i, j, n_entries;
+
+  peer = luasec_to_x509(L, 1);
+
+  lua_newtable(L); /* ret */
+
+  subject = X509_get_subject_name(peer);
+
+  n_entries = X509_NAME_entry_count(subject);
+
+  lua_newtable(L); /* {} */
+  lua_pushvalue(L, -1);
+  lua_setfield(L, -3, "subject"); /* ret.subject = {} */
+  for(i = 0; i <= n_entries; i++)
+  {
+    X509_NAME_ENTRY *entry;
+    ASN1_OBJECT *object;
+
+    entry = X509_NAME_get_entry(subject, i);
+    object = X509_NAME_ENTRY_get_object(entry);
+
+    luasec_push_asn1_objname(L, object, 1);
+
+    if(luasec_push_subtable(L, -2))
+    {
+      /* Get short/long name of the entry */
+      luasec_push_asn1_objname(L, object, 0);
+      lua_setfield(L, -2, "name");
+    }
+
+    luasec_push_asn1_string(L, X509_NAME_ENTRY_get_data(entry));
+    lua_rawseti(L, -2, lua_objlen(L, -2)+1);
+
+    lua_pop(L, 1);
+  }
+
+  lua_pop(L, 1); /* ret.subject */
+
+  lua_newtable(L); /* {} */
+  lua_pushvalue(L, -1);
+  lua_setfield(L, -3, "extensions"); /* ret.extensions = {} */
+
+  i = -1;
+  while((i = X509_get_ext_by_NID(peer, NID_subject_alt_name, i)) != -1)
+  {
+    X509_EXTENSION *extension;
+    STACK_OF(GENERAL_NAME) *values;
+    int n_general_names;
+
+    extension = X509_get_ext(peer, i);
+    if(extension == NULL)
+      break;
+
+    values = X509V3_EXT_d2i(extension);
+    if(values == NULL)
+      break;
+
+    /* Push ret.extensions[oid] */
+    luasec_push_asn1_objname(L, extension->object, 1);
+    luasec_push_subtable(L, -2);
+    /* Set ret.extensions[oid].name = name */
+    luasec_push_asn1_objname(L, extension->object, 0);
+    lua_setfield(L, -2, "name");
+
+    n_general_names = sk_GENERAL_NAME_num(values);
+    for(j = 0; j < n_general_names; j++)
+    {
+      GENERAL_NAME *general_name;
+
+      general_name = sk_GENERAL_NAME_value(values, j);
+
+      switch(general_name->type)
+      {
+      case GEN_OTHERNAME:
+      {
+        OTHERNAME *otherName = general_name->d.otherName;
+
+        luasec_push_asn1_objname(L, otherName->type_id, 1);
+
+        if(luasec_push_subtable(L, -2))
+        {
+          luasec_push_asn1_objname(L, otherName->type_id, 0);
+          lua_setfield(L, -2, "name");
+        }
+
+        luasec_push_asn1_string(L, otherName->value->value.asn1_string);
+        lua_rawseti(L, -2, lua_objlen(L, -2)+1);
+
+        lua_pop(L, 1);
+        break;
+      }
+      case GEN_DNS:
+      {
+        lua_pushstring(L, "dNSName");
+	luasec_push_subtable(L, -2);
+        luasec_push_asn1_string(L, general_name->d.dNSName);
+        lua_rawseti(L, -2, lua_objlen(L, -2)+1);
+        lua_pop(L, 1);
+        break;
+      }
+      default:
+        break;
+      }
+    }
+
+    lua_pop(L, 1); /* array */
+    i++; /* Next extension */
+  }
+  lua_pop(L, 1); /* ret.extensions */
+  return 1;
+}
+
+/**
+ * Certificate metamethods
+ */
+static luaL_Reg meta[] = {
+  {"decode",            meth_decode},
+  {NULL,                NULL}
+};
+
+LUASEC_API int luaopen_ssl_x509(lua_State *L)
+{
+  /* Register the functions and tables */
+  luaL_newmetatable(L, "SSL:Certificate");
+  lua_newtable(L);
+  luaL_register(L, NULL, meta);
+  lua_setfield(L, -2, "__index");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/x509.h	Fri Nov 05 20:48:06 2010 +0000
@@ -0,0 +1,12 @@
+#include <openssl/x509v3.h>
+#include <lua.h>
+
+typedef struct t_x509_ {
+  X509 *cert;
+} t_x509;
+typedef t_x509* p_x509;
+
+void luasec_push_x509(lua_State* L, X509* cert);
+X509* luasec_to_x509(lua_State* L, int idx);
+
+LUASEC_API int luaopen_ssl_x509(lua_State *L);

mercurial