/* Distributed Checksum Clearinghouse * * client-server and server-server protocols * * 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.109 $Revision$ */ #ifndef DCC_PROTO_H #define DCC_PROTO_H #define DCC_PKT_VERSION4 4 #define DCC_PKT_VERSION5 5 #define DCC_PKT_VERSION6 6 #define DCC_PKT_VERSION 7 #define DCC_PKT_VERSION_MIN DCC_PKT_VERSION4 #define DCC_PKT_VERSION_MAX DCC_PKT_VERSION #define DCC_SRVR_PORT 6277 /* default DCC server port # */ #define DCC_GREY_PORT 6276 /* grey listing server port */ /* types of checksums */ typedef enum { DCC_CK_INVALID =0, /* deleted from database when seen */ DCC_CK_IP =1, /* MD5 of binary source IPv6 address */ DCC_CK_ENV_FROM =2, /* " " envelope Mail From value */ DCC_CK_FROM =3, /* " " header From: line */ DCC_CK_SUB =4, /* " " substitute header line */ DCC_CK_MESSAGE_ID =5, /* " " header Message-ID: line */ DCC_CK_RECEIVED =6, /* " " last header Received: line */ DCC_CK_BODY =7, /* " " body */ DCC_CK_FUZ1 =8, /* " " filtered body */ DCC_CK_FUZ2 =9, /* " " " " */ DCC_CK_G_MSG_R_TOTAL =10, # define DCC_CK_GREY_MSG DCC_CK_G_MSG_R_TOTAL # define DCC_CK_REP_TOTAL DCC_CK_G_MSG_R_TOTAL DCC_CK_G_TRIPLE_R_BULK =11, # define DCC_CK_GREY3 DCC_CK_G_TRIPLE_R_BULK # define DCC_CK_REP_BULK DCC_CK_G_TRIPLE_R_BULK DCC_CK_SRVR_ID =12, /* hostname for server-ID check */ DCC_CK_ENV_TO =13 /* MD5 of envelope Rcpt To value */ # define DCC_CK_FLOD_PATH DCC_CK_ENV_TO /* flooding path in server-IDs */ } DCC_CK_TYPES; typedef u_char DCC_CK_TYPE_B; /* big enough */ #define DCC_CK_TYPE_FIRST DCC_CK_IP #define DCC_CK_TYPE_LAST DCC_CK_ENV_TO #define DCC_NUM_CKS DCC_CK_TYPE_LAST /* # of valid types */ /* DCC_DIM_CKS dimensions arrays of checksum types including DCC_CK_INVALID * Beware that DCC_DIM_CKS is used in the database header. */ #define DCC_DIM_CKS (DCC_CK_TYPE_LAST+1) /* DCC_MAX_FLOD_PATH assumes that among the 14 possible slots, DCC_CK_INVALID * and DCC_CK_SRVR_ID are not used when it, is so there is room for * a total of 3 DCC_CK_FLOD_PATH entries. */ #define DCC_MAX_FLOD_PATH_CKSUMS 3 /* checksums in client-server protocol */ #define DCC_QUERY_MAX DCC_DIM_CKS /* even to prevent structure padding */ /* Ensure that arrays of DCC_CKs contain an even number so that structures * containing them will have no extra structure packing */ #define DCC_COMP_DIM_CKS ((((DCC_NUM_CKS+1)+1)/2)*2) /* == DCC_DIM_CKS */ /* keep some checksums in the database longer than others */ #define DCC_CK_LONG_TERM(t) ((t) >= DCC_CK_FUZ1 \ && (t) <= DCC_CK_G_TRIPLE_R_BULK) #define DCC_CK_IS_BODY(t) ((t) >= DCC_CK_BODY && (t) <= DCC_CK_FUZ2) /* MD5 of greylist msg+sender+target */ #define DCC_CK_IS_GREY_MSG(g,t) ((g) && (t) == DCC_CK_G_MSG_R_TOTAL) /* MD5 of greylisted triple */ #define DCC_CK_IS_GREY_TRIPLE(g,t) ((g) && (t) == DCC_CK_G_TRIPLE_R_BULK) #define DCC_CK_IS_GREY(g,t) (DCC_CK_IS_GREY_MSG(g,t) \ || DCC_CK_IS_GREY_TRIPLE(g,t)) /* total messages sent by an IP address */ #define DCC_CK_IS_REP_TOTAL_CMN(g,t) (!(g) && (t) == DCC_CK_G_MSG_R_TOTAL) /* bulk messages sent by an IP address */ #define DCC_CK_IS_REP_BULK_CMN(g,t) (!(g) && (t) == DCC_CK_G_TRIPLE_R_BULK) #define DCC_CK_IS_REP_CMN(g,t) (DCC_CK_IS_REP_TOTAL_CMN(g,t) \ || DCC_CK_IS_REP_BULK_CMN(g,t)) #define DCC_CK_IS_REP_TOTAL_OP(g,t) 0 #define DCC_CK_IS_REP_BULK_OP(g,t) 0 #define DCC_CK_IS_REP_OP(g,t) 0 typedef enum { DCC_OP_INVALID =0, DCC_OP_NOP =1, /* see if the server is alive */ DCC_OP_REPORT =2, /* old client reporting and querying */ DCC_OP_QUERY =3, /* client querying */ DCC_OP_ANSWER =4, /* server responding */ DCC_OP_ADMN =5, /* control the server */ DCC_OP_OK =6, /* administrative operation ok */ DCC_OP_ERROR =7, /* server failing or complaining */ DCC_OP_DELETE =8, /* delete some checksums */ DCC_OP_GREY_REPORT =9, /* greylist report */ DCC_OP_GREY_QUERY =10, /* " " query */ DCC_OP_GREY_SPAM =11, /* forget greylisted spammer */ DCC_OP_GREY_WHITE =12 /* whitelisted greylist triple */ } DCC_OPS; typedef u_int32_t DCC_CLNT_ID; #define DCC_ID_INVALID 0 #define DCC_ID_ANON 1 /* anonymous (non-paying) client */ #define DCC_ID_WHITE 2 /* white-listed */ #define DCC_ID_COMP 3 /* compressed */ #define DCC_SRVR_ID_MIN 100 /* below reserved for special uses */ #define DCC_SRVR_ID_MAX 32767 /* below are servers--must be 2**n-1 */ #define DCC_CLNT_ID_MIN (DCC_SRVR_ID_MAX+1) #define DCC_CLNT_ID_MAX 16777215 typedef u_int16_t DCC_SRVR_ID; #define DCC_SRVR_ID_AUTH (DCC_SRVR_ID_MAX+1) /* client was authenticated */ /* client's identification of its transaction */ typedef struct { u_int32_t h; /* client host ID, e.g. IP address */ u_int32_t p; /* process ID, serial #, timestamp */ u_int32_t r; /* report ID */ u_int32_t t; /* client (re)transmission # */ } DCC_OP_NUMS; /* The inter-DCC server flooding algorithm depends on unique-per-server * timestamps to detect duplicates. That imposes a requirement on * timestamps that they have resolution enough to separate reports * from clients arriving at any single server. * The timestamps are 48 bits consisting of 17 bits of 8's of microseconds * and 31 bits of seconds. That's sufficient for the UNIX epoch. * If the DCC is still around in the 2030's (and in the unlikely case that * 8 microseconds are still fine enough), we can make the 31 bits be * an offset in a bigger window. */ #define DCC_TS_US_RSHIFT 3 #define DCC_TS_US_MULT (1<= 16777200 targets */ #define DCC_TGTS_OK 0x00fffff1 /* certified not spam */ #define DCC_TGTS_OK2 0x00fffff2 /* half certified not spam */ #define DCC_TGTS_GREY_WHITE DCC_TGTS_OK2 /* whitelisted for greylisting */ #define DCC_TGTS_DEL 0x00fffff3 /* a deleted checksum */ #define DCC_TGTS_REP_ADJ 0x00fffff4 /* scale a reputation */ #define DCC_TGTS_OK_MX 0x00fffff5 /* partly whitelist MX secondary */ #define DCC_TGTS_OK_MXDCC 0x00fffff6 /* MX secondary with DCC client */ #define DCC_TGTS_SUBMIT_CLIENT 0x00fffff7 /* SMTP submission client */ #define DCC_TGTS_MAX_DB DCC_TGTS_REP_ADJ #define DCC_TGTS_INVALID 0x01000000 #define DCC_TGTS_SPAM DCC_TGTS_INVALID #define DCC_TGTS_RPT_MAX 1000 #define DCC_TGTS_FLOD_RPT_MAX (DCC_TGTS_RPT_MAX*1000) #define BULK_THRESHOLD 10 #define REFLOOD_THRESHOLD 300 #define DCC_TGTS_REP_BULK BULK_THRESHOLD /* checksums kept by most servers */ #define DB_GLOBAL_NOKEEP(g,t) (!DCC_CK_IS_BODY(t) \ && (t) != DCC_CK_SRVR_ID \ && ((t) != DCC_CK_G_MSG_R_TOTAL || !(g)) \ && ((t) != DCC_CK_G_TRIPLE_R_BULK || !(g))) /* checksums subject to thresholds */ #define DCC_CK_THOLD_OK(t) ((t) > DCC_CK_INVALID \ && (t) <= DCC_CK_G_TRIPLE_R_BULK) /* a reported checksum from a client */ typedef u_char DCC_SUM[16]; /* for now all have 16 bytes */ typedef struct { DCC_CK_TYPE_B type; u_char len; /* total length of this checksum */ DCC_SUM sum; } DCC_CK; /* most packets from client to server */ typedef struct { DCC_HDR hdr; DCC_TGTS tgts; /* # of addressees */ DCC_CK cks[DCC_QUERY_MAX]; /* even to prevent structure padding */ DCC_SIGNATURE signature; } DCC_REPORT; /* most responses */ typedef struct { DCC_TGTS c; /* current value, with this report */ DCC_TGTS p; /* previous value, before this report */ } DCC_ANSWER_BODY_CKS; typedef struct { DCC_HDR hdr; DCC_ANSWER_BODY_CKS b[DCC_QUERY_MAX]; DCC_SIGNATURE signature; } DCC_ANSWER; #ifdef DCC_PKT_VERSION5 typedef struct { DCC_HDR hdr; DCC_TGTS b[DCC_QUERY_MAX]; /* current values */ DCC_SIGNATURE signature; } DCC_ANSWERv5; #endif typedef struct { DCC_HDR hdr; DCC_TGTS msg; DCC_TGTS triple; DCC_SIGNATURE signature; } DCC_GREY_ANSWER; /* DCC_OP_DELETE request to delete checksums */ typedef struct { DCC_HDR hdr; int32_t date; /* seconds since epoch on client */ DCC_CK ck; u_char pad[2]; DCC_SIGNATURE signature; } DCC_DELETE; /* DCC_OP_GREY_SPAM restore greylist embargo */ typedef struct { DCC_HDR hdr; DCC_CK ip; DCC_CK msg; DCC_CK triple; DCC_SIGNATURE signature; } DCC_GREY_SPAM; /* error response from server to client */ typedef struct { DCC_HDR hdr; # define DCC_ERROR_MSG_LEN 128 char msg[DCC_ERROR_MSG_LEN]; DCC_SIGNATURE signature; } DCC_ERROR; /* ************** server-to-server flooding protocol ************ */ /* flood sender's position or serial number * Only the sender understands sender positions except for these * special values. However, the special values imply that the position * must be big endian. */ typedef u_char DCC_FLOD_POS[8]; /* special cases sent by the receiver back to the sender */ typedef enum { DCC_FLOD_POS_END =0, /* receiver closing with message */ DCC_FLOD_POS_END_REQ =1, /* receiver wants to stop */ DCC_FLOD_POS_NOTE =2, /* receiver has a tracing message */ DCC_FLOD_POS_COMPLAINT =3, /* receiver has a problem message */ DCC_FLOD_POS_REWIND =4, /* receiver's database emptied */ DCC_FLOD_POS_FFWD_IN =5 /* receiver wants fast-forward */ } DCC_FLOD_POS_OPS; #define DCC_FLOD_POS_MIN 10 #define DCC_FLOD_OK_STR "DCC flod ok: " #define DCC_FLOD_MAX_RESP 200 /* report forwarded among servers */ typedef struct { DCC_FLOD_POS pos; u_char tgts[sizeof(DCC_TGTS)]; u_char srvr_id_auth[sizeof(DCC_SRVR_ID)]; /* receiving server */ DCC_TS ts; /* date reported */ u_char num_cks; DCC_CK cks[DCC_QUERY_MAX]; } DCC_FLOD; /* record of path taken by a report */ #define DCC_NUM_FLOD_PATH ((int)(sizeof(DCC_SUM)/sizeof(DCC_SRVR_ID))) typedef struct { u_char hi, lo; } DCC_FLOD_PATH_ID; /* This must not be too large lest reports become larger than DCC_DIM_CKS * */ #define DCC_MAX_FLOD_PATH (DCC_NUM_FLOD_PATH*DCC_MAX_FLOD_PATH_CKSUMS) typedef struct { DCC_FLOD_POS z; char msg[DCC_FLOD_MAX_RESP]; char null; } FLOD_END; typedef struct { DCC_FLOD_POS op; u_char len; char str[DCC_FLOD_MAX_RESP]; } FLOD_NOTE; #define FLOD_NOTE_OVHD ((int)sizeof(FLOD_NOTE)-DCC_FLOD_MAX_RESP) #define DCC_FLOD_VERSION_STR_BASE "DCC flod version " #define DCC_FLOD_VERSION7 7 #define DCC_FLOD_VERSION7_STR DCC_FLOD_VERSION_STR_BASE"7" #define DCC_FLOD_VERSION_DEF 0 #define DCC_FLOD_VERSION_CUR DCC_FLOD_VERSION7 #define DCC_FLOD_VERSION_CUR_STR DCC_FLOD_VERSION7_STR #define DCC_FLOD_REP_VERSION_STR_BASE DCC_FLOD_VERSION_STR_BASE"rep " typedef struct { # define DCC_FLOD_VERSION_STR_LEN 64 char str[DCC_FLOD_VERSION_STR_LEN]; DCC_SRVR_ID sender_srvr_id; u_char turn; /* 1=turn connection around for SOCKS */ u_char unused[3]; } DCC_FLOD_VERSION_BODY; typedef struct { DCC_FLOD_VERSION_BODY body; char pad[256-sizeof(DCC_FLOD_VERSION_BODY)-sizeof(DCC_SIGNATURE)]; DCC_SIGNATURE signature; } DCC_FLOD_VERSION_HDR; /* parts of error messages sent between flooding peers */ #define DCC_FLOD_BAD_VER_MSG_BASE "unrecognized flod version " #define DCC_FLOD_BAD_VER_MSG DCC_FLOD_BAD_VER_MSG_BASE"need \"" #define DCC_FLOD_BAD_ID_MSG "unauthorized ID" #define DCC_FLOD_BAD_AUTH_MSG "bad authentication for ID" #define DCC_FLOD_REPS_OFF_MSG "unauthorized reputations" #define DCC_FLOD_PASSWD_ID_MSG "unknown passwd-ID" #define DCC_FLOD_NO_PASSWD_MSG "no password for passwd-ID" #endif /* DCC_PROTO_H */