comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:c7f6b056b673
1 /* Distributed Checksum Clearinghouse
2 *
3 * Copyright (c) 2008 by Rhyolite Software, LLC
4 *
5 * This agreement is not applicable to any entity which sells anti-spam
6 * solutions to others or provides an anti-spam solution as part of a
7 * security solution sold to other entities, or to a private network
8 * which employs the DCC or uses data provided by operation of the DCC
9 * but does not provide corresponding data to other users.
10 *
11 * Permission to use, copy, modify, and distribute this software without
12 * changes for any purpose with or without fee is hereby granted, provided
13 * that the above copyright notice and this permission notice appear in all
14 * copies and any distributed versions or copies are either unchanged
15 * or not called anything similar to "DCC" or "Distributed Checksum
16 * Clearinghouse".
17 *
18 * Parties not eligible to receive a license under this agreement can
19 * obtain a commercial license to use DCC by contacting Rhyolite Software
20 * at sales@rhyolite.com.
21 *
22 * A commercial license would be for Distributed Checksum and Reputation
23 * Clearinghouse software. That software includes additional features. This
24 * free license for Distributed ChecksumClearinghouse Software does not in any
25 * way grant permision to use Distributed Checksum and Reputation Clearinghouse
26 * software
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
29 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
30 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
31 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
32 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
33 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
34 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
35 * SOFTWARE.
36 *
37 * Rhyolite Software DCC 1.3.103-1.47 $Revision$
38 */
39
40 #include "dcc_clnt.h"
41
42
43 /* open a file of server names, ports, and so forth */
44 FILE *
45 dcc_open_srvr_nm(DCC_EMSG emsg, const char *nm)
46 {
47 FILE *f;
48 DCC_PATH path;
49
50 f = fopen(nm, "r");
51 if (!f) {
52 dcc_pemsg(EX_NOINPUT, emsg,
53 "fopen(%s): %s", fnm2abs_err(path, nm), ERROR_STR());
54 return 0;
55 }
56
57 /* the file contains passwords,
58 * so refuse to use it if everyone can read it */
59 if (!dcc_ck_private(emsg, 0, nm, fileno(f))) {
60 fclose(f);
61 return 0;
62 }
63 return f;
64 }
65
66
67
68 /* get "hostname,port" string from the start of a line */
69 const char * /* 0=bad, rest of line if ok */
70 dcc_parse_nm_port(DCC_EMSG emsg,
71 const char *line0,
72 u_int def_port, /* default or DCC_GET_PORT_INVALID */
73 char *hostname, /* put host name here */
74 u_int hostname_len,
75 u_int16_t *portp, /* put port # in network byte order */
76 char *portname, /* put port name here */
77 u_int portname_len,
78 const char *fnm, int lno) /* configuration file source */
79 {
80 DCC_FNM_LNO_BUF fnm_buf;
81 char buf[DCC_MAXDOMAINLEN+1+MAXPORTNAMELEN+1]; /* "name,#\0" */
82 const char *line;
83 const char *pstr;
84 u_int port;
85 u_int hlen;
86
87
88 /* get both parameters */
89 line = dcc_parse_word(emsg, buf, sizeof(buf), line0,
90 "hostname,port", fnm, lno);
91 if (!line)
92 return 0;
93
94 /* get the hostname and separate the port number */
95 pstr = strchr(buf, ',');
96 if (!pstr) {
97 if (def_port == DCC_GET_PORT_INVALID) {
98 dcc_pemsg(EX_USAGE, emsg, "missing port in \"%s\"%s",
99 buf, fnm_lno(&fnm_buf, fnm, lno));
100 return 0;
101 }
102 hlen = strlen(buf);
103 pstr = "-";
104 } else {
105 hlen = pstr++ - buf;
106 }
107
108 if (hostname_len) {
109 memset(hostname, 0, hostname_len);
110 if (hlen >= hostname_len) {
111 dcc_pemsg(EX_NOHOST, emsg,
112 "hostname \"%.16s...\" too long%s",
113 buf, fnm_lno(&fnm_buf, fnm, lno));
114 return 0;
115 }
116 if (hlen)
117 memcpy(hostname, buf, hlen);
118 }
119 if (portname_len) {
120 memset(portname, 0, portname_len);
121 hlen = strlen(pstr);
122 if (hlen >= portname_len)
123 hlen = portname_len-1;
124 if (hlen)
125 memcpy(portname, pstr, hlen);
126 }
127
128 /* get the port number */
129 port = dcc_get_port(emsg, pstr, def_port, fnm, lno);
130 if (port == DCC_GET_PORT_INVALID)
131 return 0;
132
133 if (portp)
134 *portp = port;
135 return line;
136 }
137
138
139
140 /* parse a line of the following form
141 * hostname[,port-#] [RTT+adj] [Greylist] [client-ID [password]]
142 * The port-# can be "-" to specifiy the default DCC server port.
143 * If both the client-ID and the password are absent, then the anonymous
144 * client-ID is used.
145 * A null string is assumed if the password is missing.
146 */
147 int /* 1=parsed, 0=bad, -1=unknown name */
148 dcc_parse_srvr_nm(DCC_EMSG emsg,
149 DCC_SRVR_NM *nmp, /* build this entry */
150 u_char *pgrey, /* 1=for greylisting */
151 const char *line, /* from this string */
152 const char *fnm, int lno) /* that came from here */
153 {
154 DCC_FNM_LNO_BUF fnm_buf;
155 char id_buf[12];
156 char port_buf[3];
157 char *p;
158 long l;
159
160 memset(nmp, 0, sizeof(DCC_SRVR_NM));
161
162 line = dcc_parse_nm_port(emsg, line, DCC_GREY2PORT(pgrey && *pgrey),
163 nmp->hostname, sizeof(nmp->hostname),
164 &nmp->port, port_buf, sizeof(port_buf),
165 fnm, lno);
166 if (!line)
167 return 0;
168
169 for (;;) {
170 /* look for greylist flag */
171 if (!CLITCMP(line, "greylist")
172 && (line[LITZ("greylist")] == '\0'
173 || line[LITZ("greylist")] == ' '
174 || line[LITZ("greylist")] == '\t')) {
175 line += LITZ("greylist")+strspn(line+LITZ("greylist"),
176 DCC_WHITESPACE);
177 if (pgrey)
178 *pgrey = 1;
179 if (port_buf[0] == '\0' || !strcmp(port_buf, "-"))
180 nmp->port = htons(DCC_GREY_PORT);
181 continue;
182 }
183
184 /* look for optional RTT adjustment */
185 if (CLITCMP(line, "rtt"))
186 break;
187 line += LITZ("rtt")+strspn(line+LITZ("rtt"), DCC_WHITESPACE);
188 l = strtol(line, &p, 10);
189 if (p != line) {
190 int wsp = strspn(p, DCC_WHITESPACE);
191 if (!CLITCMP(p+wsp, "ms"))
192 p += wsp+LITZ("ms");
193 }
194 if (p == line
195 || (*p != '\0' && *p != ' ' && *p != '\t')) {
196 dcc_pemsg(EX_DATAERR, emsg,
197 "invalid RTT adjustment%s",
198 fnm_lno(&fnm_buf, fnm, lno));
199 return 0;
200 }
201 if (l < -DCC_RTT_ADJ_MAX/1000) {
202 l = -DCC_RTT_ADJ_MAX/1000;
203 } else if (l > DCC_RTT_ADJ_MAX/1000) {
204 l = DCC_RTT_ADJ_MAX/1000;
205 }
206 nmp->rtt_adj = l*1000;
207 line = p+strspn(p, DCC_WHITESPACE);
208 }
209
210 /* get the client-ID */
211 line = dcc_parse_word(emsg, id_buf, sizeof(id_buf),
212 line, "client-ID", fnm, lno);
213 if (!line)
214 return 0;
215 if (id_buf[0] == '\0') {
216 nmp->clnt_id = DCC_ID_ANON;
217 } else {
218 nmp->clnt_id = dcc_get_id(emsg, id_buf, fnm, lno);
219 if (nmp->clnt_id == DCC_ID_INVALID)
220 return 0;
221 if (nmp->clnt_id < DCC_CLNT_ID_MIN
222 && nmp->clnt_id != DCC_ID_ANON) {
223 dcc_pemsg(EX_DATAERR, emsg,
224 "server-ID %d is not a client-ID",
225 nmp->clnt_id);
226 return 0;
227 }
228 }
229
230 /* allow null password only for anonymous clients
231 * clients of greylist servers cannot be anonymous */
232 if (nmp->clnt_id == DCC_ID_ANON) {
233 if (*line != '\0') {
234 dcc_pemsg(EX_DATAERR, emsg,
235 "password invalid for %s"
236 " with anonymous client-ID%s",
237 nmp->hostname,
238 fnm_lno(&fnm_buf, fnm, lno));
239 return 0;
240 }
241 return 1;
242 }
243
244 if (*line == '\0') {
245 dcc_pemsg(EX_DATAERR, emsg,
246 "invalid null password for client-ID %d for %s%s",
247 nmp->clnt_id, nmp->hostname,
248 fnm_lno(&fnm_buf, fnm, lno));
249 return 0;
250 }
251
252 line = parse_passwd(emsg, nmp->passwd, line, "passwd", fnm, lno);
253 if (!line)
254 return 0;
255 if (nmp->passwd[0] == '\0' || *line != '\0') {
256 dcc_pemsg(EX_DATAERR, emsg,
257 "invalid password server %s, client-ID %d%s",
258 nmp->hostname, nmp->clnt_id,
259 fnm_lno(&fnm_buf, fnm, lno));
260 return 0;
261 }
262
263 return 1;
264 }