Logo Search packages:      
Sourcecode: dcc version File versions  Download package

dccsight.c

/* Distributed Checksum Clearinghouse server
 *
 * report the previously computed checksums of a message
 *
 * Copyright (c) 2005 by Rhyolite Software
 *
 * 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.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE
 * 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.2.74-1.34 $Revision$
 */

#include "dcc_ck.h"
#include "dcc_xhdr.h"


static DCC_EMSG dcc_emsg;

static const char *homedir;
static const char *mapfile_nm = DCC_MAP_NM_DEF;

static DCC_TGTS targets = 1;

static const char* white_nm;
static const char *ifile_nm;
static FILE *ifile;
static const char *grey_sum;

static DCC_WF dccsight_wf;
static DCC_CLNT_CTXT *ctxt;
static u_char query_only;

static DCC_GOT_CKS cks;

static DCC_HEADER_BUF header;

static void do_grey(void);
static int add_cksum(DCC_EMSG, UATTRIB DCC_WF *, const char *, int,
                 DCC_CK_TYPES, DCC_SUM, DCC_TGTS);

static void NRATTRIB
usage(void)
{
      dcc_logbad(EX_USAGE,
               "usage: [-VdQ] [-h homedir] [-m map] [-w whiteclnt]"
               " [-t targets]\n"
               "   [-i infile] [-G grey-cksum] [-L ltype,facility.level]");
}



int NRATTRIB
main(int argc, char **argv)
{
      char buf[200];
      const char *bufp;
      char type_str[DCC_XHDR_MAX_TYPE_LEN+1];
      u_long l;
      u_char skip_heading, result;
      u_int honor;
      DCC_CKS_WTGTS wtgts;
      char c1, c2, *p;
      int i;

      dcc_syslog_init(0, argv[0], 0);
      dcc_init_tholds();

      /* we must be SUID to read and write the system's common connection
       * parameter memory mapped file.  We also need to read the common
       * local white list and write the mmap()'ed hash file */
      dcc_init_priv();

      ifile = stdin;
      while ((i = getopt(argc, argv, "VdQh:m:w:t:i:G:L:")) != EOF) {
            switch (i) {
            case 'V':
                  fprintf(stderr, DCC_VERSION"\n");
                  exit(EX_OK);
                  break;

            case 'd':
                  ++dcc_clnt_debug;
                  break;

            case 'Q':
                  query_only = 1;
                  break;

            case 'h':
                  homedir = optarg;
                  break;

            case 'm':
                  mapfile_nm = optarg;
                  break;

            case 'w':
                  white_nm = optarg;
                  break;

            case 't':
                  if (!strcasecmp(optarg, "many")) {
                        targets = DCC_TGTS_TOO_MANY;
                  } else {
                        l = strtoul(optarg, &p, 0);
                        if (*p != '\0' || l > 1000)
                              dcc_error_msg("invalid count \"%s\"",
                                          optarg);
                        else
                              targets = l;
                  }
                  break;

            case 'i':
                  /* open the input file now, before changing to the
                   * home DCC directory */
                  ifile_nm = optarg;
                  ifile = fopen(ifile_nm, "r");
                  if (!ifile)
                        dcc_logbad(EX_USAGE,
                                 "bad input file \"%s\": %s",
                                 ifile_nm, ERROR_STR());
                  break;

            case 'G':
                  grey_sum = optarg;
                  break;

            case 'L':
                  dcc_parse_log_opt(optarg);
                  break;

            default:
                  usage();
            }
      }
      argc -= optind;
      argv += optind;
      if (argc != 0)
            usage();

      dcc_clnt_unthread_init();

      if (!dcc_cdhome(dcc_emsg, homedir))
            dcc_error_msg("%s", dcc_emsg);

      /* open /var/dcc/map and start a connection to a DCC server */
      ctxt = dcc_clnt_init(dcc_emsg, 0, mapfile_nm, DCC_CLNT_FG_NONE);
      if (!ctxt)
            dcc_logbad(dcc_ex_code, "%s", dcc_emsg);

      if (grey_sum) {
            if (ifile_nm)
                  dcc_logbad(EX_USAGE, "-i and -G incompatible");
            do_grey();
            exit(EX_OK);
      }

      if (!ifile_nm)
            ifile_nm = "stdin";

      /* get the checksums */
      skip_heading = 0;
      for (;;) {
            bufp = fgets(buf, sizeof(buf), ifile);
            if (!bufp) {
                  if (ferror(ifile))
                        dcc_logbad(EX_DATAERR, "fgets(%s): %s",
                                 ifile_nm, ERROR_STR());
                  break;
            }

            /* ignore blank lines */
            i = strlen(buf);
            if (!i) {
                  skip_heading = 0;
                  continue;
            }

            /* trim leading and trailing whitespace */
            p = &buf[i-1];
            bufp += strspn(bufp, DCC_WHITESPACE);
            c2 = *p;          /* should be '\n' */
            while (p > bufp) {
                  c1 = *(p-1);
                  if (c1 != '\r' && c1 != ' ' && c1 != '\t')
                        break;
                  *--p = c2;
            }
            if (*bufp == '\n' || *bufp == '\0') {
                  skip_heading = 0;
                  continue;
            }

            /* ignore DCC header lines such as in the output
             * of `dccproc -C` */
            if (!CSTRCMP(bufp, DCC_XHDR_START)) {
                  skip_heading = 1;
                  continue;
            }
            /* skip headings for the checksums */
            if (skip_heading
                && (buf[0] == ' ' || buf[0] == '\t')
                && !strchr(bufp, ':'))
                  continue;

            /* handle the next checksum */
            bufp = dcc_parse_word(dcc_emsg, type_str, sizeof(type_str),
                              bufp, "checksum type", 0, 0);
            if (!bufp)
                  dcc_logbad(dcc_ex_code, "%s", dcc_emsg);
            if (0 >= dcc_parse_hex_ck(dcc_emsg, &dccsight_wf, 0, 0,
                                type_str, bufp, 1, add_cksum))
                  dcc_logbad(dcc_ex_code, "%s", dcc_emsg);
      }
      fclose(ifile);

      if (!(cks.flags & DCC_CKS_HAVE_SUM))
            dcc_logbad(EX_DATAERR, "no reportable checksums");

      result = dcc_white_ask(dcc_emsg, &dccsight_wf, ctxt, &header, &honor,
                         white_nm, &cks, wtgts,
                         query_only ? 0 : targets);
      if (!result)
            dcc_error_msg("%s", dcc_emsg);
      else if (header.buf[0] != '\0')
            printf("%s\n", header.buf);

      exit(EX_OK);
}



static void
do_grey(void)
{
      union {
          u_int32_t n[4];
          DCC_SUM sum;
      } u;
      DCC_QUERY_REPORT rpt;
      union {
          DCC_HDR hdr;
          DCC_QUERY_RESP r;
          DCC_ERROR     error;
      } resp;
      int recv_len;

      if (4 != sscanf(grey_sum, DCC_CKSUM_HEX_PAT,
                  &u.n[0], &u.n[1], &u.n[2], &u.n[3]))
            dcc_logbad(EX_USAGE,
                     "unrecognized greylist checksum");
      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]);

      memset(&rpt, 0, sizeof(rpt));
      memcpy(rpt.cks[0].sum, u.sum, sizeof(rpt.cks[0].sum));
      rpt.cks[0].type = DCC_CK_GREY_TRIPLE;
      rpt.cks[0].len = sizeof(rpt.cks[0]);
      if (!dcc_clnt_op(dcc_emsg, ctxt, DCC_CLNT_FG_GREY, 0, 0,
                   &rpt.hdr, (sizeof(rpt) - sizeof(rpt.cks)
                            + sizeof(rpt.cks[0])),
                   query_only ? DCC_OP_GREY_QUERY : DCC_OP_GREY_WHITE,
                   &resp.hdr, sizeof(resp), 0))
            dcc_logbad(dcc_ex_code, "%s", dcc_emsg);

      recv_len = htons(resp.r.hdr.len);
      if (resp.hdr.op != DCC_OP_QUERY_RESP)
            dcc_logbad(EX_UNAVAILABLE, "DCC %s: %s %*s",
                     dcc_srvr_nm(),
                     dcc_hdr_op2str(&resp.hdr),
                     (resp.hdr.op == DCC_OP_ERROR
                      ? (recv_len - (ISZ(resp.error)
                                 - ISZ(resp.error.msg)))
                      : 0),
                     resp.error.msg);
      if (recv_len != (sizeof(resp.r) - sizeof(resp.r.body.tgts)
                   + 2*sizeof(resp.r.body.tgts[0])))
            dcc_logbad(EX_UNAVAILABLE, "DCC %s: answered with %d bytes",
                     dcc_srvr_nm(), recv_len);

      switch (ntohl(resp.r.body.tgts[1])) {
      case DCC_TGTS_OK:       /* embargo ended just now */
            printf(DCC_XHDR_EMBARGO_ENDED"\n");
            break;
      case DCC_TGTS_TOO_MANY:       /* no current embargo */
            printf(DCC_XHDR_EMBARGO_PASS"\n");
            break;
      case DCC_TGTS_OK2:            /* whitelisted for greylisting */
            printf(DCC_XHDR_EMBARGO_OK"\n");
            break;
      default:                /* embargoed */
            printf(DCC_XHDR_EMBARGO"\n");
            break;
      }
      exit(EX_OK);
}



static int
add_cksum(DCC_EMSG emsg, DCC_WF *wf UATTRIB, const char *fnm, int lineno,
        DCC_CK_TYPES type, DCC_SUM sum, DCC_TGTS tgts)
{
      if (cks.sums[type].type != DCC_CK_INVALID
          && type != DCC_CK_SUB) {
            dcc_pemsg(EX_DATAERR, emsg, "duplicate %s checksum%s",
                    dcc_type2str_err(type, 0, 0),
                    fnm_lineno(fnm, lineno));
      }
      if (type != DCC_CK_ENV_TO) {
            memcpy(cks.sums[type].sum, sum, sizeof(cks.sums[type].sum));
            cks.sums[type].type = type;
            cks.sums[type].rpt = 1;
            if (tgts)
                  cks.flags |= DCC_CKS_HAVE_SUM;
      }
      return 1;
}

Generated by  Doxygen 1.6.0   Back to index