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.h 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  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. #ifndef HTTP_H_
  17. #define HTTP_H_
  18. /**
  19. * @file http.h
  20. *
  21. * This is an interface for HTTP client and conn. This code uses HTTP parser written
  22. * by Joyent Inc based on nginx code.
  23. */
  24. #include "config.h"
  25. #include "http_parser.h"
  26. #include "keypairs_cache.h"
  27. #include "fstring.h"
  28. enum rspamd_http_connection_type {
  29. RSPAMD_HTTP_SERVER,
  30. RSPAMD_HTTP_CLIENT
  31. };
  32. /**
  33. * HTTP header structure
  34. */
  35. struct rspamd_http_header {
  36. rspamd_ftok_t *name;
  37. rspamd_ftok_t *value;
  38. rspamd_fstring_t *combined;
  39. struct rspamd_http_header *next, *prev;
  40. };
  41. /**
  42. * Legacy spamc protocol
  43. */
  44. #define RSPAMD_HTTP_FLAG_SPAMC 1 << 1
  45. /**
  46. * HTTP message structure, used for requests and replies
  47. */
  48. struct rspamd_http_message {
  49. rspamd_fstring_t *url;
  50. rspamd_fstring_t *host;
  51. unsigned port;
  52. rspamd_fstring_t *status;
  53. struct rspamd_http_header *headers;
  54. rspamd_fstring_t *body;
  55. rspamd_ftok_t body_buf;
  56. gpointer peer_key;
  57. enum http_parser_type type;
  58. time_t date;
  59. gint code;
  60. enum http_method method;
  61. gint flags;
  62. };
  63. /**
  64. * Options for HTTP connection
  65. */
  66. enum rspamd_http_options {
  67. RSPAMD_HTTP_BODY_PARTIAL = 0x1, /**< Call body handler on all body data portions */
  68. RSPAMD_HTTP_CLIENT_SIMPLE = 0x2, /**< Read HTTP client reply automatically */
  69. RSPAMD_HTTP_CLIENT_ENCRYPTED = 0x4 /**< Encrypt data for client */
  70. };
  71. struct rspamd_http_connection_private;
  72. struct rspamd_http_connection;
  73. struct rspamd_http_connection_router;
  74. struct rspamd_http_connection_entry;
  75. typedef int (*rspamd_http_body_handler_t) (struct rspamd_http_connection *conn,
  76. struct rspamd_http_message *msg,
  77. const gchar *chunk,
  78. gsize len);
  79. typedef void (*rspamd_http_error_handler_t) (struct rspamd_http_connection *conn,
  80. GError *err);
  81. typedef int (*rspamd_http_finish_handler_t) (struct rspamd_http_connection *conn,
  82. struct rspamd_http_message *msg);
  83. typedef int (*rspamd_http_router_handler_t) (struct rspamd_http_connection_entry
  84. *conn_ent,
  85. struct rspamd_http_message *msg);
  86. typedef void (*rspamd_http_router_error_handler_t) (struct
  87. rspamd_http_connection_entry *conn_ent,
  88. GError *err);
  89. typedef void (*rspamd_http_router_finish_handler_t) (struct
  90. rspamd_http_connection_entry *conn_ent);
  91. /**
  92. * HTTP connection structure
  93. */
  94. struct rspamd_http_connection {
  95. struct rspamd_http_connection_private *priv;
  96. rspamd_http_body_handler_t body_handler;
  97. rspamd_http_error_handler_t error_handler;
  98. rspamd_http_finish_handler_t finish_handler;
  99. struct rspamd_keypair_cache *cache;
  100. gpointer ud;
  101. unsigned opts;
  102. enum rspamd_http_connection_type type;
  103. gboolean finished;
  104. gint fd;
  105. gint ref;
  106. };
  107. struct rspamd_http_connection_entry {
  108. struct rspamd_http_connection_router *rt;
  109. struct rspamd_http_connection *conn;
  110. gpointer ud;
  111. gboolean is_reply;
  112. struct rspamd_http_connection_entry *prev, *next;
  113. };
  114. struct rspamd_http_connection_router {
  115. struct rspamd_http_connection_entry *conns;
  116. GHashTable *paths;
  117. struct timeval tv;
  118. struct timeval *ptv;
  119. struct event_base *ev_base;
  120. struct rspamd_keypair_cache *cache;
  121. gchar *default_fs_path;
  122. gpointer key;
  123. rspamd_http_router_error_handler_t error_handler;
  124. rspamd_http_router_finish_handler_t finish_handler;
  125. };
  126. /**
  127. * Create new http connection
  128. * @param handler_t handler_t for body
  129. * @param opts options
  130. * @return new connection structure
  131. */
  132. struct rspamd_http_connection * rspamd_http_connection_new (
  133. rspamd_http_body_handler_t body_handler,
  134. rspamd_http_error_handler_t error_handler,
  135. rspamd_http_finish_handler_t finish_handler,
  136. unsigned opts,
  137. enum rspamd_http_connection_type type,
  138. struct rspamd_keypair_cache *cache);
  139. /**
  140. * Load the encryption keypair
  141. * @param key base32 encoded privkey and pubkey (in that order)
  142. * @param keylen length of base32 string
  143. * @return opaque pointer pr NULL in case of error
  144. */
  145. gpointer rspamd_http_connection_make_key (gchar *key, gsize keylen);
  146. /**
  147. * Generate the encryption keypair
  148. * @return opaque pointer pr NULL in case of error
  149. */
  150. gpointer rspamd_http_connection_gen_key (void);
  151. /**
  152. * Set key pointed by an opaque pointer
  153. * @param conn connection structure
  154. * @param key opaque key structure
  155. */
  156. void rspamd_http_connection_set_key (struct rspamd_http_connection *conn,
  157. gpointer key);
  158. /**
  159. * Returns TRUE if a connection is encrypted
  160. * @param conn
  161. * @return
  162. */
  163. gboolean rspamd_http_connection_is_encrypted (struct rspamd_http_connection *conn);
  164. /** Print pubkey */
  165. #define RSPAMD_KEYPAIR_PUBKEY 0x1
  166. /** Print secret key */
  167. #define RSPAMD_KEYPAIR_PRIVKEY 0x2
  168. /** Print key id */
  169. #define RSPAMD_KEYPAIR_ID 0x4
  170. /** Encode output with base 32 */
  171. #define RSPAMD_KEYPAIR_BASE32 0x8
  172. /** Human readable output */
  173. #define RSPAMD_KEYPAIR_HUMAN 0x10
  174. #define RSPAMD_KEYPAIR_HEX 0x20
  175. /**
  176. * Print keypair encoding it if needed
  177. * @param key key to print
  178. * @param how flags that specifies printing behaviour
  179. * @return newly allocated string with keypair
  180. */
  181. GString *rspamd_http_connection_print_key (gpointer key, guint how);
  182. /**
  183. * Release key pointed by an opaque pointer
  184. * @param key opaque key structure
  185. */
  186. void rspamd_http_connection_key_unref (gpointer key);
  187. /**
  188. * Increase refcount for a key pointed by an opaque pointer
  189. * @param key opaque key structure
  190. */
  191. gpointer rspamd_http_connection_key_ref (gpointer key);
  192. gpointer rspamd_http_connection_make_peer_key (const gchar *key);
  193. /**
  194. * Handle a request using socket fd and user data ud
  195. * @param conn connection structure
  196. * @param ud opaque user data
  197. * @param fd fd to read/write
  198. */
  199. void rspamd_http_connection_read_message (
  200. struct rspamd_http_connection *conn,
  201. gpointer ud,
  202. gint fd,
  203. struct timeval *timeout,
  204. struct event_base *base);
  205. /**
  206. * Send reply using initialised connection
  207. * @param conn connection structure
  208. * @param msg HTTP message
  209. * @param ud opaque user data
  210. * @param fd fd to read/write
  211. */
  212. void rspamd_http_connection_write_message (
  213. struct rspamd_http_connection *conn,
  214. struct rspamd_http_message *msg,
  215. const gchar *host,
  216. const gchar *mime_type,
  217. gpointer ud,
  218. gint fd,
  219. struct timeval *timeout,
  220. struct event_base *base);
  221. /**
  222. * Free connection structure
  223. * @param conn
  224. */
  225. void rspamd_http_connection_free (struct rspamd_http_connection *conn);
  226. /**
  227. * Increase refcount for a connection
  228. * @param conn
  229. * @return
  230. */
  231. static inline struct rspamd_http_connection *
  232. rspamd_http_connection_ref (struct rspamd_http_connection *conn)
  233. {
  234. conn->ref++;
  235. return conn;
  236. }
  237. /**
  238. * Decrease a refcount for a connection and free it if refcount is equal to zero
  239. * @param conn
  240. */
  241. static void
  242. rspamd_http_connection_unref (struct rspamd_http_connection *conn)
  243. {
  244. if (--conn->ref <= 0) {
  245. rspamd_http_connection_free (conn);
  246. }
  247. }
  248. /**
  249. * Reset connection for a new request
  250. * @param conn
  251. */
  252. void rspamd_http_connection_reset (struct rspamd_http_connection *conn);
  253. /**
  254. * Extract the current message from a connection to deal with separately
  255. * @param conn
  256. * @return
  257. */
  258. struct rspamd_http_message * rspamd_http_connection_steal_msg (
  259. struct rspamd_http_connection *conn);
  260. /**
  261. * Create new HTTP message
  262. * @param type request or response
  263. * @return new http message
  264. */
  265. struct rspamd_http_message * rspamd_http_new_message (enum http_parser_type type);
  266. /**
  267. * Create HTTP message from URL
  268. * @param url
  269. * @return new message or NULL
  270. */
  271. struct rspamd_http_message* rspamd_http_message_from_url (const gchar *url);
  272. /**
  273. * Append a header to reply
  274. * @param rep
  275. * @param name
  276. * @param value
  277. */
  278. void rspamd_http_message_add_header (struct rspamd_http_message *msg,
  279. const gchar *name,
  280. const gchar *value);
  281. /**
  282. * Search for a specified header in message
  283. * @param msg message
  284. * @param name name of header
  285. */
  286. const rspamd_ftok_t * rspamd_http_message_find_header (
  287. struct rspamd_http_message *msg,
  288. const gchar *name);
  289. /**
  290. * Remove specific header from a message
  291. * @param msg
  292. * @param name
  293. * @return
  294. */
  295. gboolean rspamd_http_message_remove_header (struct rspamd_http_message *msg,
  296. const gchar *name);
  297. /**
  298. * Free HTTP message
  299. * @param msg
  300. */
  301. void rspamd_http_message_free (struct rspamd_http_message *msg);
  302. /**
  303. * Parse HTTP date header and return it as time_t
  304. * @param header HTTP date header
  305. * @param len length of header
  306. * @return time_t or (time_t)-1 in case of error
  307. */
  308. time_t rspamd_http_parse_date (const gchar *header, gsize len);
  309. /**
  310. * Create new http connection router and the associated HTTP connection
  311. * @param eh error handler callback
  312. * @param fh finish handler callback
  313. * @param default_fs_path if not NULL try to serve static files from
  314. * the specified directory
  315. * @return
  316. */
  317. struct rspamd_http_connection_router * rspamd_http_router_new (
  318. rspamd_http_router_error_handler_t eh,
  319. rspamd_http_router_finish_handler_t fh,
  320. struct timeval *timeout,
  321. struct event_base *base,
  322. const char *default_fs_path,
  323. struct rspamd_keypair_cache *cache);
  324. /**
  325. * Set encryption key for the HTTP router
  326. * @param router router structure
  327. * @param key opaque key structure
  328. */
  329. void rspamd_http_router_set_key (struct rspamd_http_connection_router *router,
  330. gpointer key);
  331. /**
  332. * Add new path to the router
  333. */
  334. void rspamd_http_router_add_path (struct rspamd_http_connection_router *router,
  335. const gchar *path, rspamd_http_router_handler_t handler);
  336. /**
  337. * Handle new accepted socket
  338. * @param router router object
  339. * @param fd server socket
  340. * @param ud opaque userdata
  341. */
  342. void rspamd_http_router_handle_socket (
  343. struct rspamd_http_connection_router *router,
  344. gint fd,
  345. gpointer ud);
  346. /**
  347. * Free router and all connections associated
  348. * @param router
  349. */
  350. void rspamd_http_router_free (struct rspamd_http_connection_router *router);
  351. /**
  352. * Extract arguments from a messsage's URI contained inside query string decoding
  353. * them if needed
  354. * @param msg HTTP request message
  355. * @return new GHashTable which maps rspamd_ftok_t* to rspamd_ftok_t*
  356. * (table must be freed by a caller)
  357. */
  358. GHashTable* rspamd_http_message_parse_query (struct rspamd_http_message *msg);
  359. #endif /* HTTP_H_ */