|
|
@@ -17,6 +17,8 @@ |
|
|
|
#include "rspamadm.h" |
|
|
|
#include "printf.h" |
|
|
|
#include "str_util.h" |
|
|
|
#include "libcryptobox/cryptobox.h" |
|
|
|
#include "contrib/libottery/ottery.h" |
|
|
|
#include "lua/lua_common.h" |
|
|
|
#include <openssl/rsa.h> |
|
|
|
#include <openssl/bn.h> |
|
|
@@ -26,6 +28,7 @@ static gchar *privkey_file = NULL; |
|
|
|
static gchar *selector = NULL; |
|
|
|
static gchar *domain = NULL; |
|
|
|
static guint bits = 1024; |
|
|
|
static gchar *type = "rsa"; |
|
|
|
|
|
|
|
static void rspamadm_dkim_keygen (gint argc, gchar **argv, |
|
|
|
const struct rspamadm_command *cmd); |
|
|
@@ -50,6 +53,8 @@ static GOptionEntry entries[] = { |
|
|
|
"Save private key in the specified file", NULL}, |
|
|
|
{"bits", 'b', 0, G_OPTION_ARG_INT, &bits, |
|
|
|
"Set key length to N bits (1024 by default)", NULL}, |
|
|
|
{"type", 't', 0, G_OPTION_ARG_STRING, &type, |
|
|
|
"Key type: rsa or ed25519 (rsa by default)", NULL}, |
|
|
|
{NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL} |
|
|
|
}; |
|
|
|
|
|
|
@@ -76,8 +81,9 @@ rspamadm_dkim_keygen_help (gboolean full_help, const struct rspamadm_command *cm |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector, |
|
|
|
const gchar *priv_fname, const gchar *pub_fname, guint keylen) |
|
|
|
rspamd_dkim_generate_rsa_keypair (const gchar *domain, const gchar *selector, |
|
|
|
const gchar *priv_fname, const gchar *pub_fname, |
|
|
|
guint keylen) |
|
|
|
{ |
|
|
|
BIGNUM *e; |
|
|
|
RSA *r; |
|
|
@@ -109,8 +115,7 @@ rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector, |
|
|
|
priv_fname, strerror (errno)); |
|
|
|
exit (EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
} else { |
|
|
|
privout = BIO_new_fp (stdout, 0); |
|
|
|
} |
|
|
|
|
|
|
@@ -125,7 +130,7 @@ rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector, |
|
|
|
BIO_free (privout); |
|
|
|
fflush (stdout); |
|
|
|
|
|
|
|
pubout = BIO_new (BIO_s_mem()); |
|
|
|
pubout = BIO_new (BIO_s_mem ()); |
|
|
|
|
|
|
|
rc = i2d_RSA_PUBKEY_bio (pubout, r); |
|
|
|
publen = BIO_get_mem_data (pubout, &pubdata); |
|
|
@@ -141,18 +146,16 @@ rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector, |
|
|
|
pub_fname, strerror (errno)); |
|
|
|
exit (EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
} else { |
|
|
|
pubfile = stdout; |
|
|
|
} |
|
|
|
|
|
|
|
if (b64_len < 255 - 2) { |
|
|
|
rspamd_fprintf (pubfile, "%s._domainkey IN TXT ( \"v=DKIM1; k=rsa; \"\n" |
|
|
|
"\t\"p=%s\" ) ;\n", |
|
|
|
"\t\"p=%s\" ) ;\n", |
|
|
|
selector ? selector : "selector", |
|
|
|
b64_data); |
|
|
|
} |
|
|
|
else { |
|
|
|
} else { |
|
|
|
guint i; |
|
|
|
gint step = 253, remain = b64_len; |
|
|
|
|
|
|
@@ -162,8 +165,7 @@ rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector, |
|
|
|
for (i = 0; i < b64_len; i += step, remain -= step) { |
|
|
|
if (i == 0) { |
|
|
|
rspamd_fprintf (pubfile, "\t\"p=%*s\"\n", MIN(step, remain), &b64_data[i]); |
|
|
|
} |
|
|
|
else { |
|
|
|
} else { |
|
|
|
step = 255; |
|
|
|
rspamd_fprintf (pubfile, "\t\"%*s\"\n", MIN(step, remain), &b64_data[i]); |
|
|
|
} |
|
|
@@ -183,6 +185,108 @@ rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector, |
|
|
|
BN_free (e); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
rspamd_dkim_generate_ed25519_keypair (const gchar *domain, const gchar *selector, |
|
|
|
const gchar *priv_fname, const gchar *pub_fname, |
|
|
|
guint keylen) |
|
|
|
{ |
|
|
|
rspamd_sig_sk_t ed_sk; |
|
|
|
rspamd_sig_pk_t ed_pk; |
|
|
|
gchar *base64_pk, *base64_sk; |
|
|
|
FILE *pubfile = NULL, *privfile = NULL; |
|
|
|
|
|
|
|
rspamd_cryptobox_keypair_sig (ed_pk, ed_sk, RSPAMD_CRYPTOBOX_MODE_25519); |
|
|
|
/* Just encode seed, not the full sk */ |
|
|
|
base64_sk = rspamd_encode_base64_common (ed_sk, 32, 0, NULL, FALSE, |
|
|
|
RSPAMD_TASK_NEWLINES_LF); |
|
|
|
base64_pk = rspamd_encode_base64_common (ed_pk, sizeof (ed_pk), 0, NULL, FALSE, |
|
|
|
RSPAMD_TASK_NEWLINES_LF); |
|
|
|
|
|
|
|
/* Cleanup sensitive data */ |
|
|
|
rspamd_explicit_memzero (ed_sk, sizeof (ed_sk)); |
|
|
|
|
|
|
|
if (priv_fname) { |
|
|
|
privfile = fopen (priv_fname, "w"); |
|
|
|
|
|
|
|
if (privfile == NULL) { |
|
|
|
rspamd_fprintf (stderr, "cannot open output file %s: %s\n", |
|
|
|
priv_fname, strerror (errno)); |
|
|
|
rspamd_explicit_memzero (base64_sk, strlen (base64_sk)); |
|
|
|
g_free (base64_sk); |
|
|
|
g_free (base64_pk); |
|
|
|
exit (EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
privfile = stdout; |
|
|
|
} |
|
|
|
|
|
|
|
if (rspamd_fprintf (privfile, "%s\n", base64_sk) == -1) { |
|
|
|
rspamd_fprintf (stderr, "cannot write to output file %s: %s\n", |
|
|
|
priv_fname, strerror (errno)); |
|
|
|
rspamd_explicit_memzero (base64_sk, strlen (base64_sk)); |
|
|
|
g_free (base64_sk); |
|
|
|
g_free (base64_pk); |
|
|
|
|
|
|
|
if (privfile != stdout) { |
|
|
|
fclose (privfile); |
|
|
|
} |
|
|
|
|
|
|
|
exit (EXIT_FAILURE); |
|
|
|
} |
|
|
|
|
|
|
|
if (privfile != stdout) { |
|
|
|
fclose (privfile); |
|
|
|
} |
|
|
|
|
|
|
|
if (pub_fname) { |
|
|
|
pubfile = fopen (pub_fname, "w"); |
|
|
|
|
|
|
|
if (pubfile == NULL) { |
|
|
|
rspamd_fprintf (stderr, "cannot open output file %s: %s\n", |
|
|
|
pub_fname, strerror (errno)); |
|
|
|
rspamd_explicit_memzero (base64_sk, strlen (base64_sk)); |
|
|
|
g_free (base64_sk); |
|
|
|
g_free (base64_pk); |
|
|
|
exit (EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
pubfile = stdout; |
|
|
|
} |
|
|
|
|
|
|
|
rspamd_fprintf (pubfile, "%s._domainkey IN TXT ( \"v=DKIM1; k=ed25519; \"\n" |
|
|
|
"\t\"p=%s\" ) ;\n", |
|
|
|
selector ? selector : "selector", |
|
|
|
base64_pk); |
|
|
|
|
|
|
|
if (pubfile != stdout) { |
|
|
|
fclose (pubfile); |
|
|
|
} |
|
|
|
|
|
|
|
rspamd_explicit_memzero (base64_sk, strlen (base64_sk)); |
|
|
|
g_free (base64_sk); |
|
|
|
g_free (base64_pk); |
|
|
|
} |
|
|
|
|
|
|
|
static void |
|
|
|
rspamadm_dkim_generate_keypair (const gchar *domain, const gchar *selector, |
|
|
|
const gchar *priv_fname, const gchar *pub_fname, guint keylen) |
|
|
|
{ |
|
|
|
if (strcmp (type, "rsa") == 0) { |
|
|
|
rspamd_dkim_generate_rsa_keypair (domain, selector, priv_fname, |
|
|
|
pub_fname, keylen); |
|
|
|
} |
|
|
|
else if (strcmp (type, "ed25519") == 0) { |
|
|
|
rspamd_dkim_generate_ed25519_keypair (domain, selector, priv_fname, |
|
|
|
pub_fname, keylen); |
|
|
|
} |
|
|
|
else { |
|
|
|
fprintf (stderr, "invalid key type: %s\n", type); |
|
|
|
exit (EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static gint |
|
|
|
rspamadm_dkim_keygen_lua_generate (lua_State *L) |
|
|
|
{ |