summaryrefslogtreecommitdiffstats
path: root/src/lmtp/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lmtp/main.c')
-rw-r--r--src/lmtp/main.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/src/lmtp/main.c b/src/lmtp/main.c
new file mode 100644
index 0000000..fb9ada8
--- /dev/null
+++ b/src/lmtp/main.c
@@ -0,0 +1,173 @@
+/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */
+
+#include "lmtp-common.h"
+#include "ioloop.h"
+#include "path-util.h"
+#include "restrict-access.h"
+#include "anvil-client.h"
+#include "master-service.h"
+#include "master-service-settings.h"
+#include "master-interface.h"
+#include "mail-deliver.h"
+#include "mail-storage-service.h"
+#include "smtp-submit-settings.h"
+#include "lda-settings.h"
+
+#include <unistd.h>
+
+#define DNS_CLIENT_SOCKET_PATH "dns-client"
+#define LMTP_MASTER_FIRST_LISTEN_FD 3
+
+#define IS_STANDALONE() \
+ (getenv(MASTER_IS_PARENT_ENV) == NULL)
+
+struct smtp_server *lmtp_server = NULL;
+
+char *dns_client_socket_path, *base_dir;
+struct mail_storage_service_ctx *storage_service;
+struct anvil_client *anvil;
+
+lmtp_client_created_func_t *hook_client_created = NULL;
+
+struct event_category event_category_lmtp = {
+ .name = "lmtp",
+};
+
+lmtp_client_created_func_t *
+lmtp_client_created_hook_set(lmtp_client_created_func_t *new_hook)
+{
+ lmtp_client_created_func_t *old_hook = hook_client_created;
+
+ hook_client_created = new_hook;
+ return old_hook;
+}
+
+void lmtp_anvil_init(void)
+{
+ if (anvil == NULL) {
+ const char *path = t_strdup_printf("%s/anvil", base_dir);
+ anvil = anvil_client_init(path, NULL, 0);
+ }
+}
+
+static void client_connected(struct master_service_connection *conn)
+{
+ master_service_client_connection_accept(conn);
+ (void)client_create(conn->fd, conn->fd, conn);
+}
+
+static void drop_privileges(void)
+{
+ struct restrict_access_settings set;
+ const char *error;
+
+ /* by default we don't drop any privileges, but keep running as root. */
+ restrict_access_get_env(&set);
+ /* open config connection before dropping privileges */
+ struct master_service_settings_input input;
+ struct master_service_settings_output output;
+
+ i_zero(&input);
+ input.module = "lmtp";
+ input.service = "lmtp";
+ if (master_service_settings_read(master_service,
+ &input, &output, &error) < 0)
+ i_fatal("Error reading configuration: %s", error);
+ restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL);
+}
+
+static void main_init(void)
+{
+ struct master_service_connection conn;
+ struct smtp_server_settings lmtp_set;
+
+ i_zero(&lmtp_set);
+ lmtp_set.protocol = SMTP_PROTOCOL_LMTP;
+ lmtp_set.auth_optional = TRUE;
+ lmtp_set.rcpt_domain_optional = TRUE;
+ lmtp_set.mail_path_allow_broken = TRUE;
+ lmtp_set.reason_code_module = "lmtp";
+
+ lmtp_server = smtp_server_init(&lmtp_set);
+
+ if (IS_STANDALONE()) {
+ i_zero(&conn);
+ (void)client_create(STDIN_FILENO, STDOUT_FILENO, &conn);
+ }
+
+ const char *error, *tmp_socket_path;
+ if (t_abspath(DNS_CLIENT_SOCKET_PATH, &tmp_socket_path, &error) < 0) {
+ i_fatal("t_abspath(%s) failed: %s", DNS_CLIENT_SOCKET_PATH, error);
+ }
+ dns_client_socket_path = i_strdup(tmp_socket_path);
+ mail_deliver_hooks_init();
+}
+
+static void main_deinit(void)
+{
+ clients_destroy();
+ if (anvil != NULL)
+ anvil_client_deinit(&anvil);
+ i_free(dns_client_socket_path);
+ i_free(base_dir);
+ smtp_server_deinit(&lmtp_server);
+}
+
+int main(int argc, char *argv[])
+{
+ const struct setting_parser_info *set_roots[] = {
+ &smtp_submit_setting_parser_info,
+ &lda_setting_parser_info,
+ &lmtp_setting_parser_info,
+ NULL
+ };
+ enum master_service_flags service_flags =
+ MASTER_SERVICE_FLAG_HAVE_STARTTLS;
+ enum mail_storage_service_flags storage_service_flags =
+ MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP |
+ MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP |
+ MAIL_STORAGE_SERVICE_FLAG_NO_IDLE_TIMEOUT;
+ const char *tmp_base_dir;
+ int c;
+
+ if (IS_STANDALONE()) {
+ service_flags |= MASTER_SERVICE_FLAG_STANDALONE |
+ MASTER_SERVICE_FLAG_STD_CLIENT;
+ } else {
+ service_flags |= MASTER_SERVICE_FLAG_KEEP_CONFIG_OPEN ;
+ }
+
+ master_service = master_service_init("lmtp", service_flags,
+ &argc, &argv, "D");
+ while ((c = master_getopt(master_service)) > 0) {
+ switch (c) {
+ case 'D':
+ storage_service_flags |=
+ MAIL_STORAGE_SERVICE_FLAG_ENABLE_CORE_DUMPS;
+ break;
+ default:
+ return FATAL_DEFAULT;
+ }
+ }
+
+ const char *error;
+ if (t_get_working_dir(&tmp_base_dir, &error) < 0)
+ i_fatal("Could not get working directory: %s", error);
+ base_dir = i_strdup(tmp_base_dir);
+
+ drop_privileges();
+ master_service_init_log_with_pid(master_service);
+
+ storage_service = mail_storage_service_init(master_service, set_roots,
+ storage_service_flags);
+ restrict_access_allow_coredumps(TRUE);
+
+ main_init();
+ master_service_init_finish(master_service);
+ master_service_run(master_service, client_connected);
+
+ main_deinit();
+ mail_storage_service_deinit(&storage_service);
+ master_service_deinit(&master_service);
+ return 0;
+}