/* Distributed Checksum Clearinghouse * * parse a named checksum * * --C-LICENSE-- * $Revision: 1.80 $ */ #include "dcc_ck.h" #include "dcc_xhdr.h" #ifndef DCC_WIN32 #include #endif static int /* -1=fatal 0=problem */ dcc_host2ck(DCC_EMSG *emsg, WF *wf, const char *ck, /* string of an IP address */ DCC_TGTS tgts, /* OK, MANY, etc. */ DCC_PARSED_CK_FNC fnc, /* do something with each checksum */ DCC_PARSED_CK_RANGE_FNC range_fnc) { int error; DCC_FNM_LNO_BUF fnm_buf; DCC_IP_RANGE range; DCC_SUM sum; DCC_SOCKU *sup; int ok; ok = str2range(emsg, &range, 0, ck, wf_fnm(wf, wf->fno), wf->lno); if (ok < 0) return 0; /* bad range */ if (ok > 0) /* valid IP address range */ return range_fnc(emsg, wf, &range, tgts); /* we have junk * or a host name which is not allowed in a per-user whitelist */ if (wf->wf_flags & WF_PER_USER) { dcc_pemsg(EX_NOHOST, emsg, "host name checksum illegal in per-user whitelist%s", wf_fnm_lno(&fnm_buf, wf)); return 0; } if (wf->wtbl) /* need future host name resolutions */ wf->wtbl->hdr.fgs |= WHITE_FG_HOSTNAMES; dcc_host_lock(); /* don't use SOCKS host name resolution because the host names that * most need whitelisting are inside the SOCKS firewall and may not * be known to outside DNS servers. */ if (!dcc_get_host(ck, DCC_GETH_DEF, &error)) { dcc_pemsg(EX_NOHOST, emsg, "host name \"%s\": %s%s", ck, H_ERROR_STR1(error), wf_fnm_lno(&fnm_buf, wf)); dcc_host_unlock(); return 0; } for (sup = dcc_hostaddrs; sup < dcc_hostaddrs_end; ++sup) { struct in6_addr addr6; ipv6tock(&sum, dcc_su2ipv6(&addr6, 0, sup)); ok = fnc(emsg, wf, DCC_CK_IP, &sum, tgts); if (ok <= 0) { dcc_host_unlock(); return ok; } } dcc_host_unlock(); return 1; } /* generate checksum value from the name of the checksum and a string */ int /* 1=ok 0=problem -1=fatal */ dcc_parse_ck(DCC_EMSG *emsg, /* failure message here */ WF *wf, const char *type_nm, DCC_CK_TYPES type, const char *str, /* ASCII string to generate checksum */ DCC_TGTS tgts, /* # of targets */ DCC_PARSED_CK_FNC add_fnc, /* do something with the checksum */ DCC_PARSED_CK_RANGE_FNC range_fnc) { DCC_FNM_LNO_BUF fnm_buf; char *phdr, c, hdr_buf[80]; DCC_SUM sum; const char *pstr; /* compute the checksum */ switch (type) { case DCC_CK_IP: return dcc_host2ck(emsg, wf, str, tgts, add_fnc, range_fnc); case DCC_CK_ENV_FROM: case DCC_CK_FROM: case DCC_CK_MESSAGE_ID: case DCC_CK_RECEIVED: case DCC_CK_ENV_TO: str2ck(&sum, 0, 0, str); return add_fnc(emsg, wf, type, &sum, tgts); case DCC_CK_SUB: str += strspn(str, DCC_WHITESPACE); pstr = str; phdr = hdr_buf; for (;;) { c = *pstr++; if (c == '\0' || c == ':' || DCC_IS_WHITE(c)) break; c = DCC_TO_LOWER(c); *phdr++ = c; if (phdr >= &hdr_buf[sizeof(hdr_buf)]) { dcc_pemsg(EX_DATAERR, emsg, " imposible substitute header name" " in \"%s\"%s", str, wf_fnm_lno(&fnm_buf, wf)); return 0; } } pstr += strspn(pstr, DCC_WHITESPACE); if (*pstr == '\0' || phdr == hdr_buf) { dcc_pemsg(EX_DATAERR, emsg, " substitute header name absent in \"%s\"%s", str, wf_fnm_lno(&fnm_buf, wf)); return 0; } str2ck(&sum, hdr_buf, phdr-hdr_buf, pstr); return add_fnc(emsg, wf, type, &sum, tgts); case DCC_CK_INVALID: case DCC_CK_BODY: case DCC_CK_FUZ1: case DCC_CK_FUZ2: case DCC_CK_G_MSG_R_TOTAL: case DCC_CK_G_TRIPLE_R_BULK: case DCC_CK_SRVR_ID: break; } dcc_pemsg(EX_DATAERR, emsg, "unrecognized checksum type \"%s\"%s", type_nm, wf_fnm_lno(&fnm_buf, wf)); return 0; } /* generate checksum value from the name of the checksum and hex values */ int /* 1=ok 0=syntax -1=fatal */ dcc_parse_hex_ck(DCC_EMSG *emsg, /* failure message here */ WF *wf, const char *type_nm, DCC_CK_TYPES type, const char *str, /* ASCII string to generate checksum */ DCC_TGTS tgts, /* # of targets */ DCC_PARSED_CK_FNC add_fnc) /* do something with the checksum */ { union { u_int32_t n[4]; DCC_SUM sum; } u; DCC_FNM_LNO_BUF fnm_buf; int id; if (type == DCC_CK_INVALID) { dcc_pemsg(EX_DATAERR, emsg, "unrecognized checksum type \"%s\"%s", type_nm, wf_fnm_lno(&fnm_buf, wf)); return 0; } if (4 == sscanf(str, DCC_CKSUM_HEX_PAT"\n", &u.n[0], &u.n[1], &u.n[2], &u.n[3]) || (type == DCC_CK_SUB && 4 == sscanf(str, "%*s "DCC_CKSUM_HEX_PAT"\n", &u.n[0], &u.n[1], &u.n[2], &u.n[3]))) { /* recognize simple hex checksums */ u.n[0] = htonl(u.n[0]); u.n[1] = htonl(u.n[1]); u.n[2] = htonl(u.n[2]); u.n[3] = htonl(u.n[3]); } else if (1 == sscanf(str, DCC_XHDR_ID_SIMPLE" at %d", &id) || 1 == sscanf(str, DCC_XHDR_ID_IGNORE" at %d", &id) || 1 == sscanf(str, DCC_XHDR_ID_ROGUE" at %d", &id)) { /* parse server-ID declarations */ DCC_ID_SRVR_TYPE_SET(&u.sum, id); } else { dcc_pemsg(EX_DATAERR, emsg, "unrecognized checksum value \"%s\"%s", str, wf_fnm_lno(&fnm_buf, wf)); return 0; } /* apply the function to the checksum */ return add_fnc(emsg, wf, type, &u.sum, tgts); }