access-lookup.c revision 5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2010-2013 Dovecot authors, see the included COPYING file */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "lib.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "ioloop.h"
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen#include "net.h"
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen#include "fdpass.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "access-lookup.h"
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include <unistd.h>
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#define ACCESS_LOOKUP_TIMEOUT_MSECS (1000*60)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenstruct access_lookup {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen int refcount;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen int fd;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen char *path;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct io *io;
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen struct timeout *to;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen access_lookup_callback_t *callback;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen void *context;
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen};
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainenstatic void access_lookup_input(struct access_lookup *lookup)
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen unsigned char buf[3];
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen ssize_t ret;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen bool success = FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen ret = read(lookup->fd, buf, sizeof(buf));
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (ret < 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen i_error("read(%s) failed: %m", lookup->path);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen } else if (ret == 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* connection close -> no success */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen } else if (ret == 2 && buf[0] == '0' && buf[1] == '\n') {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* no success */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen } else if (ret == 2 && buf[0] == '1' && buf[1] == '\n') {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen success = TRUE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen } else {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen i_error("access(%s): Invalid input", lookup->path);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen lookup->refcount++;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen lookup->callback(success, lookup->context);
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen if (lookup->refcount > 1)
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen access_lookup_destroy(&lookup);
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen access_lookup_destroy(&lookup);
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen}
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainenstatic void access_lookup_timeout(struct access_lookup *lookup)
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen{
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen i_error("access(%s): Timed out while waiting for reply", lookup->path);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen lookup->refcount++;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen lookup->callback(FALSE, lookup->context);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (lookup->refcount > 1)
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen access_lookup_destroy(&lookup);
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen access_lookup_destroy(&lookup);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainenstruct access_lookup *
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenaccess_lookup(const char *path, int client_fd, const char *daemon_name,
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen access_lookup_callback_t *callback, void *context)
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen{
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen struct access_lookup *lookup;
c1d4780bc0c9017e8e5d366b81e4fad31174c0adTimo Sirainen const char *cmd;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen ssize_t ret;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen int fd;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen fd = net_connect_unix(path);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (fd == -1) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen i_error("connect(%s) failed: %m", path);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return NULL;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen cmd = t_strconcat(daemon_name, "\n", NULL);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen ret = fd_send(fd, client_fd, cmd, strlen(cmd));
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (ret != (ssize_t)strlen(cmd)) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (ret < 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen i_error("fd_send(%s) failed: %m", path);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen else
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen i_error("fd_send(%s) didn't write enough bytes", path);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen i_close_fd(&fd);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return NULL;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen lookup = i_new(struct access_lookup, 1);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen lookup->refcount = 1;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen lookup->fd = fd;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen lookup->path = i_strdup(path);
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen lookup->io = io_add(fd, IO_READ, access_lookup_input, lookup);
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen lookup->to = timeout_add(ACCESS_LOOKUP_TIMEOUT_MSECS,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen access_lookup_timeout, lookup);
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen lookup->callback = callback;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen lookup->context = context;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen return lookup;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen}
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainenvoid access_lookup_destroy(struct access_lookup **_lookup)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen struct access_lookup *lookup = *_lookup;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen i_assert(lookup->refcount > 0);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (--lookup->refcount > 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen *_lookup = NULL;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (lookup->to != NULL)
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen timeout_remove(&lookup->to);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen io_remove(&lookup->io);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (close(lookup->fd) < 0)
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen i_error("close(%s) failed: %m", lookup->path);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen i_free(lookup->path);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen i_free(lookup);
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen}
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen