view dcclib/xhdr.c @ 5:0a7a5940ee3a

Change description per license
author Peter Gervai <grin@grin.hu>
date Tue, 10 Mar 2009 15:03:24 +0100
parents c7f6b056b673
children
line wrap: on
line source

/* Distributed Checksum Clearinghouse
 *
 * build and parse headers
 *
 * Copyright (c) 2008 by Rhyolite Software, LLC
 *
 * This agreement is not applicable to any entity which sells anti-spam
 * solutions to others or provides an anti-spam solution as part of a
 * security solution sold to other entities, or to a private network
 * which employs the DCC or uses data provided by operation of the DCC
 * but does not provide corresponding data to other users.
 *
 * Permission to use, copy, modify, and distribute this software without
 * changes for any purpose with or without fee is hereby granted, provided
 * that the above copyright notice and this permission notice appear in all
 * copies and any distributed versions or copies are either unchanged
 * or not called anything similar to "DCC" or "Distributed Checksum
 * Clearinghouse".
 *
 * Parties not eligible to receive a license under this agreement can
 * obtain a commercial license to use DCC by contacting Rhyolite Software
 * at sales@rhyolite.com.
 *
 * A commercial license would be for Distributed Checksum and Reputation
 * Clearinghouse software.  That software includes additional features.  This
 * free license for Distributed ChecksumClearinghouse Software does not in any
 * way grant permision to use Distributed Checksum and Reputation Clearinghouse
 * software
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 *
 * Rhyolite Software DCC 1.3.103-1.37 $Revision$
 */

#include "dcc_clnt.h"
#include "dcc_xhdr.h"


/* add text to the growing X-DCC header line */
void
xhdr_add_str(DCC_HEADER_BUF *hdr, const char *p, ...)
{
	char *hp;
	u_int lim, n;
	va_list args;

	lim = sizeof(hdr->buf) - hdr->used;
	if (lim <= 0)
		return;
	hp = &hdr->buf[hdr->used];
	if (*(hp-1) == '\n') {
		*(hp-1) = ' ';
		++hdr->col;
	}
	va_start(args, p);
	n = vsnprintf(hp, lim, p, args);
	va_end(args);
	if (n >= lim-3) {
		dcc_error_msg("header buffer too small");
		hdr->buf[lim-1] = '\n';
		hdr->used = sizeof(hdr->buf);
		return;
	}
	hdr->col += n;
	hp[n++] = '\n';
	hp[n] = '\0';
	hdr->used += n;

	/* follow RFC 2822 and limit lines to 78 */
	if (hdr->col > DCC_MAX_HDR_LINE	/* if pushed past line end, */
	    && *(hp-1) == ' '		/* & not the first cksum report, */
	    && hdr->used < sizeof(hdr->buf)-2) {    /* & have space */
		memmove(hp+1, hp, n+1);	/* then break the line */
		*(hp-1) = '\n';
		*hp = '\t';
		hdr->col = n+8;
		++hdr->used;
	}
}



/* generate X-DCC field name */
int					/* bytes put into buffer */
get_xhdr_fname(char *xhdr, int xhdr_len, const DCC_CLNT_INFO *info)
{
	SRVR_INX srvr_inx;
	const char *brand;
	int i;

	if (!info
	    || !GOOD_SRVR(&info->dcc, srvr_inx = info->dcc.srvr_inx)) {
		brand = "";
		i = 0;
	} else {
		brand = info->dcc.addrs[srvr_inx].brand;
		i = xhdr_len-sizeof(DCC_XHDR_START);
		if (i < 0)
			i = 0;
		if (i > ISZ(DCC_BRAND))
			i = ISZ(DCC_BRAND);
	}

	i = snprintf(xhdr, xhdr_len, DCC_XHDR_PAT, i, brand);
	if (i >= xhdr_len)
		i = xhdr_len-1;
	return i;
}



/* get ready to generate an X-DCC header including generating the
 * field name */
void
xhdr_init(DCC_HEADER_BUF *hdr, DCC_SRVR_ID srvr_id)
{
	if (srvr_id < DCC_SRVR_ID_MIN || srvr_id > DCC_SRVR_ID_MAX) {
		hdr->used = get_xhdr_fname(hdr->buf, sizeof(hdr->buf)-8,
					   0);
	} else {
		hdr->used = get_xhdr_fname(hdr->buf, sizeof(hdr->buf)-8,
					   dcc_clnt_info);
	}
	hdr->col = hdr->used;
	hdr->start_len = hdr->used;

	xhdr_add_str(hdr, ": %s %d;", dcc_clnt_hostname, srvr_id);
}



/* add a checksum and its counts to a growing X-DCC-Warning header line */
void
xhdr_add_ck(DCC_HEADER_BUF *hdr,
	    DCC_CK_TYPES type,		/* which kind of checksum */
	    DCC_TGTS tgts)
{
	char tbuf[30], ckcnt[10];

	xhdr_add_str(hdr, "%s=%s",
		     dcc_type2str(tbuf, sizeof(tbuf), type, 0, 0, 0),
		     dcc_tgts2str(ckcnt, sizeof(ckcnt), tgts, 0));
}



/* write header with lines ending with either "\n" or "\r\n"
 *	the buffer must already contain '\n' as needed */
void
xhdr_write(LOG_WRITE_FNC fnc, void *wctxt,
	   const char *hdr, int hdr_len,
	   u_char crlf)			/* 1=use "\r\n" instead of "\n" */
{
	char c;
	int i;

	if (hdr_len == 0)
		return;

	i = 0;
	for (;;) {
		c = hdr[i];
		if (c == '\n' && crlf) {
			if (i != 0)
				fnc(wctxt, hdr, i);
			fnc(wctxt, "\r\n", 2);
			++i;
			hdr += i;
			hdr_len -= i;
			if (hdr_len <= 0)
				return;
			i = 0;
			continue;
		}
		if (++i >= hdr_len) {
			fnc(wctxt, hdr, i);
			return;
		}
	}
}



/* create a special X-DCC header for a whitelist mail message
 *	it lacks a DCC server-ID because there is none and to let
 *	DCC clients distinguish it from real X-DCC headers */
void
xhdr_whitelist(DCC_HEADER_BUF *hdr)
{
	hdr->col = 0;
	hdr->start_len = 0;
	hdr->used = 0;
	xhdr_add_str(hdr, DCC_XHDR_START DCC_XHDR_END": %s; "DCC_XHDR_WHITELIST,
		     dcc_clnt_hostname);
}



/* see if an X-DCC header looks like one of our own and so should
 * be deleted */
u_char					/* 1=is an X-DCC-...-metrics header */
is_xhdr(const char *buf,		/* complete header */
	int buf_len)
{
	const char *e;

	if (buf[0] != 'X' && buf[0] != 'x')
		return 0;
	if (buf_len <= LITZ(DCC_XHDR_START DCC_XHDR_END":")
	    || CLITCMP(buf, DCC_XHDR_START))
		return 0;

	buf += LITZ(DCC_XHDR_START);
	buf_len -= LITZ(DCC_XHDR_START);

	/* look for the end of header field name */
	e = memchr(buf, ':', buf_len);
	if (e) {
		buf_len = e - buf;
		if (buf_len < LITZ(DCC_XHDR_END))
			return 0;
	}

	buf_len -= LITZ(DCC_XHDR_END);
	buf += buf_len;
	if (!CLITCMP(buf, DCC_XHDR_END))
		return 1;

	return 0;
}