cgi.c 76 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524
  1. /*********************************************************************
  2. *
  3. * File : $Source: /cvsroot/ijbswa/current/cgi.c,v $
  4. *
  5. * Purpose : Declares functions to intercept request, generate
  6. * html or gif answers, and to compose HTTP responses.
  7. * This only contains the framework functions, the
  8. * actual handler functions are declared elsewhere.
  9. *
  10. * Copyright : Written by and Copyright (C) 2001-2020
  11. * members of the 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 <ctype.h>
  41. #include <string.h>
  42. #include <limits.h>
  43. #include <assert.h>
  44. #ifdef FEATURE_COMPRESSION
  45. #include <zlib.h>
  46. #endif
  47. #include "project.h"
  48. #include "cgi.h"
  49. #include "list.h"
  50. #include "encode.h"
  51. #include "ssplit.h"
  52. #include "errlog.h"
  53. #include "filters.h"
  54. #include "miscutil.h"
  55. #include "cgisimple.h"
  56. #include "jbsockets.h"
  57. #if defined(FEATURE_CGI_EDIT_ACTIONS) || defined(FEATURE_TOGGLE)
  58. #include "cgiedit.h"
  59. #endif /* defined(FEATURE_CGI_EDIT_ACTIONS) || defined (FEATURE_TOGGLE) */
  60. #ifdef FEATURE_HTTPS_INSPECTION
  61. #include "ssl.h"
  62. #endif
  63. /* loadcfg.h is for global_toggle_state only */
  64. #include "loadcfg.h"
  65. /* jcc.h is for mutex semaphore globals only */
  66. #include "jcc.h"
  67. static char *make_menu(const struct client_state *csp, const char *self);
  68. /*
  69. * List of CGI functions: name, handler, description
  70. * Note: Do NOT use single quotes in the description;
  71. * this will break the dynamic "blocked" template!
  72. */
  73. static const struct cgi_dispatcher cgi_dispatchers[] = {
  74. { "",
  75. cgi_default,
  76. "Privoxy main page",
  77. TRUE },
  78. #ifdef FEATURE_GRACEFUL_TERMINATION
  79. { "die",
  80. cgi_die,
  81. "<b>Shut down</b> - <em class=\"warning\">Do not deploy this build in a production environment, "
  82. "this is a one click Denial Of Service attack!!!</em>",
  83. FALSE },
  84. #endif
  85. { "show-status",
  86. cgi_show_status,
  87. #ifdef FEATURE_CGI_EDIT_ACTIONS
  88. "View &amp; change the current configuration",
  89. #else
  90. "View the current configuration",
  91. #endif
  92. TRUE },
  93. #ifdef FEATURE_CLIENT_TAGS
  94. /*
  95. * This is marked as harmless because despite the description
  96. * used in the menu the actual toggling is done through another
  97. * path ("/toggle-client-tag").
  98. */
  99. { "client-tags",
  100. cgi_show_client_tags,
  101. "View or toggle the tags that can be set based on the client&#39;s address",
  102. TRUE },
  103. #endif
  104. { "show-request",
  105. cgi_show_request,
  106. "View the request headers",
  107. TRUE },
  108. { "show-url-info",
  109. cgi_show_url_info,
  110. "Look up which actions apply to a URL and why",
  111. TRUE },
  112. #ifdef FEATURE_TOGGLE
  113. { "toggle",
  114. cgi_toggle,
  115. "Toggle Privoxy on or off",
  116. FALSE },
  117. #endif /* def FEATURE_TOGGLE */
  118. #ifdef FEATURE_CLIENT_TAGS
  119. { "toggle-client-tag",
  120. cgi_toggle_client_tag,
  121. NULL,
  122. FALSE },
  123. #endif
  124. #ifdef FEATURE_CGI_EDIT_ACTIONS
  125. { "edit-actions", /* Edit the actions list */
  126. cgi_edit_actions,
  127. NULL, FALSE },
  128. { "eaa", /* Shortcut for edit-actions-add-url-form */
  129. cgi_edit_actions_add_url_form,
  130. NULL, FALSE },
  131. { "eau", /* Shortcut for edit-actions-url-form */
  132. cgi_edit_actions_url_form,
  133. NULL, FALSE },
  134. { "ear", /* Shortcut for edit-actions-remove-url-form */
  135. cgi_edit_actions_remove_url_form,
  136. NULL, FALSE },
  137. { "eal", /* Shortcut for edit-actions-list */
  138. cgi_edit_actions_list,
  139. NULL, FALSE },
  140. { "eafu", /* Shortcut for edit-actions-for-url */
  141. cgi_edit_actions_for_url,
  142. NULL, FALSE },
  143. { "eas", /* Shortcut for edit-actions-submit */
  144. cgi_edit_actions_submit,
  145. NULL, FALSE },
  146. { "easa", /* Shortcut for edit-actions-section-add */
  147. cgi_edit_actions_section_add,
  148. NULL, FALSE },
  149. { "easr", /* Shortcut for edit-actions-section-remove */
  150. cgi_edit_actions_section_remove,
  151. NULL, FALSE },
  152. { "eass", /* Shortcut for edit-actions-section-swap */
  153. cgi_edit_actions_section_swap,
  154. NULL, FALSE },
  155. { "edit-actions-for-url",
  156. cgi_edit_actions_for_url,
  157. NULL, FALSE /* Edit the actions for (a) specified URL(s) */ },
  158. { "edit-actions-list",
  159. cgi_edit_actions_list,
  160. NULL, TRUE /* Edit the actions list */ },
  161. { "edit-actions-submit",
  162. cgi_edit_actions_submit,
  163. NULL, FALSE /* Change the actions for (a) specified URL(s) */ },
  164. { "edit-actions-url",
  165. cgi_edit_actions_url,
  166. NULL, FALSE /* Change a URL pattern in the actionsfile */ },
  167. { "edit-actions-url-form",
  168. cgi_edit_actions_url_form,
  169. NULL, FALSE /* Form to change a URL pattern in the actionsfile */ },
  170. { "edit-actions-add-url",
  171. cgi_edit_actions_add_url,
  172. NULL, FALSE /* Add a URL pattern to the actionsfile */ },
  173. { "edit-actions-add-url-form",
  174. cgi_edit_actions_add_url_form,
  175. NULL, FALSE /* Form to add a URL pattern to the actionsfile */ },
  176. { "edit-actions-remove-url",
  177. cgi_edit_actions_remove_url,
  178. NULL, FALSE /* Remove a URL pattern from the actionsfile */ },
  179. { "edit-actions-remove-url-form",
  180. cgi_edit_actions_remove_url_form,
  181. NULL, FALSE /* Form to remove a URL pattern from the actionsfile */ },
  182. { "edit-actions-section-add",
  183. cgi_edit_actions_section_add,
  184. NULL, FALSE /* Remove a section from the actionsfile */ },
  185. { "edit-actions-section-remove",
  186. cgi_edit_actions_section_remove,
  187. NULL, FALSE /* Remove a section from the actionsfile */ },
  188. { "edit-actions-section-swap",
  189. cgi_edit_actions_section_swap,
  190. NULL, FALSE /* Swap two sections in the actionsfile */ },
  191. #endif /* def FEATURE_CGI_EDIT_ACTIONS */
  192. { "error-favicon.ico",
  193. cgi_send_error_favicon,
  194. NULL, TRUE /* Sends the favicon image for error pages. */ },
  195. { "favicon.ico",
  196. cgi_send_default_favicon,
  197. NULL, TRUE /* Sends the default favicon image. */ },
  198. { "robots.txt",
  199. cgi_robots_txt,
  200. NULL, TRUE /* Sends a robots.txt file to tell robots to go away. */ },
  201. { "send-banner",
  202. cgi_send_banner,
  203. NULL, TRUE /* Send a built-in image */ },
  204. { "send-stylesheet",
  205. cgi_send_stylesheet,
  206. NULL, FALSE /* Send templates/cgi-style.css */ },
  207. { "t",
  208. cgi_transparent_image,
  209. NULL, TRUE /* Send a transparent image (short name) */ },
  210. { "url-info-osd.xml",
  211. cgi_send_url_info_osd,
  212. NULL, TRUE /* Send templates/url-info-osd.xml */ },
  213. { "user-manual",
  214. cgi_send_user_manual,
  215. NULL, TRUE /* Send user-manual */ },
  216. { NULL, /* NULL Indicates end of list and default page */
  217. cgi_error_404,
  218. NULL, TRUE /* Unknown CGI page */ }
  219. };
  220. /*
  221. * Built-in images for ad replacement
  222. *
  223. * Hint: You can encode your own images like this:
  224. * cat your-image | perl -e 'while (read STDIN, $c, 1) { printf("\\%.3o", unpack("C", $c)); }'
  225. */
  226. #ifdef FEATURE_NO_GIFS
  227. /*
  228. * Checkerboard pattern, as a PNG.
  229. */
  230. const char image_pattern_data[] =
  231. "\211\120\116\107\015\012\032\012\000\000\000\015\111\110\104"
  232. "\122\000\000\000\004\000\000\000\004\010\006\000\000\000\251"
  233. "\361\236\176\000\000\000\006\142\113\107\104\000\000\000\000"
  234. "\000\000\371\103\273\177\000\000\000\033\111\104\101\124\010"
  235. "\327\143\140\140\140\060\377\377\377\077\003\234\106\341\060"
  236. "\060\230\063\020\124\001\000\161\021\031\241\034\364\030\143"
  237. "\000\000\000\000\111\105\116\104\256\102\140\202";
  238. /*
  239. * 1x1 transparent PNG.
  240. */
  241. const char image_blank_data[] =
  242. "\211\120\116\107\015\012\032\012\000\000\000\015\111\110\104\122"
  243. "\000\000\000\001\000\000\000\001\001\003\000\000\000\045\333\126"
  244. "\312\000\000\000\003\120\114\124\105\377\377\377\247\304\033\310"
  245. "\000\000\000\001\164\122\116\123\000\100\346\330\146\000\000\000"
  246. "\001\142\113\107\104\000\210\005\035\110\000\000\000\012\111\104"
  247. "\101\124\170\001\143\140\000\000\000\002\000\001\163\165\001\030"
  248. "\000\000\000\000\111\105\116\104\256\102\140\202";
  249. #else
  250. /*
  251. * Checkerboard pattern, as a GIF.
  252. */
  253. const char image_pattern_data[] =
  254. "\107\111\106\070\071\141\004\000\004\000\200\000\000\310\310"
  255. "\310\377\377\377\041\376\016\111\040\167\141\163\040\141\040"
  256. "\142\141\156\156\145\162\000\041\371\004\001\012\000\001\000"
  257. "\054\000\000\000\000\004\000\004\000\000\002\005\104\174\147"
  258. "\270\005\000\073";
  259. /*
  260. * 1x1 transparent GIF.
  261. */
  262. const char image_blank_data[] =
  263. "GIF89a\001\000\001\000\200\000\000\377\377\377\000\000"
  264. "\000!\371\004\001\000\000\000\000,\000\000\000\000\001"
  265. "\000\001\000\000\002\002D\001\000;";
  266. #endif
  267. const size_t image_pattern_length = sizeof(image_pattern_data) - 1;
  268. const size_t image_blank_length = sizeof(image_blank_data) - 1;
  269. #ifdef FEATURE_COMPRESSION
  270. /*
  271. * Minimum length which a buffer has to reach before
  272. * we bother to (re-)compress it. Completely arbitrary.
  273. */
  274. const size_t LOWER_LENGTH_LIMIT_FOR_COMPRESSION = 1024U;
  275. #endif
  276. static struct http_response cgi_error_memory_response[1];
  277. static struct http_response *dispatch_known_cgi(struct client_state * csp,
  278. const char * path);
  279. static struct map *parse_cgi_parameters(char *argstring);
  280. /*********************************************************************
  281. *
  282. * Function : dispatch_cgi
  283. *
  284. * Description : Checks if a request URL has either the magical
  285. * hostname CGI_SITE_1_HOST (usually http://p.p/) or
  286. * matches CGI_SITE_2_HOST CGI_SITE_2_PATH (usually
  287. * http://config.privoxy.org/). If so, it passes
  288. * the (rest of the) path onto dispatch_known_cgi, which
  289. * calls the relevant CGI handler function.
  290. *
  291. * Parameters :
  292. * 1 : csp = Current client state (buffers, headers, etc...)
  293. *
  294. * Returns : http_response if match, NULL if nonmatch or handler fail
  295. *
  296. *********************************************************************/
  297. struct http_response *dispatch_cgi(struct client_state *csp)
  298. {
  299. const char *host = csp->http->host;
  300. const char *path = csp->http->path;
  301. /*
  302. * Should we intercept ?
  303. */
  304. /* Note: "example.com" and "example.com." are equivalent hostnames. */
  305. /* Either the host matches CGI_SITE_1_HOST ..*/
  306. if ( ( (0 == strcmpic(host, CGI_SITE_1_HOST))
  307. || (0 == strcmpic(host, CGI_SITE_1_HOST ".")))
  308. && (path[0] == '/'))
  309. {
  310. /* ..then the path will all be for us. Remove leading '/' */
  311. path++;
  312. }
  313. /* Or it's the host part CGI_SITE_2_HOST, and the path CGI_SITE_2_PATH */
  314. else if (( (0 == strcmpic(host, CGI_SITE_2_HOST))
  315. || (0 == strcmpic(host, CGI_SITE_2_HOST ".")))
  316. && (0 == strncmpic(path, CGI_SITE_2_PATH, strlen(CGI_SITE_2_PATH))))
  317. {
  318. /* take everything following CGI_SITE_2_PATH */
  319. path += strlen(CGI_SITE_2_PATH);
  320. if (*path == '/')
  321. {
  322. /* skip the forward slash after CGI_SITE_2_PATH */
  323. path++;
  324. }
  325. else if (*path != '\0')
  326. {
  327. /*
  328. * weirdness: URL is /configXXX, where XXX is some string
  329. * Do *NOT* intercept.
  330. */
  331. return NULL;
  332. }
  333. }
  334. else
  335. {
  336. /* Not a CGI */
  337. return NULL;
  338. }
  339. if (strcmpic(csp->http->gpc, "GET")
  340. && strcmpic(csp->http->gpc, "HEAD"))
  341. {
  342. log_error(LOG_LEVEL_ERROR,
  343. "CGI request with unsupported method received: %s", csp->http->gpc);
  344. /*
  345. * The CGI pages currently only support GET and HEAD requests.
  346. *
  347. * If the client used a different method, ditch any data following
  348. * the current headers to reduce the likelihood of parse errors
  349. * with the following request.
  350. */
  351. csp->client_iob->eod = csp->client_iob->cur;
  352. }
  353. /*
  354. * This is a CGI call.
  355. */
  356. return dispatch_known_cgi(csp, path);
  357. }
  358. /*********************************************************************
  359. *
  360. * Function : grep_cgi_referrer
  361. *
  362. * Description : Ugly provisorical fix that greps the value of the
  363. * referer HTTP header field out of a linked list of
  364. * strings like found at csp->headers. Will disappear
  365. * in Privoxy 3.1.
  366. *
  367. * FIXME: csp->headers ought to be csp->http->headers
  368. * FIXME: Parsing all client header lines should
  369. * happen right after the request is received!
  370. *
  371. * Parameters :
  372. * 1 : csp = Current client state (buffers, headers, etc...)
  373. *
  374. * Returns : pointer to value (no copy!), or NULL if none found.
  375. *
  376. *********************************************************************/
  377. static char *grep_cgi_referrer(const struct client_state *csp)
  378. {
  379. struct list_entry *p;
  380. struct list_entry *first_header =
  381. #ifdef FEATURE_HTTPS_INSPECTION
  382. client_use_ssl(csp) ? csp->https_headers->first :
  383. #endif
  384. csp->headers->first;
  385. for (p = first_header; p != NULL; p = p->next)
  386. {
  387. if (p->str == NULL) continue;
  388. if (strncmpic(p->str, "Referer: ", 9) == 0)
  389. {
  390. return ((p->str) + 9);
  391. }
  392. }
  393. return NULL;
  394. }
  395. /*********************************************************************
  396. *
  397. * Function : referrer_is_safe
  398. *
  399. * Description : Decides whether we trust the Referer for
  400. * CGI pages which are only meant to be reachable
  401. * through Privoxy's web interface directly.
  402. *
  403. * Parameters :
  404. * 1 : csp = Current client state (buffers, headers, etc...)
  405. *
  406. * Returns : TRUE if the referrer is safe, or
  407. * FALSE if the referrer is unsafe or not set.
  408. *
  409. *********************************************************************/
  410. static int referrer_is_safe(const struct client_state *csp)
  411. {
  412. char *referrer;
  413. static const char alternative_prefix[] = "http://" CGI_SITE_1_HOST "/";
  414. #ifdef FEATURE_HTTPS_INSPECTION
  415. static const char alt_prefix_https[] = "https://" CGI_SITE_1_HOST "/";
  416. #endif
  417. const char *trusted_cgi_referrer = csp->config->trusted_cgi_referrer;
  418. referrer = grep_cgi_referrer(csp);
  419. if (NULL == referrer)
  420. {
  421. /* No referrer, no access */
  422. log_error(LOG_LEVEL_ERROR, "Denying access to %s. No referrer found.",
  423. csp->http->url);
  424. }
  425. else if ((0 == strncmp(referrer, CGI_PREFIX, sizeof(CGI_PREFIX)-1))
  426. #ifdef FEATURE_HTTPS_INSPECTION
  427. || (0 == strncmp(referrer, CGI_PREFIX_HTTPS, sizeof(CGI_PREFIX_HTTPS)-1))
  428. || (0 == strncmp(referrer, alt_prefix_https, strlen(alt_prefix_https)))
  429. #endif
  430. || (0 == strncmp(referrer, alternative_prefix, strlen(alternative_prefix))))
  431. {
  432. /* Trustworthy referrer */
  433. log_error(LOG_LEVEL_CGI, "Granting access to %s, referrer %s is trustworthy.",
  434. csp->http->url, referrer);
  435. return TRUE;
  436. }
  437. else if ((trusted_cgi_referrer != NULL) && (0 == strncmp(referrer,
  438. trusted_cgi_referrer, strlen(trusted_cgi_referrer))))
  439. {
  440. /*
  441. * After some more testing this block should be merged with
  442. * the previous one or the log level should bedowngraded.
  443. */
  444. log_error(LOG_LEVEL_INFO, "Granting access to %s based on trusted referrer %s",
  445. csp->http->url, referrer);
  446. return TRUE;
  447. }
  448. else
  449. {
  450. /* Untrustworthy referrer */
  451. log_error(LOG_LEVEL_ERROR, "Denying access to %s, referrer %s isn't trustworthy.",
  452. csp->http->url, referrer);
  453. }
  454. return FALSE;
  455. }
  456. /*********************************************************************
  457. *
  458. * Function : dispatch_known_cgi
  459. *
  460. * Description : Processes a CGI once dispatch_cgi has determined that
  461. * it matches one of the magic prefixes. Parses the path
  462. * as a cgi name plus query string, prepares a map that
  463. * maps CGI parameter names to their values, initializes
  464. * the http_response struct, and calls the relevant CGI
  465. * handler function.
  466. *
  467. * Parameters :
  468. * 1 : csp = Current client state (buffers, headers, etc...)
  469. * 2 : path = Path of CGI, with the CGI prefix removed.
  470. * Should not have a leading "/".
  471. *
  472. * Returns : http_response, or NULL on handler failure or out of
  473. * memory.
  474. *
  475. *********************************************************************/
  476. static struct http_response *dispatch_known_cgi(struct client_state * csp,
  477. const char * path)
  478. {
  479. const struct cgi_dispatcher *d;
  480. struct map *param_list;
  481. struct http_response *rsp;
  482. char *query_args_start;
  483. char *path_copy;
  484. jb_err err;
  485. if (NULL == (path_copy = strdup(path)))
  486. {
  487. return cgi_error_memory();
  488. }
  489. query_args_start = path_copy;
  490. while (*query_args_start && *query_args_start != '?' && *query_args_start != '/')
  491. {
  492. query_args_start++;
  493. }
  494. if (*query_args_start == '/')
  495. {
  496. *query_args_start++ = '\0';
  497. param_list = new_map();
  498. err = map(param_list, "file", 1, url_decode(query_args_start), 0);
  499. if (JB_ERR_OK != err)
  500. {
  501. free(param_list);
  502. free(path_copy);
  503. return cgi_error_memory();
  504. }
  505. }
  506. else
  507. {
  508. if (*query_args_start == '?')
  509. {
  510. *query_args_start++ = '\0';
  511. }
  512. if (NULL == (param_list = parse_cgi_parameters(query_args_start)))
  513. {
  514. free(path_copy);
  515. return cgi_error_memory();
  516. }
  517. }
  518. /*
  519. * At this point:
  520. * path_copy = CGI call name
  521. * param_list = CGI params, as map
  522. */
  523. /* Get mem for response or fail*/
  524. if (NULL == (rsp = alloc_http_response()))
  525. {
  526. free(path_copy);
  527. free_map(param_list);
  528. return cgi_error_memory();
  529. }
  530. /*
  531. * Find and start the right CGI function
  532. */
  533. d = cgi_dispatchers;
  534. for (;;)
  535. {
  536. if ((d->name == NULL) || (strcmp(path_copy, d->name) == 0))
  537. {
  538. /*
  539. * If the called CGI is either harmless, or referred
  540. * from a trusted source, start it.
  541. */
  542. if (d->harmless || referrer_is_safe(csp))
  543. {
  544. err = (d->handler)(csp, rsp, param_list);
  545. }
  546. else
  547. {
  548. /*
  549. * Else, modify toggle calls so that they only display
  550. * the status, and deny all other calls.
  551. */
  552. if (0 == strcmp(path_copy, "toggle"))
  553. {
  554. unmap(param_list, "set");
  555. err = (d->handler)(csp, rsp, param_list);
  556. }
  557. else
  558. {
  559. err = cgi_error_disabled(csp, rsp);
  560. }
  561. }
  562. free(path_copy);
  563. free_map(param_list);
  564. if (err == JB_ERR_CGI_PARAMS)
  565. {
  566. err = cgi_error_bad_param(csp, rsp);
  567. }
  568. if (err && (err != JB_ERR_MEMORY))
  569. {
  570. /* Unexpected error! Shouldn't get here */
  571. log_error(LOG_LEVEL_ERROR,
  572. "Unexpected CGI error %d in top-level handler. "
  573. "Please file a bug report!", err);
  574. err = cgi_error_unknown(csp, rsp, err);
  575. }
  576. if (!err)
  577. {
  578. /* It worked */
  579. rsp->crunch_reason = CGI_CALL;
  580. return finish_http_response(csp, rsp);
  581. }
  582. else
  583. {
  584. /* Error in handler, probably out-of-memory */
  585. free_http_response(rsp);
  586. return cgi_error_memory();
  587. }
  588. }
  589. d++;
  590. }
  591. }
  592. /*********************************************************************
  593. *
  594. * Function : parse_cgi_parameters
  595. *
  596. * Description : Parse a URL-encoded argument string into name/value
  597. * pairs and store them in a struct map list.
  598. *
  599. * Parameters :
  600. * 1 : argstring = string to be parsed. Will be trashed.
  601. *
  602. * Returns : pointer to param list, or NULL if out of memory.
  603. *
  604. *********************************************************************/
  605. static struct map *parse_cgi_parameters(char *argstring)
  606. {
  607. char *p;
  608. char **vector;
  609. int pairs, i;
  610. struct map *cgi_params;
  611. /*
  612. * XXX: This estimate is guaranteed to be high enough as we
  613. * let ssplit() ignore empty fields, but also a bit wasteful.
  614. * The same hack is used in get_last_url() so it looks like
  615. * a real solution is needed.
  616. */
  617. size_t max_segments = strlen(argstring) / 2;
  618. if (max_segments == 0)
  619. {
  620. /*
  621. * XXX: If the argstring is empty, there's really
  622. * no point in creating a param list, but currently
  623. * other parts of Privoxy depend on the list's existence.
  624. */
  625. max_segments = 1;
  626. }
  627. vector = malloc_or_die(max_segments * sizeof(char *));
  628. cgi_params = new_map();
  629. /*
  630. * IE 5 does, of course, violate RFC 2316 Sect 4.1 and sends
  631. * the fragment identifier along with the request, so we must
  632. * cut it off here, so it won't pollute the CGI params:
  633. */
  634. if (NULL != (p = strchr(argstring, '#')))
  635. {
  636. *p = '\0';
  637. }
  638. pairs = ssplit(argstring, "&", vector, max_segments);
  639. assert(pairs != -1);
  640. if (pairs == -1)
  641. {
  642. freez(vector);
  643. free_map(cgi_params);
  644. return NULL;
  645. }
  646. for (i = 0; i < pairs; i++)
  647. {
  648. if ((NULL != (p = strchr(vector[i], '='))) && (*(p+1) != '\0'))
  649. {
  650. *p = '\0';
  651. if (map(cgi_params, url_decode(vector[i]), 0, url_decode(++p), 0))
  652. {
  653. freez(vector);
  654. free_map(cgi_params);
  655. return NULL;
  656. }
  657. }
  658. }
  659. freez(vector);
  660. return cgi_params;
  661. }
  662. /*********************************************************************
  663. *
  664. * Function : get_char_param
  665. *
  666. * Description : Get a single-character parameter passed to a CGI
  667. * function.
  668. *
  669. * Parameters :
  670. * 1 : parameters = map of cgi parameters
  671. * 2 : param_name = The name of the parameter to read
  672. *
  673. * Returns : Uppercase character on success, '\0' on error.
  674. *
  675. *********************************************************************/
  676. char get_char_param(const struct map *parameters,
  677. const char *param_name)
  678. {
  679. char ch;
  680. assert(parameters);
  681. assert(param_name);
  682. ch = *(lookup(parameters, param_name));
  683. if ((ch >= 'a') && (ch <= 'z'))
  684. {
  685. ch = (char)(ch - 'a' + 'A');
  686. }
  687. return ch;
  688. }
  689. /*********************************************************************
  690. *
  691. * Function : get_string_param
  692. *
  693. * Description : Get a string parameter, to be used as an
  694. * ACTION_STRING or ACTION_MULTI parameter.
  695. * Validates the input to prevent stupid/malicious
  696. * users from corrupting their action file.
  697. *
  698. * Parameters :
  699. * 1 : parameters = map of cgi parameters
  700. * 2 : param_name = The name of the parameter to read
  701. * 3 : pparam = destination for parameter. Allocated as
  702. * part of the map "parameters", so don't free it.
  703. * Set to NULL if not specified.
  704. *
  705. * Returns : JB_ERR_OK on success, or if the parameter
  706. * was not specified.
  707. * JB_ERR_MEMORY on out-of-memory.
  708. * JB_ERR_CGI_PARAMS if the parameter is not valid.
  709. *
  710. *********************************************************************/
  711. jb_err get_string_param(const struct map *parameters,
  712. const char *param_name,
  713. const char **pparam)
  714. {
  715. const char *param;
  716. const char *s;
  717. char ch;
  718. assert(parameters);
  719. assert(param_name);
  720. assert(pparam);
  721. *pparam = NULL;
  722. param = lookup(parameters, param_name);
  723. if (!*param)
  724. {
  725. return JB_ERR_OK;
  726. }
  727. if (strlen(param) >= CGI_PARAM_LEN_MAX)
  728. {
  729. /*
  730. * Too long.
  731. *
  732. * Note that the length limit is arbitrary, it just seems
  733. * sensible to limit it to *something*. There's no
  734. * technical reason for any limit at all.
  735. */
  736. return JB_ERR_CGI_PARAMS;
  737. }
  738. /* Check every character to see if it's legal */
  739. s = param;
  740. while ((ch = *s++) != '\0')
  741. {
  742. if (((unsigned char)ch < (unsigned char)' ')
  743. || (ch == '}'))
  744. {
  745. /* Probable hack attempt, or user accidentally used '}'. */
  746. return JB_ERR_CGI_PARAMS;
  747. }
  748. }
  749. /* Success */
  750. *pparam = param;
  751. return JB_ERR_OK;
  752. }
  753. /*********************************************************************
  754. *
  755. * Function : get_number_param
  756. *
  757. * Description : Get a non-negative integer from the parameters
  758. * passed to a CGI function.
  759. *
  760. * Parameters :
  761. * 1 : csp = Current client state (buffers, headers, etc...)
  762. * 2 : parameters = map of cgi parameters
  763. * 3 : name = Name of CGI parameter to read
  764. * 4 : pvalue = destination for value.
  765. * Set to -1 on error.
  766. *
  767. * Returns : JB_ERR_OK on success
  768. * JB_ERR_MEMORY on out-of-memory
  769. * JB_ERR_CGI_PARAMS if the parameter was not specified
  770. * or is not valid.
  771. *
  772. *********************************************************************/
  773. jb_err get_number_param(struct client_state *csp,
  774. const struct map *parameters,
  775. char *name,
  776. unsigned *pvalue)
  777. {
  778. const char *param;
  779. char *endptr;
  780. assert(csp);
  781. assert(parameters);
  782. assert(name);
  783. assert(pvalue);
  784. *pvalue = 0;
  785. param = lookup(parameters, name);
  786. if (!*param)
  787. {
  788. return JB_ERR_CGI_PARAMS;
  789. }
  790. *pvalue = (unsigned int)strtol(param, &endptr, 0);
  791. if (*endptr != '\0')
  792. {
  793. return JB_ERR_CGI_PARAMS;
  794. }
  795. return JB_ERR_OK;
  796. }
  797. /*********************************************************************
  798. *
  799. * Function : error_response
  800. *
  801. * Description : returns an http_response that explains the reason
  802. * why a request failed.
  803. *
  804. * Parameters :
  805. * 1 : csp = Current client state (buffers, headers, etc...)
  806. * 2 : templatename = Which template should be used for the answer
  807. *
  808. * Returns : A http_response. If we run out of memory, this
  809. * will be cgi_error_memory().
  810. *
  811. *********************************************************************/
  812. struct http_response *error_response(struct client_state *csp,
  813. const char *templatename)
  814. {
  815. jb_err err;
  816. struct http_response *rsp;
  817. struct map *exports = default_exports(csp, NULL);
  818. char *path = NULL;
  819. if (exports == NULL)
  820. {
  821. return cgi_error_memory();
  822. }
  823. if (NULL == (rsp = alloc_http_response()))
  824. {
  825. free_map(exports);
  826. return cgi_error_memory();
  827. }
  828. #ifdef FEATURE_FORCE_LOAD
  829. if (csp->flags & CSP_FLAG_FORCED)
  830. {
  831. path = strdup(FORCE_PREFIX);
  832. }
  833. else
  834. #endif /* def FEATURE_FORCE_LOAD */
  835. {
  836. path = strdup("");
  837. }
  838. err = string_append(&path, csp->http->path);
  839. if (!err) err = map(exports, "host", 1, html_encode(csp->http->host), 0);
  840. if (!err) err = map(exports, "hostport", 1, html_encode(csp->http->hostport), 0);
  841. if (!err) err = map(exports, "path", 1, html_encode_and_free_original(path), 0);
  842. if (!err) err = map(exports, "protocol", 1, csp->http->ssl ? "https://" : "http://", 1);
  843. if (!err)
  844. {
  845. err = map(exports, "host-ip", 1, html_encode(csp->http->host_ip_addr_str), 0);
  846. if (err)
  847. {
  848. /* Some failures, like "404 no such domain", don't have an IP address. */
  849. err = map(exports, "host-ip", 1, html_encode(csp->http->host), 0);
  850. }
  851. }
  852. if (err)
  853. {
  854. free_map(exports);
  855. free_http_response(rsp);
  856. return cgi_error_memory();
  857. }
  858. if (!strcmp(templatename, "no-such-domain"))
  859. {
  860. rsp->status = strdup("404 No such domain");
  861. rsp->crunch_reason = NO_SUCH_DOMAIN;
  862. }
  863. else if (!strcmp(templatename, "forwarding-failed"))
  864. {
  865. const struct forward_spec *fwd = forward_url(csp, csp->http);
  866. char *socks_type = NULL;
  867. if (fwd == NULL)
  868. {
  869. log_error(LOG_LEVEL_FATAL, "gateway spec is NULL. This shouldn't happen!");
  870. /* Never get here - LOG_LEVEL_FATAL causes program exit */
  871. }
  872. /*
  873. * XXX: While the template is called forwarding-failed,
  874. * it currently only handles socks forwarding failures.
  875. */
  876. assert(fwd != NULL);
  877. assert(fwd->type != SOCKS_NONE);
  878. /*
  879. * Map failure reason, forwarding type and forwarder.
  880. */
  881. if (NULL == csp->error_message)
  882. {
  883. /*
  884. * Either we forgot to record the failure reason,
  885. * or the memory allocation failed.
  886. */
  887. log_error(LOG_LEVEL_ERROR, "Socks failure reason missing.");
  888. csp->error_message = strdup("Failure reason missing. Check the log file for details.");
  889. }
  890. if (!err) err = map(exports, "gateway", 1, fwd->gateway_host, 1);
  891. /*
  892. * XXX: this is almost the same code as in cgi_show_url_info()
  893. * and thus should be factored out and shared.
  894. */
  895. switch (fwd->type)
  896. {
  897. case SOCKS_4:
  898. socks_type = "socks4-";
  899. break;
  900. case SOCKS_4A:
  901. socks_type = "socks4a-";
  902. break;
  903. case SOCKS_5:
  904. socks_type = "socks5-";
  905. break;
  906. case SOCKS_5T:
  907. socks_type = "socks5t-";
  908. break;
  909. case FORWARD_WEBSERVER:
  910. socks_type = "webserver-";
  911. break;
  912. default:
  913. log_error(LOG_LEVEL_FATAL, "Unknown socks type: %d.", fwd->type);
  914. }
  915. if (!err) err = map(exports, "forwarding-type", 1, socks_type, 1);
  916. if (!err) err = map(exports, "error-message", 1, html_encode(csp->error_message), 0);
  917. if ((NULL == csp->error_message) || err)
  918. {
  919. free_map(exports);
  920. free_http_response(rsp);
  921. return cgi_error_memory();
  922. }
  923. rsp->status = strdup("503 Forwarding failure");
  924. rsp->crunch_reason = FORWARDING_FAILED;
  925. }
  926. else if (!strcmp(templatename, "connect-failed"))
  927. {
  928. rsp->status = strdup("503 Connect failed");
  929. rsp->crunch_reason = CONNECT_FAILED;
  930. }
  931. else if (!strcmp(templatename, "connection-timeout"))
  932. {
  933. rsp->status = strdup("504 Connection timeout");
  934. rsp->crunch_reason = CONNECTION_TIMEOUT;
  935. }
  936. else if (!strcmp(templatename, "no-server-data"))
  937. {
  938. rsp->status = strdup("502 No data received from server or forwarder");
  939. rsp->crunch_reason = NO_SERVER_DATA;
  940. }
  941. if (rsp->status == NULL)
  942. {
  943. free_map(exports);
  944. free_http_response(rsp);
  945. return cgi_error_memory();
  946. }
  947. err = template_fill_for_cgi(csp, templatename, exports, rsp);
  948. if (err)
  949. {
  950. free_http_response(rsp);
  951. return cgi_error_memory();
  952. }
  953. return finish_http_response(csp, rsp);
  954. }
  955. /*********************************************************************
  956. *
  957. * Function : cgi_error_disabled
  958. *
  959. * Description : CGI function that is called to generate an error
  960. * response if the actions editor or toggle CGI are
  961. * accessed despite having being disabled at compile-
  962. * or run-time, or if the user followed an untrusted link
  963. * to access a unsafe CGI feature that is only reachable
  964. * through Privoxy directly.
  965. *
  966. * Parameters :
  967. * 1 : csp = Current client state (buffers, headers, etc...)
  968. * 2 : rsp = http_response data structure for output
  969. *
  970. * CGI Parameters : none
  971. *
  972. * Returns : JB_ERR_OK on success
  973. * JB_ERR_MEMORY on out-of-memory error.
  974. *
  975. *********************************************************************/
  976. jb_err cgi_error_disabled(const struct client_state *csp,
  977. struct http_response *rsp)
  978. {
  979. struct map *exports;
  980. assert(csp);
  981. assert(rsp);
  982. rsp->status = strdup_or_die("403 Request not trusted or feature disabled");
  983. if (NULL == (exports = default_exports(csp, "cgi-error-disabled")))
  984. {
  985. return JB_ERR_MEMORY;
  986. }
  987. if (map(exports, "url", 1, html_encode(csp->http->url), 0))
  988. {
  989. /* Not important enough to do anything */
  990. log_error(LOG_LEVEL_ERROR, "Failed to fill in url.");
  991. }
  992. return template_fill_for_cgi(csp, "cgi-error-disabled", exports, rsp);
  993. }
  994. /*********************************************************************
  995. *
  996. * Function : cgi_init_error_messages
  997. *
  998. * Description : Call at the start of the program to initialize
  999. * the error message used by cgi_error_memory().
  1000. *
  1001. * Parameters : N/A
  1002. *
  1003. * Returns : N/A
  1004. *
  1005. *********************************************************************/
  1006. void cgi_init_error_messages(void)
  1007. {
  1008. memset(cgi_error_memory_response, '\0', sizeof(*cgi_error_memory_response));
  1009. cgi_error_memory_response->head =
  1010. "HTTP/1.0 500 Internal Privoxy Error\r\n"
  1011. "Content-Type: text/html\r\n"
  1012. "\r\n";
  1013. cgi_error_memory_response->body =
  1014. "<html>\n"
  1015. "<head>\n"
  1016. " <title>500 Internal Privoxy Error</title>\n"
  1017. " <link rel=\"shortcut icon\" href=\"" CGI_PREFIX "error-favicon.ico\" type=\"image/x-icon\">"
  1018. "</head>\n"
  1019. "<body>\n"
  1020. "<h1>500 Internal Privoxy Error</h1>\n"
  1021. "<p>Privoxy <b>ran out of memory</b> while processing your request.</p>\n"
  1022. "<p>Please contact your proxy administrator, or try again later</p>\n"
  1023. "</body>\n"
  1024. "</html>\n";
  1025. cgi_error_memory_response->head_length =
  1026. strlen(cgi_error_memory_response->head);
  1027. cgi_error_memory_response->content_length =
  1028. strlen(cgi_error_memory_response->body);
  1029. cgi_error_memory_response->crunch_reason = OUT_OF_MEMORY;
  1030. }
  1031. /*********************************************************************
  1032. *
  1033. * Function : cgi_error_memory
  1034. *
  1035. * Description : Called if a CGI function runs out of memory.
  1036. * Returns a statically-allocated error response.
  1037. *
  1038. * Parameters : N/A
  1039. *
  1040. * Returns : http_response data structure for output. This is
  1041. * statically allocated, for obvious reasons.
  1042. *
  1043. *********************************************************************/
  1044. struct http_response *cgi_error_memory(void)
  1045. {
  1046. /* assert that it's been initialized. */
  1047. assert(cgi_error_memory_response->head);
  1048. return cgi_error_memory_response;
  1049. }
  1050. /*********************************************************************
  1051. *
  1052. * Function : cgi_error_no_template
  1053. *
  1054. * Description : Almost-CGI function that is called if a template
  1055. * cannot be loaded. Note this is not a true CGI,
  1056. * it takes a template name rather than a map of
  1057. * parameters.
  1058. *
  1059. * Parameters :
  1060. * 1 : csp = Current client state (buffers, headers, etc...)
  1061. * 2 : rsp = http_response data structure for output
  1062. * 3 : template_name = Name of template that could not
  1063. * be loaded.
  1064. *
  1065. * Returns : JB_ERR_OK on success
  1066. * JB_ERR_MEMORY on out-of-memory error.
  1067. *
  1068. *********************************************************************/
  1069. jb_err cgi_error_no_template(const struct client_state *csp,
  1070. struct http_response *rsp,
  1071. const char *template_name)
  1072. {
  1073. static const char status[] =
  1074. "500 Internal Privoxy Error";
  1075. static const char body_prefix[] =
  1076. "<html>\n"
  1077. "<head>\n"
  1078. " <title>500 Internal Privoxy Error</title>\n"
  1079. " <link rel=\"shortcut icon\" href=\"" CGI_PREFIX "error-favicon.ico\" type=\"image/x-icon\">"
  1080. "</head>\n"
  1081. "<body>\n"
  1082. "<h1>500 Internal Privoxy Error</h1>\n"
  1083. "<p>Privoxy encountered an error while processing your request:</p>\n"
  1084. "<p><b>Could not load template file <code>";
  1085. static const char body_suffix[] =
  1086. "</code> or one of its included components.</b></p>\n"
  1087. "<p>Please contact your proxy administrator.</p>\n"
  1088. "<p>If you are the proxy administrator, please put the required file(s)"
  1089. "in the <code><i>(confdir)</i>/templates</code> directory. The "
  1090. "location of the <code><i>(confdir)</i></code> directory "
  1091. "is specified in the main Privoxy <code>config</code> "
  1092. "file. (It's typically the Privoxy install directory"
  1093. #ifndef _WIN32
  1094. ", or <code>/etc/privoxy/</code>"
  1095. #endif /* ndef _WIN32 */
  1096. ").</p>\n"
  1097. "</body>\n"
  1098. "</html>\n";
  1099. const size_t body_size = strlen(body_prefix) + strlen(template_name) + strlen(body_suffix) + 1;
  1100. assert(csp);
  1101. assert(rsp);
  1102. assert(template_name);
  1103. /* Reset rsp, if needed */
  1104. freez(rsp->status);
  1105. freez(rsp->head);
  1106. freez(rsp->body);
  1107. rsp->content_length = 0;
  1108. rsp->head_length = 0;
  1109. rsp->is_static = 0;
  1110. rsp->body = malloc_or_die(body_size);
  1111. strlcpy(rsp->body, body_prefix, body_size);
  1112. strlcat(rsp->body, template_name, body_size);
  1113. strlcat(rsp->body, body_suffix, body_size);
  1114. rsp->status = strdup(status);
  1115. if (rsp->status == NULL)
  1116. {
  1117. return JB_ERR_MEMORY;
  1118. }
  1119. return JB_ERR_OK;
  1120. }
  1121. /*********************************************************************
  1122. *
  1123. * Function : cgi_error_unknown
  1124. *
  1125. * Description : Almost-CGI function that is called if an unexpected
  1126. * error occurs in the top-level CGI dispatcher.
  1127. * In this context, "unexpected" means "anything other
  1128. * than JB_ERR_MEMORY or JB_ERR_CGI_PARAMS" - CGIs are
  1129. * expected to handle all other errors internally,
  1130. * since they can give more relevant error messages
  1131. * that way.
  1132. *
  1133. * Note this is not a true CGI, it takes an error
  1134. * code rather than a map of parameters.
  1135. *
  1136. * Parameters :
  1137. * 1 : csp = Current client state (buffers, headers, etc...)
  1138. * 2 : rsp = http_response data structure for output
  1139. * 3 : error_to_report = Error code to report.
  1140. *
  1141. * Returns : JB_ERR_OK on success
  1142. * JB_ERR_MEMORY on out-of-memory error.
  1143. *
  1144. *********************************************************************/
  1145. jb_err cgi_error_unknown(const struct client_state *csp,
  1146. struct http_response *rsp,
  1147. jb_err error_to_report)
  1148. {
  1149. static const char status[] =
  1150. "500 Internal Privoxy Error";
  1151. static const char body_prefix[] =
  1152. "<html>\n"
  1153. "<head>\n"
  1154. " <title>500 Internal Privoxy Error</title>\n"
  1155. " <link rel=\"shortcut icon\" href=\"" CGI_PREFIX "error-favicon.ico\" type=\"image/x-icon\">"
  1156. "</head>\n"
  1157. "<body>\n"
  1158. "<h1>500 Internal Privoxy Error</h1>\n"
  1159. "<p>Privoxy encountered an error while processing your request:</p>\n"
  1160. "<p><b>Unexpected internal error: ";
  1161. static const char body_suffix[] =
  1162. "</b></p>\n"
  1163. "<p>Please "
  1164. "<a href=\"http://sourceforge.net/tracker/?group_id=11118&amp;atid=111118\">"
  1165. "file a bug report</a>.</p>\n"
  1166. "</body>\n"
  1167. "</html>\n";
  1168. /* Includes room for larger error numbers in the future. */
  1169. const size_t body_size = sizeof(body_prefix) + sizeof(body_suffix) + 5;
  1170. assert(csp);
  1171. assert(rsp);
  1172. /* Reset rsp, if needed */
  1173. freez(rsp->status);
  1174. freez(rsp->head);
  1175. freez(rsp->body);
  1176. rsp->content_length = 0;
  1177. rsp->head_length = 0;
  1178. rsp->is_static = 0;
  1179. rsp->crunch_reason = INTERNAL_ERROR;
  1180. rsp->body = malloc_or_die(body_size);
  1181. snprintf(rsp->body, body_size, "%s%d%s", body_prefix, error_to_report, body_suffix);
  1182. rsp->status = strdup(status);
  1183. if (rsp->status == NULL)
  1184. {
  1185. return JB_ERR_MEMORY;
  1186. }
  1187. return JB_ERR_OK;
  1188. }
  1189. /*********************************************************************
  1190. *
  1191. * Function : cgi_error_bad_param
  1192. *
  1193. * Description : CGI function that is called if the parameters
  1194. * (query string) for a CGI were wrong.
  1195. *
  1196. * Parameters :
  1197. * 1 : csp = Current client state (buffers, headers, etc...)
  1198. * 2 : rsp = http_response data structure for output
  1199. *
  1200. * CGI Parameters : none
  1201. *
  1202. * Returns : JB_ERR_OK on success
  1203. * JB_ERR_MEMORY on out-of-memory error.
  1204. *
  1205. *********************************************************************/
  1206. jb_err cgi_error_bad_param(const struct client_state *csp,
  1207. struct http_response *rsp)
  1208. {
  1209. struct map *exports;
  1210. assert(csp);
  1211. assert(rsp);
  1212. if (NULL == (exports = default_exports(csp, NULL)))
  1213. {
  1214. return JB_ERR_MEMORY;
  1215. }
  1216. return template_fill_for_cgi(csp, "cgi-error-bad-param", exports, rsp);
  1217. }
  1218. /*********************************************************************
  1219. *
  1220. * Function : cgi_redirect
  1221. *
  1222. * Description : CGI support function to generate a HTTP redirect
  1223. * message
  1224. *
  1225. * Parameters :
  1226. * 1 : rsp = http_response data structure for output
  1227. * 2 : target = string with the target URL
  1228. *
  1229. * CGI Parameters : None
  1230. *
  1231. * Returns : JB_ERR_OK on success
  1232. * JB_ERR_MEMORY on out-of-memory error.
  1233. *
  1234. *********************************************************************/
  1235. jb_err cgi_redirect (struct http_response * rsp, const char *target)
  1236. {
  1237. jb_err err;
  1238. assert(rsp);
  1239. assert(target);
  1240. err = enlist_unique_header(rsp->headers, "Location", target);
  1241. rsp->status = strdup("302 Local Redirect from Privoxy");
  1242. if (rsp->status == NULL)
  1243. {
  1244. return JB_ERR_MEMORY;
  1245. }
  1246. return err;
  1247. }
  1248. /*********************************************************************
  1249. *
  1250. * Function : add_help_link
  1251. *
  1252. * Description : Produce a copy of the string given as item,
  1253. * embedded in an HTML link to its corresponding
  1254. * section (item name in uppercase) in the actions
  1255. * chapter of the user manual, (whose URL is given in
  1256. * the config and defaults to our web site).
  1257. *
  1258. * FIXME: I currently only work for actions, and would
  1259. * like to be generalized for other topics.
  1260. *
  1261. * Parameters :
  1262. * 1 : item = item (will NOT be free()d.)
  1263. * It is assumed to be HTML-safe.
  1264. * 2 : config = The current configuration.
  1265. *
  1266. * Returns : String with item embedded in link, or NULL on
  1267. * out-of-memory
  1268. *
  1269. *********************************************************************/
  1270. char *add_help_link(const char *item,
  1271. struct configuration_spec *config)
  1272. {
  1273. char *result;
  1274. if (!item) return NULL;
  1275. result = strdup("<a href=\"");
  1276. if (!strncmpic(config->usermanual, "file://", 7) ||
  1277. !strncmpic(config->usermanual, "http", 4))
  1278. {
  1279. string_append(&result, config->usermanual);
  1280. }
  1281. else
  1282. {
  1283. string_append(&result, "http://");
  1284. string_append(&result, CGI_SITE_2_HOST);
  1285. string_append(&result, "/user-manual/");
  1286. }
  1287. string_append(&result, ACTIONS_HELP_PREFIX);
  1288. string_join (&result, string_toupper(item));
  1289. string_append(&result, "\">");
  1290. string_append(&result, item);
  1291. string_append(&result, "</a>");
  1292. return result;
  1293. }
  1294. /*********************************************************************
  1295. *
  1296. * Function : get_http_time
  1297. *
  1298. * Description : Get the time in a format suitable for use in a
  1299. * HTTP header - e.g.:
  1300. * "Sun, 06 Nov 1994 08:49:37 GMT"
  1301. *
  1302. * Parameters :
  1303. * 1 : time_offset = Time returned will be current time
  1304. * plus this number of seconds.
  1305. * 2 : buf = Destination for result.
  1306. * 3 : buffer_size = Size of the buffer above. Must be big
  1307. * enough to hold 29 characters plus a
  1308. * trailing zero.
  1309. *
  1310. * Returns : N/A
  1311. *
  1312. *********************************************************************/
  1313. void get_http_time(int time_offset, char *buf, size_t buffer_size)
  1314. {
  1315. struct tm *t;
  1316. time_t current_time;
  1317. #if defined(HAVE_GMTIME_R)
  1318. struct tm dummy;
  1319. #endif
  1320. assert(buf);
  1321. assert(buffer_size > (size_t)29);
  1322. time(&current_time);
  1323. current_time += time_offset;
  1324. /* get and save the gmt */
  1325. #if HAVE_GMTIME_R
  1326. t = gmtime_r(&current_time, &dummy);
  1327. #elif defined(MUTEX_LOCKS_AVAILABLE)
  1328. privoxy_mutex_lock(&gmtime_mutex);
  1329. t = gmtime(&current_time);
  1330. privoxy_mutex_unlock(&gmtime_mutex);
  1331. #else
  1332. t = gmtime(&current_time);
  1333. #endif
  1334. strftime(buf, buffer_size, "%a, %d %b %Y %H:%M:%S GMT", t);
  1335. }
  1336. /*********************************************************************
  1337. *
  1338. * Function : get_locale_time
  1339. *
  1340. * Description : Get the time in a date(1)-like format
  1341. * according to the current locale - e.g.:
  1342. * "Fri Aug 29 19:37:12 CEST 2008"
  1343. *
  1344. * XXX: Should we allow the user to change the format?
  1345. *
  1346. * Parameters :
  1347. * 1 : buf = Destination for result.
  1348. * 2 : buffer_size = Size of the buffer above. Must be big
  1349. * enough to hold 29 characters plus a
  1350. * trailing zero.
  1351. *
  1352. * Returns : N/A
  1353. *
  1354. *********************************************************************/
  1355. static void get_locale_time(char *buf, size_t buffer_size)
  1356. {
  1357. struct tm *timeptr;
  1358. time_t current_time;
  1359. #if defined(HAVE_LOCALTIME_R)
  1360. struct tm dummy;
  1361. #endif
  1362. assert(buf);
  1363. assert(buffer_size > (size_t)29);
  1364. time(&current_time);
  1365. #if HAVE_LOCALTIME_R
  1366. timeptr = localtime_r(&current_time, &dummy);
  1367. #elif defined(MUTEX_LOCKS_AVAILABLE)
  1368. privoxy_mutex_lock(&localtime_mutex);
  1369. timeptr = localtime(&current_time);
  1370. #else
  1371. timeptr = localtime(&current_time);
  1372. #endif
  1373. strftime(buf, buffer_size, "%a %b %d %X %Z %Y", timeptr);
  1374. #if !defined(HAVE_LOCALTIME_R) && defined(MUTEX_LOCKS_AVAILABLE)
  1375. privoxy_mutex_unlock(&localtime_mutex);
  1376. #endif
  1377. }
  1378. #ifdef FEATURE_COMPRESSION
  1379. /*********************************************************************
  1380. *
  1381. * Function : compress_buffer
  1382. *
  1383. * Description : Compresses the content of a buffer with zlib's deflate
  1384. * Allocates a new buffer for the result, free'ing it is
  1385. * up to the caller.
  1386. *
  1387. * Parameters :
  1388. * 1 : buffer = buffer whose content should be compressed
  1389. * 2 : buffer_length = length of the buffer
  1390. * 3 : compression_level = compression level for compress2()
  1391. *
  1392. * Returns : NULL on error, otherwise a pointer to the compressed
  1393. * content of the input buffer.
  1394. *
  1395. *********************************************************************/
  1396. char *compress_buffer(char *buffer, size_t *buffer_length, int compression_level)
  1397. {
  1398. char *compressed_buffer;
  1399. uLongf new_length;
  1400. assert(-1 <= compression_level && compression_level <= 9);
  1401. /* Let zlib figure out the maximum length of the compressed data */
  1402. new_length = compressBound((uLongf)*buffer_length);
  1403. compressed_buffer = malloc_or_die(new_length);
  1404. if (Z_OK != compress2((Bytef *)compressed_buffer, &new_length,
  1405. (Bytef *)buffer, *buffer_length, compression_level))
  1406. {
  1407. log_error(LOG_LEVEL_ERROR,
  1408. "compress2() failed. Buffer size: %lu, compression level: %d.",
  1409. new_length, compression_level);
  1410. freez(compressed_buffer);
  1411. return NULL;
  1412. }
  1413. log_error(LOG_LEVEL_RE_FILTER,
  1414. "Compressed content from %lu to %lu bytes. Compression level: %d",
  1415. *buffer_length, new_length, compression_level);
  1416. *buffer_length = (size_t)new_length;
  1417. return compressed_buffer;
  1418. }
  1419. #endif
  1420. /*********************************************************************
  1421. *
  1422. * Function : finish_http_response
  1423. *
  1424. * Description : Fill in the missing headers in an http response,
  1425. * and flatten the headers to an http head.
  1426. * For HEAD requests the body is freed once
  1427. * the Content-Length header is set.
  1428. *
  1429. * Parameters :
  1430. * 1 : rsp = pointer to http_response to be processed
  1431. *
  1432. * Returns : A http_response, usually the rsp parameter.
  1433. * On error, free()s rsp and returns cgi_error_memory()
  1434. *
  1435. *********************************************************************/
  1436. struct http_response *finish_http_response(struct client_state *csp, struct http_response *rsp)
  1437. {
  1438. char buf[BUFFER_SIZE];
  1439. jb_err err;
  1440. /* Special case - do NOT change this statically allocated response,
  1441. * which is ready for output anyway.
  1442. */
  1443. if (rsp == cgi_error_memory_response)
  1444. {
  1445. return rsp;
  1446. }
  1447. /*
  1448. * Add "Cross-origin resource sharing" (CORS) headers if enabled
  1449. */
  1450. if (NULL != csp->config->cors_allowed_origin)
  1451. {
  1452. enlist_unique_header(rsp->headers, "Access-Control-Allow-Origin",
  1453. csp->config->cors_allowed_origin);
  1454. enlist_unique_header(rsp->headers, "Access-Control-Allow-Methods", "GET,POST");
  1455. enlist_unique_header(rsp->headers, "Access-Control-Allow-Headers", "X-Requested-With");
  1456. enlist_unique_header(rsp->headers, "Access-Control-Max-Age", "86400");
  1457. }
  1458. /*
  1459. * Fill in the HTTP Status, using HTTP/1.1
  1460. * unless the client asked for HTTP/1.0.
  1461. */
  1462. snprintf(buf, sizeof(buf), "%s %s",
  1463. strcmpic(csp->http->version, "HTTP/1.0") ? "HTTP/1.1" : "HTTP/1.0",
  1464. rsp->status ? rsp->status : "200 OK");
  1465. err = enlist_first(rsp->headers, buf);
  1466. /*
  1467. * Set the Content-Length
  1468. */
  1469. if (rsp->content_length == 0)
  1470. {
  1471. rsp->content_length = rsp->body ? strlen(rsp->body) : 0;
  1472. }
  1473. #ifdef FEATURE_COMPRESSION
  1474. if (!err && (csp->flags & CSP_FLAG_CLIENT_SUPPORTS_DEFLATE)
  1475. && (rsp->content_length > LOWER_LENGTH_LIMIT_FOR_COMPRESSION))
  1476. {
  1477. char *compressed_content;
  1478. compressed_content = compress_buffer(rsp->body, &rsp->content_length,
  1479. csp->config->compression_level);
  1480. if (NULL != compressed_content)
  1481. {
  1482. freez(rsp->body);
  1483. rsp->body = compressed_content;
  1484. err = enlist_unique_header(rsp->headers, "Content-Encoding", "deflate");
  1485. }
  1486. }
  1487. #endif
  1488. if (!err)
  1489. {
  1490. snprintf(buf, sizeof(buf), "Content-Length: %d", (int)rsp->content_length);
  1491. /*
  1492. * Signal serve() that the client will be able to figure out
  1493. * the end of the response without having to close the connection.
  1494. */
  1495. csp->flags |= CSP_FLAG_SERVER_CONTENT_LENGTH_SET;
  1496. err = enlist(rsp->headers, buf);
  1497. }
  1498. if (0 == strcmpic(csp->http->gpc, "head"))
  1499. {
  1500. /*
  1501. * The client only asked for the head. Dispose
  1502. * the body and log an offensive message.
  1503. *
  1504. * While it may seem to be a bit inefficient to
  1505. * prepare the body if it isn't needed, it's the
  1506. * only way to get the Content-Length right for
  1507. * dynamic pages. We could have disposed the body
  1508. * earlier, but not without duplicating the
  1509. * Content-Length setting code above.
  1510. */
  1511. log_error(LOG_LEVEL_CGI, "Preparing to give head to %s.", csp->ip_addr_str);
  1512. freez(rsp->body);
  1513. rsp->content_length = 0;
  1514. }
  1515. if (strncmpic(rsp->status, "302", 3))
  1516. {
  1517. /*
  1518. * If it's not a redirect without any content,
  1519. * set the Content-Type to text/html if it's
  1520. * not already specified.
  1521. */
  1522. if (!err) err = enlist_unique(rsp->headers, "Content-Type: text/html", 13);
  1523. }
  1524. /*
  1525. * Fill in the rest of the default headers:
  1526. *
  1527. * Date: set to current date/time.
  1528. * Last-Modified: set to date/time the page was last changed.
  1529. * Expires: set to date/time page next needs reloading.
  1530. * Cache-Control: set to "no-cache" if applicable.
  1531. *
  1532. * See http://www.w3.org/Protocols/rfc2068/rfc2068
  1533. */
  1534. if (rsp->is_static)
  1535. {
  1536. /*
  1537. * Set Expires to about 10 min into the future so it'll get reloaded
  1538. * occasionally, e.g. if Privoxy gets upgraded.
  1539. */
  1540. if (!err)
  1541. {
  1542. get_http_time(0, buf, sizeof(buf));
  1543. err = enlist_unique_header(rsp->headers, "Date", buf);
  1544. }
  1545. /* Some date in the past. */
  1546. if (!err) err = enlist_unique_header(rsp->headers, "Last-Modified", "Sat, 17 Jun 2000 12:00:00 GMT");
  1547. if (!err)
  1548. {
  1549. get_http_time(10 * 60, buf, sizeof(buf)); /* 10 * 60sec = 10 minutes */
  1550. err = enlist_unique_header(rsp->headers, "Expires", buf);
  1551. }
  1552. }
  1553. else if (!strncmpic(rsp->status, "302", 3))
  1554. {
  1555. get_http_time(0, buf, sizeof(buf));
  1556. if (!err) err = enlist_unique_header(rsp->headers, "Date", buf);
  1557. }
  1558. else
  1559. {
  1560. /*
  1561. * Setting "Cache-Control" to "no-cache" and "Expires" to
  1562. * the current time doesn't exactly forbid caching, it just
  1563. * requires the client to revalidate the cached copy.
  1564. *
  1565. * If a temporary problem occurs and the user tries again after
  1566. * getting Privoxy's error message, a compliant browser may set the
  1567. * If-Modified-Since header with the content of the error page's
  1568. * Last-Modified header. More often than not, the document on the server
  1569. * is older than Privoxy's error message, the server would send status code
  1570. * 304 and the browser would display the outdated error message again and again.
  1571. *
  1572. * For documents delivered with status code 403, 404 and 503 we set "Last-Modified"
  1573. * to Tim Berners-Lee's birthday, which predates the age of any page on the web
  1574. * and can be safely used to "revalidate" without getting a status code 304.
  1575. *
  1576. * There is no need to let the useless If-Modified-Since header reach the
  1577. * server, it is therefore stripped by client_if_modified_since in parsers.c.
  1578. */
  1579. if (!err) err = enlist_unique_header(rsp->headers, "Cache-Control", "no-cache");
  1580. get_http_time(0, buf, sizeof(buf));
  1581. if (!err) err = enlist_unique_header(rsp->headers, "Date", buf);
  1582. if (!strncmpic(rsp->status, "403", 3)
  1583. || !strncmpic(rsp->status, "404", 3)
  1584. || !strncmpic(rsp->status, "502", 3)
  1585. || !strncmpic(rsp->status, "503", 3)
  1586. || !strncmpic(rsp->status, "504", 3))
  1587. {
  1588. if (!err) err = enlist_unique_header(rsp->headers, "Last-Modified", "Wed, 08 Jun 1955 12:00:00 GMT");
  1589. }
  1590. else
  1591. {
  1592. if (!err) err = enlist_unique_header(rsp->headers, "Last-Modified", buf);
  1593. }
  1594. if (!err) err = enlist_unique_header(rsp->headers, "Expires", "Sat, 17 Jun 2000 12:00:00 GMT");
  1595. if (!err) err = enlist_unique_header(rsp->headers, "Pragma", "no-cache");
  1596. }
  1597. if (!err && (!(csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
  1598. || (csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED)))
  1599. {
  1600. err = enlist_unique_header(rsp->headers, "Connection", "close");
  1601. }
  1602. /*
  1603. * Write the head
  1604. */
  1605. if (err || (NULL == (rsp->head = list_to_text(rsp->headers))))
  1606. {
  1607. free_http_response(rsp);
  1608. return cgi_error_memory();
  1609. }
  1610. rsp->head_length = strlen(rsp->head);
  1611. return rsp;
  1612. }
  1613. /*********************************************************************
  1614. *
  1615. * Function : alloc_http_response
  1616. *
  1617. * Description : Allocates a new http_response structure.
  1618. *
  1619. * Parameters : N/A
  1620. *
  1621. * Returns : pointer to a new http_response, or NULL.
  1622. *
  1623. *********************************************************************/
  1624. struct http_response *alloc_http_response(void)
  1625. {
  1626. return (struct http_response *) zalloc(sizeof(struct http_response));
  1627. }
  1628. /*********************************************************************
  1629. *
  1630. * Function : free_http_response
  1631. *
  1632. * Description : Free the memory occupied by an http_response
  1633. * and its depandant structures.
  1634. *
  1635. * Parameters :
  1636. * 1 : rsp = pointer to http_response to be freed
  1637. *
  1638. * Returns : N/A
  1639. *
  1640. *********************************************************************/
  1641. void free_http_response(struct http_response *rsp)
  1642. {
  1643. /*
  1644. * Must special case cgi_error_memory_response, which is never freed.
  1645. */
  1646. if (rsp && (rsp != cgi_error_memory_response))
  1647. {
  1648. freez(rsp->status);
  1649. freez(rsp->head);
  1650. freez(rsp->body);
  1651. destroy_list(rsp->headers);
  1652. free(rsp);
  1653. }
  1654. }
  1655. /*********************************************************************
  1656. *
  1657. * Function : template_load
  1658. *
  1659. * Description : CGI support function that loads a given HTML
  1660. * template, ignoring comment lines and following
  1661. * #include statements up to a depth of 1.
  1662. *
  1663. * Parameters :
  1664. * 1 : csp = Current client state (buffers, headers, etc...)
  1665. * 2 : template_ptr = Destination for pointer to loaded
  1666. * template text.
  1667. * 3 : templatename = name of the HTML template to be used
  1668. * 4 : recursive = Flag set if this function calls itself
  1669. * following an #include statament
  1670. *
  1671. * Returns : JB_ERR_OK on success
  1672. * JB_ERR_MEMORY on out-of-memory error.
  1673. * JB_ERR_FILE if the template file cannot be read
  1674. *
  1675. *********************************************************************/
  1676. jb_err template_load(const struct client_state *csp, char **template_ptr,
  1677. const char *templatename, int recursive)
  1678. {
  1679. jb_err err;
  1680. char *templates_dir_path;
  1681. char *full_path;
  1682. char *file_buffer;
  1683. char *included_module;
  1684. const char *p;
  1685. FILE *fp;
  1686. char buf[BUFFER_SIZE];
  1687. assert(csp);
  1688. assert(template_ptr);
  1689. assert(templatename);
  1690. *template_ptr = NULL;
  1691. /* Validate template name. Paranoia. */
  1692. for (p = templatename; *p != 0; p++)
  1693. {
  1694. if ( ((*p < 'a') || (*p > 'z'))
  1695. && ((*p < 'A') || (*p > 'Z'))
  1696. && ((*p < '0') || (*p > '9'))
  1697. && (*p != '-')
  1698. && (*p != '.'))
  1699. {
  1700. /* Illegal character */
  1701. return JB_ERR_FILE;
  1702. }
  1703. }
  1704. /*
  1705. * Generate full path using either templdir
  1706. * or confdir/templates as base directory.
  1707. */
  1708. if (NULL != csp->config->templdir)
  1709. {
  1710. templates_dir_path = strdup(csp->config->templdir);
  1711. }
  1712. else
  1713. {
  1714. templates_dir_path = make_path(csp->config->confdir, "templates");
  1715. }
  1716. if (templates_dir_path == NULL)
  1717. {
  1718. log_error(LOG_LEVEL_ERROR, "Out of memory while generating template path for %s.",
  1719. templatename);
  1720. return JB_ERR_MEMORY;
  1721. }
  1722. full_path = make_path(templates_dir_path, templatename);
  1723. free(templates_dir_path);
  1724. if (full_path == NULL)
  1725. {
  1726. log_error(LOG_LEVEL_ERROR, "Out of memory while generating full template path for %s.",
  1727. templatename);
  1728. return JB_ERR_MEMORY;
  1729. }
  1730. /* Allocate buffer */
  1731. file_buffer = strdup("");
  1732. if (file_buffer == NULL)
  1733. {
  1734. log_error(LOG_LEVEL_ERROR, "Not enough free memory to buffer %s.", full_path);
  1735. free(full_path);
  1736. return JB_ERR_MEMORY;
  1737. }
  1738. /* Open template file */
  1739. if (NULL == (fp = fopen(full_path, "r")))
  1740. {
  1741. log_error(LOG_LEVEL_ERROR, "Cannot open template file %s: %E", full_path);
  1742. free(full_path);
  1743. free(file_buffer);
  1744. return JB_ERR_FILE;
  1745. }
  1746. free(full_path);
  1747. /*
  1748. * Read the file, ignoring comments, and honoring #include
  1749. * statements, unless we're already called recursively.
  1750. *
  1751. * XXX: The comment handling could break with lines lengths > sizeof(buf).
  1752. * This is unlikely in practise.
  1753. */
  1754. while (fgets(buf, sizeof(buf), fp))
  1755. {
  1756. if (!recursive && !strncmp(buf, "#include ", 9))
  1757. {
  1758. if (JB_ERR_OK != (err = template_load(csp, &included_module, chomp(buf + 9), 1)))
  1759. {
  1760. free(file_buffer);
  1761. fclose(fp);
  1762. return err;
  1763. }
  1764. if (string_join(&file_buffer, included_module))
  1765. {
  1766. fclose(fp);
  1767. return JB_ERR_MEMORY;
  1768. }
  1769. continue;
  1770. }
  1771. /* skip lines starting with '#' */
  1772. if (*buf == '#')
  1773. {
  1774. continue;
  1775. }
  1776. if (string_append(&file_buffer, buf))
  1777. {
  1778. fclose(fp);
  1779. return JB_ERR_MEMORY;
  1780. }
  1781. }
  1782. fclose(fp);
  1783. *template_ptr = file_buffer;
  1784. return JB_ERR_OK;
  1785. }
  1786. /*********************************************************************
  1787. *
  1788. * Function : template_fill
  1789. *
  1790. * Description : CGI support function that fills in a pre-loaded
  1791. * HTML template by replacing @name@ with value using
  1792. * pcrs, for each item in the output map.
  1793. *
  1794. * Note that a leading '$' character in the export map's
  1795. * values will be stripped and toggle on backreference
  1796. * interpretation.
  1797. *
  1798. * Parameters :
  1799. * 1 : template_ptr = IN: Template to be filled out.
  1800. * Will be free()d.
  1801. * OUT: Filled out template.
  1802. * Caller must free().
  1803. * 2 : exports = map with fill in symbol -> name pairs
  1804. *
  1805. * Returns : JB_ERR_OK on success (and for uncritical errors)
  1806. * JB_ERR_MEMORY on out-of-memory error
  1807. *
  1808. *********************************************************************/
  1809. jb_err template_fill(char **template_ptr, const struct map *exports)
  1810. {
  1811. struct map_entry *m;
  1812. pcrs_job *job;
  1813. char buf[BUFFER_SIZE];
  1814. char *tmp_out_buffer;
  1815. char *file_buffer;
  1816. size_t size;
  1817. int error;
  1818. const char *flags;
  1819. assert(template_ptr);
  1820. assert(*template_ptr);
  1821. assert(exports);
  1822. file_buffer = *template_ptr;
  1823. size = strlen(file_buffer) + 1;
  1824. /*
  1825. * Assemble pcrs joblist from exports map
  1826. */
  1827. for (m = exports->first; m != NULL; m = m->next)
  1828. {
  1829. if (*m->name == '$')
  1830. {
  1831. /*
  1832. * First character of name is '$', so remove this flag
  1833. * character and allow backreferences ($1 etc) in the
  1834. * "replace with" text.
  1835. */
  1836. snprintf(buf, sizeof(buf), "%s", m->name + 1);
  1837. flags = "sigU";
  1838. }
  1839. else
  1840. {
  1841. /*
  1842. * Treat the "replace with" text as a literal string -
  1843. * no quoting needed, no backreferences allowed.
  1844. * ("Trivial" ['T'] flag).
  1845. */
  1846. flags = "sigTU";
  1847. /* Enclose name in @@ */
  1848. snprintf(buf, sizeof(buf), "@%s@", m->name);
  1849. }
  1850. log_error(LOG_LEVEL_CGI, "Substituting: s/%s/%s/%s", buf, m->value, flags);
  1851. /* Make and run job. */
  1852. job = pcrs_compile(buf, m->value, flags, &error);
  1853. if (job == NULL)
  1854. {
  1855. if (error == PCRS_ERR_NOMEM)
  1856. {
  1857. free(file_buffer);
  1858. *template_ptr = NULL;
  1859. return JB_ERR_MEMORY;
  1860. }
  1861. else
  1862. {
  1863. log_error(LOG_LEVEL_ERROR, "Error compiling template fill job %s: %d", m->name, error);
  1864. /* Hope it wasn't important and silently ignore the invalid job */
  1865. }
  1866. }
  1867. else
  1868. {
  1869. error = pcrs_execute(job, file_buffer, size, &tmp_out_buffer, &size);
  1870. pcrs_free_job(job);
  1871. if (NULL == tmp_out_buffer)
  1872. {
  1873. *template_ptr = NULL;
  1874. return JB_ERR_MEMORY;
  1875. }
  1876. if (error < 0)
  1877. {
  1878. /*
  1879. * Substitution failed, keep the original buffer,
  1880. * log the problem and ignore it.
  1881. *
  1882. * The user might see some unresolved @CGI_VARIABLES@,
  1883. * but returning a special CGI error page seems unreasonable
  1884. * and could mask more important error messages.
  1885. */
  1886. free(tmp_out_buffer);
  1887. log_error(LOG_LEVEL_ERROR, "Failed to execute s/%s/%s/%s. %s",
  1888. buf, m->value, flags, pcrs_strerror(error));
  1889. }
  1890. else
  1891. {
  1892. /* Substitution succeeded, use modified buffer. */
  1893. free(file_buffer);
  1894. file_buffer = tmp_out_buffer;
  1895. }
  1896. }
  1897. }
  1898. /*
  1899. * Return
  1900. */
  1901. *template_ptr = file_buffer;
  1902. return JB_ERR_OK;
  1903. }
  1904. /*********************************************************************
  1905. *
  1906. * Function : template_fill_for_cgi
  1907. *
  1908. * Description : CGI support function that loads a HTML template
  1909. * and fills it in. Handles file-not-found errors
  1910. * by sending a HTML error message. For convenience,
  1911. * this function also frees the passed "exports" map.
  1912. *
  1913. * Parameters :
  1914. * 1 : csp = Client state
  1915. * 2 : templatename = name of the HTML template to be used
  1916. * 3 : exports = map with fill in symbol -> name pairs.
  1917. * Will be freed by this function.
  1918. * 4 : rsp = Response structure to fill in.
  1919. *
  1920. * Returns : JB_ERR_OK on success
  1921. * JB_ERR_MEMORY on out-of-memory error
  1922. *
  1923. *********************************************************************/
  1924. jb_err template_fill_for_cgi(const struct client_state *csp,
  1925. const char *templatename,
  1926. struct map *exports,
  1927. struct http_response *rsp)
  1928. {
  1929. jb_err err;
  1930. assert(csp);
  1931. assert(templatename);
  1932. assert(exports);
  1933. assert(rsp);
  1934. err = template_load(csp, &rsp->body, templatename, 0);
  1935. if (err == JB_ERR_FILE)
  1936. {
  1937. err = cgi_error_no_template(csp, rsp, templatename);
  1938. }
  1939. else if (err == JB_ERR_OK)
  1940. {
  1941. err = template_fill(&rsp->body, exports);
  1942. }
  1943. free_map(exports);
  1944. return err;
  1945. }
  1946. /*********************************************************************
  1947. *
  1948. * Function : default_exports
  1949. *
  1950. * Description : returns a struct map list that contains exports
  1951. * which are common to all CGI functions.
  1952. *
  1953. * Parameters :
  1954. * 1 : csp = Current client state (buffers, headers, etc...)
  1955. * 2 : caller = name of CGI who calls us and which should
  1956. * be excluded from the generated menu. May be
  1957. * NULL.
  1958. * Returns : NULL if no memory, else a new map. Caller frees.
  1959. *
  1960. *********************************************************************/
  1961. struct map *default_exports(const struct client_state *csp, const char *caller)
  1962. {
  1963. char buf[30];
  1964. jb_err err;
  1965. struct map * exports;
  1966. int local_help_exists = 0;
  1967. char *ip_address = NULL;
  1968. char *port = NULL;
  1969. char *hostname = NULL;
  1970. assert(csp);
  1971. exports = new_map();
  1972. if (csp->config->hostname)
  1973. {
  1974. get_host_information(csp->cfd, &ip_address, &port, NULL);
  1975. hostname = strdup(csp->config->hostname);
  1976. }
  1977. else
  1978. {
  1979. get_host_information(csp->cfd, &ip_address, &port, &hostname);
  1980. }
  1981. err = map(exports, "version", 1, html_encode(VERSION), 0);
  1982. get_locale_time(buf, sizeof(buf));
  1983. if (!err) err = map(exports, "time", 1, html_encode(buf), 0);
  1984. if (!err) err = map(exports, "my-ip-address", 1, html_encode(ip_address ? ip_address : "unknown"), 0);
  1985. freez(ip_address);
  1986. if (!err) err = map(exports, "my-port", 1, html_encode(port ? port : "unknown"), 0);
  1987. freez(port);
  1988. if (!err) err = map(exports, "my-hostname", 1, html_encode(hostname ? hostname : "unknown"), 0);
  1989. freez(hostname);
  1990. if (!err) err = map(exports, "homepage", 1, html_encode(HOME_PAGE_URL), 0);
  1991. if (!err)
  1992. {
  1993. err = map(exports, "default-cgi", 1, html_encode(
  1994. #ifdef FEATURE_HTTPS_INSPECTION
  1995. client_use_ssl(csp) ? CGI_PREFIX_HTTPS :
  1996. #endif
  1997. CGI_PREFIX), 0);
  1998. }
  1999. if (!err) err = map(exports, "menu", 1, make_menu(csp, caller), 0);
  2000. if (!err) err = map(exports, "code-status", 1, CODE_STATUS, 1);
  2001. if (!strncmpic(csp->config->usermanual, "file://", 7) ||
  2002. !strncmpic(csp->config->usermanual, "http", 4))
  2003. {
  2004. /* Manual is located somewhere else, just link to it. */
  2005. if (!err) err = map(exports, "user-manual", 1, html_encode(csp->config->usermanual), 0);
  2006. }
  2007. else
  2008. {
  2009. /* Manual is delivered by Privoxy. */
  2010. if (!err)
  2011. {
  2012. err = map(exports, "user-manual", 1, html_encode(
  2013. #ifdef FEATURE_HTTPS_INSPECTION
  2014. client_use_ssl(csp) ? CGI_PREFIX_HTTPS"user-manual/" :
  2015. #endif
  2016. CGI_PREFIX"user-manual/"), 0);
  2017. }
  2018. }
  2019. if (!err) err = map(exports, "actions-help-prefix", 1, ACTIONS_HELP_PREFIX ,1);
  2020. #ifdef FEATURE_TOGGLE
  2021. if (!err) err = map_conditional(exports, "enabled-display", global_toggle_state);
  2022. #else
  2023. if (!err) err = map_block_killer(exports, "can-toggle");
  2024. #endif
  2025. if (!strcmp(CODE_STATUS, "stable"))
  2026. {
  2027. if (!err) err = map_block_killer(exports, "unstable");
  2028. }
  2029. if (csp->config->admin_address != NULL)
  2030. {
  2031. if (!err) err = map(exports, "admin-address", 1, html_encode(csp->config->admin_address), 0);
  2032. local_help_exists = 1;
  2033. }
  2034. else
  2035. {
  2036. if (!err) err = map_block_killer(exports, "have-adminaddr-info");
  2037. }
  2038. if (csp->config->proxy_info_url != NULL)
  2039. {
  2040. if (!err) err = map(exports, "proxy-info-url", 1, html_encode(csp->config->proxy_info_url), 0);
  2041. local_help_exists = 1;
  2042. }
  2043. else
  2044. {
  2045. if (!err) err = map_block_killer(exports, "have-proxy-info");
  2046. }
  2047. if (local_help_exists == 0)
  2048. {
  2049. if (!err) err = map_block_killer(exports, "have-help-info");
  2050. }
  2051. if (err)
  2052. {
  2053. free_map(exports);
  2054. return NULL;
  2055. }
  2056. return exports;
  2057. }
  2058. /*********************************************************************
  2059. *
  2060. * Function : map_block_killer
  2061. *
  2062. * Description : Convenience function.
  2063. * Adds a "killer" for the conditional HTML-template
  2064. * block <name>, i.e. a substitution of the regex
  2065. * "if-<name>-start.*if-<name>-end" to the given
  2066. * export list.
  2067. *
  2068. * Parameters :
  2069. * 1 : exports = map to extend
  2070. * 2 : name = name of conditional block
  2071. *
  2072. * Returns : JB_ERR_OK on success
  2073. * JB_ERR_MEMORY on out-of-memory error.
  2074. *
  2075. *********************************************************************/
  2076. jb_err map_block_killer(struct map *exports, const char *name)
  2077. {
  2078. char buf[1000]; /* Will do, since the names are hardwired */
  2079. assert(exports);
  2080. assert(name);
  2081. assert(strlen(name) < (size_t)490);
  2082. snprintf(buf, sizeof(buf), "if-%s-start.*if-%s-end", name, name);
  2083. return map(exports, buf, 1, "", 1);
  2084. }
  2085. /*********************************************************************
  2086. *
  2087. * Function : map_block_keep
  2088. *
  2089. * Description : Convenience function. Removes the markers used
  2090. * by map-block-killer, to save a few bytes.
  2091. * i.e. removes "@if-<name>-start@" and "@if-<name>-end@"
  2092. *
  2093. * Parameters :
  2094. * 1 : exports = map to extend
  2095. * 2 : name = name of conditional block
  2096. *
  2097. * Returns : JB_ERR_OK on success
  2098. * JB_ERR_MEMORY on out-of-memory error.
  2099. *
  2100. *********************************************************************/
  2101. jb_err map_block_keep(struct map *exports, const char *name)
  2102. {
  2103. jb_err err;
  2104. char buf[500]; /* Will do, since the names are hardwired */
  2105. assert(exports);
  2106. assert(name);
  2107. assert(strlen(name) < (size_t)490);
  2108. snprintf(buf, sizeof(buf), "if-%s-start", name);
  2109. err = map(exports, buf, 1, "", 1);
  2110. if (err)
  2111. {
  2112. return err;
  2113. }
  2114. snprintf(buf, sizeof(buf), "if-%s-end", name);
  2115. return map(exports, buf, 1, "", 1);
  2116. }
  2117. /*********************************************************************
  2118. *
  2119. * Function : map_conditional
  2120. *
  2121. * Description : Convenience function.
  2122. * Adds an "if-then-else" for the conditional HTML-template
  2123. * block <name>, i.e. a substitution of the form:
  2124. * @if-<name>-then@
  2125. * True text
  2126. * @else-not-<name>@
  2127. * False text
  2128. * @endif-<name>@
  2129. *
  2130. * The control structure and one of the alternatives
  2131. * will be hidden.
  2132. *
  2133. * Parameters :
  2134. * 1 : exports = map to extend
  2135. * 2 : name = name of conditional block
  2136. * 3 : choose_first = nonzero for first, zero for second.
  2137. *
  2138. * Returns : JB_ERR_OK on success
  2139. * JB_ERR_MEMORY on out-of-memory error.
  2140. *
  2141. *********************************************************************/
  2142. jb_err map_conditional(struct map *exports, const char *name, int choose_first)
  2143. {
  2144. char buf[1000]; /* Will do, since the names are hardwired */
  2145. jb_err err;
  2146. assert(exports);
  2147. assert(name);
  2148. assert(strlen(name) < (size_t)480);
  2149. snprintf(buf, sizeof(buf), (choose_first
  2150. ? "else-not-%s@.*@endif-%s"
  2151. : "if-%s-then@.*@else-not-%s"),
  2152. name, name);
  2153. err = map(exports, buf, 1, "", 1);
  2154. if (err)
  2155. {
  2156. return err;
  2157. }
  2158. snprintf(buf, sizeof(buf), (choose_first ? "if-%s-then" : "endif-%s"), name);
  2159. return map(exports, buf, 1, "", 1);
  2160. }
  2161. /*********************************************************************
  2162. *
  2163. * Function : make_menu
  2164. *
  2165. * Description : Returns an HTML-formatted menu of the available
  2166. * unhidden CGIs, excluding the one given in <self>
  2167. * and the toggle CGI if toggling is disabled.
  2168. *
  2169. * Parameters :
  2170. * 1 : csp = Current client state (buffers, headers, etc...)
  2171. * 2 : self = name of CGI to leave out, can be NULL for
  2172. * complete listing.
  2173. *
  2174. * Returns : menu string, or NULL on out-of-memory error.
  2175. *
  2176. *********************************************************************/
  2177. char *make_menu(const struct client_state *csp, const char *self)
  2178. {
  2179. const struct cgi_dispatcher *d;
  2180. char *result = strdup("");
  2181. if (self == NULL)
  2182. {
  2183. self = "NO-SUCH-CGI!";
  2184. }
  2185. /* List available unhidden CGI's and export as "other-cgis" */
  2186. for (d = cgi_dispatchers; d->name; d++)
  2187. {
  2188. #ifdef FEATURE_TOGGLE
  2189. if (!(csp->config->feature_flags & RUNTIME_FEATURE_CGI_TOGGLE) && !strcmp(d->name, "toggle"))
  2190. {
  2191. /*
  2192. * Suppress the toggle link if remote toggling is disabled.
  2193. */
  2194. continue;
  2195. }
  2196. #endif /* def FEATURE_TOGGLE */
  2197. if (d->description && strcmp(d->name, self))
  2198. {
  2199. char *html_encoded_prefix;
  2200. /*
  2201. * Line breaks would be great, but break
  2202. * the "blocked" template's JavaScript.
  2203. */
  2204. string_append(&result, "<li><a href=\"");
  2205. html_encoded_prefix = html_encode(
  2206. #ifdef FEATURE_HTTPS_INSPECTION
  2207. client_use_ssl(csp) ? CGI_PREFIX_HTTPS :
  2208. #endif
  2209. CGI_PREFIX);
  2210. if (html_encoded_prefix == NULL)
  2211. {
  2212. return NULL;
  2213. }
  2214. else
  2215. {
  2216. string_append(&result, html_encoded_prefix);
  2217. free(html_encoded_prefix);
  2218. }
  2219. string_append(&result, d->name);
  2220. string_append(&result, "\">");
  2221. string_append(&result, d->description);
  2222. string_append(&result, "</a></li>");
  2223. }
  2224. }
  2225. return result;
  2226. }
  2227. /*********************************************************************
  2228. *
  2229. * Function : dump_map
  2230. *
  2231. * Description : HTML-dump a map for debugging (as table)
  2232. *
  2233. * Parameters :
  2234. * 1 : the_map = map to dump
  2235. *
  2236. * Returns : string with HTML
  2237. *
  2238. *********************************************************************/
  2239. char *dump_map(const struct map *the_map)
  2240. {
  2241. struct map_entry *cur_entry;
  2242. char *ret = strdup("");
  2243. string_append(&ret, "<table>\n");
  2244. for (cur_entry = the_map->first;
  2245. (cur_entry != NULL) && (ret != NULL);
  2246. cur_entry = cur_entry->next)
  2247. {
  2248. string_append(&ret, "<tr><td><b>");
  2249. string_join (&ret, html_encode(cur_entry->name));
  2250. string_append(&ret, "</b></td><td>");
  2251. string_join (&ret, html_encode(cur_entry->value));
  2252. string_append(&ret, "</td></tr>\n");
  2253. }
  2254. string_append(&ret, "</table>\n");
  2255. return ret;
  2256. }
  2257. /*
  2258. Local Variables:
  2259. tab-width: 3
  2260. end:
  2261. */