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

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