verify: Flag to ignore 'invalid purpose' errors on end cert

Sun, 21 Nov 2010 20:14:31 -0800

author
Paul Aurich <paul@darkrain42.org>
date
Sun, 21 Nov 2010 20:14:31 -0800
changeset 34
510432315106
parent 33
cc36229b3be1
child 35
4994321eae31

verify: Flag to ignore 'invalid purpose' errors on end cert

src/context.c file | annotate | diff | comparison | revisions
src/context.h file | annotate | diff | comparison | revisions
src/ssl.c file | annotate | diff | comparison | revisions
--- a/src/context.c	Sat Nov 20 20:04:11 2010 -0800
+++ b/src/context.c	Sun Nov 21 20:14:31 2010 -0800
@@ -19,6 +19,8 @@
 };
 typedef struct ssl_option_s ssl_option_t;
 
+int luasec_ssl_idx = -1;
+
 /* The export DH key */
 static DH *dh_512    = NULL;
 /* The larger key (builtin is 2048, caller may specify larger) */
@@ -107,7 +109,7 @@
 /**
  * Return the context.
  */
-static p_context checkctx(lua_State *L, int idx)
+p_context checkctx(lua_State *L, int idx)
 {
   return (p_context)luaL_checkudata(L, idx, "SSL:Context");
 }
@@ -243,6 +245,7 @@
     lua_pushstring(L, "error creating context");
     return 2;
   }
+  ctx->verify_flags = LUASEC_VERIFY_FLAGS_NONE;
   ctx->mode = MD_CTX_INVALID;
   /* No session support */
   SSL_CTX_set_session_cache_mode(ctx->context, SSL_SESS_CACHE_OFF);
@@ -389,7 +392,29 @@
 
 int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
 {
-   return 1;
+  SSL *ssl;
+  p_context ctx = NULL;
+
+  /* Short-circuit optimization */
+  if (preverify_ok)
+    return 1;
+
+  ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
+  ctx = SSL_get_ex_data(ssl, luasec_ssl_idx);
+
+  if (ctx->verify_flags & LUASEC_VERIFY_FLAGS_IGNORE_PURPOSE) {
+    int err, depth;
+
+    err = X509_STORE_CTX_get_error(x509_ctx);
+    depth = X509_STORE_CTX_get_error_depth(x509_ctx);
+
+    if (depth == 0 && err == X509_V_ERR_INVALID_PURPOSE) {
+      /* You see nothing! */
+      X509_STORE_CTX_set_error(x509_ctx, X509_V_OK);
+      preverify_ok = 1;
+    }
+  }
+  return (ctx->verify_flags & LUASEC_VERIFY_FLAGS_ALWAYS_CONTINUE ? 1 : preverify_ok);
 }
 
 /**
@@ -400,21 +425,25 @@
   int i;
   int flag = 0;
   int ignore_errors = 0;
-  SSL_CTX *ctx = ctx_getcontext(L, 1);
+  p_context ctx = checkctx(L, 1);
   int max = lua_gettop(L);
   /* any flag? */
   if (max > 1) {
+    ctx->verify_flags = LUASEC_VERIFY_FLAGS_NONE;
     for (i = 2; i <= max; i++) {
       const char *s = luaL_checkstring(L, i);
       if (!strcmp(s, "continue")) {
+        ctx->verify_flags |= LUASEC_VERIFY_FLAGS_ALWAYS_CONTINUE;
         ignore_errors = 1;
+      } else if (!strcmp(s, "ignore_purpose")) {
+        ctx->verify_flags |= LUASEC_VERIFY_FLAGS_IGNORE_PURPOSE;
       } else if (!set_verify_flag(s, &flag)) {
         lua_pushboolean(L, 0);
         lua_pushstring(L, "invalid verify option");
         return 2;
       }
     }
-    SSL_CTX_set_verify(ctx, flag, ignore_errors ? verify_cb : NULL);
+    SSL_CTX_set_verify(ctx->context, flag, ctx->verify_flags ? verify_cb : NULL);
   }
   lua_pushboolean(L, 1);
   return 1;
--- a/src/context.h	Sat Nov 20 20:04:11 2010 -0800
+++ b/src/context.h	Sun Nov 21 20:14:31 2010 -0800
@@ -20,12 +20,23 @@
 #define MD_CTX_SERVER 1
 #define MD_CTX_CLIENT 2
 
+#define LUASEC_VERIFY_FLAGS_NONE            0x0000
+#define LUASEC_VERIFY_FLAGS_ALWAYS_CONTINUE 0x0001
+#define LUASEC_VERIFY_FLAGS_IGNORE_PURPOSE  0x0002
+
 typedef struct t_context_ {
   SSL_CTX *context;
+  unsigned int verify_flags;
   char mode;
 } t_context;
 typedef t_context* p_context;
 
+/* index into the SSL storage where the context is.
+ * see SSL_get_ex_data().
+ */
+extern int luasec_ssl_idx;
+
+p_context checkctx(lua_State *L, int idx);
 /* Retrieve the SSL context from the Lua stack */
 SSL_CTX *ctx_getcontext(lua_State *L, int idx);
 /* Retrieve the mode from the context in the Lua stack */
--- a/src/ssl.c	Sat Nov 20 20:04:11 2010 -0800
+++ b/src/ssl.c	Sun Nov 21 20:14:31 2010 -0800
@@ -209,20 +209,28 @@
 {
   p_ssl ssl;
   int mode = ctx_getmode(L, 1);
-  SSL_CTX *ctx = ctx_getcontext(L, 1);
+  p_context ctx = checkctx(L, 1);
 
   if (mode == MD_CTX_INVALID) {
     lua_pushnil(L);
     lua_pushstring(L, "invalid mode");
     return 2;
   }
+  if (luasec_ssl_idx == -1) {
+    luasec_ssl_idx = SSL_get_ex_new_index(0, "luasec context", NULL, NULL, NULL);
+    if (luasec_ssl_idx == -1) {
+      lua_pushnil(L);
+      lua_pushstring(L, "error creating luasec SSL index");
+      return 2;
+    }
+  }
   ssl = (p_ssl) lua_newuserdata(L, sizeof(t_ssl));
   if (!ssl) {
     lua_pushnil(L);
     lua_pushstring(L, "error creating SSL object");
     return 2;
   }
-  ssl->ssl = SSL_new(ctx);
+  ssl->ssl = SSL_new(ctx->context);
   if (!ssl->ssl) {
     lua_pushnil(L);
     lua_pushstring(L, "error creating SSL object");
@@ -237,6 +245,8 @@
   SSL_set_mode(ssl->ssl, SSL_MODE_RELEASE_BUFFERS);
 #endif
 
+  SSL_set_ex_data(ssl->ssl, luasec_ssl_idx, ctx);
+
   if (mode == MD_CTX_SERVER)
     SSL_set_accept_state(ssl->ssl);
   else

mercurial