src/x509.c

1
/*--------------------------------------------------------------------------
2
 * LuaSec 0.4
3
 * Copyright (C) 2006-2009 Bruno Silvestre
4
 *
5
 *--------------------------------------------------------------------------*/
6
 
7
#include <string.h>
8
 
9
#include <openssl/ssl.h>
10
#include <openssl/x509v3.h>
11
#include <openssl/err.h>
12
 
13
#include <lua.h>
14
#include <lauxlib.h>
15
 
16
#include "io.h"
17
#include "buffer.h"
18
#include "timeout.h"
19
#include "socket.h"
20
#include "ssl.h"
21
#include "x509.h"
22
 
23
#define min(a, b) (a<b)?a:b
24
 
25
void luasec_push_x509(lua_State* L, X509 *cert)
26
{
27
  p_x509 cert_obj = (p_x509) lua_newuserdata(L, sizeof(t_x509));
28
  cert_obj->cert = cert;
29
  luaL_getmetatable(L, "SSL:Certificate");
30
  lua_setmetatable(L, -2);
31
}
32
 
33
X509* luasec_to_x509(lua_State* L, int idx)
34
{
35
  return ((p_x509)luaL_checkudata(L, idx, "SSL:Certificate"))->cert;
36
}
37
 
38
void luasec_push_asn1_objname(lua_State* L, ASN1_OBJECT *object, int no_name)
39
{
40
  char buffer[256];
41
  int len = OBJ_obj2txt(buffer, sizeof(buffer), object, no_name);
42
  lua_pushlstring(L, buffer, min(sizeof(buffer),len));
43
}
44
 
45
void luasec_push_asn1_string(lua_State* L, ASN1_STRING *string)
46
{
47
  if (string)
48
    lua_pushlstring(L, (char*)ASN1_STRING_data(string), ASN1_STRING_length(string));
49
  else
50
    lua_pushnil(L);
51
}
52
 
53
int luasec_push_subtable(lua_State* L, int idx)
54
{
55
 
56
  lua_pushvalue(L, -1);
57
  lua_gettable(L, idx-1);
58
 
59
  if (lua_isnil(L, -1))
60
  {
61
    lua_pop(L, 1);
62
    lua_newtable(L);
63
    lua_pushvalue(L, -2);
64
    lua_pushvalue(L, -2);
65
    lua_settable(L, idx-3);
66
 
67
    lua_replace(L, -2); /* Replace key with table */
68
    return 1;
69
  }
70
 
71
  lua_replace(L, -2); /* Replace key with table */
72
  return 0;
73
}
74
 
75
void luasec_push_x509_name(lua_State* L, X509_NAME *name)
76
{
77
  int i, n_entries;
78
  lua_newtable(L);
79
  n_entries = X509_NAME_entry_count(name);
80
 
81
  for (i = 0; i < n_entries; i++)
82
  {
83
    X509_NAME_ENTRY *entry;
84
    ASN1_OBJECT *object;
85
 
86
    entry = X509_NAME_get_entry(name, i);
87
    object = X509_NAME_ENTRY_get_object(entry);
88
 
89
    lua_newtable(L);
90
 
91
    luasec_push_asn1_objname(L, object, 1);
92
    lua_setfield(L, -2, "oid");
93
 
94
    luasec_push_asn1_objname(L, object, 0);
95
    lua_setfield(L, -2, "name");
96
 
97
    luasec_push_asn1_string(L, X509_NAME_ENTRY_get_data(entry));
98
    lua_setfield(L, -2, "value");
99
 
100
    lua_rawseti(L, -2, lua_objlen(L, -2)+1);
101
 
102
  }
103
}
104
 
105
 
106
int meth_subject(lua_State* L)
107
{
108
  luasec_push_x509_name(L, X509_get_subject_name(luasec_to_x509(L, 1)));
109
  return 1;
110
}
111
 
112
int meth_issuer(lua_State* L)
113
{
114
  luasec_push_x509_name(L, X509_get_issuer_name(luasec_to_x509(L, 1)));
115
  return 1;
116
}
117
 
118
int meth_extensions(lua_State* L)
119
{
120
  X509 *peer;
121
  int i, j;
122
 
123
  peer = luasec_to_x509(L, 1);
124
 
125
  lua_newtable(L); /* ret */
126
 
127
  i = -1;
128
  while ((i = X509_get_ext_by_NID(peer, NID_subject_alt_name, i)) != -1)
129
  {
130
    X509_EXTENSION *extension;
131
    STACK_OF(GENERAL_NAME) *values;
132
    int n_general_names;
133
 
134
    extension = X509_get_ext(peer, i);
135
    if (extension == NULL)
136
      break;
137
 
138
    values = X509V3_EXT_d2i(extension);
139
    if (values == NULL)
140
      break;
141
 
142
    /* Push ret[oid] */
143
    luasec_push_asn1_objname(L, extension->object, 1);
144
    luasec_push_subtable(L, -2);
145
    /* Set ret[oid].name = name */
146
    luasec_push_asn1_objname(L, extension->object, 0);
147
    lua_setfield(L, -2, "name");
148
 
149
    n_general_names = sk_GENERAL_NAME_num(values);
150
    for (j = 0; j < n_general_names; j++)
151
    {
152
      GENERAL_NAME *general_name;
153
 
154
      general_name = sk_GENERAL_NAME_value(values, j);
155
 
156
      switch(general_name->type)
157
      {
158
      case GEN_OTHERNAME:
159
      {
160
        OTHERNAME *otherName = general_name->d.otherName;
161
 
162
        luasec_push_asn1_objname(L, otherName->type_id, 1);
163
 
164
        if (luasec_push_subtable(L, -2))
165
        {
166
          luasec_push_asn1_objname(L, otherName->type_id, 0);
167
          lua_setfield(L, -2, "name");
168
        }
169
 
170
        luasec_push_asn1_string(L, otherName->value->value.asn1_string);
171
        lua_rawseti(L, -2, lua_objlen(L, -2)+1);
172
 
173
        lua_pop(L, 1);
174
        break;
175
      }
176
      case GEN_EMAIL:
177
        lua_pushstring(L, "rfc822Name");
178
        luasec_push_subtable(L, -2);
179
        luasec_push_asn1_string(L, general_name->d.rfc822Name);
180
        lua_rawseti(L, -2, lua_objlen(L, -2)+1);
181
        lua_pop(L, 1);
182
        break;
183
      case GEN_DNS:
184
        lua_pushstring(L, "dNSName");
185
        luasec_push_subtable(L, -2);
186
        luasec_push_asn1_string(L, general_name->d.dNSName);
187
        lua_rawseti(L, -2, lua_objlen(L, -2)+1);
188
        lua_pop(L, 1);
189
        break;
190
      case GEN_X400:
191
        /* x400Address */
192
        break;
193
      case GEN_DIRNAME:
194
        /* directoryName */
195
        break;
196
      case GEN_EDIPARTY:
197
        /* ediPartyName */
198
        break;
199
      case GEN_URI:
200
        lua_pushstring(L, "uniformResourceIdentifier");
201
        luasec_push_subtable(L, -2);
202
        luasec_push_asn1_string(L, general_name->d.uniformResourceIdentifier);
203
        lua_rawseti(L, -2, lua_objlen(L, -2)+1);
204
        lua_pop(L, 1);
205
        break;
206
      case GEN_IPADD:
207
        lua_pushstring(L, "iPAddress");
208
        luasec_push_subtable(L, -2);
209
        luasec_push_asn1_string(L, general_name->d.iPAddress);
210
        lua_rawseti(L, -2, lua_objlen(L, -2)+1);
211
        lua_pop(L, 1);
212
        break;
213
      case GEN_RID:
214
        /* registeredID */
215
        break;
216
      default:
217
        break;
218
      }
219
    }
220
 
221
    lua_pop(L, 1); /* ret[oid] */
222
    i++; /* Next extension */
223
  }
224
  return 1;
225
}
226
 
227
int meth_valid_at(lua_State* L)
228
{
229
  X509* cert = luasec_to_x509(L, 1);
230
  time_t time = luaL_checkinteger(L, 2);
231
  lua_pushboolean(L, (X509_cmp_time(X509_get_notAfter(cert), &time) >= 0
232
                  && X509_cmp_time(X509_get_notBefore(cert), &time) <= 0));
233
  return 1;
234
}
235
 
236
int meth_pem(lua_State* L)
237
{
238
  X509* cert = luasec_to_x509(L, 1);
239
  BIO *bio = BIO_new(BIO_s_mem());
240
  char* data; long bytes;
241
  if (!PEM_write_bio_X509(bio, cert))
242
  {
243
    lua_pushnil(L);
244
    return 1;
245
  }
246
  bytes = BIO_get_mem_data(bio, &data);
247
  if (bytes > 0)
248
    lua_pushlstring(L, data, bytes);
249
  else
250
    lua_pushnil(L);
251
  BIO_free(bio);
252
  return 1;
253
}
254
 
255
const char* hex_tab = "0123456789abcdef";
256
void to_hex(const char* in, int length, char* out) {
257
  int i;
258
  for (i = 0; i < length; i++) {
259
    out[i*2] = hex_tab[(in[i] >> 4) & 0xF];
260
    out[i*2+1] = hex_tab[(in[i]) & 0xF];
261
  }
262
}
263
 
264
int meth_digest(lua_State* L)
265
{
266
  X509 *cert;
267
  unsigned int bytes;
268
  unsigned char buffer[EVP_MAX_MD_SIZE];
269
  char hex_buffer[EVP_MAX_MD_SIZE*2];
270
  const EVP_MD *digest;
271
  cert = luasec_to_x509(L, 1);
272
  if (lua_gettop(L) < 2 || strcmp(luaL_checkstring(L, 2), "sha1") == 0)
273
  {
274
    digest = EVP_sha1();
275
  }
276
  else
277
  {
278
    lua_pushnil(L);
279
    lua_pushstring(L, "digest algorithm not supported");
280
    return 2;
281
  }
282
  if (!X509_digest(cert, digest, buffer, &bytes))
283
  {
284
    lua_pushnil(L);
285
    lua_pushstring(L, "out of memory");
286
    return 2;
287
  }
288
  to_hex((char*)buffer, bytes, hex_buffer);
289
  lua_pushlstring(L, hex_buffer, bytes*2);
290
  return 1;
291
}
292
 
293
int meth_destroy(lua_State* L)
294
{
295
  X509_free(luasec_to_x509(L, 1));
296
  return 0;
297
}
298
 
299
int meth_tostring(lua_State *L)
300
{
301
  X509 *cert = luasec_to_x509(L, 1);
302
  lua_pushfstring(L, "X509 certificate: %p", cert);
303
  return 1;
304
}
305
 
306
int cert_from_pem(lua_State* L)
307
{
308
  X509 *cert;
309
  BIO *bio = BIO_new(BIO_s_mem());
310
  const char* data; size_t bytes;
311
  data = luaL_checklstring(L, 1, &bytes);
312
  BIO_write(bio, data, bytes);
313
  cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
314
  if (cert)
315
    luasec_push_x509(L, cert);
316
  else
317
    lua_pushnil(L);
318
  BIO_free(bio);
319
  return 1;
320
}
321
 
322
/**
323
 * Certificate metamethods
324
 */
325
static luaL_Reg methods[] = {
326
  {"subject",       meth_subject},
327
  {"issuer",        meth_issuer},
328
  {"extensions",    meth_extensions},
329
  {"valid_at",      meth_valid_at},
330
  {"pem",           meth_pem},
331
  {"digest",        meth_digest},
332
  {NULL,            NULL}
333
};
334
 
335
/**
336
 * ssl.x509 functions
337
 */
338
static luaL_Reg funcs[] = {
339
  {"cert_from_pem", cert_from_pem},
340
  {NULL,            NULL}
341
};
342
 
343
/**
344
 * Context metamethods.
345
 */
346
static luaL_Reg meta[] = {
347
  {"__gc",       meth_destroy},
348
  {"__tostring", meth_tostring},
349
  {NULL, NULL}
350
};
351
 
352
LUASEC_API int luaopen_ssl_x509(lua_State *L)
353
{
354
  /* Register the functions and tables */
355
  luaL_newmetatable(L, "SSL:Certificate");
356
  luaL_register(L, NULL, meta);
357
 
358
  lua_newtable(L);
359
  luaL_register(L, NULL, methods);
360
  lua_setfield(L, -2, "__index");
361
 
362
  luaL_register(L, "ssl.x509", funcs);
363
  return 1;
364
}