auth-master-connection.c revision 647eed98cb795ee9e42911750402dab720b57514
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen unsigned int id;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen unsigned int id;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void master_input(struct auth_master_connection *conn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo SirainenARRAY_TYPE(auth_master_connections) auth_master_connections;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenvoid auth_master_request_callback(struct auth_stream_reply *reply,
657afb33796f8216c568ad813627da89970760beTimo Sirainen struct auth_master_connection *conn = context;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenmaster_input_request(struct auth_master_connection *conn, const char *args)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen const char *const *list;
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen /* <id> <client-pid> <client-id> <cookie> */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen id = (unsigned int)strtoul(list[0], NULL, 10);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen client_pid = (unsigned int)strtoul(list[1], NULL, 10);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen client_id = (unsigned int)strtoul(list[2], NULL, 10);
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen buffer_create_data(&buf, cookie, sizeof(cookie));
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen i_error("BUG: Master sent broken REQUEST cookie");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen client_conn = auth_client_connection_lookup(client_pid);
657afb33796f8216c568ad813627da89970760beTimo Sirainen i_error("Master requested auth for nonexisting client %u",
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen } else if (memcmp(client_conn->cookie, cookie, sizeof(cookie)) != 0) {
419baa2c17c63ae516b2df6cc5695f15aaccbff8Timo Sirainen i_error("Master requested auth for client %u with invalid cookie",
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen client_conn->request_handler, conn, id, client_id);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainenmaster_input_auth_request(struct auth_master_connection *conn, const char *args,
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen const char *cmd, struct auth_request **request_r,
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen const char **error_r)
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen /* <id> <userid> [<parameters>] */
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen auth_request = auth_request_new_dummy(conn->auth);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen auth_request->id = (unsigned int)strtoul(list[0], NULL, 10);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen if (!auth_request_set_username(auth_request, list[1], error_r)) {
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen (void)auth_request_import(auth_request, name, arg);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen i_error("BUG: Master sent %s request without service", cmd);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen struct auth_master_connection *conn = auth_request->context;
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen struct auth_stream_reply *reply = auth_request->userdb_reply;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen str_printfa(str, "FAIL\t%u", auth_request->id);
3ee2da6133bd7773961d1f3f3ac531448a5158b9Timo Sirainen str_printfa(str, "NOTFOUND\t%u", auth_request->id);
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen str_printfa(str, "USER\t%u\t", auth_request->id);
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen str_append(str, auth_stream_reply_export(reply));
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainen (void)o_stream_send(conn->output, str_data(str), str_len(str));
9398c0935613ba038cf2275ff66c43b25092cfd0Timo Sirainenmaster_input_user(struct auth_master_connection *conn, const char *args)
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen ret = master_input_auth_request(conn, args, "USER",
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen auth_request_log_info(auth_request, "userdb", "%s", error);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen user_callback(USERDB_RESULT_USER_UNKNOWN, auth_request);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen auth_request->state = AUTH_REQUEST_STATE_USERDB;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen auth_request_lookup_user(auth_request, user_callback);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen struct auth_master_connection *conn = auth_request->context;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen struct auth_stream_reply *reply = auth_request->extra_fields;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen str_printfa(str, "PASS\t%u\t", auth_request->id);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen str_append(str, auth_stream_reply_export(reply));
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen str_printfa(str, "NOTFOUND\t%u", auth_request->id);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen str_printfa(str, "FAIL\t%u", auth_request->id);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen (void)o_stream_send(conn->output, str_data(str), str_len(str));
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainenmaster_input_pass(struct auth_master_connection *conn, const char *args)
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen ret = master_input_auth_request(conn, args, "PASS",
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen auth_request_log_info(auth_request, "passdb", "%s", error);
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen auth_request->state = AUTH_REQUEST_STATE_MECH_CONTINUE;
1862352e2ef8ed1ef824368d9c0c2c0fce89962eTimo Sirainen auth_request_lookup_credentials(auth_request, "",
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void master_input_list_finish(struct master_list_iter_ctx *ctx)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->conn->io = io_add(ctx->conn->fd, IO_READ, master_input, ctx->conn);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (void)userdb_blocking_iter_deinit(&ctx->iter);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen o_stream_unset_flush_callback(ctx->conn->output);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic int master_output_list(struct master_list_iter_ctx *ctx)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if ((ret = o_stream_flush(ctx->conn->output)) < 0) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void master_input_list_callback(const char *user, void *context)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (userdb_blocking_iter_deinit(&ctx->iter) < 0)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->userdb->userdb->iface->iterate_init == NULL);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* iteration is finished */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const char *str;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen str = t_strdup_printf("DONE\t%u\t%s\n", ctx->id,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (void)o_stream_send_str(ctx->conn->output, str);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* continue iterating next userdb */
550034b94a58491a08a620c8e392fd3087551e7aTimo Sirainen ctx->iter = userdb_blocking_iter_init(ctx->userdb,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const char *str;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen str = t_strdup_printf("LIST\t%u\t%s\n", ctx->id,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ret = o_stream_send_str(ctx->conn->output, str);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* disconnected, don't bother finishing */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (o_stream_get_buffer_used_size(ctx->conn->output) == 0)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenmaster_input_list(struct auth_master_connection *conn, const char *args)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct auth_userdb *userdb = conn->auth->userdbs;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const char *str;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen unsigned int id;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen while (userdb != NULL && userdb->userdb->iface->iterate_init == NULL)
3278289d240da169166de8aa785273c5df904e64Timo Sirainen i_error("Trying to iterate users, but userdbs don't support it");
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen o_stream_set_flush_callback(conn->output, master_output_list, ctx);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen ctx->iter = userdb_blocking_iter_init(ctx->userdb,
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainenauth_master_input_line(struct auth_master_connection *conn, const char *line)
3278289d240da169166de8aa785273c5df904e64Timo Sirainen i_error("Authentication client trying to connect to "
3278289d240da169166de8aa785273c5df904e64Timo Sirainen "master socket");
0bb8c135a1c065655fc4d2d89b74b4f958fe4f02Timo Sirainen i_error("BUG: Unknown command in %s socket: %s",
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic void master_input(struct auth_master_connection *conn)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* disconnected */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* buffer full */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen i_error("BUG: Master sent us more than %d bytes",
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen /* make sure the major version matches */
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen i_error("Master not compatible with this server "
b0df0e9a8ed8889ad4bf032043ab245ce8851fdeTimo Sirainen "(mixed old and new binaries?)");
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen while ((line = i_stream_next_line(conn->input)) != NULL) {
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainenstatic int master_output(struct auth_master_connection *conn)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if ((ret = o_stream_flush(conn->output)) < 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* transmit error, probably master died */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (o_stream_get_buffer_used_size(conn->output) <= MAX_OUTBUF_SIZE/2) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* allow input again */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen conn->io = io_add(conn->fd, IO_READ, master_input, conn);
3278289d240da169166de8aa785273c5df904e64Timo Sirainenauth_master_connection_create(struct auth *auth, int fd, bool userdb_only)
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen conn = i_new(struct auth_master_connection, 1);
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE);
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_set_flush_callback(conn->output, master_output, conn);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->io = io_add(fd, IO_READ, master_input, conn);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen line = t_strdup_printf("VERSION\t%u\t%u\nSPID\t%s\n",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_append(&auth_master_connections, &conn, 1);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid auth_master_connection_destroy(struct auth_master_connection **_conn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct auth_master_connection *const *masters;
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen unsigned int idx;
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen array_foreach(&auth_master_connections, masters) {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen idx = array_foreach_idx(&auth_master_connections,
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen array_delete(&auth_master_connections, idx, 1);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen master_service_client_connection_destroyed(master_service);
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainenvoid auth_master_connection_ref(struct auth_master_connection *conn)
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainenvoid auth_master_connection_unref(struct auth_master_connection **_conn)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int i, count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen masters = array_get_modifiable(&auth_master_connections, &count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (i = count; i > 0; i--)