auth-server-connection.c revision 3c296d819c54e21ce05c3d2eeeedc79be42ac593
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2003-2012 Dovecot authors, see the included COPYING file */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "lib.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "array.h"
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen#include "hash.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "hostpid.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "ioloop.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "istream.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "ostream.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "network.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "eacces-error.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "auth-client-private.h"
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen#include "auth-client-request.h"
2cd2518bab14292a67cf8a490b58ab9ef89879daTimo Sirainen#include "auth-server-connection.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <unistd.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <stdlib.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen#define AUTH_SERVER_CONN_MAX_LINE_LENGTH AUTH_CLIENT_MAX_LINE_LENGTH
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen#define AUTH_HANDSHAKE_TIMEOUT (30*1000)
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen#define AUTH_SERVER_RECONNECT_TIMEOUT_SECS 5
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenauth_server_connection_reconnect(struct auth_server_connection *conn,
cf2e6953d03a1c22f272ec19432fc03c136ac1bbTimo Sirainen const char *disconnect_reason);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenstatic int
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenauth_server_input_mech(struct auth_server_connection *conn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *const *args)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct auth_mech_desc mech_desc;
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (conn->handshake_received) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("BUG: Authentication server already sent handshake");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (args[0] == NULL) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen i_error("BUG: Authentication server sent broken MECH line");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen memset(&mech_desc, 0, sizeof(mech_desc));
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen mech_desc.name = p_strdup(conn->pool, args[0]);
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (strcmp(mech_desc.name, "PLAIN") == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->has_plain_mech = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (args++; *args != NULL; args++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (strcmp(*args, "private") == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mech_desc.flags |= MECH_SEC_PRIVATE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else if (strcmp(*args, "anonymous") == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mech_desc.flags |= MECH_SEC_ANONYMOUS;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else if (strcmp(*args, "plaintext") == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mech_desc.flags |= MECH_SEC_PLAINTEXT;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen else if (strcmp(*args, "dictionary") == 0)
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen mech_desc.flags |= MECH_SEC_DICTIONARY;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen else if (strcmp(*args, "active") == 0)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen mech_desc.flags |= MECH_SEC_ACTIVE;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen else if (strcmp(*args, "forward-secrecy") == 0)
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen mech_desc.flags |= MECH_SEC_FORWARD_SECRECY;
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen else if (strcmp(*args, "mutual-auth") == 0)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen mech_desc.flags |= MECH_SEC_MUTUAL_AUTH;
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen array_append(&conn->available_auth_mechs, &mech_desc, 1);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return 0;
230ef558135f16a66b86cbe3762524eaa9ae9d81Timo Sirainen}
230ef558135f16a66b86cbe3762524eaa9ae9d81Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenstatic int
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenauth_server_input_spid(struct auth_server_connection *conn,
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen const char *const *args)
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (conn->handshake_received) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_error("BUG: Authentication server already sent handshake");
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return -1;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (str_to_uint(args[0], &conn->server_pid) < 0) {
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen i_error("BUG: Authentication server sent invalid PID");
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen return -1;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen }
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen return 0;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen}
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainenstatic int
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainenauth_server_input_cuid(struct auth_server_connection *conn,
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen const char *const *args)
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen{
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen if (conn->handshake_received) {
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen i_error("BUG: Authentication server already sent handshake");
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen return -1;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen }
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (args[0] == NULL ||
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen str_to_uint(args[0], &conn->connect_uid) < 0) {
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen i_error("BUG: Authentication server sent broken CUID line");
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen return -1;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen }
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen return 0;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen}
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainenstatic int
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainenauth_server_input_cookie(struct auth_server_connection *conn,
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen const char *const *args)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen{
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (conn->cookie != NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("BUG: Authentication server already sent cookie");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen }
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen conn->cookie = p_strdup(conn->pool, args[0]);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return 0;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainenstatic int auth_server_input_done(struct auth_server_connection *conn)
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen{
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen if (array_count(&conn->available_auth_mechs) == 0) {
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen i_error("BUG: Authentication server returned no mechanisms");
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen return -1;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen }
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen if (conn->cookie == NULL) {
dc07b75b7ea83ff5f447970a20419032725271a7Timo Sirainen i_error("BUG: Authentication server didn't send a cookie");
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen return -1;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen }
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen if (conn->to != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen timeout_remove(&conn->to);
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen conn->handshake_received = TRUE;
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen if (conn->client->connect_notify_callback != NULL) {
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen conn->client->connect_notify_callback(conn->client, TRUE,
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen conn->client->connect_notify_context);
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen }
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainenstatic int
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainenauth_server_lookup_request(struct auth_server_connection *conn,
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen const char *id_arg, bool remove,
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen struct auth_client_request **request_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct auth_client_request *request;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int id;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (id_arg == NULL || str_to_uint(id_arg, &id) < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("BUG: Authentication server input missing ID");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen request = hash_table_lookup(conn->requests, POINTER_CAST(id));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (request == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("BUG: Authentication server sent unknown id %u", id);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (remove || auth_client_request_is_aborted(request))
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen hash_table_remove(conn->requests, POINTER_CAST(id));
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *request_r = request;
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainenstatic int
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenauth_server_input_ok(struct auth_server_connection *conn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *const *args)
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen{
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen struct auth_client_request *request;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen return -1;
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen auth_client_request_server_input(request, AUTH_REQUEST_STATUS_OK,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen args + 1);
614529ee060755c0b282102b70daf56bcd64222dTimo Sirainen return 0;
9ebd0c59de5f8240c0dbc58773fe5679391199dbTimo Sirainen}
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int auth_server_input_cont(struct auth_server_connection *conn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *const *args)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct auth_client_request *request;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (str_array_length(args) < 2) {
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen i_error("BUG: Authentication server sent broken CONT line");
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen return -1;
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen }
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen if (auth_server_lookup_request(conn, args[0], FALSE, &request) < 0)
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_client_request_server_input(request, AUTH_REQUEST_STATUS_CONTINUE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen args + 1);
4b2a1030f9b51e90f6ff4cdbc115871a398c1e0fTimo Sirainen return 0;
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen}
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstatic int auth_server_input_fail(struct auth_server_connection *conn,
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen const char *const *args)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct auth_client_request *request;
9e291f6a7ca67b86d1d65a730ffb71fb9a334fb0Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_client_request_server_input(request, AUTH_REQUEST_STATUS_FAIL,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen args + 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenauth_server_connection_input_line(struct auth_server_connection *conn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *line)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *const *args;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (conn->client->debug)
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen i_debug("auth input: %s", line);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen args = t_strsplit_tab(line);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (args[0] == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("Auth server sent empty line");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (strcmp(args[0], "OK") == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return auth_server_input_ok(conn, args + 1);
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen else if (strcmp(args[0], "CONT") == 0)
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen return auth_server_input_cont(conn, args + 1);
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen else if (strcmp(args[0], "FAIL") == 0)
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen return auth_server_input_fail(conn, args + 1);
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen else if (strcmp(args[0], "MECH") == 0)
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen return auth_server_input_mech(conn, args + 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else if (strcmp(args[0], "SPID") == 0)
d482079eb385cd071bbc9637cacee225e4aff968Timo Sirainen return auth_server_input_spid(conn, args + 1);
9e291f6a7ca67b86d1d65a730ffb71fb9a334fb0Timo Sirainen else if (strcmp(args[0], "CUID") == 0)
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen return auth_server_input_cuid(conn, args + 1);
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen else if (strcmp(args[0], "COOKIE") == 0)
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen return auth_server_input_cookie(conn, args + 1);
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen else if (strcmp(args[0], "DONE") == 0)
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen return auth_server_input_done(conn);
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen else {
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen i_error("Auth server sent unknown command: %s", args[0]);
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen return -1;
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen }
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void auth_server_connection_input(struct auth_server_connection *conn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct istream *input;
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen const char *line, *error;
0547a828ee9647fc5fd2e359b145774740a697feTimo Sirainen int ret;
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen switch (i_stream_read(conn->input)) {
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen case 0:
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen return;
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen case -1:
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen /* disconnected */
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen error = conn->input->stream_errno != 0 ?
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen strerror(conn->input->stream_errno) : "EOF";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_server_connection_reconnect(conn, error);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case -2:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* buffer full - can't happen unless auth is buggy */
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen i_error("BUG: Auth server sent us more than %d bytes of data",
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen AUTH_SERVER_CONN_MAX_LINE_LENGTH);
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen auth_server_connection_disconnect(conn, "buffer full");
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen if (!conn->version_received) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen line = i_stream_next_line(conn->input);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (line == NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen /* make sure the major version matches */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (strncmp(line, "VERSION\t", 8) != 0 ||
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen !str_uint_equals(t_strcut(line + 8, '\t'),
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen AUTH_CLIENT_PROTOCOL_MAJOR_VERSION)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("Authentication server not compatible with "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "this client (mixed old and new binaries?)");
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen auth_server_connection_disconnect(conn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "incompatible serevr");
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen return;
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen }
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen conn->version_received = TRUE;
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen }
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainen
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainen input = conn->input;
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen i_stream_ref(input);
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen while ((line = i_stream_next_line(input)) != NULL && !input->closed) {
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen T_BEGIN {
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen ret = auth_server_connection_input_line(conn, line);
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen } T_END;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen if (ret < 0) {
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen auth_server_connection_disconnect(conn, t_strdup_printf(
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen "Received broken input: %s", line));
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen break;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen }
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen }
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen i_stream_unref(&input);
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen}
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainenstruct auth_server_connection *
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenauth_server_connection_init(struct auth_client *client)
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct auth_server_connection *conn;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen pool_t pool;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen pool = pool_alloconly_create("auth server connection", 1024);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn = p_new(pool, struct auth_server_connection, 1);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen conn->pool = pool;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen conn->client = client;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->fd = -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->requests = hash_table_create(default_pool, pool, 100, NULL, NULL);
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen i_array_init(&conn->available_auth_mechs, 8);
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen return conn;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainenauth_server_connection_remove_requests(struct auth_server_connection *conn,
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen const char *disconnect_reason)
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen{
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen static const char *const temp_failure_args[] = { "temp", NULL };
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen struct hash_iterate_context *iter;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen void *key, *value;
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen time_t created, oldest = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int request_count = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen if (hash_table_count(conn->requests) == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen iter = hash_table_iterate_init(conn->requests);
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen while (hash_table_iterate(iter, &key, &value)) {
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen struct auth_client_request *request = value;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!auth_client_request_is_aborted(request)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen request_count++;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen created = auth_client_request_get_create_time(request);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (oldest > created || oldest == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen oldest = created;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_client_request_server_input(request,
2cd2518bab14292a67cf8a490b58ab9ef89879daTimo Sirainen AUTH_REQUEST_STATUS_INTERNAL_FAIL,
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen temp_failure_args);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen hash_table_iterate_deinit(&iter);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen hash_table_clear(conn->requests, FALSE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (request_count > 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_warning("Auth connection closed with %u pending requests "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "(max %u secs, pid=%s, %s)", request_count,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (unsigned int)(ioloop_time - oldest),
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen my_pid, disconnect_reason);
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid auth_server_connection_disconnect(struct auth_server_connection *conn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *reason)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen conn->handshake_received = FALSE;
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen conn->version_received = FALSE;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen conn->has_plain_mech = FALSE;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen conn->server_pid = 0;
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen conn->connect_uid = 0;
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen conn->cookie = NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_clear(&conn->available_auth_mechs);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (conn->to != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen timeout_remove(&conn->to);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (conn->io != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen io_remove(&conn->io);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (conn->fd != -1) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_destroy(&conn->input);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen o_stream_destroy(&conn->output);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (close(conn->fd) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("close(auth server connection) failed: %m");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->fd = -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_server_connection_remove_requests(conn, reason);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (conn->client->connect_notify_callback != NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->client->connect_notify_callback(conn->client, FALSE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->client->connect_notify_context);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void auth_server_reconnect_timeout(struct auth_server_connection *conn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (void)auth_server_connection_connect(conn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenauth_server_connection_reconnect(struct auth_server_connection *conn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *disconnect_reason)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen time_t next_connect;
614529ee060755c0b282102b70daf56bcd64222dTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_server_connection_disconnect(conn, disconnect_reason);
19d01d72f98e7f28a1d8aed146adb6a777158092Timo Sirainen
61618d4c58080570f689614fec204ae14e90cef2Timo Sirainen next_connect = conn->last_connect + AUTH_SERVER_RECONNECT_TIMEOUT_SECS;
19d01d72f98e7f28a1d8aed146adb6a777158092Timo Sirainen conn->to = timeout_add(ioloop_time >= next_connect ? 0 :
61618d4c58080570f689614fec204ae14e90cef2Timo Sirainen (next_connect - ioloop_time) * 1000,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_server_reconnect_timeout, conn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid auth_server_connection_deinit(struct auth_server_connection **_conn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct auth_server_connection *conn = *_conn;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *_conn = NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_server_connection_disconnect(conn, "deinitializing");
129db31de1780783a175633eba5811e44c361a81Timo Sirainen i_assert(hash_table_count(conn->requests) == 0);
129db31de1780783a175633eba5811e44c361a81Timo Sirainen hash_table_destroy(&conn->requests);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_free(&conn->available_auth_mechs);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen pool_unref(&conn->pool);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void auth_client_handshake_timeout(struct auth_server_connection *conn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("Timeout waiting for handshake from auth server. "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "my pid=%u, input bytes=%"PRIuUOFF_T,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->client->client_pid, conn->input->v_offset);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_server_connection_reconnect(conn, "auth server timeout");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint auth_server_connection_connect(struct auth_server_connection *conn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *handshake;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int fd;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(conn->fd == -1);
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen
114162093a3eb36c23a4ce4d4f2a43541dc18cc2Timo Sirainen conn->last_connect = ioloop_time;
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen if (conn->to != NULL)
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen timeout_remove(&conn->to);
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* max. 1 second wait here. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen fd = net_connect_unix_with_retries(conn->client->auth_socket_path,
114162093a3eb36c23a4ce4d4f2a43541dc18cc2Timo Sirainen 1000);
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen if (fd == -1) {
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen if (errno == EACCES) {
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen i_error("auth: %s",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen eacces_error_get("connect",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->client->auth_socket_path));
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen } else {
129db31de1780783a175633eba5811e44c361a81Timo Sirainen i_error("auth: connect(%s) failed: %m",
129db31de1780783a175633eba5811e44c361a81Timo Sirainen conn->client->auth_socket_path);
dfcc56dc6c485fe45a3fa18325f047bfaae65019Timo Sirainen }
dfcc56dc6c485fe45a3fa18325f047bfaae65019Timo Sirainen return -1;
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen }
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen conn->fd = fd;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->io = io_add(fd, IO_READ, auth_server_connection_input, conn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->input = i_stream_create_fd(fd, AUTH_SERVER_CONN_MAX_LINE_LENGTH,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen FALSE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen AUTH_CLIENT_PROTOCOL_MAJOR_VERSION,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen AUTH_CLIENT_PROTOCOL_MINOR_VERSION,
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen conn->client->client_pid);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (o_stream_send_str(conn->output, handshake) < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_warning("Error sending handshake to auth server: %m");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_server_connection_disconnect(conn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen strerror(conn->output->last_failed_errno));
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen conn->to = timeout_add(AUTH_HANDSHAKE_TIMEOUT,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen auth_client_handshake_timeout, conn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenunsigned int
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenauth_server_connection_add_request(struct auth_server_connection *conn,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct auth_client_request *request)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int id;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen id = ++conn->client->request_id_counter;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (id == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* wrapped - ID 0 not allowed */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen id = ++conn->client->request_id_counter;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen hash_table_insert(conn->requests, POINTER_CAST(id), request);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return id;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen