auth-connection.c revision c54f8888b674639d69f3d13b8ac2910900a9dbbc
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2010-2011 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
1171f0abf442638bac1827bb24a0b6b8eb682a82Timo Sirainen#include "ostream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "network.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "llist.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "safe-memset.h"
1d738cce754bc64bbc66d3355ebdaf3f6eac55f1Timo Sirainen#include "auth-client-interface.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "auth-connection.h"
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen#include <unistd.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainenstruct auth_connection {
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen struct auth_connection *prev, *next;
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char *path;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen int fd;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct io *io;
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen struct istream *input;
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen struct ostream *output;
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen auth_input_callback *callback;
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen void *context;
8a4851655777e484d70b77bed6a7a8fac5c0c98cTimo Sirainen};
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainenstatic struct auth_connection *auth_connections;
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainenstatic void auth_connection_disconnected(struct auth_connection **conn);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainenstatic void auth_connection_input(struct auth_connection *conn)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen char *line;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen switch (i_stream_read(conn->input)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case 0:
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen return;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen case -1:
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen /* disconnected */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("Auth server disconnected unexpectedly");
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen auth_connection_disconnected(&conn);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen return;
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen case -2:
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen /* buffer full */
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen i_error("BUG: Auth server sent us more than %d bytes",
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen (int)AUTH_CLIENT_MAX_LINE_LENGTH);
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen auth_connection_disconnected(&conn);
9bd08aa09ea0cbd7b221aae9fc0534eb762d3de6Timo Sirainen return;
82ed69779f49bd71ef1b570ce8aca67d357dbee8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while ((line = i_stream_next_line(conn->input)) != NULL) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen T_BEGIN {
fcfb528483369975066c6adf1c55c16e6fb6e91fTimo Sirainen conn->callback(line, conn->context);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen safe_memset(line, 0, strlen(line));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } T_END;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen }
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainenstruct auth_connection *auth_connection_init(const char *path)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct auth_connection *conn;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen conn = i_new(struct auth_connection, 1);
03860f6dd70abfa2551a846e77a5c41cb40dc141Timo Sirainen conn->fd = -1;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen conn->path = i_strdup(path);
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen DLLIST_PREPEND(&auth_connections, conn);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return conn;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainenvoid auth_connection_set_callback(struct auth_connection *conn,
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen auth_input_callback *callback, void *context)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen{
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen conn->callback = callback;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen conn->context = context;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen}
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainenint auth_connection_connect(struct auth_connection *conn)
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen{
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen i_assert(conn->fd == -1);
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen conn->fd = net_connect_unix_with_retries(conn->path, 1000);
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen if (conn->fd == -1) {
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen i_error("connect(%s) failed: %m", conn->path);
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen return -1;
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen }
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen conn->input = i_stream_create_fd(conn->fd, AUTH_CLIENT_MAX_LINE_LENGTH,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen FALSE);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen conn->output = o_stream_create_fd(conn->fd, (size_t)-1, FALSE);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen conn->io = io_add(conn->fd, IO_READ, auth_connection_input, conn);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen return 0;
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen}
aff3354de83df9d683587e27461697193ff36591Timo Sirainen
dc0474dc9d5652d76cb41f439844dd80c8b96642Timo Sirainenvoid auth_connection_deinit(struct auth_connection **_conn)
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct auth_connection *conn = *_conn;
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen *_conn = NULL;
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen DLLIST_REMOVE(&auth_connections, conn);
72368bc3058d36912317ffe55e6017205f4fa036Timo Sirainen if (conn->fd != -1) {
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen io_remove(&conn->io);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen i_stream_unref(&conn->input);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen o_stream_unref(&conn->output);
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (close(conn->fd) < 0)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen i_error("close(auth connection) failed: %m");
6a7f64562ddd0dd2fec755ec4e9c9afde8e85cf1Timo Sirainen }
1b97a59edb073e9a89ac43a21a9abe5d590d4a56Timo Sirainen i_free(conn->path);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_free(conn);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainenstatic void auth_connection_disconnected(struct auth_connection **_conn)
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen{
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen struct auth_connection *conn = *_conn;
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen *_conn = NULL;
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen /* notify callback. it should deinit this connection */
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen conn->callback(NULL, conn->context);
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen}
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainenvoid auth_connection_send(struct auth_connection *conn,
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen const void *data, size_t size)
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen{
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen i_assert(conn->fd != -1);
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen (void)o_stream_send(conn->output, data, size);
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen}
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainenvoid auth_connections_deinit(void)
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen{
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen while (auth_connections != NULL) {
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen struct auth_connection *conn = auth_connections;
d6693dac50e4fb547d8dc61b85820f1761a33575Timo Sirainen
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen auth_connection_disconnected(&conn);
785b1ca149341b70bf2cb8cc3049f1c4c1070b52Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen