1 /* $OpenBSD$ */
2
3 /*
4 * Copyright (c) 2013 Eric Faurot <eric@openbsd.org>
5 * Copyright (c) 2011 Gilles Chehade <gilles@poolp.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #ifndef _SMTPD_API_H_
21 #define _SMTPD_API_H_
22
23 #include <sys/queue.h>
24 #include <sys/tree.h>
25 #include <sys/socket.h>
26
27 #include <stdio.h>
28 #include <netinet/in.h>
29 #include <netdb.h>
30 #include <limits.h>
31
32 #include <event.h>
33 #include <imsg.h>
34
35 #include "smtpd-defines.h"
36 #include "ioev.h"
37 #include "iobuf.h"
38 #include "log.h"
39 #include "rfc2822.h"
40
41 #define FILTER_API_VERSION 52
42
43 enum blockmodes {
44 BM_NORMAL,
45 BM_NONBLOCK
46 };
47
48 struct mproc {
49 pid_t pid;
50 char *name;
51 int proc;
52 void (*handler)(struct mproc *, struct imsg *);
53 struct imsgbuf imsgbuf;
54
55 char *m_buf;
56 size_t m_alloc;
57 size_t m_pos;
58 uint32_t m_type;
59 uint32_t m_peerid;
60 pid_t m_pid;
61 int m_fd;
62
63 int enable;
64 short events;
65 struct event ev;
66 void *data;
67
68 off_t msg_in;
69 off_t msg_out;
70 off_t bytes_in;
71 off_t bytes_out;
72 size_t bytes_queued;
73 size_t bytes_queued_max;
74 };
75
76 struct msg {
77 const uint8_t *pos;
78 const uint8_t *end;
79 };
80
81 struct mailaddr {
82 char user[SMTPD_MAXLOCALPARTSIZE];
83 char domain[SMTPD_MAXDOMAINPARTSIZE];
84 };
85
86 SPLAY_HEAD(_dict, dictentry);
87 SPLAY_HEAD(_tree, treeentry);
88
89 struct tree {
90 struct _tree tree;
91 size_t count;
92 };
93
94 struct dict {
95 struct _dict dict;
96 size_t count;
97 };
98
99 enum filter_status {
100 FILTER_OK,
101 FILTER_FAIL,
102 FILTER_CLOSE,
103 };
104
105 enum filter_imsg {
106 IMSG_FILTER_REGISTER,
107 IMSG_FILTER_EVENT,
108 IMSG_FILTER_QUERY,
109 IMSG_FILTER_PIPE,
110 IMSG_FILTER_RESPONSE
111 };
112
113 /* XXX - server side requires mfa_session.c update on filter_event */
114 enum filter_event_type {
115 EVENT_CONNECT,
116 EVENT_RESET,
117 EVENT_DISCONNECT,
118 EVENT_TX_BEGIN,
119 EVENT_TX_COMMIT,
120 EVENT_TX_ROLLBACK,
121 };
122
123 /* XXX - server side requires mfa_session.c update on filter_hook changes */
124 enum filter_query_type {
125 QUERY_CONNECT,
126 QUERY_HELO,
127 QUERY_MAIL,
128 QUERY_RCPT,
129 QUERY_DATA,
130 QUERY_EOM,
131 QUERY_DATALINE,
132 };
133
134 struct filter_connect {
135 struct sockaddr_storage local;
136 struct sockaddr_storage remote;
137 const char *hostname;
138 };
139
140 #define PROC_QUEUE_API_VERSION 2
141
142 enum {
143 PROC_QUEUE_OK,
144 PROC_QUEUE_FAIL,
145 PROC_QUEUE_INIT,
146 PROC_QUEUE_CLOSE,
147 PROC_QUEUE_MESSAGE_CREATE,
148 PROC_QUEUE_MESSAGE_DELETE,
149 PROC_QUEUE_MESSAGE_COMMIT,
150 PROC_QUEUE_MESSAGE_FD_R,
151 PROC_QUEUE_MESSAGE_CORRUPT,
152 PROC_QUEUE_MESSAGE_UNCORRUPT,
153 PROC_QUEUE_ENVELOPE_CREATE,
154 PROC_QUEUE_ENVELOPE_DELETE,
155 PROC_QUEUE_ENVELOPE_LOAD,
156 PROC_QUEUE_ENVELOPE_UPDATE,
157 PROC_QUEUE_ENVELOPE_WALK,
158 PROC_QUEUE_MESSAGE_WALK,
159 };
160
161 #define PROC_SCHEDULER_API_VERSION 2
162
163 struct scheduler_info;
164
165 enum {
166 PROC_SCHEDULER_OK,
167 PROC_SCHEDULER_FAIL,
168 PROC_SCHEDULER_INIT,
169 PROC_SCHEDULER_INSERT,
170 PROC_SCHEDULER_COMMIT,
171 PROC_SCHEDULER_ROLLBACK,
172 PROC_SCHEDULER_UPDATE,
173 PROC_SCHEDULER_DELETE,
174 PROC_SCHEDULER_HOLD,
175 PROC_SCHEDULER_RELEASE,
176 PROC_SCHEDULER_BATCH,
177 PROC_SCHEDULER_MESSAGES,
178 PROC_SCHEDULER_ENVELOPES,
179 PROC_SCHEDULER_SCHEDULE,
180 PROC_SCHEDULER_REMOVE,
181 PROC_SCHEDULER_SUSPEND,
182 PROC_SCHEDULER_RESUME,
183 };
184
185 enum envelope_flags {
186 EF_AUTHENTICATED = 0x01,
187 EF_BOUNCE = 0x02,
188 EF_INTERNAL = 0x04, /* Internal expansion forward */
189
190 /* runstate, not saved on disk */
191
192 EF_PENDING = 0x10,
193 EF_INFLIGHT = 0x20,
194 EF_SUSPEND = 0x40,
195 EF_HOLD = 0x80,
196 };
197
198 struct evpstate {
199 uint64_t evpid;
200 uint16_t flags;
201 uint16_t retry;
202 time_t time;
203 };
204
205 enum delivery_type {
206 D_MDA,
207 D_MTA,
208 D_BOUNCE,
209 };
210
211 struct scheduler_info {
212 uint64_t evpid;
213 enum delivery_type type;
214 uint16_t retry;
215 time_t creation;
216 time_t expire;
217 time_t lasttry;
218 time_t lastbounce;
219 time_t nexttry;
220 };
221
222 #define SCHED_REMOVE 0x01
223 #define SCHED_EXPIRE 0x02
224 #define SCHED_UPDATE 0x04
225 #define SCHED_BOUNCE 0x08
226 #define SCHED_MDA 0x10
227 #define SCHED_MTA 0x20
228
229 #define PROC_TABLE_API_VERSION 2
230
231 struct table_open_params {
232 uint32_t version;
233 char name[LINE_MAX];
234 };
235
236 enum table_service {
237 K_NONE = 0x000,
238 K_ALIAS = 0x001, /* returns struct expand */
239 K_DOMAIN = 0x002, /* returns struct destination */
240 K_CREDENTIALS = 0x004, /* returns struct credentials */
241 K_NETADDR = 0x008, /* returns struct netaddr */
242 K_USERINFO = 0x010, /* returns struct userinfo */
243 K_SOURCE = 0x020, /* returns struct source */
244 K_MAILADDR = 0x040, /* returns struct mailaddr */
245 K_ADDRNAME = 0x080, /* returns struct addrname */
246 K_MAILADDRMAP = 0x100, /* returns struct mailaddr */
247 };
248 #define K_ANY 0xfff
249
250 enum {
251 PROC_TABLE_OK,
252 PROC_TABLE_FAIL,
253 PROC_TABLE_OPEN,
254 PROC_TABLE_CLOSE,
255 PROC_TABLE_UPDATE,
256 PROC_TABLE_CHECK,
257 PROC_TABLE_LOOKUP,
258 PROC_TABLE_FETCH,
259 };
260
261 enum enhanced_status_code {
262 /* 0.0 */
263 ESC_OTHER_STATUS = 00,
264
265 /* 1.x */
266 ESC_OTHER_ADDRESS_STATUS = 10,
267 ESC_BAD_DESTINATION_MAILBOX_ADDRESS = 11,
268 ESC_BAD_DESTINATION_SYSTEM_ADDRESS = 12,
269 ESC_BAD_DESTINATION_MAILBOX_ADDRESS_SYNTAX = 13,
270 ESC_DESTINATION_MAILBOX_ADDRESS_AMBIGUOUS = 14,
271 ESC_DESTINATION_ADDRESS_VALID = 15,
272 ESC_DESTINATION_MAILBOX_HAS_MOVED = 16,
273 ESC_BAD_SENDER_MAILBOX_ADDRESS_SYNTAX = 17,
274 ESC_BAD_SENDER_SYSTEM_ADDRESS = 18,
275
276 /* 2.x */
277 ESC_OTHER_MAILBOX_STATUS = 20,
278 ESC_MAILBOX_DISABLED = 21,
279 ESC_MAILBOX_FULL = 22,
280 ESC_MESSAGE_LENGTH_TOO_LARGE = 23,
281 ESC_MAILING_LIST_EXPANSION_PROBLEM = 24,
282
283 /* 3.x */
284 ESC_OTHER_MAIL_SYSTEM_STATUS = 30,
285 ESC_MAIL_SYSTEM_FULL = 31,
286 ESC_SYSTEM_NOT_ACCEPTING_MESSAGES = 32,
287 ESC_SYSTEM_NOT_CAPABLE_OF_SELECTED_FEATURES = 33,
288 ESC_MESSAGE_TOO_BIG_FOR_SYSTEM = 34,
289 ESC_SYSTEM_INCORRECTLY_CONFIGURED = 35,
290
291 /* 4.x */
292 ESC_OTHER_NETWORK_ROUTING_STATUS = 40,
293 ESC_NO_ANSWER_FROM_HOST = 41,
294 ESC_BAD_CONNECTION = 42,
295 ESC_DIRECTORY_SERVER_FAILURE = 43,
296 ESC_UNABLE_TO_ROUTE = 44,
297 ESC_MAIL_SYSTEM_CONGESTION = 45,
298 ESC_ROUTING_LOOP_DETECTED = 46,
299 ESC_DELIVERY_TIME_EXPIRED = 47,
300
301 /* 5.x */
302 ESC_INVALID_RECIPIENT = 50,
303 ESC_INVALID_COMMAND = 51,
304 ESC_SYNTAX_ERROR = 52,
305 ESC_TOO_MANY_RECIPIENTS = 53,
306 ESC_INVALID_COMMAND_ARGUMENTS = 54,
307 ESC_WRONG_PROTOCOL_VERSION = 55,
308
309 /* 6.x */
310 ESC_OTHER_MEDIA_ERROR = 60,
311 ESC_MEDIA_NOT_SUPPORTED = 61,
312 ESC_CONVERSION_REQUIRED_AND_PROHIBITED = 62,
313 ESC_CONVERSION_REQUIRED_BUT_NOT_SUPPORTED = 63,
314 ESC_CONVERSION_WITH_LOSS_PERFORMED = 64,
315 ESC_CONVERSION_FAILED = 65,
316
317 /* 7.x */
318 ESC_OTHER_SECURITY_STATUS = 70,
319 ESC_DELIVERY_NOT_AUTHORIZED_MESSAGE_REFUSED = 71,
320 ESC_MAILING_LIST_EXPANSION_PROHIBITED = 72,
321 ESC_SECURITY_CONVERSION_REQUIRED_NOT_POSSIBLE = 73,
322 ESC_SECURITY_FEATURES_NOT_SUPPORTED = 74,
323 ESC_CRYPTOGRAPHIC_FAILURE = 75,
324 ESC_CRYPTOGRAPHIC_ALGORITHM_NOT_SUPPORTED = 76,
325 ESC_MESSAGE_INTEGRITY_FAILURE = 77,
326 };
327
328 enum enhanced_status_class {
329 ESC_STATUS_OK = 2,
330 ESC_STATUS_TEMPFAIL = 4,
331 ESC_STATUS_PERMFAIL = 5,
332 };
333
334 static inline uint32_t
evpid_to_msgid(uint64_t evpid)335 evpid_to_msgid(uint64_t evpid)
336 {
337 return (evpid >> 32);
338 }
339
340 static inline uint64_t
msgid_to_evpid(uint32_t msgid)341 msgid_to_evpid(uint32_t msgid)
342 {
343 return ((uint64_t)msgid << 32);
344 }
345
346 /* dict.c */
347 #define dict_init(d) do { SPLAY_INIT(&((d)->dict)); (d)->count = 0; } while(0)
348 #define dict_empty(d) SPLAY_EMPTY(&((d)->dict))
349 #define dict_count(d) ((d)->count)
350 int dict_check(struct dict *, const char *);
351 void *dict_set(struct dict *, const char *, void *);
352 void dict_xset(struct dict *, const char *, void *);
353 void *dict_get(struct dict *, const char *);
354 void *dict_xget(struct dict *, const char *);
355 void *dict_pop(struct dict *, const char *);
356 void *dict_xpop(struct dict *, const char *);
357 int dict_poproot(struct dict *, void **);
358 int dict_root(struct dict *, const char **, void **);
359 int dict_iter(struct dict *, void **, const char **, void **);
360 int dict_iterfrom(struct dict *, void **, const char *, const char **, void **);
361 void dict_merge(struct dict *, struct dict *);
362
363
364 /* esc.c */
365 const char *esc_code(enum enhanced_status_class, enum enhanced_status_code);
366 const char *esc_description(enum enhanced_status_code);
367
368
369 /* filter_api.c */
370 void filter_api_session_allocator(void *(*)(uint64_t));
371 void filter_api_session_destructor(void (*)(void *));
372 void *filter_api_session(uint64_t);
373
374 void filter_api_transaction_allocator(void *(*)(uint64_t));
375 void filter_api_transaction_destructor(void (*)(void *));
376 void *filter_api_transaction(uint64_t);
377
378 void filter_api_setugid(uid_t, gid_t);
379 void filter_api_set_chroot(const char *);
380 void filter_api_no_chroot(void);
381
382 void filter_api_data_buffered(void);
383 void filter_api_data_buffered_stream(uint64_t);
384
385 void filter_api_loop(void);
386 int filter_api_accept(uint64_t);
387 int filter_api_reject(uint64_t, enum filter_status);
388 int filter_api_reject_code(uint64_t, enum filter_status, uint32_t,
389 const char *);
390 void filter_api_writeln(uint64_t, const char *);
391 void filter_api_printf(uint64_t id, const char *, ...);
392 void filter_api_timer(uint64_t, uint32_t, void (*)(uint64_t, void *), void *);
393 const char *filter_api_sockaddr_to_text(const struct sockaddr *);
394 const char *filter_api_mailaddr_to_text(const struct mailaddr *);
395
396 FILE *filter_api_datahold_open(uint64_t, void (*callback)(uint64_t, FILE *, void *), void *);
397 void filter_api_datahold_close(uint64_t);
398
399 void filter_api_on_connect(int(*)(uint64_t, struct filter_connect *));
400 void filter_api_on_helo(int(*)(uint64_t, const char *));
401 void filter_api_on_mail(int(*)(uint64_t, struct mailaddr *));
402 void filter_api_on_rcpt(int(*)(uint64_t, struct mailaddr *));
403 void filter_api_on_data(int(*)(uint64_t));
404 void filter_api_on_msg_line(void(*)(uint64_t, const char *));
405 void filter_api_on_msg_start(void(*)(uint64_t));
406 void filter_api_on_msg_end(int(*)(uint64_t, size_t));
407 void filter_api_on_reset(void(*)(uint64_t));
408 void filter_api_on_disconnect(void(*)(uint64_t));
409 void filter_api_on_tx_begin(void(*)(uint64_t));
410 void filter_api_on_tx_commit(void(*)(uint64_t));
411 void filter_api_on_tx_rollback(void(*)(uint64_t));
412
413 const char *proc_name(enum smtp_proc_type);
414 const char *imsg_to_str(int);
415
416
417 /* mproc.c */
418 int mproc_fork(struct mproc *, const char*, char **);
419 void mproc_init(struct mproc *, int);
420 void mproc_clear(struct mproc *);
421 void mproc_enable(struct mproc *);
422 void mproc_disable(struct mproc *);
423 void mproc_event_add(struct mproc *);
424 void m_compose(struct mproc *, uint32_t, uint32_t, pid_t, int, void *, size_t);
425 void m_composev(struct mproc *, uint32_t, uint32_t, pid_t, int,
426 const struct iovec *, int);
427 void m_forward(struct mproc *, struct imsg *);
428 void m_create(struct mproc *, uint32_t, uint32_t, pid_t, int);
429 void m_add(struct mproc *, const void *, size_t);
430 void m_add_int(struct mproc *, int);
431 void m_add_u32(struct mproc *, uint32_t);
432 void m_add_size(struct mproc *, size_t);
433 void m_add_time(struct mproc *, time_t);
434 void m_add_string(struct mproc *, const char *);
435 void m_add_data(struct mproc *, const void *, size_t);
436 void m_add_evpid(struct mproc *, uint64_t);
437 void m_add_msgid(struct mproc *, uint32_t);
438 void m_add_id(struct mproc *, uint64_t);
439 void m_add_sockaddr(struct mproc *, const struct sockaddr *);
440 void m_add_mailaddr(struct mproc *, const struct mailaddr *);
441 void m_close(struct mproc *);
442 void m_flush(struct mproc *);
443
444 void m_msg(struct msg *, struct imsg *);
445 int m_is_eom(struct msg *);
446 void m_end(struct msg *);
447 void m_get_int(struct msg *, int *);
448 void m_get_size(struct msg *, size_t *);
449 void m_get_u32(struct msg *, uint32_t *);
450 void m_get_time(struct msg *, time_t *);
451 void m_get_string(struct msg *, const char **);
452 void m_get_data(struct msg *, const void **, size_t *);
453 void m_get_evpid(struct msg *, uint64_t *);
454 void m_get_msgid(struct msg *, uint32_t *);
455 void m_get_id(struct msg *, uint64_t *);
456 void m_get_sockaddr(struct msg *, struct sockaddr *);
457 void m_get_mailaddr(struct msg *, struct mailaddr *);
458
459 #ifdef BUILD_DAEMON
460 void m_add_envelope(struct mproc *, const struct envelope *);
461 void m_get_envelope(struct msg *, struct envelope *);
462 #endif
463
464
465 /* queue */
466 void queue_api_on_close(int(*)(void));
467 void queue_api_on_message_create(int(*)(uint32_t *));
468 void queue_api_on_message_commit(int(*)(uint32_t, const char*));
469 void queue_api_on_message_delete(int(*)(uint32_t));
470 void queue_api_on_message_fd_r(int(*)(uint32_t));
471 void queue_api_on_message_corrupt(int(*)(uint32_t));
472 void queue_api_on_message_uncorrupt(int(*)(uint32_t));
473 void queue_api_on_envelope_create(int(*)(uint32_t, const char *, size_t, uint64_t *));
474 void queue_api_on_envelope_delete(int(*)(uint64_t));
475 void queue_api_on_envelope_update(int(*)(uint64_t, const char *, size_t));
476 void queue_api_on_envelope_load(int(*)(uint64_t, char *, size_t));
477 void queue_api_on_envelope_walk(int(*)(uint64_t *, char *, size_t));
478 void queue_api_on_message_walk(int(*)(uint64_t *, char *, size_t,
479 uint32_t, int *, void **));
480 void queue_api_no_chroot(void);
481 void queue_api_set_chroot(const char *);
482 void queue_api_set_user(const char *);
483 int queue_api_dispatch(void);
484
485 /* queue utils */
486 uint32_t queue_generate_msgid(void);
487 uint64_t queue_generate_evpid(uint32_t);
488 int mktmpfile(void);
489
490 /* scheduler */
491 void scheduler_api_on_init(int(*)(void));
492 void scheduler_api_on_insert(int(*)(struct scheduler_info *));
493 void scheduler_api_on_commit(size_t(*)(uint32_t));
494 void scheduler_api_on_rollback(size_t(*)(uint32_t));
495 void scheduler_api_on_update(int(*)(struct scheduler_info *));
496 void scheduler_api_on_delete(int(*)(uint64_t));
497 void scheduler_api_on_hold(int(*)(uint64_t, uint64_t));
498 void scheduler_api_on_release(int(*)(int, uint64_t, int));
499 void scheduler_api_on_batch(int(*)(int, int *, size_t *, uint64_t *, int *));
500 void scheduler_api_on_messages(size_t(*)(uint32_t, uint32_t *, size_t));
501 void scheduler_api_on_envelopes(size_t(*)(uint64_t, struct evpstate *, size_t));
502 void scheduler_api_on_schedule(int(*)(uint64_t));
503 void scheduler_api_on_remove(int(*)(uint64_t));
504 void scheduler_api_on_suspend(int(*)(uint64_t));
505 void scheduler_api_on_resume(int(*)(uint64_t));
506 void scheduler_api_no_chroot(void);
507 void scheduler_api_set_chroot(const char *);
508 void scheduler_api_set_user(const char *);
509 int scheduler_api_dispatch(void);
510
511 /* table */
512 void table_api_on_update(int(*)(void));
513 void table_api_on_check(int(*)(int, struct dict *, const char *));
514 void table_api_on_lookup(int(*)(int, struct dict *, const char *, char *, size_t));
515 void table_api_on_fetch(int(*)(int, struct dict *, char *, size_t));
516 int table_api_dispatch(void);
517 const char *table_api_get_name(void);
518
519 /* tree.c */
520 #define tree_init(t) do { SPLAY_INIT(&((t)->tree)); (t)->count = 0; } while(0)
521 #define tree_empty(t) SPLAY_EMPTY(&((t)->tree))
522 #define tree_count(t) ((t)->count)
523 int tree_check(struct tree *, uint64_t);
524 void *tree_set(struct tree *, uint64_t, void *);
525 void tree_xset(struct tree *, uint64_t, void *);
526 void *tree_get(struct tree *, uint64_t);
527 void *tree_xget(struct tree *, uint64_t);
528 void *tree_pop(struct tree *, uint64_t);
529 void *tree_xpop(struct tree *, uint64_t);
530 int tree_poproot(struct tree *, uint64_t *, void **);
531 int tree_root(struct tree *, uint64_t *, void **);
532 int tree_iter(struct tree *, void **, uint64_t *, void **);
533 int tree_iterfrom(struct tree *, void **, uint64_t, uint64_t *, void **);
534 void tree_merge(struct tree *, struct tree *);
535
536 /* util.c */
537 struct iobuf; /* forward declaration */
538 void *xmalloc(size_t, const char *);
539 void *xcalloc(size_t, size_t, const char *);
540 char *xstrdup(const char *, const char *);
541 void *xmemdup(const void *, size_t, const char *);
542 void iobuf_xinit(struct iobuf *, size_t, size_t, const char *);
543 void iobuf_xfqueue(struct iobuf *, const char *, const char *, ...);
544 char *strip(char *);
545 int base64_encode(unsigned char const *, size_t, char *, size_t);
546 int base64_decode(char const *, unsigned char *, size_t);
547 int lowercase(char *, const char *, size_t);
548
549 #endif
550