auth-master.c revision 9261dbf0675204898c6557591c7aa376e23a52b2
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen#define DEFAULT_USERDB_LOOKUP_PREFIX "userdb lookup"
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen bool (*reply_callback)(const char *cmd, const char *const *args,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const char **fields;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const char *const *user_strings;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void auth_input(struct auth_master_connection *conn);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenauth_master_init(const char *auth_socket_path, enum auth_master_flags flags)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen conn = i_new(struct auth_master_connection, 1);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen conn->auth_socket_path = i_strdup(auth_socket_path);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void auth_connection_close(struct auth_master_connection *conn)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_error("close(%s) failed: %m", conn->auth_socket_path);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenvoid auth_master_deinit(struct auth_master_connection **_conn)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void auth_request_lookup_abort(struct auth_master_connection *conn)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic int auth_input_handshake(struct auth_master_connection *conn)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen while ((line = i_stream_next_line(conn->input)) != NULL) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (strcmp(tmp[1], dec2str(AUTH_PROTOCOL_MAJOR)) != 0) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen "Auth protocol version mismatch "
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic int parse_reply(const char *cmd, const char *const *args,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const char *expected_reply, const char *user, bool debug)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen } else if (debug) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_debug("user %s: Auth %s lookup returned temporary failure: %s",
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenstatic bool auth_lookup_reply_callback(const char *cmd, const char *const *args,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen unsigned int i, len;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen bool debug = (ctx->conn->flags & AUTH_MASTER_FLAG_DEBUG) != 0;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen parse_reply(cmd, args, ctx->expected_reply, ctx->user, debug);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ctx->fields = p_new(ctx->pool, const char *, len + 1);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen for (i = 0; i < len; i++)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ctx->fields[i] = p_strdup(ctx->pool, args[i]);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen /* put the reason string into first field */
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen ctx->fields = p_new(ctx->pool, const char *, 2);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen for (i = 0; i < len; i++) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_debug("auth input: %s", t_strarray_join(args, " "));
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenauth_handle_line(struct auth_master_connection *conn, const char *line)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen const char *cmd, *const *args, *id, *wanted_id;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen return conn->reply_callback(cmd, args, conn->reply_context);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen "It should be a master socket.",
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_error("%s: BUG: Unexpected input: %s", conn->prefix, line);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenstatic void auth_input(struct auth_master_connection *conn)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* disconnected */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* buffer full */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen i_error("%s: BUG: Received more than %d bytes",
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen while ((line = i_stream_next_line(conn->input)) != NULL) {
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenstatic int auth_master_connect(struct auth_master_connection *conn)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* max. 1 second wait here. */
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen fd = net_connect_unix_with_retries(conn->auth_socket_path, 1000);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_error("userdb lookup: connect(%s) failed: %m",
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenstatic void auth_request_timeout(struct auth_master_connection *conn)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen i_error("%s: Connecting timed out", conn->prefix);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen i_error("%s: Request timed out", conn->prefix);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void auth_idle_timeout(struct auth_master_connection *conn)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void auth_master_set_io(struct auth_master_connection *conn)
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen conn->input = i_stream_create_fd(conn->fd, MAX_INBUF_SIZE, FALSE);
41e1c7380edda701719d8ce1fb4d465d2ec4c84dTimo Sirainen conn->output = o_stream_create_fd(conn->fd, MAX_OUTBUF_SIZE, FALSE);
190237ce467d2389dfb809874b0fec86d3c7968dTimo Sirainen conn->io = io_add(conn->fd, IO_READ, auth_input, conn);
1e47cfede3a0b62654105daab00e97b5d660bc6bTimo Sirainen conn->to = timeout_add(1000*AUTH_REQUEST_TIMEOUT_SECS,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void auth_master_unset_io(struct auth_master_connection *conn,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if ((conn->flags & AUTH_MASTER_FLAG_NO_IDLE_TIMEOUT) == 0) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen conn->to = timeout_add(1000*AUTH_MASTER_IDLE_SECS,
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen const char *p;
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen /* make sure we're not sending any characters that have a special
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenstatic int auth_master_run_cmd(struct auth_master_connection *conn,
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen const char *cmd)
287ba82a8da3eaa473b5735d4eeac2fb4c5d8117Timo Sirainen const char *str;
const char *const **fields_r)
void *context)
const char *user;
return TRUE;
return TRUE;
return FALSE;
struct auth_master_user_list_ctx *
const char *str;
return ctx;
return NULL;
return ret;