3 .\" Copyright (c) 2019 Martijn van Duren <martijn@openbsd.org>
5 .\" Permission to use, copy, modify, and distribute this software for any
6 .\" purpose with or without fee is hereby granted, provided that the above
7 .\" copyright notice and this permission notice appear in all copies.
9 .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 .Nm osmtpd_register_filter_connect ,
22 .Nm osmtpd_register_filter_helo ,
23 .Nm osmtpd_register_filter_ehlo ,
24 .Nm osmtpd_register_filter_starttls ,
25 .Nm osmtpd_register_filter_auth ,
26 .Nm osmtpd_register_filter_mailfrom ,
27 .Nm osmtpd_register_filter_rcptto ,
28 .Nm osmtpd_register_filter_data ,
29 .Nm osmtpd_register_filter_dataline ,
30 .Nm osmtpd_register_filter_rset ,
31 .Nm osmtpd_register_filter_quit ,
32 .Nm osmtpd_register_filter_noop ,
33 .Nm osmtpd_register_filter_help ,
34 .Nm osmtpd_register_filter_wiz ,
35 .Nm osmtpd_register_filter_commit ,
36 .Nm osmtpd_register_report_connect ,
37 .Nm osmtpd_register_report_disconnect ,
38 .Nm osmtpd_register_report_identify ,
39 .Nm osmtpd_register_report_tls ,
40 .Nm osmtpd_register_report_auth ,
41 .Nm osmtpd_register_report_begin ,
42 .Nm osmtpd_register_report_mail ,
43 .Nm osmtpd_register_report_rcpt ,
44 .Nm osmtpd_register_report_envelope ,
45 .Nm osmtpd_register_report_data ,
46 .Nm osmtpd_register_report_commit ,
47 .Nm osmtpd_register_report_rollback ,
48 .Nm osmtpd_register_report_client ,
49 .Nm osmtpd_register_report_server ,
50 .Nm osmtpd_register_report_response ,
51 .Nm osmtpd_register_report_timeout ,
52 .Nm osmtpd_local_session ,
53 .Nm osmtpd_local_message ,
55 .Nm osmtpd_filter_proceed ,
56 .Nm osmtpd_filter_reject ,
57 .Nm osmtpd_filter_disconnect ,
58 .Nm osmtpd_filter_rewrite ,
59 .Nm osmtpd_filter_dataline ,
68 .Fo osmtpd_register_filter_connect
69 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *hostname, struct sockaddr_storage *ss)"
72 .Fo osmtpd_register_filter_helo
73 .Fa "void (cb*)(struct osmtpd_ctx *ctx, const char *helo)"
76 .Fo osmtpd_register_filter_ehlo
77 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *ehlo)"
80 .Fo osmtpd_register_filter_starttls
81 .Fa "void (*cb)(struct osmtpd_ctx *ctx)"
84 .Fo osmtpd_register_filter_auth
85 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *auth)"
88 .Fo osmtpd_register_filter_mailfrom
89 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *from)"
92 .Fo osmtpd_register_filter_rcptto
93 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *rcpt)"
96 .Fo osmtpd_register_filter_data
97 .Fa "void (*cb)(struct osmtpd_ctx *ctx)"
100 .Fo osmtpd_register_filter_dataline
101 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *line)"
104 .Fo osmtpd_register_filter_rset
105 .Fa "void (*cb)(struct osmtpd_ctx *ctx)"
108 .Fo osmtpd_register_filter_quit
109 .Fa "void (*cb)(struct osmtpd_ctx *ctx)"
112 .Fo osmtpd_register_filter_noop
113 .Fa "void (*cb)(struct osmtpd_ctx *ctx)"
116 .Fo osmtpd_register_filter_help
117 .Fa "void (*cb)(struct osmtpd_ctx *ctx)"
120 .Fo osmtpd_register_filter_wiz
121 .Fa "void (*cb)(struct osmtpd_ctx *ctx)"
124 .Fo osmtpd_register_filter_commit
125 .Fa "void (*cb)(struct osmtpd_ctx *ctx)"
128 .Fo osmtpd_register_report_connect
130 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *rdns, enum osmtpd_status fcrdns, struct sockaddr_storage *src, struct sockaddr_storage *dst)"
133 .Fo osmtpd_register_report_disconnect
135 .Fa "void (*ctx)(struct osmtpd_ctx *ctx)"
138 .Fo osmtpd_register_report_identify
140 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *identity)"
143 .Fo osmtpd_register_report_tls
145 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *ciphers)"
148 .Fo osmtpd_register_report_auth
150 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *username, enum osmtpd_auth_status status)"
153 .Fo osmtpd_register_report_begin
155 .Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
158 .Fo osmtpd_register_report_mail
160 .Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *mailfrom, enum osmtpd_status status)"
163 .Fo osmtpd_register_report_rcpt
165 .Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *rcptto, enum osmtpd_status status)"
168 .Fo osmtpd_register_report_envelope
170 .Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, uint64_t evpid)"
173 .Fo osmtpd_register_report_data
175 .Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, enum osmtpd_status status)"
178 .Fo osmtpd_register_report_commit
180 .Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, size_t msgsz)"
183 .Fo osmtpd_register_report_rollback
185 .Fa "void (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
188 .Fo osmtpd_register_report_client
190 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *cmd)"
193 .Fo osmtpd_register_report_server
195 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *resp)"
198 .Fo osmtpd_register_report_response
200 .Fa "void (*cb)(struct osmtpd_ctx *ctx, const char *resp)"
203 .Fo osmtpd_register_report_timeout
205 .Fa "void (*cb)(struct osmtpd_ctx *ctx)"
208 .Fo osmtpd_local_session
209 .Fa "void *(*oncreate)(struct osmtpd_ctx *ctx)"
210 .Fa "void (*ondelete)(struct osmtpd_ctx *ctx, void *data)"
213 .Fo osmtpd_local_message
214 .Fa "void *(*oncreate)(struct osmtpd_ctx *ctx)"
215 .Fa "void (*ondelete)(struct osmtpd_ctx *ctx, void *data)"
218 .Fn osmtpd_need "int needs"
220 .Fn osmtpd_filter_proceed "struct osmtpd_ctx *ctx"
222 .Fn osmtpd_filter_reject "struct osmtpd_ctx *ctx" "int error" "const char *msg" ...
224 .Fn osmtpd_filter_disconnect "struct osmtpd_ctx *ctx" "const char *msg" ...
226 .Fn osmtpd_filter_rewrite "struct osmtpd_ctx *ctx" "const char *value" ...
228 .Fn osmtpd_filter_dataline "struct osmtpd_ctx *ctx" "const char *line" ...
232 .Fn osmtpd_err "int eval" "const char *fmt" ...
234 .Fn osmtpd_errx "int eval" "const char *fmt" ...
238 API is an event based interface for writing
241 Filter and report callbacks are registered via the
243 class of functions, followed by
247 starts the communication with the server and transforms network queries to
250 .Xr event_dispatch 3 ,
251 which allows filters to be written fully asynchronously.
255 gets at least a pointer of the type
256 .Fa struct osmtpd_ctx .
257 It contains the following elements:
259 .It Fa "enum osmtpd_type type"
260 The type of request being made.
261 The possible values are
262 .Dv OSMTPD_TYPE_FILTER
264 .Dv OSMTPD_TYPE_REPORT .
265 .It Vt "enum osmtpd_phase" Va phase
266 The phase in the transaction which triggered the callback.
267 The following values match their respective
270 .Bl -tag -compact -width OSMTPD_PHASE_LINK_DISCONNECT
271 .It Dv OSMTPD_PHASE_CONNECT
272 .Nm osmtpd_register_filter_connect
273 .It Dv OSMTPD_PHASE_HELO
274 .Nm osmtpd_register_filter_helo
275 .It Dv OSMTPD_PHASE_EHLO
276 .Nm osmtpd_register_filter_ehlo
277 .It Dv OSMTPD_PHASE_STARTTLS
278 .Nm osmtpd_register_filter_starttls
279 .It Dv OSMTPD_PHASE_AUTH
280 .Nm osmtpd_register_filter_auth
281 .It Dv OSMTPD_PHASE_MAIL_FROM
282 .Nm osmtpd_register_filter_mailfrom
283 .It Dv OSMTPD_PHASE_RCPT_TO
284 .Nm osmtpd_register_filter_rcptto
285 .It Dv OSMTPD_PHASE_DATA
286 .Nm osmtpd_register_filter_data
287 .It Dv OSMTPD_PHASE_DATA_LINE
288 .Nm osmtpd_register_filter_dataline
289 .It Dv OSMTPD_PHASE_RSET
290 .Nm osmtpd_register_filter_rset
291 .It Dv OSMTPD_PHASE_QUIT
292 .Nm osmtpd_register_filter_quit
293 .It Dv OSMTPD_PHASE_NOOP
294 .Nm osmtpd_register_filter_noop
295 .It Dv OSMTPD_PHASE_HELP
296 .Nm osmtpd_register_filter_help
297 .It Dv OSMTPD_PHASE_WIZ
298 .Nm osmtpd_register_filter_wiz
299 .It Dv OSMTPD_PHASE_COMMIT
300 .Nm osmtpd_register_filter_commit
301 .It Dv OSMTPD_PHASE_LINK_CONNECT
302 .Nm osmtpd_register_report_connect
303 .It OSMTPD_PHASE_LINK_DISCONNECT
304 .Nm osmtpd_register_report_disconnect
305 .It Dv OSMTPD_PHASE_LINK_IDENTIFY
306 .Nm osmtpd_register_report_identify
307 .It Dv OSMTPD_PHASE_LINK_TLS
308 .Nm osmtpd_register_report_tls
309 .It Dv OSMTPD_PHASE_LINK_AUTH
310 .Nm osmtpd_register_report_auth
311 .It Dv OSMTPD_PHASE_TX_BEGIN
312 .Nm osmtpd_register_report_begin
313 .It Dv OSMTPD_PHASE_TX_MAIL
314 .Nm osmtpd_register_report_mail
315 .It Dv OSMTPD_PHASE_TX_RCPT
316 .Nm osmtpd_register_report_rcpt
317 .It Dv OSMTPD_PHASE_TX_ENVELOPE
318 .Nm osmtpd_register_report_envelope
319 .It Dv OSMTPD_PHASE_TX_DATA
320 .Nm osmtpd_register_report_data
321 .It Dv OSMTPD_PHASE_TX_COMMIT
322 .Nm osmtpd_register_report_commit
323 .It Dv OSMTPD_PHASE_TX_ROLLBACK
324 .Nm osmtpd_register_report_rollback
325 .It Dv OSMTPD_PHASE_PROTOCOL_CLIENT
326 .Nm osmtpd_register_report_client
327 .It Dv OSMTPD_PHASE_PROTOCOL_SERVER
328 .Nm osmtpd_register_report_server
329 .It Dv OSMTPD_PHASE_FILTER_RESPONSE
330 .Nm osmtpd_register_report_response
331 .It Dv OSMTPD_PHASE_TIMEOUT .
332 .Nm osmtpd_register_report_timeout
334 .It Vt int Va version_major
335 The major version number of the protocol.
336 Most filters don't need this information.
337 .It Vt int Va version_minor
338 The minor version number of the protocol.
339 Most filters don't need this information.
340 .It Vt "struct timespec" Va tm
341 The time the event was triggered inside
343 .It Vt int Va incoming
344 Set to 1 if the event was based on an incoming connection, 0 if it's an outgoing
347 .Nm osmtpd_register_filter
348 class of functions is always based on incoming connections.
349 .Nm osmtpd_register_report
350 can be both incoming and outgoing.
351 .It Vt uint64_t Va reqid
352 The request ID of the connection the event was issued on.
353 This value can be useful for logging.
354 Filters in need of filter specific data can use
355 .Nm osmtpd_local_session
358 .It Vt uint64_t Va token
359 The filter specific token.
360 Most filters don't need this information.
361 .It Vt "struct sockaddr_storage" Va src
362 The source address and port of the connection.
363 This needs to be cast to the appropriate sockaddr type based on the
366 It can have the following families:
371 To use this attribute, initialize
374 .Dv OSMTPD_NEED_SRC .
375 If not available the entire attribute is zeroed out.
376 .It Vt "struct sockaddr_storage" Va dst
377 The destination address and port of the connection.
378 This needs to be cast to the appropriate sockaddr type based on the
381 It can have the following families:
386 To use this attribute, initialize
389 .Dv OSMTPD_NEED_DST .
390 If not available the entire attribute is zeroed out.
392 The reverse DNS hostname of the connection.
393 To use this attribute, initialize
396 .Dv OSMTPD_NEED_RDNS .
397 If not available the attribute is set to
399 .It Vt enum osmtpd_status Va fcrdns
400 Whether the reverse DNS hostname is forward confirmed.
401 To use this attribute, initialize
404 .Dv OSMTPD_NEED_FCRDNS .
405 If not available the attribute is set to
406 .Dv OSMTPD_STATUS_TEMPFAIL .
407 .It Vt char Va *identity
408 The identity of the remote host as presented by the HELO or EHLO SMTP command.
409 To use this attribute, initialize
412 .Dv OSMTPD_NEED_IDENTITY .
413 If not available the attribute is set to
415 .It Vt char Va *ciphers
416 The ciphers used during
417 .Po start Pc Ns tls .
418 To use this attribute, initialize
421 .Dv OSMTPD_NEED_CIPHERS .
422 If not available the attribute is set to
424 .It Vt uint32_t Va msgid
425 The message ID of the current message being handled in the SMTP transaction.
426 This value can be useful for logging.
428 needs to be initialized with
429 .Dv OSMTPD_NEED_MSGID .
430 If not available the attribute is set to
432 Filters in need of filter specific data can use
433 .Nm osmtpd_local_message
436 .It Vt char Va *username
437 The username with which the session was successfully authenticated.
439 needs to be initialized with
440 .DV OSMTPD_NEED_USERNAME .
441 If not available or authentication failed is set to
443 .It Vt char Va *mailfrom
444 The envelope MAIL FROM address in the SMTP transaction.
446 needs to be initialized with
447 .Dv OSMTPD_NEED_MAILFROM .
448 If not available the attribute is set to
450 .It Vt char Va **rcptto
451 The envelope RCPT TO address in the SMTP transaction.
453 needs to be initialized with
454 .Dv OSMTPD_NEED_RCPTTO .
455 This attribute is a NULL-terminated array of address strings.
456 If not available the first element in the array is set to
458 .It Vt uint64_t Va evpid
459 The envelope ID we're currently working on.
461 needs to be initialized with
462 .Dv OSMTPD_NEED_EVPID .
463 If not available the attribute is set to
465 .It Vt void Va *local_session
466 Any filter specific data that needs to be stored during the session.
467 This is initialized on
472 .Nm osmtpd_local_session .
473 .It Vt void Va *local_message
474 Any filter specific data that needs to be stored during the message transaction.
475 This is initialized on
480 .Nm osmtpd_local_message .
484 .Nm osmtpd_register_filter
485 class of functions must call one of
486 .Nm osmtpd_filter_proceed ,
487 .Nm osmtpd_filter_rewrite ,
488 .Nm osmtpd_filter_reject
490 .Nm osmtpd_filter_disconnect .
491 This can be done either in the callback function itself, or at a later moment
492 through another callback.
493 Note that the session stalls until the
497 Exceptions to the above reply options are:
499 .Bl -bullet -compact -width Ds
501 .Nm osmtpd_register_filter_connect Ns 's
503 .Nm osmtpd_register_filter
504 functions' callbacks without argument can't use
505 .Nm osmtpd_filter_rewrite .
507 .Nm osmtpd_register_filter_dataline Ns 's
508 callback can only use osmtpd_filter_dataline.
514 can be used as a standin for
518 without printing the program name to stderr.
525 API first appeared in
528 .An Martijn van Duren Aq Mt martijn@openbsd.org