--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/x509.c Fri Nov 05 20:48:06 2010 +0000 @@ -0,0 +1,169 @@ +/*-------------------------------------------------------------------------- + * 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; +} + +int meth_decode(lua_State* L) +{ + X509 *peer; + X509_NAME *subject; + int i, j, n_entries; + + peer = luasec_to_x509(L, 1); + + lua_newtable(L); /* ret */ + + subject = X509_get_subject_name(peer); + + n_entries = X509_NAME_entry_count(subject); + + lua_newtable(L); /* {} */ + lua_pushvalue(L, -1); + lua_setfield(L, -3, "subject"); /* ret.subject = {} */ + for(i = 0; i <= n_entries; i++) + { + X509_NAME_ENTRY *entry; + ASN1_OBJECT *object; + + entry = X509_NAME_get_entry(subject, i); + object = X509_NAME_ENTRY_get_object(entry); + + luasec_push_asn1_objname(L, object, 1); + + if(luasec_push_subtable(L, -2)) + { + /* Get short/long name of the entry */ + luasec_push_asn1_objname(L, object, 0); + lua_setfield(L, -2, "name"); + } + + luasec_push_asn1_string(L, X509_NAME_ENTRY_get_data(entry)); + lua_rawseti(L, -2, lua_objlen(L, -2)+1); + + lua_pop(L, 1); + } + + lua_pop(L, 1); /* ret.subject */ + + lua_newtable(L); /* {} */ + lua_pushvalue(L, -1); + lua_setfield(L, -3, "extensions"); /* ret.extensions = {} */ + + 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.extensions[oid] */ + luasec_push_asn1_objname(L, extension->object, 1); + luasec_push_subtable(L, -2); + /* Set ret.extensions[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_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; + } + default: + break; + } + } + + lua_pop(L, 1); /* array */ + i++; /* Next extension */ + } + lua_pop(L, 1); /* ret.extensions */ + return 1; +} + +/** + * Certificate metamethods + */ +static luaL_Reg meta[] = { + {"decode", meth_decode}, + {NULL, NULL} +}; + +LUASEC_API int luaopen_ssl_x509(lua_State *L) +{ + /* Register the functions and tables */ + luaL_newmetatable(L, "SSL:Certificate"); + lua_newtable(L); + luaL_register(L, NULL, meta); + lua_setfield(L, -2, "__index"); +}