auth-server-connection.c revision 0cb5a9bfbf40b3b323956792aa13d342a459585e
c533a883a71cff9ff32df1c53c31201e1cbf371fhx/* Copyright (c) 2003-2007 Dovecot authors, see the included COPYING file */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include "lib.h"
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include "buffer.h"
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include "hash.h"
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include "ioloop.h"
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include "istream.h"
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include "ostream.h"
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include "network.h"
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include "auth-client.h"
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include "auth-server-connection.h"
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include "auth-server-request.h"
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include <unistd.h>
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#include <stdlib.h>
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx#define AUTH_HANDSHAKE_TIMEOUT (30*1000)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhxstatic void auth_server_connection_unref(struct auth_server_connection *conn);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhxstatic void update_available_auth_mechs(struct auth_server_connection *conn)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx struct auth_client *client = conn->client;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx const struct auth_mech_desc *mech;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx struct auth_mech_desc *new_mech;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx unsigned int i;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx mech = conn->available_auth_mechs;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx for (i = 0; i < conn->available_auth_mechs_count; i++) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (auth_client_find_mech(client, mech[i].name) == NULL) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx new_mech = buffer_append_space_unsafe(
c533a883a71cff9ff32df1c53c31201e1cbf371fhx client->available_auth_mechs, sizeof(*mech));
c533a883a71cff9ff32df1c53c31201e1cbf371fhx *new_mech = mech[i];
c533a883a71cff9ff32df1c53c31201e1cbf371fhx new_mech->name = i_strdup(mech[i].name);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx}
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhxstatic bool
c533a883a71cff9ff32df1c53c31201e1cbf371fhxauth_client_input_mech(struct auth_server_connection *conn, const char *args)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx const char *const *list;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx struct auth_mech_desc mech_desc;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (conn->handshake_received) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx i_error("BUG: Authentication server already sent handshake");
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return FALSE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx list = t_strsplit(args, "\t");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (list[0] == NULL) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx i_error("BUG: Authentication server sent broken MECH line");
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return FALSE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx memset(&mech_desc, 0, sizeof(mech_desc));
c533a883a71cff9ff32df1c53c31201e1cbf371fhx mech_desc.name = p_strdup(conn->pool, list[0]);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China if (strcmp(mech_desc.name, "PLAIN") == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->has_plain_mech = TRUE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx for (list++; *list != NULL; list++) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (strcmp(*list, "private") == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx mech_desc.flags |= MECH_SEC_PRIVATE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strcmp(*list, "anonymous") == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx mech_desc.flags |= MECH_SEC_ANONYMOUS;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strcmp(*list, "plaintext") == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx mech_desc.flags |= MECH_SEC_PLAINTEXT;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strcmp(*list, "dictionary") == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx mech_desc.flags |= MECH_SEC_DICTIONARY;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strcmp(*list, "active") == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx mech_desc.flags |= MECH_SEC_ACTIVE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strcmp(*list, "forward-secrecy") == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx mech_desc.flags |= MECH_SEC_FORWARD_SECRECY;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strcmp(*list, "mutual-auth") == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx mech_desc.flags |= MECH_SEC_MUTUAL_AUTH;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx buffer_append(conn->auth_mechs_buf, &mech_desc, sizeof(mech_desc));
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return TRUE;
43439c96b8398c01c375889c79bed72d78fb4c39hx}
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China
c533a883a71cff9ff32df1c53c31201e1cbf371fhxstatic bool
c533a883a71cff9ff32df1c53c31201e1cbf371fhxauth_client_input_spid(struct auth_server_connection *conn, const char *args)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (conn->handshake_received) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx i_error("BUG: Authentication server already sent handshake");
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return FALSE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->server_pid = (unsigned int)strtoul(args, NULL, 10);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return TRUE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx}
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhxstatic bool
c533a883a71cff9ff32df1c53c31201e1cbf371fhxauth_client_input_cuid(struct auth_server_connection *conn, const char *args)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (conn->handshake_received) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx i_error("BUG: Authentication server already sent handshake");
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return FALSE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->connect_uid = (unsigned int)strtoul(args, NULL, 10);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return TRUE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx}
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhxstatic bool auth_client_input_done(struct auth_server_connection *conn)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->available_auth_mechs = conn->auth_mechs_buf->data;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->available_auth_mechs_count =
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->auth_mechs_buf->used / sizeof(struct auth_mech_desc);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (conn->available_auth_mechs_count == 0) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx i_error("BUG: Authentication server returned no mechanisms");
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return FALSE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (conn->to != NULL)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx timeout_remove(&conn->to);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->handshake_received = TRUE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->client->conn_waiting_handshake_count--;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx update_available_auth_mechs(conn);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (conn->client->connect_notify_callback != NULL &&
c533a883a71cff9ff32df1c53c31201e1cbf371fhx auth_client_is_connected(conn->client)) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->client->connect_notify_callback(conn->client, TRUE,
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->client->connect_notify_context);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return TRUE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx}
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhxstatic void auth_client_input(struct auth_server_connection *conn)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx const char *line;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx int ret;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx switch (i_stream_read(conn->input)) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx case 0:
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx case -1:
c533a883a71cff9ff32df1c53c31201e1cbf371fhx /* disconnected */
c533a883a71cff9ff32df1c53c31201e1cbf371fhx auth_server_connection_destroy(&conn, TRUE);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx case -2:
c533a883a71cff9ff32df1c53c31201e1cbf371fhx /* buffer full - can't happen unless auth is buggy */
c533a883a71cff9ff32df1c53c31201e1cbf371fhx i_error("BUG: Auth server sent us more than %d bytes of data",
c533a883a71cff9ff32df1c53c31201e1cbf371fhx AUTH_CLIENT_MAX_LINE_LENGTH);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx auth_server_connection_destroy(&conn, FALSE);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (conn->version_received) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx line = i_stream_next_line(conn->input);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (line == NULL)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx /* make sure the major version matches */
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (strncmp(line, "VERSION\t", 8) != 0 ||
c533a883a71cff9ff32df1c53c31201e1cbf371fhx atoi(t_strcut(line + 8, '\t')) !=
c533a883a71cff9ff32df1c53c31201e1cbf371fhx AUTH_CLIENT_PROTOCOL_MAJOR_VERSION) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx i_error("Authentication server not compatible with "
c533a883a71cff9ff32df1c53c31201e1cbf371fhx "this client (mixed old and new binaries?)");
c533a883a71cff9ff32df1c53c31201e1cbf371fhx auth_server_connection_destroy(&conn, FALSE);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->version_received = TRUE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->refcount++;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx while ((line = i_stream_next_line(conn->input)) != NULL) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx t_push();
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (strncmp(line, "OK\t", 3) == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx ret = auth_client_input_ok(conn, line + 3);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strncmp(line, "CONT\t", 5) == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx ret = auth_client_input_cont(conn, line + 5);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strncmp(line, "FAIL\t", 5) == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx ret = auth_client_input_fail(conn, line + 5);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strncmp(line, "MECH\t", 5) == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx ret = auth_client_input_mech(conn, line + 5);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strncmp(line, "SPID\t", 5) == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx ret = auth_client_input_spid(conn, line + 5);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strncmp(line, "CUID\t", 5) == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx ret = auth_client_input_cuid(conn, line + 5);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else if (strcmp(line, "DONE") == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx ret = auth_client_input_done(conn);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx /* ignore unknown command */
c533a883a71cff9ff32df1c53c31201e1cbf371fhx ret = TRUE;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx t_pop();
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (!ret) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx auth_server_connection_destroy(&conn, FALSE);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx break;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx auth_server_connection_unref(conn);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx}
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhxstatic void auth_client_handshake_timeout(struct auth_server_connection *conn)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx i_error("Timeout waiting for handshake from auth server. "
c533a883a71cff9ff32df1c53c31201e1cbf371fhx "my pid=%u, input bytes=%"PRIuUOFF_T,
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->client->pid, conn->input->v_offset);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx auth_server_connection_destroy(&conn, TRUE);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx}
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhxstruct auth_server_connection *
c533a883a71cff9ff32df1c53c31201e1cbf371fhxauth_server_connection_new(struct auth_client *client, const char *path)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx struct auth_server_connection *conn;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx const char *handshake;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx pool_t pool;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx int fd, try;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx /* max. 1 second wait here. */
c533a883a71cff9ff32df1c53c31201e1cbf371fhx for (try = 0; try < 10; try++) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx fd = net_connect_unix(path);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (fd != -1 || (errno != EAGAIN && errno != ECONNREFUSED))
c533a883a71cff9ff32df1c53c31201e1cbf371fhx break;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx /* busy. wait for a while. */
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China usleep(((rand() % 10) + 1) * 10000);
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China }
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China if (fd == -1) {
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China i_error("Can't connect to auth server at %s: %m", path);
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China return NULL;
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China }
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China
b510adae7e8895b2bf58eda3537fd56df35302e4fei feng - Sun Microsystems - Beijing China /* use blocking connection since we depend on auth server -
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if it's slow, just wait */
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx pool = pool_alloconly_create("Auth connection", 1024);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn = p_new(pool, struct auth_server_connection, 1);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->refcount = 1;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->pool = pool;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->client = client;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->path = p_strdup(pool, path);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->fd = fd;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->io = io_add(fd, IO_READ, auth_client_input, conn);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->input = i_stream_create_fd(fd, AUTH_CLIENT_MAX_LINE_LENGTH,
c533a883a71cff9ff32df1c53c31201e1cbf371fhx FALSE);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->requests = hash_create(default_pool, pool, 100, NULL, NULL);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->auth_mechs_buf = buffer_create_dynamic(default_pool, 256);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->to = timeout_add(AUTH_HANDSHAKE_TIMEOUT,
c533a883a71cff9ff32df1c53c31201e1cbf371fhx auth_client_handshake_timeout, conn);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx conn->next = client->connections;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx client->connections = conn;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx handshake = t_strdup_printf("VERSION\t%u\t%u\nCPID\t%u\n",
c533a883a71cff9ff32df1c53c31201e1cbf371fhx AUTH_CLIENT_PROTOCOL_MAJOR_VERSION,
43439c96b8398c01c375889c79bed72d78fb4c39hx AUTH_CLIENT_PROTOCOL_MINOR_VERSION,
43439c96b8398c01c375889c79bed72d78fb4c39hx client->pid);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx client->conn_waiting_handshake_count++;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (o_stream_send_str(conn->output, handshake) < 0) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx errno = conn->output->stream_errno;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx i_warning("Error sending handshake to auth server: %m");
c533a883a71cff9ff32df1c53c31201e1cbf371fhx auth_server_connection_destroy(&conn, TRUE);
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return NULL;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return conn;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx}
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhxvoid auth_server_connection_destroy(struct auth_server_connection **_conn,
c533a883a71cff9ff32df1c53c31201e1cbf371fhx bool reconnect)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx struct auth_server_connection *conn = *_conn;
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China struct auth_client *client = conn->client;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx struct auth_server_connection **pos;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx *_conn = NULL;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China if (conn->fd == -1)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx pos = &conn->client->connections;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx for (; *pos != NULL; pos = &(*pos)->next) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (*pos == conn) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx *pos = conn->next;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx break;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (!conn->handshake_received)
43439c96b8398c01c375889c79bed72d78fb4c39hx client->conn_waiting_handshake_count--;
43439c96b8398c01c375889c79bed72d78fb4c39hx
43439c96b8398c01c375889c79bed72d78fb4c39hx if (conn->to != NULL)
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China timeout_remove(&conn->to);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China if (conn->io != NULL)
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China io_remove(&conn->io);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China i_stream_close(conn->input);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China o_stream_close(conn->output);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China if (close(conn->fd) < 0)
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China i_error("close(auth) failed: %m");
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China conn->fd = -1;
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China auth_server_requests_remove_all(conn);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China auth_server_connection_unref(conn);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China if (reconnect)
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China auth_client_connect_missing_servers(client);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China else if (client->connect_notify_callback != NULL) {
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China client->connect_notify_callback(client,
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China auth_client_is_connected(client),
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China client->connect_notify_context);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China }
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China}
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing Chinastatic void auth_server_connection_unref(struct auth_server_connection *conn)
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China{
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China if (--conn->refcount > 0)
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China return;
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China i_assert(conn->refcount == 0);
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China hash_destroy(&conn->requests);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China buffer_free(&conn->auth_mechs_buf);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China i_stream_unref(&conn->input);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China o_stream_unref(&conn->output);
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China pool_unref(&conn->pool);
d2a61391af480de12cf4264080d7254a6de96e2apengcheng chen - Sun Microsystems - Beijing China}
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhxstruct auth_server_connection *
c533a883a71cff9ff32df1c53c31201e1cbf371fhxauth_server_connection_find_path(struct auth_client *client, const char *path)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx struct auth_server_connection *conn;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx for (conn = client->connections; conn != NULL; conn = conn->next) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (strcmp(conn->path, path) == 0)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return conn;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
cdc64593cc1046229f4ac4daf5ead688b5efe6ebxinghua wen - Sun Microsystems - Beijing China
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return NULL;
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan}
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhan
bcb5c89da22515e2ccf139578bad3caebcd716adSowmini Varadhanstruct auth_server_connection *
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerauth_server_connection_find_mech(struct auth_client *client,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer const char *name, const char **error_r)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
c533a883a71cff9ff32df1c53c31201e1cbf371fhx struct auth_server_connection *conn, *match;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx const struct auth_mech_desc *mech;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx unsigned int i, n, match_n;
f3c4902c7f91725a7b538a3d82f1993bff02944fpengcheng chen - Sun Microsystems - Beijing China
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China /* find a connection which has this mechanism. if there are multiple
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China available connections to use, do round robin load balancing */
6f12def440a1ce798ab128210a43414d173669f0pengcheng chen - Sun Microsystems - Beijing China match = NULL; match_n = n = 0;
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China for (conn = client->connections; conn != NULL; conn = conn->next, n++) {
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China mech = conn->available_auth_mechs;
19d332fefbc61327bb6187d0eb818629f3b52c6ffei feng - Sun Microsystems - Beijing China for (i = 0; i < conn->available_auth_mechs_count; i++) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (strcasecmp(mech[i].name, name) == 0) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (n > client->last_used_auth_process) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx client->last_used_auth_process = n;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return conn;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (match == NULL) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx match = conn;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx match_n = n;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx break;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (match != NULL) {
c533a883a71cff9ff32df1c53c31201e1cbf371fhx client->last_used_auth_process = match_n;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return match;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx if (auth_client_find_mech(client, name) == NULL)
c533a883a71cff9ff32df1c53c31201e1cbf371fhx *error_r = "Unsupported authentication mechanism";
c533a883a71cff9ff32df1c53c31201e1cbf371fhx else {
d2a61391af480de12cf4264080d7254a6de96e2apengcheng chen - Sun Microsystems - Beijing China *error_r = "Authentication server isn't connected, "
c533a883a71cff9ff32df1c53c31201e1cbf371fhx "try again later..";
c533a883a71cff9ff32df1c53c31201e1cbf371fhx }
c533a883a71cff9ff32df1c53c31201e1cbf371fhx
c533a883a71cff9ff32df1c53c31201e1cbf371fhx return NULL;
c533a883a71cff9ff32df1c53c31201e1cbf371fhx}
c533a883a71cff9ff32df1c53c31201e1cbf371fhx