#include "lib.h"
#include "str.h"
+#include "array.h"
#include "smtp-syntax.h"
#include "smtp-server-private.h"
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);
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;
}
#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"
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;