auth-server-connection.c revision 366e81c4f5329857fefb4bc7751fb72d5dd28959
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen#define AUTH_SERVER_CONN_MAX_LINE_LENGTH AUTH_CLIENT_MAX_LINE_LENGTH
63b70dd3e4b4d68a02b1bf7d78e92076210e3e1aTimo Sirainenauth_server_connection_reconnect(struct auth_server_connection *conn);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_input_mech(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Authentication server already sent handshake");
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Authentication server sent broken MECH line");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen mech_desc.name = p_strdup(conn->pool, args[0]);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen else if (strcmp(*args, "forward-secrecy") == 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen array_append(&conn->available_auth_mechs, &mech_desc, 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_input_spid(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Authentication server already sent handshake");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->server_pid = (unsigned int)strtoul(args[0], NULL, 10);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_input_cuid(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Authentication server already sent handshake");
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen i_error("BUG: Authentication server sent broken CUID line");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->connect_uid = (unsigned int)strtoul(args[0], NULL, 10);
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainenauth_server_input_cookie(struct auth_server_connection *conn,
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen const char *const *args)
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen i_error("BUG: Authentication server already sent cookie");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int auth_server_input_done(struct auth_server_connection *conn)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (array_count(&conn->available_auth_mechs) == 0) {
e2ae85924b0ef1a7c97e021a3b901b498f599c18Timo Sirainen i_error("BUG: Authentication server returned no mechanisms");
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen i_error("BUG: Authentication server didn't send a cookie");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (conn->client->connect_notify_callback != NULL) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn->client->connect_notify_callback(conn->client, TRUE,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_lookup_request(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen unsigned int id;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("BUG: Authentication server input missing ID");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen request = hash_table_lookup(conn->requests, POINTER_CAST(id));
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("BUG: Authentication server sent unknown id %u", id);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (remove || auth_client_request_is_aborted(request))
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen hash_table_remove(conn->requests, POINTER_CAST(id));
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_input_ok(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen auth_client_request_server_input(request, AUTH_REQUEST_STATUS_OK,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int auth_server_input_cont(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("BUG: Authentication server sent broken CONT line");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (auth_server_lookup_request(conn, args[0], FALSE, &request) < 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen auth_client_request_server_input(request, AUTH_REQUEST_STATUS_CONTINUE,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic int auth_server_input_fail(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen auth_client_request_server_input(request, AUTH_REQUEST_STATUS_FAIL,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_connection_input_line(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen const char *const *args;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_cont(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_fail(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_mech(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_spid(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen return auth_server_input_cuid(conn, args + 1);
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen return auth_server_input_cookie(conn, args + 1);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("Auth server sent unknown command: %s", args[0]);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic void auth_server_connection_input(struct auth_server_connection *conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* disconnected */
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",
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen /* make sure the major version matches */
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen i_error("Authentication server not compatible with "
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen "this client (mixed old and new binaries?)");
b6e1d85292485a7fb4cfa5f40dd1ec131ab07cc1Timo Sirainen while ((line = i_stream_next_line(input)) != NULL && !input->closed) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen ret = auth_server_connection_input_line(conn, line);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_connection_init(struct auth_client *client)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen pool = pool_alloconly_create("auth server connection", 1024);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn = p_new(pool, struct auth_server_connection, 1);
3ccab0bac68040f179a7de45c516cec258e28fdbTimo Sirainen conn->requests = hash_table_create(default_pool, pool, 100, NULL, NULL);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_connection_remove_requests(struct auth_server_connection *conn)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen static const char *const temp_failure_args[] = { "temp", NULL };
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen iter = hash_table_iterate_init(conn->requests);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen while (hash_table_iterate(iter, &key, &value)) {
63b70dd3e4b4d68a02b1bf7d78e92076210e3e1aTimo Sirainenvoid auth_server_connection_disconnect(struct auth_server_connection *conn)
e63aa0fe623cee01975d57755381e2b873e5bf93Timo Sirainen i_error("close(auth server connection) failed: %m");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (conn->client->connect_notify_callback != NULL) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->client->connect_notify_callback(conn->client, FALSE,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic void auth_server_reconnect_timeout(struct auth_server_connection *conn)
63b70dd3e4b4d68a02b1bf7d78e92076210e3e1aTimo Sirainenauth_server_connection_reconnect(struct auth_server_connection *conn)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen next_connect = conn->last_connect + AUTH_SERVER_RECONNECT_TIMEOUT_SECS;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->to = timeout_add(ioloop_time >= next_connect ? 0 :
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenvoid auth_server_connection_deinit(struct auth_server_connection **_conn)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenstatic void auth_client_handshake_timeout(struct auth_server_connection *conn)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_error("Timeout waiting for handshake from auth server. "
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->client->client_pid, conn->input->v_offset);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenint auth_server_connection_connect(struct auth_server_connection *conn)
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* max. 1 second wait here. */
21c1655dbc5fe861a152dc9a8a388d0d64f5ae20Timo Sirainen fd = net_connect_unix_with_retries(conn->client->auth_socket_path,
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 conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n",
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen if (o_stream_send_str(conn->output, handshake) < 0) {
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen i_warning("Error sending handshake to auth server: %m");
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen conn->to = timeout_add(AUTH_HANDSHAKE_TIMEOUT,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainenauth_server_connection_add_request(struct auth_server_connection *conn,
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen unsigned int id;
9137c55411aa39d41c1e705ddc34d5bd26c65021Timo Sirainen /* wrapped - ID 0 not allowed */