auth-server-connection.c revision 84de4076ab3a33b34049a46e72ee0456afad8ad4
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher/* Copyright (c) 2003-2011 Dovecot authors, see the included COPYING file */
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "lib.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "array.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "hash.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "hostpid.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "ioloop.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "istream.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "ostream.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "network.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "eacces-error.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "auth-client-private.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "auth-client-request.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include "auth-server-connection.h"
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <unistd.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#include <stdlib.h>
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#define AUTH_SERVER_CONN_MAX_LINE_LENGTH AUTH_CLIENT_MAX_LINE_LENGTH
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#define AUTH_HANDSHAKE_TIMEOUT (30*1000)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher#define AUTH_SERVER_RECONNECT_TIMEOUT_SECS 5
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherstatic void
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherauth_server_connection_reconnect(struct auth_server_connection *conn,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher const char *disconnect_reason);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherstatic int
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherauth_server_input_mech(struct auth_server_connection *conn,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher const char *const *args)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher{
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher struct auth_mech_desc mech_desc;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (conn->handshake_received) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher i_error("BUG: Authentication server already sent handshake");
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return -1;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (args[0] == NULL) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher i_error("BUG: Authentication server sent broken MECH line");
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return -1;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose }
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose memset(&mech_desc, 0, sizeof(mech_desc));
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose mech_desc.name = p_strdup(conn->pool, args[0]);
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose if (strcmp(mech_desc.name, "PLAIN") == 0)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose conn->has_plain_mech = TRUE;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose for (args++; *args != NULL; args++) {
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose if (strcmp(*args, "private") == 0)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose mech_desc.flags |= MECH_SEC_PRIVATE;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose else if (strcmp(*args, "anonymous") == 0)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose mech_desc.flags |= MECH_SEC_ANONYMOUS;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose else if (strcmp(*args, "plaintext") == 0)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose mech_desc.flags |= MECH_SEC_PLAINTEXT;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose else if (strcmp(*args, "dictionary") == 0)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose mech_desc.flags |= MECH_SEC_DICTIONARY;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose else if (strcmp(*args, "active") == 0)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose mech_desc.flags |= MECH_SEC_ACTIVE;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose else if (strcmp(*args, "forward-secrecy") == 0)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose mech_desc.flags |= MECH_SEC_FORWARD_SECRECY;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose else if (strcmp(*args, "mutual-auth") == 0)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose mech_desc.flags |= MECH_SEC_MUTUAL_AUTH;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose }
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose array_append(&conn->available_auth_mechs, &mech_desc, 1);
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose return 0;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose}
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bosestatic int
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Boseauth_server_input_spid(struct auth_server_connection *conn,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose const char *const *args)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose{
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose if (conn->handshake_received) {
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose i_error("BUG: Authentication server already sent handshake");
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose return -1;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose }
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose if (str_to_uint(args[0], &conn->server_pid) < 0) {
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose i_error("BUG: Authentication server sent invalid PID");
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose return -1;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose }
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose return 0;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose}
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bosestatic int
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Boseauth_server_input_cuid(struct auth_server_connection *conn,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose const char *const *args)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose{
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose if (conn->handshake_received) {
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose i_error("BUG: Authentication server already sent handshake");
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose return -1;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose }
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose if (args[0] == NULL ||
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose str_to_uint(args[0], &conn->connect_uid) < 0) {
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose i_error("BUG: Authentication server sent broken CUID line");
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose return -1;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose }
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose return 0;
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose}
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bosestatic int
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Boseauth_server_input_cookie(struct auth_server_connection *conn,
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose const char *const *args)
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose{
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose if (conn->cookie != NULL) {
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose i_error("BUG: Authentication server already sent cookie");
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose return -1;
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose }
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose conn->cookie = p_strdup(conn->pool, args[0]);
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose return 0;
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose}
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bosestatic int auth_server_input_done(struct auth_server_connection *conn)
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose{
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose if (array_count(&conn->available_auth_mechs) == 0) {
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose i_error("BUG: Authentication server returned no mechanisms");
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return -1;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (conn->cookie == NULL) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher i_error("BUG: Authentication server didn't send a cookie");
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return -1;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (conn->to != NULL)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher timeout_remove(&conn->to);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->handshake_received = TRUE;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (conn->client->connect_notify_callback != NULL) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->client->connect_notify_callback(conn->client, TRUE,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek conn->client->connect_notify_context);
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek }
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek return 0;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek}
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
df0596ec12bc5091608371e2977f3111241e8cafSimo Sorcestatic int
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherauth_server_lookup_request(struct auth_server_connection *conn,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher const char *id_arg, bool remove,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher struct auth_client_request **request_r)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher{
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher struct auth_client_request *request;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher unsigned int id;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (id_arg == NULL || str_to_uint(id_arg, &id) < 0) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher i_error("BUG: Authentication server input missing ID");
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return -1;
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek request = hash_table_lookup(conn->requests, POINTER_CAST(id));
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek if (request == NULL) {
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek i_error("BUG: Authentication server sent unknown id %u", id);
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek return -1;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek }
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek if (remove || auth_client_request_is_aborted(request))
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek hash_table_remove(conn->requests, POINTER_CAST(id));
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek *request_r = request;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek return 0;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek}
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidekstatic int
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidekauth_server_input_ok(struct auth_server_connection *conn,
bfdb2eeed95bde6cd065a9a47a7cb1773990ccfbOndrej Kos const char *const *args)
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek{
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek struct auth_client_request *request;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
bfdb2eeed95bde6cd065a9a47a7cb1773990ccfbOndrej Kos if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek return -1;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek auth_client_request_server_input(request, AUTH_REQUEST_STATUS_OK,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek args + 1);
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek return 0;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek}
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidekstatic int auth_server_input_cont(struct auth_server_connection *conn,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek const char *const *args)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher{
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher struct auth_client_request *request;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (str_array_length(args) < 2) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher i_error("BUG: Authentication server sent broken CONT line");
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return -1;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (auth_server_lookup_request(conn, args[0], FALSE, &request) < 0)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return -1;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher auth_client_request_server_input(request, AUTH_REQUEST_STATUS_CONTINUE,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher args + 1);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return 0;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher}
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherstatic int auth_server_input_fail(struct auth_server_connection *conn,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek const char *const *args)
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek{
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek struct auth_client_request *request;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek return -1;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek auth_client_request_server_input(request, AUTH_REQUEST_STATUS_FAIL,
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek args + 1);
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek return 0;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek}
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bosestatic int
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Boseauth_server_connection_input_line(struct auth_server_connection *conn,
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose const char *line)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose{
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose const char *const *args;
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose if (conn->client->debug)
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose i_debug("auth input: %s", line);
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose args = t_strsplit(line, "\t");
949fbc93defad394648b2651b43a7bbfa5bff42bSumit Bose if (args[0] == NULL) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher i_error("Auth server sent empty line");
9a7b6d3248c5aac460e164f2246b26131cfbc055Simo Sorce return -1;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (strcmp(args[0], "OK") == 0)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return auth_server_input_ok(conn, args + 1);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher else if (strcmp(args[0], "CONT") == 0)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return auth_server_input_cont(conn, args + 1);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher else if (strcmp(args[0], "FAIL") == 0)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return auth_server_input_fail(conn, args + 1);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher else if (strcmp(args[0], "MECH") == 0)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return auth_server_input_mech(conn, args + 1);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher else if (strcmp(args[0], "SPID") == 0)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return auth_server_input_spid(conn, args + 1);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher else if (strcmp(args[0], "CUID") == 0)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return auth_server_input_cuid(conn, args + 1);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher else if (strcmp(args[0], "COOKIE") == 0)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return auth_server_input_cookie(conn, args + 1);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher else if (strcmp(args[0], "DONE") == 0)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return auth_server_input_done(conn);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher else {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher i_error("Auth server sent unknown command: %s", args[0]);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return -1;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher}
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherstatic void auth_server_connection_input(struct auth_server_connection *conn)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher{
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher struct istream *input;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher const char *line, *error;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher int ret;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher switch (i_stream_read(conn->input)) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher case 0:
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher case -1:
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher /* disconnected */
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher error = conn->input->stream_errno != 0 ?
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher strerror(conn->input->stream_errno) : "EOF";
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher auth_server_connection_reconnect(conn, error);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher case -2:
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher /* buffer full - can't happen unless auth is buggy */
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher i_error("BUG: Auth server sent us more than %d bytes of data",
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher AUTH_SERVER_CONN_MAX_LINE_LENGTH);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher auth_server_connection_disconnect(conn, "buffer full");
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (!conn->version_received) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher line = i_stream_next_line(conn->input);
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher if (line == NULL)
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher return;
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher /* make sure the major version matches */
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher if (strncmp(line, "VERSION\t", 8) != 0 ||
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher !str_uint_equals(t_strcut(line + 8, '\t'),
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher AUTH_CLIENT_PROTOCOL_MAJOR_VERSION)) {
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher i_error("Authentication server not compatible with "
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher "this client (mixed old and new binaries?)");
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher auth_server_connection_disconnect(conn,
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher "incompatible serevr");
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher return;
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher }
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher conn->version_received = TRUE;
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher }
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher input = conn->input;
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher i_stream_ref(input);
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher while ((line = i_stream_next_line(input)) != NULL && !input->closed) {
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher T_BEGIN {
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher ret = auth_server_connection_input_line(conn, line);
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher } T_END;
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher if (ret < 0) {
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher auth_server_connection_disconnect(conn, t_strdup_printf(
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher "Received broken input: %s", line));
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher break;
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher }
5dedd73d90f0c1f23299f0c613f384ef902c3653Stephen Gallagher }
5dedd73d90f0c1f23299f0c613f384ef902c3653Stephen Gallagher i_stream_unref(&input);
5dedd73d90f0c1f23299f0c613f384ef902c3653Stephen Gallagher}
5dedd73d90f0c1f23299f0c613f384ef902c3653Stephen Gallagher
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagherstruct auth_server_connection *
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagherauth_server_connection_init(struct auth_client *client)
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher{
4f3fd1fb264a7eaf3a9d062d49e071b0d17e4debStephen Gallagher struct auth_server_connection *conn;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher pool_t pool;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher pool = pool_alloconly_create("auth server connection", 1024);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn = p_new(pool, struct auth_server_connection, 1);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->pool = pool;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->client = client;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->fd = -1;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->requests = hash_table_create(default_pool, pool, 100, NULL, NULL);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher i_array_init(&conn->available_auth_mechs, 8);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher return conn;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher}
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherstatic void
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagherauth_server_connection_remove_requests(struct auth_server_connection *conn,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher const char *disconnect_reason)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher{
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher static const char *const temp_failure_args[] = { "temp", NULL };
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher struct hash_iterate_context *iter;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek void *key, *value;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher time_t created, oldest = 0;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek unsigned int request_count = 0;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (hash_table_count(conn->requests) == 0)
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek return;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek iter = hash_table_iterate_init(conn->requests);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher while (hash_table_iterate(iter, &key, &value)) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher struct auth_client_request *request = value;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek if (!auth_client_request_is_aborted(request)) {
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek request_count++;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek created = auth_client_request_get_create_time(request);
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek if (oldest > created || oldest == 0)
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek oldest = created;
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
5aad10b49e193ee14a86e1277146a223005a2d6bJakub Hrozek auth_client_request_server_input(request,
5aad10b49e193ee14a86e1277146a223005a2d6bJakub Hrozek AUTH_REQUEST_STATUS_INTERNAL_FAIL,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher temp_failure_args);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher hash_table_iterate_deinit(&iter);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher hash_table_clear(conn->requests, FALSE);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (request_count > 0) {
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher i_warning("Auth connection closed with %u pending requests "
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher "(max %u secs, pid=%s, %s)", request_count,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher (unsigned int)(ioloop_time - oldest),
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher my_pid, disconnect_reason);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher }
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher}
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallaghervoid auth_server_connection_disconnect(struct auth_server_connection *conn,
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher const char *reason)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher{
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->handshake_received = FALSE;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->version_received = FALSE;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->has_plain_mech = FALSE;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->server_pid = 0;
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher conn->connect_uid = 0;
df0596ec12bc5091608371e2977f3111241e8cafSimo Sorce conn->cookie = NULL;
9a7b6d3248c5aac460e164f2246b26131cfbc055Simo Sorce array_clear(&conn->available_auth_mechs);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher
46222e5191473f9a46aec581273eb2eef22e23beMichal Zidek if (conn->to != NULL)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher timeout_remove(&conn->to);
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher if (conn->io != NULL)
505e75ba28b42bb3de7a6d55de825091b70cc2b2Stephen Gallagher io_remove(&conn->io);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher if (conn->fd != -1) {
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher i_stream_destroy(&conn->input);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher o_stream_destroy(&conn->output);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher if (close(conn->fd) < 0)
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher i_error("close(auth server connection) failed: %m");
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher conn->fd = -1;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher }
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher auth_server_connection_remove_requests(conn, reason);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher if (conn->client->connect_notify_callback != NULL) {
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher conn->client->connect_notify_callback(conn->client, FALSE,
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher conn->client->connect_notify_context);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher }
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher}
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagherstatic void auth_server_reconnect_timeout(struct auth_server_connection *conn)
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher{
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher (void)auth_server_connection_connect(conn);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher}
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagherstatic void
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagherauth_server_connection_reconnect(struct auth_server_connection *conn,
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher const char *disconnect_reason)
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher{
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher time_t next_connect;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher auth_server_connection_disconnect(conn, disconnect_reason);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher next_connect = conn->last_connect + AUTH_SERVER_RECONNECT_TIMEOUT_SECS;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher conn->to = timeout_add(ioloop_time >= next_connect ? 0 :
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher (next_connect - ioloop_time) * 1000,
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher auth_server_reconnect_timeout, conn);
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher}
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallaghervoid auth_server_connection_deinit(struct auth_server_connection **_conn)
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher{
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher struct auth_server_connection *conn = *_conn;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher *_conn = NULL;
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher auth_server_connection_disconnect(conn, "deinitializing");
45f75fc8e98092fa48faa3d180fd42f7efd51486Stephen Gallagher i_assert(hash_table_count(conn->requests) == 0);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher hash_table_destroy(&conn->requests);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher array_free(&conn->available_auth_mechs);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher pool_unref(&conn->pool);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher}
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagherstatic void auth_client_handshake_timeout(struct auth_server_connection *conn)
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher{
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher i_error("Timeout waiting for handshake from auth server. "
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher "my pid=%u, input bytes=%"PRIuUOFF_T,
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher conn->client->client_pid, conn->input->v_offset);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher auth_server_connection_reconnect(conn, "auth server timeout");
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher}
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagherint auth_server_connection_connect(struct auth_server_connection *conn)
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek{
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek const char *handshake;
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek int fd;
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher i_assert(conn->fd == -1);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher conn->last_connect = ioloop_time;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (conn->to != NULL)
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher timeout_remove(&conn->to);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher /* max. 1 second wait here. */
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher fd = net_connect_unix_with_retries(conn->client->auth_socket_path,
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher 1000);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (fd == -1) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (errno == EACCES) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher i_error("auth: %s",
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher eacces_error_get("connect",
bfb40893be20b45279a40188cf16ef0eec1f9423Sumit Bose conn->client->auth_socket_path));
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher } else {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher i_error("auth: connect(%s) failed: %m",
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher conn->client->auth_socket_path);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher }
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher return -1;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher }
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher conn->fd = fd;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher conn->io = io_add(fd, IO_READ, auth_server_connection_input, conn);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher conn->input = i_stream_create_fd(fd, AUTH_SERVER_CONN_MAX_LINE_LENGTH,
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher FALSE);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n",
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher AUTH_CLIENT_PROTOCOL_MAJOR_VERSION,
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher AUTH_CLIENT_PROTOCOL_MINOR_VERSION,
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher conn->client->client_pid);
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (o_stream_send_str(conn->output, handshake) < 0) {
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek i_warning("Error sending handshake to auth server: %m");
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek auth_server_connection_disconnect(conn,
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek strerror(conn->output->last_failed_errno));
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek return -1;
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek }
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek conn->to = timeout_add(AUTH_HANDSHAKE_TIMEOUT,
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek auth_client_handshake_timeout, conn);
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek return 0;
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek}
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidekunsigned int
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidekauth_server_connection_add_request(struct auth_server_connection *conn,
d6f283302268520c1506fb3da4f2a22f5a741be5Michal Zidek struct auth_client_request *request)
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher{
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher unsigned int id;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher id = ++conn->client->request_id_counter;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher if (id == 0) {
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher /* wrapped - ID 0 not allowed */
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher id = ++conn->client->request_id_counter;
8be5e4497e5008f7807178acdfcbf97365ec4e73Stephen Gallagher }
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose hash_table_insert(conn->requests, POINTER_CAST(id), request);
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose return id;
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose}
b2c7b6fe7a6b9ef3af8d4d3037fe83d6e9bfd6a5Sumit Bose