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_sessions(lua_State*L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); if (lua_isstring(L, 2)) { size_t s; unsigned char* sid_ctx = (unsigned char*)luaL_checklstring(L, 2, &s); int ret = SSL_CTX_set_session_id_context(ctx, sid_ctx, s); lua_pushboolean(L, ret); return 1; } else { SSL_SESSION *s = CHECK_OBJECT(2, SSL_SESSION, "openssl.ssl_session"); int add = 1; if (!lua_isnoneornil(L, 3)) add = auxiliar_checkboolean(L, 3); if (add) add = SSL_CTX_add_session(ctx, s); else add = SSL_CTX_remove_session(ctx, s); lua_pushboolean(L, add); return 1; } }
static int openssl_ocsp_response_export(lua_State*L) { OCSP_RESPONSE *res = CHECK_OBJECT(1, OCSP_RESPONSE, "openssl.ocsp_response"); int pem = 1; int ret = 0; BIO* bio; BUF_MEM *buf; if (lua_gettop(L) > 1) pem = auxiliar_checkboolean(L, 2); bio = BIO_new(BIO_s_mem()); /* if (pem) { ret = PEM_write_bio_OCSP_RESPONSE(bio, res); } else { ret = i2d_OCSP_RESPONSE_bio(bio, res); } */ ret = i2d_OCSP_RESPONSE_bio(bio, res); if (ret) { BIO_get_mem_ptr(bio, &buf); lua_pushlstring(L, buf->data, buf->length); } BIO_free(bio); return ret; }
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_pkcs12_read) { PKCS12 * p12 = NULL; EVP_PKEY * pkey = NULL; X509 * cert = NULL; STACK_OF(X509) * ca = NULL; int ret = 0; int base64 = 0; int olb64 = 0; BIO * b64 = NULL; BIO * bio_in = load_bio_object(L, 1); const char *pass = luaL_checkstring(L, 2); if (!lua_isnoneornil(L, 3)) base64 = auxiliar_checkboolean(L, 3); if (!lua_isnoneornil(L, 4)) olb64 = auxiliar_checkboolean(L, 4); if (base64) { if ((b64 = BIO_new(BIO_f_base64())) == NULL) return 0; if (olb64) BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); bio_in = BIO_push(b64, bio_in); } if (d2i_PKCS12_bio(bio_in, &p12) && PKCS12_parse(p12, pass, &pkey, &cert, &ca)) { lua_newtable(L); AUXILIAR_SETOBJECT(L, cert, "openssl.x509" , -1, "cert"); AUXILIAR_SETOBJECT(L, pkey, "openssl.evp_pkey" , -1, "pkey"); AUXILIAR_SETOBJECT(L, ca, "openssl.stack_of_x509" , -1, "extracerts"); ret = 1; } if (b64) BIO_free(b64); BIO_free(bio_in); PKCS12_free(p12); return ret; }
static int openssl_ssl_ctx_new_ssl(lua_State*L) { SSL_CTX* ctx = CHECK_OBJECT(1, SSL_CTX, "openssl.ssl_ctx"); int server = 0; int mode_idx = 2; SSL *ssl = SSL_new(ctx); int ret = 1; BIO* bio = NULL; if (auxiliar_isclass(L, "openssl.bio", 2)) { BIO *bi = CHECK_OBJECT(2, BIO, "openssl.bio"); BIO *bo = bi; CRYPTO_add(&bi->references, 1, CRYPTO_LOCK_BIO); if (auxiliar_isclass(L, "openssl.bio", 3)) { bo = CHECK_OBJECT(3, BIO, "openssl.bio"); CRYPTO_add(&bo->references, 1, CRYPTO_LOCK_BIO); mode_idx = 4; } else mode_idx = 3; SSL_set_bio(ssl, bi, bo); ret = 1; } else if (lua_isnumber(L, 2)) { ret = SSL_set_fd(ssl, luaL_checkint(L, 2)); mode_idx = 3; } if (ret == 1 && !lua_isnoneornil(L, mode_idx)) { server = auxiliar_checkboolean(L, mode_idx); } if (ret == 1) { if (server) SSL_set_accept_state(ssl); else SSL_set_connect_state(ssl); PUSH_OBJECT(ssl, "openssl.ssl"); openssl_newvalue(L, ssl); } else { SSL_free(ssl); return openssl_pushresult(L, ret); } return 1; }
static int openssl_ts_req_cert_req(lua_State *L) { TS_REQ* req = CHECK_OBJECT(1, TS_REQ, "openssl.ts_req"); if (lua_isnone(L, 2)) { lua_pushboolean(L, TS_REQ_get_cert_req(req)); return 1; } else { int cert_req = auxiliar_checkboolean(L, 2); int ret = TS_REQ_set_cert_req(req, cert_req); return openssl_pushresult(L, ret); } }
static int openssl_cms_detached(lua_State *L) { CMS_ContentInfo *cms = CHECK_OBJECT(1, CMS_ContentInfo, "openssl.cms"); int ret = 0; if (lua_isnone(L, 2)) { ret = CMS_is_detached(cms); } else { int detached = auxiliar_checkboolean(L, 2); ret = CMS_set_detached(cms, detached); } lua_pushboolean(L, ret); return 1; }
static int openssl_version(lua_State*L) { int num = lua_isnoneornil(L, 1) ? 0 : auxiliar_checkboolean(L, 1); if (num) { lua_pushinteger(L, LOPENSSL_VERSION_NUM); lua_pushinteger(L, LUA_VERSION_NUM); lua_pushinteger(L, OPENSSL_VERSION_NUMBER); } else { lua_pushstring(L, LOPENSSL_VERSION); lua_pushstring(L, LUA_VERSION); lua_pushstring(L, OPENSSL_VERSION_TEXT); } return 3; }
static int openssl_ssl_session(lua_State*L) { SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl"); SSL_SESSION*ss; if (lua_isnoneornil(L, 2)) { ss = SSL_get1_session(s); PUSH_OBJECT(ss, "openssl.ssl_session"); } else { if (lua_isstring(L, 3)) { size_t sz; const char* sid_ctx = luaL_checklstring(L, 2, &sz); int ret = SSL_set_session_id_context(s, (unsigned char*)sid_ctx, sz); lua_pushboolean(L, ret); } else { ss = CHECK_OBJECT(2, SSL_SESSION, "openssl.ssl_session"); if (lua_isnoneornil(L, 3)) { int ret = SSL_set_session(s, ss); lua_pushboolean(L, ret); } else { #ifdef SSL_add_session int add = auxiliar_checkboolean(L, 3); if (add) add = SSL_add_session(s, ss); else add = SSL_remove_session(s, ss); lua_pushboolean(L, add); #endif } } } return 1; }
static int openssl_ssl_alert_string(lua_State*L) { int v = luaL_checkint(L, 1); int _long = lua_isnoneornil(L, 2) ? 0 : auxiliar_checkboolean(L, 2); const char* val; if (_long) val = SSL_alert_type_string_long(v); else val = SSL_alert_type_string(v); lua_pushstring(L, val); if (_long) val = SSL_alert_desc_string_long(v); else val = SSL_alert_desc_string(v); lua_pushstring(L, val); return 2; }
static int openssl_ssl_session_export(lua_State*L) { SSL_SESSION* session = CHECK_OBJECT(1, SSL_SESSION, "openssl.ssl_session"); int pem = lua_isnoneornil(L, 2) ? 1 : auxiliar_checkboolean(L, 2); BIO* bio = BIO_new(BIO_s_mem()); BUF_MEM *bio_buf; if (pem) { PEM_write_bio_SSL_SESSION(bio, session); } else { i2d_SSL_SESSION_bio(bio, session); } BIO_get_mem_ptr(bio, &bio_buf); lua_pushlstring(L, bio_buf->data, bio_buf->length); BIO_free(bio); return 1; }
/*** get FIPS mode @function FIPS_mode @treturn boolean return true when FIPS mode enabled, false when FIPS mode disabled. */ static int openssl_fips_mode(lua_State *L) { #if defined(LIBRESSL_VERSION_NUMBER) return 0; #else int ret =0, on = 0; if(lua_isnone(L, 1)) { on = FIPS_mode(); lua_pushboolean(L, on); return 1; } on = auxiliar_checkboolean(L, 1); ret = FIPS_mode_set(on); if(ret) lua_pushboolean(L, ret); else ret = openssl_pushresult(L, ret); return ret; #endif }
static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) { int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */ return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); }
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_ocsp_request_new(lua_State*L) { OCSP_REQUEST *req = NULL; if (lua_isstring(L, 1)) { BIO* bio = load_bio_object(L, 1); req = d2i_OCSP_REQUEST_bio(bio, NULL); /* if (!req) { BIO_reset(bio); req = PEM_read_bio_OCSP_REQUEST(bio, NULL, NULL); } */ BIO_free(bio); } else { X509 *issuer = CHECK_OBJECT(1, X509, "openssl.x509"); X509_NAME *iname = X509_get_subject_name(issuer); ASN1_BIT_STRING *ikey = X509_get0_pubkey_bitstr(issuer); OCSP_CERTID *id = NULL; OCSP_ONEREQ *one; char buf[1024]; int nonce = lua_gettop(L) > 2 ? auxiliar_checkboolean(L, 3) : 0; req = OCSP_REQUEST_new(); if (lua_istable(L, 2)) { int len = lua_rawlen(L, 2); int i; for (i = 1; i <= len; i++) { lua_rawgeti(L, 2, i); if (auxiliar_isclass(L, "openssl.x509", -1)) { X509 *cert = CHECK_OBJECT(2, X509, "openssl.x509"); id = OCSP_cert_to_id(NULL, cert, issuer); one = OCSP_request_add0_id(req, id); } else { size_t len; char *serial = (char *)luaL_checklstring(L, -1, &len); ASN1_INTEGER *sno = ASN1_INTEGER_new(); BIO* bio = BIO_new(BIO_s_mem()); BIO_write(bio, serial, len); if (a2i_ASN1_INTEGER(bio, sno, buf, 1024) == 1) { id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno); one = OCSP_request_add0_id(req, id); }; ASN1_INTEGER_free(sno); BIO_free(bio); } lua_pop(L, 1); } } else if (auxiliar_isclass(L, "openssl.x509", 2)) { X509 *cert = CHECK_OBJECT(2, X509, "openssl.x509"); id = OCSP_cert_to_id(NULL, cert, issuer); one = OCSP_request_add0_id(req, id); } else { ASN1_INTEGER *sno = ASN1_INTEGER_new(); BIO* bio = load_bio_object(L, 2); if (a2i_ASN1_INTEGER(bio, sno, buf, 1024) == 1) { id = OCSP_cert_id_new(EVP_sha1(), iname, ikey, sno); one = OCSP_request_add0_id(req, id); }; ASN1_INTEGER_free(sno); BIO_free(bio); } if (nonce) OCSP_request_add1_nonce(req, NULL, -1); } if(req) { PUSH_OBJECT(req, "openssl.ocsp_request"); }else lua_pushnil(L); return 1; }
static int openssl_pkey_read(lua_State*L) { EVP_PKEY * key = NULL; BIO* in = load_bio_object(L, 1); int priv = lua_isnoneornil(L, 2) ? 0 : auxiliar_checkboolean(L, 2); int fmt = luaL_checkoption(L, 3, "auto", format); const char* passphrase = luaL_optstring(L, 4, NULL); int type = -1; if (passphrase) { if (strcmp(passphrase, "rsa") == 0 || strcmp(passphrase, "RSA") == 0) type = EVP_PKEY_RSA; else if (strcmp(passphrase, "dsa") == 0 || strcmp(passphrase, "DSA") == 0) type = EVP_PKEY_DSA; else if (strcmp(passphrase, "ec") == 0 || strcmp(passphrase, "EC") == 0) type = EVP_PKEY_EC; } if (fmt == FORMAT_AUTO) { fmt = bio_is_der(in) ? FORMAT_DER : FORMAT_PEM; } if (!priv) { if (fmt == FORMAT_PEM) { key = PEM_read_bio_PUBKEY(in, NULL, NULL, (void*)passphrase); BIO_reset(in); if (key == NULL && type == EVP_PKEY_RSA) { RSA* rsa = PEM_read_bio_RSAPublicKey(in, NULL, NULL, NULL); if (rsa) { key = EVP_PKEY_new(); EVP_PKEY_assign_RSA(key, rsa); } } }else if (fmt == FORMAT_DER) { key = d2i_PUBKEY_bio(in, NULL); BIO_reset(in); if (!key && type!=-1) { char * bio_mem_ptr; long bio_mem_len; bio_mem_len = BIO_get_mem_data(in, &bio_mem_ptr); key = d2i_PublicKey(type, NULL, (const unsigned char **)&bio_mem_ptr, bio_mem_len); BIO_reset(in); } } } else { if (fmt == FORMAT_PEM) { key = PEM_read_bio_PrivateKey(in, NULL, NULL, (void*)passphrase); BIO_reset(in); }else if (fmt == FORMAT_DER) { if (passphrase) key = d2i_PKCS8PrivateKey_bio(in, NULL, NULL, (void*)passphrase); else key = d2i_PrivateKey_bio(in, NULL); BIO_reset(in); if (!key && type != -1) { char * bio_mem_ptr; long bio_mem_len; bio_mem_len = BIO_get_mem_data(in, &bio_mem_ptr); key = d2i_PrivateKey(type, NULL, (const unsigned char **)&bio_mem_ptr, bio_mem_len); BIO_reset(in); } } } BIO_free(in); if (key) { PUSH_OBJECT(key, "openssl.evp_pkey"); return 1; } return openssl_pushresult(L, 0); }
static int openssl_ssl_set(lua_State*L) { SSL* s = CHECK_OBJECT(1, SSL, "openssl.ssl"); int i; int top = lua_gettop(L); int ret = 1; for (i = 2; i <= top; i += 2) { const char* what = luaL_checklstring(L, i, NULL); if (strcmp(what, "fd") == 0) { ret = SSL_set_fd(s, luaL_checkint(L, i + 1)); } else if (strcmp(what, "rfd") == 0) { ret = SSL_set_wfd(s, luaL_checkint(L, i + 1)); } else if (strcmp(what, "wfd") == 0) { ret = SSL_set_wfd(s, luaL_checkint(L, i + 1)); } else if (strcmp(what, "client_CA") == 0) { X509* x = CHECK_OBJECT(i + 1, X509, "openssl.x509"); ret = SSL_add_client_CA(s, x); } else if (strcmp(what, "read_ahead") == 0) { int yes = auxiliar_checkboolean(L, i + 1); SSL_set_read_ahead(s, yes); } else if (strcmp(what, "cipher_list") == 0) { const char* list = lua_tostring(L, i + 1); ret = SSL_set_cipher_list(s, list); } else if (strcmp(what, "verify_depth") == 0) { int depth = luaL_checkint(L, i + 1); SSL_set_verify_depth(s, depth); } else if (strcmp(what, "purpose") == 0) { //FIX int purpose = luaL_checkint(L, i + 1); ret = SSL_set_purpose(s, purpose); } else if (strcmp(what, "trust") == 0) { //FIX int trust = luaL_checkint(L, i + 1); ret = SSL_set_trust(s, trust); } else if (strcmp(what, "verify_result") == 0) { int result = luaL_checkint(L, i + 1); SSL_set_verify_result(s, result); } else if (strcmp(what, "hostname") == 0) { const char* hostname = luaL_checkstring(L, i + 1); SSL_set_tlsext_host_name(s, hostname); } #if OPENSSL_VERSION_NUMBER > 0x10000000L else if (strcmp(what, "state") == 0) { int l = luaL_checkint(L, 2); SSL_set_state(s, l); } #endif else luaL_argerror(L, i, "don't understand"); if (ret != 1) return openssl_pushresult(L, ret); } return 0; }