auth-server-connection.c revision 991367db5ec720fa0b764bbd6df21b7f7c654d2c
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek#define AUTH_SERVER_CONN_MAX_LINE_LENGTH AUTH_CLIENT_MAX_LINE_LENGTH
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekauth_server_connection_disconnect(struct auth_server_connection *conn);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekauth_server_input_mech(struct auth_server_connection *conn,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *const *args)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek i_error("BUG: Authentication server already sent handshake");
d43c9d18fb263b1ea4071b20e93ce4994583f62fJakub Hrozek i_error("BUG: Authentication server sent broken MECH line");
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek mech_desc.name = p_strdup(conn->pool, args[0]);
5a4239490c7fb7d732180a9d40f27f0247c56631Jakub Hrozek else if (strcmp(*args, "forward-secrecy") == 0)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek array_append(&conn->available_auth_mechs, &mech_desc, 1);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekauth_server_input_spid(struct auth_server_connection *conn,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *const *args)
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov i_error("BUG: Authentication server already sent handshake");
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov conn->server_pid = (unsigned int)strtoul(args[0], NULL, 10);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekauth_server_input_cuid(struct auth_server_connection *conn,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *const *args)
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov i_error("BUG: Authentication server already sent handshake");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek i_error("BUG: Authentication server sent broken CUID line");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->connect_uid = (unsigned int)strtoul(args[0], NULL, 10);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekauth_server_input_cookie(struct auth_server_connection *conn,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *const *args)
4cae8609b513c267af11c0409bfe1d17d3a5da2fMichal Zidek i_error("BUG: Authentication server already sent cookie");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekstatic int auth_server_input_done(struct auth_server_connection *conn)
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl if (array_count(&conn->available_auth_mechs) == 0) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek i_error("BUG: Authentication server returned no mechanisms");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek i_error("BUG: Authentication server didn't send a cookie");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (conn->client->connect_notify_callback != NULL) {
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek conn->client->connect_notify_callback(conn->client, TRUE,
4cae8609b513c267af11c0409bfe1d17d3a5da2fMichal Zidekauth_server_lookup_request(struct auth_server_connection *conn,
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl unsigned int id;
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl i_error("BUG: Authentication server input missing ID");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek request = hash_table_lookup(conn->requests, POINTER_CAST(id));
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl i_error("BUG: Authentication server sent unknown id %u", id);
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl if (remove || auth_client_request_is_aborted(request))
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl hash_table_remove(conn->requests, POINTER_CAST(id));
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekauth_server_input_ok(struct auth_server_connection *conn,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *const *args)
4cae8609b513c267af11c0409bfe1d17d3a5da2fMichal Zidek if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek auth_client_request_server_input(request, AUTH_REQUEST_STATUS_OK,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekstatic int auth_server_input_cont(struct auth_server_connection *conn,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *const *args)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek i_error("BUG: Authentication server sent broken CONT line");
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek if (auth_server_lookup_request(conn, args[0], FALSE, &request) < 0)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek auth_client_request_server_input(request, AUTH_REQUEST_STATUS_CONTINUE,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekstatic int auth_server_input_fail(struct auth_server_connection *conn,
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *const *args)
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek auth_client_request_server_input(request, AUTH_REQUEST_STATUS_FAIL,
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichlauth_server_connection_input_line(struct auth_server_connection *conn,
1112e84494bcfd0f658e073d25f15ed877d047aaPavel Reichl const char *line)
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek const char *const *args;
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek return auth_server_input_cookie(conn, args + 1);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozek i_error("Auth server sent unknown command: %s", args[0]);
9cb46bc62f22e0104f1b41a423b014c281ef5fc2Jakub Hrozekstatic void auth_server_connection_input(struct auth_server_connection *conn)
1a783fb0be9a48a0abdfe8b52fce551d530487ceLukas Slebodnik /* disconnected */
1a783fb0be9a48a0abdfe8b52fce551d530487ceLukas Slebodnik /* buffer full - can't happen unless auth is buggy */
1a783fb0be9a48a0abdfe8b52fce551d530487ceLukas Slebodnik i_error("BUG: Auth server sent us more than %d bytes of data",
1a783fb0be9a48a0abdfe8b52fce551d530487ceLukas Slebodnik /* make sure the major version matches */
1a783fb0be9a48a0abdfe8b52fce551d530487ceLukas Slebodnik i_error("Authentication server not compatible with "
1a783fb0be9a48a0abdfe8b52fce551d530487ceLukas Slebodnik "this client (mixed old and new binaries?)");
1a783fb0be9a48a0abdfe8b52fce551d530487ceLukas Slebodnik while ((line = i_stream_next_line(conn->input)) != NULL) {
1a783fb0be9a48a0abdfe8b52fce551d530487ceLukas Slebodnik ret = auth_server_connection_input_line(conn, line);
aa3fd6fde3888c0e333cad852ae5b4f671d55f58Pavel Reichlauth_server_connection_init(struct auth_client *client)
aa3fd6fde3888c0e333cad852ae5b4f671d55f58Pavel Reichl pool = pool_alloconly_create("auth server connection", 1024);
aa3fd6fde3888c0e333cad852ae5b4f671d55f58Pavel Reichl conn = p_new(pool, struct auth_server_connection, 1);
aa3fd6fde3888c0e333cad852ae5b4f671d55f58Pavel Reichl conn->requests = hash_table_create(default_pool, pool, 100, NULL, NULL);
6fd5306145d98ea3bab7f32aa66475f610f388cePavel Reichlauth_server_connection_remove_requests(struct auth_server_connection *conn)
6fd5306145d98ea3bab7f32aa66475f610f388cePavel Reichl static const char *const temp_failure_args[] = { "temp", NULL };
6fd5306145d98ea3bab7f32aa66475f610f388cePavel Reichl iter = hash_table_iterate_init(conn->requests);
6fd5306145d98ea3bab7f32aa66475f610f388cePavel Reichl while (hash_table_iterate(iter, &key, &value)) {
6fd5306145d98ea3bab7f32aa66475f610f388cePavel Reichlstatic void auth_server_connection_close(struct auth_server_connection *conn)
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl i_error("close(auth server connection) failed: %m");
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl if (conn->client->connect_notify_callback != NULL) {
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl conn->client->connect_notify_callback(conn->client, FALSE,
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichlstatic void auth_server_reconnect_timeout(struct auth_server_connection *conn)
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichlauth_server_connection_disconnect(struct auth_server_connection *conn)
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl next_connect = conn->last_connect + AUTH_SERVER_RECONNECT_TIMEOUT_SECS;
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl conn->to = timeout_add(ioloop_time >= next_connect ? 0 :
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichlvoid auth_server_connection_deinit(struct auth_server_connection **_conn)
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichlstatic void auth_client_handshake_timeout(struct auth_server_connection *conn)
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl i_error("Timeout waiting for handshake from auth server. "
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl conn->client->client_pid, conn->input->v_offset);
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichlint auth_server_connection_connect(struct auth_server_connection *conn)
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl /* max. 1 second wait here. */
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl fd = net_connect_unix_with_retries(conn->client->auth_socket_path,
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl conn->io = io_add(fd, IO_READ, auth_server_connection_input, conn);
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl conn->input = i_stream_create_fd(fd, AUTH_SERVER_CONN_MAX_LINE_LENGTH,
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n",
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl if (o_stream_send_str(conn->output, handshake) < 0) {
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl i_warning("Error sending handshake to auth server: %m");
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichlauth_server_connection_add_request(struct auth_server_connection *conn,
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl unsigned int id;
b0a8ed519554f8896e35812e0759862c33f157fePavel Reichl /* wrapped - ID 0 not allowed */