Exemplo n.º 1
0
sfsistat mlfi_envfrom(SMFICTX * ctx, char **argv)
{
	struct mlfiPriv *priv = GETCONTEXT(ctx);
	char *msgid;

	/* SMTP Authenticated. Skip DNS blacklist checks */
	if (smfi_getsymval(ctx, "{auth_type}") != NULL)
		return SMFIS_ACCEPT;

	/* store message ID */
	msgid = smfi_getsymval(ctx, "{i}");
	if (msgid != NULL) {
		priv->msgid = strdup(msgid);
		if (priv->msgid == NULL) {
			mlog(LOG_ERR, "%s: %s: Memory allocation failed",
			     priv->connectfrom, "mlfi_envfrom()");
			mlfi_cleanup(ctx);
			return SMFIS_TEMPFAIL;
		}
	}

	else
		priv->msgid = NULL;

	/* store sender's address */
	priv->envfrom = strdup(argv[0]);
	if (priv->envfrom == NULL) {
		mlog(LOG_ERR, "%s: %s: Memory allocation failed",
		     (priv->msgid != NULL)? priv->msgid : priv->connectfrom,
		     "mlfi_envfrom()");
		mlfi_cleanup(ctx);
		return SMFIS_TEMPFAIL;
	}

#if SMFI_VERSION > 3
	/* null-envelope sender address, defer DNS checks till mlfi_data() */
	if (strncmp(argv[0], "<>\0", 3) == 0) {
#ifdef DEBUG
		mlog(LOG_DEBUG,
		     "%s: Null-envelope sender address, deferring",
		     (priv->msgid != NULL)? priv->msgid : priv->connectfrom);
#endif
		priv->check = 1;
		return SMFIS_CONTINUE;
	}
#endif

	priv->check = 0;
	return mlfi_dnslcheck(ctx);
}
Exemplo n.º 2
0
static int
rememberIP(SMFICTX *ctx, const char *addr)
{
	int i;
	time_t now;
	struct ip *ip;

	if(smfi_getsymval(ctx, "i") == NULL) {
		syslog(LOG_WARNING, "Add define(`confMILTER_MACROS_ENVFROM', `i')dnl to sendmail.mc");
		return 0;
	}

	now = time((time_t *)0);

	for(i = 0, ip = ips; i < NIDS; i++, ip++)
		if((ip->ip[0] != '\0' && ((now - ip->time) < TIMEOUT)))
			if(ip->ctx == ctx) {
#ifdef	DEBUG
				printf("rememberIP %s->%s already known\n",
					ip->sendmailID, addr);
#endif
				ip->time = now;	/* "touch" to put off time-outs */
				return 1;
			}

#ifdef	DEBUG
	printf("rememberIP %s ID %s\n", addr, smfi_getsymval(ctx, "i"));
#endif

	for(i = 0, ip = ips; i < NIDS; i++, ip++)
		if((ip->ip[0] == '\0' || ((now - ip->time) > TIMEOUT))) {
			strcpy(ip->ip, addr);
			strcpy(ip->sendmailID, smfi_getsymval(ctx, "i"));
			ip->ctx = ctx;
#ifdef	DEBUG
			printf("rememberIP %s->%s\n", ip->sendmailID, addr);
#endif
			ip->time = now;
			break;
		}
	if(i == NIDS) {
		syslog(LOG_ERR, "blacklist_body: out of NIDS");

		timeout();
		return 0;
	}
	return 1;
}
Exemplo n.º 3
0
sfsistat clamfi_envfrom(SMFICTX *ctx, char **argv) {
    struct CLAMFI *cf;
    const char *login = smfi_getsymval(ctx, "{auth_authen}");

    if(login && smtpauthed(login)) {
        logg("*Skipping scan for authenticated user %s\n", login);
        return SMFIS_ACCEPT;
    }

    if(whitelisted(argv[0], 1)) {
        logg("*Skipping scan for %s (whitelisted from)\n", argv[0]);
        return SMFIS_ACCEPT;
    }

    if(!(cf = (struct CLAMFI *)malloc(sizeof(*cf)))) {
        logg("!Failed to allocate CLAMFI struct\n");
        return FailAction;
    }
    cf->totsz = 0;
    cf->bufsz = 0;
    cf->main = cf->alt = -1;
    cf->all_whitelisted = 1;
    cf->gotbody = 0;
    cf->msg_subj = cf->msg_date = cf->msg_id = NULL;
    if(addxvirus==1) {
        cf->scanned_count = 0;
        cf->status_count = 0;
    }
    smfi_setpriv(ctx, (void *)cf);

    return SMFIS_CONTINUE;
}
Exemplo n.º 4
0
sfsistat mlfi_data(SMFICTX * ctx)
{
	struct mlfiPriv *priv = GETCONTEXT(ctx);
	char *msgid;

	/* In Postfix, the Sendmail macro 'i' is only available in the DATA,
	   EOH, and EOM milter protocol stages so we try get the msgid again */
	if (priv->msgid != NULL)
		goto check;

	msgid = smfi_getsymval(ctx, "{i}");
	if (msgid != NULL) {
		priv->msgid = strdup(msgid);
		if (priv->msgid == NULL) {
			mlog(LOG_ERR, "%s: %s: Memory allocation failed",
			     priv->connectfrom, "mlfi_data()");
			mlfi_cleanup(ctx);
			return SMFIS_TEMPFAIL;
		}
	}

check:
	if (priv->check != 0)
		return mlfi_dnslcheck(ctx);

	/* continue processing */
	return SMFIS_CONTINUE;
}
Exemplo n.º 5
0
static int test_reply(SMFICTX *ctx, int code)
{
    const char **cpp;
    const char *symval;

    for (cpp = macro_names; *cpp; cpp++)
	if ((symval = smfi_getsymval(ctx, (char *) *cpp)) != 0)
	    printf("macro: %s=\"%s\"\n", *cpp, symval);
    (void) fflush(stdout);			/* In case output redirected. */

    if (code == SMFIR_REPLYCODE) {
	if (smfi_setmlreply(ctx, reply_code, reply_dsn, reply_message, reply_message, (char *) 0) == MI_FAILURE)
	    fprintf(stderr, "smfi_setmlreply failed\n");
	printf("test_reply %s\n", reply_code);
	return (reply_code[0] == '4' ? SMFIS_TEMPFAIL : SMFIS_REJECT);
    } else {
	printf("test_reply %d\n\n", code);
	return (code);
    }
}
Exemplo n.º 6
0
sfsistat clamfi_eom(SMFICTX *ctx) {
    struct CLAMFI *cf;
    char *reply;
    int len, ret;
    unsigned int crcpt;

    if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx)))
	return SMFIS_CONTINUE; /* whatever */

    if(!cf->totsz) {
	/* got no headers and no body */
	logg("*Not scanning an empty message\n");
	ret = CleanAction(ctx);
	nullify(ctx, cf, CF_NONE);
	free(cf);
	return ret;
    }

    if(cf->local) {
	lseek(cf->alt, 0, SEEK_SET);

	if(nc_sendmsg(cf->main, cf->alt) == -1) {
	    logg("!FD send failed\n");
	    nullify(ctx, cf, CF_ALT);
	    free(cf);
	    return FailAction;
	}
    } else {
	uint32_t sendmetoo = 0;
	cf->sendme = htonl(cf->bufsz);
	if((cf->bufsz && nc_send(cf->main, &cf->sendme, cf->bufsz + 4)) || nc_send(cf->main, &sendmetoo, 4))  {
	    logg("!Failed to flush STREAM\n");
	    nullify(ctx, cf, CF_NONE);
	    free(cf);
	    return FailAction;
	}
    }

    reply = nc_recv(cf->main);

    if(cf->local)
	close(cf->alt);

    cf->alt = -1;

    if(!reply) {
	logg("!No reply from clamd\n");
	nullify(ctx, cf, CF_NONE);
	free(cf);
	return FailAction;
    }

    len = strlen(reply);
    if(len>5 && !strcmp(reply + len - 5, ": OK\n")) {
	if(addxvirus) add_x_header(ctx, "Clean", cf->scanned_count, cf->status_count);
	if(loginfected & LOGCLN_FULL) {
	    const char *id = smfi_getsymval(ctx, "{i}");
	    const char *from = smfi_getsymval(ctx, "{mail_addr}");
	    const char *msg_subj = makesanehdr(cf->msg_subj);
	    const char *msg_date = makesanehdr(cf->msg_date);
	    const char *msg_id = makesanehdr(cf->msg_id);
	    if(multircpt && cf->nrecipients) {
		for(crcpt = 0; crcpt < cf->nrecipients; crcpt++)
		    logg("~Clean message %s from <%s> to <%s> with subject '%s' message-id '%s' date '%s'\n", id, from, cf->recipients[crcpt], msg_subj, msg_id, msg_date);
	    } else {
		const char *to = smfi_getsymval(ctx, "{rcpt_addr}");
		logg("~Clean message %s from <%s> to <%s> with subject '%s' message-id '%s' date '%s'\n", id, from, to ? to : HDR_UNAVAIL, msg_subj, msg_id, msg_date);
	    }
	} else if(loginfected & LOGCLN_BASIC) {
	    const char *from = smfi_getsymval(ctx, "{mail_addr}");
	    if(multircpt && cf->nrecipients) {
		for(crcpt = 0; crcpt < cf->nrecipients; crcpt++)
		    logg("~Clean message from <%s> to <%s>\n", from, cf->recipients[crcpt]);
	    } else {
		const char *to = smfi_getsymval(ctx, "{rcpt_addr}");
		logg("~Clean message from <%s> to <%s>\n", from, to ? to : HDR_UNAVAIL);
	    }
	}
	ret = CleanAction(ctx);
    } else if (len>7 && !strcmp(reply + len - 7, " FOUND\n")) {
	cf->virusname = NULL;
	if((loginfected & (LOGINF_BASIC | LOGINF_FULL)) || addxvirus || rejectfmt || viraction) {
	    char *vir;

	    reply[len-7] = '\0';
	    vir = strrchr(reply, ' ');
	    if(vir) {
		unsigned int have_multi = (multircpt != 0 && cf->nrecipients);
		unsigned int lst_rcpt = (have_multi * (cf->nrecipients - 1)) + 1;
		vir++;

		if(rejectfmt)
		    cf->virusname = vir;

		if(addxvirus) {
		    char msg[255];
		    snprintf(msg, sizeof(msg), "Infected (%s)", vir);
		    msg[sizeof(msg)-1] = '\0';
		    add_x_header(ctx, msg, cf->scanned_count, cf->status_count);
		}

		for(crcpt = 0; crcpt < lst_rcpt; crcpt++) {
		    if(loginfected || viraction) {
			const char *from = smfi_getsymval(ctx, "{mail_addr}");
			const char *to = have_multi ? cf->recipients[crcpt] : smfi_getsymval(ctx, "{rcpt_addr}");

			if(!from) from = HDR_UNAVAIL;
			if(!to) to = HDR_UNAVAIL;
			if((loginfected & LOGINF_FULL) || viraction) {
			    const char *id = smfi_getsymval(ctx, "{i}");
			    const char *msg_subj = makesanehdr(cf->msg_subj);
			    const char *msg_date = makesanehdr(cf->msg_date);
			    const char *msg_id = makesanehdr(cf->msg_id);

			    if(!id) id = HDR_UNAVAIL;
			
			    if(loginfected & LOGINF_FULL)
				logg("~Message %s from <%s> to <%s> with subject '%s' message-id '%s' date '%s' infected by %s\n", id, from, to, msg_subj, msg_id, msg_date, vir);

			    if(viraction) {
				char er[256];
				char *e_id = strdup(id);
				char *e_from = strdup(from);
				char *e_to = strdup(to);
				char *e_msg_subj = strdup(msg_subj);
				char *e_msg_date = strdup(msg_date);
				char *e_msg_id = strdup(msg_id);
				pid_t pid;

				logg("*VirusEvent: about to execute '%s' '%s' '%s' '%s' '%s' '%s' '%s' '%s'\n", viraction, vir, e_id, e_from, e_to, e_msg_subj, e_msg_id, e_msg_date);

				pthread_mutex_lock(&virusaction_lock);
				pid = fork();
				if(!pid) {
				    char * args[9]; /* avoid element is not computable at load time warns */
				    args[0]= viraction;
				    args[1] = vir;
				    args[2] = e_id;
				    args[3] = e_from;
				    args[4] = e_to;
				    args[5] = e_msg_subj;
				    args[6] = e_msg_id;
				    args[7] = e_msg_date;
				    args[8] = NULL;
				    exit(execvp(viraction, args));
				} else if(pid > 0) {
				    int wret;
				    pthread_mutex_unlock(&virusaction_lock);
				    while((wret = waitpid(pid, &ret, 0)) == -1 && errno == EINTR);
				    if(wret<0)
					logg("!VirusEvent: waitpid() failed: %s\n", cli_strerror(errno, er, sizeof(er)));
				    else {
					if(WIFEXITED(ret))
					    logg("*VirusEvent: child exited with code %d\n", WEXITSTATUS(ret));
					else if(WIFSIGNALED(ret))
					    logg("*VirusEvent: child killed by signal %d\n", WTERMSIG(ret));
					else
					    logg("*VirusEvent: child lost\n");
				    }
				} else {
				    logg("!VirusEvent: fork failed: %s\n", cli_strerror(errno, er, sizeof(er)));
				}
				free(e_id);
				free(e_from);
				free(e_to);
				free(e_msg_subj);
				free(e_msg_date);
				free(e_msg_id);
			    }
			}
			if(loginfected & LOGINF_BASIC)
			    logg("~Message from <%s> to <%s> infected by %s\n", from, to, vir);
		    }
		}
	    }
	}
	ret = InfectedAction(ctx);
    } else {
	logg("!Unknown reply from clamd\n");
	ret = FailAction;
    }

    nullify(ctx, cf, CF_MAIN);
    free(cf);
    free(reply);
    return ret;
}
Exemplo n.º 7
0
static sfsistat
cb_header(SMFICTX *ctx, char *name, char *value)
{
	struct context *context;

	if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
		msg(LOG_ERR, context, "cb_header: smfi_getpriv");
		return (SMFIS_ACCEPT);
	}
	msg(LOG_DEBUG, context, "cb_header('%s', '%s')", name, value);
	if (context->fd < 0) {
		const char *sendmail_name = smfi_getsymval(ctx, "j");
		const char *sendmail_queue = smfi_getsymval(ctx, "i");
		const char *sendmail_date = smfi_getsymval(ctx, "b");
		const char *auth_type = smfi_getsymval(ctx, "{auth_type}");
		const char *auth_ssf = smfi_getsymval(ctx, "{auth_ssf}");

		if ((context->fd = get_spamd_fd(context)) < 0)
			return (SMFIS_ACCEPT);
		fdprintf(context->fd, "SYMBOLS SPAMC/1.2\r\n");
		if (spamd_user[0])
			fdprintf(context->fd, "User: %s\r\n", spamd_user);
		fdprintf(context->fd, "\r\n");
		/* send fake Received: header */
		fdprintf(context->fd, "Received: from %s (%s [%s])",
		    context->helo, context->host, context->addr);
		if (auth_type != NULL && auth_type[0]) {
			fdprintf(context->fd, "\r\n\t(authenticated");
			if (auth_ssf != NULL && auth_ssf[0])
				fdprintf(context->fd, " bits=%s", auth_ssf);
			fdprintf(context->fd, ")");
		}
		if (sendmail_name != NULL && sendmail_name[0]) {
			fdprintf(context->fd, "\r\n\tby %s (milter-spamd)",
			    sendmail_name);
			if (sendmail_queue != NULL && sendmail_queue[0])
				fdprintf(context->fd, " id %s", sendmail_queue);
		}
		if (context->env_rcpt[0])
			fdprintf(context->fd, "\r\n\tfor %s", context->env_rcpt);
		if (sendmail_date != NULL && sendmail_date[0])
			fdprintf(context->fd, "; %s", sendmail_date);
		else {
			char d[128];
			time_t t = time(NULL);

			if (strftime(d, sizeof(d), "%a, %e %b %Y %H:%M:%S %z",
			    localtime(&t)))
				fdprintf(context->fd, "; %s", d);
		}
		fdprintf(context->fd, "\r\n");
	}
	fdprintf(context->fd, "%s: %s\r\n", name, value);
	if (!strcasecmp(name, "From"))
		strlcpy(context->hdr_from, value, sizeof(context->hdr_from));
	else if (!strcasecmp(name, "To"))
		strlcpy(context->hdr_to, value, sizeof(context->hdr_to));
	else if (!strcasecmp(name, "Subject"))
		strlcpy(context->hdr_subject, value,
		    sizeof(context->hdr_subject));
	return (SMFIS_CONTINUE);
}
Exemplo n.º 8
0
sfsistat clamfi_eom(SMFICTX *ctx) {
    struct CLAMFI *cf;
    char *reply;
    int len, ret;

    if(!(cf = (struct CLAMFI *)smfi_getpriv(ctx)))
        return SMFIS_CONTINUE; /* whatever */

    if(!cf->totsz) {
        /* got no headers and no body */
        logg("*Not scanning an empty message\n");
        ret = CleanAction(ctx);
        nullify(ctx, cf, CF_NONE);
        return ret;
    }

    if(cf->local) {
        if(nc_send(cf->main, "nFILDES\n", 8)) {
            logg("!FD scan request failed\n");
            nullify(ctx, cf, CF_ALT);
            return FailAction;
        }

        lseek(cf->alt, 0, SEEK_SET);

        if(nc_sendmsg(cf->main, cf->alt) == -1) {
            logg("!FD send failed\n");
            nullify(ctx, cf, CF_ALT);
            return FailAction;
        }
    } else {
        if(cf->bufsz && nc_send(cf->alt, cf->buffer, cf->bufsz)) {
            logg("!Failed to flush STREAM\n");
            nullify(ctx, cf, CF_MAIN);
            return FailAction;
        }
        close(cf->alt);
    }

    reply = nc_recv(cf->main);

    if(cf->local)
        close(cf->alt);

    cf->alt = -1;

    if(!reply) {
        logg("!No reply from clamd\n");
        nullify(ctx, cf, CF_NONE);
        return FailAction;
    }

    len = strlen(reply);
    if(len>5 && !strcmp(reply + len - 5, ": OK\n")) {
        if(addxvirus) add_x_header(ctx, "Clean", cf->scanned_count, cf->status_count);
        ret = CleanAction(ctx);
    } else if (len>7 && !strcmp(reply + len - 7, " FOUND\n")) {
        cf->virusname = NULL;
        if(loginfected || addxvirus || rejectfmt) {
            char *vir;

            reply[len-7] = '\0';
            vir = strrchr(reply, ' ');
            if(vir) {
                vir++;

                if(rejectfmt)
                    cf->virusname = vir;

                if(addxvirus) {
                    char msg[255];
                    snprintf(msg, sizeof(msg), "Infected (%s)", vir);
                    msg[sizeof(msg)-1] = '\0';
                    add_x_header(ctx, msg, cf->scanned_count, cf->status_count);
                }

                if(loginfected) {
                    const char *from = smfi_getsymval(ctx, "{mail_addr}");
                    const char *to = smfi_getsymval(ctx, "{rcpt_addr}");

                    if(!from) from = HDR_UNAVAIL;
                    if(!to) to = HDR_UNAVAIL;
                    if(loginfected == LOGINF_FULL) {
                        const char *id = smfi_getsymval(ctx, "{i}");
                        const char *msg_subj = makesanehdr(cf->msg_subj);
                        const char *msg_date = makesanehdr(cf->msg_date);
                        const char *msg_id = makesanehdr(cf->msg_id);

                        if(!id) id = HDR_UNAVAIL;
                        logg("~Message %s from <%s> to <%s> with subject '%s' message-id '%s' date '%s' infected by %s\n", id, from, to, msg_subj, msg_id, msg_date, vir);
                    } else logg("~Message from <%s> to <%s> infected by %s\n", from, to, vir);
                }
            }
        }
        ret = InfectedAction(ctx);
    } else {
        logg("!Unknown reply from clamd\n");
        ret = FailAction;
    }

    nullify(ctx, cf, CF_MAIN);

    free(reply);
    return ret;
}