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

parse_srvr_nm.c

/* Distributed Checksum Clearinghouse
 *
 * 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_clnt.h"


/* open a file of server names, ports, and so forth */
FILE *
dcc_open_srvr_nm(DCC_EMSG emsg, const char *nm)
{
      FILE *f;

      f = fopen(nm, "r");
      if (!f) {
            dcc_pemsg(EX_NOINPUT, emsg,
                    "fopen(%s): %s", DCC_NM2PATH(nm), ERROR_STR());
            return 0;
      }

      /* the file contains passwords,
       * so refuse to use it if everyone can read it */
      if (!dcc_ck_private(emsg, 0, nm, fileno(f))) {
            fclose(f);
            return 0;
      }
      return f;
}



/* get "hostname,port" string from the start of a line */
const char *                        /* 0=bad, rest of line if ok */
dcc_parse_nm_port(DCC_EMSG emsg,
              const char *line0,
              u_int def_port, /* default or DCC_GET_PORT_INVALID */
              char *hostname, /* put host name here */
              u_int hostname_len,
              u_int16_t *portp,     /* put port # in network byte order */
              char *portname, /* put port name here */
              u_int portname_len,
              const char *fnm, int lineno)      /* configuration file source */
{
      char buf[MAXHOSTNAMELEN+1+MAXPORTNAMELEN+1];
      const char *line;
      const char *pstr;
      u_int port;
      u_int hlen;


      /* get both parameters */
      line = dcc_parse_word(emsg, buf, sizeof(buf), line0,
                        "hostname,port", fnm, lineno);
      if (!line)
            return 0;

      /* get the hostname and separate the port number */
      pstr = strchr(buf, ',');
      if (!pstr) {
            if (def_port == DCC_GET_PORT_INVALID) {
                  dcc_pemsg(EX_USAGE, emsg, "missing port in \"%s\"%s",
                          buf, fnm_lineno(fnm, lineno));
                  return 0;
            }
            hlen = strlen(buf);
            pstr = "-";
      } else {
            hlen = pstr++ - buf;
      }

      if (hostname_len) {
            if (hlen > hostname_len) {
                  dcc_pemsg(EX_NOHOST, emsg,
                          "hostname \"%.16s...\" too long%s",
                          buf, fnm_lineno(fnm, lineno));
                  return 0;
            }
            if (hlen)
                  memcpy(hostname, buf, hlen);
            hostname[hlen] = '\0';
      }
      if (portname_len) {
            hlen = strlen(pstr);
            if (hlen >= portname_len)
                  hlen = portname_len-1;
            if (hlen)
                  memcpy(portname, pstr, hlen);
            portname[hlen] = '\0';
      }

      /* get the port number */
      port = dcc_get_port(emsg, pstr, def_port, fnm, lineno);
      if (port == DCC_GET_PORT_INVALID)
            return 0;

      if (portp)
            *portp = port;
      return line;
}



/* parse a line of the following form
 *    hostname[,port-#] [RTT+adj] [Greylist] [client-ID [password]]
 *  The port-# can be "-" to specifiy the default DCC server port.
 *  If both the client-ID and the password are absent, then the anonymous
 *  client-ID is used.
 *  A null string is assumed if the password is missing.
 */
int                           /* 1=parsed, 0=bad, -1=unknown name */
dcc_parse_srvr_nm(DCC_EMSG emsg,
              DCC_SRVR_NM *nmp,     /* build this entry */
              u_char *pgrey,  /* 1=for greylisting */
              const char *line,     /* from this string */
              const char *fnm, int lineno)      /* that came from here */
{
      char id_buf[12];
      char port_buf[3];
      char *p;
      long l;

      memset(nmp, 0, sizeof(*nmp));

      line = dcc_parse_nm_port(emsg, line, DCC_GREY2PORT(pgrey && *pgrey),
                         nmp->hostname, sizeof(nmp->hostname),
                         &nmp->port, port_buf, sizeof(port_buf),
                         fnm, lineno);
      if (!line)
            return 0;

      for (;;) {
            /* look for greylist flag */
            if (!CSTRCMP(line, "Greylist")
                && (line[STRZ("Greylist")] == '\0'
                  || line[STRZ("Greylist")] == ' '
                  || line[STRZ("Greylist")] == '\t')) {
                  line += STRZ("Greylist")+strspn(line+STRZ("Greylist"),
                                          DCC_WHITESPACE);
                  if (pgrey)
                        *pgrey = 1;
                  if (port_buf[0] == '\0' || !strcmp(port_buf, "-"))
                        nmp->port = htons(DCC_GREY_PORT);
                  continue;
            }

            /* look for optional RTT adjustment */
            if (CSTRCMP(line, "rtt"))
                  break;
            line += STRZ("rtt")+strspn(line+STRZ("rtt"), DCC_WHITESPACE);
            l = strtol(line, &p, 10);
            if (p != line) {
                  int wsp = strspn(p, DCC_WHITESPACE);
                  if (!CSTRCMP(p+wsp, "ms"))
                        p += wsp+STRZ("ms");
            }
            if (p == line
                || (*p != '\0' && *p != ' ' && *p != '\t')) {
                  dcc_pemsg(EX_DATAERR, emsg,
                          "invalid RTT adjustment%s",
                          fnm_lineno(fnm, lineno));
                  return 0;
            }
            if (l < -DCC_RTT_ADJ_MAX/1000) {
                  l = -DCC_RTT_ADJ_MAX/1000;
            } else if (l > DCC_RTT_ADJ_MAX/1000) {
                  l = DCC_RTT_ADJ_MAX/1000;
            }
            nmp->rtt_adj = l*1000;
            line = p+strspn(p, DCC_WHITESPACE);
      }

      /* get the client-ID */
      line = dcc_parse_word(emsg, id_buf, sizeof(id_buf),
                        line, "client-ID", fnm, lineno);
      if (!line)
            return 0;
      if (id_buf[0] == '\0') {
            nmp->clnt_id = DCC_ID_ANON;
      } else {
            nmp->clnt_id = dcc_get_id(emsg, id_buf, fnm, lineno);
            if (nmp->clnt_id == DCC_ID_INVALID)
                  return 0;
            if (nmp->clnt_id < DCC_CLNT_ID_MIN
                && nmp->clnt_id != DCC_ID_ANON) {
                  dcc_pemsg(EX_DATAERR, emsg,
                          "server-ID %d is not a client-ID",
                          nmp->clnt_id);
                  return 0;
            }
      }

      /* allow null password only for anonymous clients
       * clients of greylist servers cannot be anonymous */
      if (nmp->clnt_id == DCC_ID_ANON) {
            if (*line != '\0') {
                  dcc_pemsg(EX_DATAERR, emsg,
                          "password invalid for %s"
                          " with anonymous client-ID%s",
                          nmp->hostname,
                          fnm_lineno(fnm, lineno));
                  return 0;
            }
            return 1;
      }

      if (*line == '\0') {
            dcc_pemsg(EX_DATAERR, emsg,
                    "invalid null password for client-ID %d for %s%s",
                    nmp->clnt_id, nmp->hostname,
                    fnm_lineno(fnm, lineno));
            return 0;
      }

      memset(nmp->passwd, 0, sizeof(nmp->passwd));
      line = dcc_parse_word(emsg, nmp->passwd, sizeof(nmp->passwd),
                        line, "passwd", fnm, lineno);
      if (!line)
            return 0;
      if (nmp->passwd[0] == '\0' || *line != '\0') {
            dcc_pemsg(EX_DATAERR, emsg,
                    "invalid password server %s, client-ID %d%s",
                    nmp->hostname, nmp->clnt_id,
                    fnm_lineno(fnm, lineno));
            return 0;
      }

      return 1;
}

Generated by  Doxygen 1.6.0   Back to index