loadcfg.c 79 KB

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