Line data Source code
1 : /*********************************************************************
2 : *
3 : * File : $Source: /cvsroot/ijbswa/current/loadcfg.c,v $
4 : *
5 : * Purpose : Loads settings from the configuration file into
6 : * global variables. This file contains both the
7 : * routine to load the configuration and the global
8 : * variables it writes to.
9 : *
10 : * Copyright : Written by and Copyright (C) 2001-2017 the
11 : * Privoxy team. https://www.privoxy.org/
12 : *
13 : * Based on the Internet Junkbuster originally written
14 : * by and Copyright (C) 1997 Anonymous Coders and
15 : * Junkbusters Corporation. http://www.junkbusters.com
16 : *
17 : * This program is free software; you can redistribute it
18 : * and/or modify it under the terms of the GNU General
19 : * Public License as published by the Free Software
20 : * Foundation; either version 2 of the License, or (at
21 : * your option) any later version.
22 : *
23 : * This program is distributed in the hope that it will
24 : * be useful, but WITHOUT ANY WARRANTY; without even the
25 : * implied warranty of MERCHANTABILITY or FITNESS FOR A
26 : * PARTICULAR PURPOSE. See the GNU General Public
27 : * License for more details.
28 : *
29 : * The GNU General Public License should be included with
30 : * this file. If not, you can view it at
31 : * http://www.gnu.org/copyleft/gpl.html
32 : * or write to the Free Software Foundation, Inc., 59
33 : * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 : *
35 : *********************************************************************/
36 :
37 :
38 : #include "config.h"
39 :
40 : #include <stdio.h>
41 : #include <sys/types.h>
42 : #include <stdlib.h>
43 : #include <string.h>
44 : #include <signal.h>
45 : #include <fcntl.h>
46 : #include <errno.h>
47 : #include <ctype.h>
48 : #include <assert.h>
49 :
50 : #ifdef _WIN32
51 :
52 : # ifndef STRICT
53 : # define STRICT
54 : # endif
55 : # include <winsock2.h>
56 : # include <windows.h>
57 :
58 : # include "win32.h"
59 : # ifndef _WIN_CONSOLE
60 : # include "w32log.h"
61 : # endif /* ndef _WIN_CONSOLE */
62 :
63 : #else /* ifndef _WIN32 */
64 :
65 : # include <unistd.h>
66 : # include <sys/wait.h>
67 : # include <sys/time.h>
68 : # include <sys/stat.h>
69 : # include <signal.h>
70 :
71 : #endif
72 :
73 : #include "project.h"
74 : #include "loadcfg.h"
75 : #include "list.h"
76 : #include "jcc.h"
77 : #include "filters.h"
78 : #include "loaders.h"
79 : #include "miscutil.h"
80 : #include "errlog.h"
81 : #include "ssplit.h"
82 : #include "encode.h"
83 : #include "urlmatch.h"
84 : #include "cgi.h"
85 : #include "gateway.h"
86 : #ifdef FEATURE_CLIENT_TAGS
87 : #include "client-tags.h"
88 : #endif
89 :
90 : /*
91 : * Default number of seconds after which an
92 : * open connection will no longer be reused.
93 : */
94 : #define DEFAULT_KEEP_ALIVE_TIMEOUT 180
95 :
96 : /*
97 : * Default backlog passed to listen().
98 : */
99 : #define DEFAULT_LISTEN_BACKLOG 128
100 :
101 : #ifdef FEATURE_TOGGLE
102 : /* Privoxy is enabled by default. */
103 : int global_toggle_state = 1;
104 : #endif /* def FEATURE_TOGGLE */
105 :
106 : /* The filename of the configfile */
107 : const char *configfile = NULL;
108 :
109 : /*
110 : * CGI functions will later need access to the invocation args,
111 : * so we will make argc and argv global.
112 : */
113 : int Argc = 0;
114 : char * const * Argv = NULL;
115 :
116 : static struct file_list *current_configfile = NULL;
117 :
118 :
119 : /*
120 : * This takes the "cryptic" hash of each keyword and aliases them to
121 : * something a little more readable. This also makes changing the
122 : * hash values easier if they should change or the hash algorithm changes.
123 : * To find out the hash for a new directive put it in the config file
124 : * and read the number from the error message in the log).
125 : *
126 : * Please keep this list sorted alphabetically (but with the Windows
127 : * console and GUI specific options last).
128 : */
129 :
130 : #define hash_actions_file 1196306641U /* "actionsfile" */
131 : #define hash_accept_intercepted_requests 1513024973U /* "accept-intercepted-requests" */
132 : #define hash_admin_address 4112573064U /* "admin-address" */
133 : #define hash_allow_cgi_request_crunching 258915987U /* "allow-cgi-request-crunching" */
134 : #define hash_buffer_limit 1881726070U /* "buffer-limit */
135 : #define hash_ca_cert_file 1622923720U /* "ca-cert-file" */
136 : #define hash_ca_directory 1623615670U /* "ca-directory" */
137 : #define hash_ca_key_file 1184187891U /* "ca-key-file" */
138 : #define hash_ca_password 1184543320U /* "ca-password" */
139 : #define hash_certificate_directory 1367994217U /* "certificate-directory" */
140 : #define hash_cipher_list 1225729316U /* "cipher-list" */
141 : #define hash_client_header_order 2701453514U /* "client-header-order" */
142 : #define hash_client_specific_tag 3353703383U /* "client-specific-tag" */
143 : #define hash_client_tag_lifetime 3239141416U /* "client-tag-lifetime" */
144 : #define hash_compression_level 2464423563U /* "compression-level" */
145 : #define hash_confdir 1978389U /* "confdir" */
146 : #define hash_connection_sharing 1348841265U /* "connection-sharing" */
147 : #define hash_cors_allowed_origin 2769345637U /* "cors-allowed-origin" */
148 : #define hash_debug 78263U /* "debug" */
149 : #define hash_default_server_timeout 2530089913U /* "default-server-timeout" */
150 : #define hash_deny_access 1227333715U /* "deny-access" */
151 : #define hash_enable_accept_filter 2909040407U /* "enable-accept-filter" */
152 : #define hash_enable_edit_actions 2517097536U /* "enable-edit-actions" */
153 : #define hash_enable_compression 3943696946U /* "enable-compression" */
154 : #define hash_enable_proxy_authentication_forwarding 4040610791U /* enable-proxy-authentication-forwarding */
155 : #define hash_enable_remote_toggle 2979744683U /* "enable-remote-toggle" */
156 : #define hash_enable_remote_http_toggle 110543988U /* "enable-remote-http-toggle" */
157 : #define hash_enforce_blocks 1862427469U /* "enforce-blocks" */
158 : #define hash_filterfile 250887266U /* "filterfile" */
159 : #define hash_forward 2029845U /* "forward" */
160 : #define hash_forward_socks4 3963965521U /* "forward-socks4" */
161 : #define hash_forward_socks4a 2639958518U /* "forward-socks4a" */
162 : #define hash_forward_socks5 3963965522U /* "forward-socks5" */
163 : #define hash_forward_socks5t 2639958542U /* "forward-socks5t" */
164 : #define hash_forwarded_connect_retries 101465292U /* "forwarded-connect-retries" */
165 : #define hash_handle_as_empty_returns_ok 1444873247U /* "handle-as-empty-doc-returns-ok" */
166 : #define hash_hostname 10308071U /* "hostname" */
167 : #define hash_keep_alive_timeout 3878599515U /* "keep-alive-timeout" */
168 : #define hash_listen_address 1255650842U /* "listen-address" */
169 : #define hash_listen_backlog 1255655735U /* "listen-backlog" */
170 : #define hash_logdir 422889U /* "logdir" */
171 : #define hash_logfile 2114766U /* "logfile" */
172 : #define hash_max_client_connections 3595884446U /* "max-client-connections" */
173 : #define hash_permit_access 3587953268U /* "permit-access" */
174 : #define hash_proxy_info_url 3903079059U /* "proxy-info-url" */
175 : #define hash_receive_buffer_size 2880297454U /* "receive-buffer-size */
176 : #define hash_single_threaded 4250084780U /* "single-threaded" */
177 : #define hash_socket_timeout 1809001761U /* "socket-timeout" */
178 : #define hash_split_large_cgi_forms 671658948U /* "split-large-cgi-forms" */
179 : #define hash_suppress_blocklists 1948693308U /* "suppress-blocklists" */
180 : #define hash_templdir 11067889U /* "templdir" */
181 : #define hash_temporary_directory 1824125181U /* "temporary-directory" */
182 : #define hash_tolerate_pipelining 1360286620U /* "tolerate-pipelining" */
183 : #define hash_toggle 447966U /* "toggle" */
184 : #define hash_trust_info_url 430331967U /* "trust-info-url" */
185 : #define hash_trust_x_forwarded_for 2971537414U /* "trust-x-forwarded-for" */
186 : #define hash_trusted_cgi_referrer 4270883427U /* "trusted-cgi-referrer" */
187 : #define hash_trusted_cas_file 2679803024U /* "trusted-cas-files" */
188 : #define hash_trustfile 56494766U /* "trustfile" */
189 : #define hash_usermanual 1416668518U /* "user-manual" */
190 : #define hash_activity_animation 1817904738U /* "activity-animation" */
191 : #define hash_close_button_minimizes 3651284693U /* "close-button-minimizes" */
192 : #define hash_hide_console 2048809870U /* "hide-console" */
193 : #define hash_log_buffer_size 2918070425U /* "log-buffer-size" */
194 : #define hash_log_font_name 2866730124U /* "log-font-name" */
195 : #define hash_log_font_size 2866731014U /* "log-font-size" */
196 : #define hash_log_highlight_messages 4032101240U /* "log-highlight-messages" */
197 : #define hash_log_max_lines 2868344173U /* "log-max-lines" */
198 : #define hash_log_messages 2291744899U /* "log-messages" */
199 : #define hash_show_on_task_bar 215410365U /* "show-on-task-bar" */
200 :
201 :
202 : static void savearg(char *command, char *argument, struct configuration_spec * config);
203 : #ifdef FEATURE_CLIENT_TAGS
204 : static void free_client_specific_tags(struct client_tag_spec *tag_list);
205 : #endif
206 :
207 : /*********************************************************************
208 : *
209 : * Function : unload_configfile
210 : *
211 : * Description : Free the config structure and all components.
212 : *
213 : * Parameters :
214 : * 1 : data: struct configuration_spec to unload
215 : *
216 : * Returns : N/A
217 : *
218 : *********************************************************************/
219 0 : static void unload_configfile (void * data)
220 : {
221 0 : struct configuration_spec * config = (struct configuration_spec *)data;
222 0 : struct forward_spec *cur_fwd = config->forward;
223 : int i;
224 :
225 : #ifdef FEATURE_ACL
226 0 : struct access_control_list *cur_acl = config->acl;
227 :
228 0 : while (cur_acl != NULL)
229 : {
230 0 : struct access_control_list * next_acl = cur_acl->next;
231 0 : free(cur_acl);
232 0 : cur_acl = next_acl;
233 : }
234 0 : config->acl = NULL;
235 : #endif /* def FEATURE_ACL */
236 :
237 0 : while (cur_fwd != NULL)
238 : {
239 0 : struct forward_spec * next_fwd = cur_fwd->next;
240 :
241 0 : unload_forward_spec(cur_fwd);
242 :
243 0 : cur_fwd = next_fwd;
244 : }
245 0 : config->forward = NULL;
246 :
247 0 : freez(config->confdir);
248 0 : freez(config->logdir);
249 0 : freez(config->templdir);
250 0 : freez(config->hostname);
251 : #ifdef FEATURE_EXTERNAL_FILTERS
252 0 : freez(config->temporary_directory);
253 : #endif
254 :
255 0 : for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
256 : {
257 0 : freez(config->haddr[i]);
258 : }
259 0 : freez(config->logfile);
260 :
261 0 : for (i = 0; i < MAX_AF_FILES; i++)
262 : {
263 0 : freez(config->actions_file_short[i]);
264 0 : freez(config->actions_file[i]);
265 0 : freez(config->re_filterfile_short[i]);
266 0 : freez(config->re_filterfile[i]);
267 : }
268 :
269 0 : list_remove_all(config->ordered_client_headers);
270 :
271 0 : freez(config->admin_address);
272 0 : freez(config->cors_allowed_origin);
273 0 : freez(config->proxy_info_url);
274 0 : freez(config->proxy_args);
275 0 : freez(config->usermanual);
276 0 : freez(config->trusted_cgi_referrer);
277 :
278 : #ifdef FEATURE_HTTPS_INSPECTION
279 0 : freez(config->ca_password);
280 0 : freez(config->ca_directory);
281 0 : freez(config->ca_cert_file);
282 0 : freez(config->ca_key_file);
283 0 : freez(config->certificate_directory);
284 0 : freez(config->cipher_list);
285 0 : freez(config->trusted_cas_file);
286 : #endif
287 :
288 : #ifdef FEATURE_TRUST
289 0 : freez(config->trustfile);
290 0 : list_remove_all(config->trust_info);
291 : #endif /* def FEATURE_TRUST */
292 :
293 : #ifdef FEATURE_CLIENT_TAGS
294 0 : free_client_specific_tags(config->client_tags);
295 : #endif
296 :
297 0 : freez(config);
298 0 : }
299 :
300 :
301 : #ifdef FEATURE_GRACEFUL_TERMINATION
302 : /*********************************************************************
303 : *
304 : * Function : unload_current_config_file
305 : *
306 : * Description : Unloads current config file - reset to state at
307 : * beginning of program.
308 : *
309 : * Parameters : None
310 : *
311 : * Returns : N/A
312 : *
313 : *********************************************************************/
314 : void unload_current_config_file(void)
315 : {
316 : if (current_configfile)
317 : {
318 : current_configfile->unloader = unload_configfile;
319 : current_configfile = NULL;
320 : }
321 : }
322 : #endif
323 :
324 :
325 : #ifdef FEATURE_CLIENT_TAGS
326 : /*********************************************************************
327 : *
328 : * Function : register_tag
329 : *
330 : * Description : Registers a client-specific-tag and its description
331 : *
332 : * Parameters :
333 : * 1 : config: The tag list
334 : * 2 : name: The name of the client-specific-tag
335 : * 3 : description: The human-readable description for the tag
336 : *
337 : * Returns : N/A
338 : *
339 : *********************************************************************/
340 12392 : static void register_tag(struct client_tag_spec *tag_list,
341 : const char *name, const char *description)
342 : {
343 : struct client_tag_spec *new_tag;
344 : struct client_tag_spec *last_tag;
345 :
346 12392 : last_tag = tag_list;
347 21686 : while (last_tag->next != NULL)
348 : {
349 9294 : last_tag = last_tag->next;
350 : }
351 12392 : if (last_tag->name == NULL)
352 : {
353 : /* First entry */
354 3098 : new_tag = last_tag;
355 : }
356 : else
357 : {
358 9294 : new_tag = zalloc_or_die(sizeof(struct client_tag_spec));
359 : }
360 12392 : new_tag->name = strdup_or_die(name);
361 12392 : new_tag->description = strdup_or_die(description);
362 12392 : if (new_tag != last_tag)
363 : {
364 9294 : last_tag->next = new_tag;
365 : }
366 12392 : }
367 :
368 :
369 : /*********************************************************************
370 : *
371 : * Function : free_client_specific_tags
372 : *
373 : * Description : Frees client-specific tags and their descriptions
374 : *
375 : * Parameters :
376 : * 1 : tag_list: The tag list to free
377 : *
378 : * Returns : N/A
379 : *
380 : *********************************************************************/
381 0 : static void free_client_specific_tags(struct client_tag_spec *tag_list)
382 : {
383 : struct client_tag_spec *this_tag;
384 : struct client_tag_spec *next_tag;
385 :
386 0 : next_tag = tag_list;
387 : do
388 : {
389 0 : this_tag = next_tag;
390 0 : next_tag = next_tag->next;
391 :
392 0 : freez(this_tag->name);
393 0 : freez(this_tag->description);
394 :
395 0 : if (this_tag != tag_list)
396 : {
397 0 : freez(this_tag);
398 : }
399 0 : } while (next_tag != NULL);
400 0 : }
401 : #endif /* def FEATURE_CLIENT_TAGS */
402 :
403 :
404 : /*********************************************************************
405 : *
406 : * Function : parse_numeric_value
407 : *
408 : * Description : Parse the value of a directive that can only have
409 : * a single numeric value. Terminates with a fatal error
410 : * if the value is NULL or not numeric.
411 : *
412 : * Parameters :
413 : * 1 : name: The name of the directive. Used for log messages.
414 : * 2 : value: The value to parse
415 : *
416 : *
417 : * Returns : The numerical value as integer
418 : *
419 : *********************************************************************/
420 65058 : static int parse_numeric_value(const char *name, const char *value)
421 : {
422 : int number;
423 : char *endptr;
424 :
425 65058 : assert(name != NULL);
426 65058 : assert(value != NULL);
427 :
428 65058 : if ((value == NULL) || (*value == '\0'))
429 : {
430 0 : log_error(LOG_LEVEL_FATAL, "Directive %s used without argument", name);
431 : }
432 :
433 65058 : number = (int)strtol(value, &endptr, 0);
434 65058 : if (*endptr != '\0')
435 : {
436 0 : log_error(LOG_LEVEL_FATAL,
437 : "Directive '%s' used with non-numerical value: '%s'", name, value);
438 : }
439 :
440 65058 : return number;
441 :
442 : }
443 :
444 :
445 : /*********************************************************************
446 : *
447 : * Function : parse_toggle_value
448 : *
449 : * Description : Parse the value of a directive that can only be
450 : * enabled or disabled. Terminates with a fatal error
451 : * if the value is NULL or something other than 0 or 1.
452 : *
453 : * Parameters :
454 : * 1 : name: The name of the directive. Used for log messages.
455 : * 2 : value: The value to parse
456 : *
457 : *
458 : * Returns : The numerical toggle state
459 : *
460 : *********************************************************************/
461 43372 : static int parse_toggle_state(const char *name, const char *value)
462 : {
463 : int toggle_state;
464 43372 : assert(name != NULL);
465 43372 : assert(value != NULL);
466 :
467 43372 : if ((value == NULL) || (*value == '\0'))
468 : {
469 0 : log_error(LOG_LEVEL_FATAL, "Directive %s used without argument", name);
470 : }
471 :
472 43372 : toggle_state = atoi(value);
473 :
474 : /*
475 : * Also check the length as atoi() doesn't mind
476 : * garbage after a valid integer, but we do.
477 : */
478 43372 : if (((toggle_state != 0) && (toggle_state != 1)) || (strlen(value) != 1))
479 : {
480 0 : log_error(LOG_LEVEL_FATAL,
481 : "Directive %s used with invalid argument '%s'. Use either '0' or '1'.",
482 : name, value);
483 : }
484 :
485 43372 : return toggle_state;
486 :
487 : }
488 :
489 :
490 : /*********************************************************************
491 : *
492 : * Function : parse_client_header_order
493 : *
494 : * Description : Parse the value of the header-order directive
495 : *
496 : * Parameters :
497 : * 1 : ordered_header_list: List to insert the ordered
498 : * headers into.
499 : * 2 : ordered_headers: The ordered header names separated
500 : * by spaces or tabs.
501 : *
502 : *
503 : * Returns : N/A
504 : *
505 : *********************************************************************/
506 3098 : static void parse_client_header_order(struct list *ordered_header_list, const char *ordered_headers)
507 : {
508 : char *original_headers_copy;
509 : char **vector;
510 : size_t max_segments;
511 : int number_of_headers;
512 : int i;
513 :
514 3098 : assert(ordered_header_list != NULL);
515 3098 : assert(ordered_headers != NULL);
516 :
517 3098 : if (ordered_headers == NULL)
518 : {
519 0 : log_error(LOG_LEVEL_FATAL, "header-order used without argument");
520 : }
521 :
522 : /*
523 : * XXX: This estimate is guaranteed to be high enough as we
524 : * let ssplit() ignore empty fields, but also a bit wasteful.
525 : * The same hack is used in get_last_url() so it looks like
526 : * a real solution is needed.
527 : */
528 3098 : max_segments = strlen(ordered_headers) / 2;
529 3098 : if (max_segments == 0)
530 : {
531 0 : max_segments = 1;
532 : }
533 3098 : vector = malloc_or_die(max_segments * sizeof(char *));
534 :
535 3098 : original_headers_copy = strdup_or_die(ordered_headers);
536 :
537 3098 : number_of_headers = ssplit(original_headers_copy, "\t ", vector, max_segments);
538 3098 : if (number_of_headers == -1)
539 : {
540 0 : log_error(LOG_LEVEL_FATAL, "Failed to split ordered headers");
541 : }
542 :
543 27882 : for (i = 0; i < number_of_headers; i++)
544 : {
545 24784 : if (JB_ERR_OK != enlist(ordered_header_list, vector[i]))
546 : {
547 0 : log_error(LOG_LEVEL_FATAL,
548 0 : "Failed to enlist ordered header: %s", vector[i]);
549 : }
550 : }
551 :
552 3098 : freez(vector);
553 3098 : freez(original_headers_copy);
554 :
555 3098 : return;
556 :
557 : }
558 :
559 :
560 : /*********************************************************************
561 : *
562 : * Function : load_config
563 : *
564 : * Description : Load the config file and all parameters.
565 : *
566 : * XXX: more than thousand lines long
567 : * and thus in serious need of refactoring.
568 : *
569 : * Parameters : None
570 : *
571 : * Returns : The configuration_spec, or NULL on error.
572 : *
573 : *********************************************************************/
574 3098 : struct configuration_spec * load_config(void)
575 : {
576 3098 : char *buf = NULL;
577 : char *p, *q;
578 3098 : FILE *configfp = NULL;
579 3098 : struct configuration_spec * config = NULL;
580 : struct client_state * fake_csp;
581 : struct file_list *fs;
582 3098 : unsigned long linenum = 0;
583 : int i;
584 3098 : char *logfile = NULL;
585 : #ifdef FEATURE_HTTPS_INSPECTION
586 3098 : char *ca_cert_file = NULL;
587 3098 : char *ca_key_file = NULL;
588 3098 : char *ca_directory = NULL;
589 3098 : char *trusted_cas_file = NULL;
590 3098 : char *certificate_directory = NULL;
591 : #endif
592 :
593 3098 : if (!check_file_changed(current_configfile, configfile, &fs))
594 : {
595 : /* No need to load */
596 0 : return ((struct configuration_spec *)current_configfile->f);
597 : }
598 3098 : if (NULL == fs)
599 : {
600 0 : log_error(LOG_LEVEL_FATAL,
601 : "can't check configuration file '%s': %E", configfile);
602 0 : return NULL;
603 : }
604 :
605 3098 : if (NULL != current_configfile)
606 : {
607 0 : log_error(LOG_LEVEL_INFO, "Reloading configuration file '%s'", configfile);
608 : }
609 :
610 : #ifdef FEATURE_TOGGLE
611 3098 : global_toggle_state = 1;
612 : #endif /* def FEATURE_TOGGLE */
613 :
614 3098 : fs->f = config = zalloc_or_die(sizeof(*config));
615 :
616 : /*
617 : * This is backwards from how it's usually done.
618 : * Following the usual pattern, "fs" would be stored in a member
619 : * variable in "csp", and then we'd access "config" from "fs->f",
620 : * using a cast. However, "config" is used so often that a
621 : * cast each time would be very ugly, and the extra indirection
622 : * would waste CPU cycles. Therefore we store "config" in
623 : * "csp->config", and "fs" in "csp->config->config_file_list".
624 : */
625 3098 : config->config_file_list = fs;
626 :
627 : /*
628 : * Set to defaults
629 : */
630 3098 : config->multi_threaded = 1;
631 3098 : config->buffer_limit = 4096 * 1024;
632 3098 : config->receive_buffer_size = BUFFER_SIZE;
633 3098 : config->usermanual = strdup_or_die(USER_MANUAL_URL);
634 3098 : config->proxy_args = strdup_or_die("");
635 3098 : config->forwarded_connect_retries = 0;
636 : #ifdef FEATURE_HTTPS_INSPECTION
637 3098 : config->ca_password = strdup("");
638 3098 : ca_cert_file = strdup("cacert.crt");
639 3098 : ca_key_file = strdup("cakey.pem");
640 3098 : ca_directory = strdup("./CA");
641 3098 : trusted_cas_file = strdup("trustedCAs.pem");
642 3098 : certificate_directory = strdup("./certs");
643 : #endif
644 :
645 : #ifdef FEATURE_CLIENT_TAGS
646 3098 : config->client_tag_lifetime = 60;
647 : #endif
648 3098 : config->trust_x_forwarded_for = 0;
649 : #if defined(FEATURE_ACCEPT_FILTER) && defined(SO_ACCEPTFILTER)
650 : config->enable_accept_filter = 0;
651 : #endif
652 3098 : config->listen_backlog = DEFAULT_LISTEN_BACKLOG;
653 3098 : config->trusted_cgi_referrer = NULL;
654 : /*
655 : * 128 client sockets ought to be enough for everybody who can't
656 : * be bothered to read the documentation to figure out how to
657 : * increase the limit.
658 : */
659 3098 : config->max_client_connections = 128;
660 3098 : config->socket_timeout = 300; /* XXX: Should be a macro. */
661 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
662 3098 : config->default_server_timeout = 0;
663 3098 : config->keep_alive_timeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
664 3098 : config->feature_flags &= ~RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
665 3098 : config->feature_flags &= ~RUNTIME_FEATURE_CONNECTION_SHARING;
666 : #endif
667 3098 : config->feature_flags &= ~RUNTIME_FEATURE_CGI_TOGGLE;
668 3098 : config->feature_flags &= ~RUNTIME_FEATURE_SPLIT_LARGE_FORMS;
669 3098 : config->feature_flags &= ~RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS;
670 3098 : config->feature_flags &= ~RUNTIME_FEATURE_EMPTY_DOC_RETURNS_OK;
671 3098 : config->feature_flags &= ~RUNTIME_FEATURE_FORWARD_PROXY_AUTHENTICATION_HEADERS;
672 : #ifdef FEATURE_COMPRESSION
673 3098 : config->feature_flags &= ~RUNTIME_FEATURE_COMPRESSION;
674 : /*
675 : * XXX: Run some benchmarks to see if there are better default values.
676 : */
677 3098 : config->compression_level = 1;
678 : #endif
679 3098 : config->feature_flags &= ~RUNTIME_FEATURE_TOLERATE_PIPELINING;
680 3098 : config->cors_allowed_origin = NULL;
681 :
682 3098 : configfp = fopen(configfile, "r");
683 3098 : if (NULL == configfp)
684 : {
685 0 : log_error(LOG_LEVEL_FATAL,
686 : "can't open configuration file '%s': %E", configfile);
687 : /* Never get here - LOG_LEVEL_FATAL causes program exit */
688 : }
689 :
690 176586 : while (read_config_line(configfp, &linenum, &buf) != NULL)
691 : {
692 : char cmd[BUFFER_SIZE];
693 : char arg[BUFFER_SIZE];
694 : char tmp[BUFFER_SIZE];
695 : #ifdef FEATURE_ACL
696 : struct access_control_list *cur_acl;
697 : #endif /* def FEATURE_ACL */
698 : struct forward_spec *cur_fwd;
699 : int vec_count;
700 : char *vec[3];
701 : unsigned int directive_hash;
702 :
703 173488 : strlcpy(tmp, buf, sizeof(tmp));
704 :
705 : /* Copy command (i.e. up to space or tab) into cmd */
706 173488 : p = buf;
707 173488 : q = cmd;
708 2518674 : while (*p && (*p != ' ') && (*p != '\t'))
709 : {
710 2345186 : *q++ = *p++;
711 : }
712 173488 : *q = '\0';
713 :
714 : /* Skip over the whitespace in buf */
715 467798 : while (*p && ((*p == ' ') || (*p == '\t')))
716 : {
717 294310 : p++;
718 : }
719 :
720 : /* Copy the argument into arg */
721 173488 : if (strlcpy(arg, p, sizeof(arg)) >= sizeof(arg))
722 : {
723 0 : log_error(LOG_LEVEL_FATAL, "Config line too long: %s", buf);
724 : }
725 :
726 : /* Should never happen, but check this anyway */
727 173488 : if (*cmd == '\0')
728 : {
729 0 : freez(buf);
730 0 : continue;
731 : }
732 :
733 : /* Make sure the command field is lower case */
734 2518674 : for (p = cmd; *p; p++)
735 : {
736 2345186 : if (privoxy_isupper(*p))
737 : {
738 0 : *p = (char)privoxy_tolower(*p);
739 : }
740 : }
741 :
742 173488 : directive_hash = hash_string(cmd);
743 173488 : switch (directive_hash)
744 : {
745 : /* *************************************************************************
746 : * actionsfile actions-file-name
747 : * In confdir by default
748 : * *************************************************************************/
749 6196 : case hash_actions_file :
750 6196 : i = 0;
751 9294 : while ((i < MAX_AF_FILES) && (NULL != config->actions_file[i]))
752 : {
753 3098 : i++;
754 : }
755 :
756 6196 : if (i >= MAX_AF_FILES)
757 : {
758 0 : log_error(LOG_LEVEL_FATAL, "Too many 'actionsfile' directives in config file - limit is %d.\n"
759 : "(You can increase this limit by changing MAX_AF_FILES in project.h and recompiling).",
760 : MAX_AF_FILES);
761 : }
762 6196 : config->actions_file_short[i] = strdup_or_die(arg);
763 6196 : config->actions_file[i] = make_path(config->confdir, arg);
764 :
765 6196 : break;
766 : /* *************************************************************************
767 : * accept-intercepted-requests
768 : * *************************************************************************/
769 3098 : case hash_accept_intercepted_requests:
770 3098 : if (parse_toggle_state(cmd, arg) == 1)
771 : {
772 3098 : config->feature_flags |= RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS;
773 : }
774 : else
775 : {
776 0 : config->feature_flags &= ~RUNTIME_FEATURE_ACCEPT_INTERCEPTED_REQUESTS;
777 : }
778 3098 : break;
779 :
780 : /* *************************************************************************
781 : * admin-address email-address
782 : * *************************************************************************/
783 0 : case hash_admin_address :
784 0 : freez(config->admin_address);
785 0 : config->admin_address = strdup_or_die(arg);
786 0 : break;
787 :
788 : /* *************************************************************************
789 : * allow-cgi-request-crunching
790 : * *************************************************************************/
791 3098 : case hash_allow_cgi_request_crunching:
792 3098 : if (parse_toggle_state(cmd, arg) == 1)
793 : {
794 0 : config->feature_flags |= RUNTIME_FEATURE_CGI_CRUNCHING;
795 : }
796 : else
797 : {
798 3098 : config->feature_flags &= ~RUNTIME_FEATURE_CGI_CRUNCHING;
799 : }
800 3098 : break;
801 :
802 : /* *************************************************************************
803 : * buffer-limit n
804 : * *************************************************************************/
805 3098 : case hash_buffer_limit :
806 3098 : config->buffer_limit = (size_t)(1024 * parse_numeric_value(cmd, arg));
807 3098 : break;
808 :
809 : /* *************************************************************************
810 : * client-header-order header-1 header-2 ... header-n
811 : * *************************************************************************/
812 3098 : case hash_client_header_order:
813 3098 : list_remove_all(config->ordered_client_headers);
814 3098 : parse_client_header_order(config->ordered_client_headers, arg);
815 3098 : break;
816 :
817 : /* *************************************************************************
818 : * client-specific-tag tag-name description
819 : * *************************************************************************/
820 : #ifdef FEATURE_CLIENT_TAGS
821 12392 : case hash_client_specific_tag:
822 : {
823 : char *name;
824 : char *description;
825 :
826 12392 : name = arg;
827 12392 : description = strstr(arg, " ");
828 12392 : if (description == NULL)
829 : {
830 0 : log_error(LOG_LEVEL_FATAL,
831 : "client-specific-tag '%s' lacks a description.", name);
832 : }
833 12392 : *description = '\0';
834 : /*
835 : * The length is limited because we don't want truncated
836 : * HTML caused by the cgi interface using static buffer
837 : * sizes.
838 : */
839 12392 : if (strlen(name) > CLIENT_TAG_LENGTH_MAX)
840 : {
841 0 : log_error(LOG_LEVEL_FATAL,
842 : "client-specific-tag '%s' is longer than %d characters.",
843 : name, CLIENT_TAG_LENGTH_MAX);
844 : }
845 12392 : description++;
846 12392 : register_tag(config->client_tags, name, description);
847 : }
848 12392 : break;
849 : #endif /* def FEATURE_CLIENT_TAGS */
850 :
851 : /* *************************************************************************
852 : * client-tag-lifetime ttl
853 : * *************************************************************************/
854 : #ifdef FEATURE_CLIENT_TAGS
855 3098 : case hash_client_tag_lifetime:
856 : {
857 3098 : int ttl = parse_numeric_value(cmd, arg);
858 3098 : if (0 <= ttl)
859 : {
860 3098 : config->client_tag_lifetime = (unsigned)ttl;
861 : }
862 : else
863 : {
864 0 : log_error(LOG_LEVEL_FATAL,
865 : "client-tag-lifetime can't be negative.");
866 : }
867 3098 : break;
868 : }
869 : #endif /* def FEATURE_CLIENT_TAGS */
870 :
871 : /* *************************************************************************
872 : * confdir directory-name
873 : * *************************************************************************/
874 3098 : case hash_confdir :
875 3098 : freez(config->confdir);
876 3098 : config->confdir = make_path(NULL, arg);
877 3098 : break;
878 :
879 : /* *************************************************************************
880 : * compression-level 0-9
881 : * *************************************************************************/
882 : #ifdef FEATURE_COMPRESSION
883 3098 : case hash_compression_level :
884 : {
885 3098 : int compression_level = parse_numeric_value(cmd, arg);
886 3098 : if (-1 <= compression_level && compression_level <= 9)
887 : {
888 3098 : config->compression_level = compression_level;
889 : }
890 : else
891 : {
892 0 : log_error(LOG_LEVEL_FATAL,
893 : "Invalid compression-level value: %s", arg);
894 : }
895 3098 : break;
896 : }
897 : #endif
898 :
899 : /* *************************************************************************
900 : * connection-sharing (0|1)
901 : * *************************************************************************/
902 : #ifdef FEATURE_CONNECTION_SHARING
903 3098 : case hash_connection_sharing :
904 3098 : if (parse_toggle_state(cmd, arg) == 1)
905 : {
906 0 : config->feature_flags |= RUNTIME_FEATURE_CONNECTION_SHARING;
907 : }
908 : else
909 : {
910 3098 : config->feature_flags &= ~RUNTIME_FEATURE_CONNECTION_SHARING;
911 : }
912 3098 : break;
913 : #endif
914 :
915 : /* *************************************************************************
916 : * cors-allowed-origin http://www.example.org
917 : * *************************************************************************/
918 3098 : case hash_cors_allowed_origin :
919 : /*
920 : * We don't validate the specified referrer as
921 : * it's only used for string comparison.
922 : */
923 3098 : freez(config->cors_allowed_origin);
924 3098 : config->cors_allowed_origin = strdup_or_die(arg);
925 3098 : break;
926 :
927 : /* *************************************************************************
928 : * debug n
929 : * Specifies debug level, multiple values are ORed together.
930 : * *************************************************************************/
931 49568 : case hash_debug :
932 49568 : config->debug |= parse_numeric_value(cmd, arg);
933 49568 : break;
934 :
935 : /* *************************************************************************
936 : * default-server-timeout timeout
937 : * *************************************************************************/
938 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
939 0 : case hash_default_server_timeout :
940 : {
941 0 : int timeout = parse_numeric_value(cmd, arg);
942 0 : if (0 <= timeout)
943 : {
944 0 : config->default_server_timeout = (unsigned int)timeout;
945 : }
946 : else
947 : {
948 0 : log_error(LOG_LEVEL_FATAL,
949 : "Invalid default-server-timeout value: %s", arg);
950 : }
951 0 : break;
952 : }
953 : #endif
954 :
955 : /* *************************************************************************
956 : * deny-access source-ip[/significant-bits] [dest-ip[/significant-bits]]
957 : * *************************************************************************/
958 : #ifdef FEATURE_ACL
959 0 : case hash_deny_access:
960 0 : strlcpy(tmp, arg, sizeof(tmp));
961 0 : vec_count = ssplit(tmp, " \t", vec, SZ(vec));
962 :
963 0 : if ((vec_count != 1) && (vec_count != 2))
964 : {
965 0 : log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
966 : "deny-access directive in configuration file.");
967 0 : string_append(&config->proxy_args,
968 : "<br>\nWARNING: Wrong number of parameters for "
969 : "deny-access directive in configuration file.<br><br>\n");
970 0 : break;
971 : }
972 :
973 : /* allocate a new node */
974 0 : cur_acl = zalloc_or_die(sizeof(*cur_acl));
975 0 : cur_acl->action = ACL_DENY;
976 :
977 0 : if (acl_addr(vec[0], cur_acl->src) < 0)
978 : {
979 0 : log_error(LOG_LEVEL_ERROR, "Invalid source address, port or netmask "
980 : "for deny-access directive in configuration file: \"%s\"", vec[0]);
981 0 : string_append(&config->proxy_args,
982 : "<br>\nWARNING: Invalid source address, port or netmask "
983 : "for deny-access directive in configuration file: \"");
984 0 : string_append(&config->proxy_args,
985 0 : vec[0]);
986 0 : string_append(&config->proxy_args,
987 : "\"<br><br>\n");
988 0 : freez(cur_acl);
989 0 : break;
990 : }
991 0 : if (vec_count == 2)
992 : {
993 0 : if (acl_addr(vec[1], cur_acl->dst) < 0)
994 : {
995 0 : log_error(LOG_LEVEL_ERROR, "Invalid destination address, port or netmask "
996 : "for deny-access directive in configuration file: \"%s\"", vec[1]);
997 0 : string_append(&config->proxy_args,
998 : "<br>\nWARNING: Invalid destination address, port or netmask "
999 : "for deny-access directive in configuration file: \"");
1000 0 : string_append(&config->proxy_args,
1001 0 : vec[1]);
1002 0 : string_append(&config->proxy_args,
1003 : "\"<br><br>\n");
1004 0 : freez(cur_acl);
1005 0 : break;
1006 : }
1007 : }
1008 : #ifdef HAVE_RFC2553
1009 : else
1010 : {
1011 0 : cur_acl->wildcard_dst = 1;
1012 : }
1013 : #endif /* def HAVE_RFC2553 */
1014 :
1015 : /*
1016 : * Add it to the list. Note we reverse the list to get the
1017 : * behaviour the user expects. With both the ACL and
1018 : * actions file, the last match wins. However, the internal
1019 : * implementations are different: The actions file is stored
1020 : * in the same order as the file, and scanned completely.
1021 : * With the ACL, we reverse the order as we load it, then
1022 : * when we scan it we stop as soon as we get a match.
1023 : */
1024 0 : cur_acl->next = config->acl;
1025 0 : config->acl = cur_acl;
1026 :
1027 0 : break;
1028 : #endif /* def FEATURE_ACL */
1029 :
1030 : #if defined(FEATURE_ACCEPT_FILTER) && defined(SO_ACCEPTFILTER)
1031 : /* *************************************************************************
1032 : * enable-accept-filter 0|1
1033 : * *************************************************************************/
1034 : case hash_enable_accept_filter :
1035 : config->enable_accept_filter = parse_toggle_state(cmd, arg);
1036 : break;
1037 : #endif /* defined(FEATURE_ACCEPT_FILTER) && defined(SO_ACCEPTFILTER) */
1038 :
1039 : /* *************************************************************************
1040 : * enable-edit-actions 0|1
1041 : * *************************************************************************/
1042 : #ifdef FEATURE_CGI_EDIT_ACTIONS
1043 3098 : case hash_enable_edit_actions:
1044 3098 : if (parse_toggle_state(cmd, arg) == 1)
1045 : {
1046 3098 : config->feature_flags |= RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
1047 : }
1048 : else
1049 : {
1050 0 : config->feature_flags &= ~RUNTIME_FEATURE_CGI_EDIT_ACTIONS;
1051 : }
1052 3098 : break;
1053 : #endif /* def FEATURE_CGI_EDIT_ACTIONS */
1054 :
1055 : /* *************************************************************************
1056 : * enable-compression 0|1
1057 : * *************************************************************************/
1058 : #ifdef FEATURE_COMPRESSION
1059 3098 : case hash_enable_compression:
1060 3098 : if (parse_toggle_state(cmd, arg) == 1)
1061 : {
1062 3098 : config->feature_flags |= RUNTIME_FEATURE_COMPRESSION;
1063 : }
1064 : else
1065 : {
1066 0 : config->feature_flags &= ~RUNTIME_FEATURE_COMPRESSION;
1067 : }
1068 3098 : break;
1069 : #endif /* def FEATURE_COMPRESSION */
1070 :
1071 : /* *************************************************************************
1072 : * enable-proxy-authentication-forwarding 0|1
1073 : * *************************************************************************/
1074 3098 : case hash_enable_proxy_authentication_forwarding:
1075 3098 : if (parse_toggle_state(cmd, arg) == 1)
1076 : {
1077 3098 : config->feature_flags |= RUNTIME_FEATURE_FORWARD_PROXY_AUTHENTICATION_HEADERS;
1078 : }
1079 : else
1080 : {
1081 0 : config->feature_flags &= ~RUNTIME_FEATURE_FORWARD_PROXY_AUTHENTICATION_HEADERS;
1082 : }
1083 3098 : break;
1084 :
1085 : /* *************************************************************************
1086 : * enable-remote-toggle 0|1
1087 : * *************************************************************************/
1088 : #ifdef FEATURE_TOGGLE
1089 3098 : case hash_enable_remote_toggle:
1090 3098 : if (parse_toggle_state(cmd, arg) == 1)
1091 : {
1092 3098 : config->feature_flags |= RUNTIME_FEATURE_CGI_TOGGLE;
1093 : }
1094 : else
1095 : {
1096 0 : config->feature_flags &= ~RUNTIME_FEATURE_CGI_TOGGLE;
1097 : }
1098 3098 : break;
1099 : #endif /* def FEATURE_TOGGLE */
1100 :
1101 : /* *************************************************************************
1102 : * enable-remote-http-toggle 0|1
1103 : * *************************************************************************/
1104 3098 : case hash_enable_remote_http_toggle:
1105 3098 : if (parse_toggle_state(cmd, arg) == 1)
1106 : {
1107 3098 : config->feature_flags |= RUNTIME_FEATURE_HTTP_TOGGLE;
1108 : }
1109 : else
1110 : {
1111 0 : config->feature_flags &= ~RUNTIME_FEATURE_HTTP_TOGGLE;
1112 : }
1113 3098 : break;
1114 :
1115 : /* *************************************************************************
1116 : * enforce-blocks 0|1
1117 : * *************************************************************************/
1118 3098 : case hash_enforce_blocks:
1119 : #ifdef FEATURE_FORCE_LOAD
1120 3098 : if (parse_toggle_state(cmd, arg) == 1)
1121 : {
1122 0 : config->feature_flags |= RUNTIME_FEATURE_ENFORCE_BLOCKS;
1123 : }
1124 : else
1125 : {
1126 3098 : config->feature_flags &= ~RUNTIME_FEATURE_ENFORCE_BLOCKS;
1127 : }
1128 : #else
1129 : log_error(LOG_LEVEL_ERROR, "Ignoring directive 'enforce-blocks'. "
1130 : "FEATURE_FORCE_LOAD is disabled, blocks will always be enforced.");
1131 : #endif /* def FEATURE_FORCE_LOAD */
1132 3098 : break;
1133 :
1134 : /* *************************************************************************
1135 : * filterfile file-name
1136 : * In confdir by default.
1137 : * *************************************************************************/
1138 6196 : case hash_filterfile :
1139 6196 : i = 0;
1140 9294 : while ((i < MAX_AF_FILES) && (NULL != config->re_filterfile[i]))
1141 : {
1142 3098 : i++;
1143 : }
1144 :
1145 6196 : if (i >= MAX_AF_FILES)
1146 : {
1147 0 : log_error(LOG_LEVEL_FATAL, "Too many 'filterfile' directives in config file - limit is %d.\n"
1148 : "(You can increase this limit by changing MAX_AF_FILES in project.h and recompiling).",
1149 : MAX_AF_FILES);
1150 : }
1151 6196 : config->re_filterfile_short[i] = strdup_or_die(arg);
1152 6196 : config->re_filterfile[i] = make_path(config->confdir, arg);
1153 :
1154 6196 : break;
1155 :
1156 : /* *************************************************************************
1157 : * forward url-pattern (.|http-proxy-host[:port])
1158 : * *************************************************************************/
1159 0 : case hash_forward:
1160 0 : strlcpy(tmp, arg, sizeof(tmp));
1161 0 : vec_count = ssplit(tmp, " \t", vec, SZ(vec));
1162 :
1163 0 : if (vec_count != 2)
1164 : {
1165 0 : log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for forward "
1166 : "directive in configuration file.");
1167 0 : string_append(&config->proxy_args,
1168 : "<br>\nWARNING: Wrong number of parameters for "
1169 : "forward directive in configuration file.");
1170 0 : break;
1171 : }
1172 :
1173 : /* allocate a new node */
1174 0 : cur_fwd = zalloc_or_die(sizeof(*cur_fwd));
1175 0 : cur_fwd->type = SOCKS_NONE;
1176 :
1177 : /* Save the URL pattern */
1178 0 : if (create_pattern_spec(cur_fwd->url, vec[0]))
1179 : {
1180 0 : log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward "
1181 : "directive in configuration file.");
1182 0 : string_append(&config->proxy_args,
1183 : "<br>\nWARNING: Bad URL specifier for "
1184 : "forward directive in configuration file.");
1185 0 : freez(cur_fwd);
1186 0 : break;
1187 : }
1188 :
1189 : /* Parse the parent HTTP proxy host:port */
1190 0 : p = vec[1];
1191 :
1192 0 : if (strcmp(p, ".") != 0)
1193 : {
1194 0 : cur_fwd->forward_port = 8000;
1195 0 : parse_forwarder_address(p,
1196 : &cur_fwd->forward_host, &cur_fwd->forward_port,
1197 : NULL, NULL);
1198 : }
1199 :
1200 : /* Add to list. */
1201 0 : cur_fwd->next = config->forward;
1202 0 : config->forward = cur_fwd;
1203 :
1204 0 : break;
1205 :
1206 : /* *************************************************************************
1207 : * forward-socks4 url-pattern socks-proxy[:port] (.|http-proxy[:port])
1208 : * *************************************************************************/
1209 0 : case hash_forward_socks4:
1210 0 : strlcpy(tmp, arg, sizeof(tmp));
1211 0 : vec_count = ssplit(tmp, " \t", vec, SZ(vec));
1212 :
1213 0 : if (vec_count != 3)
1214 : {
1215 0 : log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
1216 : "forward-socks4 directive in configuration file.");
1217 0 : string_append(&config->proxy_args,
1218 : "<br>\nWARNING: Wrong number of parameters for "
1219 : "forward-socks4 directive in configuration file.");
1220 0 : break;
1221 : }
1222 :
1223 : /* allocate a new node */
1224 0 : cur_fwd = zalloc_or_die(sizeof(*cur_fwd));
1225 0 : cur_fwd->type = SOCKS_4;
1226 :
1227 : /* Save the URL pattern */
1228 0 : if (create_pattern_spec(cur_fwd->url, vec[0]))
1229 : {
1230 0 : log_error(LOG_LEVEL_ERROR, "Bad URL specifier for forward-socks4 "
1231 : "directive in configuration file.");
1232 0 : string_append(&config->proxy_args,
1233 : "<br>\nWARNING: Bad URL specifier for "
1234 : "forward-socks4 directive in configuration file.");
1235 0 : freez(cur_fwd);
1236 0 : break;
1237 : }
1238 :
1239 : /* Parse the SOCKS proxy host[:port] */
1240 0 : p = vec[1];
1241 :
1242 : /* XXX: This check looks like a bug. */
1243 0 : if (strcmp(p, ".") != 0)
1244 : {
1245 0 : cur_fwd->gateway_port = 1080;
1246 0 : parse_forwarder_address(p,
1247 : &cur_fwd->gateway_host, &cur_fwd->gateway_port,
1248 : NULL, NULL);
1249 : }
1250 :
1251 : /* Parse the parent HTTP proxy host[:port] */
1252 0 : p = vec[2];
1253 :
1254 0 : if (strcmp(p, ".") != 0)
1255 : {
1256 0 : cur_fwd->forward_port = 8000;
1257 0 : parse_forwarder_address(p,
1258 : &cur_fwd->forward_host, &cur_fwd->forward_port,
1259 : NULL, NULL);
1260 : }
1261 :
1262 : /* Add to list. */
1263 0 : cur_fwd->next = config->forward;
1264 0 : config->forward = cur_fwd;
1265 :
1266 0 : break;
1267 :
1268 : /* *************************************************************************
1269 : * forward-socks4a url-pattern socks-proxy[:port] (.|http-proxy[:port])
1270 : * *************************************************************************/
1271 0 : case hash_forward_socks4a:
1272 : case hash_forward_socks5:
1273 : case hash_forward_socks5t:
1274 0 : strlcpy(tmp, arg, sizeof(tmp));
1275 0 : vec_count = ssplit(tmp, " \t", vec, SZ(vec));
1276 :
1277 0 : if (vec_count != 3)
1278 : {
1279 0 : log_error(LOG_LEVEL_ERROR,
1280 : "Wrong number of parameters for %s in configuration file.",
1281 : cmd);
1282 0 : string_append(&config->proxy_args,
1283 : "<br>\nWARNING: Wrong number of parameters for ");
1284 0 : string_append(&config->proxy_args, cmd);
1285 0 : string_append(&config->proxy_args,
1286 : "directive in configuration file.");
1287 0 : break;
1288 : }
1289 :
1290 : /* allocate a new node */
1291 0 : cur_fwd = zalloc_or_die(sizeof(*cur_fwd));
1292 :
1293 0 : if (directive_hash == hash_forward_socks4a)
1294 : {
1295 0 : cur_fwd->type = SOCKS_4A;
1296 : }
1297 0 : else if (directive_hash == hash_forward_socks5)
1298 : {
1299 0 : cur_fwd->type = SOCKS_5;
1300 : }
1301 : else
1302 : {
1303 0 : assert(directive_hash == hash_forward_socks5t);
1304 0 : cur_fwd->type = SOCKS_5T;
1305 : }
1306 :
1307 : /* Save the URL pattern */
1308 0 : if (create_pattern_spec(cur_fwd->url, vec[0]))
1309 : {
1310 0 : log_error(LOG_LEVEL_ERROR,
1311 : "Bad URL specifier for %s in configuration file.",
1312 : cmd);
1313 0 : string_append(&config->proxy_args,
1314 : "<br>\nWARNING: Bad URL specifier for ");
1315 0 : string_append(&config->proxy_args, cmd);
1316 0 : string_append(&config->proxy_args,
1317 : "directive in configuration file.");
1318 0 : freez(cur_fwd);
1319 0 : break;
1320 : }
1321 :
1322 : /* Parse the SOCKS proxy [user:pass@]host[:port] */
1323 0 : p = vec[1];
1324 :
1325 0 : cur_fwd->gateway_port = 1080;
1326 0 : parse_forwarder_address(p,
1327 : &cur_fwd->gateway_host, &cur_fwd->gateway_port,
1328 : &cur_fwd->auth_username, &cur_fwd->auth_password);
1329 :
1330 : /* Parse the parent HTTP proxy host[:port] */
1331 0 : p = vec[2];
1332 :
1333 0 : if (strcmp(p, ".") != 0)
1334 : {
1335 0 : cur_fwd->forward_port = 8000;
1336 0 : parse_forwarder_address(p,
1337 : &cur_fwd->forward_host, &cur_fwd->forward_port,
1338 : NULL, NULL);
1339 : }
1340 :
1341 : /* Add to list. */
1342 0 : cur_fwd->next = config->forward;
1343 0 : config->forward = cur_fwd;
1344 :
1345 0 : break;
1346 :
1347 : /* *************************************************************************
1348 : * forwarded-connect-retries n
1349 : * *************************************************************************/
1350 3098 : case hash_forwarded_connect_retries :
1351 3098 : config->forwarded_connect_retries = parse_numeric_value(cmd, arg);
1352 3098 : break;
1353 :
1354 : /* *************************************************************************
1355 : * handle-as-empty-doc-returns-ok 0|1
1356 : *
1357 : * Workaround for firefox hanging on blocked javascript pages.
1358 : * Block with the "+handle-as-empty-document" flag and set the
1359 : * "handle-as-empty-doc-returns-ok" run-time config flag so that
1360 : * Privoxy returns a 200/OK status instead of a 403/Forbidden status
1361 : * to the browser for blocked pages.
1362 : ***************************************************************************/
1363 0 : case hash_handle_as_empty_returns_ok:
1364 0 : if (parse_toggle_state(cmd, arg) == 1)
1365 : {
1366 0 : config->feature_flags |= RUNTIME_FEATURE_EMPTY_DOC_RETURNS_OK;
1367 : }
1368 : else
1369 : {
1370 0 : config->feature_flags &= ~RUNTIME_FEATURE_EMPTY_DOC_RETURNS_OK;
1371 : }
1372 0 : break;
1373 :
1374 : /* *************************************************************************
1375 : * hostname hostname-to-show-on-cgi-pages
1376 : * *************************************************************************/
1377 0 : case hash_hostname :
1378 0 : freez(config->hostname);
1379 0 : config->hostname = strdup_or_die(arg);
1380 0 : break;
1381 :
1382 : /* *************************************************************************
1383 : * keep-alive-timeout timeout
1384 : * *************************************************************************/
1385 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
1386 0 : case hash_keep_alive_timeout :
1387 : {
1388 0 : int timeout = parse_numeric_value(cmd, arg);
1389 0 : if (0 < timeout)
1390 : {
1391 0 : config->feature_flags |= RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
1392 0 : config->keep_alive_timeout = (unsigned int)timeout;
1393 : }
1394 : else
1395 : {
1396 0 : config->feature_flags &= ~RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
1397 : }
1398 0 : break;
1399 : }
1400 : #endif
1401 :
1402 : /* *************************************************************************
1403 : * listen-address [ip][:port]
1404 : * *************************************************************************/
1405 3098 : case hash_listen_address :
1406 3098 : i = 0;
1407 3098 : while ((i < MAX_LISTENING_SOCKETS) && (NULL != config->haddr[i]))
1408 : {
1409 0 : i++;
1410 : }
1411 :
1412 3098 : if (i >= MAX_LISTENING_SOCKETS)
1413 : {
1414 0 : log_error(LOG_LEVEL_FATAL, "Too many 'listen-address' directives in config file - limit is %d.\n"
1415 : "(You can increase this limit by changing MAX_LISTENING_SOCKETS in project.h and recompiling).",
1416 : MAX_LISTENING_SOCKETS);
1417 : }
1418 3098 : config->haddr[i] = strdup_or_die(arg);
1419 3098 : break;
1420 :
1421 : /* *************************************************************************
1422 : * listen-backlog n
1423 : * *************************************************************************/
1424 0 : case hash_listen_backlog :
1425 : /*
1426 : * We don't enfore an upper or lower limit because on
1427 : * many platforms all values are valid and negative
1428 : * number mean "use the highest value allowed".
1429 : */
1430 0 : config->listen_backlog = parse_numeric_value(cmd, arg);
1431 0 : break;
1432 :
1433 : /* *************************************************************************
1434 : * logdir directory-name
1435 : * *************************************************************************/
1436 3098 : case hash_logdir :
1437 3098 : freez(config->logdir);
1438 3098 : config->logdir = make_path(NULL, arg);
1439 3098 : break;
1440 :
1441 : /* *************************************************************************
1442 : * logfile log-file-name
1443 : * In logdir by default
1444 : * *************************************************************************/
1445 0 : case hash_logfile :
1446 0 : if (daemon_mode)
1447 : {
1448 0 : logfile = make_path(config->logdir, arg);
1449 0 : if (NULL == logfile)
1450 : {
1451 0 : log_error(LOG_LEVEL_FATAL, "Out of memory while creating logfile path");
1452 : }
1453 : }
1454 0 : break;
1455 :
1456 : /* *************************************************************************
1457 : * max-client-connections number
1458 : * *************************************************************************/
1459 0 : case hash_max_client_connections :
1460 : {
1461 0 : int max_client_connections = parse_numeric_value(cmd, arg);
1462 :
1463 : #if !defined(_WIN32) && !defined(HAVE_POLL)
1464 : /*
1465 : * Reject values below 1 for obvious reasons and values above
1466 : * FD_SETSIZE/2 because Privoxy needs two sockets to serve
1467 : * client connections that need forwarding.
1468 : *
1469 : * We ignore the fact that the first three file descriptors
1470 : * are usually set to /dev/null, one is used for logging
1471 : * and yet another file descriptor is required to load
1472 : * config files.
1473 : */
1474 : if ((max_client_connections < 1) || (FD_SETSIZE/2 < max_client_connections))
1475 : {
1476 : log_error(LOG_LEVEL_FATAL, "max-client-connections value %d"
1477 : " is invalid. Value needs to be above 1 and below %d"
1478 : " (FD_SETSIZE/2).", max_client_connections, FD_SETSIZE/2);
1479 : }
1480 : #else
1481 : /*
1482 : * The Windows libc uses FD_SETSIZE for an array used
1483 : * by select(), but has no problems with file descriptors
1484 : * above the limit as long as no more than FD_SETSIZE are
1485 : * passed to select().
1486 : * https://msdn.microsoft.com/en-us/library/windows/desktop/ms739169%28v=vs.85%29.aspx
1487 : *
1488 : * On platforms were we use poll() we don't have to enforce
1489 : * an upper connection limit either.
1490 : */
1491 0 : if (max_client_connections < 1)
1492 : {
1493 0 : log_error(LOG_LEVEL_FATAL, "max-client-connections value"
1494 : " has to be a number above 1. %d is invalid.",
1495 : max_client_connections);
1496 : }
1497 : #endif
1498 0 : config->max_client_connections = max_client_connections;
1499 0 : break;
1500 : }
1501 :
1502 : /* *************************************************************************
1503 : * permit-access source-ip[/significant-bits] [dest-ip[/significant-bits]]
1504 : * *************************************************************************/
1505 : #ifdef FEATURE_ACL
1506 3098 : case hash_permit_access:
1507 3098 : strlcpy(tmp, arg, sizeof(tmp));
1508 3098 : vec_count = ssplit(tmp, " \t", vec, SZ(vec));
1509 :
1510 3098 : if ((vec_count != 1) && (vec_count != 2))
1511 : {
1512 0 : log_error(LOG_LEVEL_ERROR, "Wrong number of parameters for "
1513 : "permit-access directive in configuration file.");
1514 0 : string_append(&config->proxy_args,
1515 : "<br>\nWARNING: Wrong number of parameters for "
1516 : "permit-access directive in configuration file.<br><br>\n");
1517 :
1518 0 : break;
1519 : }
1520 :
1521 : /* allocate a new node */
1522 3098 : cur_acl = zalloc_or_die(sizeof(*cur_acl));
1523 3098 : cur_acl->action = ACL_PERMIT;
1524 :
1525 3098 : if (acl_addr(vec[0], cur_acl->src) < 0)
1526 : {
1527 0 : log_error(LOG_LEVEL_ERROR, "Invalid source address, port or netmask "
1528 : "for permit-access directive in configuration file: \"%s\"", vec[0]);
1529 0 : string_append(&config->proxy_args,
1530 : "<br>\nWARNING: Invalid source address, port or netmask for "
1531 : "permit-access directive in configuration file: \"");
1532 0 : string_append(&config->proxy_args,
1533 0 : vec[0]);
1534 0 : string_append(&config->proxy_args,
1535 : "\"<br><br>\n");
1536 0 : freez(cur_acl);
1537 0 : break;
1538 : }
1539 3098 : if (vec_count == 2)
1540 : {
1541 0 : if (acl_addr(vec[1], cur_acl->dst) < 0)
1542 : {
1543 0 : log_error(LOG_LEVEL_ERROR, "Invalid destination address, port or netmask "
1544 : "for permit-access directive in configuration file: \"%s\"", vec[1]);
1545 0 : string_append(&config->proxy_args,
1546 : "<br>\nWARNING: Invalid destination address, port or netmask for "
1547 : "permit-access directive in configuration file: \"");
1548 0 : string_append(&config->proxy_args,
1549 0 : vec[1]);
1550 0 : string_append(&config->proxy_args,
1551 : "\"<br><br>\n");
1552 0 : freez(cur_acl);
1553 0 : break;
1554 : }
1555 : }
1556 : #ifdef HAVE_RFC2553
1557 : else
1558 : {
1559 3098 : cur_acl->wildcard_dst = 1;
1560 : }
1561 : #endif /* def HAVE_RFC2553 */
1562 :
1563 : /*
1564 : * Add it to the list. Note we reverse the list to get the
1565 : * behaviour the user expects. With both the ACL and
1566 : * actions file, the last match wins. However, the internal
1567 : * implementations are different: The actions file is stored
1568 : * in the same order as the file, and scanned completely.
1569 : * With the ACL, we reverse the order as we load it, then
1570 : * when we scan it we stop as soon as we get a match.
1571 : */
1572 3098 : cur_acl->next = config->acl;
1573 3098 : config->acl = cur_acl;
1574 :
1575 3098 : break;
1576 : #endif /* def FEATURE_ACL */
1577 :
1578 : /* *************************************************************************
1579 : * proxy-info-url url
1580 : * *************************************************************************/
1581 0 : case hash_proxy_info_url :
1582 0 : freez(config->proxy_info_url);
1583 0 : config->proxy_info_url = strdup_or_die(arg);
1584 0 : break;
1585 :
1586 :
1587 : /* *************************************************************************
1588 : * receive-buffer-size n
1589 : * *************************************************************************/
1590 0 : case hash_receive_buffer_size :
1591 0 : config->receive_buffer_size = (size_t)parse_numeric_value(cmd, arg);
1592 0 : if (config->receive_buffer_size < BUFFER_SIZE)
1593 : {
1594 0 : log_error(LOG_LEVEL_INFO,
1595 : "receive-buffer-size %lu seems low and may cause problems."
1596 : "Consider setting it to at least %d.",
1597 : config->receive_buffer_size, BUFFER_SIZE);
1598 : }
1599 0 : break;
1600 :
1601 : /* *************************************************************************
1602 : * single-threaded 0|1
1603 : * *************************************************************************/
1604 3098 : case hash_single_threaded :
1605 3098 : config->multi_threaded = 0 == parse_toggle_state(cmd, arg);
1606 3098 : break;
1607 :
1608 : /* *************************************************************************
1609 : * socket-timeout numer_of_seconds
1610 : * *************************************************************************/
1611 3098 : case hash_socket_timeout :
1612 : {
1613 3098 : int socket_timeout = parse_numeric_value(cmd, arg);
1614 3098 : if (0 <= socket_timeout)
1615 : {
1616 3098 : config->socket_timeout = socket_timeout;
1617 : }
1618 : else
1619 : {
1620 0 : log_error(LOG_LEVEL_FATAL, "Invalid socket-timeout: '%s'", arg);
1621 : }
1622 3098 : break;
1623 : }
1624 :
1625 : /* *************************************************************************
1626 : * split-large-cgi-forms
1627 : * *************************************************************************/
1628 3098 : case hash_split_large_cgi_forms :
1629 3098 : if (parse_toggle_state(cmd, arg) == 1)
1630 : {
1631 0 : config->feature_flags |= RUNTIME_FEATURE_SPLIT_LARGE_FORMS;
1632 : }
1633 : else
1634 : {
1635 3098 : config->feature_flags &= ~RUNTIME_FEATURE_SPLIT_LARGE_FORMS;
1636 : }
1637 3098 : break;
1638 :
1639 : /* *************************************************************************
1640 : * templdir directory-name
1641 : * *************************************************************************/
1642 0 : case hash_templdir :
1643 0 : freez(config->templdir);
1644 0 : config->templdir = make_path(NULL, arg);
1645 0 : break;
1646 :
1647 : #ifdef FEATURE_EXTERNAL_FILTERS
1648 : /* *************************************************************************
1649 : * temporary-directory directory-name
1650 : * *************************************************************************/
1651 3098 : case hash_temporary_directory :
1652 3098 : freez(config->temporary_directory);
1653 3098 : config->temporary_directory = make_path(NULL, arg);
1654 3098 : break;
1655 : #endif
1656 :
1657 : /* *************************************************************************
1658 : * tolerate-pipelining (0|1)
1659 : * *************************************************************************/
1660 3098 : case hash_tolerate_pipelining :
1661 3098 : if (parse_toggle_state(cmd, arg) == 1)
1662 : {
1663 3098 : config->feature_flags |= RUNTIME_FEATURE_TOLERATE_PIPELINING;
1664 : }
1665 : else
1666 : {
1667 0 : config->feature_flags &= ~RUNTIME_FEATURE_TOLERATE_PIPELINING;
1668 : }
1669 3098 : break;
1670 :
1671 : /* *************************************************************************
1672 : * toggle (0|1)
1673 : * *************************************************************************/
1674 : #ifdef FEATURE_TOGGLE
1675 3098 : case hash_toggle :
1676 3098 : global_toggle_state = parse_toggle_state(cmd, arg);
1677 3098 : break;
1678 : #endif /* def FEATURE_TOGGLE */
1679 :
1680 : /* *************************************************************************
1681 : * trust-info-url url
1682 : * *************************************************************************/
1683 : #ifdef FEATURE_TRUST
1684 0 : case hash_trust_info_url :
1685 0 : enlist(config->trust_info, arg);
1686 0 : break;
1687 : #endif /* def FEATURE_TRUST */
1688 :
1689 : /* *************************************************************************
1690 : * trust-x-forwarded-for (0|1)
1691 : * *************************************************************************/
1692 3098 : case hash_trust_x_forwarded_for :
1693 3098 : config->trust_x_forwarded_for = parse_toggle_state(cmd, arg);
1694 3098 : break;
1695 :
1696 : /* *************************************************************************
1697 : * trusted-cgi-referrer http://www.example.org/some/path.html
1698 : * *************************************************************************/
1699 3098 : case hash_trusted_cgi_referrer :
1700 : /*
1701 : * We don't validate the specified referrer as
1702 : * it's only used for string comparison.
1703 : */
1704 3098 : freez(config->trusted_cgi_referrer);
1705 3098 : config->trusted_cgi_referrer = strdup_or_die(arg);
1706 3098 : break;
1707 :
1708 : /* *************************************************************************
1709 : * trustfile filename
1710 : * (In confdir by default.)
1711 : * *************************************************************************/
1712 : #ifdef FEATURE_TRUST
1713 0 : case hash_trustfile :
1714 0 : freez(config->trustfile);
1715 0 : config->trustfile = make_path(config->confdir, arg);
1716 0 : break;
1717 : #endif /* def FEATURE_TRUST */
1718 :
1719 : /* *************************************************************************
1720 : * usermanual url
1721 : * *************************************************************************/
1722 0 : case hash_usermanual :
1723 : /*
1724 : * XXX: If this isn't the first config directive, the
1725 : * show-status page links to the website documentation
1726 : * for the directives that were already parsed. Lame.
1727 : */
1728 0 : freez(config->usermanual);
1729 0 : config->usermanual = strdup_or_die(arg);
1730 0 : break;
1731 :
1732 : #ifdef FEATURE_HTTPS_INSPECTION
1733 : /* *************************************************************************
1734 : * ca private key file password
1735 : * *************************************************************************/
1736 0 : case hash_ca_password:
1737 0 : freez(config->ca_password);
1738 0 : config->ca_password = strdup(arg);
1739 0 : break;
1740 :
1741 : /* *************************************************************************
1742 : * ca-directory directory
1743 : * *************************************************************************/
1744 3098 : case hash_ca_directory:
1745 3098 : freez(ca_directory);
1746 3098 : ca_directory = make_path(NULL, arg);
1747 :
1748 3098 : if (NULL == ca_directory)
1749 : {
1750 0 : log_error(LOG_LEVEL_FATAL, "Out of memory while creating ca dir path");
1751 : }
1752 :
1753 3098 : break;
1754 :
1755 : /* *************************************************************************
1756 : * ca cert file ca-cert-file
1757 : * In ca dir by default
1758 : * *************************************************************************/
1759 3098 : case hash_ca_cert_file:
1760 3098 : freez(ca_cert_file);
1761 3098 : ca_cert_file = make_path(config->ca_directory, arg);
1762 :
1763 3098 : if (NULL == ca_cert_file)
1764 : {
1765 0 : log_error(LOG_LEVEL_FATAL, "Out of memory while creating ca certificate file path");
1766 : }
1767 :
1768 3098 : break;
1769 :
1770 : /* *************************************************************************
1771 : * ca key file ca-key-file
1772 : * In ca dir by default
1773 : * *************************************************************************/
1774 3098 : case hash_ca_key_file:
1775 3098 : freez(ca_key_file);
1776 3098 : ca_key_file = make_path(config->ca_directory, arg);
1777 :
1778 3098 : if (NULL == ca_key_file)
1779 : {
1780 0 : log_error(LOG_LEVEL_FATAL, "Out of memory while creating ca key file path");
1781 : }
1782 :
1783 3098 : break;
1784 :
1785 : /* *************************************************************************
1786 : * certificate-directory directory
1787 : * *************************************************************************/
1788 3098 : case hash_certificate_directory:
1789 3098 : freez(certificate_directory);
1790 3098 : certificate_directory = make_path(NULL, arg);
1791 :
1792 3098 : if (NULL == certificate_directory)
1793 : {
1794 0 : log_error(LOG_LEVEL_FATAL,
1795 : "Out of memory while creating certificate directory path");
1796 : }
1797 :
1798 3098 : break;
1799 :
1800 : /* *************************************************************************
1801 : * cipher-list list-of-ciphers
1802 : * *************************************************************************/
1803 0 : case hash_cipher_list:
1804 0 : freez(config->cipher_list);
1805 0 : config->cipher_list = strdup_or_die(arg);
1806 :
1807 0 : break;
1808 :
1809 : /* *************************************************************************
1810 : * trusted CAs file name trusted-cas-file
1811 : * *************************************************************************/
1812 3098 : case hash_trusted_cas_file:
1813 3098 : freez(trusted_cas_file);
1814 3098 : trusted_cas_file = make_path(config->ca_directory, arg);
1815 :
1816 3098 : if (NULL == trusted_cas_file)
1817 : {
1818 0 : log_error(LOG_LEVEL_FATAL, "Out of memory while creating trusted CAs file path");
1819 : }
1820 :
1821 3098 : break;
1822 : #endif
1823 :
1824 : /* *************************************************************************
1825 : * Win32 Console options:
1826 : * *************************************************************************/
1827 :
1828 : /* *************************************************************************
1829 : * hide-console
1830 : * *************************************************************************/
1831 : #ifdef _WIN_CONSOLE
1832 : case hash_hide_console :
1833 : hideConsole = 1;
1834 : break;
1835 : #endif /*def _WIN_CONSOLE*/
1836 :
1837 :
1838 : /* *************************************************************************
1839 : * Win32 GUI options:
1840 : * *************************************************************************/
1841 :
1842 : #if defined(_WIN32) && ! defined(_WIN_CONSOLE)
1843 : /* *************************************************************************
1844 : * activity-animation (0|1)
1845 : * *************************************************************************/
1846 : case hash_activity_animation :
1847 : g_bShowActivityAnimation = parse_toggle_state(cmd, arg);
1848 : break;
1849 :
1850 : /* *************************************************************************
1851 : * close-button-minimizes (0|1)
1852 : * *************************************************************************/
1853 : case hash_close_button_minimizes :
1854 : g_bCloseHidesWindow = parse_toggle_state(cmd, arg);
1855 : break;
1856 :
1857 : /* *************************************************************************
1858 : * log-buffer-size (0|1)
1859 : * *************************************************************************/
1860 : case hash_log_buffer_size :
1861 : g_bLimitBufferSize = parse_toggle_state(cmd, arg);
1862 : break;
1863 :
1864 : /* *************************************************************************
1865 : * log-font-name fontname
1866 : * *************************************************************************/
1867 : case hash_log_font_name :
1868 : if (strlcpy(g_szFontFaceName, arg,
1869 : sizeof(g_szFontFaceName)) >= sizeof(g_szFontFaceName))
1870 : {
1871 : log_error(LOG_LEVEL_FATAL,
1872 : "log-font-name argument '%s' is longer than %u characters.",
1873 : arg, sizeof(g_szFontFaceName)-1);
1874 : }
1875 : break;
1876 :
1877 : /* *************************************************************************
1878 : * log-font-size n
1879 : * *************************************************************************/
1880 : case hash_log_font_size :
1881 : g_nFontSize = parse_numeric_value(cmd, arg);
1882 : break;
1883 :
1884 : /* *************************************************************************
1885 : * log-highlight-messages (0|1)
1886 : * *************************************************************************/
1887 : case hash_log_highlight_messages :
1888 : g_bHighlightMessages = parse_toggle_state(cmd, arg);
1889 : break;
1890 :
1891 : /* *************************************************************************
1892 : * log-max-lines n
1893 : * *************************************************************************/
1894 : case hash_log_max_lines :
1895 : g_nMaxBufferLines = parse_numeric_value(cmd, arg);
1896 : break;
1897 :
1898 : /* *************************************************************************
1899 : * log-messages (0|1)
1900 : * *************************************************************************/
1901 : case hash_log_messages :
1902 : g_bLogMessages = parse_toggle_state(cmd, arg);
1903 : break;
1904 :
1905 : /* *************************************************************************
1906 : * show-on-task-bar (0|1)
1907 : * *************************************************************************/
1908 : case hash_show_on_task_bar :
1909 : g_bShowOnTaskBar = parse_toggle_state(cmd, arg);
1910 : break;
1911 :
1912 : #endif /* defined(_WIN32) && ! defined(_WIN_CONSOLE) */
1913 :
1914 :
1915 : /* *************************************************************************
1916 : * Warnings about unsupported features
1917 : * *************************************************************************/
1918 : #ifndef FEATURE_ACL
1919 : case hash_deny_access:
1920 : #endif /* ndef FEATURE_ACL */
1921 : #ifndef FEATURE_CGI_EDIT_ACTIONS
1922 : case hash_enable_edit_actions:
1923 : #endif /* ndef FEATURE_CGI_EDIT_ACTIONS */
1924 : #ifndef FEATURE_TOGGLE
1925 : case hash_enable_remote_toggle:
1926 : #endif /* ndef FEATURE_TOGGLE */
1927 : #ifndef FEATURE_ACL
1928 : case hash_permit_access:
1929 : #endif /* ndef FEATURE_ACL */
1930 : #ifndef FEATURE_TOGGLE
1931 : case hash_toggle :
1932 : #endif /* ndef FEATURE_TOGGLE */
1933 : #ifndef FEATURE_TRUST
1934 : case hash_trustfile :
1935 : case hash_trust_info_url :
1936 : #endif /* ndef FEATURE_TRUST */
1937 :
1938 : #ifndef _WIN_CONSOLE
1939 0 : case hash_hide_console :
1940 : #endif /* ndef _WIN_CONSOLE */
1941 :
1942 : #if defined(_WIN_CONSOLE) || ! defined(_WIN32)
1943 : case hash_activity_animation :
1944 : case hash_close_button_minimizes :
1945 : case hash_log_buffer_size :
1946 : case hash_log_font_name :
1947 : case hash_log_font_size :
1948 : case hash_log_highlight_messages :
1949 : case hash_log_max_lines :
1950 : case hash_log_messages :
1951 : case hash_show_on_task_bar :
1952 : #endif /* defined(_WIN_CONSOLE) || ! defined(_WIN32) */
1953 : /* These warnings are annoying - so hide them. -- Jon */
1954 : /* log_error(LOG_LEVEL_INFO, "Unsupported directive \"%s\" ignored.", cmd); */
1955 0 : break;
1956 :
1957 : /* *************************************************************************/
1958 0 : default :
1959 : /* *************************************************************************/
1960 : /*
1961 : * I decided that I liked this better as a warning than an
1962 : * error. To change back to an error, just change log level
1963 : * to LOG_LEVEL_FATAL.
1964 : */
1965 0 : log_error(LOG_LEVEL_ERROR, "Ignoring unrecognized directive "
1966 : "'%s' (%uU) in line %lu in configuration file (%s).",
1967 : buf, directive_hash, linenum, configfile);
1968 0 : string_append(&config->proxy_args,
1969 : " <strong class='warning'>Warning: Ignoring unrecognized directive:</strong>");
1970 0 : break;
1971 :
1972 : /* *************************************************************************/
1973 : } /* end switch(hash_string(cmd)) */
1974 :
1975 : /* Save the argument for the show-status page. */
1976 173488 : savearg(cmd, arg, config);
1977 173488 : freez(buf);
1978 : } /* end while (read_config_line(...)) */
1979 :
1980 3098 : fclose(configfp);
1981 :
1982 3098 : set_debug_level(config->debug);
1983 :
1984 3098 : freez(config->logfile);
1985 :
1986 3098 : if (daemon_mode)
1987 : {
1988 0 : if (NULL != logfile)
1989 : {
1990 0 : config->logfile = logfile;
1991 0 : init_error_log(Argv[0], config->logfile);
1992 : }
1993 : else
1994 : {
1995 0 : disable_logging();
1996 : }
1997 : }
1998 :
1999 : #ifdef FEATURE_HTTPS_INSPECTION
2000 : /*
2001 : * Setting SSL parameters from loaded values into structures
2002 : */
2003 3098 : freez(config->ca_directory);
2004 3098 : config->ca_directory = make_path(NULL, ca_directory);
2005 3098 : freez(ca_directory);
2006 :
2007 3098 : freez(config->ca_cert_file);
2008 3098 : config->ca_cert_file = make_path(config->ca_directory, ca_cert_file);
2009 3098 : freez(ca_cert_file);
2010 :
2011 3098 : freez(config->ca_key_file);
2012 3098 : config->ca_key_file = make_path(config->ca_directory, ca_key_file);
2013 3098 : freez(ca_key_file);
2014 :
2015 3098 : freez(config->trusted_cas_file);
2016 3098 : config->trusted_cas_file = make_path(config->ca_directory, trusted_cas_file);
2017 3098 : freez(trusted_cas_file);
2018 :
2019 3098 : freez(config->certificate_directory);
2020 3098 : config->certificate_directory = make_path(NULL, certificate_directory);
2021 3098 : freez(certificate_directory);
2022 : #endif
2023 : #ifdef FEATURE_CONNECTION_KEEP_ALIVE
2024 3098 : if (config->default_server_timeout > config->keep_alive_timeout)
2025 : {
2026 0 : log_error(LOG_LEVEL_ERROR,
2027 : "Reducing the default-server-timeout from %d to the keep-alive-timeout %d.",
2028 : config->default_server_timeout, config->keep_alive_timeout);
2029 0 : config->default_server_timeout = config->keep_alive_timeout;
2030 : }
2031 : #endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
2032 :
2033 : #ifdef FEATURE_CONNECTION_SHARING
2034 3098 : if (config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE)
2035 : {
2036 0 : if (!config->multi_threaded)
2037 : {
2038 : /*
2039 : * While we could use keep-alive without multiple threads
2040 : * if we didn't bother with enforcing the connection timeout,
2041 : * that might make Tor users sad, even though they shouldn't
2042 : * enable the single-threaded option anyway.
2043 : *
2044 : * XXX: We could still use Proxy-Connection: keep-alive.
2045 : */
2046 0 : config->feature_flags &= ~RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE;
2047 0 : log_error(LOG_LEVEL_ERROR,
2048 : "Config option single-threaded disables connection keep-alive.");
2049 : }
2050 : }
2051 3098 : else if ((config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING))
2052 : {
2053 0 : log_error(LOG_LEVEL_ERROR, "Config option connection-sharing "
2054 : "has no effect if keep-alive-timeout isn't set.");
2055 0 : config->feature_flags &= ~RUNTIME_FEATURE_CONNECTION_SHARING;
2056 : }
2057 : #endif /* def FEATURE_CONNECTION_SHARING */
2058 :
2059 3098 : if (NULL == config->proxy_args)
2060 : {
2061 0 : log_error(LOG_LEVEL_FATAL, "Out of memory loading config - insufficient memory for config->proxy_args");
2062 : }
2063 :
2064 3098 : if (config->re_filterfile[0])
2065 : {
2066 3098 : add_loader(load_re_filterfiles, config);
2067 : }
2068 :
2069 3098 : if (config->actions_file[0])
2070 : {
2071 3098 : add_loader(load_action_files, config);
2072 : }
2073 :
2074 : #ifdef FEATURE_TRUST
2075 3098 : if (config->trustfile)
2076 : {
2077 0 : add_loader(load_trustfile, config);
2078 : }
2079 : #endif /* def FEATURE_TRUST */
2080 :
2081 3098 : if (NULL == config->haddr[0])
2082 : {
2083 0 : config->haddr[0] = strdup_or_die(HADDR_DEFAULT);
2084 : }
2085 :
2086 6196 : for (i = 0; i < MAX_LISTENING_SOCKETS && NULL != config->haddr[i]; i++)
2087 : {
2088 3098 : if ((*config->haddr[i] == '[')
2089 0 : && (NULL != (p = strchr(config->haddr[i], ']')))
2090 0 : && (p[1] == ':')
2091 0 : && (0 < (config->hport[i] = atoi(p + 2))))
2092 : {
2093 0 : *p = '\0';
2094 0 : memmove((void *)config->haddr[i], config->haddr[i] + 1,
2095 0 : (size_t)(p - config->haddr[i]));
2096 : }
2097 3098 : else if (NULL != (p = strchr(config->haddr[i], ':'))
2098 3098 : && (0 < (config->hport[i] = atoi(p + 1))))
2099 : {
2100 3098 : *p = '\0';
2101 : }
2102 : else
2103 : {
2104 0 : log_error(LOG_LEVEL_FATAL, "invalid bind port spec %s", config->haddr[i]);
2105 : /* Never get here - LOG_LEVEL_FATAL causes program exit */
2106 : }
2107 3098 : if (*config->haddr[i] == '\0')
2108 : {
2109 : /*
2110 : * Only the port specified. We stored it in config->hport[i]
2111 : * and don't need its text representation anymore.
2112 : * Use config->hport[i] == 0 to iterate listening addresses since
2113 : * now.
2114 : */
2115 0 : freez(config->haddr[i]);
2116 : }
2117 : }
2118 :
2119 : /*
2120 : * Want to run all the loaders once now.
2121 : *
2122 : * Need to set up a fake csp, so they can get to the config.
2123 : */
2124 3098 : fake_csp = zalloc_or_die(sizeof(*fake_csp));
2125 3098 : fake_csp->config = config;
2126 :
2127 3098 : if (run_loader(fake_csp))
2128 : {
2129 0 : freez(fake_csp);
2130 0 : log_error(LOG_LEVEL_FATAL, "A loader failed while loading config file. Exiting.");
2131 : /* Never get here - LOG_LEVEL_FATAL causes program exit */
2132 : }
2133 3098 : freez(fake_csp);
2134 :
2135 : /* FIXME: this is a kludge for win32 */
2136 : #if defined(_WIN32) && !defined (_WIN_CONSOLE)
2137 :
2138 : g_default_actions_file = config->actions_file[1]; /* FIXME Hope this is default.action */
2139 : g_user_actions_file = config->actions_file[2]; /* FIXME Hope this is user.action */
2140 : g_default_filterfile = config->re_filterfile[0]; /* FIXME Hope this is default.filter */
2141 : g_user_filterfile = config->re_filterfile[1]; /* FIXME Hope this is user.filter */
2142 :
2143 : #ifdef FEATURE_TRUST
2144 : g_trustfile = config->trustfile;
2145 : #endif /* def FEATURE_TRUST */
2146 :
2147 :
2148 : #endif /* defined(_WIN32) && !defined (_WIN_CONSOLE) */
2149 : /* FIXME: end kludge */
2150 :
2151 :
2152 3098 : if (current_configfile == NULL)
2153 : {
2154 3098 : config->need_bind = 1;
2155 : }
2156 : else
2157 : {
2158 0 : struct configuration_spec * oldcfg = (struct configuration_spec *)
2159 0 : current_configfile->f;
2160 : /*
2161 : * Check if config->haddr[i],hport[i] == oldcfg->haddr[i],hport[i]
2162 : */
2163 0 : config->need_bind = 0;
2164 :
2165 0 : for (i = 0; i < MAX_LISTENING_SOCKETS; i++)
2166 : {
2167 0 : if (config->hport[i] != oldcfg->hport[i])
2168 : {
2169 0 : config->need_bind = 1;
2170 : }
2171 0 : else if (config->haddr[i] == NULL)
2172 : {
2173 0 : if (oldcfg->haddr[i] != NULL)
2174 : {
2175 0 : config->need_bind = 1;
2176 : }
2177 : }
2178 0 : else if (oldcfg->haddr[i] == NULL)
2179 : {
2180 0 : config->need_bind = 1;
2181 : }
2182 0 : else if (0 != strcmp(config->haddr[i], oldcfg->haddr[i]))
2183 : {
2184 0 : config->need_bind = 1;
2185 : }
2186 : }
2187 :
2188 0 : current_configfile->unloader = unload_configfile;
2189 : }
2190 :
2191 3098 : fs->next = files->next;
2192 3098 : files->next = fs;
2193 :
2194 3098 : current_configfile = fs;
2195 :
2196 3098 : return (config);
2197 : }
2198 :
2199 :
2200 : /*********************************************************************
2201 : *
2202 : * Function : savearg
2203 : *
2204 : * Description : Called from `load_config'. It saves each non-empty
2205 : * and non-comment line from config into
2206 : * config->proxy_args. This is used to create the
2207 : * show-status page. On error, frees
2208 : * config->proxy_args and sets it to NULL
2209 : *
2210 : * Parameters :
2211 : * 1 : command = config setting that was found
2212 : * 2 : argument = the setting's argument (if any)
2213 : * 3 : config = Configuration to save into.
2214 : *
2215 : * Returns : N/A
2216 : *
2217 : *********************************************************************/
2218 173488 : static void savearg(char *command, char *argument, struct configuration_spec * config)
2219 : {
2220 : char * buf;
2221 : char * s;
2222 :
2223 173488 : assert(command);
2224 173488 : assert(argument);
2225 :
2226 : /*
2227 : * Add config option name embedded in
2228 : * link to its section in the user-manual
2229 : */
2230 173488 : buf = strdup_or_die("\n<a href=\"");
2231 346976 : if (!strncmpic(config->usermanual, "file://", 7) ||
2232 173488 : !strncmpic(config->usermanual, "http", 4))
2233 : {
2234 173488 : string_append(&buf, config->usermanual);
2235 : }
2236 : else
2237 : {
2238 0 : string_append(&buf, "http://" CGI_SITE_2_HOST "/user-manual/");
2239 : }
2240 173488 : string_append(&buf, CONFIG_HELP_PREFIX);
2241 173488 : string_join (&buf, string_toupper(command));
2242 173488 : string_append(&buf, "\">");
2243 173488 : string_append(&buf, command);
2244 173488 : string_append(&buf, "</a> ");
2245 :
2246 173488 : if (NULL == buf)
2247 : {
2248 0 : freez(config->proxy_args);
2249 0 : return;
2250 : }
2251 :
2252 173488 : if ((NULL != argument) && ('\0' != *argument))
2253 : {
2254 173488 : s = html_encode(argument);
2255 173488 : if (NULL == s)
2256 : {
2257 0 : freez(buf);
2258 0 : freez(config->proxy_args);
2259 0 : return;
2260 : }
2261 :
2262 173488 : if (strncmpic(argument, "http://", 7) == 0)
2263 : {
2264 0 : string_append(&buf, "<a href=\"");
2265 0 : string_append(&buf, s);
2266 0 : string_append(&buf, "\">");
2267 0 : string_join (&buf, s);
2268 0 : string_append(&buf, "</a>");
2269 : }
2270 : else
2271 : {
2272 173488 : string_join (&buf, s);
2273 : }
2274 : }
2275 :
2276 173488 : string_append(&buf, "<br>");
2277 173488 : string_join(&config->proxy_args, buf);
2278 : }
2279 :
2280 :
2281 : /*
2282 : Local Variables:
2283 : tab-width: 3
2284 : end:
2285 : */
|