diff -r 85d59ac3328b -r e26f1f91118a src/context.c --- 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 #include #include +#include +#include #include #include #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);