2 * Copyright (c) 1987, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 #include <pcap.h> // for PCAP_ERRBUF_SIZE
46 #include "sockutils.h" // for SOCK_DEBUG_MESSAGE
47 #include "portability.h"
49 #include "config_params.h" // configuration file parameters
51 #include "rpcap-protocol.h"
57 #define PARAM_ACTIVECLIENT "ActiveClient"
58 #define PARAM_PASSIVECLIENT "PassiveClient"
59 #define PARAM_NULLAUTHPERMIT "NullAuthPermit"
61 static char *skipws(char *ptr
);
63 void fileconf_read(void)
66 char msg
[PCAP_ERRBUF_SIZE
+ 1];
67 unsigned int num_active_clients
;
69 if ((fp
= fopen(loadfile
, "r")) != NULL
)
71 char line
[MAX_LINE
+ 1];
75 num_active_clients
= 0;
78 while (fgets(line
, MAX_LINE
, fp
) != NULL
)
88 linelen
= strlen(line
);
89 if (line
[linelen
- 1] != '\n')
94 // Either the line doesn't fit in
95 // the buffer, or we got an EOF
96 // before the EOL. Assume it's the
99 rpcapd_log(LOGPRIO_ERROR
,
100 "%s, line %u is longer than %u characters",
101 loadfile
, lineno
, MAX_LINE
);
104 // Eat characters until we get an NL.
106 while ((c
= getc(fp
)) != '\n')
113 // Try the next line.
120 // Skip leading white space, if any.
130 // Is the next character a "#"? If so, this
131 // line is a comment; skip to the next line.
137 // Is the next character alphabetic? If not,
138 // this isn't a valid parameter name.
140 if (!isascii(*ptr
) || !isalpha(*ptr
))
142 rpcapd_log(LOGPRIO_ERROR
,
143 "%s, line %u doesn't have a valid parameter name",
149 // Grab the first token, which is made of
150 // alphanumerics, underscores, and hyphens.
151 // That's the name of the parameter being set.
154 while (isascii(*ptr
) &&
155 (isalnum(*ptr
) || *ptr
== '-' || *ptr
== '_'))
159 // Skip over white space, if any.
162 if (ptr
== NULL
|| *ptr
!= '=')
165 // We hit the end of the line before
166 // finding a non-white space character,
167 // or we found one but it's not an "=".
168 // That means there's no "=", so this
169 // line is invalid. Complain and skip
172 rpcapd_log(LOGPRIO_ERROR
,
173 "%s, line %u has a parameter but no =",
179 // We found the '='; set it to '\0', and skip
185 // Skip past any white space after the "=".
191 // The value is empty.
193 rpcapd_log(LOGPRIO_ERROR
,
194 "%s, line %u has a parameter but no value",
200 // OK, what parameter is this?
202 if (strcmp(param
, PARAM_ACTIVECLIENT
) == 0) {
204 // Add this to the list of active clients.
206 char *address
, *port
;
209 // We can't have more than MAX_ACTIVE_LIST
212 if (num_active_clients
>= MAX_ACTIVE_LIST
)
215 // Too many entries for the active
216 // client list. Complain and
219 rpcapd_log(LOGPRIO_ERROR
,
220 "%s, line %u has an %s parameter, but we already have %u active clients",
221 loadfile
, lineno
, PARAM_ACTIVECLIENT
,
228 // It's terminated by a host list separator
229 // *or* a #; there *shouldn't* be a #, as
230 // that starts a comment, and that would
231 // mean that we have no port.
234 toklen
= strcspn(ptr
, RPCAP_HOSTLIST_SEP
"#");
235 ptr
+= toklen
; // skip to the terminator
239 (isspace(*ptr
) || *ptr
== '#' || *ptr
== '\0'))
242 // The first character it saw
243 // was a whitespace character
244 // or a comment character.
245 // This means that there's
248 rpcapd_log(LOGPRIO_ERROR
,
249 "%s, line %u has a parameter but no value",
255 // This means that the first
256 // character it saw was a
257 // separator. This means that
258 // there's no address in the
259 // value, just a port.
261 rpcapd_log(LOGPRIO_ERROR
,
262 "%s, line %u has an %s parameter with a value containing no address",
263 loadfile
, lineno
, PARAM_ACTIVECLIENT
);
269 // Null-terminate the address, and skip past
275 // Skip any white space following the
276 // separating character.
282 // The value is empty, so there's
283 // no port in the value.
285 rpcapd_log(LOGPRIO_ERROR
,
286 "%s, line %u has an %s parameter with a value containing no port",
287 loadfile
, lineno
, PARAM_ACTIVECLIENT
);
293 // We look for a white space character
294 // or a # as a terminator; the # introduces
295 // a comment that runs to the end of the
299 toklen
= strcspn(ptr
, " \t#\r\n");
304 // The value is empty, so there's
305 // no port in the value.
307 rpcapd_log(LOGPRIO_ERROR
,
308 "%s, line %u has an %s parameter with a value containing no port",
309 loadfile
, lineno
, PARAM_ACTIVECLIENT
);
314 // Null-terminate the port, and skip past
318 result
= strlcpy(activelist
[num_active_clients
].address
, address
, sizeof(activelist
[num_active_clients
].address
));
319 if (result
>= sizeof(activelist
[num_active_clients
].address
))
324 rpcapd_log(LOGPRIO_ERROR
,
325 "%s, line %u has an %s parameter with an address with more than %u characters",
326 loadfile
, lineno
, PARAM_ACTIVECLIENT
,
327 (unsigned int)(sizeof(activelist
[num_active_clients
].address
) - 1));
330 if (strcmp(port
, "DEFAULT") == 0) // the user choose a custom port
331 result
= strlcpy(activelist
[num_active_clients
].port
, RPCAP_DEFAULT_NETPORT_ACTIVE
, sizeof(activelist
[num_active_clients
].port
));
333 result
= strlcpy(activelist
[num_active_clients
].port
, port
, sizeof(activelist
[num_active_clients
].port
));
334 if (result
>= sizeof(activelist
[num_active_clients
].address
))
339 rpcapd_log(LOGPRIO_ERROR
,
340 "%s, line %u has an %s parameter with an port with more than %u characters",
341 loadfile
, lineno
, PARAM_ACTIVECLIENT
,
342 (unsigned int)(sizeof(activelist
[num_active_clients
].port
) - 1));
346 num_active_clients
++;
348 else if (strcmp(param
, PARAM_PASSIVECLIENT
) == 0)
355 // We look for a white space character
356 // or a # as a terminator; the # introduces
357 // a comment that runs to the end of the
361 toklen
= strcspn(ptr
, " \t#\r\n");
365 // The first character it saw
366 // was a whitespace character
367 // or a comment character.
368 // This means that there's
371 rpcapd_log(LOGPRIO_ERROR
,
372 "%s, line %u has a parameter but no value",
380 // Append this to the host list.
381 // Save the curren end-of-string for the
382 // host list, in case the new host doesn't
383 // fit, so that we can discard the partially-
386 eos
= hostlist
+ strlen(hostlist
);
390 // The list is not empty, so prepend
391 // a comma before adding this host.
393 result
= strlcat(hostlist
, ",", sizeof(hostlist
));
394 if (result
>= sizeof(hostlist
))
397 // It didn't fit. Discard
398 // the comma (which wasn't
399 // added, but...), complain,
400 // and ignore this line.
403 rpcapd_log(LOGPRIO_ERROR
,
404 "%s, line %u has a %s parameter with a host name that doesn't fit",
405 loadfile
, lineno
, PARAM_PASSIVECLIENT
);
409 result
= strlcat(hostlist
, host
, sizeof(hostlist
));
410 if (result
>= sizeof(hostlist
))
413 // It didn't fit. Discard the comma,
414 // complain, and ignore this line.
417 rpcapd_log(LOGPRIO_ERROR
,
418 "%s, line %u has a %s parameter with a host name that doesn't fit",
419 loadfile
, lineno
, PARAM_PASSIVECLIENT
);
423 else if (strcmp(param
, PARAM_NULLAUTHPERMIT
) == 0)
429 // We look for a white space character
430 // or a # as a terminator; the # introduces
431 // a comment that runs to the end of the
435 toklen
= strcspn(ptr
, " \t#\r\n");
440 // The first character it saw
441 // was a whitespace character
442 // or a comment character.
443 // This means that there's
446 rpcapd_log(LOGPRIO_ERROR
,
447 "%s, line %u has a parameter but no value",
454 // XXX - should we complain if it's
455 // neither "yes" nor "no"?
457 if (strcmp(setting
, "YES") == 0)
464 rpcapd_log(LOGPRIO_ERROR
,
465 "%s, line %u has an unknown parameter %s",
466 loadfile
, lineno
, param
);
472 // clear the remaining fields of the active list
473 for (int i
= num_active_clients
; i
< MAX_ACTIVE_LIST
; i
++)
475 activelist
[i
].address
[0] = 0;
476 activelist
[i
].port
[0] = 0;
477 num_active_clients
++;
480 pcap_snprintf(msg
, PCAP_ERRBUF_SIZE
, "New passive host list: %s\n\n", hostlist
);
481 SOCK_DEBUG_MESSAGE(msg
);
486 int fileconf_save(const char *savefile
)
490 if ((fp
= fopen(savefile
, "w")) != NULL
)
492 char *token
; /*, *port;*/ // temp, needed to separate items into the hostlist
493 char temphostlist
[MAX_HOST_LIST
+ 1];
497 fprintf(fp
, "# Configuration file help.\n\n");
499 // Save list of clients which are allowed to connect to us in passive mode
500 fprintf(fp
, "# Hosts which are allowed to connect to this server (passive mode)\n");
501 fprintf(fp
, "# Format: PassiveClient = <name or address>\n\n");
503 strncpy(temphostlist
, hostlist
, MAX_HOST_LIST
);
504 temphostlist
[MAX_HOST_LIST
] = 0;
506 token
= pcap_strtok_r(temphostlist
, RPCAP_HOSTLIST_SEP
, &lasts
);
509 fprintf(fp
, "%s = %s\n", PARAM_PASSIVECLIENT
, token
);
510 token
= pcap_strtok_r(NULL
, RPCAP_HOSTLIST_SEP
, &lasts
);
514 // Save list of clients which are allowed to connect to us in active mode
516 fprintf(fp
, "# Hosts to which this server is trying to connect to (active mode)\n");
517 fprintf(fp
, "# Format: ActiveClient = <name or address>, <port | DEFAULT>\n\n");
520 while ((i
< MAX_ACTIVE_LIST
) && (activelist
[i
].address
[0] != 0))
522 fprintf(fp
, "%s = %s, %s\n", PARAM_ACTIVECLIENT
,
523 activelist
[i
].address
, activelist
[i
].port
);
527 // Save if we want to permit NULL authentication
529 fprintf(fp
, "# Permit NULL authentication: YES or NO\n\n");
531 fprintf(fp
, "%s = %s\n", PARAM_NULLAUTHPERMIT
,
532 nullAuthAllowed
? "YES" : "NO");
545 // Skip over white space.
546 // If we hit a CR or LF, return NULL, otherwise return a pointer to
547 // the first non-white space character. Replace white space characters
548 // other than CR or LF with '\0', so that, if we're skipping white space
549 // after a token, the token is null-terminated.
551 static char *skipws(char *ptr
)
553 while (isascii(*ptr
) && isspace(*ptr
)) {
554 if (*ptr
== '\r' || *ptr
== '\n')