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_reset ,
42 .Nm osmtpd_register_report_begin ,
43 .Nm osmtpd_register_report_mail ,
44 .Nm osmtpd_register_report_rcpt ,
45 .Nm osmtpd_register_report_envelope ,
46 .Nm osmtpd_register_report_data ,
47 .Nm osmtpd_register_report_commit ,
48 .Nm osmtpd_register_report_rollback ,
49 .Nm osmtpd_register_report_client ,
50 .Nm osmtpd_register_report_server ,
51 .Nm osmtpd_register_report_response ,
52 .Nm osmtpd_register_report_timeout ,
53 .Nm osmtpd_local_session ,
54 .Nm osmtpd_local_message ,
56 .Nm osmtpd_filter_proceed ,
57 .Nm osmtpd_filter_reject ,
58 .Nm osmtpd_filter_disconnect ,
59 .Nm osmtpd_filter_rewrite ,
60 .Nm osmtpd_filter_dataline ,
74 .Fo osmtpd_register_filter_connect
75 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *hostname, struct sockaddr_storage *ss)"
78 .Fo osmtpd_register_filter_helo
79 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *helo)"
82 .Fo osmtpd_register_filter_ehlo
83 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *ehlo)"
86 .Fo osmtpd_register_filter_starttls
87 .Fa "int (*cb)(struct osmtpd_ctx *ctx)"
90 .Fo osmtpd_register_filter_auth
91 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *auth)"
94 .Fo osmtpd_register_filter_mailfrom
95 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *from)"
98 .Fo osmtpd_register_filter_rcptto
99 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *rcpt)"
102 .Fo osmtpd_register_filter_data
103 .Fa "int (*cb)(struct osmtpd_ctx *ctx)"
106 .Fo osmtpd_register_filter_dataline
107 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *line)"
110 .Fo osmtpd_register_filter_rset
111 .Fa "int (*cb)(struct osmtpd_ctx *ctx)"
114 .Fo osmtpd_register_filter_quit
115 .Fa "int (*cb)(struct osmtpd_ctx *ctx)"
118 .Fo osmtpd_register_filter_noop
119 .Fa "int (*cb)(struct osmtpd_ctx *ctx)"
122 .Fo osmtpd_register_filter_help
123 .Fa "int (*cb)(struct osmtpd_ctx *ctx)"
126 .Fo osmtpd_register_filter_wiz
127 .Fa "int (*cb)(struct osmtpd_ctx *ctx)"
130 .Fo osmtpd_register_filter_commit
131 .Fa "int (*cb)(struct osmtpd_ctx *ctx)"
134 .Fo osmtpd_register_report_connect
136 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *rdns, enum osmtpd_status fcrdns, struct sockaddr_storage *src, struct sockaddr_storage *dst)"
139 .Fo osmtpd_register_report_disconnect
141 .Fa "int (*cb)(struct osmtpd_ctx *ctx)"
144 .Fo osmtpd_register_report_identify
146 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *identity)"
149 .Fo osmtpd_register_report_tls
151 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *ciphers)"
154 .Fo osmtpd_register_report_auth
156 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *username, enum osmtpd_auth_status status)"
159 .Fo osmtpd_register_report_reset
161 .Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
164 .Fo osmtpd_register_report_begin
166 .Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
169 .Fo osmtpd_register_report_mail
171 .Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *mailfrom, enum osmtpd_status status)"
174 .Fo osmtpd_register_report_rcpt
176 .Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, const char *rcptto, enum osmtpd_status status)"
179 .Fo osmtpd_register_report_envelope
181 .Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, uint64_t evpid)"
184 .Fo osmtpd_register_report_data
186 .Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, enum osmtpd_status status)"
189 .Fo osmtpd_register_report_commit
191 .Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid, size_t msgsz)"
194 .Fo osmtpd_register_report_rollback
196 .Fa "int (*cb)(struct osmtpd_ctx *ctx, uint32_t msgid)"
199 .Fo osmtpd_register_report_client
201 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *cmd)"
204 .Fo osmtpd_register_report_server
206 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *resp)"
209 .Fo osmtpd_register_report_response
211 .Fa "int (*cb)(struct osmtpd_ctx *ctx, const char *resp)"
214 .Fo osmtpd_register_report_timeout
216 .Fa "int (*cb)(struct osmtpd_ctx *ctx)"
219 .Fo osmtpd_local_session
220 .Fa "void *(*oncreate)(struct osmtpd_ctx *ctx)"
221 .Fa "void (*ondelete)(struct osmtpd_ctx *ctx, void *data)"
224 .Fo osmtpd_local_message
225 .Fa "void *(*oncreate)(struct osmtpd_ctx *ctx)"
226 .Fa "void (*ondelete)(struct osmtpd_ctx *ctx, void *data)"
229 .Fn osmtpd_need "int needs"
231 .Fn osmtpd_filter_proceed "struct osmtpd_ctx *ctx"
233 .Fn osmtpd_filter_reject "struct osmtpd_ctx *ctx" "int error" "const char *msg" ...
235 .Fn osmtpd_filter_disconnect "struct osmtpd_ctx *ctx" "const char *msg" ...
237 .Fn osmtpd_filter_rewrite "struct osmtpd_ctx *ctx" "const char *value" ...
239 .Fn osmtpd_filter_dataline "struct osmtpd_ctx *ctx" "const char *line" ...
243 .Fn osmtpd_err "int eval" "const char *fmt" ...
245 .Fn osmtpd_errx "int eval" "const char *fmt" ...
247 .Fn osmtpd_warn "struct osmtpd_ctx *ctx" "const char *fmt" ...
249 .Fn osmtpd_warnx "struct osmtpd_ctx *ctx" "const char *fmt" ...
251 .Fn osmtpd_info "struct osmtpd_ctx *ctx" "const char *fmt" ...
253 .Fn osmtpd_debug "struct osmtpd_ctx *ctx" "const char *fmt" ...
257 API is an event based interface for writing
260 Filter and report callbacks are registered via the
262 class of functions, followed by
264 A callback should return
266 in the case of success, or
268 in the case of error which leads to disconnect of this session.
271 starts the communication with the server and transforms network queries to
274 .Xr event_dispatch 3 ,
275 which allows filters to be written fully asynchronously.
279 gets at least a pointer of the type
280 .Fa struct osmtpd_ctx .
281 It contains the following elements:
283 .It Fa "enum osmtpd_type type"
284 The type of request being made.
285 The possible values are
286 .Dv OSMTPD_TYPE_FILTER
288 .Dv OSMTPD_TYPE_REPORT .
289 .It Vt "enum osmtpd_phase" Va phase
290 The phase in the transaction which triggered the callback.
291 The following values match their respective
294 .Bl -tag -compact -width OSMTPD_PHASE_LINK_DISCONNECT
295 .It Dv OSMTPD_PHASE_CONNECT
296 .Nm osmtpd_register_filter_connect
297 .It Dv OSMTPD_PHASE_HELO
298 .Nm osmtpd_register_filter_helo
299 .It Dv OSMTPD_PHASE_EHLO
300 .Nm osmtpd_register_filter_ehlo
301 .It Dv OSMTPD_PHASE_STARTTLS
302 .Nm osmtpd_register_filter_starttls
303 .It Dv OSMTPD_PHASE_AUTH
304 .Nm osmtpd_register_filter_auth
305 .It Dv OSMTPD_PHASE_MAIL_FROM
306 .Nm osmtpd_register_filter_mailfrom
307 .It Dv OSMTPD_PHASE_RCPT_TO
308 .Nm osmtpd_register_filter_rcptto
309 .It Dv OSMTPD_PHASE_DATA
310 .Nm osmtpd_register_filter_data
311 .It Dv OSMTPD_PHASE_DATA_LINE
312 .Nm osmtpd_register_filter_dataline
313 .It Dv OSMTPD_PHASE_RSET
314 .Nm osmtpd_register_filter_rset
315 .It Dv OSMTPD_PHASE_QUIT
316 .Nm osmtpd_register_filter_quit
317 .It Dv OSMTPD_PHASE_NOOP
318 .Nm osmtpd_register_filter_noop
319 .It Dv OSMTPD_PHASE_HELP
320 .Nm osmtpd_register_filter_help
321 .It Dv OSMTPD_PHASE_WIZ
322 .Nm osmtpd_register_filter_wiz
323 .It Dv OSMTPD_PHASE_COMMIT
324 .Nm osmtpd_register_filter_commit
325 .It Dv OSMTPD_PHASE_LINK_CONNECT
326 .Nm osmtpd_register_report_connect
327 .It OSMTPD_PHASE_LINK_DISCONNECT
328 .Nm osmtpd_register_report_disconnect
329 .It Dv OSMTPD_PHASE_LINK_IDENTIFY
330 .Nm osmtpd_register_report_identify
331 .It Dv OSMTPD_PHASE_LINK_TLS
332 .Nm osmtpd_register_report_tls
333 .It Dv OSMTPD_PHASE_LINK_AUTH
334 .Nm osmtpd_register_report_auth
335 .It Dv OSMTPD_PHASE_TX_RESET
336 .Nm osmtpd_register_report_reset
337 .It Dv OSMTPD_PHASE_TX_BEGIN
338 .Nm osmtpd_register_report_begin
339 .It Dv OSMTPD_PHASE_TX_MAIL
340 .Nm osmtpd_register_report_mail
341 .It Dv OSMTPD_PHASE_TX_RCPT
342 .Nm osmtpd_register_report_rcpt
343 .It Dv OSMTPD_PHASE_TX_ENVELOPE
344 .Nm osmtpd_register_report_envelope
345 .It Dv OSMTPD_PHASE_TX_DATA
346 .Nm osmtpd_register_report_data
347 .It Dv OSMTPD_PHASE_TX_COMMIT
348 .Nm osmtpd_register_report_commit
349 .It Dv OSMTPD_PHASE_TX_ROLLBACK
350 .Nm osmtpd_register_report_rollback
351 .It Dv OSMTPD_PHASE_PROTOCOL_CLIENT
352 .Nm osmtpd_register_report_client
353 .It Dv OSMTPD_PHASE_PROTOCOL_SERVER
354 .Nm osmtpd_register_report_server
355 .It Dv OSMTPD_PHASE_FILTER_RESPONSE
356 .Nm osmtpd_register_report_response
357 .It Dv OSMTPD_PHASE_TIMEOUT .
358 .Nm osmtpd_register_report_timeout
360 .It Vt int Va version_major
361 The major version number of the protocol.
362 Most filters don't need this information.
363 .It Vt int Va version_minor
364 The minor version number of the protocol.
365 Most filters don't need this information.
366 .It Vt "struct timespec" Va tm
367 The time the event was triggered inside
369 .It Vt int Va incoming
370 Set to 1 if the event was based on an incoming connection, 0 if it's an outgoing
373 .Nm osmtpd_register_filter
374 class of functions is always based on incoming connections.
375 .Nm osmtpd_register_report
376 can be both incoming and outgoing.
377 .It Vt uint64_t Va reqid
378 The request ID of the connection the event was issued on.
379 This value can be useful for logging.
380 Filters in need of filter specific data can use
381 .Nm osmtpd_local_session
384 .It Vt uint64_t Va token
385 The filter specific token.
386 Most filters don't need this information.
387 .It Vt "struct sockaddr_storage" Va src
388 The source address and port of the connection.
389 This needs to be cast to the appropriate sockaddr type based on the
392 It can have the following families:
397 To use this attribute, initialize
400 .Dv OSMTPD_NEED_SRC .
401 If not available the entire attribute is zeroed out.
402 .It Vt "struct sockaddr_storage" Va dst
403 The destination address and port of the connection.
404 This needs to be cast to the appropriate sockaddr type based on the
407 It can have the following families:
412 To use this attribute, initialize
415 .Dv OSMTPD_NEED_DST .
416 If not available the entire attribute is zeroed out.
418 The reverse DNS hostname of the connection.
419 To use this attribute, initialize
422 .Dv OSMTPD_NEED_RDNS .
423 If not available the attribute is set to
425 .It Vt enum osmtpd_status Va fcrdns
426 Whether the reverse DNS hostname is forward confirmed.
427 To use this attribute, initialize
430 .Dv OSMTPD_NEED_FCRDNS .
431 If not available the attribute is set to
432 .Dv OSMTPD_STATUS_TEMPFAIL .
433 .It Vt char Va *identity
434 The identity of the remote host as presented by the HELO or EHLO SMTP command.
435 To use this attribute, initialize
438 .Dv OSMTPD_NEED_IDENTITY .
439 If not available the attribute is set to
441 .It Vt char Va *ciphers
442 The ciphers used during
443 .Po start Pc Ns tls .
444 To use this attribute, initialize
447 .Dv OSMTPD_NEED_CIPHERS .
448 If not available the attribute is set to
450 .It Vt uint32_t Va msgid
451 The message ID of the current message being handled in the SMTP transaction.
452 This value can be useful for logging.
454 needs to be initialized with
455 .Dv OSMTPD_NEED_MSGID .
456 If not available the attribute is set to
458 Filters in need of filter specific data can use
459 .Nm osmtpd_local_message
462 .It Vt char Va *username
463 The username with which the session was successfully authenticated.
465 needs to be initialized with
466 .DV OSMTPD_NEED_USERNAME .
467 If not available or authentication failed is set to
469 .It Vt char Va *mailfrom
470 The envelope MAIL FROM address in the SMTP transaction.
472 needs to be initialized with
473 .Dv OSMTPD_NEED_MAILFROM .
474 If not available the attribute is set to
476 .It Vt char Va **rcptto
477 The envelope RCPT TO address in the SMTP transaction.
479 needs to be initialized with
480 .Dv OSMTPD_NEED_RCPTTO .
481 This attribute is a NULL-terminated array of address strings.
482 If not available the first element in the array is set to
484 .It Vt uint64_t Va evpid
485 The envelope ID we're currently working on.
487 needs to be initialized with
488 .Dv OSMTPD_NEED_EVPID .
489 If not available the attribute is set to
491 .It Vt void Va *local_session
492 Any filter specific data that needs to be stored during the session.
493 This is initialized on
498 .Nm osmtpd_local_session .
499 .It Vt void Va *local_message
500 Any filter specific data that needs to be stored during the message transaction.
501 This is initialized on
506 .Nm osmtpd_local_message .
510 .Nm osmtpd_register_filter
511 class of functions must call one of
512 .Nm osmtpd_filter_proceed ,
513 .Nm osmtpd_filter_rewrite ,
514 .Nm osmtpd_filter_reject
516 .Nm osmtpd_filter_disconnect .
517 This can be done either in the callback function itself, or at a later moment
518 through another callback.
519 Note that the session stalls until the
523 Exceptions to the above reply options are:
525 .Bl -bullet -compact -width Ds
527 .Nm osmtpd_register_filter_connect Ns 's
529 .Nm osmtpd_register_filter
530 functions' callbacks without argument can't use
531 .Nm osmtpd_filter_rewrite .
533 .Nm osmtpd_register_filter_dataline Ns 's
534 callback can only use osmtpd_filter_dataline.
544 are used for logging to
561 prints the request ID on the logline when
571 API first appeared in
574 .An Martijn van Duren Aq Mt martijn@openbsd.org