static void auth_server_connection_input(struct auth_server_connection *conn) { struct istream *input; const char *line, *error; int ret; switch (i_stream_read(conn->input)) { case 0: return; case -1: /* disconnected */ error = conn->input->stream_errno != 0 ? strerror(conn->input->stream_errno) : "EOF"; auth_server_connection_reconnect(conn, error); return; case -2: /* buffer full - can't happen unless auth is buggy */ i_error("BUG: Auth server sent us more than %d bytes of data", AUTH_SERVER_CONN_MAX_LINE_LENGTH); auth_server_connection_disconnect(conn, "buffer full"); return; } if (!conn->version_received) { line = i_stream_next_line(conn->input); if (line == NULL) return; /* make sure the major version matches */ if (strncmp(line, "VERSION\t", 8) != 0 || !str_uint_equals(t_strcut(line + 8, '\t'), AUTH_CLIENT_PROTOCOL_MAJOR_VERSION)) { i_error("Authentication server not compatible with " "this client (mixed old and new binaries?)"); auth_server_connection_disconnect(conn, "incompatible server"); return; } conn->version_received = TRUE; } input = conn->input; i_stream_ref(input); while ((line = i_stream_next_line(input)) != NULL && !input->closed) { T_BEGIN { ret = auth_server_connection_input_line(conn, line); } T_END; if (ret < 0) { auth_server_connection_disconnect(conn, t_strdup_printf( "Received broken input: %s", line)); break; } } i_stream_unref(&input); }
void auth_server_connection_deinit(struct auth_server_connection **_conn) { struct auth_server_connection *conn = *_conn; *_conn = NULL; auth_server_connection_disconnect(conn); hash_table_destroy(&conn->requests); array_free(&conn->available_auth_mechs); pool_unref(&conn->pool); }
static void auth_server_connection_reconnect(struct auth_server_connection *conn) { time_t next_connect; auth_server_connection_disconnect(conn); next_connect = conn->last_connect + AUTH_SERVER_RECONNECT_TIMEOUT_SECS; conn->to = timeout_add(ioloop_time >= next_connect ? 0 : (next_connect - ioloop_time) * 1000, auth_server_reconnect_timeout, conn); }
int auth_server_connection_connect(struct auth_server_connection *conn) { const char *handshake; int fd; i_assert(!conn->connected); i_assert(conn->fd == -1); conn->last_connect = ioloop_time; timeout_remove(&conn->to); /* max. 1 second wait here. */ fd = net_connect_unix_with_retries(conn->client->auth_socket_path, 1000); if (fd == -1) { if (errno == EACCES) { i_error("auth: %s", eacces_error_get("connect", conn->client->auth_socket_path)); } else { i_error("auth: connect(%s) failed: %m", conn->client->auth_socket_path); } return -1; } conn->fd = fd; conn->io = io_add(fd, IO_READ, auth_server_connection_input, conn); conn->input = i_stream_create_fd(fd, AUTH_SERVER_CONN_MAX_LINE_LENGTH); conn->output = o_stream_create_fd(fd, (size_t)-1); conn->connected = TRUE; handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n", AUTH_CLIENT_PROTOCOL_MAJOR_VERSION, AUTH_CLIENT_PROTOCOL_MINOR_VERSION, conn->client->client_pid); if (o_stream_send_str(conn->output, handshake) < 0) { i_warning("Error sending handshake to auth server: %s", o_stream_get_error(conn->output)); auth_server_connection_disconnect(conn, o_stream_get_error(conn->output)); return -1; } conn->to = timeout_add(AUTH_HANDSHAKE_TIMEOUT, auth_client_handshake_timeout, conn); return 0; }