src/context.c

changeset 41
e26f1f91118a
parent 38
4ecd7b0e67ea
child 42
b6271d3bae0b
--- a/src/context.c	Sun Jul 03 13:13:36 2011 -0700
+++ b/src/context.c	Sun Jul 03 13:13:36 2011 -0700
@@ -7,11 +7,14 @@
 #include <string.h>
 #include <openssl/ssl.h>
 #include <openssl/err.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
 
 #include <lua.h>
 #include <lauxlib.h>
 
 #include "context.h"
+#include "ssl.h"
 
 struct ssl_option_s {
   const char *name;
@@ -249,7 +252,8 @@
     lua_pushnil(L);
     lua_pushstring(L, "error creating context");
     return 2;
-  }  
+  }
+  ctx->L = L;
   ctx->context = SSL_CTX_new(method);
   if (!ctx->context) {
     lua_pushnil(L);
@@ -403,11 +407,37 @@
   return 1;
 }
 
+static void
+luasec_push_cert_error(lua_State *L, int ref, int depth, int err)
+{
+  int created = 0;
+
+  lua_rawgeti(L, LUA_REGISTRYINDEX, ref);
+  lua_rawgeti(L, -1, depth + 1);
+  if (!lua_istable(L, -1)) {
+    /* If the table doesn't exist, create it */
+    created = 1;
+    lua_pop(L, 1);
+    lua_newtable(L);
+  }
+
+  lua_pushstring(L, X509_verify_cert_error_string(err));
+  lua_rawseti(L, -2, lua_objlen(L, -2)+1);
+
+  if (created) {
+    lua_rawseti(L, -2, depth + 1);
+    lua_pop(L, 1);
+  } else
+    lua_pop(L, 2);
+}
+
 int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
 {
   SSL_CTX *context;
   SSL *ssl;
   p_context l_ctx;
+  p_ssl l_ssl;
+  int err, depth;
 
   /* Short-circuit optimization */
   if (preverify_ok)
@@ -415,21 +445,37 @@
 
   ssl = X509_STORE_CTX_get_ex_data(x509_ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
   context = ssl->ctx;
+  l_ssl = SSL_get_ex_data(ssl, luasec_ssl_idx);
   l_ctx = SSL_CTX_get_ex_data(context, luasec_sslctx_idx);
 
-  if (l_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 (err != X509_V_OK) {
+    if (l_ssl->t_cert_errors == LUA_NOREF) {
+      lua_newtable(l_ctx->L);
+      l_ssl->t_cert_errors = luaL_ref(l_ctx->L, LUA_REGISTRYINDEX);
+    }
+
+    luasec_push_cert_error(l_ctx->L, l_ssl->t_cert_errors, depth, err);
+  }
 
-    err = X509_STORE_CTX_get_error(x509_ctx);
-    depth = X509_STORE_CTX_get_error_depth(x509_ctx);
+  return (l_ctx->verify_flags & LUASEC_VERIFY_FLAGS_ALWAYS_CONTINUE ? 1 : preverify_ok);
+}
 
-    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;
+static int luasec_verify(X509_STORE_CTX *x509_ctx, void *ptr)
+{
+  p_context ctx = ptr;
+
+  if (ctx->verify_flags & LUASEC_VERIFY_FLAGS_IGNORE_PURPOSE) {
+    X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(x509_ctx);
+    if (param) {
+      X509_VERIFY_PARAM_set_purpose(param, X509_PURPOSE_SSL_SERVER);
+      X509_VERIFY_PARAM_set_trust(param, X509_TRUST_SSL_SERVER);
     }
   }
-  return (l_ctx->verify_flags & LUASEC_VERIFY_FLAGS_ALWAYS_CONTINUE ? 1 : preverify_ok);
+
+  return X509_verify_cert(x509_ctx);
 }
 
 /**
@@ -463,6 +509,7 @@
       }
     }
     SSL_CTX_set_verify(ctx->context, flag, ctx->verify_flags ? verify_cb : NULL);
+    SSL_CTX_set_cert_verify_callback(ctx->context, luasec_verify, ctx);
     if(vflag)
     {
       X509_STORE *store = SSL_CTX_get_cert_store(ctx->context);

mercurial