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_connection.c 62KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549
  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 "http_connection.h"
  18. #include "http_private.h"
  19. #include "http_message.h"
  20. #include "utlist.h"
  21. #include "util.h"
  22. #include "printf.h"
  23. #include "logger.h"
  24. #include "ref.h"
  25. #include "ottery.h"
  26. #include "keypair_private.h"
  27. #include "cryptobox.h"
  28. #include "libutil/libev_helper.h"
  29. #include "libserver/ssl_util.h"
  30. #include "libserver/url.h"
  31. #include "contrib/mumhash/mum.h"
  32. #include "contrib/http-parser/http_parser.h"
  33. #include "unix-std.h"
  34. #include <openssl/err.h>
  35. #define ENCRYPTED_VERSION " HTTP/1.0"
  36. struct _rspamd_http_privbuf {
  37. rspamd_fstring_t *data;
  38. const gchar *zc_buf;
  39. gsize zc_remain;
  40. ref_entry_t ref;
  41. };
  42. enum rspamd_http_priv_flags {
  43. RSPAMD_HTTP_CONN_FLAG_ENCRYPTED = 1u << 0u,
  44. RSPAMD_HTTP_CONN_FLAG_NEW_HEADER = 1u << 1u,
  45. RSPAMD_HTTP_CONN_FLAG_RESETED = 1u << 2u,
  46. RSPAMD_HTTP_CONN_FLAG_TOO_LARGE = 1u << 3u,
  47. RSPAMD_HTTP_CONN_FLAG_ENCRYPTION_NEEDED = 1u << 4u,
  48. RSPAMD_HTTP_CONN_FLAG_PROXY = 1u << 5u,
  49. RSPAMD_HTTP_CONN_FLAG_PROXY_REQUEST = 1u << 6u,
  50. RSPAMD_HTTP_CONN_OWN_SOCKET = 1u << 7u,
  51. };
  52. #define IS_CONN_ENCRYPTED(c) ((c)->flags & RSPAMD_HTTP_CONN_FLAG_ENCRYPTED)
  53. #define IS_CONN_RESETED(c) ((c)->flags & RSPAMD_HTTP_CONN_FLAG_RESETED)
  54. struct rspamd_http_connection_private {
  55. struct rspamd_http_context *ctx;
  56. struct rspamd_ssl_connection *ssl;
  57. struct _rspamd_http_privbuf *buf;
  58. struct rspamd_keypair_cache *cache;
  59. struct rspamd_cryptobox_pubkey *peer_key;
  60. struct rspamd_cryptobox_keypair *local_key;
  61. struct rspamd_http_header *header;
  62. struct http_parser parser;
  63. struct http_parser_settings parser_cb;
  64. struct rspamd_io_ev ev;
  65. ev_tstamp timeout;
  66. struct rspamd_http_message *msg;
  67. struct iovec *out;
  68. guint outlen;
  69. enum rspamd_http_priv_flags flags;
  70. gsize wr_pos;
  71. gsize wr_total;
  72. };
  73. static const rspamd_ftok_t key_header = {
  74. .begin = "Key",
  75. .len = 3
  76. };
  77. static const rspamd_ftok_t date_header = {
  78. .begin = "Date",
  79. .len = 4
  80. };
  81. static const rspamd_ftok_t last_modified_header = {
  82. .begin = "Last-Modified",
  83. .len = 13
  84. };
  85. #define HTTP_ERROR http_error_quark ()
  86. GQuark
  87. http_error_quark (void)
  88. {
  89. return g_quark_from_static_string ("http-error-quark");
  90. }
  91. static void
  92. rspamd_http_privbuf_dtor (gpointer ud)
  93. {
  94. struct _rspamd_http_privbuf *p = (struct _rspamd_http_privbuf *)ud;
  95. if (p->data) {
  96. rspamd_fstring_free (p->data);
  97. }
  98. g_free (p);
  99. }
  100. static const gchar *
  101. rspamd_http_code_to_str (gint code)
  102. {
  103. if (code == 200) {
  104. return "OK";
  105. }
  106. else if (code == 404) {
  107. return "Not found";
  108. }
  109. else if (code == 403 || code == 401) {
  110. return "Not authorized";
  111. }
  112. else if (code >= 400 && code < 500) {
  113. return "Bad request";
  114. }
  115. else if (code >= 300 && code < 400) {
  116. return "See Other";
  117. }
  118. else if (code >= 500 && code < 600) {
  119. return "Internal server error";
  120. }
  121. return "Unknown error";
  122. }
  123. static void
  124. rspamd_http_parse_key (rspamd_ftok_t *data, struct rspamd_http_connection *conn,
  125. struct rspamd_http_connection_private *priv)
  126. {
  127. guchar *decoded_id;
  128. const gchar *eq_pos;
  129. gsize id_len;
  130. struct rspamd_cryptobox_pubkey *pk;
  131. if (priv->local_key == NULL) {
  132. /* In this case we cannot do anything, e.g. we cannot decrypt payload */
  133. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
  134. }
  135. else {
  136. /* Check sanity of what we have */
  137. eq_pos = memchr (data->begin, '=', data->len);
  138. if (eq_pos != NULL) {
  139. decoded_id = rspamd_decode_base32 (data->begin, eq_pos - data->begin,
  140. &id_len, RSPAMD_BASE32_DEFAULT);
  141. if (decoded_id != NULL && id_len >= RSPAMD_KEYPAIR_SHORT_ID_LEN) {
  142. pk = rspamd_pubkey_from_base32 (eq_pos + 1,
  143. data->begin + data->len - eq_pos - 1,
  144. RSPAMD_KEYPAIR_KEX,
  145. RSPAMD_CRYPTOBOX_MODE_25519);
  146. if (pk != NULL) {
  147. if (memcmp (rspamd_keypair_get_id (priv->local_key),
  148. decoded_id,
  149. RSPAMD_KEYPAIR_SHORT_ID_LEN) == 0) {
  150. priv->msg->peer_key = pk;
  151. if (priv->cache && priv->msg->peer_key) {
  152. rspamd_keypair_cache_process (priv->cache,
  153. priv->local_key,
  154. priv->msg->peer_key);
  155. }
  156. }
  157. else {
  158. rspamd_pubkey_unref (pk);
  159. }
  160. }
  161. }
  162. priv->flags |= RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
  163. g_free (decoded_id);
  164. }
  165. }
  166. }
  167. static inline void
  168. rspamd_http_check_special_header (struct rspamd_http_connection *conn,
  169. struct rspamd_http_connection_private *priv)
  170. {
  171. if (rspamd_ftok_casecmp (&priv->header->name, &date_header) == 0) {
  172. priv->msg->date = rspamd_http_parse_date (priv->header->value.begin,
  173. priv->header->value.len);
  174. }
  175. else if (rspamd_ftok_casecmp (&priv->header->name, &key_header) == 0) {
  176. rspamd_http_parse_key (&priv->header->value, conn, priv);
  177. }
  178. else if (rspamd_ftok_casecmp (&priv->header->name, &last_modified_header) == 0) {
  179. priv->msg->last_modified = rspamd_http_parse_date (
  180. priv->header->value.begin,
  181. priv->header->value.len);
  182. }
  183. }
  184. static gint
  185. rspamd_http_on_url (http_parser * parser, const gchar *at, size_t length)
  186. {
  187. struct rspamd_http_connection *conn =
  188. (struct rspamd_http_connection *)parser->data;
  189. struct rspamd_http_connection_private *priv;
  190. priv = conn->priv;
  191. priv->msg->url = rspamd_fstring_append (priv->msg->url, at, length);
  192. return 0;
  193. }
  194. static gint
  195. rspamd_http_on_status (http_parser * parser, const gchar *at, size_t length)
  196. {
  197. struct rspamd_http_connection *conn =
  198. (struct rspamd_http_connection *)parser->data;
  199. struct rspamd_http_connection_private *priv;
  200. priv = conn->priv;
  201. if (parser->status_code != 200) {
  202. if (priv->msg->status == NULL) {
  203. priv->msg->status = rspamd_fstring_new ();
  204. }
  205. priv->msg->status = rspamd_fstring_append (priv->msg->status, at, length);
  206. }
  207. return 0;
  208. }
  209. static void
  210. rspamd_http_finish_header (struct rspamd_http_connection *conn,
  211. struct rspamd_http_connection_private *priv)
  212. {
  213. struct rspamd_http_header *hdr;
  214. khiter_t k;
  215. gint r;
  216. priv->header->combined = rspamd_fstring_append (priv->header->combined,
  217. "\r\n", 2);
  218. priv->header->value.len = priv->header->combined->len -
  219. priv->header->name.len - 4;
  220. priv->header->value.begin = priv->header->combined->str +
  221. priv->header->name.len + 2;
  222. priv->header->name.begin = priv->header->combined->str;
  223. k = kh_put (rspamd_http_headers_hash, priv->msg->headers, &priv->header->name,
  224. &r);
  225. if (r != 0) {
  226. kh_value (priv->msg->headers, k) = priv->header;
  227. hdr = NULL;
  228. }
  229. else {
  230. hdr = kh_value (priv->msg->headers, k);
  231. }
  232. DL_APPEND (hdr, priv->header);
  233. rspamd_http_check_special_header (conn, priv);
  234. }
  235. static void
  236. rspamd_http_init_header (struct rspamd_http_connection_private *priv)
  237. {
  238. priv->header = g_malloc0 (sizeof (struct rspamd_http_header));
  239. priv->header->combined = rspamd_fstring_new ();
  240. }
  241. static gint
  242. rspamd_http_on_header_field (http_parser * parser,
  243. const gchar *at,
  244. size_t length)
  245. {
  246. struct rspamd_http_connection *conn =
  247. (struct rspamd_http_connection *)parser->data;
  248. struct rspamd_http_connection_private *priv;
  249. priv = conn->priv;
  250. if (priv->header == NULL) {
  251. rspamd_http_init_header (priv);
  252. }
  253. else if (priv->flags & RSPAMD_HTTP_CONN_FLAG_NEW_HEADER) {
  254. rspamd_http_finish_header (conn, priv);
  255. rspamd_http_init_header (priv);
  256. }
  257. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
  258. priv->header->combined = rspamd_fstring_append (priv->header->combined,
  259. at, length);
  260. return 0;
  261. }
  262. static gint
  263. rspamd_http_on_header_value (http_parser * parser,
  264. const gchar *at,
  265. size_t length)
  266. {
  267. struct rspamd_http_connection *conn =
  268. (struct rspamd_http_connection *)parser->data;
  269. struct rspamd_http_connection_private *priv;
  270. priv = conn->priv;
  271. if (priv->header == NULL) {
  272. /* Should not happen */
  273. return -1;
  274. }
  275. if (!(priv->flags & RSPAMD_HTTP_CONN_FLAG_NEW_HEADER)) {
  276. priv->flags |= RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
  277. priv->header->combined = rspamd_fstring_append (priv->header->combined,
  278. ": ", 2);
  279. priv->header->name.len = priv->header->combined->len - 2;
  280. }
  281. priv->header->combined = rspamd_fstring_append (priv->header->combined,
  282. at, length);
  283. return 0;
  284. }
  285. static int
  286. rspamd_http_on_headers_complete (http_parser * parser)
  287. {
  288. struct rspamd_http_connection *conn =
  289. (struct rspamd_http_connection *)parser->data;
  290. struct rspamd_http_connection_private *priv;
  291. struct rspamd_http_message *msg;
  292. int ret;
  293. priv = conn->priv;
  294. msg = priv->msg;
  295. if (priv->header != NULL) {
  296. rspamd_http_finish_header (conn, priv);
  297. priv->header = NULL;
  298. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
  299. }
  300. if (msg->method == HTTP_HEAD) {
  301. /* We don't care about the rest */
  302. rspamd_ev_watcher_stop (priv->ctx->event_loop, &priv->ev);
  303. msg->code = parser->status_code;
  304. rspamd_http_connection_ref (conn);
  305. ret = conn->finish_handler (conn, msg);
  306. if (conn->opts & RSPAMD_HTTP_CLIENT_KEEP_ALIVE) {
  307. rspamd_http_context_push_keepalive (conn->priv->ctx, conn,
  308. msg, conn->priv->ctx->event_loop);
  309. rspamd_http_connection_reset (conn);
  310. }
  311. else {
  312. conn->finished = TRUE;
  313. }
  314. rspamd_http_connection_unref (conn);
  315. return ret;
  316. }
  317. /*
  318. * HTTP parser sets content length to (-1) when it doesn't know the real
  319. * length, for example, in case of chunked encoding.
  320. *
  321. * Hence, we skip body setup here
  322. */
  323. if (parser->content_length != ULLONG_MAX && parser->content_length != 0 &&
  324. msg->method != HTTP_HEAD) {
  325. if (conn->max_size > 0 &&
  326. parser->content_length > conn->max_size) {
  327. /* Too large message */
  328. priv->flags |= RSPAMD_HTTP_CONN_FLAG_TOO_LARGE;
  329. return -1;
  330. }
  331. if (!rspamd_http_message_set_body (msg, NULL, parser->content_length)) {
  332. return -1;
  333. }
  334. }
  335. if (parser->flags & F_SPAMC) {
  336. msg->flags |= RSPAMD_HTTP_FLAG_SPAMC;
  337. }
  338. msg->method = parser->method;
  339. msg->code = parser->status_code;
  340. return 0;
  341. }
  342. static void
  343. rspamd_http_switch_zc (struct _rspamd_http_privbuf *pbuf,
  344. struct rspamd_http_message *msg)
  345. {
  346. pbuf->zc_buf = msg->body_buf.begin + msg->body_buf.len;
  347. pbuf->zc_remain = msg->body_buf.allocated_len - msg->body_buf.len;
  348. }
  349. static int
  350. rspamd_http_on_body (http_parser * parser, const gchar *at, size_t length)
  351. {
  352. struct rspamd_http_connection *conn =
  353. (struct rspamd_http_connection *)parser->data;
  354. struct rspamd_http_connection_private *priv;
  355. struct rspamd_http_message *msg;
  356. struct _rspamd_http_privbuf *pbuf;
  357. const gchar *p;
  358. priv = conn->priv;
  359. msg = priv->msg;
  360. pbuf = priv->buf;
  361. p = at;
  362. if (!(msg->flags & RSPAMD_HTTP_FLAG_HAS_BODY)) {
  363. if (!rspamd_http_message_set_body (msg, NULL, parser->content_length)) {
  364. return -1;
  365. }
  366. }
  367. if (conn->finished) {
  368. return 0;
  369. }
  370. if (conn->max_size > 0 &&
  371. msg->body_buf.len + length > conn->max_size) {
  372. /* Body length overflow */
  373. priv->flags |= RSPAMD_HTTP_CONN_FLAG_TOO_LARGE;
  374. return -1;
  375. }
  376. if (!pbuf->zc_buf) {
  377. if (!rspamd_http_message_append_body (msg, at, length)) {
  378. return -1;
  379. }
  380. /* We might have some leftover in our private buffer */
  381. if (pbuf->data->len == length) {
  382. /* Switch to zero-copy mode */
  383. rspamd_http_switch_zc (pbuf, msg);
  384. }
  385. }
  386. else {
  387. if (msg->body_buf.begin + msg->body_buf.len != at) {
  388. /* Likely chunked encoding */
  389. memmove ((gchar *)msg->body_buf.begin + msg->body_buf.len, at, length);
  390. p = msg->body_buf.begin + msg->body_buf.len;
  391. }
  392. /* Adjust zero-copy buf */
  393. msg->body_buf.len += length;
  394. if (!(msg->flags & RSPAMD_HTTP_FLAG_SHMEM)) {
  395. msg->body_buf.c.normal->len += length;
  396. }
  397. pbuf->zc_buf = msg->body_buf.begin + msg->body_buf.len;
  398. pbuf->zc_remain = msg->body_buf.allocated_len - msg->body_buf.len;
  399. }
  400. if ((conn->opts & RSPAMD_HTTP_BODY_PARTIAL) && !IS_CONN_ENCRYPTED (priv)) {
  401. /* Incremental update is impossible for encrypted requests so far */
  402. return (conn->body_handler (conn, msg, p, length));
  403. }
  404. return 0;
  405. }
  406. static int
  407. rspamd_http_on_body_decrypted (http_parser * parser, const gchar *at, size_t length)
  408. {
  409. struct rspamd_http_connection *conn =
  410. (struct rspamd_http_connection *)parser->data;
  411. struct rspamd_http_connection_private *priv;
  412. priv = conn->priv;
  413. if (priv->header != NULL) {
  414. rspamd_http_finish_header (conn, priv);
  415. priv->header = NULL;
  416. }
  417. if (conn->finished) {
  418. return 0;
  419. }
  420. if (priv->msg->body_buf.len == 0) {
  421. priv->msg->body_buf.begin = at;
  422. priv->msg->method = parser->method;
  423. priv->msg->code = parser->status_code;
  424. }
  425. priv->msg->body_buf.len += length;
  426. return 0;
  427. }
  428. static int
  429. rspamd_http_on_headers_complete_decrypted (http_parser *parser)
  430. {
  431. struct rspamd_http_connection *conn =
  432. (struct rspamd_http_connection *) parser->data;
  433. struct rspamd_http_connection_private *priv;
  434. struct rspamd_http_message *msg;
  435. int ret;
  436. priv = conn->priv;
  437. msg = priv->msg;
  438. if (priv->header != NULL) {
  439. rspamd_http_finish_header (conn, priv);
  440. priv->header = NULL;
  441. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
  442. }
  443. if (parser->flags & F_SPAMC) {
  444. priv->msg->flags |= RSPAMD_HTTP_FLAG_SPAMC;
  445. }
  446. if (msg->method == HTTP_HEAD) {
  447. /* We don't care about the rest */
  448. rspamd_ev_watcher_stop (priv->ctx->event_loop, &priv->ev);
  449. msg->code = parser->status_code;
  450. rspamd_http_connection_ref (conn);
  451. ret = conn->finish_handler (conn, msg);
  452. if (conn->opts & RSPAMD_HTTP_CLIENT_KEEP_ALIVE) {
  453. rspamd_http_context_push_keepalive (conn->priv->ctx, conn,
  454. msg, conn->priv->ctx->event_loop);
  455. rspamd_http_connection_reset (conn);
  456. }
  457. else {
  458. conn->finished = TRUE;
  459. }
  460. rspamd_http_connection_unref (conn);
  461. return ret;
  462. }
  463. priv->msg->method = parser->method;
  464. priv->msg->code = parser->status_code;
  465. return 0;
  466. }
  467. static int
  468. rspamd_http_decrypt_message (struct rspamd_http_connection *conn,
  469. struct rspamd_http_connection_private *priv,
  470. struct rspamd_cryptobox_pubkey *peer_key)
  471. {
  472. guchar *nonce, *m;
  473. const guchar *nm;
  474. gsize dec_len;
  475. struct rspamd_http_message *msg = priv->msg;
  476. struct rspamd_http_header *hdr, *hcur, *hcurtmp;
  477. struct http_parser decrypted_parser;
  478. struct http_parser_settings decrypted_cb;
  479. enum rspamd_cryptobox_mode mode;
  480. mode = rspamd_keypair_alg (priv->local_key);
  481. nonce = msg->body_buf.str;
  482. m = msg->body_buf.str + rspamd_cryptobox_nonce_bytes (mode) +
  483. rspamd_cryptobox_mac_bytes (mode);
  484. dec_len = msg->body_buf.len - rspamd_cryptobox_nonce_bytes (mode) -
  485. rspamd_cryptobox_mac_bytes (mode);
  486. if ((nm = rspamd_pubkey_get_nm (peer_key, priv->local_key)) == NULL) {
  487. nm = rspamd_pubkey_calculate_nm (peer_key, priv->local_key);
  488. }
  489. if (!rspamd_cryptobox_decrypt_nm_inplace (m, dec_len, nonce,
  490. nm, m - rspamd_cryptobox_mac_bytes (mode), mode)) {
  491. msg_err ("cannot verify encrypted message, first bytes of the input: %*xs",
  492. (gint)MIN(msg->body_buf.len, 64), msg->body_buf.begin);
  493. return -1;
  494. }
  495. /* Cleanup message */
  496. kh_foreach_value (msg->headers, hdr, {
  497. DL_FOREACH_SAFE (hdr, hcur, hcurtmp) {
  498. rspamd_fstring_free (hcur->combined);
  499. g_free (hcur);
  500. }
  501. });
  502. kh_destroy (rspamd_http_headers_hash, msg->headers);
  503. msg->headers = kh_init (rspamd_http_headers_hash);
  504. if (msg->url != NULL) {
  505. msg->url = rspamd_fstring_assign (msg->url, "", 0);
  506. }
  507. msg->body_buf.len = 0;
  508. memset (&decrypted_parser, 0, sizeof (decrypted_parser));
  509. http_parser_init (&decrypted_parser,
  510. conn->type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE);
  511. memset (&decrypted_cb, 0, sizeof (decrypted_cb));
  512. decrypted_cb.on_url = rspamd_http_on_url;
  513. decrypted_cb.on_status = rspamd_http_on_status;
  514. decrypted_cb.on_header_field = rspamd_http_on_header_field;
  515. decrypted_cb.on_header_value = rspamd_http_on_header_value;
  516. decrypted_cb.on_headers_complete = rspamd_http_on_headers_complete_decrypted;
  517. decrypted_cb.on_body = rspamd_http_on_body_decrypted;
  518. decrypted_parser.data = conn;
  519. decrypted_parser.content_length = dec_len;
  520. if (http_parser_execute (&decrypted_parser, &decrypted_cb, m,
  521. dec_len) != (size_t)dec_len) {
  522. msg_err ("HTTP parser error: %s when parsing encrypted request",
  523. http_errno_description (decrypted_parser.http_errno));
  524. return -1;
  525. }
  526. return 0;
  527. }
  528. static int
  529. rspamd_http_on_message_complete (http_parser * parser)
  530. {
  531. struct rspamd_http_connection *conn =
  532. (struct rspamd_http_connection *)parser->data;
  533. struct rspamd_http_connection_private *priv;
  534. int ret = 0;
  535. enum rspamd_cryptobox_mode mode;
  536. if (conn->finished) {
  537. return 0;
  538. }
  539. priv = conn->priv;
  540. if ((conn->opts & RSPAMD_HTTP_REQUIRE_ENCRYPTION) && !IS_CONN_ENCRYPTED (priv)) {
  541. priv->flags |= RSPAMD_HTTP_CONN_FLAG_ENCRYPTION_NEEDED;
  542. msg_err ("unencrypted connection when encryption has been requested");
  543. return -1;
  544. }
  545. if ((conn->opts & RSPAMD_HTTP_BODY_PARTIAL) == 0 && IS_CONN_ENCRYPTED (priv)) {
  546. mode = rspamd_keypair_alg (priv->local_key);
  547. if (priv->local_key == NULL || priv->msg->peer_key == NULL ||
  548. priv->msg->body_buf.len < rspamd_cryptobox_nonce_bytes (mode) +
  549. rspamd_cryptobox_mac_bytes (mode)) {
  550. msg_err ("cannot decrypt message");
  551. return -1;
  552. }
  553. /* We have keys, so we can decrypt message */
  554. ret = rspamd_http_decrypt_message (conn, priv, priv->msg->peer_key);
  555. if (ret != 0) {
  556. return ret;
  557. }
  558. if (conn->body_handler != NULL) {
  559. rspamd_http_connection_ref (conn);
  560. ret = conn->body_handler (conn,
  561. priv->msg,
  562. priv->msg->body_buf.begin,
  563. priv->msg->body_buf.len);
  564. rspamd_http_connection_unref (conn);
  565. }
  566. }
  567. else if ((conn->opts & RSPAMD_HTTP_BODY_PARTIAL) == 0 && conn->body_handler) {
  568. g_assert (conn->body_handler != NULL);
  569. rspamd_http_connection_ref (conn);
  570. ret = conn->body_handler (conn,
  571. priv->msg,
  572. priv->msg->body_buf.begin,
  573. priv->msg->body_buf.len);
  574. rspamd_http_connection_unref (conn);
  575. }
  576. if (ret == 0) {
  577. rspamd_ev_watcher_stop (priv->ctx->event_loop, &priv->ev);
  578. rspamd_http_connection_ref (conn);
  579. ret = conn->finish_handler (conn, priv->msg);
  580. if (conn->opts & RSPAMD_HTTP_CLIENT_KEEP_ALIVE) {
  581. rspamd_http_context_push_keepalive (conn->priv->ctx, conn,
  582. priv->msg, conn->priv->ctx->event_loop);
  583. rspamd_http_connection_reset (conn);
  584. }
  585. else {
  586. conn->finished = TRUE;
  587. }
  588. rspamd_http_connection_unref (conn);
  589. }
  590. return ret;
  591. }
  592. static void
  593. rspamd_http_simple_client_helper (struct rspamd_http_connection *conn)
  594. {
  595. struct rspamd_http_connection_private *priv;
  596. gpointer ssl;
  597. gint request_method;
  598. GString *prev_host = NULL;
  599. priv = conn->priv;
  600. ssl = priv->ssl;
  601. priv->ssl = NULL;
  602. /* Preserve data */
  603. if (priv->msg) {
  604. request_method = priv->msg->method;
  605. /* Preserve host for keepalive */
  606. prev_host = priv->msg->host;
  607. priv->msg->host = NULL;
  608. }
  609. rspamd_http_connection_reset (conn);
  610. priv->ssl = ssl;
  611. /* Plan read message */
  612. if (conn->opts & RSPAMD_HTTP_CLIENT_SHARED) {
  613. rspamd_http_connection_read_message_shared (conn, conn->ud,
  614. conn->priv->timeout);
  615. }
  616. else {
  617. rspamd_http_connection_read_message (conn, conn->ud,
  618. conn->priv->timeout);
  619. }
  620. if (priv->msg) {
  621. priv->msg->method = request_method;
  622. priv->msg->host = prev_host;
  623. }
  624. else {
  625. if (prev_host) {
  626. g_string_free (prev_host, TRUE);
  627. }
  628. }
  629. }
  630. static void
  631. rspamd_http_write_helper (struct rspamd_http_connection *conn)
  632. {
  633. struct rspamd_http_connection_private *priv;
  634. struct iovec *start;
  635. guint niov, i;
  636. gint flags = 0;
  637. gsize remain;
  638. gssize r;
  639. GError *err;
  640. struct iovec *cur_iov;
  641. struct msghdr msg;
  642. priv = conn->priv;
  643. if (priv->wr_pos == priv->wr_total) {
  644. goto call_finish_handler;
  645. }
  646. start = &priv->out[0];
  647. niov = priv->outlen;
  648. remain = priv->wr_pos;
  649. /* We know that niov is small enough for that */
  650. if (priv->ssl) {
  651. /* Might be recursive! */
  652. cur_iov = g_malloc (niov * sizeof (struct iovec));
  653. }
  654. else {
  655. cur_iov = alloca (niov * sizeof (struct iovec));
  656. }
  657. memcpy (cur_iov, priv->out, niov * sizeof (struct iovec));
  658. for (i = 0; i < priv->outlen && remain > 0; i++) {
  659. /* Find out the first iov required */
  660. start = &cur_iov[i];
  661. if (start->iov_len <= remain) {
  662. remain -= start->iov_len;
  663. start = &cur_iov[i + 1];
  664. niov--;
  665. }
  666. else {
  667. start->iov_base = (void *)((char *)start->iov_base + remain);
  668. start->iov_len -= remain;
  669. remain = 0;
  670. }
  671. }
  672. memset (&msg, 0, sizeof (msg));
  673. msg.msg_iov = start;
  674. msg.msg_iovlen = MIN (IOV_MAX, niov);
  675. g_assert (niov > 0);
  676. #ifdef MSG_NOSIGNAL
  677. flags = MSG_NOSIGNAL;
  678. #endif
  679. if (priv->ssl) {
  680. r = rspamd_ssl_writev (priv->ssl, msg.msg_iov, msg.msg_iovlen);
  681. g_free (cur_iov);
  682. }
  683. else {
  684. r = sendmsg (conn->fd, &msg, flags);
  685. }
  686. if (r == -1) {
  687. if (!priv->ssl) {
  688. err = g_error_new (HTTP_ERROR, 500, "IO write error: %s", strerror (errno));
  689. rspamd_http_connection_ref (conn);
  690. conn->error_handler (conn, err);
  691. rspamd_http_connection_unref (conn);
  692. g_error_free (err);
  693. }
  694. return;
  695. }
  696. else {
  697. priv->wr_pos += r;
  698. }
  699. if (priv->wr_pos >= priv->wr_total) {
  700. goto call_finish_handler;
  701. }
  702. else {
  703. /* Want to write more */
  704. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_RESETED;
  705. if (priv->ssl && r > 0) {
  706. /* We can write more data... */
  707. rspamd_http_write_helper (conn);
  708. return;
  709. }
  710. }
  711. return;
  712. call_finish_handler:
  713. rspamd_ev_watcher_stop (priv->ctx->event_loop, &priv->ev);
  714. if ((conn->opts & RSPAMD_HTTP_CLIENT_SIMPLE) == 0) {
  715. rspamd_http_connection_ref (conn);
  716. conn->finished = TRUE;
  717. conn->finish_handler (conn, priv->msg);
  718. rspamd_http_connection_unref (conn);
  719. }
  720. else {
  721. /* Plan read message */
  722. rspamd_http_simple_client_helper (conn);
  723. }
  724. }
  725. static gssize
  726. rspamd_http_try_read (gint fd,
  727. struct rspamd_http_connection *conn,
  728. struct rspamd_http_connection_private *priv,
  729. struct _rspamd_http_privbuf *pbuf,
  730. const gchar **buf_ptr)
  731. {
  732. gssize r;
  733. gchar *data;
  734. gsize len;
  735. struct rspamd_http_message *msg;
  736. msg = priv->msg;
  737. if (pbuf->zc_buf == NULL) {
  738. data = priv->buf->data->str;
  739. len = priv->buf->data->allocated;
  740. }
  741. else {
  742. data = (gchar *)pbuf->zc_buf;
  743. len = pbuf->zc_remain;
  744. if (len == 0) {
  745. rspamd_http_message_grow_body (priv->msg, priv->buf->data->allocated);
  746. rspamd_http_switch_zc (pbuf, msg);
  747. data = (gchar *)pbuf->zc_buf;
  748. len = pbuf->zc_remain;
  749. }
  750. }
  751. if (priv->ssl) {
  752. r = rspamd_ssl_read (priv->ssl, data, len);
  753. }
  754. else {
  755. r = read (fd, data, len);
  756. }
  757. if (r <= 0) {
  758. return r;
  759. }
  760. else {
  761. if (pbuf->zc_buf == NULL) {
  762. priv->buf->data->len = r;
  763. }
  764. else {
  765. pbuf->zc_remain -= r;
  766. pbuf->zc_buf += r;
  767. }
  768. }
  769. if (buf_ptr) {
  770. *buf_ptr = data;
  771. }
  772. return r;
  773. }
  774. static void
  775. rspamd_http_ssl_err_handler (gpointer ud, GError *err)
  776. {
  777. struct rspamd_http_connection *conn = (struct rspamd_http_connection *)ud;
  778. rspamd_http_connection_ref (conn);
  779. conn->error_handler (conn, err);
  780. rspamd_http_connection_unref (conn);
  781. }
  782. static void
  783. rspamd_http_event_handler (int fd, short what, gpointer ud)
  784. {
  785. struct rspamd_http_connection *conn = (struct rspamd_http_connection *)ud;
  786. struct rspamd_http_connection_private *priv;
  787. struct _rspamd_http_privbuf *pbuf;
  788. const gchar *d;
  789. gssize r;
  790. GError *err;
  791. priv = conn->priv;
  792. pbuf = priv->buf;
  793. REF_RETAIN (pbuf);
  794. rspamd_http_connection_ref (conn);
  795. if (what == EV_READ) {
  796. r = rspamd_http_try_read (fd, conn, priv, pbuf, &d);
  797. if (r > 0) {
  798. if (http_parser_execute (&priv->parser, &priv->parser_cb,
  799. d, r) != (size_t)r || priv->parser.http_errno != 0) {
  800. if (priv->flags & RSPAMD_HTTP_CONN_FLAG_TOO_LARGE) {
  801. err = g_error_new (HTTP_ERROR, 413,
  802. "Request entity too large: %zu",
  803. (size_t)priv->parser.content_length);
  804. }
  805. else if (priv->flags & RSPAMD_HTTP_CONN_FLAG_ENCRYPTION_NEEDED) {
  806. err = g_error_new (HTTP_ERROR, 400,
  807. "Encryption required");
  808. }
  809. else if (priv->parser.http_errno == HPE_CLOSED_CONNECTION) {
  810. msg_err ("got garbage after end of the message, ignore it");
  811. REF_RELEASE (pbuf);
  812. rspamd_http_connection_unref (conn);
  813. return;
  814. }
  815. else {
  816. if (priv->parser.http_errno > HPE_CB_status) {
  817. err = g_error_new (HTTP_ERROR, 400,
  818. "HTTP parser error: %s",
  819. http_errno_description (priv->parser.http_errno));
  820. }
  821. else {
  822. err = g_error_new (HTTP_ERROR, 500,
  823. "HTTP parser internal error: %s",
  824. http_errno_description (priv->parser.http_errno));
  825. }
  826. }
  827. if (!conn->finished) {
  828. conn->error_handler (conn, err);
  829. }
  830. else {
  831. msg_err ("got error after HTTP request is finished: %e", err);
  832. }
  833. g_error_free (err);
  834. REF_RELEASE (pbuf);
  835. rspamd_http_connection_unref (conn);
  836. return;
  837. }
  838. }
  839. else if (r == 0) {
  840. /* We can still call http parser */
  841. http_parser_execute (&priv->parser, &priv->parser_cb, d, r);
  842. if (!conn->finished) {
  843. err = g_error_new (HTTP_ERROR,
  844. 400,
  845. "IO read error: unexpected EOF");
  846. conn->error_handler (conn, err);
  847. g_error_free (err);
  848. }
  849. REF_RELEASE (pbuf);
  850. rspamd_http_connection_unref (conn);
  851. return;
  852. }
  853. else {
  854. if (!priv->ssl) {
  855. err = g_error_new (HTTP_ERROR,
  856. 500,
  857. "HTTP IO read error: %s",
  858. strerror (errno));
  859. conn->error_handler (conn, err);
  860. g_error_free (err);
  861. }
  862. REF_RELEASE (pbuf);
  863. rspamd_http_connection_unref (conn);
  864. return;
  865. }
  866. }
  867. else if (what == EV_TIMEOUT) {
  868. /* Let's try to read from the socket first */
  869. r = rspamd_http_try_read (fd, conn, priv, pbuf, &d);
  870. if (r > 0) {
  871. if (http_parser_execute (&priv->parser, &priv->parser_cb,
  872. d, r) != (size_t)r || priv->parser.http_errno != 0) {
  873. err = g_error_new (HTTP_ERROR, 400,
  874. "HTTP parser error: %s",
  875. http_errno_description (priv->parser.http_errno));
  876. if (!conn->finished) {
  877. conn->error_handler (conn, err);
  878. }
  879. else {
  880. msg_err ("got error after HTTP request is finished: %e", err);
  881. }
  882. g_error_free (err);
  883. REF_RELEASE (pbuf);
  884. rspamd_http_connection_unref (conn);
  885. return;
  886. }
  887. }
  888. else if (r == 0) {
  889. if (!conn->finished) {
  890. err = g_error_new (HTTP_ERROR, 408,
  891. "IO timeout");
  892. conn->error_handler (conn, err);
  893. g_error_free (err);
  894. }
  895. REF_RELEASE (pbuf);
  896. rspamd_http_connection_unref (conn);
  897. return;
  898. }
  899. else {
  900. err = g_error_new (HTTP_ERROR, 408,
  901. "IO timeout");
  902. conn->error_handler (conn, err);
  903. g_error_free (err);
  904. REF_RELEASE (pbuf);
  905. rspamd_http_connection_unref (conn);
  906. return;
  907. }
  908. }
  909. else if (what == EV_WRITE) {
  910. rspamd_http_write_helper (conn);
  911. }
  912. REF_RELEASE (pbuf);
  913. rspamd_http_connection_unref (conn);
  914. }
  915. static void
  916. rspamd_http_parser_reset (struct rspamd_http_connection *conn)
  917. {
  918. struct rspamd_http_connection_private *priv = conn->priv;
  919. http_parser_init (&priv->parser,
  920. conn->type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE);
  921. priv->parser_cb.on_url = rspamd_http_on_url;
  922. priv->parser_cb.on_status = rspamd_http_on_status;
  923. priv->parser_cb.on_header_field = rspamd_http_on_header_field;
  924. priv->parser_cb.on_header_value = rspamd_http_on_header_value;
  925. priv->parser_cb.on_headers_complete = rspamd_http_on_headers_complete;
  926. priv->parser_cb.on_body = rspamd_http_on_body;
  927. priv->parser_cb.on_message_complete = rspamd_http_on_message_complete;
  928. }
  929. static struct rspamd_http_connection *
  930. rspamd_http_connection_new_common (struct rspamd_http_context *ctx,
  931. gint fd,
  932. rspamd_http_body_handler_t body_handler,
  933. rspamd_http_error_handler_t error_handler,
  934. rspamd_http_finish_handler_t finish_handler,
  935. unsigned opts,
  936. enum rspamd_http_connection_type type,
  937. enum rspamd_http_priv_flags priv_flags,
  938. struct upstream *proxy_upstream)
  939. {
  940. struct rspamd_http_connection *conn;
  941. struct rspamd_http_connection_private *priv;
  942. g_assert (error_handler != NULL && finish_handler != NULL);
  943. if (ctx == NULL) {
  944. ctx = rspamd_http_context_default ();
  945. }
  946. conn = g_malloc0 (sizeof (struct rspamd_http_connection));
  947. conn->opts = opts;
  948. conn->type = type;
  949. conn->body_handler = body_handler;
  950. conn->error_handler = error_handler;
  951. conn->finish_handler = finish_handler;
  952. conn->fd = fd;
  953. conn->ref = 1;
  954. conn->finished = FALSE;
  955. /* Init priv */
  956. priv = g_malloc0 (sizeof (struct rspamd_http_connection_private));
  957. conn->priv = priv;
  958. priv->ctx = ctx;
  959. priv->flags = priv_flags;
  960. if (type == RSPAMD_HTTP_SERVER) {
  961. priv->cache = ctx->server_kp_cache;
  962. }
  963. else {
  964. priv->cache = ctx->client_kp_cache;
  965. if (ctx->client_kp) {
  966. priv->local_key = rspamd_keypair_ref (ctx->client_kp);
  967. }
  968. }
  969. rspamd_http_parser_reset (conn);
  970. priv->parser.data = conn;
  971. return conn;
  972. }
  973. struct rspamd_http_connection *
  974. rspamd_http_connection_new_server (struct rspamd_http_context *ctx,
  975. gint fd,
  976. rspamd_http_body_handler_t body_handler,
  977. rspamd_http_error_handler_t error_handler,
  978. rspamd_http_finish_handler_t finish_handler,
  979. unsigned opts)
  980. {
  981. return rspamd_http_connection_new_common (ctx, fd, body_handler,
  982. error_handler, finish_handler, opts, RSPAMD_HTTP_SERVER, 0, NULL);
  983. }
  984. struct rspamd_http_connection *
  985. rspamd_http_connection_new_client_socket (struct rspamd_http_context *ctx,
  986. rspamd_http_body_handler_t body_handler,
  987. rspamd_http_error_handler_t error_handler,
  988. rspamd_http_finish_handler_t finish_handler,
  989. unsigned opts,
  990. gint fd)
  991. {
  992. return rspamd_http_connection_new_common (ctx, fd, body_handler,
  993. error_handler, finish_handler, opts, RSPAMD_HTTP_CLIENT, 0, NULL);
  994. }
  995. struct rspamd_http_connection *
  996. rspamd_http_connection_new_client (struct rspamd_http_context *ctx,
  997. rspamd_http_body_handler_t body_handler,
  998. rspamd_http_error_handler_t error_handler,
  999. rspamd_http_finish_handler_t finish_handler,
  1000. unsigned opts,
  1001. rspamd_inet_addr_t *addr)
  1002. {
  1003. gint fd;
  1004. if (ctx == NULL) {
  1005. ctx = rspamd_http_context_default ();
  1006. }
  1007. if (ctx->http_proxies) {
  1008. struct upstream *up = rspamd_upstream_get (ctx->http_proxies,
  1009. RSPAMD_UPSTREAM_ROUND_ROBIN, NULL, 0);
  1010. if (up) {
  1011. rspamd_inet_addr_t *proxy_addr = rspamd_upstream_addr_next (up);
  1012. fd = rspamd_inet_address_connect (proxy_addr, SOCK_STREAM, TRUE);
  1013. if (fd == -1) {
  1014. msg_info ("cannot connect to http proxy %s: %s",
  1015. rspamd_inet_address_to_string_pretty (proxy_addr),
  1016. strerror (errno));
  1017. rspamd_upstream_fail (up, TRUE, strerror (errno));
  1018. return NULL;
  1019. }
  1020. return rspamd_http_connection_new_common (ctx, fd, body_handler,
  1021. error_handler, finish_handler, opts,
  1022. RSPAMD_HTTP_CLIENT,
  1023. RSPAMD_HTTP_CONN_OWN_SOCKET|RSPAMD_HTTP_CONN_FLAG_PROXY,
  1024. up);
  1025. }
  1026. }
  1027. /* Unproxied version */
  1028. fd = rspamd_inet_address_connect (addr, SOCK_STREAM, TRUE);
  1029. if (fd == -1) {
  1030. msg_info ("cannot connect make http connection to %s: %s",
  1031. rspamd_inet_address_to_string_pretty (addr),
  1032. strerror (errno));
  1033. return NULL;
  1034. }
  1035. return rspamd_http_connection_new_common (ctx, fd, body_handler,
  1036. error_handler, finish_handler, opts,
  1037. RSPAMD_HTTP_CLIENT,
  1038. RSPAMD_HTTP_CONN_OWN_SOCKET,
  1039. NULL);
  1040. }
  1041. struct rspamd_http_connection *
  1042. rspamd_http_connection_new_keepalive (struct rspamd_http_context *ctx,
  1043. rspamd_http_body_handler_t body_handler,
  1044. rspamd_http_error_handler_t error_handler,
  1045. rspamd_http_finish_handler_t finish_handler,
  1046. rspamd_inet_addr_t *addr,
  1047. const gchar *host)
  1048. {
  1049. struct rspamd_http_connection *conn;
  1050. if (ctx == NULL) {
  1051. ctx = rspamd_http_context_default ();
  1052. }
  1053. conn = rspamd_http_context_check_keepalive (ctx, addr, host);
  1054. if (conn) {
  1055. return conn;
  1056. }
  1057. conn = rspamd_http_connection_new_client (ctx,
  1058. body_handler, error_handler, finish_handler,
  1059. RSPAMD_HTTP_CLIENT_SIMPLE|RSPAMD_HTTP_CLIENT_KEEP_ALIVE,
  1060. addr);
  1061. if (conn) {
  1062. rspamd_http_context_prepare_keepalive (ctx, conn, addr, host);
  1063. }
  1064. return conn;
  1065. }
  1066. void
  1067. rspamd_http_connection_reset (struct rspamd_http_connection *conn)
  1068. {
  1069. struct rspamd_http_connection_private *priv;
  1070. struct rspamd_http_message *msg;
  1071. priv = conn->priv;
  1072. msg = priv->msg;
  1073. /* Clear request */
  1074. if (msg != NULL) {
  1075. if (msg->peer_key) {
  1076. priv->peer_key = msg->peer_key;
  1077. msg->peer_key = NULL;
  1078. }
  1079. rspamd_http_message_unref (msg);
  1080. priv->msg = NULL;
  1081. }
  1082. conn->finished = FALSE;
  1083. /* Clear priv */
  1084. rspamd_ev_watcher_stop (priv->ctx->event_loop, &priv->ev);
  1085. if (!(priv->flags & RSPAMD_HTTP_CONN_FLAG_RESETED)) {
  1086. rspamd_http_parser_reset (conn);
  1087. }
  1088. if (priv->buf != NULL) {
  1089. REF_RELEASE (priv->buf);
  1090. priv->buf = NULL;
  1091. }
  1092. if (priv->out != NULL) {
  1093. g_free (priv->out);
  1094. priv->out = NULL;
  1095. }
  1096. priv->flags |= RSPAMD_HTTP_CONN_FLAG_RESETED;
  1097. }
  1098. struct rspamd_http_message *
  1099. rspamd_http_connection_steal_msg (struct rspamd_http_connection *conn)
  1100. {
  1101. struct rspamd_http_connection_private *priv;
  1102. struct rspamd_http_message *msg;
  1103. priv = conn->priv;
  1104. msg = priv->msg;
  1105. /* Clear request */
  1106. if (msg != NULL) {
  1107. if (msg->peer_key) {
  1108. priv->peer_key = msg->peer_key;
  1109. msg->peer_key = NULL;
  1110. }
  1111. priv->msg = NULL;
  1112. }
  1113. return msg;
  1114. }
  1115. struct rspamd_http_message *
  1116. rspamd_http_connection_copy_msg (struct rspamd_http_message *msg, GError **err)
  1117. {
  1118. struct rspamd_http_message *new_msg;
  1119. struct rspamd_http_header *hdr, *nhdr, *nhdrs, *hcur;
  1120. const gchar *old_body;
  1121. gsize old_len;
  1122. struct stat st;
  1123. union _rspamd_storage_u *storage;
  1124. new_msg = rspamd_http_new_message (msg->type);
  1125. new_msg->flags = msg->flags;
  1126. if (msg->body_buf.len > 0) {
  1127. if (msg->flags & RSPAMD_HTTP_FLAG_SHMEM) {
  1128. /* Avoid copying by just maping a shared segment */
  1129. new_msg->flags |= RSPAMD_HTTP_FLAG_SHMEM_IMMUTABLE;
  1130. storage = &new_msg->body_buf.c;
  1131. storage->shared.shm_fd = dup (msg->body_buf.c.shared.shm_fd);
  1132. if (storage->shared.shm_fd == -1) {
  1133. rspamd_http_message_unref (new_msg);
  1134. g_set_error (err, http_error_quark (), errno,
  1135. "cannot dup shmem fd: %d: %s",
  1136. msg->body_buf.c.shared.shm_fd, strerror (errno));
  1137. return NULL;
  1138. }
  1139. if (fstat (storage->shared.shm_fd, &st) == -1) {
  1140. g_set_error (err, http_error_quark (), errno,
  1141. "cannot stat shmem fd: %d: %s",
  1142. storage->shared.shm_fd, strerror (errno));
  1143. rspamd_http_message_unref (new_msg);
  1144. return NULL;
  1145. }
  1146. /* We don't own segment, so do not try to touch it */
  1147. if (msg->body_buf.c.shared.name) {
  1148. storage->shared.name = msg->body_buf.c.shared.name;
  1149. REF_RETAIN (storage->shared.name);
  1150. }
  1151. new_msg->body_buf.str = mmap (NULL, st.st_size,
  1152. PROT_READ, MAP_SHARED,
  1153. storage->shared.shm_fd, 0);
  1154. if (new_msg->body_buf.str == MAP_FAILED) {
  1155. g_set_error (err, http_error_quark (), errno,
  1156. "cannot mmap shmem fd: %d: %s",
  1157. storage->shared.shm_fd, strerror (errno));
  1158. rspamd_http_message_unref (new_msg);
  1159. return NULL;
  1160. }
  1161. new_msg->body_buf.begin = new_msg->body_buf.str;
  1162. new_msg->body_buf.len = msg->body_buf.len;
  1163. new_msg->body_buf.begin = new_msg->body_buf.str +
  1164. (msg->body_buf.begin - msg->body_buf.str);
  1165. }
  1166. else {
  1167. old_body = rspamd_http_message_get_body (msg, &old_len);
  1168. if (!rspamd_http_message_set_body (new_msg, old_body, old_len)) {
  1169. g_set_error (err, http_error_quark (), errno,
  1170. "cannot set body for message, length: %zd",
  1171. old_len);
  1172. rspamd_http_message_unref (new_msg);
  1173. return NULL;
  1174. }
  1175. }
  1176. }
  1177. if (msg->url) {
  1178. if (new_msg->url) {
  1179. new_msg->url = rspamd_fstring_append (new_msg->url, msg->url->str,
  1180. msg->url->len);
  1181. }
  1182. else {
  1183. new_msg->url = rspamd_fstring_new_init (msg->url->str,
  1184. msg->url->len);
  1185. }
  1186. }
  1187. if (msg->host) {
  1188. new_msg->host = g_string_new_len (msg->host->str, msg->host->len);
  1189. }
  1190. new_msg->method = msg->method;
  1191. new_msg->port = msg->port;
  1192. new_msg->date = msg->date;
  1193. new_msg->last_modified = msg->last_modified;
  1194. kh_foreach_value (msg->headers, hdr, {
  1195. nhdrs = NULL;
  1196. DL_FOREACH (hdr, hcur) {
  1197. nhdr = g_malloc (sizeof (struct rspamd_http_header));
  1198. nhdr->combined = rspamd_fstring_new_init (hcur->combined->str,
  1199. hcur->combined->len);
  1200. nhdr->name.begin = nhdr->combined->str +
  1201. (hcur->name.begin - hcur->combined->str);
  1202. nhdr->name.len = hcur->name.len;
  1203. nhdr->value.begin = nhdr->combined->str +
  1204. (hcur->value.begin - hcur->combined->str);
  1205. nhdr->value.len = hcur->value.len;
  1206. DL_APPEND (nhdrs, nhdr);
  1207. }
  1208. gint r;
  1209. khiter_t k = kh_put (rspamd_http_headers_hash, new_msg->headers,
  1210. &nhdrs->name,&r);
  1211. if (r != 0) {
  1212. kh_value (new_msg->headers, k) = nhdrs;
  1213. }
  1214. else {
  1215. DL_CONCAT (kh_value (new_msg->headers, k), nhdrs);
  1216. }
  1217. });
  1218. return new_msg;
  1219. }
  1220. void
  1221. rspamd_http_connection_free (struct rspamd_http_connection *conn)
  1222. {
  1223. struct rspamd_http_connection_private *priv;
  1224. priv = conn->priv;
  1225. if (priv != NULL) {
  1226. rspamd_http_connection_reset (conn);
  1227. if (priv->ssl) {
  1228. rspamd_ssl_connection_free (priv->ssl);
  1229. priv->ssl = NULL;
  1230. }
  1231. if (priv->local_key) {
  1232. rspamd_keypair_unref (priv->local_key);
  1233. }
  1234. if (priv->peer_key) {
  1235. rspamd_pubkey_unref (priv->peer_key);
  1236. }
  1237. if (priv->flags & RSPAMD_HTTP_CONN_OWN_SOCKET) {
  1238. /* Fd is owned by a connection */
  1239. close (conn->fd);
  1240. }
  1241. g_free (priv);
  1242. }
  1243. g_free (conn);
  1244. }
  1245. static void
  1246. rspamd_http_connection_read_message_common (struct rspamd_http_connection *conn,
  1247. gpointer ud, ev_tstamp timeout,
  1248. gint flags)
  1249. {
  1250. struct rspamd_http_connection_private *priv = conn->priv;
  1251. struct rspamd_http_message *req;
  1252. conn->ud = ud;
  1253. req = rspamd_http_new_message (
  1254. conn->type == RSPAMD_HTTP_SERVER ? HTTP_REQUEST : HTTP_RESPONSE);
  1255. priv->msg = req;
  1256. req->flags = flags;
  1257. if (flags & RSPAMD_HTTP_FLAG_SHMEM) {
  1258. req->body_buf.c.shared.shm_fd = -1;
  1259. }
  1260. if (priv->peer_key) {
  1261. priv->msg->peer_key = priv->peer_key;
  1262. priv->peer_key = NULL;
  1263. priv->flags |= RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
  1264. }
  1265. priv->timeout = timeout;
  1266. priv->header = NULL;
  1267. priv->buf = g_malloc0 (sizeof (*priv->buf));
  1268. REF_INIT_RETAIN (priv->buf, rspamd_http_privbuf_dtor);
  1269. priv->buf->data = rspamd_fstring_sized_new (8192);
  1270. priv->flags |= RSPAMD_HTTP_CONN_FLAG_NEW_HEADER;
  1271. rspamd_ev_watcher_init (&priv->ev, conn->fd, EV_READ,
  1272. rspamd_http_event_handler, conn);
  1273. rspamd_ev_watcher_start (priv->ctx->event_loop, &priv->ev, priv->timeout);
  1274. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_RESETED;
  1275. }
  1276. void
  1277. rspamd_http_connection_read_message (struct rspamd_http_connection *conn,
  1278. gpointer ud, ev_tstamp timeout)
  1279. {
  1280. rspamd_http_connection_read_message_common (conn, ud, timeout, 0);
  1281. }
  1282. void
  1283. rspamd_http_connection_read_message_shared (struct rspamd_http_connection *conn,
  1284. gpointer ud, ev_tstamp timeout)
  1285. {
  1286. rspamd_http_connection_read_message_common (conn, ud, timeout,
  1287. RSPAMD_HTTP_FLAG_SHMEM);
  1288. }
  1289. static void
  1290. rspamd_http_connection_encrypt_message (
  1291. struct rspamd_http_connection *conn,
  1292. struct rspamd_http_message *msg,
  1293. struct rspamd_http_connection_private *priv,
  1294. guchar *pbody,
  1295. guint bodylen,
  1296. guchar *pmethod,
  1297. guint methodlen,
  1298. guint preludelen,
  1299. gint hdrcount,
  1300. guchar *np,
  1301. guchar *mp,
  1302. struct rspamd_cryptobox_pubkey *peer_key)
  1303. {
  1304. struct rspamd_cryptobox_segment *segments;
  1305. guchar *crlfp;
  1306. const guchar *nm;
  1307. gint i, cnt;
  1308. guint outlen;
  1309. struct rspamd_http_header *hdr, *hcur;
  1310. enum rspamd_cryptobox_mode mode;
  1311. mode = rspamd_keypair_alg (priv->local_key);
  1312. crlfp = mp + rspamd_cryptobox_mac_bytes (mode);
  1313. outlen = priv->out[0].iov_len + priv->out[1].iov_len;
  1314. /*
  1315. * Create segments from the following:
  1316. * Method, [URL], CRLF, nheaders, CRLF, body
  1317. */
  1318. segments = g_new (struct rspamd_cryptobox_segment, hdrcount + 5);
  1319. segments[0].data = pmethod;
  1320. segments[0].len = methodlen;
  1321. if (conn->type != RSPAMD_HTTP_SERVER) {
  1322. segments[1].data = msg->url->str;
  1323. segments[1].len = msg->url->len;
  1324. /* space + HTTP version + crlf */
  1325. segments[2].data = crlfp;
  1326. segments[2].len = preludelen - 2;
  1327. crlfp += segments[2].len;
  1328. i = 3;
  1329. }
  1330. else {
  1331. /* Here we send just CRLF */
  1332. segments[1].data = crlfp;
  1333. segments[1].len = 2;
  1334. crlfp += segments[1].len;
  1335. i = 2;
  1336. }
  1337. kh_foreach_value (msg->headers, hdr, {
  1338. DL_FOREACH (hdr, hcur) {
  1339. segments[i].data = hcur->combined->str;
  1340. segments[i++].len = hcur->combined->len;
  1341. }
  1342. });
  1343. /* crlfp should point now at the second crlf */
  1344. segments[i].data = crlfp;
  1345. segments[i++].len = 2;
  1346. if (pbody) {
  1347. segments[i].data = pbody;
  1348. segments[i++].len = bodylen;
  1349. }
  1350. cnt = i;
  1351. if ((nm = rspamd_pubkey_get_nm (peer_key, priv->local_key)) == NULL) {
  1352. nm = rspamd_pubkey_calculate_nm (peer_key, priv->local_key);
  1353. }
  1354. rspamd_cryptobox_encryptv_nm_inplace (segments, cnt, np, nm, mp, mode);
  1355. /*
  1356. * iov[0] = base HTTP request
  1357. * iov[1] = CRLF
  1358. * iov[2] = nonce
  1359. * iov[3] = mac
  1360. * iov[4..i] = encrypted HTTP request/reply
  1361. */
  1362. priv->out[2].iov_base = np;
  1363. priv->out[2].iov_len = rspamd_cryptobox_nonce_bytes (mode);
  1364. priv->out[3].iov_base = mp;
  1365. priv->out[3].iov_len = rspamd_cryptobox_mac_bytes (mode);
  1366. outlen += rspamd_cryptobox_nonce_bytes (mode) +
  1367. rspamd_cryptobox_mac_bytes (mode);
  1368. for (i = 0; i < cnt; i ++) {
  1369. priv->out[i + 4].iov_base = segments[i].data;
  1370. priv->out[i + 4].iov_len = segments[i].len;
  1371. outlen += segments[i].len;
  1372. }
  1373. priv->wr_total = outlen;
  1374. g_free (segments);
  1375. }
  1376. static void
  1377. rspamd_http_detach_shared (struct rspamd_http_message *msg)
  1378. {
  1379. rspamd_fstring_t *cpy_str;
  1380. cpy_str = rspamd_fstring_new_init (msg->body_buf.begin, msg->body_buf.len);
  1381. rspamd_http_message_set_body_from_fstring_steal (msg, cpy_str);
  1382. }
  1383. gint
  1384. rspamd_http_message_write_header (const gchar* mime_type, gboolean encrypted,
  1385. gchar *repbuf, gsize replen, gsize bodylen, gsize enclen, const gchar* host,
  1386. struct rspamd_http_connection* conn, struct rspamd_http_message* msg,
  1387. rspamd_fstring_t** buf,
  1388. struct rspamd_http_connection_private* priv,
  1389. struct rspamd_cryptobox_pubkey* peer_key)
  1390. {
  1391. gchar datebuf[64];
  1392. gint meth_len = 0;
  1393. const gchar *conn_type = "close";
  1394. if (conn->type == RSPAMD_HTTP_SERVER) {
  1395. /* Format reply */
  1396. if (msg->method < HTTP_SYMBOLS) {
  1397. rspamd_ftok_t status;
  1398. rspamd_http_date_format (datebuf, sizeof (datebuf), msg->date);
  1399. if (mime_type == NULL) {
  1400. mime_type =
  1401. encrypted ? "application/octet-stream" : "text/plain";
  1402. }
  1403. if (msg->status == NULL || msg->status->len == 0) {
  1404. if (msg->code == 200) {
  1405. RSPAMD_FTOK_ASSIGN (&status, "OK");
  1406. }
  1407. else if (msg->code == 404) {
  1408. RSPAMD_FTOK_ASSIGN (&status, "Not Found");
  1409. }
  1410. else if (msg->code == 403) {
  1411. RSPAMD_FTOK_ASSIGN (&status, "Forbidden");
  1412. }
  1413. else if (msg->code >= 500 && msg->code < 600) {
  1414. RSPAMD_FTOK_ASSIGN (&status, "Internal Server Error");
  1415. }
  1416. else {
  1417. RSPAMD_FTOK_ASSIGN (&status, "Undefined Error");
  1418. }
  1419. }
  1420. else {
  1421. status.begin = msg->status->str;
  1422. status.len = msg->status->len;
  1423. }
  1424. if (encrypted) {
  1425. /* Internal reply (encrypted) */
  1426. if (mime_type) {
  1427. meth_len =
  1428. rspamd_snprintf (repbuf, replen,
  1429. "HTTP/1.1 %d %T\r\n"
  1430. "Connection: close\r\n"
  1431. "Server: %s\r\n"
  1432. "Date: %s\r\n"
  1433. "Content-Length: %z\r\n"
  1434. "Content-Type: %s", /* NO \r\n at the end ! */
  1435. msg->code, &status, priv->ctx->config.server_hdr,
  1436. datebuf,
  1437. bodylen, mime_type);
  1438. }
  1439. else {
  1440. meth_len =
  1441. rspamd_snprintf (repbuf, replen,
  1442. "HTTP/1.1 %d %T\r\n"
  1443. "Connection: close\r\n"
  1444. "Server: %s\r\n"
  1445. "Date: %s\r\n"
  1446. "Content-Length: %z", /* NO \r\n at the end ! */
  1447. msg->code, &status, priv->ctx->config.server_hdr,
  1448. datebuf,
  1449. bodylen);
  1450. }
  1451. enclen += meth_len;
  1452. /* External reply */
  1453. rspamd_printf_fstring (buf,
  1454. "HTTP/1.1 200 OK\r\n"
  1455. "Connection: close\r\n"
  1456. "Server: %s\r\n"
  1457. "Date: %s\r\n"
  1458. "Content-Length: %z\r\n"
  1459. "Content-Type: application/octet-stream\r\n",
  1460. priv->ctx->config.server_hdr,
  1461. datebuf, enclen);
  1462. }
  1463. else {
  1464. if (mime_type) {
  1465. meth_len =
  1466. rspamd_printf_fstring (buf,
  1467. "HTTP/1.1 %d %T\r\n"
  1468. "Connection: close\r\n"
  1469. "Server: %s\r\n"
  1470. "Date: %s\r\n"
  1471. "Content-Length: %z\r\n"
  1472. "Content-Type: %s\r\n",
  1473. msg->code, &status, priv->ctx->config.server_hdr,
  1474. datebuf,
  1475. bodylen, mime_type);
  1476. }
  1477. else {
  1478. meth_len =
  1479. rspamd_printf_fstring (buf,
  1480. "HTTP/1.1 %d %T\r\n"
  1481. "Connection: close\r\n"
  1482. "Server: %s\r\n"
  1483. "Date: %s\r\n"
  1484. "Content-Length: %z\r\n",
  1485. msg->code, &status, priv->ctx->config.server_hdr,
  1486. datebuf,
  1487. bodylen);
  1488. }
  1489. }
  1490. }
  1491. else {
  1492. /* Legacy spamd reply */
  1493. if (msg->flags & RSPAMD_HTTP_FLAG_SPAMC) {
  1494. gsize real_bodylen;
  1495. goffset eoh_pos;
  1496. GString tmp;
  1497. /* Unfortunately, spamc protocol is deadly brain damaged */
  1498. tmp.str = (gchar *)msg->body_buf.begin;
  1499. tmp.len = msg->body_buf.len;
  1500. if (rspamd_string_find_eoh (&tmp, &eoh_pos) != -1 &&
  1501. bodylen > eoh_pos) {
  1502. real_bodylen = bodylen - eoh_pos;
  1503. }
  1504. else {
  1505. real_bodylen = bodylen;
  1506. }
  1507. rspamd_printf_fstring (buf, "SPAMD/1.1 0 EX_OK\r\n"
  1508. "Content-length: %z\r\n",
  1509. real_bodylen);
  1510. }
  1511. else {
  1512. rspamd_printf_fstring (buf, "RSPAMD/1.3 0 EX_OK\r\n");
  1513. }
  1514. }
  1515. }
  1516. else {
  1517. /* Client request */
  1518. if (conn->opts & RSPAMD_HTTP_CLIENT_KEEP_ALIVE) {
  1519. conn_type = "keep-alive";
  1520. }
  1521. /* Format request */
  1522. enclen += RSPAMD_FSTRING_LEN (msg->url) +
  1523. strlen (http_method_str (msg->method)) + 1;
  1524. if (host == NULL && msg->host == NULL) {
  1525. /* Fallback to HTTP/1.0 */
  1526. if (encrypted) {
  1527. rspamd_printf_fstring (buf,
  1528. "%s %s HTTP/1.0\r\n"
  1529. "Content-Length: %z\r\n"
  1530. "Content-Type: application/octet-stream\r\n"
  1531. "Connection: %s\r\n",
  1532. "POST",
  1533. "/post",
  1534. enclen,
  1535. conn_type);
  1536. }
  1537. else {
  1538. rspamd_printf_fstring (buf,
  1539. "%s %V HTTP/1.0\r\n"
  1540. "Content-Length: %z\r\n"
  1541. "Connection: %s\r\n",
  1542. http_method_str (msg->method),
  1543. msg->url,
  1544. bodylen,
  1545. conn_type);
  1546. if (bodylen > 0) {
  1547. if (mime_type == NULL) {
  1548. mime_type = "text/plain";
  1549. }
  1550. rspamd_printf_fstring (buf,
  1551. "Content-Type: %s\r\n",
  1552. mime_type);
  1553. }
  1554. }
  1555. }
  1556. else {
  1557. /* Normal HTTP/1.1 with Host */
  1558. if (host == NULL) {
  1559. host = msg->host->str;
  1560. }
  1561. if (encrypted) {
  1562. /* TODO: Add proxy support to HTTPCrypt */
  1563. rspamd_printf_fstring (buf,
  1564. "%s %s HTTP/1.1\r\n"
  1565. "Connection: %s\r\n"
  1566. "Host: %s\r\n"
  1567. "Content-Length: %z\r\n"
  1568. "Content-Type: application/octet-stream\r\n",
  1569. "POST",
  1570. "/post",
  1571. conn_type,
  1572. host,
  1573. enclen);
  1574. }
  1575. else {
  1576. if (conn->priv->flags & RSPAMD_HTTP_CONN_FLAG_PROXY) {
  1577. rspamd_printf_fstring (buf,
  1578. "%s %s://%s:%d/%V HTTP/1.1\r\n"
  1579. "Connection: %s\r\n"
  1580. "Host: %s\r\n"
  1581. "Content-Length: %z\r\n",
  1582. http_method_str (msg->method),
  1583. (msg->flags & RSPAMD_HTTP_FLAG_SSL) ? "https" : "http",
  1584. host,
  1585. msg->port,
  1586. msg->url,
  1587. conn_type,
  1588. host,
  1589. bodylen);
  1590. }
  1591. else {
  1592. rspamd_printf_fstring (buf,
  1593. "%s %V HTTP/1.1\r\n"
  1594. "Connection: %s\r\n"
  1595. "Host: %s\r\n"
  1596. "Content-Length: %z\r\n",
  1597. http_method_str (msg->method),
  1598. msg->url,
  1599. conn_type,
  1600. host,
  1601. bodylen);
  1602. }
  1603. if (bodylen > 0) {
  1604. if (mime_type != NULL) {
  1605. rspamd_printf_fstring (buf,
  1606. "Content-Type: %s\r\n",
  1607. mime_type);
  1608. }
  1609. }
  1610. }
  1611. }
  1612. if (encrypted) {
  1613. GString *b32_key, *b32_id;
  1614. b32_key = rspamd_keypair_print (priv->local_key,
  1615. RSPAMD_KEYPAIR_PUBKEY | RSPAMD_KEYPAIR_BASE32);
  1616. b32_id = rspamd_pubkey_print (peer_key,
  1617. RSPAMD_KEYPAIR_ID_SHORT | RSPAMD_KEYPAIR_BASE32);
  1618. /* XXX: add some fuzz here */
  1619. rspamd_printf_fstring (&*buf, "Key: %v=%v\r\n", b32_id, b32_key);
  1620. g_string_free (b32_key, TRUE);
  1621. g_string_free (b32_id, TRUE);
  1622. }
  1623. }
  1624. return meth_len;
  1625. }
  1626. static gboolean
  1627. rspamd_http_connection_write_message_common (struct rspamd_http_connection *conn,
  1628. struct rspamd_http_message *msg,
  1629. const gchar *host,
  1630. const gchar *mime_type,
  1631. gpointer ud,
  1632. ev_tstamp timeout,
  1633. gboolean allow_shared)
  1634. {
  1635. struct rspamd_http_connection_private *priv = conn->priv;
  1636. struct rspamd_http_header *hdr, *hcur;
  1637. gchar repbuf[512], *pbody;
  1638. gint i, hdrcount, meth_len = 0, preludelen = 0;
  1639. gsize bodylen, enclen = 0;
  1640. rspamd_fstring_t *buf;
  1641. gboolean encrypted = FALSE;
  1642. guchar nonce[rspamd_cryptobox_MAX_NONCEBYTES], mac[rspamd_cryptobox_MAX_MACBYTES];
  1643. guchar *np = NULL, *mp = NULL, *meth_pos = NULL;
  1644. struct rspamd_cryptobox_pubkey *peer_key = NULL;
  1645. enum rspamd_cryptobox_mode mode;
  1646. GError *err;
  1647. conn->ud = ud;
  1648. priv->msg = msg;
  1649. priv->timeout = timeout;
  1650. priv->header = NULL;
  1651. priv->buf = g_malloc0 (sizeof (*priv->buf));
  1652. REF_INIT_RETAIN (priv->buf, rspamd_http_privbuf_dtor);
  1653. priv->buf->data = rspamd_fstring_sized_new (512);
  1654. buf = priv->buf->data;
  1655. if (priv->peer_key && priv->local_key) {
  1656. priv->msg->peer_key = priv->peer_key;
  1657. priv->peer_key = NULL;
  1658. priv->flags |= RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
  1659. }
  1660. if (msg->peer_key != NULL) {
  1661. if (priv->local_key == NULL) {
  1662. /* Automatically generate a temporary keypair */
  1663. priv->local_key = rspamd_keypair_new (RSPAMD_KEYPAIR_KEX,
  1664. RSPAMD_CRYPTOBOX_MODE_25519);
  1665. }
  1666. encrypted = TRUE;
  1667. if (priv->cache) {
  1668. rspamd_keypair_cache_process (priv->cache,
  1669. priv->local_key, priv->msg->peer_key);
  1670. }
  1671. }
  1672. if (encrypted && (msg->flags &
  1673. (RSPAMD_HTTP_FLAG_SHMEM_IMMUTABLE|RSPAMD_HTTP_FLAG_SHMEM))) {
  1674. /* We cannot use immutable body to encrypt message in place */
  1675. allow_shared = FALSE;
  1676. rspamd_http_detach_shared (msg);
  1677. }
  1678. if (allow_shared) {
  1679. gchar tmpbuf[64];
  1680. if (!(msg->flags & RSPAMD_HTTP_FLAG_SHMEM) ||
  1681. msg->body_buf.c.shared.name == NULL) {
  1682. allow_shared = FALSE;
  1683. }
  1684. else {
  1685. /* Insert new headers */
  1686. rspamd_http_message_add_header (msg, "Shm",
  1687. msg->body_buf.c.shared.name->shm_name);
  1688. rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "%d",
  1689. (int)(msg->body_buf.begin - msg->body_buf.str));
  1690. rspamd_http_message_add_header (msg, "Shm-Offset",
  1691. tmpbuf);
  1692. rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "%z",
  1693. msg->body_buf.len);
  1694. rspamd_http_message_add_header (msg, "Shm-Length",
  1695. tmpbuf);
  1696. }
  1697. }
  1698. if (priv->ctx->config.user_agent && conn->type == RSPAMD_HTTP_CLIENT) {
  1699. rspamd_ftok_t srch;
  1700. khiter_t k;
  1701. gint r;
  1702. RSPAMD_FTOK_ASSIGN (&srch, "User-Agent");
  1703. k = kh_put (rspamd_http_headers_hash, msg->headers, &srch,&r);
  1704. if (r != 0) {
  1705. hdr = g_malloc0 (sizeof (struct rspamd_http_header));
  1706. guint vlen = strlen (priv->ctx->config.user_agent);
  1707. hdr->combined = rspamd_fstring_sized_new (srch.len + vlen + 4);
  1708. rspamd_printf_fstring (&hdr->combined, "%T: %*s\r\n", &srch, vlen,
  1709. priv->ctx->config.user_agent);
  1710. hdr->name.begin = hdr->combined->str;
  1711. hdr->name.len = srch.len;
  1712. hdr->value.begin = hdr->combined->str + srch.len + 2;
  1713. hdr->value.len = vlen;
  1714. hdr->prev = hdr; /* for utlists */
  1715. kh_value (msg->headers, k) = hdr;
  1716. /* as we searched using static buffer */
  1717. kh_key (msg->headers, k) = &hdr->name;
  1718. }
  1719. }
  1720. if (encrypted) {
  1721. mode = rspamd_keypair_alg (priv->local_key);
  1722. if (msg->body_buf.len == 0) {
  1723. pbody = NULL;
  1724. bodylen = 0;
  1725. msg->method = HTTP_GET;
  1726. }
  1727. else {
  1728. pbody = (gchar *)msg->body_buf.begin;
  1729. bodylen = msg->body_buf.len;
  1730. msg->method = HTTP_POST;
  1731. }
  1732. if (conn->type == RSPAMD_HTTP_SERVER) {
  1733. /*
  1734. * iov[0] = base reply
  1735. * iov[1] = CRLF
  1736. * iov[2] = nonce
  1737. * iov[3] = mac
  1738. * iov[4] = encrypted reply
  1739. * iov[6] = encrypted crlf
  1740. * iov[7..n] = encrypted headers
  1741. * iov[n + 1] = encrypted crlf
  1742. * [iov[n + 2] = encrypted body]
  1743. */
  1744. priv->outlen = 7;
  1745. enclen = rspamd_cryptobox_nonce_bytes (mode) +
  1746. rspamd_cryptobox_mac_bytes (mode) +
  1747. 4 + /* 2 * CRLF */
  1748. bodylen;
  1749. }
  1750. else {
  1751. /*
  1752. * iov[0] = base request
  1753. * iov[1] = CRLF
  1754. * iov[2] = nonce
  1755. * iov[3] = mac
  1756. * iov[4] = encrypted method + space
  1757. * iov[5] = encrypted url
  1758. * iov[7] = encrypted prelude
  1759. * iov[8..n] = encrypted headers
  1760. * iov[n + 1] = encrypted crlf
  1761. * [iov[n + 2] = encrypted body]
  1762. */
  1763. priv->outlen = 8;
  1764. if (bodylen > 0) {
  1765. if (mime_type != NULL) {
  1766. preludelen = rspamd_snprintf (repbuf, sizeof (repbuf), "%s\r\n"
  1767. "Content-Length: %z\r\n"
  1768. "Content-Type: %s\r\n"
  1769. "\r\n", ENCRYPTED_VERSION, bodylen,
  1770. mime_type);
  1771. }
  1772. else {
  1773. preludelen = rspamd_snprintf (repbuf, sizeof (repbuf), "%s\r\n"
  1774. "Content-Length: %z\r\n"
  1775. ""
  1776. "\r\n", ENCRYPTED_VERSION, bodylen);
  1777. }
  1778. }
  1779. else {
  1780. preludelen = rspamd_snprintf (repbuf, sizeof (repbuf),
  1781. "%s\r\n\r\n",
  1782. ENCRYPTED_VERSION);
  1783. }
  1784. enclen = rspamd_cryptobox_nonce_bytes (mode) +
  1785. rspamd_cryptobox_mac_bytes (mode) +
  1786. preludelen + /* version [content-length] + 2 * CRLF */
  1787. bodylen;
  1788. }
  1789. if (bodylen > 0) {
  1790. priv->outlen ++;
  1791. }
  1792. }
  1793. else {
  1794. if (msg->method < HTTP_SYMBOLS) {
  1795. if (msg->body_buf.len == 0 || allow_shared) {
  1796. pbody = NULL;
  1797. bodylen = 0;
  1798. priv->outlen = 2;
  1799. if (msg->method == HTTP_INVALID) {
  1800. msg->method = HTTP_GET;
  1801. }
  1802. }
  1803. else {
  1804. pbody = (gchar *)msg->body_buf.begin;
  1805. bodylen = msg->body_buf.len;
  1806. priv->outlen = 3;
  1807. if (msg->method == HTTP_INVALID) {
  1808. msg->method = HTTP_POST;
  1809. }
  1810. }
  1811. }
  1812. else if (msg->body_buf.len > 0) {
  1813. allow_shared = FALSE;
  1814. pbody = (gchar *)msg->body_buf.begin;
  1815. bodylen = msg->body_buf.len;
  1816. priv->outlen = 2;
  1817. }
  1818. else {
  1819. /* Invalid body for spamc method */
  1820. abort ();
  1821. }
  1822. }
  1823. peer_key = msg->peer_key;
  1824. priv->wr_total = bodylen + 2;
  1825. hdrcount = 0;
  1826. if (msg->method < HTTP_SYMBOLS) {
  1827. kh_foreach_value (msg->headers, hdr, {
  1828. DL_FOREACH (hdr, hcur) {
  1829. /* <name: value\r\n> */
  1830. priv->wr_total += hcur->combined->len;
  1831. enclen += hcur->combined->len;
  1832. priv->outlen ++;
  1833. hdrcount ++;
  1834. }
  1835. });
  1836. }
  1837. /* Allocate iov */
  1838. priv->out = g_malloc0 (sizeof (struct iovec) * priv->outlen);
  1839. priv->wr_pos = 0;
  1840. meth_len = rspamd_http_message_write_header (mime_type, encrypted,
  1841. repbuf, sizeof (repbuf), bodylen, enclen,
  1842. host, conn, msg,
  1843. &buf, priv, peer_key);
  1844. priv->wr_total += buf->len;
  1845. /* Setup external request body */
  1846. priv->out[0].iov_base = buf->str;
  1847. priv->out[0].iov_len = buf->len;
  1848. /* Buf will be used eventually for encryption */
  1849. if (encrypted) {
  1850. gint meth_offset, nonce_offset, mac_offset;
  1851. mode = rspamd_keypair_alg (priv->local_key);
  1852. ottery_rand_bytes (nonce, rspamd_cryptobox_nonce_bytes (mode));
  1853. memset (mac, 0, rspamd_cryptobox_mac_bytes (mode));
  1854. meth_offset = buf->len;
  1855. if (conn->type == RSPAMD_HTTP_SERVER) {
  1856. buf = rspamd_fstring_append (buf, repbuf, meth_len);
  1857. }
  1858. else {
  1859. meth_len = strlen (http_method_str (msg->method)) + 1; /* + space */
  1860. buf = rspamd_fstring_append (buf, http_method_str (msg->method),
  1861. meth_len - 1);
  1862. buf = rspamd_fstring_append (buf, " ", 1);
  1863. }
  1864. nonce_offset = buf->len;
  1865. buf = rspamd_fstring_append (buf, nonce,
  1866. rspamd_cryptobox_nonce_bytes (mode));
  1867. mac_offset = buf->len;
  1868. buf = rspamd_fstring_append (buf, mac,
  1869. rspamd_cryptobox_mac_bytes (mode));
  1870. /* Need to be encrypted */
  1871. if (conn->type == RSPAMD_HTTP_SERVER) {
  1872. buf = rspamd_fstring_append (buf, "\r\n\r\n", 4);
  1873. }
  1874. else {
  1875. buf = rspamd_fstring_append (buf, repbuf, preludelen);
  1876. }
  1877. meth_pos = buf->str + meth_offset;
  1878. np = buf->str + nonce_offset;
  1879. mp = buf->str + mac_offset;
  1880. }
  1881. /* During previous writes, buf might be reallocated and changed */
  1882. priv->buf->data = buf;
  1883. if (encrypted) {
  1884. /* Finish external HTTP request */
  1885. priv->out[1].iov_base = "\r\n";
  1886. priv->out[1].iov_len = 2;
  1887. /* Encrypt the real request */
  1888. rspamd_http_connection_encrypt_message (conn, msg, priv, pbody, bodylen,
  1889. meth_pos, meth_len, preludelen, hdrcount, np, mp, peer_key);
  1890. }
  1891. else {
  1892. i = 1;
  1893. if (msg->method < HTTP_SYMBOLS) {
  1894. kh_foreach_value (msg->headers, hdr, {
  1895. DL_FOREACH (hdr, hcur) {
  1896. priv->out[i].iov_base = hcur->combined->str;
  1897. priv->out[i++].iov_len = hcur->combined->len;
  1898. }
  1899. });
  1900. priv->out[i].iov_base = "\r\n";
  1901. priv->out[i++].iov_len = 2;
  1902. }
  1903. else {
  1904. /* No CRLF for compatibility reply */
  1905. priv->wr_total -= 2;
  1906. }
  1907. if (pbody != NULL) {
  1908. priv->out[i].iov_base = pbody;
  1909. priv->out[i++].iov_len = bodylen;
  1910. }
  1911. }
  1912. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_RESETED;
  1913. if (priv->flags & RSPAMD_HTTP_CONN_FLAG_PROXY) {
  1914. /* We need to disable SSL flag! */
  1915. msg->flags &=~ RSPAMD_HTTP_FLAG_SSL;
  1916. }
  1917. rspamd_ev_watcher_stop (priv->ctx->event_loop, &priv->ev);
  1918. if (msg->flags & RSPAMD_HTTP_FLAG_SSL) {
  1919. gpointer ssl_ctx = (msg->flags & RSPAMD_HTTP_FLAG_SSL_NOVERIFY) ?
  1920. priv->ctx->ssl_ctx_noverify : priv->ctx->ssl_ctx;
  1921. if (!ssl_ctx) {
  1922. err = g_error_new (HTTP_ERROR, 400, "ssl message requested "
  1923. "with no ssl ctx");
  1924. rspamd_http_connection_ref (conn);
  1925. conn->error_handler (conn, err);
  1926. rspamd_http_connection_unref (conn);
  1927. g_error_free (err);
  1928. return FALSE;
  1929. }
  1930. else {
  1931. if (priv->ssl) {
  1932. /* Cleanup the existing connection */
  1933. rspamd_ssl_connection_free (priv->ssl);
  1934. }
  1935. priv->ssl = rspamd_ssl_connection_new (ssl_ctx, priv->ctx->event_loop,
  1936. !(msg->flags & RSPAMD_HTTP_FLAG_SSL_NOVERIFY),
  1937. conn->log_tag);
  1938. g_assert (priv->ssl != NULL);
  1939. if (!rspamd_ssl_connect_fd (priv->ssl, conn->fd, host, &priv->ev,
  1940. priv->timeout, rspamd_http_event_handler,
  1941. rspamd_http_ssl_err_handler, conn)) {
  1942. err = g_error_new (HTTP_ERROR, 400,
  1943. "ssl connection error: ssl error=%s, errno=%s",
  1944. ERR_error_string (ERR_get_error (), NULL),
  1945. strerror (errno));
  1946. rspamd_http_connection_ref (conn);
  1947. conn->error_handler (conn, err);
  1948. rspamd_http_connection_unref (conn);
  1949. g_error_free (err);
  1950. return FALSE;
  1951. }
  1952. }
  1953. }
  1954. else {
  1955. rspamd_ev_watcher_init (&priv->ev, conn->fd, EV_WRITE,
  1956. rspamd_http_event_handler, conn);
  1957. rspamd_ev_watcher_start (priv->ctx->event_loop, &priv->ev, priv->timeout);
  1958. }
  1959. return TRUE;
  1960. }
  1961. gboolean
  1962. rspamd_http_connection_write_message (struct rspamd_http_connection *conn,
  1963. struct rspamd_http_message *msg,
  1964. const gchar *host,
  1965. const gchar *mime_type,
  1966. gpointer ud,
  1967. ev_tstamp timeout)
  1968. {
  1969. return rspamd_http_connection_write_message_common (conn, msg, host, mime_type,
  1970. ud, timeout, FALSE);
  1971. }
  1972. gboolean
  1973. rspamd_http_connection_write_message_shared (struct rspamd_http_connection *conn,
  1974. struct rspamd_http_message *msg,
  1975. const gchar *host,
  1976. const gchar *mime_type,
  1977. gpointer ud,
  1978. ev_tstamp timeout)
  1979. {
  1980. return rspamd_http_connection_write_message_common (conn, msg, host, mime_type,
  1981. ud, timeout, TRUE);
  1982. }
  1983. void
  1984. rspamd_http_connection_set_max_size (struct rspamd_http_connection *conn,
  1985. gsize sz)
  1986. {
  1987. conn->max_size = sz;
  1988. }
  1989. void
  1990. rspamd_http_connection_set_key (struct rspamd_http_connection *conn,
  1991. struct rspamd_cryptobox_keypair *key)
  1992. {
  1993. struct rspamd_http_connection_private *priv = conn->priv;
  1994. g_assert (key != NULL);
  1995. priv->local_key = rspamd_keypair_ref (key);
  1996. }
  1997. void
  1998. rspamd_http_connection_own_socket (struct rspamd_http_connection *conn)
  1999. {
  2000. struct rspamd_http_connection_private *priv = conn->priv;
  2001. priv->flags |= RSPAMD_HTTP_CONN_OWN_SOCKET;
  2002. }
  2003. const struct rspamd_cryptobox_pubkey*
  2004. rspamd_http_connection_get_peer_key (struct rspamd_http_connection *conn)
  2005. {
  2006. struct rspamd_http_connection_private *priv = conn->priv;
  2007. if (priv->peer_key) {
  2008. return priv->peer_key;
  2009. }
  2010. else if (priv->msg) {
  2011. return priv->msg->peer_key;
  2012. }
  2013. return NULL;
  2014. }
  2015. gboolean
  2016. rspamd_http_connection_is_encrypted (struct rspamd_http_connection *conn)
  2017. {
  2018. struct rspamd_http_connection_private *priv = conn->priv;
  2019. if (priv->peer_key != NULL) {
  2020. return TRUE;
  2021. }
  2022. else if (priv->msg) {
  2023. return priv->msg->peer_key != NULL;
  2024. }
  2025. return FALSE;
  2026. }
  2027. GHashTable *
  2028. rspamd_http_message_parse_query (struct rspamd_http_message *msg)
  2029. {
  2030. GHashTable *res;
  2031. rspamd_fstring_t *key = NULL, *value = NULL;
  2032. rspamd_ftok_t *key_tok = NULL, *value_tok = NULL;
  2033. const gchar *p, *c, *end;
  2034. struct http_parser_url u;
  2035. enum {
  2036. parse_key,
  2037. parse_eqsign,
  2038. parse_value,
  2039. parse_ampersand
  2040. } state = parse_key;
  2041. res = g_hash_table_new_full (rspamd_ftok_icase_hash,
  2042. rspamd_ftok_icase_equal,
  2043. rspamd_fstring_mapped_ftok_free,
  2044. rspamd_fstring_mapped_ftok_free);
  2045. if (msg->url && msg->url->len > 0) {
  2046. http_parser_parse_url (msg->url->str, msg->url->len, TRUE, &u);
  2047. if (u.field_set & (1 << UF_QUERY)) {
  2048. p = msg->url->str + u.field_data[UF_QUERY].off;
  2049. c = p;
  2050. end = p + u.field_data[UF_QUERY].len;
  2051. while (p <= end) {
  2052. switch (state) {
  2053. case parse_key:
  2054. if ((p == end || *p == '&') && p > c) {
  2055. /* We have a single parameter without a value */
  2056. key = rspamd_fstring_new_init (c, p - c);
  2057. key_tok = rspamd_ftok_map (key);
  2058. key_tok->len = rspamd_url_decode (key->str, key->str,
  2059. key->len);
  2060. value = rspamd_fstring_new_init ("", 0);
  2061. value_tok = rspamd_ftok_map (value);
  2062. g_hash_table_replace (res, key_tok, value_tok);
  2063. state = parse_ampersand;
  2064. }
  2065. else if (*p == '=' && p > c) {
  2066. /* We have something like key=value */
  2067. key = rspamd_fstring_new_init (c, p - c);
  2068. key_tok = rspamd_ftok_map (key);
  2069. key_tok->len = rspamd_url_decode (key->str, key->str,
  2070. key->len);
  2071. state = parse_eqsign;
  2072. }
  2073. else {
  2074. p ++;
  2075. }
  2076. break;
  2077. case parse_eqsign:
  2078. if (*p != '=') {
  2079. c = p;
  2080. state = parse_value;
  2081. }
  2082. else {
  2083. p ++;
  2084. }
  2085. break;
  2086. case parse_value:
  2087. if ((p == end || *p == '&') && p >= c) {
  2088. g_assert (key != NULL);
  2089. if (p > c) {
  2090. value = rspamd_fstring_new_init (c, p - c);
  2091. value_tok = rspamd_ftok_map (value);
  2092. value_tok->len = rspamd_url_decode (value->str,
  2093. value->str,
  2094. value->len);
  2095. /* Detect quotes for value */
  2096. if (value_tok->begin[0] == '"') {
  2097. memmove (value->str, value->str + 1,
  2098. value_tok->len - 1);
  2099. value_tok->len --;
  2100. }
  2101. if (value_tok->begin[value_tok->len - 1] == '"') {
  2102. value_tok->len --;
  2103. }
  2104. }
  2105. else {
  2106. value = rspamd_fstring_new_init ("", 0);
  2107. value_tok = rspamd_ftok_map (value);
  2108. }
  2109. g_hash_table_replace (res, key_tok, value_tok);
  2110. key = value = NULL;
  2111. key_tok = value_tok = NULL;
  2112. state = parse_ampersand;
  2113. }
  2114. else {
  2115. p ++;
  2116. }
  2117. break;
  2118. case parse_ampersand:
  2119. if (p != end && *p != '&') {
  2120. c = p;
  2121. state = parse_key;
  2122. }
  2123. else {
  2124. p ++;
  2125. }
  2126. break;
  2127. }
  2128. }
  2129. }
  2130. if (state != parse_ampersand && key != NULL) {
  2131. rspamd_fstring_free (key);
  2132. }
  2133. }
  2134. return res;
  2135. }
  2136. struct rspamd_http_message *
  2137. rspamd_http_message_ref (struct rspamd_http_message *msg)
  2138. {
  2139. REF_RETAIN (msg);
  2140. return msg;
  2141. }
  2142. void
  2143. rspamd_http_message_unref (struct rspamd_http_message *msg)
  2144. {
  2145. REF_RELEASE (msg);
  2146. }
  2147. void
  2148. rspamd_http_connection_disable_encryption (struct rspamd_http_connection *conn)
  2149. {
  2150. struct rspamd_http_connection_private *priv;
  2151. priv = conn->priv;
  2152. if (priv) {
  2153. if (priv->local_key) {
  2154. rspamd_keypair_unref (priv->local_key);
  2155. }
  2156. if (priv->peer_key) {
  2157. rspamd_pubkey_unref (priv->peer_key);
  2158. }
  2159. priv->local_key = NULL;
  2160. priv->peer_key = NULL;
  2161. priv->flags &= ~RSPAMD_HTTP_CONN_FLAG_ENCRYPTED;
  2162. }
  2163. }