diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2007-10-01 23:50:32 +0200 |
---|---|---|
committer | Johannes Berg <johannes@sipsolutions.net> | 2007-10-01 23:50:32 +0200 |
commit | d96a64a0a3ab81eb1dd8c7ad91ef12f312894666 (patch) | |
tree | 66adfc9bcdaa8c9dbcc2d6475d3ee9261c21006b /crm114-exec.c | |
parent | af77b1801a2d6a34305e78232376039b0c8d85a6 (diff) | |
download | dovecot-antispam-d96a64a0a3ab81eb1dd8c7ad91ef12f312894666.tar.gz dovecot-antispam-d96a64a0a3ab81eb1dd8c7ad91ef12f312894666.tar.xz dovecot-antispam-d96a64a0a3ab81eb1dd8c7ad91ef12f312894666.zip |
add experimental crm114 backend
Diffstat (limited to 'crm114-exec.c')
-rw-r--r-- | crm114-exec.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/crm114-exec.c b/crm114-exec.c new file mode 100644 index 0000000..91a72e7 --- /dev/null +++ b/crm114-exec.c @@ -0,0 +1,200 @@ +/* + * crm114 backend for dovecot antispam plugin + * + * Copyright (C) 2004-2007 Johannes Berg <johannes@sipsolutions.net> + * 2006 Frank Cusack + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <unistd.h> +#include <stdlib.h> +#include <sys/wait.h> +#include <fcntl.h> + +#include "lib.h" +#include "mail-storage-private.h" + +#include "antispam-plugin.h" +#include "signature.h" + +static const char *reaver_binary = "/bin/false"; +static char **extra_args = NULL; +static int extra_args_num = 0; + +#define FIXED_ARGS_NUM 2 +#define CRM_HDR "X-CRM114-CacheID" + +static int call_reaver(const char *signature, enum classification wanted) +{ + pid_t pid; + const char *class_arg; + int pipes[2]; + + switch (wanted) { + case CLASS_NOTSPAM: + class_arg = "good"; + break; + case CLASS_SPAM: + class_arg = "spam"; + break; + } + + /* + * For reaver stdin, it wants to read a full message but + * really only needs the signature. + */ + pipe(pipes); + + pid = fork(); + if (pid < 0) + return -1; + + if (pid) { + int status; + + close(pipes[0]); + + /* + * Reaver wants the mail but only needs the cache ID + */ + write(pipes[1], CRM_HDR, strlen(CRM_HDR)); + write(pipes[1], ": ", 2); + write(pipes[1], signature, strlen(signature)); + write(pipes[1], "\r\n\r\n", 4); + close(pipes[1]); + + /* + * Wait for reaver + */ + waitpid(pid, &status, 0); + if (!WIFEXITED(status)) + return 1; + + return WEXITSTATUS(status); + } else { + int fd = open("/dev/null", O_RDONLY); + char **argv; + int sz = sizeof(char *) * (FIXED_ARGS_NUM + extra_args_num + 1); + int i; + + argv = i_malloc(sz); + memset(argv, 0, sz); + + close(0); + close(1); + close(2); + /* see above */ + close(pipes[1]); + + if (dup2(pipes[0], 0) != 2) + exit(1); + close(pipes[0]); + + if (dup2(fd, 1) != 0) + exit(1); + if (dup2(fd, 2) != 0) + exit(1); + close(fd); + + argv[0] = (char *)reaver_binary; + argv[1] = (char *)class_arg; + + debug("antispam: %s %s ...", reaver_binary, class_arg); + + for (i = 0; i < extra_args_num; i++) + argv[i + FIXED_ARGS_NUM] = (char *)extra_args[i]; + + execv(reaver_binary, argv); + /* fall through if reaver can't be found */ + exit(127); + /* not reached */ + return -1; + } +} + +struct antispam_transaction_context { + struct siglist *siglist; +}; + +struct antispam_transaction_context *backend_start(struct mailbox *box) +{ + struct antispam_transaction_context *ast; + + ast = i_new(struct antispam_transaction_context, 1); + ast->siglist = NULL; + return ast; +} + +void backend_rollback(struct antispam_transaction_context *ast) +{ + signature_list_free(&ast->siglist); + i_free(ast); +} + +int backend_commit(struct mailbox_transaction_context *ctx, + struct antispam_transaction_context *ast) +{ + struct siglist *item = ast->siglist; + int ret = 0; + + while (item) { + if (call_reaver(item->sig, item->wanted)) { + ret = -1; + mail_storage_set_error(ctx->box->storage, + "Failed to call reaver"); + break; + } + item = item->next; + } + + signature_list_free(&ast->siglist); + i_free(ast); + return ret; +} + +int backend_handle_mail(struct mailbox_transaction_context *t, + struct antispam_transaction_context *ast, + struct mail *mail, enum classification want) +{ + return signature_extract_to_list(t, mail, &ast->siglist, want); +} + +void backend_init(pool_t pool) +{ + char *tmp; + int i; + + tmp = getenv("ANTISPAM_CRM_BINARY"); + if (tmp) { + reaver_binary = tmp; + debug("antispam: reaver binary set to %s\n", tmp); + } + + tmp = getenv("ANTISPAM_CRM_ARGS"); + if (tmp) { + extra_args = p_strsplit(pool, tmp, ";"); + extra_args_num = str_array_length( + (const char *const *)extra_args); + for (i = 0; i < extra_args_num; i++) + debug("antispam: reaver extra arg %s\n", + extra_args[i]); + } + + signature_init(); +} + +void backend_exit(void) +{ +} |