static int openssl_ssl_ctx_set_cert_verify(lua_State*L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); if (lua_isfunction(L, 2) || lua_istable(L, 2)) { lua_pushvalue(L, 2); if (lua_istable(L, 2)) { openssl_setvalue(L, ctx, "verify_cb_flags"); lua_pushvalue(L, 2); } openssl_setvalue(L, ctx, "cert_verify_cb"); lua_pushvalue(L, 3); openssl_setvalue(L, ctx, "cert_verify_data"); /* X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(xctx); lua_getfield(L, -1, "ignore_purpose"); if (lua_toboolean(L, -1) && param) { X509_VERIFY_PARAM_set_purpose(param, X509_PURPOSE_SSL_SERVER); X509_VERIFY_PARAM_set_trust(param, X509_TRUST_SSL_SERVER); } */ SSL_CTX_set_cert_verify_callback(ctx, openssl_cert_verify_cb, L); } else SSL_CTX_set_cert_verify_callback(ctx, NULL, NULL); return 0; }
static LUA_FUNCTION(openssl_bio_accept) { BIO* bio = CHECK_OBJECT(1, BIO, "openssl.bio"); int first = lua_isnoneornil(L, 2) ? 0 : lua_toboolean(L, 2); int ret = BIO_do_accept(bio); if (ret == 1) { if (!first) { BIO *nb = BIO_pop(bio); PUSH_OBJECT(nb, "openssl.bio"); openssl_newvalue(L, nb); lua_pushboolean(L, 1); openssl_setvalue(L, nb, "free_all"); return 1; } else return openssl_pushresult(L, ret); } else luaL_error(L, "BIO_do_accept fail"); return 0; }
static int openssl_ssl_ctx_set_servername_callback(lua_State*L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); luaL_argcheck(L, lua_istable(L, 2) || lua_isfunction(L, 2), 2, "must be table or function"); lua_pushvalue(L, 2); openssl_setvalue(L, ctx, "tlsext_servername"); SSL_CTX_set_tlsext_servername_callback(ctx, tlsext_servername_callback); return 0; }
static int openssl_bio_new_connect(lua_State *L) { const char *host = luaL_checkstring(L, 1); BIO* bio = BIO_new_connect((char*)host); int doconn = 1; if (lua_isstring(L, 2)) { if (BIO_set_conn_port(bio, lua_tostring(L, 2)) <= 0) { BIO_free(bio); bio = NULL; } else { doconn = lua_isnoneornil(L, 3) ? doconn : auxiliar_checkboolean(L, 3); } } else doconn = auxiliar_checkboolean(L, 2); if (bio) { int ret = 1; if (doconn) { ret = BIO_do_connect(bio); } if (ret == 1) { PUSH_OBJECT(bio, "openssl.bio"); openssl_newvalue(L, bio); lua_pushboolean(L, 1); openssl_setvalue(L, bio, "free_all"); return 1; } else { BIO_free(bio); luaL_error(L, "Error creating connection to remote machine"); } } if (!bio) luaL_error(L, "Error creating connection BIO"); return 0; }
static int openssl_ssl_ctx_new_bio(lua_State*L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); const char* host_addr = luaL_checkstring(L, 2); int server = lua_isnoneornil(L, 3) ? 0 : auxiliar_checkboolean(L, 3); int autoretry = lua_isnoneornil(L, 4) ? 1 : auxiliar_checkboolean(L, 4); SSL *ssl = NULL; BIO *bio = server ? BIO_new_ssl(ctx, 0) : BIO_new_ssl_connect(ctx); int ret = BIO_get_ssl(bio, &ssl); if (ret == 1 && ssl) { if (autoretry) SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); if (server) { BIO* acpt = BIO_new_accept((char*)host_addr); BIO_set_accept_bios(acpt, bio); bio = acpt; } else { ret = BIO_set_conn_hostname(bio, host_addr); } if (ret == 1) { PUSH_OBJECT(bio, "openssl.bio"); openssl_newvalue(L, bio); lua_pushboolean(L, 1); openssl_setvalue(L, bio, "free_all"); return 1; } else return openssl_pushresult(L, ret); } else { BIO_free(bio); bio = NULL; return 0; } }
static LUA_FUNCTION(openssl_bio_new_filter) { /* 0 1 2 3 4 5 */ static const char* sType[] = {"base64", "buffer", "cipher", "md", "ssl", NULL}; int type = luaL_checkoption(L, 1, NULL, sType); BIO* bio = NULL; int ret = 1; int closeflag = 0; switch (type) { case 0: bio = BIO_new(BIO_f_base64()); break; case 1: bio = BIO_new(BIO_f_buffer()); break; case 2: { const EVP_CIPHER* c = get_cipher(L, 2, NULL); size_t kl, il; const char* k = luaL_checklstring(L, 3, &kl); const char* v = luaL_checklstring(L, 4, &il); int encrypt = auxiliar_checkboolean(L, 5); bio = BIO_new(BIO_f_cipher()); BIO_set_cipher(bio, c, (const unsigned char*)k, (const unsigned char*)v, encrypt); } break; case 3: { const EVP_MD* md = get_digest(L, 2); bio = BIO_new(BIO_f_md()); ret = BIO_set_md(bio, md); } case 4: { SSL* ssl = CHECK_OBJECT(2, SSL, "openssl.ssl"); closeflag = luaL_checkoption(L, 3, "noclose", close_flags); bio = BIO_new(BIO_f_ssl()); ret = BIO_set_ssl(bio, ssl, closeflag); } break; default: ret = 0; } if (ret == 1 && bio) { PUSH_OBJECT(bio, "openssl.bio"); if (closeflag) { openssl_newvalue(L, bio); lua_pushboolean(L, 1); openssl_setvalue(L, bio, "free_all"); } return 1; } else { if (bio) BIO_free(bio); return openssl_pushresult(L, ret); } return 0; }
static int openssl_ssl_ctx_set_tmp(lua_State *L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); static const char* which[] = { "dh", "rsa", "ecdh", NULL }; int nwhich = luaL_checkoption(L, 2, NULL, which); int ret = 0; if (lua_isfunction(L, 3)) { lua_pushvalue(L, 3); ret = 1; switch (nwhich) { case 0: openssl_setvalue(L, ctx, "tmp_dh_callback"); SSL_CTX_set_tmp_dh_callback(ctx, tmp_dh_callback); break; case 1: openssl_setvalue(L, ctx, "tmp_rsa_callback"); SSL_CTX_set_tmp_rsa_callback(ctx, tmp_rsa_callback); break; case 2: { luaL_argcheck(L, lua_isstring(L, 4), 4, "must supply curve name"); openssl_setvalue(L, ctx, "tmp_ecdh_callback"); SSL_CTX_set_tmp_ecdh_callback(ctx, tmp_ecdh_callback); lua_pushvalue(L, 4); openssl_setvalue(L, ctx, "curve"); } break; } } else if (lua_isstring(L, 3)) { BIO* bio = load_bio_object(L, 3); switch (nwhich) { case 0: { DH* dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); if (dh) ret = SSL_CTX_set_tmp_dh(ctx, dh); else luaL_error(L, "generate new tmp dh fail"); } break; case 1: { RSA* rsa = PEM_read_bio_RSAPrivateKey(bio, NULL, NULL, NULL); if (rsa) ret = SSL_CTX_set_tmp_rsa(ctx, rsa); else luaL_error(L, "generate new tmp rsa fail"); } break; case 2: { int nid = NID_undef; EC_KEY* ec = PEM_read_bio_ECPrivateKey(bio, NULL, NULL, NULL); if (ec == NULL) { nid = OBJ_txt2nid(lua_tostring(L, 3)); if (nid != NID_undef) ec = EC_KEY_new_by_curve_name(nid); } if (ec) ret = SSL_CTX_set_tmp_ecdh(ctx, ec); else luaL_error(L, "generate new tmp ec_key fail"); } break; } BIO_free(bio); } else if (lua_isuserdata(L, 3)) { luaL_argerror(L, 3, "userdata arg NYI"); } else luaL_argerror(L, 3, "should be tmp key callback function or pem string or key object"); return openssl_pushresult(L, ret); }
static int openssl_ssl_ctx_verify_mode(lua_State*L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); if (lua_gettop(L) > 1) { size_t i; int mode = 0; luaL_checktable(L, 2); for (i = 0; i < lua_rawlen(L, 2); i++) { lua_rawgeti(L, 2, i + 1); mode |= auxiliar_checkoption(L, -1, NULL, sVerifyMode_Options, iVerifyMode_Options); lua_pop(L, 1); } luaL_argcheck(L, lua_isnoneornil(L, 3) || lua_isfunction(L, 3), 3, "must be function callback"); if (lua_isfunction(L, 3)) { lua_pushvalue(L, 3); openssl_setvalue(L, ctx, "verify_cb"); SSL_CTX_set_verify(ctx, mode, openssl_verify_cb); } else { SSL_CTX_set_verify(ctx, mode, openssl_verify_cb); } return 0; } else { int i = 0; int mode = SSL_CTX_get_verify_mode(ctx); lua_pushinteger(L, mode); i += 1; if (mode == SSL_VERIFY_NONE) { lua_pushstring(L, "none"); i += 1; } else { if (mode & SSL_VERIFY_PEER) { lua_pushstring(L, "peer"); i += 1; } if (mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) { lua_pushstring(L, "fail_if_no_peer_cert"); i += 1; } if (mode & SSL_VERIFY_CLIENT_ONCE) { lua_pushstring(L, "client_once"); i += 1; } } return i; } return 0; }