src/x509.c

Fri, 05 Nov 2010 21:25:30 +0000

author
Matthew Wild <mwild1@gmail.com>
date
Fri, 05 Nov 2010 21:25:30 +0000
changeset 16
0cefcdd5b635
parent 15
f1de983ff659
child 17
4e3da35cc9ab
permissions
-rw-r--r--

Add :pem() method to certificates

/*--------------------------------------------------------------------------
 * 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;
}

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;
}

/**
 * Certificate metamethods
 */
static luaL_Reg meta[] = {
  {"decode",            meth_decode},
  {"pem",               meth_pem},
  {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");

  lua_newtable(L);
  return 1;
}

mercurial