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 61KB

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