# HG changeset patch # User Paul Aurich # Date 1309724016 25200 # Node ID e26f1f91118ae17420e1db82e9b577e745f6ec18 # Parent 85d59ac3328b845756bdbcfa78e631d281b1fee4 Fix the verification function so it doesn't pass for everyone on invalid purpose errors. Inspiration and code partially from Matthew 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); diff -r 85d59ac3328b -r e26f1f91118a src/context.h --- a/src/context.h Sun Jul 03 13:13:36 2011 -0700 +++ b/src/context.h Sun Jul 03 13:13:36 2011 -0700 @@ -26,6 +26,7 @@ typedef struct t_context_ { SSL_CTX *context; + lua_State *L; unsigned int verify_flags; char mode; } t_context; diff -r 85d59ac3328b -r e26f1f91118a src/ssl.c --- a/src/ssl.c Sun Jul 03 13:13:36 2011 -0700 +++ b/src/ssl.c Sun Jul 03 13:13:36 2011 -0700 @@ -23,7 +23,7 @@ /* index into the SSL storage where the t_ssl is. * see SSL_get_ex_data(). */ - static int luasec_ssl_idx; + int luasec_ssl_idx; /** * Map error code into string. @@ -61,6 +61,8 @@ SSL_free(ssl->ssl); ssl->ssl = NULL; } + luaL_unref(L, LUA_REGISTRYINDEX, ssl->t_cert_errors); + ssl->t_cert_errors = LUA_NOREF; return 0; } @@ -251,6 +253,7 @@ #endif SSL_set_ex_data(ssl->ssl, luasec_ssl_idx, ssl); + ssl->t_cert_errors = LUA_NOREF; if (mode == MD_CTX_SERVER) SSL_set_accept_state(ssl->ssl); @@ -403,18 +406,12 @@ /** * Return the validation state of the peer chain */ -static int meth_getpeerchainvalid(lua_State *L) +static int meth_getpeerverification(lua_State *L) { p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection"); - long result = SSL_get_verify_result(ssl->ssl); - if (result == X509_V_OK) { - lua_pushboolean(L, 1); - return 1; - } - - lua_pushboolean(L, 0); - lua_pushstring(L, X509_verify_cert_error_string(result)); + lua_pushboolean(L, SSL_get_verify_result(ssl->ssl) == X509_V_OK); + lua_rawgeti(L, LUA_REGISTRYINDEX, ssl->t_cert_errors); return 2; } @@ -552,7 +549,7 @@ {"compression", meth_compression}, {"getpeercertificate",meth_getpeercertificate}, {"getpeerchain", meth_getpeerchain}, - {"getpeerchainvalid", meth_getpeerchainvalid}, + {"getpeerverification", meth_getpeerverification}, {"getfinished", meth_getfinished}, {"getpeerfinished", meth_getpeerfinished}, {NULL, NULL} diff -r 85d59ac3328b -r e26f1f91118a src/ssl.h --- a/src/ssl.h Sun Jul 03 13:13:36 2011 -0700 +++ b/src/ssl.h Sun Jul 03 13:13:36 2011 -0700 @@ -28,9 +28,11 @@ SSL *ssl; char state; int error; + int t_cert_errors; /* reference to a table of cert errors...or LUA_NOREF */ } t_ssl; typedef t_ssl* p_ssl; +extern int luasec_ssl_idx; LUASEC_API int luaopen_ssl_core(lua_State *L); #endif