}
static void
-cmd_auth_set_master_data_prefix(struct submission_client *subm_client)
+cmd_auth_set_master_data_prefix(struct submission_client *subm_client,
+ const char *mail_params) ATTR_NULL(2)
{
struct client *client = &subm_client->common;
struct smtp_server_helo_data *helo;
buffer_append(buf, proxy.helo, strlen(proxy.helo));
buffer_append_c(buf, '\0');
+ /* Pass MAIL command to post-login service if any. */
+ if (mail_params != NULL) {
+ buffer_append(buf, "MAIL ", 5);
+ buffer_append(buf, mail_params, strlen(mail_params));
+ buffer_append(buf, "\r\n", 2);
+ }
+
i_free(client->master_data_prefix);
client->master_data_prefix_len = buf->used;
client->master_data_prefix = buffer_free_without_data(&buf);
struct submission_client *subm_client = conn_ctx;
struct client *client = &subm_client->common;
- cmd_auth_set_master_data_prefix(subm_client);
+ cmd_auth_set_master_data_prefix(subm_client, NULL);
i_assert(subm_client->pending_auth == NULL);
subm_client->pending_auth = cmd;
(void)client_auth_begin(client, data->sasl_mech, data->initial_response);
return 0;
}
+
+void cmd_mail(struct smtp_server_cmd_ctx *cmd, const char *params)
+{
+ struct smtp_server_connection *conn = cmd->conn;
+ struct submission_client *subm_client =
+ smtp_server_connection_get_context(conn);
+ struct client *client = &subm_client->common;
+ enum submission_login_client_workarounds workarounds =
+ subm_client->set->parsed_workarounds;
+
+ if (HAS_NO_BITS(workarounds,
+ SUBMISSION_LOGIN_WORKAROUND_IMPLICIT_AUTH_EXTERNAL) ||
+ sasl_server_find_available_mech(client, "EXTERNAL") == NULL) {
+ smtp_server_command_fail(cmd->cmd, 530, "5.7.0",
+ "Authentication required.");
+ return;
+ }
+
+ e_debug(cmd->event,
+ "Performing implicit EXTERNAL authentication");
+
+ smtp_server_command_input_lock(cmd);
+
+ cmd_auth_set_master_data_prefix(subm_client, params);
+
+ i_assert(subm_client->pending_auth == NULL);
+ subm_client->pending_auth = cmd;
+
+ (void)client_auth_begin_implicit(client, "EXTERNAL", "=");
+}
int cmd_auth(void *conn_ctx, struct smtp_server_cmd_ctx *cmd,
struct smtp_server_cmd_auth *data);
+void cmd_mail(struct smtp_server_cmd_ctx *cmd, const char *params);
+
#endif
It's not very useful. */
smtp_server_set.no_state_in_reason = TRUE;
smtp_server = smtp_server_init(&smtp_server_set);
+ smtp_server_command_override(smtp_server, "MAIL", cmd_mail,
+ SMTP_SERVER_CMD_FLAG_PREAUTH);
}
static void submission_login_deinit(void)
DEF(STR, hostname),
DEF(SIZE, submission_max_mail_size),
+ DEF(STR, submission_client_workarounds),
DEF(STR, submission_backend_capabilities),
SETTING_DEFINE_LIST_END
.hostname = "",
.submission_max_mail_size = 0,
+ .submission_client_workarounds = "",
.submission_backend_capabilities = NULL
};
.struct_size = sizeof(struct submission_login_settings),
.parent_offset = SIZE_MAX,
-#ifndef CONFIG_BINARY
.check_func = submission_login_settings_check,
-#endif
.dependencies = submission_login_setting_dependencies
};
NULL
};
+/* <settings checks> */
+struct submission_login_client_workaround_list {
+ const char *name;
+ enum submission_login_client_workarounds num;
+};
+
+/* These definitions need to be kept in sync with equivalent definitions present
+ in src/submission/submission-settings.c. Workarounds that are not relevant
+ to the submission-login service are defined as 0 here to prevent "Unknown
+ workaround" errors below. */
+static const struct submission_login_client_workaround_list
+submission_login_client_workaround_list[] = {
+ { "whitespace-before-path", 0},
+ { "mailbox-for-path", 0 },
+ { "implicit-auth-external",
+ SUBMISSION_LOGIN_WORKAROUND_IMPLICIT_AUTH_EXTERNAL },
+ { NULL, 0 }
+};
+
+static int
+submission_login_settings_parse_workarounds(
+ struct submission_login_settings *set, const char **error_r)
+{
+ enum submission_login_client_workarounds client_workarounds = 0;
+ const struct submission_login_client_workaround_list *list;
+ const char *const *str;
+
+ str = t_strsplit_spaces(set->submission_client_workarounds, " ,");
+ for (; *str != NULL; str++) {
+ list = submission_login_client_workaround_list;
+ for (; list->name != NULL; list++) {
+ if (strcasecmp(*str, list->name) == 0) {
+ client_workarounds |= list->num;
+ break;
+ }
+ }
+ if (list->name == NULL) {
+ *error_r = t_strdup_printf(
+ "submission_client_workarounds: "
+ "Unknown workaround: %s", *str);
+ return -1;
+ }
+ }
+ set->parsed_workarounds = client_workarounds;
+ return 0;
+}
+
static bool
-submission_login_settings_check(void *_set, pool_t pool,
- const char **error_r ATTR_UNUSED)
+submission_login_settings_check(void *_set, pool_t pool ATTR_UNUSED,
+ const char **error_r)
{
struct submission_login_settings *set = _set;
+ if (submission_login_settings_parse_workarounds(set, error_r) < 0)
+ return FALSE;
+
+#ifndef CONFIG_BINARY
if (*set->hostname == '\0')
set->hostname = p_strdup(pool, my_hostdomain());
+#endif
return TRUE;
}
+/* </settings checks> */
#ifndef SUBMISSION_LOGIN_SETTINGS_H
#define SUBMISSION_LOGIN_SETTINGS_H
+/* <settings checks> */
+enum submission_login_client_workarounds {
+ SUBMISSION_LOGIN_WORKAROUND_IMPLICIT_AUTH_EXTERNAL = BIT(0),
+};
+/* </settings checks> */
+
struct submission_login_settings {
const char *hostname;
/* submission: */
uoff_t submission_max_mail_size;
+ const char *submission_client_workarounds;
const char *submission_backend_capabilities;
+
+ enum submission_login_client_workarounds parsed_workarounds;
};
extern const struct setting_parser_info *submission_login_setting_roots[];
static int
client_create_from_input(const struct mail_storage_service_input *input,
+ enum mail_auth_request_flags login_flags,
int fd_in, int fd_out, const buffer_t *input_buf,
const char **error_r)
{
struct mail_storage_service_user *user;
struct mail_user *mail_user;
struct submission_settings *set;
+ bool no_greeting = HAS_ALL_BITS(login_flags,
+ MAIL_AUTH_REQUEST_FLAG_IMPLICIT);
const char *errstr;
const char *helo = NULL;
struct smtp_proxy_data proxy_data;
}
(void)client_create(fd_in, fd_out, mail_user,
- user, set, helo, &proxy_data, data, data_len);
+ user, set, helo, &proxy_data, data, data_len,
+ no_greeting);
return 0;
}
input_buf = input_base64 == NULL ? NULL :
t_base64_decode_str(input_base64);
- if (client_create_from_input(&input, STDIN_FILENO, STDOUT_FILENO,
+ if (client_create_from_input(&input, 0, STDIN_FILENO, STDOUT_FILENO,
input_buf, &error) < 0)
i_fatal("%s", error);
}
buffer_create_from_const_data(&input_buf, login_client->data,
login_client->auth_req.data_size);
- if (client_create_from_input(&input, login_client->fd, login_client->fd,
+ if (client_create_from_input(&input, flags,
+ login_client->fd, login_client->fd,
&input_buf, &error) < 0) {
int fd = login_client->fd;
i_error("%s", error);
struct mail_storage_service_user *service_user,
const struct submission_settings *set, const char *helo,
const struct smtp_proxy_data *proxy_data,
- const unsigned char *pdata, unsigned int pdata_len)
+ const unsigned char *pdata, unsigned int pdata_len,
+ bool no_greeting)
{
enum submission_client_workarounds workarounds =
set->parsed_workarounds;
smtp_set.max_client_idle_time_msecs = CLIENT_IDLE_TIMEOUT_MSECS;
smtp_set.max_message_size = set->submission_max_mail_size;
smtp_set.rawlog_dir = set->rawlog_dir;
+ smtp_set.no_greeting = no_greeting;
smtp_set.debug = user->mail_debug;
if ((workarounds & SUBMISSION_WORKAROUND_WHITESPACE_BEFORE_PATH) != 0) {
struct mail_storage_service_user *service_user,
const struct submission_settings *set, const char *helo,
const struct smtp_proxy_data *proxy_data,
- const unsigned char *pdata, unsigned int pdata_len);
+ const unsigned char *pdata, unsigned int pdata_len,
+ bool no_greeting);
void client_destroy(struct client **client, const char *prefix,
const char *reason) ATTR_NULL(2, 3);
enum submission_client_workarounds num;
};
+/* These definitions need to be kept in sync with equivalent definitions present
+ in src/submission-login/submission-login-settings.c. Workarounds that are not
+ relevant to the submission service are defined as 0 here to prevent "Unknown
+ workaround" errors below. */
static const struct submission_client_workaround_list
submission_client_workaround_list[] = {
{ "whitespace-before-path",
SUBMISSION_WORKAROUND_WHITESPACE_BEFORE_PATH },
{ "mailbox-for-path",
SUBMISSION_WORKAROUND_MAILBOX_FOR_PATH },
+ { "implicit-auth-external", 0 },
{ NULL, 0 }
};