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.

milter_internal.h 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*-
  2. * Copyright 2017 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 RSPAMD_MILTER_INTERNAL_H
  17. #define RSPAMD_MILTER_INTERNAL_H
  18. #include "config.h"
  19. #include "libutil/mem_pool.h"
  20. #include "contrib/libev/ev.h"
  21. #include "khash.h"
  22. #include "libutil/str_util.h"
  23. #include "libutil/libev_helper.h"
  24. #ifdef __cplusplus
  25. extern "C" {
  26. #endif
  27. enum rspamd_milter_state {
  28. st_len_1 = 0,
  29. st_len_2,
  30. st_len_3,
  31. st_len_4,
  32. st_read_cmd,
  33. st_read_data
  34. };
  35. struct rspamd_milter_parser {
  36. rspamd_fstring_t *buf;
  37. goffset pos;
  38. goffset cmd_start;
  39. gsize datalen;
  40. enum rspamd_milter_state state;
  41. char cur_cmd;
  42. };
  43. struct rspamd_milter_outbuf {
  44. rspamd_fstring_t *buf;
  45. goffset pos;
  46. struct rspamd_milter_outbuf *next, *prev;
  47. };
  48. enum rspamd_milter_io_state {
  49. RSPAMD_MILTER_READ_MORE,
  50. RSPAMD_MILTER_WRITE_REPLY,
  51. RSPAMD_MILTER_WANNA_DIE,
  52. RSPAMD_MILTER_WRITE_AND_DIE,
  53. RSPAMD_MILTER_PONG_AND_DIE,
  54. };
  55. KHASH_INIT(milter_headers_hash_t, char *, GArray *, true,
  56. rspamd_strcase_hash, rspamd_strcase_equal);
  57. struct rspamd_milter_private {
  58. struct rspamd_milter_parser parser;
  59. struct rspamd_io_ev ev;
  60. struct rspamd_milter_outbuf *out_chain;
  61. struct ev_loop *event_loop;
  62. rspamd_mempool_t *pool;
  63. khash_t(milter_headers_hash_t) * headers;
  64. int cur_hdr;
  65. rspamd_milter_finish fin_cb;
  66. rspamd_milter_error err_cb;
  67. void *ud;
  68. enum rspamd_milter_io_state state;
  69. int fd;
  70. gboolean discard_on_reject;
  71. gboolean quarantine_on_reject;
  72. gboolean no_action;
  73. };
  74. enum rspamd_milter_io_cmd {
  75. RSPAMD_MILTER_CMD_ABORT = 'A', /* Abort */
  76. RSPAMD_MILTER_CMD_BODY = 'B', /* Body chunk */
  77. RSPAMD_MILTER_CMD_CONNECT = 'C', /* Connection information */
  78. RSPAMD_MILTER_CMD_MACRO = 'D', /* Define macro */
  79. RSPAMD_MILTER_CMD_BODYEOB = 'E', /* final body chunk (end of message) */
  80. RSPAMD_MILTER_CMD_HELO = 'H', /* HELO/EHLO */
  81. RSPAMD_MILTER_CMD_QUIT_NC = 'K', /* QUIT but new connection follows */
  82. RSPAMD_MILTER_CMD_HEADER = 'L', /* Header */
  83. RSPAMD_MILTER_CMD_MAIL = 'M', /* MAIL from */
  84. RSPAMD_MILTER_CMD_EOH = 'N', /* EOH */
  85. RSPAMD_MILTER_CMD_OPTNEG = 'O', /* Option negotiation */
  86. RSPAMD_MILTER_CMD_QUIT = 'Q', /* QUIT */
  87. RSPAMD_MILTER_CMD_RCPT = 'R', /* RCPT to */
  88. RSPAMD_MILTER_CMD_DATA = 'T', /* DATA */
  89. RSPAMD_MILTER_CMD_UNKNOWN = 'U' /* Any unknown command */
  90. };
  91. /*
  92. * Protocol flags
  93. */
  94. #define RSPAMD_MILTER_FLAG_NOUNKNOWN (1L << 8) /* filter does not want unknown cmd */
  95. #define RSPAMD_MILTER_FLAG_NODATA (1L << 9) /* filter does not want DATA */
  96. #define RSPAMD_MILTER_FLAG_NR_HDR (1L << 7) /* filter won't reply for header */
  97. #define RSPAMD_MILTER_FLAG_SKIP (1L << 10) /* MTA supports SMFIR_SKIP */
  98. #define RSPAMD_MILTER_FLAG_RCPT_REJ (1L << 11) /* filter wants rejected RCPTs */
  99. #define RSPAMD_MILTER_FLAG_NR_CONN (1L << 12) /* filter won't reply for connect */
  100. #define RSPAMD_MILTER_FLAG_NR_HELO (1L << 13) /* filter won't reply for HELO */
  101. #define RSPAMD_MILTER_FLAG_NR_MAIL (1L << 14) /* filter won't reply for MAIL */
  102. #define RSPAMD_MILTER_FLAG_NR_RCPT (1L << 15) /* filter won't reply for RCPT */
  103. #define RSPAMD_MILTER_FLAG_NR_DATA (1L << 16) /* filter won't reply for DATA */
  104. #define RSPAMD_MILTER_FLAG_NR_UNKN (1L << 17) /* filter won't reply for UNKNOWN */
  105. #define RSPAMD_MILTER_FLAG_NR_EOH (1L << 18) /* filter won't reply for eoh */
  106. #define RSPAMD_MILTER_FLAG_NR_BODY (1L << 19) /* filter won't reply for body chunk */
  107. /*
  108. * For now, we specify that we want to reply just after EOM
  109. */
  110. #define RSPAMD_MILTER_FLAG_NOREPLY_MASK \
  111. (RSPAMD_MILTER_FLAG_NR_CONN | RSPAMD_MILTER_FLAG_NR_HELO | \
  112. RSPAMD_MILTER_FLAG_NR_MAIL | RSPAMD_MILTER_FLAG_NR_RCPT | \
  113. RSPAMD_MILTER_FLAG_NR_DATA | RSPAMD_MILTER_FLAG_NR_UNKN | \
  114. RSPAMD_MILTER_FLAG_NR_HDR | RSPAMD_MILTER_FLAG_NR_EOH | \
  115. RSPAMD_MILTER_FLAG_NR_BODY)
  116. /*
  117. * Options that the filter may send at initial handshake time, and message
  118. * modifications that the filter may request at the end of the message body.
  119. */
  120. #define RSPAMD_MILTER_FLAG_ADDHDRS (1L << 0) /* filter may add headers */
  121. #define RSPAMD_MILTER_FLAG_CHGBODY (1L << 1) /* filter may replace body */
  122. #define RSPAMD_MILTER_FLAG_ADDRCPT (1L << 2) /* filter may add recipients */
  123. #define RSPAMD_MILTER_FLAG_DELRCPT (1L << 3) /* filter may delete recipients */
  124. #define RSPAMD_MILTER_FLAG_CHGHDRS (1L << 4) /* filter may change/delete headers */
  125. #define RSPAMD_MILTER_FLAG_QUARANTINE (1L << 5) /* filter may request quarantine */
  126. #define RSPAMD_MILTER_ACTIONS_MASK \
  127. (RSPAMD_MILTER_FLAG_ADDHDRS | RSPAMD_MILTER_FLAG_ADDRCPT | \
  128. RSPAMD_MILTER_FLAG_DELRCPT | RSPAMD_MILTER_FLAG_CHGHDRS | \
  129. RSPAMD_MILTER_FLAG_CHGBODY | RSPAMD_MILTER_FLAG_QUARANTINE)
  130. enum rspamd_milter_connect_proto {
  131. RSPAMD_MILTER_CONN_UNKNOWN = 'U',
  132. RSPAMD_MILTER_CONN_UNIX = 'L',
  133. RSPAMD_MILTER_CONN_INET = '4',
  134. RSPAMD_MILTER_CONN_INET6 = '6',
  135. };
  136. /*
  137. * Rspamd supports just version 6 of the protocol, failing all versions below
  138. * this one
  139. */
  140. #define RSPAMD_MILTER_PROTO_VER 6
  141. #define RSPAMD_MILTER_MESSAGE_CHUNK 65536
  142. #define RSPAMD_MILTER_RCODE_REJECT "554"
  143. #define RSPAMD_MILTER_RCODE_TEMPFAIL "451"
  144. #define RSPAMD_MILTER_RCODE_LATER "452"
  145. #define RSPAMD_MILTER_XCODE_REJECT "5.7.1"
  146. #define RSPAMD_MILTER_XCODE_TEMPFAIL "4.7.1"
  147. #define RSPAMD_MILTER_REJECT_MESSAGE "Spam message rejected"
  148. #define RSPAMD_MILTER_QUARANTINE_MESSAGE "Spam message quarantined"
  149. #define RSPAMD_MILTER_TEMPFAIL_MESSAGE "Try again later"
  150. #define RSPAMD_MILTER_SPAM_HEADER "X-Spam"
  151. #define RSPAMD_MILTER_DKIM_HEADER "DKIM-Signature"
  152. #define RSPAMD_MILTER_ACTION_HEADER "X-Rspamd-Action"
  153. #ifdef __cplusplus
  154. }
  155. #endif
  156. #endif