Example #1
0
sfsistat clamfi_abort(SMFICTX *ctx) {
    struct CLAMFI *cf;

    if((cf = (struct CLAMFI *)smfi_getpriv(ctx)))
        nullify(ctx, cf, CF_ANY);
    return SMFIS_CONTINUE;
}
Example #2
0
File: bav.c Project: dpalic/openemm
	/*}}}*/
}	priv_t;
static char *
xfree (char *s) /*{{{*/
{
	if (s)
		free (s);
	return NULL;
}/*}}}*/
static bool_t
xcopy (char **buf, const char *str) /*{{{*/
{
	if (*buf)
		free (*buf);
	*buf = str ? strdup (str) : NULL;
	return (! str) || *buf ? true : false;
}/*}}}*/
static void
priv_clear (priv_t *p) /*{{{*/
{
	if (p) {
		p -> x_agn = 0;
		p -> from = xfree (p -> from);
		p -> receiver = charc_free_all (p -> receiver);
		p -> prev = NULL;
		p -> info = xfree (p -> info);
	}
}/*}}}*/
static priv_t *
priv_free (priv_t *p) /*{{{*/
{
	if (p) {
		priv_clear (p);
		if (p -> lg)
			log_free (p -> lg);
		if (p -> cfg)
			cfg_free (p -> cfg);
		free (p);
	}
	return NULL;
}/*}}}*/
static priv_t *
priv_alloc (void) /*{{{*/
{
	priv_t	*p;
	
	if (p = (priv_t *) malloc (sizeof (priv_t)))
		if (p -> cfg = cfg_alloc (cfgfile)) {
			p -> is_local = false;
			p -> x_agn = 0;
			p -> from = NULL;
			p -> receiver = NULL;
			p -> prev = NULL;
			p -> info = NULL;
			if (! (p -> lg = log_alloc (NULL, program, loglevel)))
				p = priv_free (p);
		} else {
			free (p);
			p = NULL;
		}
	return p;
}/*}}}*/
static bool_t
priv_setfrom (priv_t *p, const char *from) /*{{{*/
{
	return xcopy (& p -> from, from);
}/*}}}*/
static bool_t
priv_setto (priv_t *p, const char *to) /*{{{*/
{
	charc_t	*r;
	
	if (r = charc_alloc (to)) {
		if (p -> prev)
			p -> prev -> next = r;
		else
			p -> receiver = r;
		p -> prev = r;
	}
	return r ? true : false;
}/*}}}*/
static bool_t
priv_addinfo (priv_t *p, const char *info) /*{{{*/
{
	char	*temp;

	if ((! p -> info) || (! p -> info[0]))
		return xcopy (& p -> info, info);
	if (temp = malloc (strlen (p -> info) + strlen (info) + 2)) {
		sprintf (temp, "%s,%s", p -> info, info);
		free (p -> info);
		p -> info = temp;
		return true;
	}
	return false;
}/*}}}*/
static bool_t
priv_addinfopair (priv_t *p, const char *var, const char *val) /*{{{*/
{
	bool_t	rc;
	char	*scratch, *ptr;
	
	if (scratch = malloc (strlen (var) + strlen (val) + 2)) {
		for (ptr = scratch; *var; *ptr++ = *var++)
			;
		*ptr++ = '=';
		for (;*val; ++val)
			*ptr++ = *val == ',' ? '_' : *val;
		*ptr = '\0';
		rc = priv_addinfo (p, scratch);
		free (scratch);
	} else
		rc = false;
	return rc;
}/*}}}*/

static sfsistat
handle_connect (SMFICTX *ctx, char  *hostname, _SOCK_ADDR *hostaddr) /*{{{*/
{
	priv_t	*p;

	if (! (p = priv_alloc ()))
		return SMFIS_TEMPFAIL;
	if (hostaddr -> sa_family == AF_INET) {
		struct sockaddr_in	*iaddr = (struct sockaddr_in *) hostaddr;

		if (ntohl (iaddr -> sin_addr.s_addr) == INADDR_LOOPBACK)
			p -> is_local = true;
	}
# ifdef		AF_INET6
	else if (hostaddr -> sa_family == AF_INET6) {
		struct sockaddr_in6	*i6addr = (struct sockaddr_in6 *) hostaddr;
		static struct in6_addr	loopback = IN6ADDR_LOOPBACK_INIT;
		
		if (memcmp (& i6addr -> sin6_addr, & loopback, sizeof (i6addr -> sin6_addr)) == 0)
			p -> is_local = true;
	}
# endif		/* AF_INET6 */
	smfi_setpriv (ctx, p);
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_from (SMFICTX *ctx, char **argv) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	
	if (! p)
		return SMFIS_TEMPFAIL;
	priv_clear (p);
	if (! priv_setfrom (p, argv[0]))
		return SMFIS_TEMPFAIL;
	priv_addinfopair (p, "from", argv[0]);
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_to (SMFICTX *ctx, char **argv) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	char	*chk, *opt;
	bool_t	reject, tempfail;
	
	if (! p)
		return SMFIS_TEMPFAIL;
	if (p -> is_local)
		return SMFIS_CONTINUE;
	if (! (chk = cfg_valid_address (p -> cfg, argv[0]))) {
		log_out (p -> lg, LV_ERROR, "Unable to setup initial data for `%s'", argv[0]);
		return SMFIS_TEMPFAIL;
	}
	if (opt = strchr (chk, ':'))
		*opt++ = '\0';
	reject = false;
	tempfail = false;
	if (! strcmp (chk, ID_REJECT))
		reject = true;
	else if (! strcmp (chk, ID_TEMPFAIL))
		tempfail = true;
	else if ((! strcmp (chk, ID_ACCEPT)) && opt)
		priv_addinfo (p, opt);
	priv_addinfopair (p, "to", argv[0]);
	free (chk);
	if (reject) {
		log_out (p -> lg, LV_INFO, "Receiver `%s' is rejected", argv[0]);
		smfi_setreply (ctx, (char *) "550", (char *) "5.1.1", (char *) "No such user");
		return SMFIS_REJECT;
	}
	if (tempfail) {
		log_out (p -> lg, LV_INFO, "Receiver `%s' is temp. disbaled", argv[0]);
		smfi_setreply (ctx, (char *) "400", (char *) "4.0.0", (char *) "Please try again later");
		return SMFIS_TEMPFAIL;
	}
	if (! priv_setto (p, argv[0]))
		return SMFIS_TEMPFAIL;
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_header (SMFICTX *ctx, char *field, char *value) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);

	if (! p)
		return SMFIS_TEMPFAIL;
	if (p -> is_local)
		return SMFIS_CONTINUE;
	if (! strcasecmp (field, X_LOOP)) {
		log_out (p -> lg, LV_WARNING, "Mail from `%s' has already loop marker set, rejected", p -> from);
		smfi_setreply (ctx, (char *) "500", (char *) "5.4.6", (char *) "Loop detected");
		return SMFIS_REJECT;
	}
	if (! strcasecmp (field, X_AGN))
		p -> x_agn++;
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_eom (SMFICTX *ctx) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	int	n;
	
	if (! p)
		return SMFIS_TEMPFAIL;
	for (n = 0; n < p -> x_agn; ++n)
		smfi_chgheader (ctx, (char *) X_AGN, 0, NULL);
	if (! p -> is_local) {
		if (p -> info)
			smfi_addheader (ctx, (char *) X_AGN, p -> info);
		smfi_addheader (ctx, (char *) X_LOOP, (char *) LOOP_SET);
	}
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_close(SMFICTX *ctx) /*{{{*/
{
	priv_free (smfi_getpriv (ctx));
	smfi_setpriv (ctx, NULL);
	return SMFIS_CONTINUE;
}/*}}}*/
Example #3
0
static sfsistat
cb_body(SMFICTX *ctx, u_char *chunk, size_t size)
{
	struct context *context;

	if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
		msg(LOG_ERR, NULL, "cb_body: smfi_getpriv");
		return (SMFIS_ACCEPT);
	}
	for (; size > 0; size--, chunk++) {
		context->buf[context->pos] = *chunk;
		if (context->buf[context->pos] == '\n' ||
		    context->pos == sizeof(context->buf) - 1) {
			if (context->pos > 0 &&
			    context->buf[context->pos - 1] == '\r')
				context->buf[context->pos - 1] = 0;
			else
				context->buf[context->pos] = 0;
			context->pos = 0;
			msg(LOG_DEBUG, context, "cb_body('%s')", context->buf);
			if (context->fd >= 0 && context->lines < 1000) {
				fdprintf(context->fd, "%s\r\n", context->buf);
				context->lines++;
			}
		} else
			context->pos++;
	}
	return (SMFIS_CONTINUE);
}
Example #4
0
sfsistat clamfi_envrcpt(SMFICTX *ctx, char **argv) {
    struct CLAMFI *cf;

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

    if(cf->all_whitelisted)
	cf->all_whitelisted &= whitelisted(argv[0], 0);

    if(multircpt) {
	void *new_rcpt = realloc(cf->recipients, (cf->nrecipients + 1) * sizeof(*(cf->recipients)));
	unsigned int rcpt_cnt;
	if(!new_rcpt) {
	    logg("!Failed to allocate array for new recipient\n");
	    nullify(ctx, cf, CF_ANY);
	    free(cf);
	    return FailAction;
	}
	cf->recipients = new_rcpt;
	rcpt_cnt = cf->nrecipients++;
	if(!(cf->recipients[rcpt_cnt] = strdup(argv[0]))) {
	    logg("!Failed to allocate space for new recipient\n");
	    nullify(ctx, cf, CF_ANY);
	    free(cf);
	    return FailAction;
	}
    }

    return SMFIS_CONTINUE;
}
Example #5
0
sfsistat mlfi_abort(SMFICTX *ctx)
{
	struct nameserver	*mp = smfi_getpriv(ctx) ;
	int			status = SMFIS_CONTINUE ;

	// Do nothing here at this time...
	return(status) ;
}
Example #6
0
static sfsistat
cb_header(SMFICTX *ctx, char *name, char *value)
{
    struct context *context;
    const struct action *action;
    int salevel;

    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->sclvalue != -1) return (SMFIS_CONTINUE);

    if (!strcasecmp(name, "X-Spam-Level")) {
        salevel = strlen(value);

        switch (salevel) {
        case 0:
        case 1:
            context->sclvalue = 1;
            break;
        case 2:
            context->sclvalue = 2;
            break;
        case 3:
            context->sclvalue = 3;
            break;
        case 4:
            context->sclvalue = 4;
            break;
        case 5:
            context->sclvalue = 5;
            break;
        case 6:
            context->sclvalue = 6;
            break;
        case 7:
        case 8:
            context->sclvalue = 7;
            break;
        case 9:
        case 10:
            context->sclvalue = 8;
            break;
        default:
            if (salevel > 10) {
                context->sclvalue = 9;
            } else {
                msg(LOG_ERR, NULL, "cb_header: X-Spam-Level parsed %d",
                    salevel);
            }
            break;
        }
    }
    return (SMFIS_CONTINUE);
}
Example #7
0
sfsistat clamfi_envrcpt(SMFICTX *ctx, char **argv) {
    struct CLAMFI *cf;

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

    if(cf->all_whitelisted)
        cf->all_whitelisted &= whitelisted(argv[0], 0);
    return SMFIS_CONTINUE;
}
Example #8
0
sfsistat mlfi_close(SMFICTX *ctx)
{
	struct nameserver	*mp = smfi_getpriv(ctx) ;
	int			status = SMFIS_CONTINUE ;

	// We are done with the connection, so free up our context
	if(mp != NULL) {
		free(mp) ;
		smfi_setpriv(ctx, NULL) ;
	}
	return(status) ;
}
Example #9
0
static sfsistat action_reject_msg(SMFICTX *ctx) {
    struct CLAMFI *cf;
    char buf[1024];

    if(!rejectfmt || !(cf = (struct CLAMFI *)smfi_getpriv(ctx)))
	return SMFIS_REJECT;

    snprintf(buf, sizeof(buf), rejectfmt, cf->virusname);
    buf[sizeof(buf)-1] = '\0';
    smfi_setreply(ctx, "550", "5.7.1", buf);
    return SMFIS_REJECT;
}
Example #10
0
static sfsistat
cb_close(SMFICTX *ctx)
{
    struct context *context;

    context = (struct context *)smfi_getpriv(ctx);
    msg(LOG_DEBUG, context, "cb_close()");
    if (context != NULL) {
        smfi_setpriv(ctx, NULL);
        free(context);
    }
    return (SMFIS_CONTINUE);
}
Example #11
0
static sfsistat
cb_helo(SMFICTX *ctx, char *arg)
{
	struct context *context;

	if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
		msg(LOG_ERR, NULL, "cb_helo: smfi_getpriv");
		return (SMFIS_ACCEPT);
	}
	strlcpy(context->helo, arg, sizeof(context->helo));
	msg(LOG_DEBUG, context, "cb_helo('%s')", arg);
	return (SMFIS_CONTINUE);
}
Example #12
0
static sfsistat
cb_envfrom(SMFICTX *ctx, char **args)
{
	struct context *context;

	if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
		msg(LOG_ERR, NULL, "cb_envfrom: smfi_getpriv");
		return (SMFIS_ACCEPT);
	}
	if (*args != NULL)
		msg(LOG_DEBUG, context, "cb_envfrom('%s')", *args);
	return (SMFIS_CONTINUE);
}
Example #13
0
File: bav.c Project: dpalic/openemm
	/*}}}*/
}	priv_t;
static char *
xfree (char *s) /*{{{*/
{
	if (s)
		free (s);
	return NULL;
}/*}}}*/
static bool_t
xcopy (char **buf, const char *str) /*{{{*/
{
	if (*buf)
		free (*buf);
	*buf = str ? strdup (str) : NULL;
	return (! str) || *buf ? true : false;
}/*}}}*/
static void
priv_clear (priv_t *p) /*{{{*/
{
	if (p) {
		p -> x_agn = 0;
		p -> from = xfree (p -> from);
		p -> receiver = charc_free_all (p -> receiver);
		p -> prev = NULL;
		p -> info = xfree (p -> info);
	}
}/*}}}*/
static priv_t *
priv_free (priv_t *p) /*{{{*/
{
	if (p) {
		priv_clear (p);
		if (p -> lg)
			log_free (p -> lg);
		if (p -> cfg)
			cfg_free (p -> cfg);
		free (p);
	}
	return NULL;
}/*}}}*/
static priv_t *
priv_alloc (void) /*{{{*/
{
	priv_t	*p;
	
	if (p = (priv_t *) malloc (sizeof (priv_t)))
		if (p -> cfg = cfg_alloc (cfgfile)) {
			p -> is_local = false;
			p -> x_agn = 0;
			p -> from = NULL;
			p -> receiver = NULL;
			p -> prev = NULL;
			p -> info = NULL;
			if (! (p -> lg = log_alloc (NULL, program, loglevel)))
				p = priv_free (p);
		} else {
			free (p);
			p = NULL;
		}
	return p;
}/*}}}*/
static bool_t
priv_setfrom (priv_t *p, const char *from) /*{{{*/
{
	return xcopy (& p -> from, from);
}/*}}}*/
static bool_t
priv_setto (priv_t *p, const char *to) /*{{{*/
{
	charc_t	*r;
	
	if (r = charc_alloc (to)) {
		if (p -> prev)
			p -> prev -> next = r;
		else
			p -> receiver = r;
		p -> prev = r;
	}
	return r ? true : false;
}/*}}}*/
static bool_t
priv_addinfo (priv_t *p, const char *info) /*{{{*/
{
	char	*temp;

	if ((! p -> info) || (! p -> info[0]))
		return xcopy (& p -> info, info);
	if (temp = malloc (strlen (p -> info) + strlen (info) + 2)) {
		sprintf (temp, "%s,%s", p -> info, info);
		free (p -> info);
		p -> info = temp;
		return true;
	}
	return false;
}/*}}}*/
static bool_t
priv_addinfopair (priv_t *p, const char *var, const char *val) /*{{{*/
{
	bool_t	rc;
	char	*scratch, *ptr;
	
	if (scratch = malloc (strlen (var) + strlen (val) + 2)) {
		for (ptr = scratch; *var; *ptr++ = *var++)
			;
		*ptr++ = '=';
		for (;*val; ++val)
			*ptr++ = *val == ',' ? '_' : *val;
		*ptr = '\0';
		rc = priv_addinfo (p, scratch);
		free (scratch);
	} else
		rc = false;
	return rc;
}/*}}}*/

static sfsistat
handle_connect (SMFICTX *ctx, char  *hostname, _SOCK_ADDR *hostaddr) /*{{{*/
{
	priv_t	*p;

	if (! (p = priv_alloc ()))
		return SMFIS_TEMPFAIL;
	if (hostaddr -> sa_family == AF_INET) {
		struct sockaddr_in	*iaddr = (struct sockaddr_in *) hostaddr;

		if (ntohl (iaddr -> sin_addr.s_addr) == INADDR_LOOPBACK)
			p -> is_local = true;
	}
# ifdef		AF_INET6
	else if (hostaddr -> sa_family == AF_INET6) {
		struct sockaddr_in6	*i6addr = (struct sockaddr_in6 *) hostaddr;
		static struct in6_addr	loopback = IN6ADDR_LOOPBACK_INIT;
		
		if (memcmp (& i6addr -> sin6_addr, & loopback, sizeof (i6addr -> sin6_addr)) == 0)
			p -> is_local = true;
	}
# endif		/* AF_INET6 */
	smfi_setpriv (ctx, p);
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_from (SMFICTX *ctx, char **argv) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	
	if (! p)
		return SMFIS_TEMPFAIL;
	priv_clear (p);
	if (! priv_setfrom (p, argv[0]))
		return SMFIS_TEMPFAIL;
	priv_addinfopair (p, "from", argv[0]);
	return SMFIS_CONTINUE;
}/*}}}*/
Example #14
0
sfsistat clamfi_body(SMFICTX *ctx, unsigned char *bodyp, size_t len) {
    struct CLAMFI *cf;

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

    if(!cf->gotbody) {
        sfsistat ret = sendchunk(cf, (unsigned char *)"\r\n", 2, ctx);
        if(ret != SMFIS_CONTINUE)
            return ret;
        cf->gotbody = 1;
    }

    return sendchunk(cf, bodyp, len, ctx);
}
Example #15
0
static sfsistat
cb_envrcpt(SMFICTX *ctx, char **args)
{
	struct context *context;

	if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
		msg(LOG_ERR, NULL, "cb_envrcpt: smfi_getpriv");
		return (SMFIS_ACCEPT);
	}
	if (*args != NULL) {
		strlcpy(context->env_rcpt, *args, sizeof(context->env_rcpt));
		msg(LOG_DEBUG, context, "cb_envrcpt('%s')", *args);
	}
	return (SMFIS_CONTINUE);
}
Example #16
0
static sfsistat
cb_eoh(SMFICTX *ctx)
{
	struct context *context;

	if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
		msg(LOG_ERR, NULL, "cb_eoh: smfi_getpriv");
		return (SMFIS_ACCEPT);
	}
	msg(LOG_DEBUG, context, "cb_eoh()");
	if (context->fd >= 0)
		fdprintf(context->fd, "\r\n");
	memset(context->buf, 0, sizeof(context->buf));
	context->pos = 0;
	return (SMFIS_CONTINUE);
}
Example #17
0
sfsistat clamfi_header(SMFICTX *ctx, char *headerf, char *headerv) {
    struct CLAMFI *cf;
    sfsistat ret;

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

    if(!cf->totsz && cf->all_whitelisted) {
	logg("*Skipping scan (all destinations whitelisted)\n");
	nullify(ctx, cf, CF_NONE);
	free(cf);
	return SMFIS_ACCEPT;
    }

    if(!headerf) return SMFIS_CONTINUE; /* just in case */

    if((loginfected & (LOGINF_FULL | LOGCLN_FULL)) || viraction) {
	if(!cf->msg_subj && !strcasecmp(headerf, "Subject"))
	    cf->msg_subj = strdup(headerv ? headerv : "");
	if(!cf->msg_date && !strcasecmp(headerf, "Date"))
	    cf->msg_date = strdup(headerv ? headerv : "");
	if(!cf->msg_id && !strcasecmp(headerf, "Message-ID"))
	    cf->msg_id = strdup(headerv ? headerv : "");
    }

    if(addxvirus==1) {
	if(!strcasecmp(headerf, "X-Virus-Scanned")) cf->scanned_count++;
	if(!strcasecmp(headerf, "X-Virus-Status")) cf->status_count++;
    }

    if((ret = sendchunk(cf, (unsigned char *)headerf, strlen(headerf), ctx)) != SMFIS_CONTINUE) {
        free(cf);
        return ret;
    }
    if((ret = sendchunk(cf, (unsigned char *)": ", 2, ctx)) != SMFIS_CONTINUE) {
        free(cf);
        return ret;
    }
    if(headerv && (ret = sendchunk(cf, (unsigned char *)headerv, strlen(headerv), ctx)) != SMFIS_CONTINUE) {
        free(cf);
        return ret;
    }
    ret = sendchunk(cf, (unsigned char *)"\r\n", 2, ctx);
    if(ret != SMFIS_CONTINUE)
        free(cf);
    return ret;
}
Example #18
0
static sfsistat
cb_eoh(SMFICTX *ctx)
{
    struct context *context;

    if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
        msg(LOG_ERR, NULL, "cb_eoh: smfi_getpriv");
        return (SMFIS_ACCEPT);
    }
    msg(LOG_DEBUG, context, "cb_eoh()");

    if (context->sclvalue == -1) {
        context->sclvalue = 0;
    }

    return (SMFIS_CONTINUE);
}
Example #19
0
static sfsistat
cb_envrcpt(SMFICTX *ctx, char **args)
{
    struct context *context;

    if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
        msg(LOG_ERR, NULL, "cb_envrcpt: smfi_getpriv");
        return (SMFIS_ACCEPT);
    }
    if (*args != NULL) {
        msg(LOG_DEBUG, context, "cb_envrcpt('%s')", *args);
        if (!strcasecmp(args[0], "*****@*****.**")) {
            context->sclvalue = 0;
        }
    }
    return (SMFIS_CONTINUE);
}
Example #20
0
sfsistat mlfi_helo(SMFICTX *ctx, char *helohost)
{
	char			*p ;
	int			status = SMFIS_CONTINUE ;
	struct nameserver	*mp = smfi_getpriv(ctx) ;

	// Note that we test for HELO being 'ylmf-pc', since this has 
	// been seen in a lot of places trying to brute-force accounts on
	// SMTP servers.  If found, we force reject on the reset of the 
	// connection.
	strncpy(mp->helo, helohost, sizeof(mp->helo)-1) ;
	if(strcmp(mp->helo, "ylmf-pc") == 0) {
		syslog(LOG_INFO, "Reject ylmf-pc: Host=%s", mp->host) ;
		status = SMFIS_REJECT ;
	}
	return(status) ;
}
Example #21
0
File: bav.c Project: dpalic/openemm
	/*}}}*/
}	priv_t;
static char *
xfree (char *s) /*{{{*/
{
	if (s)
		free (s);
	return NULL;
}/*}}}*/
static bool_t
xcopy (char **buf, const char *str) /*{{{*/
{
	if (*buf)
		free (*buf);
	*buf = str ? strdup (str) : NULL;
	return (! str) || *buf ? true : false;
}/*}}}*/
static void
priv_clear (priv_t *p) /*{{{*/
{
	if (p) {
		p -> x_agn = 0;
		p -> from = xfree (p -> from);
		p -> receiver = charc_free_all (p -> receiver);
		p -> prev = NULL;
		p -> info = xfree (p -> info);
	}
}/*}}}*/
static priv_t *
priv_free (priv_t *p) /*{{{*/
{
	if (p) {
		priv_clear (p);
		if (p -> lg)
			log_free (p -> lg);
		if (p -> cfg)
			cfg_free (p -> cfg);
		free (p);
	}
	return NULL;
}/*}}}*/
static priv_t *
priv_alloc (void) /*{{{*/
{
	priv_t	*p;
	
	if (p = (priv_t *) malloc (sizeof (priv_t)))
		if (p -> cfg = cfg_alloc (cfgfile)) {
			p -> is_local = false;
			p -> x_agn = 0;
			p -> from = NULL;
			p -> receiver = NULL;
			p -> prev = NULL;
			p -> info = NULL;
			if (! (p -> lg = log_alloc (NULL, program, loglevel)))
				p = priv_free (p);
		} else {
			free (p);
			p = NULL;
		}
	return p;
}/*}}}*/
static bool_t
priv_setfrom (priv_t *p, const char *from) /*{{{*/
{
	return xcopy (& p -> from, from);
}/*}}}*/
static bool_t
priv_setto (priv_t *p, const char *to) /*{{{*/
{
	charc_t	*r;
	
	if (r = charc_alloc (to)) {
		if (p -> prev)
			p -> prev -> next = r;
		else
			p -> receiver = r;
		p -> prev = r;
	}
	return r ? true : false;
}/*}}}*/
static bool_t
priv_addinfo (priv_t *p, const char *info) /*{{{*/
{
	char	*temp;

	if ((! p -> info) || (! p -> info[0]))
		return xcopy (& p -> info, info);
	if (temp = malloc (strlen (p -> info) + strlen (info) + 2)) {
		sprintf (temp, "%s,%s", p -> info, info);
		free (p -> info);
		p -> info = temp;
		return true;
	}
	return false;
}/*}}}*/
static bool_t
priv_addinfopair (priv_t *p, const char *var, const char *val) /*{{{*/
{
	bool_t	rc;
	char	*scratch, *ptr;
	
	if (scratch = malloc (strlen (var) + strlen (val) + 2)) {
		for (ptr = scratch; *var; *ptr++ = *var++)
			;
		*ptr++ = '=';
		for (;*val; ++val)
			*ptr++ = *val == ',' ? '_' : *val;
		*ptr = '\0';
		rc = priv_addinfo (p, scratch);
		free (scratch);
	} else
		rc = false;
	return rc;
}/*}}}*/

static sfsistat
handle_connect (SMFICTX *ctx, char  *hostname, _SOCK_ADDR *hostaddr) /*{{{*/
{
	priv_t	*p;

	if (! (p = priv_alloc ()))
		return SMFIS_TEMPFAIL;
	if (hostaddr -> sa_family == AF_INET) {
		struct sockaddr_in	*iaddr = (struct sockaddr_in *) hostaddr;

		if (ntohl (iaddr -> sin_addr.s_addr) == INADDR_LOOPBACK)
			p -> is_local = true;
	}
# ifdef		AF_INET6
	else if (hostaddr -> sa_family == AF_INET6) {
		struct sockaddr_in6	*i6addr = (struct sockaddr_in6 *) hostaddr;
		static struct in6_addr	loopback = IN6ADDR_LOOPBACK_INIT;
		
		if (memcmp (& i6addr -> sin6_addr, & loopback, sizeof (i6addr -> sin6_addr)) == 0)
			p -> is_local = true;
	}
# endif		/* AF_INET6 */
	smfi_setpriv (ctx, p);
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_from (SMFICTX *ctx, char **argv) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	
	if (! p)
		return SMFIS_TEMPFAIL;
	priv_clear (p);
	if (! priv_setfrom (p, argv[0]))
		return SMFIS_TEMPFAIL;
	priv_addinfopair (p, "from", argv[0]);
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_to (SMFICTX *ctx, char **argv) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	char	*chk, *opt;
	bool_t	reject, tempfail;
	
	if (! p)
		return SMFIS_TEMPFAIL;
	if (p -> is_local)
		return SMFIS_CONTINUE;
	if (! (chk = cfg_valid_address (p -> cfg, argv[0]))) {
		log_out (p -> lg, LV_ERROR, "Unable to setup initial data for `%s'", argv[0]);
		return SMFIS_TEMPFAIL;
	}
	if (opt = strchr (chk, ':'))
		*opt++ = '\0';
	reject = false;
	tempfail = false;
	if (! strcmp (chk, ID_REJECT))
		reject = true;
	else if (! strcmp (chk, ID_TEMPFAIL))
		tempfail = true;
	else if ((! strcmp (chk, ID_ACCEPT)) && opt)
		priv_addinfo (p, opt);
	priv_addinfopair (p, "to", argv[0]);
	free (chk);
	if (reject) {
		log_out (p -> lg, LV_INFO, "Receiver `%s' is rejected", argv[0]);
		smfi_setreply (ctx, (char *) "550", (char *) "5.1.1", (char *) "No such user");
		return SMFIS_REJECT;
	}
	if (tempfail) {
		log_out (p -> lg, LV_INFO, "Receiver `%s' is temp. disbaled", argv[0]);
		smfi_setreply (ctx, (char *) "400", (char *) "4.0.0", (char *) "Please try again later");
		return SMFIS_TEMPFAIL;
	}
	if (! priv_setto (p, argv[0]))
		return SMFIS_TEMPFAIL;
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_header (SMFICTX *ctx, char *field, char *value) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);

	if (! p)
		return SMFIS_TEMPFAIL;
	if (p -> is_local)
		return SMFIS_CONTINUE;
	if (! strcasecmp (field, X_LOOP)) {
		log_out (p -> lg, LV_WARNING, "Mail from `%s' has already loop marker set, rejected", p -> from);
		smfi_setreply (ctx, (char *) "500", (char *) "5.4.6", (char *) "Loop detected");
		return SMFIS_REJECT;
	}
	if (! strcasecmp (field, X_AGN))
		p -> x_agn++;
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_eom (SMFICTX *ctx) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	int	n;
	
	if (! p)
		return SMFIS_TEMPFAIL;
	for (n = 0; n < p -> x_agn; ++n)
		smfi_chgheader (ctx, (char *) X_AGN, 0, NULL);
	if (! p -> is_local) {
		if (p -> info)
			smfi_addheader (ctx, (char *) X_AGN, p -> info);
		smfi_addheader (ctx, (char *) X_LOOP, (char *) LOOP_SET);
	}
	return SMFIS_CONTINUE;
}/*}}}*/
Example #22
0
File: bav.c Project: dpalic/openemm
	/*}}}*/
}	priv_t;
static char *
xfree (char *s) /*{{{*/
{
	if (s)
		free (s);
	return NULL;
}/*}}}*/
static bool_t
xcopy (char **buf, const char *str) /*{{{*/
{
	if (*buf)
		free (*buf);
	*buf = str ? strdup (str) : NULL;
	return (! str) || *buf ? true : false;
}/*}}}*/
static void
priv_clear (priv_t *p) /*{{{*/
{
	if (p) {
		p -> x_agn = 0;
		p -> from = xfree (p -> from);
		p -> receiver = charc_free_all (p -> receiver);
		p -> prev = NULL;
		p -> info = xfree (p -> info);
	}
}/*}}}*/
static priv_t *
priv_free (priv_t *p) /*{{{*/
{
	if (p) {
		priv_clear (p);
		if (p -> lg)
			log_free (p -> lg);
		if (p -> cfg)
			cfg_free (p -> cfg);
		free (p);
	}
	return NULL;
}/*}}}*/
static priv_t *
priv_alloc (void) /*{{{*/
{
	priv_t	*p;
	
	if (p = (priv_t *) malloc (sizeof (priv_t)))
		if (p -> cfg = cfg_alloc (cfgfile)) {
			p -> is_local = false;
			p -> x_agn = 0;
			p -> from = NULL;
			p -> receiver = NULL;
			p -> prev = NULL;
			p -> info = NULL;
			if (! (p -> lg = log_alloc (NULL, program, loglevel)))
				p = priv_free (p);
		} else {
			free (p);
			p = NULL;
		}
	return p;
}/*}}}*/
static bool_t
priv_setfrom (priv_t *p, const char *from) /*{{{*/
{
	return xcopy (& p -> from, from);
}/*}}}*/
static bool_t
priv_setto (priv_t *p, const char *to) /*{{{*/
{
	charc_t	*r;
	
	if (r = charc_alloc (to)) {
		if (p -> prev)
			p -> prev -> next = r;
		else
			p -> receiver = r;
		p -> prev = r;
	}
	return r ? true : false;
}/*}}}*/
static bool_t
priv_addinfo (priv_t *p, const char *info) /*{{{*/
{
	char	*temp;

	if ((! p -> info) || (! p -> info[0]))
		return xcopy (& p -> info, info);
	if (temp = malloc (strlen (p -> info) + strlen (info) + 2)) {
		sprintf (temp, "%s,%s", p -> info, info);
		free (p -> info);
		p -> info = temp;
		return true;
	}
	return false;
}/*}}}*/
static bool_t
priv_addinfopair (priv_t *p, const char *var, const char *val) /*{{{*/
{
	bool_t	rc;
	char	*scratch, *ptr;
	
	if (scratch = malloc (strlen (var) + strlen (val) + 2)) {
		for (ptr = scratch; *var; *ptr++ = *var++)
			;
		*ptr++ = '=';
		for (;*val; ++val)
			*ptr++ = *val == ',' ? '_' : *val;
		*ptr = '\0';
		rc = priv_addinfo (p, scratch);
		free (scratch);
	} else
		rc = false;
	return rc;
}/*}}}*/

static sfsistat
handle_connect (SMFICTX *ctx, char  *hostname, _SOCK_ADDR *hostaddr) /*{{{*/
{
	priv_t	*p;

	if (! (p = priv_alloc ()))
		return SMFIS_TEMPFAIL;
	if (hostaddr -> sa_family == AF_INET) {
		struct sockaddr_in	*iaddr = (struct sockaddr_in *) hostaddr;

		if (ntohl (iaddr -> sin_addr.s_addr) == INADDR_LOOPBACK)
			p -> is_local = true;
	}
# ifdef		AF_INET6
	else if (hostaddr -> sa_family == AF_INET6) {
		struct sockaddr_in6	*i6addr = (struct sockaddr_in6 *) hostaddr;
		static struct in6_addr	loopback = IN6ADDR_LOOPBACK_INIT;
		
		if (memcmp (& i6addr -> sin6_addr, & loopback, sizeof (i6addr -> sin6_addr)) == 0)
			p -> is_local = true;
	}
# endif		/* AF_INET6 */
	smfi_setpriv (ctx, p);
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_from (SMFICTX *ctx, char **argv) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	
	if (! p)
		return SMFIS_TEMPFAIL;
	priv_clear (p);
	if (! priv_setfrom (p, argv[0]))
		return SMFIS_TEMPFAIL;
	priv_addinfopair (p, "from", argv[0]);
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_to (SMFICTX *ctx, char **argv) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	char	*chk, *opt;
	bool_t	reject, tempfail;
	
	if (! p)
		return SMFIS_TEMPFAIL;
	if (p -> is_local)
		return SMFIS_CONTINUE;
	if (! (chk = cfg_valid_address (p -> cfg, argv[0]))) {
		log_out (p -> lg, LV_ERROR, "Unable to setup initial data for `%s'", argv[0]);
		return SMFIS_TEMPFAIL;
	}
	if (opt = strchr (chk, ':'))
		*opt++ = '\0';
	reject = false;
	tempfail = false;
	if (! strcmp (chk, ID_REJECT))
		reject = true;
	else if (! strcmp (chk, ID_TEMPFAIL))
		tempfail = true;
	else if ((! strcmp (chk, ID_ACCEPT)) && opt)
		priv_addinfo (p, opt);
	priv_addinfopair (p, "to", argv[0]);
	free (chk);
	if (reject) {
		log_out (p -> lg, LV_INFO, "Receiver `%s' is rejected", argv[0]);
		smfi_setreply (ctx, (char *) "550", (char *) "5.1.1", (char *) "No such user");
		return SMFIS_REJECT;
	}
	if (tempfail) {
		log_out (p -> lg, LV_INFO, "Receiver `%s' is temp. disbaled", argv[0]);
		smfi_setreply (ctx, (char *) "400", (char *) "4.0.0", (char *) "Please try again later");
		return SMFIS_TEMPFAIL;
	}
	if (! priv_setto (p, argv[0]))
		return SMFIS_TEMPFAIL;
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_header (SMFICTX *ctx, char *field, char *value) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);

	if (! p)
		return SMFIS_TEMPFAIL;
	if (p -> is_local)
		return SMFIS_CONTINUE;
	if (! strcasecmp (field, X_LOOP)) {
		log_out (p -> lg, LV_WARNING, "Mail from `%s' has already loop marker set, rejected", p -> from);
		smfi_setreply (ctx, (char *) "500", (char *) "5.4.6", (char *) "Loop detected");
		return SMFIS_REJECT;
	}
	if (! strcasecmp (field, X_AGN))
		p -> x_agn++;
	return SMFIS_CONTINUE;
}/*}}}*/
Example #23
0
static sfsistat
blacklist_cleanup(SMFICTX *ctx)
{
	struct privdata *p = smfi_getpriv(ctx);

	if(p) {
		int i;

		for(i = 0; i < NIDS; i++)
			if(ips[i].ctx == ctx) {
				ips[i].ip[0] = ips[i].sendmailID[0] = '\0';
				ips[i].ctx = NULL;
				break;
			}
		free(p);
		smfi_setpriv(ctx, NULL);
	}
	return SMFIS_CONTINUE;
}
Example #24
0
static sfsistat
cb_eom(SMFICTX *ctx)
{
    struct context *context;
    char sclstr[16];

    if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
        msg(LOG_ERR, NULL, "cb_eom: smfi_getpriv");
        return (SMFIS_ACCEPT);
    }
    msg(LOG_DEBUG, context, "cb_eom()");

    if (context->sclvalue != -1) {
        snprintf(sclstr, 16, "%d", context->sclvalue);
        if (smfi_addheader(ctx, "X-MS-Exchange-Organization-SCL", sclstr) != MI_SUCCESS)
            msg(LOG_ERR, context, "cb_eom: smfi_addheader");
    }
    return (SMFIS_ACCEPT);
}
Example #25
0
static sfsistat
cb_abort(SMFICTX *ctx)
{
	struct context *context;

	if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
		msg(LOG_ERR, NULL, "cb_abort: smfi_getpriv");
		return (SMFIS_ACCEPT);
	}
	msg(LOG_DEBUG, context, "cb_abort()");
	if (context->fd >= 0) {
		close(context->fd);
		context->fd = -1;
	}
	context->pos = context->hdr_from[0] = context->hdr_to[0] =
	    context->hdr_subject[0] = context->state = context->spam =
	    context->symbols[0] = 0;
	context->score = context->threshold = 0.0;
	return (SMFIS_CONTINUE);
}
Example #26
0
File: bav.c Project: dpalic/openemm
	/*}}}*/
}	priv_t;
static char *
xfree (char *s) /*{{{*/
{
	if (s)
		free (s);
	return NULL;
}/*}}}*/
static bool_t
xcopy (char **buf, const char *str) /*{{{*/
{
	if (*buf)
		free (*buf);
	*buf = str ? strdup (str) : NULL;
	return (! str) || *buf ? true : false;
}/*}}}*/
static void
priv_clear (priv_t *p) /*{{{*/
{
	if (p) {
		p -> x_agn = 0;
		p -> from = xfree (p -> from);
		p -> receiver = charc_free_all (p -> receiver);
		p -> prev = NULL;
		p -> info = xfree (p -> info);
	}
}/*}}}*/
static priv_t *
priv_free (priv_t *p) /*{{{*/
{
	if (p) {
		priv_clear (p);
		if (p -> lg)
			log_free (p -> lg);
		if (p -> cfg)
			cfg_free (p -> cfg);
		free (p);
	}
	return NULL;
}/*}}}*/
static priv_t *
priv_alloc (void) /*{{{*/
{
	priv_t	*p;
	
	if (p = (priv_t *) malloc (sizeof (priv_t)))
		if (p -> cfg = cfg_alloc (cfgfile)) {
			p -> is_local = false;
			p -> x_agn = 0;
			p -> from = NULL;
			p -> receiver = NULL;
			p -> prev = NULL;
			p -> info = NULL;
			if (! (p -> lg = log_alloc (NULL, program, loglevel)))
				p = priv_free (p);
		} else {
			free (p);
			p = NULL;
		}
	return p;
}/*}}}*/
static bool_t
priv_setfrom (priv_t *p, const char *from) /*{{{*/
{
	return xcopy (& p -> from, from);
}/*}}}*/
static bool_t
priv_setto (priv_t *p, const char *to) /*{{{*/
{
	charc_t	*r;
	
	if (r = charc_alloc (to)) {
		if (p -> prev)
			p -> prev -> next = r;
		else
			p -> receiver = r;
		p -> prev = r;
	}
	return r ? true : false;
}/*}}}*/
static bool_t
priv_addinfo (priv_t *p, const char *info) /*{{{*/
{
	char	*temp;

	if ((! p -> info) || (! p -> info[0]))
		return xcopy (& p -> info, info);
	if (temp = malloc (strlen (p -> info) + strlen (info) + 2)) {
		sprintf (temp, "%s,%s", p -> info, info);
		free (p -> info);
		p -> info = temp;
		return true;
	}
	return false;
}/*}}}*/
static bool_t
priv_addinfopair (priv_t *p, const char *var, const char *val) /*{{{*/
{
	bool_t	rc;
	char	*scratch, *ptr;
	
	if (scratch = malloc (strlen (var) + strlen (val) + 2)) {
		for (ptr = scratch; *var; *ptr++ = *var++)
			;
		*ptr++ = '=';
		for (;*val; ++val)
			*ptr++ = *val == ',' ? '_' : *val;
		*ptr = '\0';
		rc = priv_addinfo (p, scratch);
		free (scratch);
	} else
		rc = false;
	return rc;
}/*}}}*/

static sfsistat
handle_connect (SMFICTX *ctx, char  *hostname, _SOCK_ADDR *hostaddr) /*{{{*/
{
	priv_t	*p;

	if (! (p = priv_alloc ()))
		return SMFIS_TEMPFAIL;
	if (hostaddr -> sa_family == AF_INET) {
		struct sockaddr_in	*iaddr = (struct sockaddr_in *) hostaddr;

		if (ntohl (iaddr -> sin_addr.s_addr) == INADDR_LOOPBACK)
			p -> is_local = true;
	}
# ifdef		AF_INET6
	else if (hostaddr -> sa_family == AF_INET6) {
		struct sockaddr_in6	*i6addr = (struct sockaddr_in6 *) hostaddr;
		static struct in6_addr	loopback = IN6ADDR_LOOPBACK_INIT;
		
		if (memcmp (& i6addr -> sin6_addr, & loopback, sizeof (i6addr -> sin6_addr)) == 0)
			p -> is_local = true;
	}
# endif		/* AF_INET6 */
	smfi_setpriv (ctx, p);
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_from (SMFICTX *ctx, char **argv) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	
	if (! p)
		return SMFIS_TEMPFAIL;
	priv_clear (p);
	if (! priv_setfrom (p, argv[0]))
		return SMFIS_TEMPFAIL;
	priv_addinfopair (p, "from", argv[0]);
	return SMFIS_CONTINUE;
}/*}}}*/
static sfsistat
handle_to (SMFICTX *ctx, char **argv) /*{{{*/
{
	priv_t	*p = (priv_t *) smfi_getpriv (ctx);
	char	*chk, *opt;
	bool_t	reject, tempfail;
	
	if (! p)
		return SMFIS_TEMPFAIL;
	if (p -> is_local)
		return SMFIS_CONTINUE;
	if (! (chk = cfg_valid_address (p -> cfg, argv[0]))) {
		log_out (p -> lg, LV_ERROR, "Unable to setup initial data for `%s'", argv[0]);
		return SMFIS_TEMPFAIL;
	}
	if (opt = strchr (chk, ':'))
		*opt++ = '\0';
	reject = false;
	tempfail = false;
	if (! strcmp (chk, ID_REJECT))
		reject = true;
	else if (! strcmp (chk, ID_TEMPFAIL))
		tempfail = true;
	else if ((! strcmp (chk, ID_ACCEPT)) && opt)
		priv_addinfo (p, opt);
	priv_addinfopair (p, "to", argv[0]);
	free (chk);
	if (reject) {
		log_out (p -> lg, LV_INFO, "Receiver `%s' is rejected", argv[0]);
		smfi_setreply (ctx, (char *) "550", (char *) "5.1.1", (char *) "No such user");
		return SMFIS_REJECT;
	}
	if (tempfail) {
		log_out (p -> lg, LV_INFO, "Receiver `%s' is temp. disbaled", argv[0]);
		smfi_setreply (ctx, (char *) "400", (char *) "4.0.0", (char *) "Please try again later");
		return SMFIS_TEMPFAIL;
	}
	if (! priv_setto (p, argv[0]))
		return SMFIS_TEMPFAIL;
	return SMFIS_CONTINUE;
}/*}}}*/
Example #27
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;
}
Example #28
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);
}
Example #29
0
static sfsistat
blacklist_body(SMFICTX *ctx, u_char *bodyp, size_t len)
{
	char *string = malloc(len + 1);
	int rc, i;
	struct privdata *privdata;
	time_t now;
	struct bip *bip;

	if(string == NULL)
		return SMFIS_CONTINUE;

	if(len == 0) {	/* unlikely */
		free(string);
		return SMFIS_CONTINUE;
	}

	memcpy(string, bodyp, len);
	string[len] = '\0';

	if(strstr(string, "One or more viruses were detected in the message") ||
	   strstr(string, "This message contains malware or a virus ") ||
	   strstr(string, "Virus Warning Message") ||
	   strstr(string, "infected with the W32/Netsky.p@MM virus and was not successfully cleaned.") ||
	   strstr(string, " contains virus W32.Email.W.NetSky.Q. Action: Deleted") ||
	   strstr(string, "Our firewall determined the e-mails containing worm copies are being sent from your computer.") ||
	   strstr(string, "The message has been blocked because it contains a component") ||
	   strstr(string, "virus(es) in your email to the following recipient(s):") ||
	   strstr(string, "An attachment in that mail was of a file type that the Spam Firewall is set to block.") ||
	   strstr(string, "Mail-Header, Mail-Body and Error Description are attached") ||
	   strstr(string, "The following email message was blocked by MailMarshal:") ||
	   strstr(string, "Il sistema antivirus ha rilevato una infezione nel messaggio:-") ||
	   strstr(string, "The original message content contained a virus or was blocked") ||
	   strstr(string, "Found virus WORM_MYDOOM.M in file ") ||
	   strstr(string, "Alerta! Posible Virus Detectado ") ||
	   strstr(string, "The following email message was blocked by ") ||
	   strstr(string, "Unrepairable Virus Detected. Your mail has not been sent.") ||
	   strstr(string, "ANTIVIRUS SYSTEM FOUND VIRUSES") ||
	   strstr(string, "An e-mail sent by you has been blocked by our automated software") ||
	   strstr(string, "Please check your system for viruses") ||
	   strstr(string, "foi rejeitado por conter virus") ||
	   strstr(string, "This is a message from the MailScanner E-Mail Virus Protection Service") ||
	   strstr(string, "was blocked by our Spam Firewall. The email you sent with the following subject ") ||
	   strstr(string, "Certain attachments are not allowed for security reasons.Your message has been rejected.")) {
		smfi_setreply(ctx, "554", "5.7.1", "Forged bounce message not accepted - update your virus scanner");
		syslog(LOG_NOTICE, "Blocked by blacklist-milter");
		rc = SMFIS_REJECT;
	} else
		rc = SMFIS_CONTINUE;

	free(string);
	privdata = smfi_getpriv(ctx);

	if(privdata == NULL)
		/*
		 * Not the first call to blacklist_body for this message
		 */
		return rc;

	now = time((time_t *)0);
	for(i = 0, bip = bips; i < NBLACKLISTED; i++, bip++)
		if(strcmp(bip->ip, privdata->ip) == 0) {
			if((now - bip->time) < TIMEOUT) {
				/*
				 * Another spam in the same connection
				 */
				syslog(LOG_NOTICE, "Rejected message from blacklisted IP %s\n", privdata->ip);
				smfi_setreply(ctx, "550", "5.7.1", "Your IP is blacklisted because you are sending spam");
				thread_sleep(2);	/* waste their time */
				bip->time = now;
				return SMFIS_REJECT;
			} else
				/* timeout */
				bip->ip[0] = '\0';
			break;
		}

	if(rememberIP(ctx, privdata->ip))
		return rc;

	free(privdata);
	smfi_setpriv(ctx, NULL);
	return SMFIS_TEMPFAIL;
}
Example #30
0
static sfsistat
cb_eom(SMFICTX *ctx)
{
	struct context *context;
	sfsistat action = SMFIS_CONTINUE;
	char buf[2048];
	int pos = 0, retry = 0;

	if ((context = (struct context *)smfi_getpriv(ctx)) == NULL) {
		msg(LOG_ERR, NULL, "cb_eom: smfi_getpriv");
		return (SMFIS_ACCEPT);
	}
	msg(LOG_DEBUG, context, "cb_eom()");
	if (context->fd < 0)
		goto done;
	context->symbols[0] = 0;
	/* no more writing data to spamd, want to read result now */
	if (shutdown(context->fd, SHUT_WR)) {
		msg(LOG_ERR, context, "cb_eom: shutdown: %s", strerror(errno));
		goto done;
	}
	if (fcntl(context->fd, F_SETFL, fcntl(context->fd, F_GETFL) |
	    O_NONBLOCK)) {
		msg(LOG_ERR, context, "cb_eom: fcntl: %s", strerror(errno));
		goto done;
	}
	/* try at most 6 times (10 seconds timeout each) */
	while (action == SMFIS_CONTINUE && retry < 6) {
		fd_set fds;
		struct timeval tv;
		int r, i;
		char b[8192];

		FD_ZERO(&fds);
		FD_SET(context->fd, &fds);
		tv.tv_sec = 10;
		tv.tv_usec = 0;
		r = select(context->fd + 1, &fds, NULL, NULL, &tv);
		if (r < 0) {
			if (errno != EINTR) {
				msg(LOG_ERR, context, "cb_eom: select: %s",
				    strerror(errno));
				break;
			}
			continue;
		} else if (r == 0 || !FD_ISSET(context->fd, &fds)) {
			retry++;
			msg(LOG_DEBUG, context, "cb_eom: waiting for "
			    "spamd reply (retry %d)", retry);
			continue;
		}
		r = read(context->fd, b, sizeof(b));
		if (r < 0) {
			if (errno != EINTR) {
				msg(LOG_ERR, context, "cb_eom: read: %s",
				    strerror(errno));
				break;
			}
			continue;
		} else if (r == 0)
			/* connection closed by spamd */
			break;
		for (i = 0; i < r; ++i)
			if (b[i] == '\n' || pos == sizeof(buf) - 1) {
				if (pos > 0 && buf[pos - 1] == '\r')
					buf[pos - 1] = 0;
				else
					buf[pos] = 0;
				/* sets action when done */
				spamd_reply(buf, context, &action);
				pos = 0;
			} else
				buf[pos++] = b[i];
	}
	if (retry == 6)
		msg(LOG_ERR, context, "cb_eom: spamd connection timed out");
done:
	if (context->fd >= 0) {
		close(context->fd);
		context->fd = -1;
	}
	/* either way, we don't want to continue */
	if (action == SMFIS_CONTINUE)
		action = (context->spam && context->score > REJECT_SPAM_LEVEL) ? SMFIS_REJECT : SMFIS_ACCEPT;
	msg(action == SMFIS_REJECT ? LOG_NOTICE : LOG_INFO, context,
	    "%s (%s %.1f/%.1f%s%s), From: %s, To: %s, Subject: %s",
	    (action == SMFIS_REJECT ? "REJECT" : "ACCEPT"),
	    (context->spam ? "SPAM" : "ham"), context->score, context->threshold,
	    (context->symbols[0] ? " " :  ""), context->symbols,
	    context->hdr_from, context->hdr_to, context->hdr_subject);
	if (action == SMFIS_REJECT) {
		char m[1024];

		snprintf(m, sizeof(m), "Spam (score %.1f)", context->score);
               if (smfi_setreply(ctx, RCODE_REJECT, XCODE_REJECT, m) !=
		    MI_SUCCESS)
			msg(LOG_ERR, context, "smfi_setreply");
	} else {
	 char m[1024];
		int j=0;
		int starcnt = (int)context->score;
		const char *star = "*";
		char stars[1024];
		stars[0]='\0';
		snprintf(m, sizeof(m), "%s, %s%.1f %s%.1f%s%s",
		    (context->spam ? "Yes" : "No"),"score=",
		    context->score, "required=",context->threshold,
		    (context->symbols[0] ? " " :  ""), context->symbols);

                if (smfi_addheader(ctx, "X-Spam-Flag", context->spam ? "YES" : "NO") != MI_SUCCESS) {
		      msg(LOG_ERR, context, "smfi_addheader");
        }

        if (smfi_addheader(ctx, "X-Spam-Status", m) != MI_SUCCESS) {
            msg(LOG_ERR, context, "smfi_addheader");
        }

        for (j = 0; j < starcnt; j++) {
            strlcat(stars, star, sizeof (stars));
        }
        if (smfi_addheader(ctx, "X-Spam-Level", stars) != MI_SUCCESS) {
            msg(LOG_ERR, context, "smfi_addheader");
        }


    }
    context->pos = context->hdr_from[0] = context->hdr_to[0] =
            context->hdr_subject[0] = context->state = context->spam =
            context->symbols[0] = 0;
    context->score = context->threshold = 0.0;
    return (action);
}