diff dcclib/xhdr.c @ 0:c7f6b056b673

First import of vendor version
author Peter Gervai <grin@grin.hu>
date Tue, 10 Mar 2009 13:49:58 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dcclib/xhdr.c	Tue Mar 10 13:49:58 2009 +0100
@@ -0,0 +1,237 @@
+/* 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;
+}