auth-server-connection.c revision bdd36cfdba3ff66d25570a9ff568d69e1eb543cf
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "lib.h"
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#include "array.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "hash.h"
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen#include "hostpid.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "ioloop.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "istream.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "ostream.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#include "eacces-error.h"
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#include "auth-client-private.h"
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#include "auth-client-request.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include "auth-server-connection.h"
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen#include <unistd.h>
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen#include <stdlib.h>
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#define AUTH_SERVER_CONN_MAX_LINE_LENGTH AUTH_CLIENT_MAX_LINE_LENGTH
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen#define AUTH_HANDSHAKE_TIMEOUT (30*1000)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#define AUTH_SERVER_RECONNECT_TIMEOUT_SECS 5
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic void
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainenauth_server_connection_reconnect(struct auth_server_connection *conn,
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen const char *disconnect_reason);
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_input_mech(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen struct auth_mech_desc mech_desc;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (conn->handshake_received) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Authentication server already sent handshake");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (args[0] == NULL) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Authentication server sent broken MECH line");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen memset(&mech_desc, 0, sizeof(mech_desc));
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen mech_desc.name = p_strdup(conn->pool, args[0]);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (strcmp(mech_desc.name, "PLAIN") == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen conn->has_plain_mech = TRUE;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen for (args++; *args != NULL; args++) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (strcmp(*args, "private") == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen mech_desc.flags |= MECH_SEC_PRIVATE;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(*args, "anonymous") == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen mech_desc.flags |= MECH_SEC_ANONYMOUS;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(*args, "plaintext") == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen mech_desc.flags |= MECH_SEC_PLAINTEXT;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(*args, "dictionary") == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen mech_desc.flags |= MECH_SEC_DICTIONARY;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(*args, "active") == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen mech_desc.flags |= MECH_SEC_ACTIVE;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(*args, "forward-secrecy") == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen mech_desc.flags |= MECH_SEC_FORWARD_SECRECY;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(*args, "mutual-auth") == 0)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen mech_desc.flags |= MECH_SEC_MUTUAL_AUTH;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen array_append(&conn->available_auth_mechs, &mech_desc, 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return 0;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_input_spid(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (conn->handshake_received) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Authentication server already sent handshake");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (str_to_uint(args[0], &conn->server_pid) < 0) {
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen i_error("BUG: Authentication server sent invalid PID");
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen return -1;
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return 0;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_input_cuid(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen{
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (conn->handshake_received) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Authentication server already sent handshake");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen }
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (args[0] == NULL ||
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen str_to_uint(args[0], &conn->connect_uid) < 0) {
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen i_error("BUG: Authentication server sent broken CUID line");
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen return -1;
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return 0;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen}
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainenstatic int
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainenauth_server_input_cookie(struct auth_server_connection *conn,
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen const char *const *args)
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen{
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen if (conn->cookie != NULL) {
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen i_error("BUG: Authentication server already sent cookie");
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen return -1;
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen }
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen conn->cookie = p_strdup(conn->pool, args[0]);
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen return 0;
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen}
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int auth_server_input_done(struct auth_server_connection *conn)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (array_count(&conn->available_auth_mechs) == 0) {
e2ae85924b0ef1a7c97e021a3b901b498f599c18Timo Sirainen i_error("BUG: Authentication server returned no mechanisms");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
e2ae85924b0ef1a7c97e021a3b901b498f599c18Timo Sirainen }
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen if (conn->cookie == NULL) {
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen i_error("BUG: Authentication server didn't send a cookie");
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen return -1;
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen }
e2ae85924b0ef1a7c97e021a3b901b498f599c18Timo Sirainen
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen if (conn->to != NULL)
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen timeout_remove(&conn->to);
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen conn->handshake_received = TRUE;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (conn->client->connect_notify_callback != NULL) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->client->connect_notify_callback(conn->client, TRUE,
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->client->connect_notify_context);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return 0;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen}
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_lookup_request(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *id_arg, bool remove,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen struct auth_client_request **request_r)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen struct auth_client_request *request;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen unsigned int id;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen if (id_arg == NULL || str_to_uint(id_arg, &id) < 0) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("BUG: Authentication server input missing ID");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen request = hash_table_lookup(conn->requests, POINTER_CAST(id));
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (request == NULL) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("BUG: Authentication server sent unknown id %u", id);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (remove || auth_client_request_is_aborted(request))
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen hash_table_remove(conn->requests, POINTER_CAST(id));
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen *request_r = request;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return 0;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen}
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_input_ok(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen struct auth_client_request *request;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen auth_client_request_server_input(request, AUTH_REQUEST_STATUS_OK,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return 0;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen}
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int auth_server_input_cont(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen struct auth_client_request *request;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (str_array_length(args) < 2) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("BUG: Authentication server sent broken CONT line");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (auth_server_lookup_request(conn, args[0], FALSE, &request) < 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen auth_client_request_server_input(request, AUTH_REQUEST_STATUS_CONTINUE,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return 0;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen}
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int auth_server_input_fail(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen struct auth_client_request *request;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen auth_client_request_server_input(request, AUTH_REQUEST_STATUS_FAIL,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return 0;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_connection_input_line(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *line)
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (conn->client->debug)
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk i_debug("auth input: %s", line);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
3c296d819c54e21ce05c3d2eeeedc79be42ac593Timo Sirainen args = t_strsplit_tab(line);
31fda2fc79d48e5186163972b52eb97b4bd8b6fdTimo Sirainen if (args[0] == NULL) {
31fda2fc79d48e5186163972b52eb97b4bd8b6fdTimo Sirainen i_error("Auth server sent empty line");
31fda2fc79d48e5186163972b52eb97b4bd8b6fdTimo Sirainen return -1;
31fda2fc79d48e5186163972b52eb97b4bd8b6fdTimo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (strcmp(args[0], "OK") == 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_ok(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(args[0], "CONT") == 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_cont(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(args[0], "FAIL") == 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_fail(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(args[0], "MECH") == 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_mech(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(args[0], "SPID") == 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_spid(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(args[0], "CUID") == 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_cuid(conn, args + 1);
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen else if (strcmp(args[0], "COOKIE") == 0)
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen return auth_server_input_cookie(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(args[0], "DONE") == 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_done(conn);
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen else {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("Auth server sent unknown command: %s", args[0]);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen }
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic void auth_server_connection_input(struct auth_server_connection *conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
b6e1d85292485a7fb4cfa5f40dd1ec131ab07cc1Timo Sirainen struct istream *input;
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen const char *line, *error;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen int ret;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen switch (i_stream_read(conn->input)) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen case 0:
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen case -1:
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* disconnected */
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen error = conn->input->stream_errno != 0 ?
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen strerror(conn->input->stream_errno) : "EOF";
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen auth_server_connection_reconnect(conn, error);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen case -2:
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* buffer full - can't happen unless auth is buggy */
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen i_error("BUG: Auth server sent us more than %d bytes of data",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen AUTH_SERVER_CONN_MAX_LINE_LENGTH);
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen auth_server_connection_disconnect(conn, "buffer full");
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (!conn->version_received) {
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen line = i_stream_next_line(conn->input);
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen if (line == NULL)
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen return;
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen /* make sure the major version matches */
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen if (strncmp(line, "VERSION\t", 8) != 0 ||
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen !str_uint_equals(t_strcut(line + 8, '\t'),
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen AUTH_CLIENT_PROTOCOL_MAJOR_VERSION)) {
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen i_error("Authentication server not compatible with "
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen "this client (mixed old and new binaries?)");
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen auth_server_connection_disconnect(conn,
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen "incompatible serevr");
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen return;
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen }
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen conn->version_received = TRUE;
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen }
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen
b6e1d85292485a7fb4cfa5f40dd1ec131ab07cc1Timo Sirainen input = conn->input;
b6e1d85292485a7fb4cfa5f40dd1ec131ab07cc1Timo Sirainen i_stream_ref(input);
b6e1d85292485a7fb4cfa5f40dd1ec131ab07cc1Timo Sirainen while ((line = i_stream_next_line(input)) != NULL && !input->closed) {
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen T_BEGIN {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen ret = auth_server_connection_input_line(conn, line);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (ret < 0) {
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen auth_server_connection_disconnect(conn, t_strdup_printf(
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen "Received broken input: %s", line));
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen break;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen }
b6e1d85292485a7fb4cfa5f40dd1ec131ab07cc1Timo Sirainen i_stream_unref(&input);
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen}
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstruct auth_server_connection *
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_connection_init(struct auth_client *client)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_server_connection *conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen pool_t pool;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen pool = pool_alloconly_create("auth server connection", 1024);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn = p_new(pool, struct auth_server_connection, 1);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->pool = pool;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->client = client;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->fd = -1;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen hash_table_create_direct(&conn->requests, pool, 100);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_array_init(&conn->available_auth_mechs, 8);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen return conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic void
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainenauth_server_connection_remove_requests(struct auth_server_connection *conn,
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen const char *disconnect_reason)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen static const char *const temp_failure_args[] = { "temp", NULL };
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen struct hash_iterate_context *iter;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen void *key;
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen struct auth_client_request *request;
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen time_t created, oldest = 0;
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen unsigned int request_count = 0;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen if (hash_table_count(conn->requests) == 0)
742b9a0fc1d5513552fe99aa726497d1250d762eTimo Sirainen return;
742b9a0fc1d5513552fe99aa726497d1250d762eTimo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen iter = hash_table_iterate_init(conn->requests);
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen while (hash_table_iterate(iter, conn->requests, &key, &request)) {
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen if (!auth_client_request_is_aborted(request)) {
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen request_count++;
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen created = auth_client_request_get_create_time(request);
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen if (oldest > created || oldest == 0)
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen oldest = created;
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen }
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen auth_client_request_server_input(request,
7c849dbc7be089175c1a83a84ee7249ed695810dTimo Sirainen AUTH_REQUEST_STATUS_INTERNAL_FAIL,
7c849dbc7be089175c1a83a84ee7249ed695810dTimo Sirainen temp_failure_args);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen hash_table_iterate_deinit(&iter);
bf05bf725add3686bdb1cb2723208b1562596d17Timo Sirainen hash_table_clear(conn->requests, FALSE);
84de4076ab3a33b34049a46e72ee0456afad8ad4Timo Sirainen
84de4076ab3a33b34049a46e72ee0456afad8ad4Timo Sirainen if (request_count > 0) {
84de4076ab3a33b34049a46e72ee0456afad8ad4Timo Sirainen i_warning("Auth connection closed with %u pending requests "
84de4076ab3a33b34049a46e72ee0456afad8ad4Timo Sirainen "(max %u secs, pid=%s, %s)", request_count,
84de4076ab3a33b34049a46e72ee0456afad8ad4Timo Sirainen (unsigned int)(ioloop_time - oldest),
84de4076ab3a33b34049a46e72ee0456afad8ad4Timo Sirainen my_pid, disconnect_reason);
84de4076ab3a33b34049a46e72ee0456afad8ad4Timo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainenvoid auth_server_connection_disconnect(struct auth_server_connection *conn,
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen const char *reason)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen{
991367db5ec720fa0b764bbd6df21b7f7c654d2cTimo Sirainen conn->handshake_received = FALSE;
991367db5ec720fa0b764bbd6df21b7f7c654d2cTimo Sirainen conn->version_received = FALSE;
991367db5ec720fa0b764bbd6df21b7f7c654d2cTimo Sirainen conn->has_plain_mech = FALSE;
991367db5ec720fa0b764bbd6df21b7f7c654d2cTimo Sirainen conn->server_pid = 0;
991367db5ec720fa0b764bbd6df21b7f7c654d2cTimo Sirainen conn->connect_uid = 0;
991367db5ec720fa0b764bbd6df21b7f7c654d2cTimo Sirainen conn->cookie = NULL;
991367db5ec720fa0b764bbd6df21b7f7c654d2cTimo Sirainen array_clear(&conn->available_auth_mechs);
991367db5ec720fa0b764bbd6df21b7f7c654d2cTimo Sirainen
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen if (conn->to != NULL)
0cb5a9bfbf40b3b323956792aa13d342a459585eTimo Sirainen timeout_remove(&conn->to);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (conn->io != NULL)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen io_remove(&conn->io);
e63aa0fe623cee01975d57755381e2b873e5bf93Timo Sirainen if (conn->fd != -1) {
e63aa0fe623cee01975d57755381e2b873e5bf93Timo Sirainen i_stream_destroy(&conn->input);
e63aa0fe623cee01975d57755381e2b873e5bf93Timo Sirainen o_stream_destroy(&conn->output);
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen
e63aa0fe623cee01975d57755381e2b873e5bf93Timo Sirainen if (close(conn->fd) < 0)
e63aa0fe623cee01975d57755381e2b873e5bf93Timo Sirainen i_error("close(auth server connection) failed: %m");
e63aa0fe623cee01975d57755381e2b873e5bf93Timo Sirainen conn->fd = -1;
e63aa0fe623cee01975d57755381e2b873e5bf93Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen auth_server_connection_remove_requests(conn, reason);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (conn->client->connect_notify_callback != NULL) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->client->connect_notify_callback(conn->client, FALSE,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->client->connect_notify_context);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic void auth_server_reconnect_timeout(struct auth_server_connection *conn)
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen (void)auth_server_connection_connect(conn);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen}
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic void
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainenauth_server_connection_reconnect(struct auth_server_connection *conn,
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen const char *disconnect_reason)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen time_t next_connect;
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen auth_server_connection_disconnect(conn, disconnect_reason);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen next_connect = conn->last_connect + AUTH_SERVER_RECONNECT_TIMEOUT_SECS;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->to = timeout_add(ioloop_time >= next_connect ? 0 :
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen (next_connect - ioloop_time) * 1000,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen auth_server_reconnect_timeout, conn);
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen}
a272994d43de80a306a8ed1f2983960d1f3102d0Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenvoid auth_server_connection_deinit(struct auth_server_connection **_conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen struct auth_server_connection *conn = *_conn;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen *_conn = NULL;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen auth_server_connection_disconnect(conn, "deinitializing");
742b9a0fc1d5513552fe99aa726497d1250d762eTimo Sirainen i_assert(hash_table_count(conn->requests) == 0);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen hash_table_destroy(&conn->requests);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen array_free(&conn->available_auth_mechs);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen pool_unref(&conn->pool);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic void auth_client_handshake_timeout(struct auth_server_connection *conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("Timeout waiting for handshake from auth server. "
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen "my pid=%u, input bytes=%"PRIuUOFF_T,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->client->client_pid, conn->input->v_offset);
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen auth_server_connection_reconnect(conn, "auth server timeout");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen}
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenint auth_server_connection_connect(struct auth_server_connection *conn)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *handshake;
21c1655dbc5fe861a152dc9a8a388d0d64f5ae20Timo Sirainen int fd;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_assert(conn->fd == -1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->last_connect = ioloop_time;
366e81c4f5329857fefb4bc7751fb72d5dd28959Timo Sirainen if (conn->to != NULL)
366e81c4f5329857fefb4bc7751fb72d5dd28959Timo Sirainen timeout_remove(&conn->to);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* max. 1 second wait here. */
21c1655dbc5fe861a152dc9a8a388d0d64f5ae20Timo Sirainen fd = net_connect_unix_with_retries(conn->client->auth_socket_path,
21c1655dbc5fe861a152dc9a8a388d0d64f5ae20Timo Sirainen 1000);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (fd == -1) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (errno == EACCES) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("auth: %s",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen eacces_error_get("connect",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->client->auth_socket_path));
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen } else {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("auth: connect(%s) failed: %m",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->client->auth_socket_path);
d1414c09cf0d58ac983054e2f4e1a1f329272dcfTimo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen }
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->fd = fd;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->io = io_add(fd, IO_READ, auth_server_connection_input, conn);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->input = i_stream_create_fd(fd, AUTH_SERVER_CONN_MAX_LINE_LENGTH,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen FALSE);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen AUTH_CLIENT_PROTOCOL_MAJOR_VERSION,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen AUTH_CLIENT_PROTOCOL_MINOR_VERSION,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->client->client_pid);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (o_stream_send_str(conn->output, handshake) < 0) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_warning("Error sending handshake to auth server: %m");
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen auth_server_connection_disconnect(conn,
9ddd3d7d8651985e373a6c48e0ddc76b8a4ef1c7Timo Sirainen strerror(conn->output->last_failed_errno));
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return -1;
f540662dd02e930cf704c1468cccd05d512bc663Timo Sirainen }
f540662dd02e930cf704c1468cccd05d512bc663Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->to = timeout_add(AUTH_HANDSHAKE_TIMEOUT,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen auth_client_handshake_timeout, conn);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return 0;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen}
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenunsigned int
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_connection_add_request(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen struct auth_client_request *request)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen{
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen unsigned int id;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen id = ++conn->client->request_id_counter;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (id == 0) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* wrapped - ID 0 not allowed */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen id = ++conn->client->request_id_counter;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen }
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen hash_table_insert(conn->requests, POINTER_CAST(id), request);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return id;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen}