auth-server-connection.c revision b6e1d85292485a7fb4cfa5f40dd1ec131ab07cc1
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi#define AUTH_SERVER_CONN_MAX_LINE_LENGTH AUTH_CLIENT_MAX_LINE_LENGTH
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanianauth_server_connection_disconnect(struct auth_server_connection *conn);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiauth_server_input_mech(struct auth_server_connection *conn,
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian const char *const *args)
14ea4bb737263733ad80a36b4f73f681c30a6b45sd i_error("BUG: Authentication server already sent handshake");
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi i_error("BUG: Authentication server sent broken MECH line");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi array_append(&conn->available_auth_mechs, &mech_desc, 1);
d5ea2ced3a0abbaf6cd28ea669168246d35920e7Scott Davenportauth_server_input_spid(struct auth_server_connection *conn,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const char *const *args)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi i_error("BUG: Authentication server already sent handshake");
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi conn->server_pid = (unsigned int)strtoul(args[0], NULL, 10);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiauth_server_input_cuid(struct auth_server_connection *conn,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const char *const *args)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi i_error("BUG: Authentication server already sent handshake");
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi i_error("BUG: Authentication server sent broken CUID line");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi conn->connect_uid = (unsigned int)strtoul(args[0], NULL, 10);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiauth_server_input_cookie(struct auth_server_connection *conn,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const char *const *args)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi i_error("BUG: Authentication server already sent cookie");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic int auth_server_input_done(struct auth_server_connection *conn)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi i_error("BUG: Authentication server returned no mechanisms");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi i_error("BUG: Authentication server didn't send a cookie");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi conn->client->connect_notify_callback(conn->client, TRUE,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiauth_server_lookup_request(struct auth_server_connection *conn,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi unsigned int id;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi i_error("BUG: Authentication server input missing ID");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi request = hash_table_lookup(conn->requests, POINTER_CAST(id));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi i_error("BUG: Authentication server sent unknown id %u", id);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (remove || auth_client_request_is_aborted(request))
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiauth_server_input_ok(struct auth_server_connection *conn,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const char *const *args)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi auth_client_request_server_input(request, AUTH_REQUEST_STATUS_OK,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic int auth_server_input_cont(struct auth_server_connection *conn,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const char *const *args)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi i_error("BUG: Authentication server sent broken CONT line");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (auth_server_lookup_request(conn, args[0], FALSE, &request) < 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi auth_client_request_server_input(request, AUTH_REQUEST_STATUS_CONTINUE,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic int auth_server_input_fail(struct auth_server_connection *conn,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const char *const *args)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (auth_server_lookup_request(conn, args[0], TRUE, &request) < 0)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi auth_client_request_server_input(request, AUTH_REQUEST_STATUS_FAIL,
14ea4bb737263733ad80a36b4f73f681c30a6b45sdauth_server_connection_input_line(struct auth_server_connection *conn,
7bebe46c240b554f47faeed19186123896281967jc const char *line)
14ea4bb737263733ad80a36b4f73f681c30a6b45sd const char *const *args;
14ea4bb737263733ad80a36b4f73f681c30a6b45sd i_error("Auth server sent unknown command: %s", args[0]);
14ea4bb737263733ad80a36b4f73f681c30a6b45sd return -1;
7bebe46c240b554f47faeed19186123896281967jcstatic void auth_server_connection_input(struct auth_server_connection *conn)
7bebe46c240b554f47faeed19186123896281967jc const char *line;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* disconnected */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* buffer full - can't happen unless auth is buggy */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi i_error("BUG: Auth server sent us more than %d bytes of data",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* make sure the major version matches */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi "this client (mixed old and new binaries?)");
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi while ((line = i_stream_next_line(input)) != NULL && !input->closed) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (ret < 0) {
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian pool = pool_alloconly_create("auth server connection", 1024);
7bebe46c240b554f47faeed19186123896281967jc conn->requests = hash_table_create(default_pool, pool, 100, NULL, NULL);
7bebe46c240b554f47faeed19186123896281967jcauth_server_connection_remove_requests(struct auth_server_connection *conn)
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian static const char *const temp_failure_args[] = { "temp", NULL };
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian iter = hash_table_iterate_init(conn->requests);
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanianstatic void auth_server_connection_close(struct auth_server_connection *conn)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi conn->client->connect_notify_callback(conn->client, FALSE,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic void auth_server_reconnect_timeout(struct auth_server_connection *conn)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiauth_server_connection_disconnect(struct auth_server_connection *conn)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi next_connect = conn->last_connect + AUTH_SERVER_RECONNECT_TIMEOUT_SECS;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi conn->to = timeout_add(ioloop_time >= next_connect ? 0 :
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindivoid auth_server_connection_deinit(struct auth_server_connection **_conn)
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian auth_server_connection_close(conn);
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian hash_table_destroy(&conn->requests);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic void auth_client_handshake_timeout(struct auth_server_connection *conn)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi i_error("Timeout waiting for handshake from auth server. "
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindiint auth_server_connection_connect(struct auth_server_connection *conn)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi const char *handshake;
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi /* max. 1 second wait here. */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi fd = net_connect_unix_with_retries(conn->client->auth_socket_path,
7bebe46c240b554f47faeed19186123896281967jc conn->io = io_add(fd, IO_READ, auth_server_connection_input, conn);
7bebe46c240b554f47faeed19186123896281967jc conn->input = i_stream_create_fd(fd, AUTH_SERVER_CONN_MAX_LINE_LENGTH,
7bebe46c240b554f47faeed19186123896281967jc conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
7bebe46c240b554f47faeed19186123896281967jc handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n",
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian if (o_stream_send_str(conn->output, handshake) < 0) {
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian i_warning("Error sending handshake to auth server: %m");
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian auth_server_connection_disconnect(conn);
7bebe46c240b554f47faeed19186123896281967jc return -1;
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanianauth_server_connection_add_request(struct auth_server_connection *conn,
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian struct auth_client_request *request)
7bebe46c240b554f47faeed19186123896281967jc if (id == 0) {
7bebe46c240b554f47faeed19186123896281967jc /* wrapped - ID 0 not allowed */
a62774df315360f02521d6470eab7d5080137dadSinanallur Balasubramanian id = ++conn->client->request_id_counter;