Sun, 05 Dec 2010 23:45:57 -0800
Clean up the ex_data callers
The best explanation I can come up with here is that I totally missed the existence of SSL_[gs]et_ex_data...
/*-------------------------------------------------------------------------- * LuaSec 0.4 * Copyright (C) 2006-2009 Bruno Silvestre * *--------------------------------------------------------------------------*/ #include <string.h> #include <openssl/ssl.h> #include <openssl/x509v3.h> #include <openssl/err.h> #include <lua.h> #include <lauxlib.h> #include "io.h" #include "buffer.h" #include "timeout.h" #include "socket.h" #include "ssl.h" #include "x509.h" #define min(a, b) (a<b)?a:b void luasec_push_x509(lua_State* L, X509 *cert) { p_x509 cert_obj = (p_x509) lua_newuserdata(L, sizeof(t_x509)); cert_obj->cert = cert; luaL_getmetatable(L, "SSL:Certificate"); lua_setmetatable(L, -2); } X509* luasec_to_x509(lua_State* L, int idx) { return ((p_x509)luaL_checkudata(L, idx, "SSL:Certificate"))->cert; } void luasec_push_asn1_objname(lua_State* L, ASN1_OBJECT *object, int no_name) { char buffer[256]; int len = OBJ_obj2txt(buffer, sizeof(buffer), object, no_name); lua_pushlstring(L, buffer, min(sizeof(buffer),len)); } void luasec_push_asn1_string(lua_State* L, ASN1_STRING *string) { if (string) lua_pushlstring(L, (char*)ASN1_STRING_data(string), ASN1_STRING_length(string)); else lua_pushnil(L); } int luasec_push_subtable(lua_State* L, int idx) { lua_pushvalue(L, -1); lua_gettable(L, idx-1); if (lua_isnil(L, -1)) { lua_pop(L, 1); lua_newtable(L); lua_pushvalue(L, -2); lua_pushvalue(L, -2); lua_settable(L, idx-3); lua_replace(L, -2); /* Replace key with table */ return 1; } lua_replace(L, -2); /* Replace key with table */ return 0; } void luasec_push_x509_name(lua_State* L, X509_NAME *name) { int i, n_entries; lua_newtable(L); n_entries = X509_NAME_entry_count(name); for (i = 0; i < n_entries; i++) { X509_NAME_ENTRY *entry; ASN1_OBJECT *object; entry = X509_NAME_get_entry(name, i); object = X509_NAME_ENTRY_get_object(entry); lua_newtable(L); luasec_push_asn1_objname(L, object, 1); lua_setfield(L, -2, "oid"); luasec_push_asn1_objname(L, object, 0); lua_setfield(L, -2, "name"); luasec_push_asn1_string(L, X509_NAME_ENTRY_get_data(entry)); lua_setfield(L, -2, "value"); lua_rawseti(L, -2, lua_objlen(L, -2)+1); } } int meth_subject(lua_State* L) { luasec_push_x509_name(L, X509_get_subject_name(luasec_to_x509(L, 1))); return 1; } int meth_issuer(lua_State* L) { luasec_push_x509_name(L, X509_get_issuer_name(luasec_to_x509(L, 1))); return 1; } int meth_extensions(lua_State* L) { X509 *peer; int i, j; peer = luasec_to_x509(L, 1); lua_newtable(L); /* ret */ i = -1; while ((i = X509_get_ext_by_NID(peer, NID_subject_alt_name, i)) != -1) { X509_EXTENSION *extension; STACK_OF(GENERAL_NAME) *values; int n_general_names; extension = X509_get_ext(peer, i); if (extension == NULL) break; values = X509V3_EXT_d2i(extension); if (values == NULL) break; /* Push ret[oid] */ luasec_push_asn1_objname(L, extension->object, 1); luasec_push_subtable(L, -2); /* Set ret[oid].name = name */ luasec_push_asn1_objname(L, extension->object, 0); lua_setfield(L, -2, "name"); n_general_names = sk_GENERAL_NAME_num(values); for (j = 0; j < n_general_names; j++) { GENERAL_NAME *general_name; general_name = sk_GENERAL_NAME_value(values, j); switch(general_name->type) { case GEN_OTHERNAME: { OTHERNAME *otherName = general_name->d.otherName; luasec_push_asn1_objname(L, otherName->type_id, 1); if (luasec_push_subtable(L, -2)) { luasec_push_asn1_objname(L, otherName->type_id, 0); lua_setfield(L, -2, "name"); } luasec_push_asn1_string(L, otherName->value->value.asn1_string); lua_rawseti(L, -2, lua_objlen(L, -2)+1); lua_pop(L, 1); break; } case GEN_EMAIL: lua_pushstring(L, "rfc822Name"); luasec_push_subtable(L, -2); luasec_push_asn1_string(L, general_name->d.rfc822Name); lua_rawseti(L, -2, lua_objlen(L, -2)+1); lua_pop(L, 1); break; case GEN_DNS: lua_pushstring(L, "dNSName"); luasec_push_subtable(L, -2); luasec_push_asn1_string(L, general_name->d.dNSName); lua_rawseti(L, -2, lua_objlen(L, -2)+1); lua_pop(L, 1); break; case GEN_X400: /* x400Address */ break; case GEN_DIRNAME: /* directoryName */ break; case GEN_EDIPARTY: /* ediPartyName */ break; case GEN_URI: lua_pushstring(L, "uniformResourceIdentifier"); luasec_push_subtable(L, -2); luasec_push_asn1_string(L, general_name->d.uniformResourceIdentifier); lua_rawseti(L, -2, lua_objlen(L, -2)+1); lua_pop(L, 1); break; case GEN_IPADD: lua_pushstring(L, "iPAddress"); luasec_push_subtable(L, -2); luasec_push_asn1_string(L, general_name->d.iPAddress); lua_rawseti(L, -2, lua_objlen(L, -2)+1); lua_pop(L, 1); break; case GEN_RID: /* registeredID */ break; default: break; } } lua_pop(L, 1); /* ret[oid] */ i++; /* Next extension */ } return 1; } int meth_valid_at(lua_State* L) { X509* cert = luasec_to_x509(L, 1); time_t time = luaL_checkinteger(L, 2); lua_pushboolean(L, (X509_cmp_time(X509_get_notAfter(cert), &time) >= 0 && X509_cmp_time(X509_get_notBefore(cert), &time) <= 0)); return 1; } int meth_pem(lua_State* L) { X509* cert = luasec_to_x509(L, 1); BIO *bio = BIO_new(BIO_s_mem()); char* data; long bytes; if (!PEM_write_bio_X509(bio, cert)) { lua_pushnil(L); return 1; } bytes = BIO_get_mem_data(bio, &data); if (bytes > 0) lua_pushlstring(L, data, bytes); else lua_pushnil(L); BIO_free(bio); return 1; } const char* hex_tab = "0123456789abcdef"; void to_hex(const char* in, int length, char* out) { int i; for (i = 0; i < length; i++) { out[i*2] = hex_tab[(in[i] >> 4) & 0xF]; out[i*2+1] = hex_tab[(in[i]) & 0xF]; } } int meth_digest(lua_State* L) { X509 *cert; unsigned int bytes; unsigned char buffer[EVP_MAX_MD_SIZE]; char hex_buffer[EVP_MAX_MD_SIZE*2]; const EVP_MD *digest; cert = luasec_to_x509(L, 1); if (lua_gettop(L) < 2 || strcmp(luaL_checkstring(L, 2), "sha1") == 0) { digest = EVP_sha1(); } else { lua_pushnil(L); lua_pushstring(L, "digest algorithm not supported"); return 2; } if (!X509_digest(cert, digest, buffer, &bytes)) { lua_pushnil(L); lua_pushstring(L, "out of memory"); return 2; } to_hex((char*)buffer, bytes, hex_buffer); lua_pushlstring(L, hex_buffer, bytes*2); return 1; } int meth_destroy(lua_State* L) { X509_free(luasec_to_x509(L, 1)); return 0; } int meth_tostring(lua_State *L) { X509 *cert = luasec_to_x509(L, 1); lua_pushfstring(L, "X509 certificate: %p", cert); return 1; } int cert_from_pem(lua_State* L) { X509 *cert; BIO *bio = BIO_new(BIO_s_mem()); const char* data; size_t bytes; data = luaL_checklstring(L, 1, &bytes); BIO_write(bio, data, bytes); cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); if (cert) luasec_push_x509(L, cert); else lua_pushnil(L); BIO_free(bio); return 1; } /** * Certificate metamethods */ static luaL_Reg methods[] = { {"subject", meth_subject}, {"issuer", meth_issuer}, {"extensions", meth_extensions}, {"valid_at", meth_valid_at}, {"pem", meth_pem}, {"digest", meth_digest}, {NULL, NULL} }; /** * ssl.x509 functions */ static luaL_Reg funcs[] = { {"cert_from_pem", cert_from_pem}, {NULL, NULL} }; /** * Context metamethods. */ static luaL_Reg meta[] = { {"__gc", meth_destroy}, {"__tostring", meth_tostring}, {NULL, NULL} }; LUASEC_API int luaopen_ssl_x509(lua_State *L) { /* Register the functions and tables */ luaL_newmetatable(L, "SSL:Certificate"); luaL_register(L, NULL, meta); lua_newtable(L); luaL_register(L, NULL, methods); lua_setfield(L, -2, "__index"); luaL_register(L, "ssl.x509", funcs); return 1; }