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