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

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