/* Distributed Checksum Clearinghouse * * build and parse headers * * Copyright (c) 2006 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 for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * Parties not eligible to receive a license under this agreement can * obtain a commercial license to use DCC and permission to use * U.S. Patent 6,330,590 by contacting Commtouch at http://www.commtouch.com/ * or by email to nospam@commtouch.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.50-1.34 $Revision$ */ #include "dcc_clnt.h" #include "dcc_xhdr.h" /* add text to the growing X-DCC header line */ void dcc_add_header(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; } } int dcc_xhdr_start(char *xhdr, int xhdr_len, const DCC_CLNT_INFO *info) { int inx, i; const char *brand; if (!info || (inx = info->dcc.act_inx) >= info->dcc.num_addrs) { brand = ""; i = 0; } else { brand = info->dcc.addrs[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_START"%.*s-Metrics", i, brand); if (i >= xhdr_len) i = xhdr_len-1; return i; } void dcc_header_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 = dcc_xhdr_start(hdr->buf, sizeof(hdr->buf)-8, 0); } else { hdr->used = dcc_xhdr_start(hdr->buf, sizeof(hdr->buf)-8, dcc_clnt_info); } hdr->col = hdr->used; hdr->start_len = hdr->used; dcc_add_header(hdr, ": %s %d;", dcc_clnt_hostname, srvr_id); } /* add a checksum and its counts to a growing X-DCC-Warning header line */ void dcc_add_header_ck(DCC_HEADER_BUF *hdr, DCC_CK_TYPES type, /* which kind of checksum */ DCC_TGTS tgts) { char tbuf[30], ckcnt[10]; dcc_add_header(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 dcc_write_header(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 an X-DCC header for a whitelist mail message */ void dcc_header_white(DCC_HEADER_BUF *hdr) { hdr->col = hdr->used; hdr->start_len = hdr->used; hdr->used = dcc_xhdr_start(hdr->buf, sizeof(hdr->buf)-8, 0); dcc_add_header(hdr, ": %s; "DCC_XHDR_WHITELIST, dcc_clnt_hostname); }