Mercurial > notdcc
diff dcclib/parse_srvr_nm.c @ 0:c7f6b056b673
First import of vendor version
author | Peter Gervai <grin@grin.hu> |
---|---|
date | Tue, 10 Mar 2009 13:49:58 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dcclib/parse_srvr_nm.c Tue Mar 10 13:49:58 2009 +0100 @@ -0,0 +1,264 @@ +/* Distributed Checksum Clearinghouse + * + * Copyright (c) 2008 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 without + * changes for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice appear in all + * copies and any distributed versions or copies are either unchanged + * or not called anything similar to "DCC" or "Distributed Checksum + * Clearinghouse". + * + * Parties not eligible to receive a license under this agreement can + * obtain a commercial license to use DCC by contacting Rhyolite Software + * at sales@rhyolite.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.103-1.47 $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; + DCC_PATH path; + + f = fopen(nm, "r"); + if (!f) { + dcc_pemsg(EX_NOINPUT, emsg, + "fopen(%s): %s", fnm2abs_err(path, 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 lno) /* configuration file source */ +{ + DCC_FNM_LNO_BUF fnm_buf; + char buf[DCC_MAXDOMAINLEN+1+MAXPORTNAMELEN+1]; /* "name,#\0" */ + 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, lno); + 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_lno(&fnm_buf, fnm, lno)); + return 0; + } + hlen = strlen(buf); + pstr = "-"; + } else { + hlen = pstr++ - buf; + } + + if (hostname_len) { + memset(hostname, 0, hostname_len); + if (hlen >= hostname_len) { + dcc_pemsg(EX_NOHOST, emsg, + "hostname \"%.16s...\" too long%s", + buf, fnm_lno(&fnm_buf, fnm, lno)); + return 0; + } + if (hlen) + memcpy(hostname, buf, hlen); + } + if (portname_len) { + memset(portname, 0, portname_len); + hlen = strlen(pstr); + if (hlen >= portname_len) + hlen = portname_len-1; + if (hlen) + memcpy(portname, pstr, hlen); + } + + /* get the port number */ + port = dcc_get_port(emsg, pstr, def_port, fnm, lno); + 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 lno) /* that came from here */ +{ + DCC_FNM_LNO_BUF fnm_buf; + char id_buf[12]; + char port_buf[3]; + char *p; + long l; + + memset(nmp, 0, sizeof(DCC_SRVR_NM)); + + line = dcc_parse_nm_port(emsg, line, DCC_GREY2PORT(pgrey && *pgrey), + nmp->hostname, sizeof(nmp->hostname), + &nmp->port, port_buf, sizeof(port_buf), + fnm, lno); + if (!line) + return 0; + + for (;;) { + /* look for greylist flag */ + if (!CLITCMP(line, "greylist") + && (line[LITZ("greylist")] == '\0' + || line[LITZ("greylist")] == ' ' + || line[LITZ("greylist")] == '\t')) { + line += LITZ("greylist")+strspn(line+LITZ("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 (CLITCMP(line, "rtt")) + break; + line += LITZ("rtt")+strspn(line+LITZ("rtt"), DCC_WHITESPACE); + l = strtol(line, &p, 10); + if (p != line) { + int wsp = strspn(p, DCC_WHITESPACE); + if (!CLITCMP(p+wsp, "ms")) + p += wsp+LITZ("ms"); + } + if (p == line + || (*p != '\0' && *p != ' ' && *p != '\t')) { + dcc_pemsg(EX_DATAERR, emsg, + "invalid RTT adjustment%s", + fnm_lno(&fnm_buf, fnm, lno)); + 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, lno); + 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, lno); + 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_lno(&fnm_buf, fnm, lno)); + 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_lno(&fnm_buf, fnm, lno)); + return 0; + } + + line = parse_passwd(emsg, nmp->passwd, line, "passwd", fnm, lno); + 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_lno(&fnm_buf, fnm, lno)); + return 0; + } + + return 1; +}