]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
expire-tool: Use the new auth-master API instead of doing the lookup ourself.
authorTimo Sirainen <tss@iki.fi>
Sat, 1 Nov 2008 12:49:12 +0000 (14:49 +0200)
committerTimo Sirainen <tss@iki.fi>
Sat, 1 Nov 2008 12:49:12 +0000 (14:49 +0200)
--HG--
branch : HEAD

src/plugins/expire/Makefile.am
src/plugins/expire/auth-client.c
src/plugins/expire/expire-tool.c

index f8b5ab4683845c839b7573f2f7d9ec63f8a9bd32..15115a021121aa8fc028536dd2d512d954397542 100644 (file)
@@ -2,6 +2,7 @@ pkglibexecdir = $(libexecdir)/dovecot
 
 AM_CPPFLAGS = \
        -I$(top_srcdir)/src/lib \
+       -I$(top_srcdir)/src/lib-auth \
        -I$(top_srcdir)/src/lib-dict \
        -I$(top_srcdir)/src/lib-mail \
        -I$(top_srcdir)/src/lib-imap \
@@ -37,6 +38,7 @@ libs = \
        $(top_builddir)/src/lib-imap/libimap.a \
        $(top_builddir)/src/lib-mail/libmail.a \
        $(top_builddir)/src/lib-dict/libdict.a \
+       $(top_builddir)/src/lib-auth/libauth.a \
        $(top_builddir)/src/lib-charset/libcharset.a \
        $(top_builddir)/src/lib/liblib.a
 
index c460795b79241b886f237660b3e837f9f38ff2ca..2d55ae6c6073986b3aae5f974b0a8b72633227c5 100644 (file)
 /* Copyright (c) 2005-2008 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
-#include "ioloop.h"
-#include "network.h"
-#include "istream.h"
-#include "ostream.h"
+#include "array.h"
 #include "env-util.h"
 #include "restrict-access.h"
 #include "auth-client.h"
+#include "auth-master.h"
 
-#include <stdlib.h>
 #include <unistd.h>
 
-#define MAX_INBUF_SIZE 8192
-#define MAX_OUTBUF_SIZE 512
+static uid_t current_uid = 0;
 
-struct auth_connection {
-       char *auth_socket;
-
-       int fd;
-       struct io *io;
-       struct istream *input;
-       struct ostream *output;
-
-       uid_t orig_uid, current_uid;
-       const char *current_user;
-       int return_value;
-
-       unsigned int handshaked:1;
-};
-
-static void auth_input(struct auth_connection *conn);
-
-static int auth_connection_connect(struct auth_connection *conn)
-{
-       int fd;
-
-       if (conn->fd != -1)
-               return 0;
-
-       fd = net_connect_unix(conn->auth_socket);
-       if (fd < 0) {
-               i_error("net_connect(%s) failed: %m", conn->auth_socket);
-               return -1;
-       }
-
-       conn->fd = fd;
-       conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE);
-       conn->output = o_stream_create_fd(fd, MAX_OUTBUF_SIZE, FALSE);
-       conn->io = io_add(fd, IO_READ, auth_input, conn);
-
-       o_stream_send_str(conn->output, "VERSION\t1\t0\n");
-       return 0;
-}
-
-static void auth_connection_close(struct auth_connection *conn)
-{
-       if (conn->fd == -1)
-               return;
-
-       io_remove(&conn->io);
-       i_stream_unref(&conn->input);
-       o_stream_unref(&conn->output);
-
-       if (close(conn->fd) < 0)
-               i_error("close() failed: %m");
-       conn->fd = -1;
-}
-
-struct auth_connection *auth_connection_init(const char *auth_socket)
-{
-       struct auth_connection *conn;
-
-       conn = i_new(struct auth_connection, 1);
-       conn->auth_socket = i_strdup(auth_socket);
-       conn->orig_uid = conn->current_uid = geteuid();
-       conn->fd = -1;
-
-       (void)auth_connection_connect(conn);
-       return conn;
-}
-
-void auth_connection_deinit(struct auth_connection *conn)
-{
-       auth_connection_close(conn);
-       i_free(conn->auth_socket);
-       i_free(conn);
-}
-
-static void auth_parse_input(struct auth_connection *conn, const char *args)
+static void auth_set_env(const char *user, struct auth_user_reply *reply)
 {
-       const char *const *tmp, *key, *value;
-       uid_t uid = (uid_t)-1;
-       int home_found = FALSE;
-
-       for (tmp = t_strsplit(args, "\t"); *tmp != NULL; tmp++) {
-               if (strncmp(*tmp, "uid=", 4) == 0)
-                       uid = strtoul(*tmp + 4, NULL, 10);
-               else if (strncmp(*tmp, "gid=", 4) == 0) {
-                       gid_t gid = strtoul(*tmp + 4, NULL, 10);
+       const char *const *fields, *key, *value;
+       unsigned int i, count;
 
-                       if (conn->orig_uid == 0 || getegid() != gid) {
-                               env_put(t_strconcat("RESTRICT_SETGID=",
-                                                   *tmp + 4, NULL));
-                       }
-               } else if (strncmp(*tmp, "chroot=", 7) == 0) {
-                       env_put(t_strconcat("RESTRICT_CHROOT=",
-                                           *tmp + 7, NULL));
-               } else if (strncmp(*tmp, "home=", 5) == 0) {
-                       home_found = TRUE;
-                       env_put(t_strconcat("HOME=", *tmp + 5, NULL));
-               } else {
-                       key = t_str_ucase(t_strcut(*tmp, '='));
-                       value = strchr(*tmp, '=');
-                       if (value != NULL)
-                               env_put(t_strconcat(key, "=", value+1, NULL));
-               }
+       if (reply->gid != (gid_t)-1 && getegid() != reply->gid) {
+               env_put(t_strconcat("RESTRICT_SETGID=",
+                                   dec2str(reply->gid), NULL));
        }
+       if (reply->chroot != NULL)
+               env_put(t_strconcat("RESTRICT_CHROOT=", reply->chroot, NULL));
 
-       if (!home_found) {
+       if (reply->home == NULL) {
                /* we must have a home directory */
-               i_error("userdb(%s) didn't return a home directory",
-                       conn->current_user);
+               i_error("userdb(%s) didn't return a home directory", user);
                return;
        }
-
-       if (uid == (uid_t)-1) {
-               i_error("userdb(%s) didn't return uid", conn->current_user);
+       if (reply->uid == (uid_t)-1) {
+               i_error("userdb(%s) didn't return uid", user);
                return;
        }
 
-       if (uid != conn->current_uid && conn->current_uid != 0) {
+       if (reply->uid != current_uid && current_uid != 0) {
+               /* we're changing the UID, switch back to root */
                if (seteuid(0) != 0)
                        i_fatal("seteuid(0) failed: %m");
-               conn->current_uid = 0;
+               current_uid = 0;
        }
 
        /* change GID */
@@ -142,81 +46,36 @@ static void auth_parse_input(struct auth_connection *conn, const char *args)
        /* we'll change only effective UID. This is a bit unfortunate since
           it allows reverting back to root, but we'll have to be able to
           access different users' mailboxes.. */
-       if (uid != conn->current_uid) {
-               if (seteuid(uid) < 0)
-                       i_fatal("seteuid(%s) failed: %m", dec2str(uid));
-               conn->current_uid = uid;
-       }
-
-       conn->return_value = 1;
-}
-
-static void auth_input(struct auth_connection *conn)
-{
-       const char *line;
-
-       switch (i_stream_read(conn->input)) {
-       case 0:
-               return;
-       case -1:
-               /* disconnected */
-               auth_connection_close(conn);
-               return;
-       case -2:
-               /* buffer full */
-               i_error("BUG: Auth master sent us more than %d bytes",
-                       MAX_INBUF_SIZE);
-               auth_connection_close(conn);
-               return;
+       if (reply->uid != current_uid) {
+               if (seteuid(reply->uid) < 0)
+                       i_fatal("seteuid(%s) failed: %m", dec2str(reply->uid));
+               current_uid = reply->uid;
        }
 
-       if (!conn->handshaked) {
-               while ((line = i_stream_next_line(conn->input)) != NULL) {
-                       if (strncmp(line, "VERSION\t", 8) == 0) {
-                               if (strncmp(line + 8, "1\t", 2) != 0) {
-                                       i_error("Auth master version mismatch");
-                                       auth_connection_close(conn);
-                                       return;
-                               }
-                       } else if (strncmp(line, "SPID\t", 5) == 0) {
-                               conn->handshaked = TRUE;
-                               break;
-                       }
-               }
-       }
-
-       line = i_stream_next_line(conn->input);
-       if (line != NULL) {
-               if (strncmp(line, "USER\t1\t", 7) == 0) {
-                       auth_parse_input(conn, line + 7);
-               } else if (strcmp(line, "NOTFOUND\t1") == 0)
-                       conn->return_value = 0;
-               else if (strncmp(line, "FAIL\t1\t", 7) == 0)
-                       conn->return_value = -1;
-               else {
-                       i_error("BUG: Unexpected input from auth master: %s",
-                               line);
-                       auth_connection_close(conn);
-               }
-               io_loop_stop(current_ioloop);
+       fields = array_get(&reply->extra_fields, &count);
+       for (i = 0; i < count; i++) {
+               key = t_str_ucase(t_strcut(fields[i], '='));
+               value = strchr(fields[i], '=');
+               if (value != NULL)
+                       value++;
+               else
+                       value = "1";
+               env_put(t_strconcat(key, "=", value, NULL));
        }
+       env_put(t_strconcat("HOME=", reply->home, NULL));
 }
 
 int auth_client_put_user_env(struct auth_connection *conn,
                             const char *user)
 {
-       if (auth_connection_connect(conn) < 0)
-               return -1;
-
-       conn->current_user = user;
-       conn->return_value = -1;
-
-       o_stream_send_str(conn->output,
-                         t_strconcat("USER\t1\t", user, "\t"
-                                     "service=expire\n", NULL));
-
-       io_loop_run(current_ioloop);
-
-       conn->current_user = NULL;
-       return conn->return_value;
+       struct auth_user_reply reply;
+       pool_t pool;
+       int ret;
+
+       pool = pool_alloconly_create("userdb lookup", 512);
+       ret = auth_master_user_lookup(conn, user, "expire", pool, &reply);
+       if (ret > 0)
+               auth_set_env(user, &reply);
+       pool_unref(&pool);
+       return ret;
 }
index 708683987e523bf6bdc03989a4200ff79612e5fb..35c9a5153766366c2097c5492ba5254c0480433d 100644 (file)
@@ -204,7 +204,7 @@ static void expire_run(bool testrun)
 
        memset(&ctx, 0, sizeof(ctx));
        ctx.testrun = testrun;
-       ctx.auth_conn = auth_connection_init(auth_socket);
+       ctx.auth_conn = auth_master_init(auth_socket, getenv("DEBUG") != NULL);
        env = expire_env_init(getenv("EXPIRE"), getenv("EXPIRE_ALTMOVE"));
        dict = dict_init(getenv("EXPIRE_DICT"), DICT_DATA_TYPE_UINT32, "");
        if (dict == NULL)
@@ -292,7 +292,7 @@ static void expire_run(bool testrun)
 
        if (ctx.user != NULL)
                user_deinit(&ctx);
-       auth_connection_deinit(ctx.auth_conn);
+       auth_master_deinit(&ctx.auth_conn);
 
        mail_storage_deinit();
        dict_drivers_unregister_builtin();