]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
script: Added enough features to get rawlog working again.
authorTimo Sirainen <tss@iki.fi>
Sat, 12 Dec 2009 00:26:26 +0000 (19:26 -0500)
committerTimo Sirainen <tss@iki.fi>
Sat, 12 Dec 2009 00:26:26 +0000 (19:26 -0500)
Also added -d parameter to drop privileges before executing script.

--HG--
branch : HEAD

src/util/Makefile.am
src/util/script.c

index 395ff619fb4ad52d3a3c59d61aa3116eba9d8212..e54d4c540efd215984013f306f0fbc7b4adb1e6f 100644 (file)
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
        -I$(top_srcdir)/src/lib-auth \
        -I$(top_srcdir)/src/lib-dict \
+       -I$(top_srcdir)/src/lib-settings \
        -I$(top_srcdir)/src/lib-master \
        -I$(top_srcdir)/src/lib-mail \
        -I$(top_srcdir)/src/lib-imap \
@@ -26,8 +27,8 @@ rawlog_DEPENDENCIES = $(LIBDOVECOT_DEPS)
 rawlog_SOURCES = \
        rawlog.c
 
-script_LDADD = $(LIBDOVECOT)
-script_DEPENDENCIES = $(LIBDOVECOT_DEPS)
+script_LDADD = $(LIBDOVECOT_STORAGE) $(LIBDOVECOT) $(MODULE_LIBS)
+script_DEPENDENCIES = $(LIBDOVECOT_STORAGE) $(LIBDOVECOT_DEPS)
 script_SOURCES = \
        script.c
 
index 06463a7ef69f22700f750750fb6fb8dc23f11790..510aa92e31b3604400fc496e79b8ff6675ac0be8 100644 (file)
@@ -3,35 +3,42 @@
 #include "lib.h"
 #include "env-util.h"
 #include "fdpass.h"
+#include "restrict-access.h"
 #include "str.h"
 #include "strescape.h"
+#include "settings-parser.h"
+#include "mail-storage-service.h"
 #include "master-interface.h"
 #include "master-service.h"
+#include "master-service-settings.h"
 
 #include <stdlib.h>
 #include <unistd.h>
 
 #define ENV_USERDB_KEYS "USERDB_KEYS"
 #define SCRIPT_COMM_FD 3
-#define SCRIPT_CLIENT_FD 1
 
 static char **exec_args;
+static bool drop_privileges = FALSE;
 
 static void client_connected(const struct master_service_connection *conn)
 {
-       string_t *input, *keys;
-       const char **args, *arg, *key, *value, *username;
+       string_t *instr, *keys;
+       const char **args, *key, *value, *error;
+       struct mail_storage_service_ctx *service_ctx;
+       struct mail_storage_service_input input;
+       struct mail_storage_service_user *user;
        char buf[1024];
        unsigned int i;
        int fd = -1;
        ssize_t ret;
 
-       input = t_str_new(1024);
+       instr = t_str_new(1024);
        ret = fd_read(conn->fd, buf, sizeof(buf), &fd);
        while (ret > 0) {
-               str_append_n(input, buf, ret);
+               str_append_n(instr, buf, ret);
                if (buf[ret-1] == '\n') {
-                       str_truncate(input, str_len(input)-1);
+                       str_truncate(instr, str_len(instr)-1);
                        break;
                }
 
@@ -51,38 +58,54 @@ static void client_connected(const struct master_service_connection *conn)
        /* put everything to environment */
        env_clean();
        keys = t_str_new(256);
-       args = t_strsplit(str_c(input), "\t");
+       args = t_strsplit(str_c(instr), "\t");
 
        if (str_array_length(args) < 3)
                i_fatal("Missing input fields");
 
        i = 0;
-       env_put(t_strconcat("LOCAL_IP=", args[i++], NULL));
-       env_put(t_strconcat("IP=", args[i++], NULL));
-       username = args[i++];
-       env_put(t_strconcat("USER=", username, NULL));
+       memset(&input, 0, sizeof(input));
+       input.module = input.service = "script";
+       (void)net_addr2ip(args[i++], &input.local_ip);
+       (void)net_addr2ip(args[i++], &input.remote_ip);
+       input.username = args[i++];
+       input.userdb_fields = args + i;
+
+       env_put(t_strconcat("LOCAL_IP=", net_ip2addr(&input.local_ip), NULL));
+       env_put(t_strconcat("IP=", net_ip2addr(&input.remote_ip), NULL));
+       env_put(t_strconcat("USER=", input.username, NULL));
 
        for (; args[i] != '\0'; i++) {
-               arg = str_tabunescape(t_strdup_noconst(args[i]));
-               value = strchr(arg, '=');
+               args[i] = str_tabunescape(t_strdup_noconst(args[i]));
+               value = strchr(args[i], '=');
                if (value != NULL) {
-                       key = t_str_ucase(t_strdup_until(arg, value));
+                       key = t_str_ucase(t_strdup_until(args[i], value));
                        env_put(t_strconcat(key, value, NULL));
                        str_printfa(keys, "%s ", key);
                }
        }
        env_put(t_strconcat(ENV_USERDB_KEYS"=", str_c(keys), NULL));
 
-       if (dup2(fd, SCRIPT_CLIENT_FD) < 0)
+       master_service_init_log(master_service,
+               t_strdup_printf("script(%s): ", input.username));
+
+       service_ctx = mail_storage_service_init(master_service, NULL, 0);
+       if (mail_storage_service_lookup(service_ctx, &input, &user, &error) < 0)
+               i_fatal("%s", error);
+       mail_storage_service_restrict_setenv(service_ctx, user);
+
+       if (drop_privileges)
+               restrict_access_by_env(getenv("HOME"), TRUE);
+
+       if (dup2(fd, STDIN_FILENO) < 0)
+               i_fatal("dup2() failed: %m");
+       if (dup2(fd, STDOUT_FILENO) < 0)
                i_fatal("dup2() failed: %m");
        if (conn->fd != SCRIPT_COMM_FD) {
                if (dup2(conn->fd, SCRIPT_COMM_FD) < 0)
                        i_fatal("dup2() failed: %m");
        }
 
-       master_service_init_log(master_service,
-                               t_strdup_printf("script(%s): ", username));
-
        (void)execvp(exec_args[0], exec_args);
        i_fatal("execvp(%s) failed: %m", exec_args[0]);
 }
@@ -113,7 +136,7 @@ static void script_execute_finish(void)
        }
        str_append_c(reply, '\n');
 
-       ret = fd_send(SCRIPT_COMM_FD, SCRIPT_CLIENT_FD,
+       ret = fd_send(SCRIPT_COMM_FD, STDOUT_FILENO,
                      str_data(reply), str_len(reply));
        if (ret < 0)
                i_fatal("fd_send() failed: %m");
@@ -124,15 +147,25 @@ static void script_execute_finish(void)
 int main(int argc, char *argv[])
 {
        enum master_service_flags flags = 0;
-       int i;
+       const char *path;
+       int i, c;
 
        if (getenv(MASTER_UID_ENV) == NULL)
                flags |= MASTER_SERVICE_FLAG_STANDALONE;
 
        master_service = master_service_init("script", flags,
-                                            &argc, &argv, NULL);
-       if (master_getopt(master_service) > 0)
-               return FATAL_DEFAULT;
+                                            &argc, &argv, "d");
+       while ((c = master_getopt(master_service)) > 0) {
+               switch (c) {
+               case 'd':
+                       drop_privileges = TRUE;
+                       break;
+               default:
+                       return FATAL_DEFAULT;
+               }
+       }
+       argc -= optind;
+       argv += optind;
 
        master_service_init_log(master_service, "script: ");
        master_service_init_finish(master_service);
@@ -141,13 +174,19 @@ int main(int argc, char *argv[])
        if ((flags & MASTER_SERVICE_FLAG_STANDALONE) != 0)
                script_execute_finish();
        else {
-               if (argv[1] == NULL)
+               if (argv[0] == NULL)
                        i_fatal("Missing script path");
-               exec_args = i_new(char *, argc + 1);
-               for (i = 1; i < argc; i++)
-                       exec_args[i-1] = argv[i];
-               exec_args[i-1] = PKG_LIBEXECDIR"/script";
-               exec_args[i] = NULL;
+               exec_args = i_new(char *, argc + 2);
+               for (i = 0; i < argc; i++)
+                       exec_args[i] = argv[i];
+               exec_args[i] = PKG_LIBEXECDIR"/script";
+               exec_args[i+1] = NULL;
+
+               if (exec_args[0][0] != '/') {
+                       path = t_strconcat(PKG_LIBEXECDIR"/",
+                                          exec_args[0], NULL);
+                       exec_args[0] = t_strdup_noconst(path);
+               }
 
                master_service_run(master_service, client_connected);
        }