/* Author: Catalin(ux aka Dino) BOIE 2005 Description: This program rejects mail to an address it it doesn't come from a specified class. Compilation: gcc -O2 -Wall -pedantic -ansi -ggdb3 rejint.c -o rejint -lmilter -lpthread Usage: ./rejint net_class_allowed list Examples: ./rejint 192.168. list1@domain.tld Notes: Don't run it as root! Link: Link: http://kernel.umbrella.ro/ */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include struct mlfiPriv { char *ip; char *ident; char *helo; char *mail_addr; }; #define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx)) static char *class = ""; static char *list = ""; sfsistat mlfi_cleanup(SMFICTX *, int); sfsistat mlfi_connect(ctx, hostname, hostaddr) SMFICTX *ctx; char *hostname; _SOCK_ADDR *hostaddr; { struct mlfiPriv *priv; char *ident; char ip[128], *r; struct sockaddr_in *in; /* allocate some private memory */ priv = malloc(sizeof *priv); if (priv == NULL) { /* can't accept this message right now */ return SMFIS_TEMPFAIL; } memset(priv, '\0', sizeof *priv); /* save the private data */ smfi_setpriv(ctx, priv); in = (struct sockaddr_in *) hostaddr; r = inet_ntop(in->sin_family, (void *)&in->sin_addr, ip, sizeof(ip)); if (r == NULL) { printf("Cannot inet_pton!\n"); strcpy(ip, "???"); } priv->ip = strdup(ip); ident = smfi_getsymval(ctx, "_"); if (ident == NULL) ident = "?"; priv->ident = strdup(ident); /* continue processing */ return SMFIS_CONTINUE; } sfsistat mlfi_helo(ctx, helohost) SMFICTX *ctx; char *helohost; { struct mlfiPriv *priv = MLFIPRIV; priv->helo = strdup(helohost ? helohost : "?"); return SMFIS_CONTINUE; } sfsistat mlfi_envfrom(ctx, argv) SMFICTX *ctx; char **argv; { struct mlfiPriv *priv = MLFIPRIV; char *mail_addr = smfi_getsymval(ctx, "{mail_addr}"); priv->mail_addr = strdup(mail_addr ? mail_addr : "?"); return SMFIS_CONTINUE; } sfsistat mlfi_envrcpt(ctx, argv) SMFICTX *ctx; char **argv; { struct mlfiPriv *priv = MLFIPRIV; char *rcpt_addr = smfi_getsymval(ctx, "{rcpt_addr}"); char *rcpt_mailer = smfi_getsymval(ctx, "{rcpt_mailer}"); int ok = 1; if (rcpt_addr == NULL) rcpt_addr = "?"; if (rcpt_mailer == NULL) rcpt_mailer = "?"; printf("ip=[%s] ident=[%s] helo=[%s] mail_addr=[%s] rcpt_addr=[%s] rcpt_mailer=[%s]: ", priv->ip, priv->ident, priv->helo, priv->mail_addr, rcpt_addr, rcpt_mailer); /* if we match the list and addresses are ok, permit */ if (strstr(rcpt_addr, list)) { ok = 0; if (strcmp(priv->ip, "127.0.0.1") == 0) ok = 1; if (strncmp(priv->ip, class, strlen(class)) == 0) ok = 1; } if (ok == 0) { printf("I will reject this!\n"); return SMFIS_REJECT; } printf("Accepted!\n"); /* continue processing */ return SMFIS_CONTINUE; } sfsistat mlfi_header(ctx, headerf, headerv) SMFICTX *ctx; char *headerf; unsigned char *headerv; { return mlfi_cleanup(ctx, 1); } sfsistat mlfi_eoh(ctx) SMFICTX *ctx; { return SMFIS_CONTINUE; } sfsistat mlfi_body(ctx, bodyp, bodylen) SMFICTX *ctx; unsigned char *bodyp; size_t bodylen; { return SMFIS_CONTINUE; } sfsistat mlfi_eom(ctx) SMFICTX *ctx; { int ok = 1; /* change recipients, if requested */ /* if (add != NULL) ok = (smfi_addrcpt(ctx, add) == MI_SUCCESS); */ return mlfi_cleanup(ctx, ok); } sfsistat mlfi_abort(ctx) SMFICTX *ctx; { return mlfi_cleanup(ctx, 0); } sfsistat mlfi_cleanup(ctx, ok) SMFICTX *ctx; int ok; { return SMFIS_CONTINUE; } sfsistat mlfi_close(ctx) SMFICTX *ctx; { struct mlfiPriv *priv = MLFIPRIV; if (priv == NULL) return SMFIS_CONTINUE; free(priv->ip); free(priv->ident); free(priv->helo); free(priv->mail_addr); free(priv); smfi_setpriv(ctx, NULL); return SMFIS_CONTINUE; } struct smfiDesc smfilter = { "RejInt", /* filter name */ SMFI_VERSION, /* version code -- do not change */ SMFIF_ADDHDRS, /* flags */ mlfi_connect, /* connection info filter */ mlfi_helo, /* SMTP HELO command filter */ mlfi_envfrom, /* envelope sender filter */ mlfi_envrcpt, /* envelope recipient filter */ mlfi_header, /* header filter */ mlfi_eoh, /* end of header */ mlfi_body, /* body block filter */ mlfi_eom, /* end of message */ mlfi_abort, /* message aborted */ mlfi_close, /* connection cleanup */ }; int main(int argc, char *argv[]) { char *path = "/var/run/rejint.sock"; if (argc < 3) { printf("Usage: %s class_allowed rcpt_match (ex: %s 192.168.1. lists-)\n", argv[0], argv[0]); return 1; } class = argv[1]; list = argv[2]; unlink(path); if (smfi_setconn(path) == MI_FAILURE) { printf("smfi_setconn failed\n"); return EX_SOFTWARE; } if (smfi_register(smfilter) == MI_FAILURE) { printf("smfi_register failed\n"); return EX_UNAVAILABLE; } printf("Waiting for connections on %s.\nAllow only from localhost and %s for string [%s]...\n", path, class, list); return smfi_main(); }