return hdr;
}
+
+gboolean
+rspamd_dkim_match_keys (rspamd_dkim_key_t *pk,
+ rspamd_dkim_sign_key_t *sk,
+ GError **err)
+{
+ const BIGNUM *n1, *n2;
+
+ if (pk == NULL || sk == NULL) {
+ g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
+ "missing public or private key");
+ return FALSE;
+ }
+
+ if (pk->type != RSPAMD_DKIM_KEY_RSA) {
+ g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYFAIL,
+ "pubkey is not RSA key");
+ return FALSE;
+ }
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+ RSA_get0_key (pk->key.key_rsa, &n1, NULL, NULL);
+ n2 = RSA_get0_key (sk->key_rsa, &n2, NULL, NULL);
+#else
+ n1 = pk->key.key_rsa->n;
+ n2 = sk->key_rsa->n;
+#endif
+
+ if (BN_cmp (n1, n2) != 0) {
+ g_set_error (err, dkim_error_quark (), DKIM_SIGERROR_KEYHASHMISMATCH,
+ "pubkey does not match private key");
+ return FALSE;
+ }
+
+ return TRUE;
+}
\ No newline at end of file
GError *err = NULL;
GString *hdr;
const gchar *selector = NULL, *domain = NULL, *key = NULL, *rawkey = NULL,
- *headers = NULL, *sign_type_str = NULL, *arc_cv = NULL;
+ *headers = NULL, *sign_type_str = NULL, *arc_cv = NULL,
+ *pubkey = NULL;
rspamd_dkim_sign_context_t *ctx;
rspamd_dkim_sign_key_t *dkim_key;
gsize rawlen = 0, keylen = 0;
*/
if (!rspamd_lua_parse_table_arguments (L, 2, &err,
"key=V;rawkey=V;*domain=S;*selector=S;no_cache=B;headers=S;"
- "sign_type=S;arc_idx=I;arc_cv=S;expire=I",
+ "sign_type=S;arc_idx=I;arc_cv=S;expire=I;pubkey=S",
&keylen, &key, &rawlen, &rawkey, &domain,
&selector, &no_cache, &headers,
- &sign_type_str, &arc_idx, &arc_cv, &expire)) {
- msg_err_task ("invalid return value from sign condition: %e",
+ &sign_type_str, &arc_idx, &arc_cv, &expire, &pubkey)) {
+ msg_err_task ("cannot parse table arguments: %e",
err);
g_error_free (err);
}
}
+ if (pubkey != NULL) {
+ /* Also check if private and public keys match */
+ rspamd_dkim_key_t *pk;
+ gsize keylen = strlen (pubkey);
+
+ pk = rspamd_dkim_parse_key (pubkey, &keylen, NULL);
+
+ if (pk == NULL) {
+ msg_warn_task ("cannot parse pubkey from string: %s",
+ pubkey);
+ }
+ else {
+ GError *te = NULL;
+
+ /* We have parsed the key, so try to check keys */
+ if (!rspamd_dkim_match_keys (pk, dkim_key, &te)) {
+ msg_warn_task ("public key for %s/%s does not match private key: %e",
+ domain, selector, te);
+ g_error_free (te);
+
+ /* TODO: add fatal failure possibility */
+ }
+ }
+ }
+
ctx = rspamd_create_dkim_sign_context (task, dkim_key,
DKIM_CANON_RELAXED, DKIM_CANON_RELAXED,
headers, sign_type, &err);