access-lookup.c revision cb78bd2ad54e402c1f53930b41e2295683bda90b
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen/* Copyright (c) 2010-2012 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "lib.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "ioloop.h"
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen#include "network.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "fdpass.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "access-lookup.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen#include <unistd.h>
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#define ACCESS_LOOKUP_TIMEOUT_MSECS (1000*60)
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstruct access_lookup {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int refcount;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int fd;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen char *path;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct io *io;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct timeout *to;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen access_lookup_callback_t *callback;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen void *context;
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen};
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainenstatic void access_lookup_input(struct access_lookup *lookup)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned char buf[3];
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen ssize_t ret;
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen bool success = FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ret = read(lookup->fd, buf, sizeof(buf));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (ret < 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_error("read(%s) failed: %m", lookup->path);
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen } else if (ret == 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* connection close -> no success */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else if (ret == 2 && buf[0] == '0' && buf[1] == '\n') {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* no success */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else if (ret == 2 && buf[0] == '1' && buf[1] == '\n') {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen success = TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_error("access(%s): Invalid input", lookup->path);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup->refcount++;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup->callback(success, lookup->context);
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen if (lookup->refcount > 1)
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen access_lookup_destroy(&lookup);
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen access_lookup_destroy(&lookup);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void access_lookup_timeout(struct access_lookup *lookup)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_error("access(%s): Timed out while waiting for reply", lookup->path);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup->refcount++;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup->callback(FALSE, lookup->context);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (lookup->refcount > 1)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen access_lookup_destroy(&lookup);
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen access_lookup_destroy(&lookup);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
66c0f96d704f09c88dd03b0ee13a3e9711ffe593Timo Sirainenstruct access_lookup *
66c0f96d704f09c88dd03b0ee13a3e9711ffe593Timo Sirainenaccess_lookup(const char *path, int client_fd, const char *daemon_name,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen access_lookup_callback_t *callback, void *context)
66c0f96d704f09c88dd03b0ee13a3e9711ffe593Timo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct access_lookup *lookup;
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen const char *cmd;
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen ssize_t ret;
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen int fd;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen fd = net_connect_unix(path);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (fd == -1) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_error("connect(%s) failed: %m", path);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen cmd = t_strconcat(daemon_name, "\n", NULL);
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen ret = fd_send(fd, client_fd, cmd, strlen(cmd));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (ret != (ssize_t)strlen(cmd)) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (ret < 0)
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen i_error("fd_send(%s) failed: %m", path);
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen else
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen i_error("fd_send(%s) didn't write enough bytes", path);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_close_fd(fd);
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen return NULL;
db0735f9b388c5bcfb781b1b25015e898d63d953Timo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup = i_new(struct access_lookup, 1);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup->refcount = 1;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup->fd = fd;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup->path = i_strdup(path);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup->io = io_add(fd, IO_READ, access_lookup_input, lookup);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup->to = timeout_add(ACCESS_LOOKUP_TIMEOUT_MSECS,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen access_lookup_timeout, lookup);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen lookup->callback = callback;
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen lookup->context = context;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return lookup;
834f2b9f60d93e4c7dfc6992e692f5b7213a1b11Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvoid access_lookup_destroy(struct access_lookup **_lookup)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct access_lookup *lookup = *_lookup;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_assert(lookup->refcount > 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (--lookup->refcount > 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *_lookup = NULL;
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen if (lookup->to != NULL)
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen timeout_remove(&lookup->to);
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen io_remove(&lookup->io);
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen if (close(lookup->fd) < 0)
bcdb6c0bd2e7dbb34b306d3d8c2383a7d7654612Timo Sirainen i_error("close(%s) failed: %m", lookup->path);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
111a7dda02defa4d612468cfc3c40da5240645afTimo Sirainen i_free(lookup->path);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_free(lookup);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen}
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen