You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

http.c 90KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "config.h"
  17. #include "../../contrib/mumhash/mum.h"
  18. #include "http_private.h"
  19. #include "utlist.h"
  20. #include "util.h"
  21. #include "printf.h"
  22. #include "logger.h"
  23. #include "ref.h"
  24. #include "ottery.h"
  25. #include "keypair_private.h"
  26. #include "cryptobox.h"
  27. #include "unix-std.h"
  28. #include "libutil/ssl_util.h"
  29. #include "libutil/regexp.h"
  30. #include "libserver/url.h"
  31. #include <openssl/err.h>
  32. #define ENCRYPTED_VERSION " HTTP/1.0"
  33. struct _rspamd_http_privbuf {
  34. rspamd_fstring_t *data;
  35. const gchar *zc_buf;
  36. gsize zc_remain;
  37. ref_entry_t ref;
  38. };
  39. enum rspamd_http_priv_flags {
  40. RSPAMD_HTTP_CONN_FLAG_ENCRYPTED = 1 << 0,
  41. RSPAMD_HTTP_CONN_FLAG_NEW_HEADER = 1 << 1,
  42. RSPAMD_HTTP_CONN_FLAG_RESETED = 1 << 2,
  43. RSPAMD_HTTP_CONN_FLAG_TOO_LARGE = 1 << 3,
  44. };
  45. #define IS_CONN_ENCRYPTED(c) ((c)->flags & RSPAMD_HTTP_CONN_FLAG_ENCRYPTED)
  46. #define IS_CONN_RESETED(c) ((c)->flags & RSPAMD_HTTP_CONN_FLAG_RESETED)
  47. struct rspamd_http_connection_private {
  48. gpointer ssl_ctx;
  49. struct rspamd_ssl_connection *ssl;
  50. struct _rspamd_http_privbuf *buf;
  51. struct rspamd_cryptobox_pubkey *peer_key;
  52. struct rspamd_cryptobox_keypair *local_key;
  53. struct rspamd_http_header *header;
  54. struct http_parser parser;
  55. struct http_parser_settings parser_cb;
  56. struct event ev;
  57. struct timeval tv;
  58. struct timeval *ptv;
  59. struct rspamd_http_message *msg;
  60. struct iovec *out;
  61. guint outlen;
  62. enum rspamd_http_priv_flags flags;
  63. gsize wr_pos;
  64. gsize wr_total;
  65. };
  66. enum http_magic_type {
  67. HTTP_MAGIC_PLAIN = 0,
  68. HTTP_MAGIC_HTML,
  69. HTTP_MAGIC_CSS,
  70. HTTP_MAGIC_JS,
  71. HTTP_MAGIC_PNG,
  72. HTTP_MAGIC_JPG
  73. };
  74. static const struct _rspamd_http_magic {
  75. const gchar *ext;
  76. const gchar *ct;
  77. } http_file_types[] = {
  78. [HTTP_MAGIC_PLAIN] = { "txt", "text/plain" },
  79. [HTTP_MAGIC_HTML] = { "html", "text/html" },
  80. [HTTP_MAGIC_CSS] = { "css", "text/css" },
  81. [HTTP_MAGIC_JS] = { "js", "application/javascript" },
  82. [HTTP_MAGIC_PNG] = { "png", "image/png" },
  83. [HTTP_MAGIC_JPG] = { "jpg", "image/jpeg" },
  84. };
  85. static const gchar *http_week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  86. static const gchar *http_month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  87. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  88. static const rspamd_ftok_t key_header = {
  89. .begin = "Key",
  90. .len = 3
  91. };
  92. static const rspamd_ftok_t date_header = {
  93. .begin = "Date",
  94. .len = 4
  95. };
  96. static const rspamd_ftok_t last_modified_header = {
  97. .begin = "Last-Modified",
  98. .len = 13
  99. };
  100. static void rspamd_http_message_storage_cleanup (struct rspamd_http_message *msg);
  101. static gboolean rspamd_http_message_grow_body (struct rspamd_http_message *msg,
  102. gsize len);
  103. #define HTTP_ERROR http_error_quark ()
  104. GQuark
  105. http_error_quark (void)
  106. {
  107. return g_quark_from_static_string ("http-error-quark");
  108. }
  109. static void
  110. rspamd_http_privbuf_dtor (gpointer ud)
  111. {
  112. struct _rspamd_http_privbuf *p = (struct _rspamd_http_privbuf *)ud;
  113. if (p->data) {
  114. rspamd_fstring_free (p->data);
  115. }
  116. g_free (p);
  117. }
  118. static const gchar *
  119. rspamd_http_code_to_str (gint code)
  120. {
  121. if (code == 200) {
  122. return "OK";
  123. }
  124. else if (code == 404) {
  125. return "Not found";
  126. }
  127. else if (code == 403 || code == 401) {
  128. return "Not authorized";
  129. }
  130. else if (code >= 400 && code < 500) {
  131. return "Bad request";
  132. }
  133. else if (code >= 300 && code < 400) {
  134. return "See Other";
  135. }
  136. else if (code >= 500 && code < 600) {
  137. return "Internal server error";
  138. }
  139. return "Unknown error";
  140. }
  141. /*
  142. * Obtained from nginx
  143. * Copyright (C) Igor Sysoev
  144. */
  145. static guint mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  146. time_t
  147. rspamd_http_parse_date (const gchar *header, gsize len)
  148. {
  149. const gchar *p, *end;
  150. gint month;
  151. guint day, year, hour, min, sec;
  152. guint64 time;
  153. enum {
  154. no = 0, rfc822, /* Tue, 10 Nov 2002 23:50:13 */
  155. rfc850, /* Tuesday, 10-Dec-02 23:50:13 */
  156. isoc /* Tue Dec 10 23:50:13 2002 */
  157. } fmt;
  158. fmt = 0;
  159. if (len > 0) {
  160. end = header + len;
  161. }
  162. else {
  163. end = header + strlen (header);
  164. }
  165. day = 32;
  166. year = 2038;
  167. for (p = header; p < end; p++) {
  168. if (*p == ',') {
  169. break;
  170. }
  171. if (*p == ' ') {
  172. fmt = isoc;
  173. break;
  174. }
  175. }
  176. for (p++; p < end; p++)
  177. if (*p != ' ') {
  178. break;
  179. }
  180. if (end - p < 18) {
  181. return (time_t)-1;
  182. }
  183. if (fmt != isoc) {
  184. if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
  185. return (time_t)-1;
  186. }
  187. day = (*p - '0') * 10 + *(p + 1) - '0';
  188. p += 2;
  189. if (*p == ' ') {
  190. if (end - p < 18) {
  191. return (time_t)-1;
  192. }
  193. fmt = rfc822;
  194. }
  195. else if (*p == '-') {
  196. fmt = rfc850;
  197. }
  198. else {
  199. return (time_t)-1;
  200. }
  201. p++;
  202. }
  203. switch (*p) {
  204. case 'J':
  205. month = *(p + 1) == 'a' ? 0 : *(p + 2) == 'n' ? 5 : 6;
  206. break;
  207. case 'F':
  208. month = 1;
  209. break;
  210. case 'M':
  211. month = *(p + 2) == 'r' ? 2 : 4;
  212. break;
  213. case 'A':
  214. month = *(p + 1) == 'p' ? 3 : 7;
  215. break;
  216. case 'S':
  217. month = 8;
  218. break;
  219. case 'O':
  220. month = 9;
  221. break;
  222. case 'N':
  223. month = 10;
  224. break;
  225. case 'D':
  226. month = 11;
  227. break;
  228. default:
  229. return (time_t)-1;
  230. }
  231. p += 3;
  232. if ((fmt == rfc822 && *p != ' ') || (fmt == rfc850 && *p != '-')) {
  233. return (time_t)-1;
  234. }
  235. p++;
  236. if (fmt == rfc822) {
  237. if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
  238. || *(p + 2) < '0' || *(p + 2) > '9' || *(p + 3) < '0'
  239. || *(p + 3) > '9') {
  240. return (time_t)-1;
  241. }
  242. year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
  243. + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
  244. p += 4;
  245. }
  246. else if (fmt == rfc850) {
  247. if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
  248. return (time_t)-1;
  249. }
  250. year = (*p - '0') * 10 + *(p + 1) - '0';
  251. year += (year < 70) ? 2000 : 1900;
  252. p += 2;
  253. }
  254. if (fmt == isoc) {
  255. if (*p == ' ') {
  256. p++;
  257. }
  258. if (*p < '0' || *p > '9') {
  259. return (time_t)-1;
  260. }
  261. day = *p++ - '0';
  262. if (*p != ' ') {
  263. if (*p < '0' || *p > '9') {
  264. return (time_t)-1;
  265. }
  266. day = day * 10 + *p++ - '0';
  267. }
  268. if (end - p < 14) {
  269. return (time_t)-1;
  270. }
  271. }
  272. if (*p++ != ' ') {
  273. return (time_t)-1;
  274. }
  275. if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
  276. return (time_t)-1;
  277. }
  278. hour = (*p - '0') * 10 + *(p + 1) - '0';
  279. p += 2;
  280. if (*p++ != ':') {
  281. return (time_t)-1;
  282. }
  283. if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
  284. return (time_t)-1;
  285. }
  286. min = (*p - '0') * 10 + *(p + 1) - '0';
  287. p += 2;
  288. if (*p++ != ':') {
  289. return (time_t)-1;
  290. }
  291. if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9') {
  292. return (time_t)-1;
  293. }
  294. sec = (*p - '0') * 10 + *(p + 1) - '0';
  295. if (fmt == isoc) {
  296. p += 2;
  297. if (*p++ != ' ') {
  298. return (time_t)-1;
  299. }
  300. if (*p < '0' || *p > '9' || *(p + 1) < '0' || *(p + 1) > '9'
  301. || *(p + 2) < '0' || *(p + 2) > '9' || *(p + 3) < '0'
  302. || *(p + 3) > '9') {
  303. return (time_t)-1;
  304. }
  305. year = (*p - '0') * 1000 + (*(p + 1) - '0') * 100
  306. + (*(p + 2) - '0') * 10 + *(p + 3) - '0';
  307. }
  308. if (hour > 23 || min > 59 || sec > 59) {
  309. return (time_t)-1;
  310. }
  311. if (day == 29 && month == 1) {
  312. if ((year & 3) || ((year % 100 == 0) && (year % 400) != 0)) {
  313. return (time_t)-1;
  314. }
  315. }
  316. else if (day > mday[month]) {
  317. return (time_t)-1;
  318. }
  319. /*
  320. * shift new year to March 1 and start months from 1 (not 0),
  321. * it is needed for Gauss' formula
  322. */
  323. if (--month <= 0) {
  324. month += 12;
  325. year -= 1;
  326. }
  327. /* Gauss' formula for Gregorian days since March 1, 1 BC */
  328. time = (guint64) (
  329. /* days in years including leap years since March 1, 1 BC */
  330. 365 * year + year / 4 - year / 100 + year / 400
  331. /* days before the month */
  332. + 367 * month / 12 - 30
  333. /* days before the day */
  334. + day - 1
  335. /*
  336. * 719527 days were between March 1, 1 BC and March 1, 1970,
  337. * 31 and 28 days were in January and February 1970
  338. */
  339. - 719527 + 31 + 28) * 86400 + hour * 3600 + min * 60 + sec;
  340. return (time_t) time;
  341. }
  342. static void
  343. rspamd_http_parse_key (rspamd_ftok_t *data, struct rspamd_http_connection *conn,
  344. struct rspamd_http_connection_private *priv)
  345. {
  346. guchar *decoded_id;
  347. const gchar *eq_pos;
  348. gsize id_len;
  349. struct rspamd_cryptobox_pubkey *pk;
  350. if (priv->local_key == NULL) {
  351. /* In this case we cannot do anything, e.g. we cannot decrypt payload */
  352. priv->flags |= RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
  353. }
  354. else {
  355. /* Check sanity of what we have */
  356. eq_pos = memchr (data->begin, '=', data->len);
  357. if (eq_pos != NULL) {
  358. decoded_id = rspamd_decode_base32 (data->begin, eq_pos - data->begin,
  359. &id_len);
  360. if (decoded_id != NULL && id_len >= RSPAMD_KEYPAIR_SHORT_ID_LEN) {
  361. pk = rspamd_pubkey_from_base32 (eq_pos + 1,
  362. data->begin + data->len - eq_pos - 1,
  363. RSPAMD_KEYPAIR_KEX,
  364. RSPAMD_CRYPTOBOX_MODE_25519);
  365. if (pk != NULL) {
  366. if (memcmp (rspamd_keypair_get_id (priv->local_key),
  367. decoded_id,
  368. RSPAMD_KEYPAIR_SHORT_ID_LEN) == 0) {
  369. priv->msg->peer_key = pk;
  370. if (conn->cache && priv->msg->peer_key) {
  371. rspamd_keypair_cache_process (conn->cache,
  372. priv->local_key, priv->msg->peer_key);
  373. }
  374. }
  375. else {
  376. rspamd_pubkey_unref (pk);
  377. }
  378. }
  379. }
  380. priv->flags |= RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
  381. g_free (decoded_id);
  382. }
  383. }
  384. }
  385. static inline void
  386. rspamd_http_check_special_header (struct rspamd_http_connection *conn,
  387. struct rspamd_http_connection_private *priv)
  388. {
  389. if (rspamd_ftok_casecmp (&priv->header->name, &date_header) == 0) {
  390. priv->msg->date = rspamd_http_parse_date (priv->header->value.begin,
  391. priv->header->value.len);
  392. }
  393. else if (rspamd_ftok_casecmp (&priv->header->name, &key_header) == 0) {
  394. rspamd_http_parse_key (&priv->header->value, conn, priv);
  395. }
  396. else if (rspamd_ftok_casecmp (&priv->header->name, &last_modified_header) == 0) {
  397. priv->msg->last_modified = rspamd_http_parse_date (
  398. priv->header->value.begin,
  399. priv->header->value.len);
  400. }
  401. }
  402. static gint
  403. rspamd_http_on_url (http_parser * parser, const gchar *at, size_t length)
  404. {
  405. struct rspamd_http_connection *conn =
  406. (struct rspamd_http_connection *)parser->data;
  407. struct rspamd_http_connection_private *priv;
  408. priv = conn->priv;
  409. priv->msg->url = rspamd_fstring_append (priv->msg->url, at, length);
  410. return 0;
  411. }
  412. static gint
  413. rspamd_http_on_status (http_parser * parser, const gchar *at, size_t length)
  414. {
  415. struct rspamd_http_connection *conn =
  416. (struct rspamd_http_connection *)parser->data;
  417. struct rspamd_http_connection_private *priv;
  418. priv = conn->priv;
  419. if (parser->status_code != 200) {
  420. if (priv->msg->status == NULL) {
  421. priv->msg->status = rspamd_fstring_new ();
  422. }
  423. priv->msg->status = rspamd_fstring_append (priv->msg->status, at, length);
  424. }
  425. return 0;
  426. }
  427. static void
  428. rspamd_http_finish_header (struct rspamd_http_connection *conn,
  429. struct rspamd_http_connection_private *priv)
  430. {
  431. struct rspamd_http_header *hdr;
  432. priv->header->combined = rspamd_fstring_append (priv->header->combined,
  433. "\r\n", 2);
  434. priv->header->value.len = priv->header->combined->len -
  435. priv->header->name.len - 4;
  436. priv->header->value.begin = priv->header->combined->str +
  437. priv->header->name.len + 2;
  438. priv->header->name.begin = priv->header->combined->str;
  439. HASH_FIND (hh, priv->msg->headers, priv->header->name.begin,
  440. priv->header->name.len, hdr);
  441. if (hdr == NULL) {
  442. HASH_ADD_KEYPTR (hh, priv->msg->headers, priv->header->name.begin,
  443. priv->header->name.len, priv->header);
  444. }
  445. DL_APPEND (hdr, priv->header);
  446. rspamd_http_check_special_header (conn, priv);
  447. }
  448. static void
  449. rspamd_http_init_header (struct rspamd_http_connection_private *priv)
  450. {
  451. priv->header = g_malloc0 (sizeof (struct rspamd_http_header));
  452. priv->header->combined = rspamd_fstring_new ();
  453. }
  454. static gint
  455. rspamd_http_on_header_field (http_parser * parser,
  456. const gchar *at,
  457. size_t length)
  458. {
  459. struct rspamd_http_connection *conn =
  460. (struct rspamd_http_connection *)parser->data;
  461. struct rspamd_http_connection_private *priv;
  462. priv = conn->priv;
  463. if (priv->header == NULL) {
  464. rspamd_http_init_header (priv);
  465. }
  466. else if (priv->flags & RSPAMD_HTTP_CONN_FLAG_NEW_HEADER) {
  467. rspamd_http_finish_header (conn, priv);
  468. rspamd_http_init_header (priv);
  469. }
  470. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
  471. priv->header->combined = rspamd_fstring_append (priv->header->combined,
  472. at, length);
  473. return 0;
  474. }
  475. static gint
  476. rspamd_http_on_header_value (http_parser * parser,
  477. const gchar *at,
  478. size_t length)
  479. {
  480. struct rspamd_http_connection *conn =
  481. (struct rspamd_http_connection *)parser->data;
  482. struct rspamd_http_connection_private *priv;
  483. priv = conn->priv;
  484. if (priv->header == NULL) {
  485. /* Should not happen */
  486. return -1;
  487. }
  488. if (!(priv->flags & RSPAMD_HTTP_CONN_FLAG_NEW_HEADER)) {
  489. priv->flags |= RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
  490. priv->header->combined = rspamd_fstring_append (priv->header->combined,
  491. ": ", 2);
  492. priv->header->name.len = priv->header->combined->len - 2;
  493. }
  494. priv->header->combined = rspamd_fstring_append (priv->header->combined,
  495. at, length);
  496. return 0;
  497. }
  498. static int
  499. rspamd_http_on_headers_complete (http_parser * parser)
  500. {
  501. struct rspamd_http_connection *conn =
  502. (struct rspamd_http_connection *)parser->data;
  503. struct rspamd_http_connection_private *priv;
  504. struct rspamd_http_message *msg;
  505. int ret;
  506. priv = conn->priv;
  507. msg = priv->msg;
  508. if (priv->header != NULL) {
  509. rspamd_http_finish_header (conn, priv);
  510. priv->header = NULL;
  511. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
  512. }
  513. if (msg->method == HTTP_HEAD) {
  514. /* We don't care about the rest */
  515. if (rspamd_event_pending (&priv->ev, EV_READ)) {
  516. event_del (&priv->ev);
  517. }
  518. msg->code = parser->status_code;
  519. rspamd_http_connection_ref (conn);
  520. ret = conn->finish_handler (conn, msg);
  521. conn->finished = TRUE;
  522. rspamd_http_connection_unref (conn);
  523. return ret;
  524. }
  525. /*
  526. * HTTP parser sets content length to (-1) when it doesn't know the real
  527. * length, for example, in case of chunked encoding.
  528. *
  529. * Hence, we skip body setup here
  530. */
  531. if (parser->content_length != ULLONG_MAX && parser->content_length != 0) {
  532. if (conn->max_size > 0 &&
  533. parser->content_length > conn->max_size) {
  534. /* Too large message */
  535. priv->flags |= RSPAMD_HTTP_CONN_FLAG_TOO_LARGE;
  536. return -1;
  537. }
  538. if (!rspamd_http_message_set_body (msg, NULL, parser->content_length)) {
  539. return -1;
  540. }
  541. }
  542. if (parser->flags & F_SPAMC) {
  543. msg->flags |= RSPAMD_HTTP_FLAG_SPAMC;
  544. }
  545. msg->method = parser->method;
  546. msg->code = parser->status_code;
  547. return 0;
  548. }
  549. static void
  550. rspamd_http_switch_zc (struct _rspamd_http_privbuf *pbuf,
  551. struct rspamd_http_message *msg)
  552. {
  553. pbuf->zc_buf = msg->body_buf.begin + msg->body_buf.len;
  554. pbuf->zc_remain = msg->body_buf.allocated_len - msg->body_buf.len;
  555. }
  556. static int
  557. rspamd_http_on_body (http_parser * parser, const gchar *at, size_t length)
  558. {
  559. struct rspamd_http_connection *conn =
  560. (struct rspamd_http_connection *)parser->data;
  561. struct rspamd_http_connection_private *priv;
  562. struct rspamd_http_message *msg;
  563. struct _rspamd_http_privbuf *pbuf;
  564. const gchar *p;
  565. priv = conn->priv;
  566. msg = priv->msg;
  567. pbuf = priv->buf;
  568. p = at;
  569. if (!(msg->flags & RSPAMD_HTTP_FLAG_HAS_BODY)) {
  570. if (!rspamd_http_message_set_body (msg, NULL, parser->content_length)) {
  571. return -1;
  572. }
  573. }
  574. if (conn->finished) {
  575. return 0;
  576. }
  577. if (conn->max_size > 0 &&
  578. msg->body_buf.len + length > conn->max_size) {
  579. /* Body length overflow */
  580. priv->flags |= RSPAMD_HTTP_CONN_FLAG_TOO_LARGE;
  581. return -1;
  582. }
  583. if (!pbuf->zc_buf) {
  584. if (!rspamd_http_message_append_body (msg, at, length)) {
  585. return -1;
  586. }
  587. /* We might have some leftover in our private buffer */
  588. if (pbuf->data->len == length) {
  589. /* Switch to zero-copy mode */
  590. rspamd_http_switch_zc (pbuf, msg);
  591. }
  592. }
  593. else {
  594. if (msg->body_buf.begin + msg->body_buf.len != at) {
  595. /* Likely chunked encoding */
  596. memmove ((gchar *)msg->body_buf.begin + msg->body_buf.len, at, length);
  597. p = msg->body_buf.begin + msg->body_buf.len;
  598. }
  599. /* Adjust zero-copy buf */
  600. msg->body_buf.len += length;
  601. if (!(msg->flags & RSPAMD_HTTP_FLAG_SHMEM)) {
  602. msg->body_buf.c.normal->len += length;
  603. }
  604. pbuf->zc_buf = msg->body_buf.begin + msg->body_buf.len;
  605. pbuf->zc_remain = msg->body_buf.allocated_len - msg->body_buf.len;
  606. }
  607. if ((conn->opts & RSPAMD_HTTP_BODY_PARTIAL) && !IS_CONN_ENCRYPTED (priv)) {
  608. /* Incremental update is impossible for encrypted requests so far */
  609. return (conn->body_handler (conn, msg, p, length));
  610. }
  611. return 0;
  612. }
  613. static int
  614. rspamd_http_on_body_decrypted (http_parser * parser, const gchar *at, size_t length)
  615. {
  616. struct rspamd_http_connection *conn =
  617. (struct rspamd_http_connection *)parser->data;
  618. struct rspamd_http_connection_private *priv;
  619. priv = conn->priv;
  620. if (priv->header != NULL) {
  621. rspamd_http_finish_header (conn, priv);
  622. priv->header = NULL;
  623. }
  624. if (conn->finished) {
  625. return 0;
  626. }
  627. if (priv->msg->body_buf.len == 0) {
  628. priv->msg->body_buf.begin = at;
  629. priv->msg->method = parser->method;
  630. priv->msg->code = parser->status_code;
  631. }
  632. priv->msg->body_buf.len += length;
  633. return 0;
  634. }
  635. static int
  636. rspamd_http_on_headers_complete_decrypted (http_parser *parser)
  637. {
  638. struct rspamd_http_connection *conn =
  639. (struct rspamd_http_connection *) parser->data;
  640. struct rspamd_http_connection_private *priv;
  641. struct rspamd_http_message *msg;
  642. int ret;
  643. priv = conn->priv;
  644. msg = priv->msg;
  645. if (priv->header != NULL) {
  646. rspamd_http_finish_header (conn, priv);
  647. priv->header = NULL;
  648. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
  649. }
  650. if (parser->flags & F_SPAMC) {
  651. priv->msg->flags |= RSPAMD_HTTP_FLAG_SPAMC;
  652. }
  653. if (msg->method == HTTP_HEAD) {
  654. /* We don't care about the rest */
  655. if (rspamd_event_pending (&priv->ev, EV_READ)) {
  656. event_del (&priv->ev);
  657. }
  658. msg->code = parser->status_code;
  659. rspamd_http_connection_ref (conn);
  660. ret = conn->finish_handler (conn, msg);
  661. conn->finished = TRUE;
  662. rspamd_http_connection_unref (conn);
  663. return ret;
  664. }
  665. priv->msg->method = parser->method;
  666. priv->msg->code = parser->status_code;
  667. return 0;
  668. }
  669. static int
  670. rspamd_http_decrypt_message (struct rspamd_http_connection *conn,
  671. struct rspamd_http_connection_private *priv,
  672. struct rspamd_cryptobox_pubkey *peer_key)
  673. {
  674. guchar *nonce, *m;
  675. const guchar *nm;
  676. gsize dec_len;
  677. struct rspamd_http_message *msg = priv->msg;
  678. struct rspamd_http_header *hdr, *hdrtmp, *hcur, *hcurtmp;
  679. struct http_parser decrypted_parser;
  680. struct http_parser_settings decrypted_cb;
  681. enum rspamd_cryptobox_mode mode;
  682. mode = rspamd_keypair_alg (priv->local_key);
  683. nonce = msg->body_buf.str;
  684. m = msg->body_buf.str + rspamd_cryptobox_nonce_bytes (mode) +
  685. rspamd_cryptobox_mac_bytes (mode);
  686. dec_len = msg->body_buf.len - rspamd_cryptobox_nonce_bytes (mode) -
  687. rspamd_cryptobox_mac_bytes (mode);
  688. if ((nm = rspamd_pubkey_get_nm (peer_key, priv->local_key)) == NULL) {
  689. nm = rspamd_pubkey_calculate_nm (peer_key, priv->local_key);
  690. }
  691. if (!rspamd_cryptobox_decrypt_nm_inplace (m, dec_len, nonce,
  692. nm, m - rspamd_cryptobox_mac_bytes (mode), mode)) {
  693. msg_err ("cannot verify encrypted message, first bytes of the input: %*xs",
  694. (gint)MIN(msg->body_buf.len, 64), msg->body_buf.begin);
  695. return -1;
  696. }
  697. /* Cleanup message */
  698. HASH_ITER (hh, msg->headers, hdr, hdrtmp) {
  699. HASH_DELETE (hh, msg->headers, hdr);
  700. DL_FOREACH_SAFE (hdr, hcur, hcurtmp) {
  701. rspamd_fstring_free (hcur->combined);
  702. g_free (hcur);
  703. }
  704. }
  705. msg->headers = NULL;
  706. if (msg->url != NULL) {
  707. msg->url = rspamd_fstring_assign (msg->url, "", 0);
  708. }
  709. msg->body_buf.len = 0;
  710. memset (&decrypted_parser, 0, sizeof (decrypted_parser));
  711. http_parser_init (&decrypted_parser,
  712. conn->type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE);
  713. memset (&decrypted_cb, 0, sizeof (decrypted_cb));
  714. decrypted_cb.on_url = rspamd_http_on_url;
  715. decrypted_cb.on_status = rspamd_http_on_status;
  716. decrypted_cb.on_header_field = rspamd_http_on_header_field;
  717. decrypted_cb.on_header_value = rspamd_http_on_header_value;
  718. decrypted_cb.on_headers_complete = rspamd_http_on_headers_complete_decrypted;
  719. decrypted_cb.on_body = rspamd_http_on_body_decrypted;
  720. decrypted_parser.data = conn;
  721. decrypted_parser.content_length = dec_len;
  722. if (http_parser_execute (&decrypted_parser, &decrypted_cb, m,
  723. dec_len) != (size_t)dec_len) {
  724. msg_err ("HTTP parser error: %s when parsing encrypted request",
  725. http_errno_description (decrypted_parser.http_errno));
  726. return -1;
  727. }
  728. return 0;
  729. }
  730. static int
  731. rspamd_http_on_message_complete (http_parser * parser)
  732. {
  733. struct rspamd_http_connection *conn =
  734. (struct rspamd_http_connection *)parser->data;
  735. struct rspamd_http_connection_private *priv;
  736. int ret = 0;
  737. enum rspamd_cryptobox_mode mode;
  738. if (conn->finished) {
  739. return 0;
  740. }
  741. priv = conn->priv;
  742. if ((conn->opts & RSPAMD_HTTP_BODY_PARTIAL) == 0 && IS_CONN_ENCRYPTED (priv)) {
  743. mode = rspamd_keypair_alg (priv->local_key);
  744. if (priv->local_key == NULL || priv->msg->peer_key == NULL ||
  745. priv->msg->body_buf.len < rspamd_cryptobox_nonce_bytes (mode) +
  746. rspamd_cryptobox_mac_bytes (mode)) {
  747. msg_err ("cannot decrypt message");
  748. return -1;
  749. }
  750. /* We have keys, so we can decrypt message */
  751. ret = rspamd_http_decrypt_message (conn, priv, priv->msg->peer_key);
  752. if (ret != 0) {
  753. return ret;
  754. }
  755. if (conn->body_handler != NULL) {
  756. rspamd_http_connection_ref (conn);
  757. ret = conn->body_handler (conn,
  758. priv->msg,
  759. priv->msg->body_buf.begin,
  760. priv->msg->body_buf.len);
  761. rspamd_http_connection_unref (conn);
  762. }
  763. }
  764. else if ((conn->opts & RSPAMD_HTTP_BODY_PARTIAL) == 0 && conn->body_handler) {
  765. g_assert (conn->body_handler != NULL);
  766. rspamd_http_connection_ref (conn);
  767. ret = conn->body_handler (conn,
  768. priv->msg,
  769. priv->msg->body_buf.begin,
  770. priv->msg->body_buf.len);
  771. rspamd_http_connection_unref (conn);
  772. }
  773. if (ret == 0) {
  774. if (rspamd_event_pending (&priv->ev, EV_READ)) {
  775. event_del (&priv->ev);
  776. }
  777. rspamd_http_connection_ref (conn);
  778. ret = conn->finish_handler (conn, priv->msg);
  779. conn->finished = TRUE;
  780. rspamd_http_connection_unref (conn);
  781. }
  782. return ret;
  783. }
  784. static void
  785. rspamd_http_simple_client_helper (struct rspamd_http_connection *conn)
  786. {
  787. struct event_base *base;
  788. struct rspamd_http_connection_private *priv;
  789. gpointer ssl;
  790. gint request_method;
  791. priv = conn->priv;
  792. base = conn->priv->ev.ev_base;
  793. ssl = priv->ssl;
  794. priv->ssl = NULL;
  795. request_method = priv->msg->method;
  796. rspamd_http_connection_reset (conn);
  797. priv->ssl = ssl;
  798. /* Plan read message */
  799. if (conn->opts & RSPAMD_HTTP_CLIENT_SHARED) {
  800. rspamd_http_connection_read_message_shared (conn, conn->ud, conn->fd,
  801. conn->priv->ptv, base);
  802. }
  803. else {
  804. rspamd_http_connection_read_message (conn, conn->ud, conn->fd,
  805. conn->priv->ptv, base);
  806. }
  807. priv->msg->method = request_method;
  808. }
  809. static void
  810. rspamd_http_write_helper (struct rspamd_http_connection *conn)
  811. {
  812. struct rspamd_http_connection_private *priv;
  813. struct iovec *start;
  814. guint niov, i;
  815. gint flags = 0;
  816. gsize remain;
  817. gssize r;
  818. GError *err;
  819. struct iovec *cur_iov;
  820. struct msghdr msg;
  821. priv = conn->priv;
  822. if (priv->wr_pos == priv->wr_total) {
  823. goto call_finish_handler;
  824. }
  825. start = &priv->out[0];
  826. niov = priv->outlen;
  827. remain = priv->wr_pos;
  828. /* We know that niov is small enough for that */
  829. cur_iov = alloca (niov * sizeof (struct iovec));
  830. memcpy (cur_iov, priv->out, niov * sizeof (struct iovec));
  831. for (i = 0; i < priv->outlen && remain > 0; i++) {
  832. /* Find out the first iov required */
  833. start = &cur_iov[i];
  834. if (start->iov_len <= remain) {
  835. remain -= start->iov_len;
  836. start = &cur_iov[i + 1];
  837. niov--;
  838. }
  839. else {
  840. start->iov_base = (void *)((char *)start->iov_base + remain);
  841. start->iov_len -= remain;
  842. remain = 0;
  843. }
  844. }
  845. memset (&msg, 0, sizeof (msg));
  846. msg.msg_iov = start;
  847. msg.msg_iovlen = MIN (IOV_MAX, niov);
  848. g_assert (niov > 0);
  849. #ifdef MSG_NOSIGNAL
  850. flags = MSG_NOSIGNAL;
  851. #endif
  852. if (priv->ssl) {
  853. r = rspamd_ssl_writev (priv->ssl, msg.msg_iov, msg.msg_iovlen);
  854. }
  855. else {
  856. r = sendmsg (conn->fd, &msg, flags);
  857. }
  858. if (r == -1) {
  859. if (!priv->ssl) {
  860. err = g_error_new (HTTP_ERROR, errno, "IO write error: %s", strerror (errno));
  861. rspamd_http_connection_ref (conn);
  862. conn->error_handler (conn, err);
  863. rspamd_http_connection_unref (conn);
  864. g_error_free (err);
  865. }
  866. return;
  867. }
  868. else {
  869. priv->wr_pos += r;
  870. }
  871. if (priv->wr_pos >= priv->wr_total) {
  872. goto call_finish_handler;
  873. }
  874. else {
  875. /* Want to write more */
  876. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_RESETED;
  877. event_add (&priv->ev, priv->ptv);
  878. }
  879. return;
  880. call_finish_handler:
  881. if ((conn->opts & RSPAMD_HTTP_CLIENT_SIMPLE) == 0) {
  882. rspamd_http_connection_ref (conn);
  883. conn->finished = TRUE;
  884. conn->finish_handler (conn, priv->msg);
  885. rspamd_http_connection_unref (conn);
  886. }
  887. else {
  888. /* Plan read message */
  889. rspamd_http_simple_client_helper (conn);
  890. }
  891. }
  892. static gssize
  893. rspamd_http_try_read (gint fd,
  894. struct rspamd_http_connection *conn,
  895. struct rspamd_http_connection_private *priv,
  896. struct _rspamd_http_privbuf *pbuf,
  897. const gchar **buf_ptr)
  898. {
  899. gssize r;
  900. gchar *data;
  901. gsize len;
  902. struct rspamd_http_message *msg;
  903. msg = priv->msg;
  904. if (pbuf->zc_buf == NULL) {
  905. data = priv->buf->data->str;
  906. len = priv->buf->data->allocated;
  907. }
  908. else {
  909. data = (gchar *)pbuf->zc_buf;
  910. len = pbuf->zc_remain;
  911. if (len == 0) {
  912. rspamd_http_message_grow_body (priv->msg, priv->buf->data->allocated);
  913. rspamd_http_switch_zc (pbuf, msg);
  914. data = (gchar *)pbuf->zc_buf;
  915. len = pbuf->zc_remain;
  916. }
  917. }
  918. if (priv->ssl) {
  919. r = rspamd_ssl_read (priv->ssl, data, len);
  920. }
  921. else {
  922. r = read (fd, data, len);
  923. }
  924. if (r <= 0) {
  925. return r;
  926. }
  927. else {
  928. if (pbuf->zc_buf == NULL) {
  929. priv->buf->data->len = r;
  930. }
  931. else {
  932. pbuf->zc_remain -= r;
  933. pbuf->zc_buf += r;
  934. }
  935. }
  936. if (buf_ptr) {
  937. *buf_ptr = data;
  938. }
  939. return r;
  940. }
  941. static void
  942. rspamd_http_ssl_err_handler (gpointer ud, GError *err)
  943. {
  944. struct rspamd_http_connection *conn = (struct rspamd_http_connection *)ud;
  945. rspamd_http_connection_ref (conn);
  946. conn->error_handler (conn, err);
  947. rspamd_http_connection_unref (conn);
  948. }
  949. static void
  950. rspamd_http_event_handler (int fd, short what, gpointer ud)
  951. {
  952. struct rspamd_http_connection *conn = (struct rspamd_http_connection *)ud;
  953. struct rspamd_http_connection_private *priv;
  954. struct _rspamd_http_privbuf *pbuf;
  955. const gchar *d;
  956. gssize r;
  957. GError *err;
  958. priv = conn->priv;
  959. pbuf = priv->buf;
  960. REF_RETAIN (pbuf);
  961. rspamd_http_connection_ref (conn);
  962. if (what == EV_READ) {
  963. r = rspamd_http_try_read (fd, conn, priv, pbuf, &d);
  964. if (r > 0) {
  965. if (http_parser_execute (&priv->parser, &priv->parser_cb,
  966. d, r) != (size_t)r || priv->parser.http_errno != 0) {
  967. if (priv->flags & RSPAMD_HTTP_CONN_FLAG_TOO_LARGE) {
  968. err = g_error_new (HTTP_ERROR, 413,
  969. "Request entity too large: %zu",
  970. (size_t)priv->parser.content_length);
  971. }
  972. else {
  973. err = g_error_new (HTTP_ERROR, priv->parser.http_errno,
  974. "HTTP parser error: %s",
  975. http_errno_description (priv->parser.http_errno));
  976. }
  977. if (!conn->finished) {
  978. conn->error_handler (conn, err);
  979. }
  980. else {
  981. msg_err ("got error after HTTP request is finished: %e", err);
  982. }
  983. g_error_free (err);
  984. REF_RELEASE (pbuf);
  985. rspamd_http_connection_unref (conn);
  986. return;
  987. }
  988. }
  989. else if (r == 0) {
  990. /* We can still call http parser */
  991. http_parser_execute (&priv->parser, &priv->parser_cb, d, r);
  992. if (!conn->finished) {
  993. err = g_error_new (HTTP_ERROR,
  994. errno,
  995. "IO read error: unexpected EOF");
  996. conn->error_handler (conn, err);
  997. g_error_free (err);
  998. }
  999. REF_RELEASE (pbuf);
  1000. rspamd_http_connection_unref (conn);
  1001. return;
  1002. }
  1003. else {
  1004. if (!priv->ssl) {
  1005. err = g_error_new (HTTP_ERROR,
  1006. errno,
  1007. "IO read error: %s",
  1008. strerror (errno));
  1009. conn->error_handler (conn, err);
  1010. g_error_free (err);
  1011. }
  1012. REF_RELEASE (pbuf);
  1013. rspamd_http_connection_unref (conn);
  1014. return;
  1015. }
  1016. }
  1017. else if (what == EV_TIMEOUT) {
  1018. /* Let's try to read from the socket first */
  1019. r = rspamd_http_try_read (fd, conn, priv, pbuf, &d);
  1020. if (r > 0) {
  1021. if (http_parser_execute (&priv->parser, &priv->parser_cb,
  1022. d, r) != (size_t)r || priv->parser.http_errno != 0) {
  1023. err = g_error_new (HTTP_ERROR, priv->parser.http_errno,
  1024. "HTTP parser error: %s",
  1025. http_errno_description (priv->parser.http_errno));
  1026. if (!conn->finished) {
  1027. conn->error_handler (conn, err);
  1028. }
  1029. else {
  1030. msg_err ("got error after HTTP request is finished: %e", err);
  1031. }
  1032. g_error_free (err);
  1033. REF_RELEASE (pbuf);
  1034. rspamd_http_connection_unref (conn);
  1035. return;
  1036. }
  1037. }
  1038. else if (r == 0) {
  1039. if (!conn->finished) {
  1040. err = g_error_new (HTTP_ERROR, ETIMEDOUT,
  1041. "IO timeout");
  1042. conn->error_handler (conn, err);
  1043. g_error_free (err);
  1044. }
  1045. REF_RELEASE (pbuf);
  1046. rspamd_http_connection_unref (conn);
  1047. return;
  1048. }
  1049. else {
  1050. err = g_error_new (HTTP_ERROR, ETIMEDOUT,
  1051. "IO timeout");
  1052. conn->error_handler (conn, err);
  1053. g_error_free (err);
  1054. REF_RELEASE (pbuf);
  1055. rspamd_http_connection_unref (conn);
  1056. return;
  1057. }
  1058. }
  1059. else if (what == EV_WRITE) {
  1060. rspamd_http_write_helper (conn);
  1061. }
  1062. REF_RELEASE (pbuf);
  1063. rspamd_http_connection_unref (conn);
  1064. }
  1065. static void
  1066. rspamd_http_parser_reset (struct rspamd_http_connection *conn)
  1067. {
  1068. struct rspamd_http_connection_private *priv = conn->priv;
  1069. http_parser_init (&priv->parser,
  1070. conn->type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE);
  1071. priv->parser_cb.on_url = rspamd_http_on_url;
  1072. priv->parser_cb.on_status = rspamd_http_on_status;
  1073. priv->parser_cb.on_header_field = rspamd_http_on_header_field;
  1074. priv->parser_cb.on_header_value = rspamd_http_on_header_value;
  1075. priv->parser_cb.on_headers_complete = rspamd_http_on_headers_complete;
  1076. priv->parser_cb.on_body = rspamd_http_on_body;
  1077. priv->parser_cb.on_message_complete = rspamd_http_on_message_complete;
  1078. }
  1079. struct rspamd_http_connection *
  1080. rspamd_http_connection_new (
  1081. rspamd_http_body_handler_t body_handler,
  1082. rspamd_http_error_handler_t error_handler,
  1083. rspamd_http_finish_handler_t finish_handler,
  1084. unsigned opts,
  1085. enum rspamd_http_connection_type type,
  1086. struct rspamd_keypair_cache *cache,
  1087. gpointer ssl_ctx)
  1088. {
  1089. struct rspamd_http_connection *conn;
  1090. struct rspamd_http_connection_private *priv;
  1091. if (error_handler == NULL || finish_handler == NULL) {
  1092. return NULL;
  1093. }
  1094. conn = g_malloc0 (sizeof (struct rspamd_http_connection));
  1095. conn->opts = opts;
  1096. conn->type = type;
  1097. conn->body_handler = body_handler;
  1098. conn->error_handler = error_handler;
  1099. conn->finish_handler = finish_handler;
  1100. conn->fd = -1;
  1101. conn->ref = 1;
  1102. conn->finished = FALSE;
  1103. conn->cache = cache;
  1104. /* Init priv */
  1105. priv = g_malloc0 (sizeof (struct rspamd_http_connection_private));
  1106. conn->priv = priv;
  1107. priv->ssl_ctx = ssl_ctx;
  1108. rspamd_http_parser_reset (conn);
  1109. priv->parser.data = conn;
  1110. return conn;
  1111. }
  1112. void
  1113. rspamd_http_connection_reset (struct rspamd_http_connection *conn)
  1114. {
  1115. struct rspamd_http_connection_private *priv;
  1116. struct rspamd_http_message *msg;
  1117. priv = conn->priv;
  1118. msg = priv->msg;
  1119. /* Clear request */
  1120. if (msg != NULL) {
  1121. if (msg->peer_key) {
  1122. priv->peer_key = msg->peer_key;
  1123. msg->peer_key = NULL;
  1124. }
  1125. rspamd_http_message_unref (msg);
  1126. priv->msg = NULL;
  1127. }
  1128. conn->finished = FALSE;
  1129. /* Clear priv */
  1130. if (!(priv->flags & RSPAMD_HTTP_CONN_FLAG_RESETED)) {
  1131. if (rspamd_event_pending (&priv->ev, EV_READ|EV_WRITE|EV_TIMEOUT)) {
  1132. event_del (&priv->ev);
  1133. }
  1134. rspamd_http_parser_reset (conn);
  1135. }
  1136. if (priv->buf != NULL) {
  1137. REF_RELEASE (priv->buf);
  1138. priv->buf = NULL;
  1139. }
  1140. if (priv->out != NULL) {
  1141. g_free (priv->out);
  1142. priv->out = NULL;
  1143. }
  1144. priv->flags |= RSPAMD_HTTP_CONN_FLAG_RESETED;
  1145. }
  1146. struct rspamd_http_message *
  1147. rspamd_http_connection_steal_msg (struct rspamd_http_connection *conn)
  1148. {
  1149. struct rspamd_http_connection_private *priv;
  1150. struct rspamd_http_message *msg;
  1151. priv = conn->priv;
  1152. msg = priv->msg;
  1153. /* Clear request */
  1154. if (msg != NULL) {
  1155. if (msg->peer_key) {
  1156. priv->peer_key = msg->peer_key;
  1157. msg->peer_key = NULL;
  1158. }
  1159. priv->msg = NULL;
  1160. }
  1161. return msg;
  1162. }
  1163. struct rspamd_http_message *
  1164. rspamd_http_connection_copy_msg (struct rspamd_http_message *msg, GError **err)
  1165. {
  1166. struct rspamd_http_message *new_msg;
  1167. struct rspamd_http_header *hdr, *nhdr, *nhdrs, *thdr, *hcur;
  1168. const gchar *old_body;
  1169. gsize old_len;
  1170. struct stat st;
  1171. union _rspamd_storage_u *storage;
  1172. new_msg = rspamd_http_new_message (msg->type);
  1173. new_msg->flags = msg->flags;
  1174. if (msg->body_buf.len > 0) {
  1175. if (msg->flags & RSPAMD_HTTP_FLAG_SHMEM) {
  1176. /* Avoid copying by just maping a shared segment */
  1177. new_msg->flags |= RSPAMD_HTTP_FLAG_SHMEM_IMMUTABLE;
  1178. storage = &new_msg->body_buf.c;
  1179. storage->shared.shm_fd = dup (msg->body_buf.c.shared.shm_fd);
  1180. if (storage->shared.shm_fd == -1) {
  1181. rspamd_http_message_unref (new_msg);
  1182. g_set_error (err, http_error_quark (), errno,
  1183. "cannot dup shmem fd: %d: %s",
  1184. msg->body_buf.c.shared.shm_fd, strerror (errno));
  1185. return NULL;
  1186. }
  1187. if (fstat (storage->shared.shm_fd, &st) == -1) {
  1188. g_set_error (err, http_error_quark (), errno,
  1189. "cannot stat shmem fd: %d: %s",
  1190. storage->shared.shm_fd, strerror (errno));
  1191. rspamd_http_message_unref (new_msg);
  1192. return NULL;
  1193. }
  1194. /* We don't own segment, so do not try to touch it */
  1195. if (msg->body_buf.c.shared.name) {
  1196. storage->shared.name = msg->body_buf.c.shared.name;
  1197. REF_RETAIN (storage->shared.name);
  1198. }
  1199. new_msg->body_buf.str = mmap (NULL, st.st_size,
  1200. PROT_READ, MAP_SHARED,
  1201. storage->shared.shm_fd, 0);
  1202. if (new_msg->body_buf.str == MAP_FAILED) {
  1203. g_set_error (err, http_error_quark (), errno,
  1204. "cannot mmap shmem fd: %d: %s",
  1205. storage->shared.shm_fd, strerror (errno));
  1206. rspamd_http_message_unref (new_msg);
  1207. return NULL;
  1208. }
  1209. new_msg->body_buf.begin = new_msg->body_buf.str;
  1210. new_msg->body_buf.len = msg->body_buf.len;
  1211. new_msg->body_buf.begin = new_msg->body_buf.str +
  1212. (msg->body_buf.begin - msg->body_buf.str);
  1213. }
  1214. else {
  1215. old_body = rspamd_http_message_get_body (msg, &old_len);
  1216. if (!rspamd_http_message_set_body (new_msg, old_body, old_len)) {
  1217. g_set_error (err, http_error_quark (), errno,
  1218. "cannot set body for message, length: %zd",
  1219. old_len);
  1220. rspamd_http_message_unref (new_msg);
  1221. return NULL;
  1222. }
  1223. }
  1224. }
  1225. if (msg->url) {
  1226. if (new_msg->url) {
  1227. new_msg->url = rspamd_fstring_append (new_msg->url, msg->url->str,
  1228. msg->url->len);
  1229. }
  1230. else {
  1231. new_msg->url = rspamd_fstring_new_init (msg->url->str,
  1232. msg->url->len);
  1233. }
  1234. }
  1235. if (msg->host) {
  1236. new_msg->host = rspamd_fstring_new_init (msg->host->str,
  1237. msg->host->len);
  1238. }
  1239. new_msg->method = msg->method;
  1240. new_msg->port = msg->port;
  1241. new_msg->date = msg->date;
  1242. new_msg->last_modified = msg->last_modified;
  1243. HASH_ITER (hh, msg->headers, hdr, thdr) {
  1244. nhdrs = NULL;
  1245. DL_FOREACH (hdr, hcur) {
  1246. nhdr = g_malloc (sizeof (struct rspamd_http_header));
  1247. nhdr->combined = rspamd_fstring_new_init (hcur->combined->str,
  1248. hcur->combined->len);
  1249. nhdr->name.begin = nhdr->combined->str +
  1250. (hcur->name.begin - hcur->combined->str);
  1251. nhdr->name.len = hcur->name.len;
  1252. nhdr->value.begin = nhdr->combined->str +
  1253. (hcur->value.begin - hcur->combined->str);
  1254. nhdr->value.len = hcur->value.len;
  1255. DL_APPEND (nhdrs, nhdr);
  1256. }
  1257. HASH_ADD_KEYPTR (hh, new_msg->headers, nhdrs->name.begin,
  1258. nhdrs->name.len, nhdrs);
  1259. }
  1260. return new_msg;
  1261. }
  1262. void
  1263. rspamd_http_connection_free (struct rspamd_http_connection *conn)
  1264. {
  1265. struct rspamd_http_connection_private *priv;
  1266. priv = conn->priv;
  1267. if (priv != NULL) {
  1268. rspamd_http_connection_reset (conn);
  1269. if (priv->ssl) {
  1270. rspamd_ssl_connection_free (priv->ssl);
  1271. priv->ssl = NULL;
  1272. }
  1273. if (priv->local_key) {
  1274. rspamd_keypair_unref (priv->local_key);
  1275. }
  1276. if (priv->peer_key) {
  1277. rspamd_pubkey_unref (priv->peer_key);
  1278. }
  1279. g_free (priv);
  1280. }
  1281. g_free (conn);
  1282. }
  1283. static void
  1284. rspamd_http_connection_read_message_common (struct rspamd_http_connection *conn,
  1285. gpointer ud, gint fd, struct timeval *timeout, struct event_base *base,
  1286. gint flags)
  1287. {
  1288. struct rspamd_http_connection_private *priv = conn->priv;
  1289. struct rspamd_http_message *req;
  1290. conn->fd = fd;
  1291. conn->ud = ud;
  1292. req = rspamd_http_new_message (
  1293. conn->type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE);
  1294. priv->msg = req;
  1295. req->flags = flags;
  1296. if (flags & RSPAMD_HTTP_FLAG_SHMEM) {
  1297. req->body_buf.c.shared.shm_fd = -1;
  1298. }
  1299. if (priv->peer_key) {
  1300. priv->msg->peer_key = priv->peer_key;
  1301. priv->peer_key = NULL;
  1302. priv->flags |= RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
  1303. }
  1304. if (timeout == NULL) {
  1305. priv->ptv = NULL;
  1306. }
  1307. else if (&priv->tv != timeout) {
  1308. memcpy (&priv->tv, timeout, sizeof (struct timeval));
  1309. priv->ptv = &priv->tv;
  1310. }
  1311. priv->header = NULL;
  1312. priv->buf = g_malloc0 (sizeof (*priv->buf));
  1313. REF_INIT_RETAIN (priv->buf, rspamd_http_privbuf_dtor);
  1314. priv->buf->data = rspamd_fstring_sized_new (8192);
  1315. priv->flags |= RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
  1316. event_set (&priv->ev,
  1317. fd,
  1318. EV_READ | EV_PERSIST,
  1319. rspamd_http_event_handler,
  1320. conn);
  1321. if (base != NULL) {
  1322. event_base_set (base, &priv->ev);
  1323. }
  1324. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_RESETED;
  1325. event_add (&priv->ev, priv->ptv);
  1326. }
  1327. void
  1328. rspamd_http_connection_read_message (struct rspamd_http_connection *conn,
  1329. gpointer ud, gint fd, struct timeval *timeout, struct event_base *base)
  1330. {
  1331. rspamd_http_connection_read_message_common (conn, ud, fd, timeout, base, 0);
  1332. }
  1333. void
  1334. rspamd_http_connection_read_message_shared (struct rspamd_http_connection *conn,
  1335. gpointer ud, gint fd, struct timeval *timeout, struct event_base *base)
  1336. {
  1337. rspamd_http_connection_read_message_common (conn, ud, fd, timeout, base,
  1338. RSPAMD_HTTP_FLAG_SHMEM);
  1339. }
  1340. static void
  1341. rspamd_http_connection_encrypt_message (
  1342. struct rspamd_http_connection *conn,
  1343. struct rspamd_http_message *msg,
  1344. struct rspamd_http_connection_private *priv,
  1345. guchar *pbody,
  1346. guint bodylen,
  1347. guchar *pmethod,
  1348. guint methodlen,
  1349. guint preludelen,
  1350. gint hdrcount,
  1351. guchar *np,
  1352. guchar *mp,
  1353. struct rspamd_cryptobox_pubkey *peer_key)
  1354. {
  1355. struct rspamd_cryptobox_segment *segments;
  1356. guchar *crlfp;
  1357. const guchar *nm;
  1358. gint i, cnt;
  1359. guint outlen;
  1360. struct rspamd_http_header *hdr, *htmp, *hcur;
  1361. enum rspamd_cryptobox_mode mode;
  1362. mode = rspamd_keypair_alg (priv->local_key);
  1363. crlfp = mp + rspamd_cryptobox_mac_bytes (mode);
  1364. outlen = priv->out[0].iov_len + priv->out[1].iov_len;
  1365. /*
  1366. * Create segments from the following:
  1367. * Method, [URL], CRLF, nheaders, CRLF, body
  1368. */
  1369. segments = g_new (struct rspamd_cryptobox_segment, hdrcount + 5);
  1370. segments[0].data = pmethod;
  1371. segments[0].len = methodlen;
  1372. if (conn->type != RSPAMD_HTTP_SERVER) {
  1373. segments[1].data = msg->url->str;
  1374. segments[1].len = msg->url->len;
  1375. /* space + HTTP version + crlf */
  1376. segments[2].data = crlfp;
  1377. segments[2].len = preludelen - 2;
  1378. crlfp += segments[2].len;
  1379. i = 3;
  1380. }
  1381. else {
  1382. /* Here we send just CRLF */
  1383. segments[1].data = crlfp;
  1384. segments[1].len = 2;
  1385. crlfp += segments[1].len;
  1386. i = 2;
  1387. }
  1388. HASH_ITER (hh, msg->headers, hdr, htmp) {
  1389. DL_FOREACH (hdr, hcur) {
  1390. segments[i].data = hcur->combined->str;
  1391. segments[i++].len = hcur->combined->len;
  1392. }
  1393. }
  1394. /* crlfp should point now at the second crlf */
  1395. segments[i].data = crlfp;
  1396. segments[i++].len = 2;
  1397. if (pbody) {
  1398. segments[i].data = pbody;
  1399. segments[i++].len = bodylen;
  1400. }
  1401. cnt = i;
  1402. if ((nm = rspamd_pubkey_get_nm (peer_key, priv->local_key)) == NULL) {
  1403. nm = rspamd_pubkey_calculate_nm (peer_key, priv->local_key);
  1404. }
  1405. rspamd_cryptobox_encryptv_nm_inplace (segments, cnt, np, nm, mp, mode);
  1406. /*
  1407. * iov[0] = base HTTP request
  1408. * iov[1] = CRLF
  1409. * iov[2] = nonce
  1410. * iov[3] = mac
  1411. * iov[4..i] = encrypted HTTP request/reply
  1412. */
  1413. priv->out[2].iov_base = np;
  1414. priv->out[2].iov_len = rspamd_cryptobox_nonce_bytes (mode);
  1415. priv->out[3].iov_base = mp;
  1416. priv->out[3].iov_len = rspamd_cryptobox_mac_bytes (mode);
  1417. outlen += rspamd_cryptobox_nonce_bytes (mode) +
  1418. rspamd_cryptobox_mac_bytes (mode);
  1419. for (i = 0; i < cnt; i ++) {
  1420. priv->out[i + 4].iov_base = segments[i].data;
  1421. priv->out[i + 4].iov_len = segments[i].len;
  1422. outlen += segments[i].len;
  1423. }
  1424. priv->wr_total = outlen;
  1425. g_free (segments);
  1426. }
  1427. static void
  1428. rspamd_http_detach_shared (struct rspamd_http_message *msg)
  1429. {
  1430. rspamd_fstring_t *cpy_str;
  1431. cpy_str = rspamd_fstring_new_init (msg->body_buf.begin, msg->body_buf.len);
  1432. rspamd_http_message_set_body_from_fstring_steal (msg, cpy_str);
  1433. }
  1434. gint
  1435. rspamd_http_message_write_header (const gchar* mime_type, gboolean encrypted,
  1436. gchar *repbuf, gsize replen, gsize bodylen, gsize enclen, const gchar* host,
  1437. struct rspamd_http_connection* conn, struct rspamd_http_message* msg,
  1438. rspamd_fstring_t** buf,
  1439. struct rspamd_http_connection_private* priv,
  1440. struct rspamd_cryptobox_pubkey* peer_key)
  1441. {
  1442. gchar datebuf[64];
  1443. gint meth_len = 0;
  1444. struct tm t;
  1445. if (conn->type == RSPAMD_HTTP_SERVER) {
  1446. /* Format reply */
  1447. if (msg->method < HTTP_SYMBOLS) {
  1448. rspamd_ftok_t status;
  1449. rspamd_gmtime (msg->date, &t);
  1450. rspamd_snprintf (datebuf, sizeof(datebuf),
  1451. "%s, %02d %s %4d %02d:%02d:%02d GMT", http_week[t.tm_wday],
  1452. t.tm_mday, http_month[t.tm_mon], t.tm_year + 1900,
  1453. t.tm_hour, t.tm_min, t.tm_sec);
  1454. if (mime_type == NULL) {
  1455. mime_type =
  1456. encrypted ? "application/octet-stream" : "text/plain";
  1457. }
  1458. if (msg->status == NULL || msg->status->len == 0) {
  1459. if (msg->code == 200) {
  1460. RSPAMD_FTOK_ASSIGN (&status, "OK");
  1461. }
  1462. else if (msg->code == 404) {
  1463. RSPAMD_FTOK_ASSIGN (&status, "Not Found");
  1464. }
  1465. else if (msg->code == 403) {
  1466. RSPAMD_FTOK_ASSIGN (&status, "Forbidden");
  1467. }
  1468. else if (msg->code >= 500 && msg->code < 600) {
  1469. RSPAMD_FTOK_ASSIGN (&status, "Internal Server Error");
  1470. }
  1471. else {
  1472. RSPAMD_FTOK_ASSIGN (&status, "Undefined Error");
  1473. }
  1474. }
  1475. else {
  1476. status.begin = msg->status->str;
  1477. status.len = msg->status->len;
  1478. }
  1479. if (encrypted) {
  1480. /* Internal reply (encrypted) */
  1481. if (mime_type) {
  1482. meth_len =
  1483. rspamd_snprintf (repbuf, replen,
  1484. "HTTP/1.1 %d %T\r\n"
  1485. "Connection: close\r\n"
  1486. "Server: %s\r\n"
  1487. "Date: %s\r\n"
  1488. "Content-Length: %z\r\n"
  1489. "Content-Type: %s", /* NO \r\n at the end ! */
  1490. msg->code, &status, "rspamd/" RVERSION,
  1491. datebuf,
  1492. bodylen, mime_type);
  1493. }
  1494. else {
  1495. meth_len =
  1496. rspamd_snprintf (repbuf, replen,
  1497. "HTTP/1.1 %d %T\r\n"
  1498. "Connection: close\r\n"
  1499. "Server: %s\r\n"
  1500. "Date: %s\r\n"
  1501. "Content-Length: %z", /* NO \r\n at the end ! */
  1502. msg->code, &status, "rspamd/" RVERSION,
  1503. datebuf,
  1504. bodylen);
  1505. }
  1506. enclen += meth_len;
  1507. /* External reply */
  1508. rspamd_printf_fstring (buf,
  1509. "HTTP/1.1 200 OK\r\n"
  1510. "Connection: close\r\n"
  1511. "Server: rspamd\r\n"
  1512. "Date: %s\r\n"
  1513. "Content-Length: %z\r\n"
  1514. "Content-Type: application/octet-stream\r\n",
  1515. datebuf, enclen);
  1516. }
  1517. else {
  1518. if (mime_type) {
  1519. meth_len =
  1520. rspamd_printf_fstring (buf,
  1521. "HTTP/1.1 %d %T\r\n"
  1522. "Connection: close\r\n"
  1523. "Server: %s\r\n"
  1524. "Date: %s\r\n"
  1525. "Content-Length: %z\r\n"
  1526. "Content-Type: %s\r\n",
  1527. msg->code, &status, "rspamd/" RVERSION,
  1528. datebuf,
  1529. bodylen, mime_type);
  1530. }
  1531. else {
  1532. meth_len =
  1533. rspamd_printf_fstring (buf,
  1534. "HTTP/1.1 %d %T\r\n"
  1535. "Connection: close\r\n"
  1536. "Server: %s\r\n"
  1537. "Date: %s\r\n"
  1538. "Content-Length: %z\r\n",
  1539. msg->code, &status, "rspamd/" RVERSION,
  1540. datebuf,
  1541. bodylen);
  1542. }
  1543. }
  1544. }
  1545. else {
  1546. /* Legacy spamd reply */
  1547. if (msg->flags & RSPAMD_HTTP_FLAG_SPAMC) {
  1548. gsize real_bodylen;
  1549. goffset eoh_pos;
  1550. GString tmp;
  1551. /* Unfortunately, spamc protocol is deadly brain damaged */
  1552. tmp.str = (gchar *)msg->body_buf.begin;
  1553. tmp.len = msg->body_buf.len;
  1554. if (rspamd_string_find_eoh (&tmp, &eoh_pos) != -1 &&
  1555. bodylen > eoh_pos) {
  1556. real_bodylen = bodylen - eoh_pos;
  1557. }
  1558. else {
  1559. real_bodylen = bodylen;
  1560. }
  1561. rspamd_printf_fstring (buf, "SPAMD/1.1 0 EX_OK\r\n"
  1562. "Content-length: %z\r\n",
  1563. real_bodylen);
  1564. }
  1565. else {
  1566. rspamd_printf_fstring (buf, "RSPAMD/1.3 0 EX_OK\r\n");
  1567. }
  1568. }
  1569. }
  1570. else {
  1571. /* Format request */
  1572. enclen += msg->url->len + strlen (http_method_str (msg->method)) + 1;
  1573. if (host == NULL && msg->host == NULL) {
  1574. /* Fallback to HTTP/1.0 */
  1575. if (encrypted) {
  1576. rspamd_printf_fstring (buf,
  1577. "%s %s HTTP/1.0\r\n"
  1578. "Content-Length: %z\r\n"
  1579. "Content-Type: application/octet-stream\r\n",
  1580. "POST",
  1581. "/post", enclen);
  1582. }
  1583. else {
  1584. rspamd_printf_fstring (buf,
  1585. "%s %V HTTP/1.0\r\n"
  1586. "Content-Length: %z\r\n",
  1587. http_method_str (msg->method), msg->url, bodylen);
  1588. if (bodylen > 0) {
  1589. if (mime_type == NULL) {
  1590. mime_type = "text/plain";
  1591. }
  1592. rspamd_printf_fstring (buf,
  1593. "Content-Type: %s\r\n",
  1594. mime_type);
  1595. }
  1596. }
  1597. }
  1598. else {
  1599. if (encrypted) {
  1600. if (host != NULL) {
  1601. rspamd_printf_fstring (buf,
  1602. "%s %s HTTP/1.1\r\n"
  1603. "Connection: close\r\n"
  1604. "Host: %s\r\n"
  1605. "Content-Length: %z\r\n"
  1606. "Content-Type: application/octet-stream\r\n",
  1607. "POST", "/post", host, enclen);
  1608. }
  1609. else {
  1610. rspamd_printf_fstring (buf,
  1611. "%s %s HTTP/1.1\r\n"
  1612. "Connection: close\r\n"
  1613. "Host: %V\r\n"
  1614. "Content-Length: %z\r\n"
  1615. "Content-Type: application/octet-stream\r\n",
  1616. "POST", "/post", msg->host, enclen);
  1617. }
  1618. }
  1619. else {
  1620. if (host != NULL) {
  1621. rspamd_printf_fstring (buf,
  1622. "%s %V HTTP/1.1\r\nConnection: close\r\n"
  1623. "Host: %s\r\n"
  1624. "Content-Length: %z\r\n",
  1625. http_method_str (msg->method), msg->url, host,
  1626. bodylen);
  1627. }
  1628. else {
  1629. rspamd_printf_fstring (buf,
  1630. "%s %V HTTP/1.1\r\n"
  1631. "Connection: close\r\n"
  1632. "Host: %V\r\n"
  1633. "Content-Length: %z\r\n",
  1634. http_method_str (msg->method), msg->url, msg->host,
  1635. bodylen);
  1636. }
  1637. if (bodylen > 0) {
  1638. if (mime_type != NULL) {
  1639. rspamd_printf_fstring (buf,
  1640. "Content-Type: %s\r\n",
  1641. mime_type);
  1642. }
  1643. }
  1644. }
  1645. }
  1646. if (encrypted) {
  1647. GString *b32_key, *b32_id;
  1648. b32_key = rspamd_keypair_print (priv->local_key,
  1649. RSPAMD_KEYPAIR_PUBKEY | RSPAMD_KEYPAIR_BASE32);
  1650. b32_id = rspamd_pubkey_print (peer_key,
  1651. RSPAMD_KEYPAIR_ID_SHORT | RSPAMD_KEYPAIR_BASE32);
  1652. /* XXX: add some fuzz here */
  1653. rspamd_printf_fstring (&*buf, "Key: %v=%v\r\n", b32_id, b32_key);
  1654. g_string_free (b32_key, TRUE);
  1655. g_string_free (b32_id, TRUE);
  1656. }
  1657. }
  1658. return meth_len;
  1659. }
  1660. static void
  1661. rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn,
  1662. struct rspamd_http_message *msg, const gchar *host, const gchar *mime_type,
  1663. gpointer ud, gint fd, struct timeval *timeout, struct event_base *base,
  1664. gboolean allow_shared)
  1665. {
  1666. struct rspamd_http_connection_private *priv = conn->priv;
  1667. struct rspamd_http_header *hdr, *htmp, *hcur;
  1668. gchar repbuf[512], *pbody;
  1669. gint i, hdrcount, meth_len = 0, preludelen = 0;
  1670. gsize bodylen, enclen = 0;
  1671. rspamd_fstring_t *buf;
  1672. gboolean encrypted = FALSE;
  1673. guchar nonce[rspamd_cryptobox_MAX_NONCEBYTES], mac[rspamd_cryptobox_MAX_MACBYTES];
  1674. guchar *np = NULL, *mp = NULL, *meth_pos = NULL;
  1675. struct rspamd_cryptobox_pubkey *peer_key = NULL;
  1676. enum rspamd_cryptobox_mode mode;
  1677. GError *err;
  1678. conn->fd = fd;
  1679. conn->ud = ud;
  1680. priv->msg = msg;
  1681. if (timeout == NULL) {
  1682. priv->ptv = NULL;
  1683. }
  1684. else if (timeout != &priv->tv) {
  1685. memcpy (&priv->tv, timeout, sizeof (struct timeval));
  1686. priv->ptv = &priv->tv;
  1687. }
  1688. priv->header = NULL;
  1689. priv->buf = g_malloc0 (sizeof (*priv->buf));
  1690. REF_INIT_RETAIN (priv->buf, rspamd_http_privbuf_dtor);
  1691. priv->buf->data = rspamd_fstring_sized_new (512);
  1692. buf = priv->buf->data;
  1693. if (priv->peer_key && priv->local_key) {
  1694. priv->msg->peer_key = priv->peer_key;
  1695. priv->peer_key = NULL;
  1696. priv->flags |= RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
  1697. }
  1698. if (msg->peer_key != NULL) {
  1699. if (priv->local_key == NULL) {
  1700. /* Automatically generate a temporary keypair */
  1701. priv->local_key = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX,
  1702. RSPAMD_CRYPTOBOX_MODE_25519);
  1703. }
  1704. encrypted = TRUE;
  1705. if (conn->cache) {
  1706. rspamd_keypair_cache_process (conn->cache,
  1707. priv->local_key, priv->msg->peer_key);
  1708. }
  1709. }
  1710. if (encrypted && (msg->flags &
  1711. (RSPAMD_HTTP_FLAG_SHMEM_IMMUTABLE|RSPAMD_HTTP_FLAG_SHMEM))) {
  1712. /* We cannot use immutable body to encrypt message in place */
  1713. allow_shared = FALSE;
  1714. rspamd_http_detach_shared (msg);
  1715. }
  1716. if (allow_shared) {
  1717. gchar tmpbuf[64];
  1718. if (!(msg->flags & RSPAMD_HTTP_FLAG_SHMEM) ||
  1719. msg->body_buf.c.shared.name == NULL) {
  1720. allow_shared = FALSE;
  1721. }
  1722. else {
  1723. /* Insert new headers */
  1724. rspamd_http_message_add_header (msg, "Shm",
  1725. msg->body_buf.c.shared.name->shm_name);
  1726. rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "%d",
  1727. (int)(msg->body_buf.begin - msg->body_buf.str));
  1728. rspamd_http_message_add_header (msg, "Shm-Offset",
  1729. tmpbuf);
  1730. rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "%z",
  1731. msg->body_buf.len);
  1732. rspamd_http_message_add_header (msg, "Shm-Length",
  1733. tmpbuf);
  1734. }
  1735. }
  1736. if (encrypted) {
  1737. mode = rspamd_keypair_alg (priv->local_key);
  1738. if (msg->body_buf.len == 0) {
  1739. pbody = NULL;
  1740. bodylen = 0;
  1741. msg->method = HTTP_GET;
  1742. }
  1743. else {
  1744. pbody = (gchar *)msg->body_buf.begin;
  1745. bodylen = msg->body_buf.len;
  1746. msg->method = HTTP_POST;
  1747. }
  1748. if (conn->type == RSPAMD_HTTP_SERVER) {
  1749. /*
  1750. * iov[0] = base reply
  1751. * iov[1] = CRLF
  1752. * iov[2] = nonce
  1753. * iov[3] = mac
  1754. * iov[4] = encrypted reply
  1755. * iov[6] = encrypted crlf
  1756. * iov[7..n] = encrypted headers
  1757. * iov[n + 1] = encrypted crlf
  1758. * [iov[n + 2] = encrypted body]
  1759. */
  1760. priv->outlen = 7;
  1761. enclen = rspamd_cryptobox_nonce_bytes (mode) +
  1762. rspamd_cryptobox_mac_bytes (mode) +
  1763. 4 + /* 2 * CRLF */
  1764. bodylen;
  1765. }
  1766. else {
  1767. /*
  1768. * iov[0] = base request
  1769. * iov[1] = CRLF
  1770. * iov[2] = nonce
  1771. * iov[3] = mac
  1772. * iov[4] = encrypted method + space
  1773. * iov[5] = encrypted url
  1774. * iov[7] = encrypted prelude
  1775. * iov[8..n] = encrypted headers
  1776. * iov[n + 1] = encrypted crlf
  1777. * [iov[n + 2] = encrypted body]
  1778. */
  1779. priv->outlen = 8;
  1780. if (bodylen > 0) {
  1781. if (mime_type != NULL) {
  1782. preludelen = rspamd_snprintf (repbuf, sizeof (repbuf), "%s\r\n"
  1783. "Content-Length: %z\r\n"
  1784. "Content-Type: %s\r\n"
  1785. "\r\n", ENCRYPTED_VERSION, bodylen,
  1786. mime_type);
  1787. }
  1788. else {
  1789. preludelen = rspamd_snprintf (repbuf, sizeof (repbuf), "%s\r\n"
  1790. "Content-Length: %z\r\n"
  1791. ""
  1792. "\r\n", ENCRYPTED_VERSION, bodylen);
  1793. }
  1794. preludelen = rspamd_snprintf (repbuf, sizeof (repbuf), "%s\r\n"
  1795. "Content-Length: %z\r\n"
  1796. "Content-Type: %s\r\n"
  1797. "\r\n", ENCRYPTED_VERSION, bodylen,
  1798. mime_type);
  1799. }
  1800. else {
  1801. preludelen = rspamd_snprintf (repbuf, sizeof (repbuf),
  1802. "%s\r\n\r\n",
  1803. ENCRYPTED_VERSION);
  1804. }
  1805. enclen = rspamd_cryptobox_nonce_bytes (mode) +
  1806. rspamd_cryptobox_mac_bytes (mode) +
  1807. preludelen + /* version [content-length] + 2 * CRLF */
  1808. bodylen;
  1809. }
  1810. if (bodylen > 0) {
  1811. priv->outlen ++;
  1812. }
  1813. }
  1814. else {
  1815. if (msg->method < HTTP_SYMBOLS) {
  1816. if (msg->body_buf.len == 0 || allow_shared) {
  1817. pbody = NULL;
  1818. bodylen = 0;
  1819. priv->outlen = 2;
  1820. if (msg->method == HTTP_INVALID) {
  1821. msg->method = HTTP_GET;
  1822. }
  1823. }
  1824. else {
  1825. pbody = (gchar *)msg->body_buf.begin;
  1826. bodylen = msg->body_buf.len;
  1827. priv->outlen = 3;
  1828. if (msg->method == HTTP_INVALID) {
  1829. msg->method = HTTP_POST;
  1830. }
  1831. }
  1832. }
  1833. else if (msg->body_buf.len > 0) {
  1834. allow_shared = FALSE;
  1835. pbody = (gchar *)msg->body_buf.begin;
  1836. bodylen = msg->body_buf.len;
  1837. priv->outlen = 2;
  1838. }
  1839. else {
  1840. /* Invalid body for spamc method */
  1841. abort ();
  1842. }
  1843. }
  1844. peer_key = msg->peer_key;
  1845. priv->wr_total = bodylen + 2;
  1846. hdrcount = 0;
  1847. if (msg->method < HTTP_SYMBOLS) {
  1848. HASH_ITER (hh, msg->headers, hdr, htmp) {
  1849. DL_FOREACH (hdr, hcur) {
  1850. /* <name: value\r\n> */
  1851. priv->wr_total += hcur->combined->len;
  1852. enclen += hcur->combined->len;
  1853. priv->outlen ++;
  1854. hdrcount ++;
  1855. }
  1856. }
  1857. }
  1858. /* Allocate iov */
  1859. priv->out = g_malloc0 (sizeof (struct iovec) * priv->outlen);
  1860. priv->wr_pos = 0;
  1861. meth_len = rspamd_http_message_write_header (mime_type, encrypted,
  1862. repbuf, sizeof (repbuf), bodylen, enclen,
  1863. host, conn, msg,
  1864. &buf, priv, peer_key);
  1865. priv->wr_total += buf->len;
  1866. /* Setup external request body */
  1867. priv->out[0].iov_base = buf->str;
  1868. priv->out[0].iov_len = buf->len;
  1869. /* Buf will be used eventually for encryption */
  1870. if (encrypted) {
  1871. gint meth_offset, nonce_offset, mac_offset;
  1872. mode = rspamd_keypair_alg (priv->local_key);
  1873. ottery_rand_bytes (nonce, rspamd_cryptobox_nonce_bytes (mode));
  1874. memset (mac, 0, rspamd_cryptobox_mac_bytes (mode));
  1875. meth_offset = buf->len;
  1876. if (conn->type == RSPAMD_HTTP_SERVER) {
  1877. buf = rspamd_fstring_append (buf, repbuf, meth_len);
  1878. }
  1879. else {
  1880. meth_len = strlen (http_method_str (msg->method)) + 1; /* + space */
  1881. buf = rspamd_fstring_append (buf, http_method_str (msg->method),
  1882. meth_len - 1);
  1883. buf = rspamd_fstring_append (buf, " ", 1);
  1884. }
  1885. nonce_offset = buf->len;
  1886. buf = rspamd_fstring_append (buf, nonce,
  1887. rspamd_cryptobox_nonce_bytes (mode));
  1888. mac_offset = buf->len;
  1889. buf = rspamd_fstring_append (buf, mac,
  1890. rspamd_cryptobox_mac_bytes (mode));
  1891. /* Need to be encrypted */
  1892. if (conn->type == RSPAMD_HTTP_SERVER) {
  1893. buf = rspamd_fstring_append (buf, "\r\n\r\n", 4);
  1894. }
  1895. else {
  1896. buf = rspamd_fstring_append (buf, repbuf, preludelen);
  1897. }
  1898. meth_pos = buf->str + meth_offset;
  1899. np = buf->str + nonce_offset;
  1900. mp = buf->str + mac_offset;
  1901. }
  1902. /* During previous writes, buf might be reallocated and changed */
  1903. priv->buf->data = buf;
  1904. if (encrypted) {
  1905. /* Finish external HTTP request */
  1906. priv->out[1].iov_base = "\r\n";
  1907. priv->out[1].iov_len = 2;
  1908. /* Encrypt the real request */
  1909. rspamd_http_connection_encrypt_message (conn, msg, priv, pbody, bodylen,
  1910. meth_pos, meth_len, preludelen, hdrcount, np, mp, peer_key);
  1911. }
  1912. else {
  1913. i = 1;
  1914. if (msg->method < HTTP_SYMBOLS) {
  1915. HASH_ITER (hh, msg->headers, hdr, htmp) {
  1916. DL_FOREACH (hdr, hcur) {
  1917. priv->out[i].iov_base = hcur->combined->str;
  1918. priv->out[i++].iov_len = hcur->combined->len;
  1919. }
  1920. }
  1921. priv->out[i].iov_base = "\r\n";
  1922. priv->out[i++].iov_len = 2;
  1923. }
  1924. else {
  1925. /* No CRLF for compatibility reply */
  1926. priv->wr_total -= 2;
  1927. }
  1928. if (pbody != NULL) {
  1929. priv->out[i].iov_base = pbody;
  1930. priv->out[i++].iov_len = bodylen;
  1931. }
  1932. }
  1933. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_RESETED;
  1934. if (rspamd_event_pending (&priv->ev, EV_TIMEOUT|EV_WRITE|EV_READ)) {
  1935. event_del (&priv->ev);
  1936. }
  1937. if (msg->flags & RSPAMD_HTTP_FLAG_SSL) {
  1938. if (base != NULL) {
  1939. event_base_set (base, &priv->ev);
  1940. }
  1941. if (!priv->ssl_ctx) {
  1942. err = g_error_new (HTTP_ERROR, errno, "ssl message requested "
  1943. "with no ssl ctx");
  1944. rspamd_http_connection_ref (conn);
  1945. conn->error_handler (conn, err);
  1946. rspamd_http_connection_unref (conn);
  1947. g_error_free (err);
  1948. return;
  1949. }
  1950. else {
  1951. if (priv->ssl) {
  1952. /* Cleanup the existing connection */
  1953. rspamd_ssl_connection_free (priv->ssl);
  1954. }
  1955. priv->ssl = rspamd_ssl_connection_new (priv->ssl_ctx, base,
  1956. !(msg->flags & RSPAMD_HTTP_FLAG_SSL_NOVERIFY));
  1957. g_assert (priv->ssl != NULL);
  1958. if (!rspamd_ssl_connect_fd (priv->ssl, fd, host, &priv->ev,
  1959. priv->ptv, rspamd_http_event_handler,
  1960. rspamd_http_ssl_err_handler, conn)) {
  1961. err = g_error_new (HTTP_ERROR, errno,
  1962. "ssl connection error: ssl error=%s, errno=%s",
  1963. ERR_error_string (ERR_get_error (), NULL),
  1964. strerror (errno));
  1965. rspamd_http_connection_ref (conn);
  1966. conn->error_handler (conn, err);
  1967. rspamd_http_connection_unref (conn);
  1968. g_error_free (err);
  1969. return;
  1970. }
  1971. }
  1972. }
  1973. else {
  1974. event_set (&priv->ev, fd, EV_WRITE, rspamd_http_event_handler, conn);
  1975. if (base != NULL) {
  1976. event_base_set (base, &priv->ev);
  1977. }
  1978. event_add (&priv->ev, priv->ptv);
  1979. }
  1980. }
  1981. void
  1982. rspamd_http_connection_write_message (struct rspamd_http_connection *conn,
  1983. struct rspamd_http_message *msg, const gchar *host, const gchar *mime_type,
  1984. gpointer ud, gint fd, struct timeval *timeout, struct event_base *base)
  1985. {
  1986. rspamd_http_connection_write_message_common (conn, msg, host, mime_type,
  1987. ud, fd, timeout, base, FALSE);
  1988. }
  1989. void
  1990. rspamd_http_connection_write_message_shared (struct rspamd_http_connection *conn,
  1991. struct rspamd_http_message *msg, const gchar *host, const gchar *mime_type,
  1992. gpointer ud, gint fd, struct timeval *timeout, struct event_base *base)
  1993. {
  1994. rspamd_http_connection_write_message_common (conn, msg, host, mime_type,
  1995. ud, fd, timeout, base, TRUE);
  1996. }
  1997. struct rspamd_http_message *
  1998. rspamd_http_new_message (enum http_parser_type type)
  1999. {
  2000. struct rspamd_http_message *new;
  2001. new = g_malloc0 (sizeof (struct rspamd_http_message));
  2002. if (type == HTTP_REQUEST) {
  2003. new->url = rspamd_fstring_new ();
  2004. }
  2005. else {
  2006. new->url = NULL;
  2007. new->code = 200;
  2008. }
  2009. new->port = 80;
  2010. new->type = type;
  2011. new->method = HTTP_INVALID;
  2012. REF_INIT_RETAIN (new, rspamd_http_message_free);
  2013. return new;
  2014. }
  2015. struct rspamd_http_message*
  2016. rspamd_http_message_from_url (const gchar *url)
  2017. {
  2018. struct http_parser_url pu;
  2019. struct rspamd_http_message *msg;
  2020. const gchar *host, *path;
  2021. size_t pathlen, urllen;
  2022. guint flags = 0;
  2023. if (url == NULL) {
  2024. return NULL;
  2025. }
  2026. urllen = strlen (url);
  2027. memset (&pu, 0, sizeof (pu));
  2028. if (http_parser_parse_url (url, urllen, FALSE, &pu) != 0) {
  2029. msg_warn ("cannot parse URL: %s", url);
  2030. return NULL;
  2031. }
  2032. if ((pu.field_set & (1 << UF_HOST)) == 0) {
  2033. msg_warn ("no host argument in URL: %s", url);
  2034. return NULL;
  2035. }
  2036. if ((pu.field_set & (1 << UF_SCHEMA))) {
  2037. if (pu.field_data[UF_SCHEMA].len == sizeof ("https") - 1 &&
  2038. memcmp (url + pu.field_data[UF_SCHEMA].off, "https", 5) == 0) {
  2039. flags |= RSPAMD_HTTP_FLAG_SSL;
  2040. }
  2041. }
  2042. if ((pu.field_set & (1 << UF_PATH)) == 0) {
  2043. path = "/";
  2044. pathlen = 1;
  2045. }
  2046. else {
  2047. path = url + pu.field_data[UF_PATH].off;
  2048. pathlen = urllen - pu.field_data[UF_PATH].off;
  2049. }
  2050. msg = rspamd_http_new_message (HTTP_REQUEST);
  2051. host = url + pu.field_data[UF_HOST].off;
  2052. msg->flags = flags;
  2053. if ((pu.field_set & (1 << UF_PORT)) != 0) {
  2054. msg->port = pu.port;
  2055. }
  2056. else {
  2057. /* XXX: magic constant */
  2058. if (flags & RSPAMD_HTTP_FLAG_SSL) {
  2059. msg->port = 443;
  2060. }
  2061. else {
  2062. msg->port = 80;
  2063. }
  2064. }
  2065. msg->host = rspamd_fstring_new_init (host, pu.field_data[UF_HOST].len);
  2066. msg->url = rspamd_fstring_append (msg->url, path, pathlen);
  2067. REF_INIT_RETAIN (msg, rspamd_http_message_free);
  2068. return msg;
  2069. }
  2070. const gchar *
  2071. rspamd_http_message_get_body (struct rspamd_http_message *msg,
  2072. gsize *blen)
  2073. {
  2074. const gchar *ret = NULL;
  2075. if (msg->body_buf.len > 0) {
  2076. ret = msg->body_buf.begin;
  2077. }
  2078. if (blen) {
  2079. *blen = msg->body_buf.len;
  2080. }
  2081. return ret;
  2082. }
  2083. static void
  2084. rspamd_http_shname_dtor (void *p)
  2085. {
  2086. struct rspamd_storage_shmem *n = p;
  2087. #ifdef HAVE_SANE_SHMEM
  2088. shm_unlink (n->shm_name);
  2089. #else
  2090. unlink (n->shm_name);
  2091. #endif
  2092. g_free (n->shm_name);
  2093. g_free (n);
  2094. }
  2095. struct rspamd_storage_shmem *
  2096. rspamd_http_message_shmem_ref (struct rspamd_http_message *msg)
  2097. {
  2098. if ((msg->flags & RSPAMD_HTTP_FLAG_SHMEM) && msg->body_buf.c.shared.name) {
  2099. REF_RETAIN (msg->body_buf.c.shared.name);
  2100. return msg->body_buf.c.shared.name;
  2101. }
  2102. return NULL;
  2103. }
  2104. guint
  2105. rspamd_http_message_get_flags (struct rspamd_http_message *msg)
  2106. {
  2107. return msg->flags;
  2108. }
  2109. void
  2110. rspamd_http_message_shmem_unref (struct rspamd_storage_shmem *p)
  2111. {
  2112. REF_RELEASE (p);
  2113. }
  2114. gboolean
  2115. rspamd_http_message_set_body (struct rspamd_http_message *msg,
  2116. const gchar *data, gsize len)
  2117. {
  2118. union _rspamd_storage_u *storage;
  2119. storage = &msg->body_buf.c;
  2120. rspamd_http_message_storage_cleanup (msg);
  2121. if (msg->flags & RSPAMD_HTTP_FLAG_SHMEM) {
  2122. storage->shared.name = g_malloc (sizeof (*storage->shared.name));
  2123. REF_INIT_RETAIN (storage->shared.name, rspamd_http_shname_dtor);
  2124. #ifdef HAVE_SANE_SHMEM
  2125. #if defined(__DragonFly__)
  2126. // DragonFly uses regular files for shm. User rspamd is not allowed to create
  2127. // files in the root.
  2128. storage->shared.name->shm_name = g_strdup ("/tmp/rhm.XXXXXXXXXXXXXXXXXXXX");
  2129. #else
  2130. storage->shared.name->shm_name = g_strdup ("/rhm.XXXXXXXXXXXXXXXXXXXX");
  2131. #endif
  2132. storage->shared.shm_fd = rspamd_shmem_mkstemp (storage->shared.name->shm_name);
  2133. #else
  2134. /* XXX: assume that tempdir is /tmp */
  2135. storage->shared.name->shm_name = g_strdup ("/tmp/rhm.XXXXXXXXXXXXXXXXXXXX");
  2136. storage->shared.shm_fd = mkstemp (storage->shared.name->shm_name);
  2137. #endif
  2138. if (storage->shared.shm_fd == -1) {
  2139. return FALSE;
  2140. }
  2141. if (len != 0 && len != ULLONG_MAX) {
  2142. if (ftruncate (storage->shared.shm_fd, len) == -1) {
  2143. return FALSE;
  2144. }
  2145. msg->body_buf.str = mmap (NULL, len,
  2146. PROT_WRITE|PROT_READ, MAP_SHARED,
  2147. storage->shared.shm_fd, 0);
  2148. if (msg->body_buf.str == MAP_FAILED) {
  2149. return FALSE;
  2150. }
  2151. msg->body_buf.begin = msg->body_buf.str;
  2152. msg->body_buf.allocated_len = len;
  2153. if (data != NULL) {
  2154. memcpy (msg->body_buf.str, data, len);
  2155. msg->body_buf.len = len;
  2156. }
  2157. }
  2158. else {
  2159. msg->body_buf.len = 0;
  2160. msg->body_buf.begin = NULL;
  2161. msg->body_buf.str = NULL;
  2162. msg->body_buf.allocated_len = 0;
  2163. }
  2164. }
  2165. else {
  2166. if (len != 0 && len != ULLONG_MAX) {
  2167. if (data == NULL) {
  2168. storage->normal = rspamd_fstring_sized_new (len);
  2169. msg->body_buf.len = 0;
  2170. }
  2171. else {
  2172. storage->normal = rspamd_fstring_new_init (data, len);
  2173. msg->body_buf.len = len;
  2174. }
  2175. }
  2176. else {
  2177. storage->normal = rspamd_fstring_new ();
  2178. }
  2179. msg->body_buf.begin = storage->normal->str;
  2180. msg->body_buf.str = storage->normal->str;
  2181. msg->body_buf.allocated_len = storage->normal->allocated;
  2182. }
  2183. msg->flags |= RSPAMD_HTTP_FLAG_HAS_BODY;
  2184. return TRUE;
  2185. }
  2186. void
  2187. rspamd_http_message_set_method (struct rspamd_http_message *msg,
  2188. const gchar *method)
  2189. {
  2190. gint i;
  2191. /* Linear search: not very efficient method */
  2192. for (i = 0; i < HTTP_METHOD_MAX; i ++) {
  2193. if (g_ascii_strcasecmp (method, http_method_str (i)) == 0) {
  2194. msg->method = i;
  2195. }
  2196. }
  2197. }
  2198. gboolean
  2199. rspamd_http_message_set_body_from_fd (struct rspamd_http_message *msg,
  2200. gint fd)
  2201. {
  2202. union _rspamd_storage_u *storage;
  2203. struct stat st;
  2204. rspamd_http_message_storage_cleanup (msg);
  2205. storage = &msg->body_buf.c;
  2206. msg->flags |= RSPAMD_HTTP_FLAG_SHMEM|RSPAMD_HTTP_FLAG_SHMEM_IMMUTABLE;
  2207. storage->shared.shm_fd = dup (fd);
  2208. msg->body_buf.str = MAP_FAILED;
  2209. if (storage->shared.shm_fd == -1) {
  2210. return FALSE;
  2211. }
  2212. if (fstat (storage->shared.shm_fd, &st) == -1) {
  2213. return FALSE;
  2214. }
  2215. msg->body_buf.str = mmap (NULL, st.st_size,
  2216. PROT_READ, MAP_SHARED,
  2217. storage->shared.shm_fd, 0);
  2218. if (msg->body_buf.str == MAP_FAILED) {
  2219. return FALSE;
  2220. }
  2221. msg->body_buf.begin = msg->body_buf.str;
  2222. msg->body_buf.len = st.st_size;
  2223. msg->body_buf.allocated_len = st.st_size;
  2224. return TRUE;
  2225. }
  2226. gboolean
  2227. rspamd_http_message_set_body_from_fstring_steal (struct rspamd_http_message *msg,
  2228. rspamd_fstring_t *fstr)
  2229. {
  2230. union _rspamd_storage_u *storage;
  2231. rspamd_http_message_storage_cleanup (msg);
  2232. storage = &msg->body_buf.c;
  2233. msg->flags &= ~(RSPAMD_HTTP_FLAG_SHMEM|RSPAMD_HTTP_FLAG_SHMEM_IMMUTABLE);
  2234. storage->normal = fstr;
  2235. msg->body_buf.str = fstr->str;
  2236. msg->body_buf.begin = msg->body_buf.str;
  2237. msg->body_buf.len = fstr->len;
  2238. msg->body_buf.allocated_len = fstr->allocated;
  2239. return TRUE;
  2240. }
  2241. gboolean
  2242. rspamd_http_message_set_body_from_fstring_copy (struct rspamd_http_message *msg,
  2243. const rspamd_fstring_t *fstr)
  2244. {
  2245. union _rspamd_storage_u *storage;
  2246. rspamd_http_message_storage_cleanup (msg);
  2247. storage = &msg->body_buf.c;
  2248. msg->flags &= ~(RSPAMD_HTTP_FLAG_SHMEM|RSPAMD_HTTP_FLAG_SHMEM_IMMUTABLE);
  2249. storage->normal = rspamd_fstring_new_init (fstr->str, fstr->len);
  2250. msg->body_buf.str = storage->normal->str;
  2251. msg->body_buf.begin = msg->body_buf.str;
  2252. msg->body_buf.len = storage->normal->len;
  2253. msg->body_buf.allocated_len = storage->normal->allocated;
  2254. return TRUE;
  2255. }
  2256. static gboolean
  2257. rspamd_http_message_grow_body (struct rspamd_http_message *msg, gsize len)
  2258. {
  2259. struct stat st;
  2260. union _rspamd_storage_u *storage;
  2261. gsize newlen;
  2262. storage = &msg->body_buf.c;
  2263. if (msg->flags & RSPAMD_HTTP_FLAG_SHMEM) {
  2264. if (storage->shared.shm_fd == -1) {
  2265. return FALSE;
  2266. }
  2267. if (fstat (storage->shared.shm_fd, &st) == -1) {
  2268. return FALSE;
  2269. }
  2270. /* Check if we need to grow */
  2271. if ((gsize)st.st_size < msg->body_buf.len + len) {
  2272. /* Need to grow */
  2273. newlen = rspamd_fstring_suggest_size (msg->body_buf.len, st.st_size,
  2274. len);
  2275. /* Unmap as we need another size of segment */
  2276. if (msg->body_buf.str != MAP_FAILED) {
  2277. munmap (msg->body_buf.str, st.st_size);
  2278. }
  2279. if (ftruncate (storage->shared.shm_fd, newlen) == -1) {
  2280. return FALSE;
  2281. }
  2282. msg->body_buf.str = mmap (NULL, newlen,
  2283. PROT_WRITE|PROT_READ, MAP_SHARED,
  2284. storage->shared.shm_fd, 0);
  2285. if (msg->body_buf.str == MAP_FAILED) {
  2286. return FALSE;
  2287. }
  2288. msg->body_buf.begin = msg->body_buf.str;
  2289. msg->body_buf.allocated_len = newlen;
  2290. }
  2291. }
  2292. else {
  2293. storage->normal = rspamd_fstring_grow (storage->normal, len);
  2294. /* Append might cause realloc */
  2295. msg->body_buf.begin = storage->normal->str;
  2296. msg->body_buf.len = storage->normal->len;
  2297. msg->body_buf.str = storage->normal->str;
  2298. msg->body_buf.allocated_len = storage->normal->allocated;
  2299. }
  2300. return TRUE;
  2301. }
  2302. gboolean
  2303. rspamd_http_message_append_body (struct rspamd_http_message *msg,
  2304. const gchar *data, gsize len)
  2305. {
  2306. union _rspamd_storage_u *storage;
  2307. storage = &msg->body_buf.c;
  2308. if (msg->flags & RSPAMD_HTTP_FLAG_SHMEM) {
  2309. if (!rspamd_http_message_grow_body (msg, len)) {
  2310. return FALSE;
  2311. }
  2312. memcpy (msg->body_buf.str + msg->body_buf.len, data, len);
  2313. msg->body_buf.len += len;
  2314. }
  2315. else {
  2316. storage->normal = rspamd_fstring_append (storage->normal, data, len);
  2317. /* Append might cause realloc */
  2318. msg->body_buf.begin = storage->normal->str;
  2319. msg->body_buf.len = storage->normal->len;
  2320. msg->body_buf.str = storage->normal->str;
  2321. msg->body_buf.allocated_len = storage->normal->allocated;
  2322. }
  2323. return TRUE;
  2324. }
  2325. static void
  2326. rspamd_http_message_storage_cleanup (struct rspamd_http_message *msg)
  2327. {
  2328. union _rspamd_storage_u *storage;
  2329. struct stat st;
  2330. if (msg->flags & RSPAMD_HTTP_FLAG_SHMEM) {
  2331. storage = &msg->body_buf.c;
  2332. if (storage->shared.shm_fd > 0) {
  2333. g_assert (fstat (storage->shared.shm_fd, &st) != -1);
  2334. if (msg->body_buf.str != MAP_FAILED) {
  2335. munmap (msg->body_buf.str, st.st_size);
  2336. }
  2337. close (storage->shared.shm_fd);
  2338. }
  2339. if (storage->shared.name != NULL) {
  2340. REF_RELEASE (storage->shared.name);
  2341. }
  2342. storage->shared.shm_fd = -1;
  2343. msg->body_buf.str = MAP_FAILED;
  2344. }
  2345. else {
  2346. if (msg->body_buf.c.normal) {
  2347. rspamd_fstring_free (msg->body_buf.c.normal);
  2348. }
  2349. msg->body_buf.c.normal = NULL;
  2350. }
  2351. msg->body_buf.len = 0;
  2352. }
  2353. void
  2354. rspamd_http_connection_set_max_size (struct rspamd_http_connection *conn,
  2355. gsize sz)
  2356. {
  2357. conn->max_size = sz;
  2358. }
  2359. void
  2360. rspamd_http_message_free (struct rspamd_http_message *msg)
  2361. {
  2362. struct rspamd_http_header *hdr, *htmp, *hcur, *hcurtmp;
  2363. HASH_ITER (hh, msg->headers, hdr, htmp) {
  2364. HASH_DEL (msg->headers, hdr);
  2365. DL_FOREACH_SAFE (hdr, hcur, hcurtmp) {
  2366. rspamd_fstring_free (hcur->combined);
  2367. g_free (hcur);
  2368. }
  2369. }
  2370. rspamd_http_message_storage_cleanup (msg);
  2371. if (msg->url != NULL) {
  2372. rspamd_fstring_free (msg->url);
  2373. }
  2374. if (msg->status != NULL) {
  2375. rspamd_fstring_free (msg->status);
  2376. }
  2377. if (msg->host != NULL) {
  2378. rspamd_fstring_free (msg->host);
  2379. }
  2380. if (msg->peer_key != NULL) {
  2381. rspamd_pubkey_unref (msg->peer_key);
  2382. }
  2383. g_free (msg);
  2384. }
  2385. void
  2386. rspamd_http_message_set_peer_key (struct rspamd_http_message *msg,
  2387. struct rspamd_cryptobox_pubkey *pk)
  2388. {
  2389. if (msg->peer_key != NULL) {
  2390. rspamd_pubkey_unref (msg->peer_key);
  2391. }
  2392. if (pk) {
  2393. msg->peer_key = rspamd_pubkey_ref (pk);
  2394. }
  2395. else {
  2396. msg->peer_key = NULL;
  2397. }
  2398. }
  2399. void
  2400. rspamd_http_message_add_header_len (struct rspamd_http_message *msg,
  2401. const gchar *name,
  2402. const gchar *value,
  2403. gsize len)
  2404. {
  2405. struct rspamd_http_header *hdr, *found = NULL;
  2406. guint nlen, vlen;
  2407. if (msg != NULL && name != NULL && value != NULL) {
  2408. hdr = g_malloc0 (sizeof (struct rspamd_http_header));
  2409. nlen = strlen (name);
  2410. vlen = len;
  2411. hdr->combined = rspamd_fstring_sized_new (nlen + vlen + 4);
  2412. rspamd_printf_fstring (&hdr->combined, "%s: %*s\r\n", name, (gint)vlen,
  2413. value);
  2414. hdr->name.begin = hdr->combined->str;
  2415. hdr->name.len = nlen;
  2416. hdr->value.begin = hdr->combined->str + nlen + 2;
  2417. hdr->value.len = vlen;
  2418. HASH_FIND (hh, msg->headers, hdr->name.begin,
  2419. hdr->name.len, found);
  2420. if (found == NULL) {
  2421. HASH_ADD_KEYPTR (hh, msg->headers, hdr->name.begin,
  2422. hdr->name.len, hdr);
  2423. }
  2424. DL_APPEND (found, hdr);
  2425. }
  2426. }
  2427. void
  2428. rspamd_http_message_add_header (struct rspamd_http_message *msg,
  2429. const gchar *name,
  2430. const gchar *value)
  2431. {
  2432. if (value) {
  2433. rspamd_http_message_add_header_len (msg, name, value, strlen (value));
  2434. }
  2435. }
  2436. void
  2437. rspamd_http_message_add_header_fstr (struct rspamd_http_message *msg,
  2438. const gchar *name,
  2439. rspamd_fstring_t *value)
  2440. {
  2441. struct rspamd_http_header *hdr, *found = NULL;
  2442. guint nlen, vlen;
  2443. if (msg != NULL && name != NULL && value != NULL) {
  2444. hdr = g_malloc0 (sizeof (struct rspamd_http_header));
  2445. nlen = strlen (name);
  2446. vlen = value->len;
  2447. hdr->combined = rspamd_fstring_sized_new (nlen + vlen + 4);
  2448. rspamd_printf_fstring (&hdr->combined, "%s: %V\r\n", name, value);
  2449. hdr->name.begin = hdr->combined->str;
  2450. hdr->name.len = nlen;
  2451. hdr->value.begin = hdr->combined->str + nlen + 2;
  2452. hdr->value.len = vlen;
  2453. HASH_FIND (hh, msg->headers, hdr->name.begin,
  2454. hdr->name.len, found);
  2455. if (found == NULL) {
  2456. HASH_ADD_KEYPTR (hh, msg->headers, hdr->name.begin,
  2457. hdr->name.len, hdr);
  2458. }
  2459. DL_APPEND (found, hdr);
  2460. }
  2461. }
  2462. const rspamd_ftok_t *
  2463. rspamd_http_message_find_header (struct rspamd_http_message *msg,
  2464. const gchar *name)
  2465. {
  2466. struct rspamd_http_header *hdr;
  2467. const rspamd_ftok_t *res = NULL;
  2468. guint slen = strlen (name);
  2469. if (msg != NULL) {
  2470. HASH_FIND (hh, msg->headers, name, slen, hdr);
  2471. if (hdr) {
  2472. res = &hdr->value;
  2473. }
  2474. }
  2475. return res;
  2476. }
  2477. GPtrArray*
  2478. rspamd_http_message_find_header_multiple (
  2479. struct rspamd_http_message *msg,
  2480. const gchar *name)
  2481. {
  2482. GPtrArray *res = NULL;
  2483. struct rspamd_http_header *hdr, *cur;
  2484. guint slen = strlen (name);
  2485. if (msg != NULL) {
  2486. HASH_FIND (hh, msg->headers, name, slen, hdr);
  2487. if (hdr) {
  2488. res = g_ptr_array_sized_new (4);
  2489. LL_FOREACH (hdr, cur) {
  2490. g_ptr_array_add (res, &cur->value);
  2491. }
  2492. }
  2493. }
  2494. return res;
  2495. }
  2496. gboolean
  2497. rspamd_http_message_remove_header (struct rspamd_http_message *msg,
  2498. const gchar *name)
  2499. {
  2500. struct rspamd_http_header *hdr, *hcur, *hcurtmp;
  2501. gboolean res = FALSE;
  2502. guint slen = strlen (name);
  2503. if (msg != NULL) {
  2504. HASH_FIND (hh, msg->headers, name, slen, hdr);
  2505. if (hdr) {
  2506. HASH_DEL (msg->headers, hdr);
  2507. res = TRUE;
  2508. DL_FOREACH_SAFE (hdr, hcur, hcurtmp) {
  2509. rspamd_fstring_free (hcur->combined);
  2510. g_free (hcur);
  2511. }
  2512. }
  2513. }
  2514. return res;
  2515. }
  2516. /*
  2517. * HTTP router functions
  2518. */
  2519. static void
  2520. rspamd_http_entry_free (struct rspamd_http_connection_entry *entry)
  2521. {
  2522. if (entry != NULL) {
  2523. close (entry->conn->fd);
  2524. rspamd_http_connection_unref (entry->conn);
  2525. if (entry->rt->finish_handler) {
  2526. entry->rt->finish_handler (entry);
  2527. }
  2528. DL_DELETE (entry->rt->conns, entry);
  2529. g_free (entry);
  2530. }
  2531. }
  2532. static void
  2533. rspamd_http_router_error_handler (struct rspamd_http_connection *conn,
  2534. GError *err)
  2535. {
  2536. struct rspamd_http_connection_entry *entry = conn->ud;
  2537. struct rspamd_http_message *msg;
  2538. if (entry->is_reply) {
  2539. /* At this point we need to finish this session and close owned socket */
  2540. if (entry->rt->error_handler != NULL) {
  2541. entry->rt->error_handler (entry, err);
  2542. }
  2543. rspamd_http_entry_free (entry);
  2544. }
  2545. else {
  2546. /* Here we can write a reply to a client */
  2547. if (entry->rt->error_handler != NULL) {
  2548. entry->rt->error_handler (entry, err);
  2549. }
  2550. msg = rspamd_http_new_message (HTTP_RESPONSE);
  2551. msg->date = time (NULL);
  2552. msg->code = err->code;
  2553. rspamd_http_message_set_body (msg, err->message, strlen (err->message));
  2554. rspamd_http_connection_reset (entry->conn);
  2555. rspamd_http_connection_write_message (entry->conn,
  2556. msg,
  2557. NULL,
  2558. "text/plain",
  2559. entry,
  2560. entry->conn->fd,
  2561. entry->rt->ptv,
  2562. entry->rt->ev_base);
  2563. entry->is_reply = TRUE;
  2564. }
  2565. }
  2566. static const gchar *
  2567. rspamd_http_router_detect_ct (const gchar *path)
  2568. {
  2569. const gchar *dot;
  2570. guint i;
  2571. dot = strrchr (path, '.');
  2572. if (dot == NULL) {
  2573. return http_file_types[HTTP_MAGIC_PLAIN].ct;
  2574. }
  2575. dot++;
  2576. for (i = 0; i < G_N_ELEMENTS (http_file_types); i++) {
  2577. if (strcmp (http_file_types[i].ext, dot) == 0) {
  2578. return http_file_types[i].ct;
  2579. }
  2580. }
  2581. return http_file_types[HTTP_MAGIC_PLAIN].ct;
  2582. }
  2583. static gboolean
  2584. rspamd_http_router_is_subdir (const gchar *parent, const gchar *sub)
  2585. {
  2586. if (parent == NULL || sub == NULL || *parent == '\0') {
  2587. return FALSE;
  2588. }
  2589. while (*parent != '\0') {
  2590. if (*sub != *parent) {
  2591. return FALSE;
  2592. }
  2593. parent++;
  2594. sub++;
  2595. }
  2596. parent--;
  2597. if (*parent == G_DIR_SEPARATOR) {
  2598. return TRUE;
  2599. }
  2600. return (*sub == G_DIR_SEPARATOR || *sub == '\0');
  2601. }
  2602. static gboolean
  2603. rspamd_http_router_try_file (struct rspamd_http_connection_entry *entry,
  2604. rspamd_ftok_t *lookup, gboolean expand_path)
  2605. {
  2606. struct stat st;
  2607. gint fd;
  2608. gchar filebuf[PATH_MAX], realbuf[PATH_MAX], *dir;
  2609. struct rspamd_http_message *reply_msg;
  2610. rspamd_snprintf (filebuf, sizeof (filebuf), "%s%c%T",
  2611. entry->rt->default_fs_path, G_DIR_SEPARATOR, lookup);
  2612. if (realpath (filebuf, realbuf) == NULL ||
  2613. lstat (realbuf, &st) == -1) {
  2614. return FALSE;
  2615. }
  2616. if (S_ISDIR (st.st_mode) && expand_path) {
  2617. /* Try to append 'index.html' to the url */
  2618. rspamd_fstring_t *nlookup;
  2619. rspamd_ftok_t tok;
  2620. gboolean ret;
  2621. nlookup = rspamd_fstring_sized_new (lookup->len + sizeof ("index.html"));
  2622. rspamd_printf_fstring (&nlookup, "%T%c%s", lookup, G_DIR_SEPARATOR,
  2623. "index.html");
  2624. tok.begin = nlookup->str;
  2625. tok.len = nlookup->len;
  2626. ret = rspamd_http_router_try_file (entry, &tok, FALSE);
  2627. rspamd_fstring_free (nlookup);
  2628. return ret;
  2629. }
  2630. else if (!S_ISREG (st.st_mode)) {
  2631. return FALSE;
  2632. }
  2633. /* We also need to ensure that file is inside the defined dir */
  2634. rspamd_strlcpy (filebuf, realbuf, sizeof (filebuf));
  2635. dir = dirname (filebuf);
  2636. if (dir == NULL ||
  2637. !rspamd_http_router_is_subdir (entry->rt->default_fs_path,
  2638. dir)) {
  2639. return FALSE;
  2640. }
  2641. fd = open (realbuf, O_RDONLY);
  2642. if (fd == -1) {
  2643. return FALSE;
  2644. }
  2645. reply_msg = rspamd_http_new_message (HTTP_RESPONSE);
  2646. reply_msg->date = time (NULL);
  2647. reply_msg->code = 200;
  2648. rspamd_http_router_insert_headers (entry->rt, reply_msg);
  2649. if (!rspamd_http_message_set_body_from_fd (reply_msg, fd)) {
  2650. close (fd);
  2651. return FALSE;
  2652. }
  2653. close (fd);
  2654. rspamd_http_connection_reset (entry->conn);
  2655. msg_debug ("requested file %s", realbuf);
  2656. rspamd_http_connection_write_message (entry->conn, reply_msg, NULL,
  2657. rspamd_http_router_detect_ct (realbuf), entry, entry->conn->fd,
  2658. entry->rt->ptv, entry->rt->ev_base);
  2659. return TRUE;
  2660. }
  2661. static void
  2662. rspamd_http_router_send_error (GError *err,
  2663. struct rspamd_http_connection_entry *entry)
  2664. {
  2665. struct rspamd_http_message *err_msg;
  2666. err_msg = rspamd_http_new_message (HTTP_RESPONSE);
  2667. err_msg->date = time (NULL);
  2668. err_msg->code = err->code;
  2669. rspamd_http_message_set_body (err_msg, err->message,
  2670. strlen (err->message));
  2671. entry->is_reply = TRUE;
  2672. err_msg->status = rspamd_fstring_new_init (err->message, strlen (err->message));
  2673. rspamd_http_router_insert_headers (entry->rt, err_msg);
  2674. rspamd_http_connection_reset (entry->conn);
  2675. rspamd_http_connection_write_message (entry->conn,
  2676. err_msg,
  2677. NULL,
  2678. "text/plain",
  2679. entry,
  2680. entry->conn->fd,
  2681. entry->rt->ptv,
  2682. entry->rt->ev_base);
  2683. }
  2684. static int
  2685. rspamd_http_router_finish_handler (struct rspamd_http_connection *conn,
  2686. struct rspamd_http_message *msg)
  2687. {
  2688. struct rspamd_http_connection_entry *entry = conn->ud;
  2689. rspamd_http_router_handler_t handler = NULL;
  2690. gpointer found;
  2691. GError *err;
  2692. rspamd_ftok_t lookup;
  2693. const rspamd_ftok_t *encoding;
  2694. struct http_parser_url u;
  2695. guint i;
  2696. rspamd_regexp_t *re;
  2697. struct rspamd_http_connection_router *router;
  2698. G_STATIC_ASSERT (sizeof (rspamd_http_router_handler_t) ==
  2699. sizeof (gpointer));
  2700. memset (&lookup, 0, sizeof (lookup));
  2701. router = entry->rt;
  2702. if (entry->is_reply) {
  2703. /* Request is finished, it is safe to free a connection */
  2704. rspamd_http_entry_free (entry);
  2705. }
  2706. else {
  2707. if (G_UNLIKELY (msg->method != HTTP_GET && msg->method != HTTP_POST)) {
  2708. if (router->unknown_method_handler) {
  2709. return router->unknown_method_handler (entry, msg);
  2710. }
  2711. else {
  2712. err = g_error_new (HTTP_ERROR, 500,
  2713. "Invalid method");
  2714. if (entry->rt->error_handler != NULL) {
  2715. entry->rt->error_handler (entry, err);
  2716. }
  2717. rspamd_http_router_send_error (err, entry);
  2718. g_error_free (err);
  2719. return 0;
  2720. }
  2721. }
  2722. /* Search for path */
  2723. if (msg->url != NULL && msg->url->len != 0) {
  2724. http_parser_parse_url (msg->url->str, msg->url->len, TRUE, &u);
  2725. if (u.field_set & (1 << UF_PATH)) {
  2726. guint unnorm_len;
  2727. lookup.begin = msg->url->str + u.field_data[UF_PATH].off;
  2728. lookup.len = u.field_data[UF_PATH].len;
  2729. rspamd_http_normalize_path_inplace ((gchar *)lookup.begin,
  2730. lookup.len,
  2731. &unnorm_len);
  2732. lookup.len = unnorm_len;
  2733. }
  2734. else {
  2735. lookup.begin = msg->url->str;
  2736. lookup.len = msg->url->len;
  2737. }
  2738. found = g_hash_table_lookup (entry->rt->paths, &lookup);
  2739. memcpy (&handler, &found, sizeof (found));
  2740. msg_debug ("requested known path: %T", &lookup);
  2741. }
  2742. else {
  2743. err = g_error_new (HTTP_ERROR, 404,
  2744. "Empty path requested");
  2745. if (entry->rt->error_handler != NULL) {
  2746. entry->rt->error_handler (entry, err);
  2747. }
  2748. rspamd_http_router_send_error (err, entry);
  2749. g_error_free (err);
  2750. return 0;
  2751. }
  2752. entry->is_reply = TRUE;
  2753. encoding = rspamd_http_message_find_header (msg, "Accept-Encoding");
  2754. if (encoding && rspamd_substring_search (encoding->begin, encoding->len,
  2755. "gzip", 4) != -1) {
  2756. entry->support_gzip = TRUE;
  2757. }
  2758. if (handler != NULL) {
  2759. return handler (entry, msg);
  2760. }
  2761. else {
  2762. /* Try regexps */
  2763. for (i = 0; i < router->regexps->len; i ++) {
  2764. re = g_ptr_array_index (router->regexps, i);
  2765. if (rspamd_regexp_match (re, lookup.begin, lookup.len,
  2766. TRUE)) {
  2767. found = rspamd_regexp_get_ud (re);
  2768. memcpy (&handler, &found, sizeof (found));
  2769. return handler (entry, msg);
  2770. }
  2771. }
  2772. /* Now try plain file */
  2773. if (entry->rt->default_fs_path == NULL || lookup.len == 0 ||
  2774. !rspamd_http_router_try_file (entry, &lookup, TRUE)) {
  2775. err = g_error_new (HTTP_ERROR, 404,
  2776. "Not found");
  2777. if (entry->rt->error_handler != NULL) {
  2778. entry->rt->error_handler (entry, err);
  2779. }
  2780. msg_info ("path: %T not found", &lookup);
  2781. rspamd_http_router_send_error (err, entry);
  2782. g_error_free (err);
  2783. }
  2784. }
  2785. }
  2786. return 0;
  2787. }
  2788. struct rspamd_http_connection_router *
  2789. rspamd_http_router_new (rspamd_http_router_error_handler_t eh,
  2790. rspamd_http_router_finish_handler_t fh,
  2791. struct timeval *timeout, struct event_base *base,
  2792. const char *default_fs_path,
  2793. struct rspamd_keypair_cache *cache)
  2794. {
  2795. struct rspamd_http_connection_router * new;
  2796. struct stat st;
  2797. new = g_malloc0 (sizeof (struct rspamd_http_connection_router));
  2798. new->paths = g_hash_table_new_full (rspamd_ftok_icase_hash,
  2799. rspamd_ftok_icase_equal, rspamd_fstring_mapped_ftok_free, NULL);
  2800. new->regexps = g_ptr_array_new ();
  2801. new->conns = NULL;
  2802. new->error_handler = eh;
  2803. new->finish_handler = fh;
  2804. new->ev_base = base;
  2805. new->response_headers = g_hash_table_new_full (rspamd_strcase_hash,
  2806. rspamd_strcase_equal, g_free, g_free);
  2807. if (timeout) {
  2808. new->tv = *timeout;
  2809. new->ptv = &new->tv;
  2810. }
  2811. else {
  2812. new->ptv = NULL;
  2813. }
  2814. new->default_fs_path = NULL;
  2815. if (default_fs_path != NULL) {
  2816. if (stat (default_fs_path, &st) == -1) {
  2817. msg_err ("cannot stat %s", default_fs_path);
  2818. }
  2819. else {
  2820. if (!S_ISDIR (st.st_mode)) {
  2821. msg_err ("path %s is not a directory", default_fs_path);
  2822. }
  2823. else {
  2824. new->default_fs_path = realpath (default_fs_path, NULL);
  2825. }
  2826. }
  2827. }
  2828. new->cache = cache;
  2829. return new;
  2830. }
  2831. void
  2832. rspamd_http_router_set_key (struct rspamd_http_connection_router *router,
  2833. struct rspamd_cryptobox_keypair *key)
  2834. {
  2835. g_assert (key != NULL);
  2836. router->key = rspamd_keypair_ref (key);
  2837. }
  2838. void
  2839. rspamd_http_router_add_path (struct rspamd_http_connection_router *router,
  2840. const gchar *path, rspamd_http_router_handler_t handler)
  2841. {
  2842. gpointer ptr;
  2843. rspamd_ftok_t *key;
  2844. rspamd_fstring_t *storage;
  2845. G_STATIC_ASSERT (sizeof (rspamd_http_router_handler_t) ==
  2846. sizeof (gpointer));
  2847. if (path != NULL && handler != NULL && router != NULL) {
  2848. memcpy (&ptr, &handler, sizeof (ptr));
  2849. storage = rspamd_fstring_new_init (path, strlen (path));
  2850. key = g_malloc0 (sizeof (*key));
  2851. key->begin = storage->str;
  2852. key->len = storage->len;
  2853. g_hash_table_insert (router->paths, key, ptr);
  2854. }
  2855. }
  2856. void
  2857. rspamd_http_router_set_unknown_handler (struct rspamd_http_connection_router *router,
  2858. rspamd_http_router_handler_t handler)
  2859. {
  2860. if (router != NULL) {
  2861. router->unknown_method_handler = handler;
  2862. }
  2863. }
  2864. void
  2865. rspamd_http_router_add_header (struct rspamd_http_connection_router *router,
  2866. const gchar *name, const gchar *value)
  2867. {
  2868. if (name != NULL && value != NULL && router != NULL) {
  2869. g_hash_table_replace (router->response_headers, g_strdup (name),
  2870. g_strdup (value));
  2871. }
  2872. }
  2873. void
  2874. rspamd_http_router_insert_headers (struct rspamd_http_connection_router *router,
  2875. struct rspamd_http_message *msg)
  2876. {
  2877. GHashTableIter it;
  2878. gpointer k, v;
  2879. if (router && msg) {
  2880. g_hash_table_iter_init (&it, router->response_headers);
  2881. while (g_hash_table_iter_next (&it, &k, &v)) {
  2882. rspamd_http_message_add_header (msg, k, v);
  2883. }
  2884. }
  2885. }
  2886. void
  2887. rspamd_http_router_add_regexp (struct rspamd_http_connection_router *router,
  2888. struct rspamd_regexp_s *re, rspamd_http_router_handler_t handler)
  2889. {
  2890. gpointer ptr;
  2891. G_STATIC_ASSERT (sizeof (rspamd_http_router_handler_t) ==
  2892. sizeof (gpointer));
  2893. if (re != NULL && handler != NULL && router != NULL) {
  2894. memcpy (&ptr, &handler, sizeof (ptr));
  2895. rspamd_regexp_set_ud (re, ptr);
  2896. g_ptr_array_add (router->regexps, rspamd_regexp_ref (re));
  2897. }
  2898. }
  2899. void
  2900. rspamd_http_router_handle_socket (struct rspamd_http_connection_router *router,
  2901. gint fd, gpointer ud)
  2902. {
  2903. struct rspamd_http_connection_entry *conn;
  2904. conn = g_malloc0 (sizeof (struct rspamd_http_connection_entry));
  2905. conn->rt = router;
  2906. conn->ud = ud;
  2907. conn->is_reply = FALSE;
  2908. conn->conn = rspamd_http_connection_new (NULL,
  2909. rspamd_http_router_error_handler,
  2910. rspamd_http_router_finish_handler,
  2911. 0,
  2912. RSPAMD_HTTP_SERVER,
  2913. router->cache,
  2914. NULL);
  2915. if (router->key) {
  2916. rspamd_http_connection_set_key (conn->conn, router->key);
  2917. }
  2918. rspamd_http_connection_read_message (conn->conn, conn, fd, router->ptv,
  2919. router->ev_base);
  2920. DL_PREPEND (router->conns, conn);
  2921. }
  2922. void
  2923. rspamd_http_router_free (struct rspamd_http_connection_router *router)
  2924. {
  2925. struct rspamd_http_connection_entry *conn, *tmp;
  2926. rspamd_regexp_t *re;
  2927. guint i;
  2928. if (router) {
  2929. DL_FOREACH_SAFE (router->conns, conn, tmp) {
  2930. rspamd_http_entry_free (conn);
  2931. }
  2932. if (router->key) {
  2933. rspamd_keypair_unref (router->key);
  2934. }
  2935. if (router->cache) {
  2936. rspamd_keypair_cache_destroy (router->cache);
  2937. }
  2938. if (router->default_fs_path != NULL) {
  2939. g_free (router->default_fs_path);
  2940. }
  2941. for (i = 0; i < router->regexps->len; i ++) {
  2942. re = g_ptr_array_index (router->regexps, i);
  2943. rspamd_regexp_unref (re);
  2944. }
  2945. g_ptr_array_free (router->regexps, TRUE);
  2946. g_hash_table_unref (router->paths);
  2947. g_hash_table_unref (router->response_headers);
  2948. g_free (router);
  2949. }
  2950. }
  2951. void
  2952. rspamd_http_connection_set_key (struct rspamd_http_connection *conn,
  2953. struct rspamd_cryptobox_keypair *key)
  2954. {
  2955. struct rspamd_http_connection_private *priv = conn->priv;
  2956. g_assert (key != NULL);
  2957. priv->local_key = rspamd_keypair_ref (key);
  2958. }
  2959. const struct rspamd_cryptobox_pubkey*
  2960. rspamd_http_connection_get_peer_key (struct rspamd_http_connection *conn)
  2961. {
  2962. struct rspamd_http_connection_private *priv = conn->priv;
  2963. if (priv->peer_key) {
  2964. return priv->peer_key;
  2965. }
  2966. else if (priv->msg) {
  2967. return priv->msg->peer_key;
  2968. }
  2969. return NULL;
  2970. }
  2971. gboolean
  2972. rspamd_http_connection_is_encrypted (struct rspamd_http_connection *conn)
  2973. {
  2974. struct rspamd_http_connection_private *priv = conn->priv;
  2975. if (priv->peer_key != NULL) {
  2976. return TRUE;
  2977. }
  2978. else if (priv->msg) {
  2979. return priv->msg->peer_key != NULL;
  2980. }
  2981. return FALSE;
  2982. }
  2983. GHashTable *
  2984. rspamd_http_message_parse_query (struct rspamd_http_message *msg)
  2985. {
  2986. GHashTable *res;
  2987. rspamd_fstring_t *key = NULL, *value = NULL;
  2988. rspamd_ftok_t *key_tok = NULL, *value_tok = NULL;
  2989. const gchar *p, *c, *end;
  2990. struct http_parser_url u;
  2991. enum {
  2992. parse_key,
  2993. parse_eqsign,
  2994. parse_value,
  2995. parse_ampersand
  2996. } state = parse_key;
  2997. res = g_hash_table_new_full (rspamd_ftok_icase_hash,
  2998. rspamd_ftok_icase_equal,
  2999. rspamd_fstring_mapped_ftok_free,
  3000. rspamd_fstring_mapped_ftok_free);
  3001. if (msg->url && msg->url->len > 0) {
  3002. http_parser_parse_url (msg->url->str, msg->url->len, TRUE, &u);
  3003. if (u.field_set & (1 << UF_QUERY)) {
  3004. p = msg->url->str + u.field_data[UF_QUERY].off;
  3005. c = p;
  3006. end = p + u.field_data[UF_QUERY].len;
  3007. while (p <= end) {
  3008. switch (state) {
  3009. case parse_key:
  3010. if ((p == end || *p == '&') && p > c) {
  3011. /* We have a single parameter without a value */
  3012. key = rspamd_fstring_new_init (c, p - c);
  3013. key_tok = rspamd_ftok_map (key);
  3014. key_tok->len = rspamd_url_decode (key->str, key->str,
  3015. key->len);
  3016. value = rspamd_fstring_new_init ("", 0);
  3017. value_tok = rspamd_ftok_map (value);
  3018. g_hash_table_replace (res, key_tok, value_tok);
  3019. state = parse_ampersand;
  3020. }
  3021. else if (*p == '=' && p > c) {
  3022. /* We have something like key=value */
  3023. key = rspamd_fstring_new_init (c, p - c);
  3024. key_tok = rspamd_ftok_map (key);
  3025. key_tok->len = rspamd_url_decode (key->str, key->str,
  3026. key->len);
  3027. state = parse_eqsign;
  3028. }
  3029. else {
  3030. p ++;
  3031. }
  3032. break;
  3033. case parse_eqsign:
  3034. if (*p != '=') {
  3035. c = p;
  3036. state = parse_value;
  3037. }
  3038. else {
  3039. p ++;
  3040. }
  3041. break;
  3042. case parse_value:
  3043. if ((p == end || *p == '&') && p >= c) {
  3044. g_assert (key != NULL);
  3045. if (p > c) {
  3046. value = rspamd_fstring_new_init (c, p - c);
  3047. value_tok = rspamd_ftok_map (value);
  3048. value_tok->len = rspamd_url_decode (value->str,
  3049. value->str,
  3050. value->len);
  3051. /* Detect quotes for value */
  3052. if (value_tok->begin[0] == '"') {
  3053. memmove (value->str, value->str + 1,
  3054. value_tok->len - 1);
  3055. value_tok->len --;
  3056. }
  3057. if (value_tok->begin[value_tok->len - 1] == '"') {
  3058. value_tok->len --;
  3059. }
  3060. }
  3061. else {
  3062. value = rspamd_fstring_new_init ("", 0);
  3063. value_tok = rspamd_ftok_map (value);
  3064. }
  3065. g_hash_table_replace (res, key_tok, value_tok);
  3066. key = value = NULL;
  3067. key_tok = value_tok = NULL;
  3068. state = parse_ampersand;
  3069. }
  3070. else {
  3071. p ++;
  3072. }
  3073. break;
  3074. case parse_ampersand:
  3075. if (p != end && *p != '&') {
  3076. c = p;
  3077. state = parse_key;
  3078. }
  3079. else {
  3080. p ++;
  3081. }
  3082. break;
  3083. }
  3084. }
  3085. }
  3086. if (state != parse_ampersand && key != NULL) {
  3087. rspamd_fstring_free (key);
  3088. }
  3089. }
  3090. return res;
  3091. }
  3092. glong
  3093. rspamd_http_date_format (gchar *buf, gsize len, time_t time)
  3094. {
  3095. struct tm tms;
  3096. rspamd_gmtime (time, &tms);
  3097. return rspamd_snprintf (buf, len, "%s, %02d %s %4d %02d:%02d:%02d GMT",
  3098. http_week[tms.tm_wday], tms.tm_mday,
  3099. http_month[tms.tm_mon], tms.tm_year + 1900,
  3100. tms.tm_hour, tms.tm_min, tms.tm_sec);
  3101. }
  3102. struct rspamd_http_message *
  3103. rspamd_http_message_ref (struct rspamd_http_message *msg)
  3104. {
  3105. REF_RETAIN (msg);
  3106. return msg;
  3107. }
  3108. void
  3109. rspamd_http_message_unref (struct rspamd_http_message *msg)
  3110. {
  3111. REF_RELEASE (msg);
  3112. }
  3113. void
  3114. rspamd_http_normalize_path_inplace (gchar *path, guint len, guint *nlen)
  3115. {
  3116. const gchar *p, *end, *slash = NULL, *dot = NULL;
  3117. gchar *o;
  3118. enum {
  3119. st_normal = 0,
  3120. st_got_dot,
  3121. st_got_dot_dot,
  3122. st_got_slash,
  3123. st_got_slash_slash,
  3124. } state = st_normal;
  3125. p = path;
  3126. end = path + len;
  3127. o = path;
  3128. while (p < end) {
  3129. switch (state) {
  3130. case st_normal:
  3131. if (G_UNLIKELY (*p == '/')) {
  3132. state = st_got_slash;
  3133. slash = p;
  3134. }
  3135. else if (G_UNLIKELY (*p == '.')) {
  3136. state = st_got_dot;
  3137. dot = p;
  3138. }
  3139. else {
  3140. *o++ = *p;
  3141. }
  3142. p ++;
  3143. break;
  3144. case st_got_slash:
  3145. if (G_UNLIKELY (*p == '/')) {
  3146. /* Ignore double slash */
  3147. *o++ = *p;
  3148. state = st_got_slash_slash;
  3149. }
  3150. else if (G_UNLIKELY (*p == '.')) {
  3151. dot = p;
  3152. state = st_got_dot;
  3153. }
  3154. else {
  3155. *o++ = '/';
  3156. *o++ = *p;
  3157. slash = NULL;
  3158. dot = NULL;
  3159. state = st_normal;
  3160. }
  3161. p ++;
  3162. break;
  3163. case st_got_slash_slash:
  3164. if (G_LIKELY (*p != '/')) {
  3165. slash = p - 1;
  3166. dot = NULL;
  3167. state = st_normal;
  3168. continue;
  3169. }
  3170. p ++;
  3171. break;
  3172. case st_got_dot:
  3173. if (G_UNLIKELY (*p == '/')) {
  3174. /* Remove any /./ or ./ paths */
  3175. if (((o > path && *(o - 1) != '/') || (o == path)) && slash) {
  3176. /* Preserve one slash */
  3177. *o++ = '/';
  3178. }
  3179. slash = p;
  3180. dot = NULL;
  3181. /* Ignore last slash */
  3182. state = st_normal;
  3183. }
  3184. else if (*p == '.') {
  3185. /* Double dot character */
  3186. state = st_got_dot_dot;
  3187. }
  3188. else {
  3189. /* We have something like .some or /.some */
  3190. if (dot && p > dot) {
  3191. if (slash == dot - 1 && (o > path && *(o - 1) != '/')) {
  3192. /* /.blah */
  3193. memmove (o, slash, p - slash);
  3194. o += p - slash;
  3195. }
  3196. else {
  3197. memmove (o, dot, p - dot);
  3198. o += p - dot;
  3199. }
  3200. }
  3201. slash = NULL;
  3202. dot = NULL;
  3203. state = st_normal;
  3204. continue;
  3205. }
  3206. p ++;
  3207. break;
  3208. case st_got_dot_dot:
  3209. if (*p == '/') {
  3210. /* We have something like /../ or ../ */
  3211. if (slash) {
  3212. /* We need to remove the last component from o if it is there */
  3213. if (o > path + 2 && *(o - 1) == '/') {
  3214. slash = rspamd_memrchr (path, '/', o - path - 2);
  3215. }
  3216. else if (o > path + 1) {
  3217. slash = rspamd_memrchr (path, '/', o - path - 1);
  3218. }
  3219. else {
  3220. slash = NULL;
  3221. }
  3222. if (slash) {
  3223. o = (gchar *)slash;
  3224. }
  3225. /* Otherwise we keep these dots */
  3226. slash = p;
  3227. state = st_got_slash;
  3228. }
  3229. else {
  3230. /* We have something like bla../, so we need to copy it as is */
  3231. if (o > path && dot && p > dot) {
  3232. memmove (o, dot, p - dot);
  3233. o += p - dot;
  3234. }
  3235. slash = NULL;
  3236. dot = NULL;
  3237. state = st_normal;
  3238. continue;
  3239. }
  3240. }
  3241. else {
  3242. /* We have something like ..bla or ... */
  3243. if (slash) {
  3244. *o ++ = '/';
  3245. }
  3246. if (dot && p > dot) {
  3247. memmove (o, dot, p - dot);
  3248. o += p - dot;
  3249. }
  3250. slash = NULL;
  3251. dot = NULL;
  3252. state = st_normal;
  3253. continue;
  3254. }
  3255. p ++;
  3256. break;
  3257. }
  3258. }
  3259. /* Leftover */
  3260. switch (state) {
  3261. case st_got_dot_dot:
  3262. /* Trailing .. */
  3263. if (slash) {
  3264. /* We need to remove the last component from o if it is there */
  3265. if (o > path + 2 && *(o - 1) == '/') {
  3266. slash = rspamd_memrchr (path, '/', o - path - 2);
  3267. }
  3268. else if (o > path + 1) {
  3269. slash = rspamd_memrchr (path, '/', o - path - 1);
  3270. }
  3271. else {
  3272. if (o == path) {
  3273. /* Corner case */
  3274. *o++ = '/';
  3275. }
  3276. slash = NULL;
  3277. }
  3278. if (slash) {
  3279. /* Remove last / */
  3280. o = (gchar *)slash;
  3281. }
  3282. }
  3283. else {
  3284. /* Corner case */
  3285. if (o == path) {
  3286. *o++ = '/';
  3287. }
  3288. else {
  3289. if (dot && p > dot) {
  3290. memmove (o, dot, p - dot);
  3291. o += p - dot;
  3292. }
  3293. }
  3294. }
  3295. break;
  3296. case st_got_slash:
  3297. *o++ = '/';
  3298. break;
  3299. default:
  3300. if (o > path + 1 && *(o - 1) == '/') {
  3301. o --;
  3302. }
  3303. break;
  3304. }
  3305. if (nlen) {
  3306. *nlen = (o - path);
  3307. }
  3308. }
  3309. void
  3310. rspamd_http_connection_disable_encryption (struct rspamd_http_connection *conn)
  3311. {
  3312. struct rspamd_http_connection_private *priv;
  3313. priv = conn->priv;
  3314. if (priv) {
  3315. if (priv->local_key) {
  3316. rspamd_keypair_unref (priv->local_key);
  3317. }
  3318. if (priv->peer_key) {
  3319. rspamd_pubkey_unref (priv->peer_key);
  3320. }
  3321. priv->local_key = NULL;
  3322. priv->peer_key = NULL;
  3323. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
  3324. }
  3325. }