I'm not sure how you like patches so here's a crude git diff patch of my first attempt :-)
diff --git a/Symbols.list b/Symbols.list index a73487d..360ae2a 100644 --- a/Symbols.list +++ b/Symbols.list @@ -14,6 +14,7 @@ osmtpd_register_filter_noop osmtpd_register_filter_help osmtpd_register_filter_wiz osmtpd_register_filter_commit +osmtpd_register_report_auth osmtpd_register_report_connect osmtpd_register_report_disconnect osmtpd_register_report_identify diff --git a/opensmtpd.c b/opensmtpd.c index 71b0691..7953973 100644 --- a/opensmtpd.c +++ b/opensmtpd.c @@ -72,6 +72,8 @@ static void osmtpd_connect(struct osmtpd_callback *, struct osmtpd_ctx *, char *, char *); static void osmtpd_identify(struct osmtpd_callback *, struct osmtpd_ctx *, char *, char *); +static void osmtpd_link_auth(struct osmtpd_callback *, struct osmtpd_ctx *, + char *, char *); static void osmtpd_link_connect(struct osmtpd_callback *, struct osmtpd_ctx *, char *, char *); static void osmtpd_link_disconnect(struct osmtpd_callback *, @@ -241,6 +243,15 @@ static struct osmtpd_callback osmtpd_callbacks[] = { 0, 0 }, + { + OSMTPD_TYPE_REPORT, + OSMTPD_PHASE_LINK_AUTH, + 1, + osmtpd_link_auth, + NULL, + 0, + 0 + }, { OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_CONNECT, @@ -829,6 +840,16 @@ osmtpd_register_report_timeout(int incoming, void (*cb)(struct osmtpd_ctx *)) incoming, 0, NULL); } +void +osmtpd_register_report_auth(int incoming, void (*cb)(struct osmtpd_ctx *, + const char * username, enum osmtpd_auth_result)) +{ + osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_AUTH, + incoming, 0, (void *)cb); + osmtpd_register(OSMTPD_TYPE_REPORT, OSMTPD_PHASE_LINK_DISCONNECT, + incoming, 0, NULL); +} + void osmtpd_local_session(void *(*oncreate)(struct osmtpd_ctx *), void (*ondelete)(struct osmtpd_ctx *, void *)) @@ -1267,6 +1288,34 @@ osmtpd_identify(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx, f(ctx, identity); } +static void +osmtpd_link_auth(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx, + char *params, char *linedup) +{ + enum osmtpd_auth_result auth_res; + char * username, *end; + void (*f)(struct osmtpd_ctx *, const char *, enum osmtpd_auth_result); + + if ((end = strchr(params, '|')) == NULL) + osmtpd_errx(1, "Invalid line received: missing username: %s", + linedup); + end++[0] = '\0'; + username = params; + params = end; + if (strcmp(params, "pass") == 0) + auth_res = OSMTPD_AUTH_PASS; + else if (strcmp(params, "fail") == 0) + auth_res = OSMTPD_AUTH_FAIL; + else if (strcmp(params, "error") == 0) + auth_res = OSMTPD_AUTH_ERROR; + else + osmtpd_errx(1, "Invalid line received: invalid result: %s", + linedup); + + if ((f = cb->cb) != NULL) + f(ctx, username, auth_res); +} + static void osmtpd_link_connect(struct osmtpd_callback *cb, struct osmtpd_ctx *ctx, char *params, char *linedup) @@ -1870,6 +1919,8 @@ osmtpd_strtophase(const char *phase, const char *linedup) return OSMTPD_PHASE_WIZ; if (strcmp(phase, "commit") == 0) return OSMTPD_PHASE_COMMIT; + if (strcmp(phase, "link-auth") == 0) + return OSMTPD_PHASE_LINK_AUTH; if (strcmp(phase, "link-connect") == 0) return OSMTPD_PHASE_LINK_CONNECT; if (strcmp(phase, "link-disconnect") == 0) @@ -1951,6 +2002,8 @@ osmtpd_phasetostr(enum osmtpd_phase phase) return "wiz"; case OSMTPD_PHASE_COMMIT: return "commit"; + case OSMTPD_PHASE_LINK_AUTH: + return "link-auth"; case OSMTPD_PHASE_LINK_CONNECT: return "link-connect"; case OSMTPD_PHASE_LINK_DISCONNECT: diff --git a/opensmtpd.h b/opensmtpd.h index eef3237..d59d220 100644 --- a/opensmtpd.h +++ b/opensmtpd.h @@ -13,6 +13,7 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <stdint.h> #include <sys/socket.h> #ifndef __dead @@ -49,6 +50,7 @@ enum osmtpd_phase { OSMTPD_PHASE_HELP, OSMTPD_PHASE_WIZ, OSMTPD_PHASE_COMMIT, + OSMTPD_PHASE_LINK_AUTH, OSMTPD_PHASE_LINK_CONNECT, OSMTPD_PHASE_LINK_DISCONNECT, OSMTPD_PHASE_LINK_GREETING, @@ -67,6 +69,12 @@ enum osmtpd_phase { OSMTPD_PHASE_TIMEOUT }; +enum osmtpd_auth_result { + OSMTPD_AUTH_PASS, + OSMTPD_AUTH_FAIL, + OSMTPD_AUTH_ERROR +}; + #define OSMTPD_NEED_SRC 1 << 0 #define OSMTPD_NEED_DST 1 << 1 #define OSMTPD_NEED_RDNS 1 << 2 @@ -156,6 +164,8 @@ void osmtpd_register_report_server(int, void (*)(struct osmtpd_ctx *, void osmtpd_register_report_response(int, void (*)(struct osmtpd_ctx *, const char *)); void osmtpd_register_report_timeout(int, void (*)(struct osmtpd_ctx *)); +void osmtpd_register_report_auth(int, void (*)(struct osmtpd_ctx *, + const char *, enum osmtpd_auth_result)); void osmtpd_local_session(void *(*)(struct osmtpd_ctx *), void (*)(struct osmtpd_ctx *, void *)); void osmtpd_local_message(void *(*)(struct osmtpd_ctx *), On Tue, Oct 18 2022, Martijn van Duren <opensm...@list.imperialat.at> wrote: > There's no particular reason why I didn't implement it. > It should be relatively straight forward, if you have a patch > which is up to par I'm willing to add it to my repo. > > martijn@ > > On Tue, 2022-10-18 at 10:34 +0200, Martin Kjær Jørgensen wrote: >> Hello, >> >> I came across your libopensmtpd while developing a relative simple >> reporting plugin for smtpd. I see the API has alot of existing calls, >> but I'm basically missing the following function or something like it; >> >> void osmtpd_register_report_auth(int, void (*)(struct osmtpd_ctx *, >> const char * username, enum osmtpd_auth status)); >> >> I wan't to monitor amount of failed auth attempts and block IP/port >> temporarily based on statistics. >> >> Do you consider it a bad or unneeded feature, or would you accept the >> feature if I write a patch; >> >> /Martin >>