auth-server-connection.c revision eddd9bf1a1369aea4a2715f6be1137da6d17d293
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void auth_server_connection_unref(struct auth_server_connection *conn);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void update_available_auth_mechs(struct auth_server_connection *conn)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < conn->available_auth_mechs_count; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (auth_client_find_mech(client, mech[i].name) == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenauth_client_input_mech(struct auth_server_connection *conn, const char *args)
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen const char *const *list;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("BUG: Authentication server already sent handshake");
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen i_error("BUG: Authentication server sent broken MECH line");
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen mech_desc.name = p_strdup(conn->pool, list[0]);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen else if (strcmp(*list, "forward-secrecy") == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_append(conn->auth_mechs_buf, &mech_desc, sizeof(mech_desc));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenauth_client_input_spid(struct auth_server_connection *conn, const char *args)
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen i_error("BUG: Authentication server already sent handshake");
abe7afb8f1766fbcef1b9df513109e43d7d16e49Timo Sirainen conn->server_pid = (unsigned int)strtoul(args, NULL, 10);
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainenauth_client_input_cuid(struct auth_server_connection *conn, const char *args)
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen i_error("BUG: Authentication server already sent handshake");
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen conn->connect_uid = (unsigned int)strtoul(args, NULL, 10);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainenstatic bool auth_client_input_done(struct auth_server_connection *conn)
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen conn->available_auth_mechs = conn->auth_mechs_buf->data;
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen conn->auth_mechs_buf->used / sizeof(struct auth_mech_desc);
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen i_error("BUG: Authentication server returned no mechanisms");
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen if (conn->client->connect_notify_callback != NULL &&
69e03a846f6980144aa75bff0590c04852bffbbcTimo Sirainen conn->client->connect_notify_callback(conn->client, TRUE,
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainenauth_client_input_line(struct auth_server_connection *conn, const char *line)
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen return auth_client_input_cont(conn, line + 5);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen return auth_client_input_fail(conn, line + 5);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen return auth_client_input_mech(conn, line + 5);
bc564f1d3d953cf724828322b11ae89e0f59ffc9Timo Sirainen return auth_client_input_spid(conn, line + 5);
2131ef7a3390f15ea6a958256ea54908f1096350Timo Sirainen return auth_client_input_cuid(conn, line + 5);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen /* ignore unknown command */
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic void auth_client_input(struct auth_server_connection *conn)
c53e8ee216904ffe6de4f6518d9f9f5107b7610eTimo Sirainen /* disconnected */
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen /* buffer full - can't happen unless auth is buggy */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen i_error("BUG: Auth server sent us more than %d bytes of data",
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* make sure the major version matches */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_error("Authentication server not compatible with "
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen "this client (mixed old and new binaries?)");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen while ((line = i_stream_next_line(conn->input)) != NULL) {
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainenstatic void auth_client_handshake_timeout(struct auth_server_connection *conn)
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainen i_error("Timeout waiting for handshake from auth server. "
25c22e54d1071d120641e9eecd0023e7373e65ffTimo Sirainenauth_server_connection_new(struct auth_client *client, const char *path)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* max. 1 second wait here. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (fd != -1 || (errno != EAGAIN && errno != ECONNREFUSED))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* busy. wait for a while. */
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen i_error("Can't connect to auth server at %s: %m", path);
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen /* use blocking connection since we depend on auth server -
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen if it's slow, just wait */
6bc0f424bcdb9119d8159874cf98adfa53eefd9aTimo Sirainen pool = pool_alloconly_create("Auth connection", 1024);
e192a3b1ca8ae857e7d87298ea507d32977ba570Timo Sirainen conn = p_new(pool, struct auth_server_connection, 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen conn->io = io_add(fd, IO_READ, auth_client_input, conn);
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen conn->input = i_stream_create_fd(fd, AUTH_CLIENT_MAX_LINE_LENGTH,
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
8b9342aa96b2f297e23afb261f9f7dd859800952Timo Sirainen conn->requests = hash_create(default_pool, pool, 100, NULL, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen conn->auth_mechs_buf = buffer_create_dynamic(default_pool, 256);
37e6cf44d61a81c6839e3ab76234b54309d8d292Timo Sirainen conn->to = timeout_add(AUTH_HANDSHAKE_TIMEOUT,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (o_stream_send_str(conn->output, handshake) < 0) {
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen i_warning("Error sending handshake to auth server: %m");
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenvoid auth_server_connection_destroy(struct auth_server_connection **_conn,
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen else if (client->connect_notify_callback != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void auth_server_connection_unref(struct auth_server_connection *conn)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenauth_server_connection_find_path(struct auth_client *client, const char *path)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (conn = client->connections; conn != NULL; conn = conn->next) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenauth_server_connection_find_mech(struct auth_client *client,
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen unsigned int i, n, match_n;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen /* find a connection which has this mechanism. if there are multiple
df6478c4cf605bd81b3891c148b84c14eb6c4035Timo Sirainen available connections to use, do round robin load balancing */
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen for (conn = client->connections; conn != NULL; conn = conn->next, n++) {
f501ad38c51cf1d8f4f84313922c785e6ae6e81fTimo Sirainen for (i = 0; i < conn->available_auth_mechs_count; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (auth_client_find_mech(client, name) == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = "Unsupported authentication mechanism";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = "Authentication server isn't connected, "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "try again later..";