diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-06-13 15:47:32 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-06-13 15:47:32 +0100 |
commit | b346120d244ee4761bb0b0838ae00264376b97e9 (patch) | |
tree | 26c9ecd3051b656e93153f426a9140d6bc543b92 /src/lua/lua_rsa.c | |
parent | 9deefe925c11413cb4e37bf6ef7fd13730e7af1d (diff) | |
download | rspamd-b346120d244ee4761bb0b0838ae00264376b97e9.tar.gz rspamd-b346120d244ee4761bb0b0838ae00264376b97e9.zip |
Add a simple test of rsa utils in lua.
Support RSA signing in lua_rsa module.
Add save function for rsa_signature.
Fix test logic for lua modules.
Diffstat (limited to 'src/lua/lua_rsa.c')
-rw-r--r-- | src/lua/lua_rsa.c | 360 |
1 files changed, 325 insertions, 35 deletions
diff --git a/src/lua/lua_rsa.c b/src/lua/lua_rsa.c index 66b1f9b26..38820e4e2 100644 --- a/src/lua/lua_rsa.c +++ b/src/lua/lua_rsa.c @@ -36,30 +36,50 @@ #include <openssl/rsa.h> #include <openssl/pem.h> -LUA_FUNCTION_DEF (rsa_key, load); -LUA_FUNCTION_DEF (rsa_key, create); -LUA_FUNCTION_DEF (rsa_key, gc); +LUA_FUNCTION_DEF (rsa_pubkey, load); +LUA_FUNCTION_DEF (rsa_pubkey, create); +LUA_FUNCTION_DEF (rsa_pubkey, gc); +LUA_FUNCTION_DEF (rsa_privkey, load); +LUA_FUNCTION_DEF (rsa_privkey, create); +LUA_FUNCTION_DEF (rsa_privkey, gc); LUA_FUNCTION_DEF (rsa_signature, create); LUA_FUNCTION_DEF (rsa_signature, load); +LUA_FUNCTION_DEF (rsa_signature, save); LUA_FUNCTION_DEF (rsa_signature, gc); -LUA_FUNCTION_DEF (rsa, check_memory); -LUA_FUNCTION_DEF (rsa, check_file); +LUA_FUNCTION_DEF (rsa, verify_memory); +LUA_FUNCTION_DEF (rsa, verify_file); +LUA_FUNCTION_DEF (rsa, sign_file); +LUA_FUNCTION_DEF (rsa, sign_memory); static const struct luaL_reg rsalib_f[] = { - LUA_INTERFACE_DEF (rsa, check_memory), - LUA_INTERFACE_DEF (rsa, check_file), + LUA_INTERFACE_DEF (rsa, verify_memory), + LUA_INTERFACE_DEF (rsa, verify_file), + LUA_INTERFACE_DEF (rsa, sign_memory), + LUA_INTERFACE_DEF (rsa, sign_file), {NULL, NULL} }; -static const struct luaL_reg rsakeylib_f[] = { - LUA_INTERFACE_DEF (rsa_key, load), - LUA_INTERFACE_DEF (rsa_key, create), +static const struct luaL_reg rsapubkeylib_f[] = { + LUA_INTERFACE_DEF (rsa_pubkey, load), + LUA_INTERFACE_DEF (rsa_pubkey, create), {NULL, NULL} }; -static const struct luaL_reg rsakeylib_m[] = { +static const struct luaL_reg rsapubkeylib_m[] = { {"__tostring", lua_class_tostring}, - {"__gc", lua_rsa_key_gc}, + {"__gc", lua_rsa_pubkey_gc}, + {NULL, NULL} +}; + +static const struct luaL_reg rsaprivkeylib_f[] = { + LUA_INTERFACE_DEF (rsa_privkey, load), + LUA_INTERFACE_DEF (rsa_privkey, create), + {NULL, NULL} +}; + +static const struct luaL_reg rsaprivkeylib_m[] = { + {"__tostring", lua_class_tostring}, + {"__gc", lua_rsa_privkey_gc}, {NULL, NULL} }; @@ -70,17 +90,27 @@ static const struct luaL_reg rsasignlib_f[] = { }; static const struct luaL_reg rsasignlib_m[] = { + LUA_INTERFACE_DEF (rsa_signature, save), {"__tostring", lua_class_tostring}, {"__gc", lua_rsa_signature_gc}, {NULL, NULL} }; static RSA * -lua_check_rsa_key (lua_State * L, int pos) +lua_check_rsa_pubkey (lua_State * L, int pos) +{ + void *ud = luaL_checkudata (L, pos, "rspamd{rsa_pubkey}"); + + luaL_argcheck (L, ud != NULL, 1, "'rsa_pubkey' expected"); + return ud ? *((RSA **)ud) : NULL; +} + +static RSA * +lua_check_rsa_privkey (lua_State * L, int pos) { - void *ud = luaL_checkudata (L, pos, "rspamd{rsa_key}"); + void *ud = luaL_checkudata (L, pos, "rspamd{rsa_privkey}"); - luaL_argcheck (L, ud != NULL, 1, "'rsa_key' expected"); + luaL_argcheck (L, ud != NULL, 1, "'rsa_privkey' expected"); return ud ? *((RSA **)ud) : NULL; } @@ -94,7 +124,7 @@ lua_check_rsa_sign (lua_State * L, int pos) } static gint -lua_rsa_key_load (lua_State *L) +lua_rsa_pubkey_load (lua_State *L) { RSA *rsa = NULL, **prsa; const gchar *filename; @@ -115,7 +145,7 @@ lua_rsa_key_load (lua_State *L) } else { prsa = lua_newuserdata (L, sizeof (RSA *)); - lua_setclass (L, "rspamd{rsa_key}", -1); + lua_setclass (L, "rspamd{rsa_pubkey}", -1); *prsa = rsa; } fclose (f); @@ -128,7 +158,7 @@ lua_rsa_key_load (lua_State *L) } static gint -lua_rsa_key_create (lua_State *L) +lua_rsa_pubkey_create (lua_State *L) { RSA *rsa = NULL, **prsa; const gchar *buf; @@ -145,7 +175,7 @@ lua_rsa_key_create (lua_State *L) } else { prsa = lua_newuserdata (L, sizeof (RSA *)); - lua_setclass (L, "rspamd{rsa_key}", -1); + lua_setclass (L, "rspamd{rsa_pubkey}", -1); *prsa = rsa; } BIO_free (bp); @@ -157,9 +187,84 @@ lua_rsa_key_create (lua_State *L) } static gint -lua_rsa_key_gc (lua_State *L) +lua_rsa_pubkey_gc (lua_State *L) { - RSA *rsa = lua_check_rsa_key (L, 1); + RSA *rsa = lua_check_rsa_pubkey (L, 1); + + if (rsa != NULL) { + RSA_free (rsa); + } + + return 0; +} + +static gint +lua_rsa_privkey_load (lua_State *L) +{ + RSA *rsa = NULL, **prsa; + const gchar *filename; + FILE *f; + + filename = luaL_checkstring (L, 1); + if (filename != NULL) { + f = fopen (filename, "r"); + if (f == NULL) { + msg_err ("cannot open private key from file: %s, %s", filename, strerror (errno)); + lua_pushnil (L); + } + else { + if (! PEM_read_RSAPrivateKey (f, &rsa, NULL, NULL)) { + msg_err ("cannot open private key from file: %s, %s", filename, + ERR_error_string (ERR_get_error (), NULL)); + lua_pushnil (L); + } + else { + prsa = lua_newuserdata (L, sizeof (RSA *)); + lua_setclass (L, "rspamd{rsa_privkey}", -1); + *prsa = rsa; + } + fclose (f); + } + } + else { + lua_pushnil (L); + } + return 1; +} + +static gint +lua_rsa_privkey_create (lua_State *L) +{ + RSA *rsa = NULL, **prsa; + const gchar *buf; + BIO *bp; + + buf = luaL_checkstring (L, 1); + if (buf != NULL) { + bp = BIO_new_mem_buf ((void *)buf, -1); + + if (! PEM_read_bio_RSAPrivateKey (bp, &rsa, NULL, NULL)) { + msg_err ("cannot parse private key: %s", + ERR_error_string (ERR_get_error (), NULL)); + lua_pushnil (L); + } + else { + prsa = lua_newuserdata (L, sizeof (RSA *)); + lua_setclass (L, "rspamd{rsa_privkey}", -1); + *prsa = rsa; + } + BIO_free (bp); + } + else { + lua_pushnil (L); + } + return 1; +} + +static gint +lua_rsa_privkey_gc (lua_State *L) +{ + RSA *rsa = lua_check_rsa_privkey (L, 1); if (rsa != NULL) { RSA_free (rsa); @@ -211,6 +316,53 @@ lua_rsa_signature_load (lua_State *L) } static gint +lua_rsa_signature_save (lua_State *L) +{ + f_str_t *sig; + gint fd, flags; + const gchar *filename; + gboolean forced = FALSE, res = TRUE; + + sig = lua_check_rsa_sign (L, 1); + filename = luaL_checkstring (L, 2); + if (lua_gettop (L) > 2) { + forced = lua_toboolean (L, 3); + } + + if (sig != NULL && filename != NULL) { + flags = O_WRONLY | O_CREAT; + if (forced) { + flags |= O_TRUNC; + } + else { + flags |= O_EXCL; + } + fd = open (filename, flags, 00644); + if (fd == -1) { + msg_err ("cannot create a signature file: %s, %s", filename, strerror (errno)); + lua_pushboolean (L, FALSE); + } + else { + while (write (fd, sig->begin, sig->len) == -1) { + if (errno == EINTR) { + continue; + } + msg_err ("cannot write to a signature file: %s, %s", filename, strerror (errno)); + res = FALSE; + break; + } + lua_pushboolean (L, res); + close (fd); + } + } + else { + lua_pushboolean (L, FALSE); + } + + return 1; +} + +static gint lua_rsa_signature_create (lua_State *L) { f_str_t *sig, **psig; @@ -250,14 +402,14 @@ lua_rsa_signature_gc (lua_State *L) * Check memory using specified rsa key and signature * * arguments: - * (rsa_key, rsa_signature, string) + * (rsa_pubkey, rsa_signature, string) * * returns: * true - if string match rsa signature * false - otherwise */ static gint -lua_rsa_check_memory (lua_State *L) +lua_rsa_verify_memory (lua_State *L) { RSA *rsa; f_str_t *signature; @@ -265,19 +417,23 @@ lua_rsa_check_memory (lua_State *L) gchar *data_sig; gint ret; - rsa = lua_check_rsa_key (L, 1); + rsa = lua_check_rsa_pubkey (L, 1); signature = lua_check_rsa_sign (L, 2); data = luaL_checkstring (L, 3); if (rsa != NULL && signature != NULL && data != NULL) { data_sig = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, -1); - ret = RSA_verify (NID_sha1, signature->begin, signature->len, data_sig, strlen (data_sig), rsa); + ret = RSA_verify (NID_sha1, data_sig, strlen (data_sig), + signature->begin, signature->len, rsa); if (ret == 0) { + msg_info ("cannot check rsa signature for data: %s", + ERR_error_string (ERR_get_error (), NULL)); lua_pushboolean (L, FALSE); } else { lua_pushboolean (L, TRUE); } + g_free (data_sig); } else { lua_pushnil (L); @@ -290,14 +446,14 @@ lua_rsa_check_memory (lua_State *L) * Check memory using specified rsa key and signature * * arguments: - * (rsa_key, rsa_signature, string) + * (rsa_pubkey, rsa_signature, string) * * returns: * true - if string match rsa signature * false - otherwise */ static gint -lua_rsa_check_file (lua_State *L) +lua_rsa_verify_file (lua_State *L) { RSA *rsa; f_str_t *signature; @@ -306,11 +462,11 @@ lua_rsa_check_file (lua_State *L) gint ret, fd; struct stat st; - rsa = lua_check_rsa_key (L, 1); + rsa = lua_check_rsa_pubkey (L, 1); signature = lua_check_rsa_sign (L, 2); filename = luaL_checkstring (L, 3); - if (rsa != NULL && signature != NULL && data != NULL) { + if (rsa != NULL && signature != NULL && filename != NULL) { fd = open (filename, O_RDONLY); if (fd == -1) { msg_err ("cannot open file %s: %s", filename, strerror (errno)); @@ -324,14 +480,136 @@ lua_rsa_check_file (lua_State *L) } else { data_sig = g_compute_checksum_for_data (G_CHECKSUM_SHA256, data, st.st_size); - ret = RSA_verify (NID_sha1, signature->begin, signature->len, - data_sig, strlen (data_sig), rsa); + ret = RSA_verify (NID_sha1, data_sig, strlen (data_sig), + signature->begin, signature->len, rsa); if (ret == 0) { + msg_info ("cannot check rsa signature for file: %s, %s", + filename, ERR_error_string (ERR_get_error (), NULL)); lua_pushboolean (L, FALSE); } else { lua_pushboolean (L, TRUE); } + g_free (data_sig); + munmap (data, st.st_size); + } + close (fd); + } + } + else { + lua_pushnil (L); + } + + return 1; +} + +/** + * Sign memory using specified rsa key and signature + * + * arguments: + * (rsa_privkey, string) + * + * returns: + * rspamd_signature object + * nil - otherwise + */ +static gint +lua_rsa_sign_memory (lua_State *L) +{ + RSA *rsa; + f_str_t *signature, **psig; + const gchar *data; + gchar *data_sig; + gint ret; + + rsa = lua_check_rsa_privkey (L, 1); + data = luaL_checkstring (L, 2); + + if (rsa != NULL && data != NULL) { + signature = g_malloc (sizeof (f_str_t)); + signature->len = RSA_size (rsa); + signature->size = signature->len; + signature->begin = g_malloc (signature->len); + data_sig = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, -1); + ret = RSA_sign (NID_sha1, data_sig, strlen (data_sig), + signature->begin, (guint *)&signature->len, rsa); + if (ret == 0) { + msg_info ("cannot make a signature for data: %s", + ERR_error_string (ERR_get_error (), NULL)); + lua_pushnil (L); + g_free (signature->begin); + g_free (signature); + } + else { + psig = lua_newuserdata (L, sizeof (f_str_t *)); + lua_setclass (L, "rspamd{rsa_signature}", -1); + *psig = signature; + } + g_free (data_sig); + } + else { + lua_pushnil (L); + } + + return 1; +} + +/** + * Sign file using specified rsa key and signature + * + * arguments: + * (rsa_privkey, rsa_signature, string) + * + * returns: + * true - if string match rsa signature + * false - otherwise + */ +static gint +lua_rsa_sign_file (lua_State *L) +{ + RSA *rsa; + f_str_t *signature, **psig; + const gchar *filename; + gchar *data = NULL, *data_sig; + gint ret, fd; + struct stat st; + + rsa = lua_check_rsa_privkey (L, 1); + filename = luaL_checkstring (L, 2); + + if (rsa != NULL && filename != NULL) { + fd = open (filename, O_RDONLY); + if (fd == -1) { + msg_err ("cannot open file %s: %s", filename, strerror (errno)); + lua_pushnil (L); + } + else { + if (fstat (fd, &st) == -1 || + (data = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { + msg_err ("cannot mmap file %s: %s", filename, strerror (errno)); + lua_pushnil (L); + } + else { + signature = g_malloc (sizeof (f_str_t)); + signature->len = RSA_size (rsa); + signature->size = signature->len; + signature->begin = g_malloc (signature->len); + data_sig = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, st.st_size); + ret = RSA_sign (NID_sha1, data_sig, strlen (data_sig), + signature->begin, (guint *)&signature->len, rsa); + if (ret == 0) { + msg_info ("cannot make a signature for data: %s", + ERR_error_string (ERR_get_error (), NULL)); + lua_pushnil (L); + g_free (signature->begin); + g_free (signature); + } + else { + psig = lua_newuserdata (L, sizeof (f_str_t *)); + lua_setclass (L, "rspamd{rsa_signature}", -1); + *psig = signature; + } + g_free (data_sig); munmap (data, st.st_size); } close (fd); @@ -347,17 +625,29 @@ lua_rsa_check_file (lua_State *L) gint luaopen_rsa (lua_State * L) { - luaL_newmetatable (L, "rspamd{rsa_key}"); + luaL_newmetatable (L, "rspamd{rsa_pubkey}"); + lua_pushstring (L, "__index"); + lua_pushvalue (L, -2); + lua_settable (L, -3); + + lua_pushstring (L, "class"); + lua_pushstring (L, "rspamd{rsa_pubkey}"); + lua_rawset (L, -3); + + luaL_register (L, NULL, rsapubkeylib_m); + luaL_register (L, "rsa_pubkey", rsapubkeylib_f); + + luaL_newmetatable (L, "rspamd{rsa_privkey}"); lua_pushstring (L, "__index"); lua_pushvalue (L, -2); lua_settable (L, -3); lua_pushstring (L, "class"); - lua_pushstring (L, "rspamd{rsa_key}"); + lua_pushstring (L, "rspamd{rsa_privkey}"); lua_rawset (L, -3); - luaL_register (L, NULL, rsakeylib_m); - luaL_register (L, "rsa_key", rsakeylib_f); + luaL_register (L, NULL, rsaprivkeylib_m); + luaL_register (L, "rsa_privkey", rsaprivkeylib_f); luaL_newmetatable (L, "rspamd{rsa_signature}"); lua_pushstring (L, "__index"); |