From: Stephan Bosch Date: Sat, 3 Nov 2018 10:18:46 +0000 (+0100) Subject: lib-smtp: server: Add support for adding (non-standard) extra capabilities. X-Git-Tag: 2.3.9~983 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7611991db340080418167cf72abbe4ee018806a4;p=thirdparty%2Fdovecot%2Fcore.git lib-smtp: server: Add support for adding (non-standard) extra capabilities. --- diff --git a/src/lib-smtp/smtp-server-cmd-helo.c b/src/lib-smtp/smtp-server-cmd-helo.c index c5e734615c..4b0584c1b0 100644 --- a/src/lib-smtp/smtp-server-cmd-helo.c +++ b/src/lib-smtp/smtp-server-cmd-helo.c @@ -2,6 +2,7 @@ #include "lib.h" #include "str.h" +#include "array.h" #include "smtp-syntax.h" #include "smtp-server-private.h" @@ -129,8 +130,29 @@ void smtp_server_cmd_helo(struct smtp_server_cmd_ctx *cmd, struct smtp_server_reply * smtp_server_cmd_ehlo_reply_create(struct smtp_server_cmd_ctx *cmd) { + static struct { + const char *name; + void (*add)(struct smtp_server_reply *reply); + } standard_caps[] = { + /* Sorted alphabetically */ + { "8BITMIME", smtp_server_reply_ehlo_add_8bitmime }, + { "BINARYMIME", smtp_server_reply_ehlo_add_binarymime }, + { "CHUNKING", smtp_server_reply_ehlo_add_chunking }, + { "DSN", smtp_server_reply_ehlo_add_dsn }, + { "ENHANCEDSTATUSCODES", + smtp_server_reply_ehlo_add_enhancedstatuscodes }, + { "PIPELINING", smtp_server_reply_ehlo_add_pipelining }, + { "SIZE", smtp_server_reply_ehlo_add_size }, + { "STARTTLS", smtp_server_reply_ehlo_add_starttls }, + { "VRFY", smtp_server_reply_ehlo_add_vrfy }, + { "XCLIENT", smtp_server_reply_ehlo_add_xclient } + }; + const unsigned int standard_caps_count = N_ELEMENTS(standard_caps); + struct smtp_server_connection *conn = cmd->conn; struct smtp_server_command *command = cmd->cmd; struct smtp_server_cmd_helo *helo_data = command->data; + const struct smtp_capability_extra *extra_caps = NULL; + unsigned int extra_caps_count, i, j; struct smtp_server_reply *reply; i_assert(cmd->cmd->reg->func == smtp_server_cmd_ehlo); @@ -139,17 +161,27 @@ smtp_server_cmd_ehlo_reply_create(struct smtp_server_cmd_ctx *cmd) if (helo_data->helo.old_smtp) return reply; - smtp_server_reply_ehlo_add_8bitmime(reply); - smtp_server_reply_ehlo_add_binarymime(reply); - smtp_server_reply_ehlo_add_chunking(reply); - smtp_server_reply_ehlo_add_dsn(reply); - smtp_server_reply_ehlo_add_enhancedstatuscodes(reply); - smtp_server_reply_ehlo_add_pipelining(reply); - smtp_server_reply_ehlo_add_size(reply); - smtp_server_reply_ehlo_add_starttls(reply); - smtp_server_reply_ehlo_add_vrfy(reply); - smtp_server_reply_ehlo_add_xclient(reply); + extra_caps_count = 0; + if (array_is_created(&conn->extra_capabilities)) { + extra_caps = array_get(&conn->extra_capabilities, + &extra_caps_count); + } + i = j = 0; + while (i < standard_caps_count || j < extra_caps_count) { + if (i < standard_caps_count && + (j >= extra_caps_count || + strcasecmp(standard_caps[i].name, + extra_caps[j].name) < 0)) { + standard_caps[i].add(reply); + i++; + } else { + smtp_server_reply_ehlo_add_params( + reply, extra_caps[j].name, + extra_caps[j].params); + j++; + } + } return reply; } diff --git a/src/lib-smtp/smtp-server-connection.c b/src/lib-smtp/smtp-server-connection.c index a2b3f81dfc..131e390f22 100644 --- a/src/lib-smtp/smtp-server-connection.c +++ b/src/lib-smtp/smtp-server-connection.c @@ -14,6 +14,7 @@ #include "master-service.h" #include "master-service-ssl.h" +#include "smtp-syntax.h" #include "smtp-reply-parser.h" #include "smtp-command-parser.h" #include "smtp-server-private.h" @@ -1436,6 +1437,49 @@ void smtp_server_connection_set_capabilities( conn->set.capabilities = capabilities; } +void smtp_server_connection_add_extra_capability( + struct smtp_server_connection *conn, + const struct smtp_capability_extra *cap) +{ + const struct smtp_capability_extra *cap_idx; + struct smtp_capability_extra cap_new; + unsigned int insert_idx; + pool_t pool = conn->pool; + + /* Avoid committing protocol errors */ + i_assert(smtp_ehlo_keyword_is_valid(cap->name)); + i_assert(smtp_ehlo_params_are_valid(cap->params)); + + /* Cannot override standard capabiltiies */ + i_assert(smtp_capability_find_by_name(cap->name) + == SMTP_CAPABILITY_NONE); + + if (!array_is_created(&conn->extra_capabilities)) + p_array_init(&conn->extra_capabilities, pool, 4); + + /* Keep array sorted */ + insert_idx = array_count(&conn->extra_capabilities); + array_foreach(&conn->extra_capabilities, cap_idx) { + int cmp = strcasecmp(cap_idx->name, cap->name); + + /* Prohibit duplicates */ + i_assert(cmp != 0); + + if (cmp > 0) { + insert_idx = array_foreach_idx( + &conn->extra_capabilities, cap_idx); + break; + } + } + + i_zero(&cap_new); + cap_new.name = p_strdup(pool, cap->name); + if (cap->params != NULL) + cap_new.params = p_strarray_dup(pool, cap->params); + + array_insert(&conn->extra_capabilities, insert_idx, &cap_new, 1); +} + void *smtp_server_connection_get_context(struct smtp_server_connection *conn) { return conn->context; diff --git a/src/lib-smtp/smtp-server-private.h b/src/lib-smtp/smtp-server-private.h index 70f8762797..746c29f619 100644 --- a/src/lib-smtp/smtp-server-private.h +++ b/src/lib-smtp/smtp-server-private.h @@ -144,6 +144,7 @@ struct smtp_server_connection { struct smtp_server_settings set; + ARRAY(struct smtp_capability_extra) extra_capabilities; ARRAY_TYPE(const_string) mail_param_extensions; /* NULL-terminated */ ARRAY_TYPE(const_string) rcpt_param_extensions; /* NULL-terminated */ diff --git a/src/lib-smtp/smtp-server.h b/src/lib-smtp/smtp-server.h index ff9ee92f5e..1c6ff697df 100644 --- a/src/lib-smtp/smtp-server.h +++ b/src/lib-smtp/smtp-server.h @@ -427,6 +427,9 @@ void smtp_server_connection_get_proxy_data(struct smtp_server_connection *conn, void smtp_server_connection_set_capabilities( struct smtp_server_connection *conn, enum smtp_capability capabilities); +void smtp_server_connection_add_extra_capability( + struct smtp_server_connection *conn, + const struct smtp_capability_extra *cap); void smtp_server_connection_register_mail_param( struct smtp_server_connection *conn, const char *param);