Skip to content

Commit

Permalink
lib-smtp: server: Add support for adding (non-standard) extra capabil…
Browse files Browse the repository at this point in the history
…ities.
  • Loading branch information
stephanbosch committed Dec 12, 2018
1 parent 6813a27 commit 7611991
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 10 deletions.
52 changes: 42 additions & 10 deletions src/lib-smtp/smtp-server-cmd-helo.c
Expand Up @@ -2,6 +2,7 @@

#include "lib.h"
#include "str.h"
#include "array.h"
#include "smtp-syntax.h"

#include "smtp-server-private.h"
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}

Expand Down
44 changes: 44 additions & 0 deletions src/lib-smtp/smtp-server-connection.c
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/lib-smtp/smtp-server-private.h
Expand Up @@ -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 */

Expand Down
3 changes: 3 additions & 0 deletions src/lib-smtp/smtp-server.h
Expand Up @@ -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);
Expand Down

0 comments on commit 7611991

Please sign in to comment.