auth-master-connection.c revision 4b8c92b4773677a7b4064816e469eeafc976ba75
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen unsigned int id;
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenstatic void auth_master_connection_close(struct auth_master_connection *conn);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic int auth_master_connection_unref(struct auth_master_connection *conn);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void master_send(struct auth_master_connection *conn,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void master_send(struct auth_master_connection *conn,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen const char *fmt, ...)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen (void)o_stream_send(conn->output, str_data(str), str_len(str));
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void append_user_reply(string_t *str, const struct user_data *user)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen const char *p;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_printfa(str, "%s\tuid=%s\tgid=%s", user->virtual_user,
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_printfa(str, "\tsystem_user=%s", user->system_user);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen p = user->home != NULL ? strstr(user->home, "/./") : NULL;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen /* wu-ftpd like <chroot>/./<home> */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenstatic void userdb_callback(const struct user_data *user, void *context)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct master_userdb_request *master_request = context;
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen if (auth_master_connection_unref(master_request->conn)) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen master_send(master_request->conn, "NOTFOUND\t%u",
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen str_printfa(str, "USER\t%u\t", master_request->id);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen master_send(master_request->conn, "%s", str_c(str));
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen auth_request_destroy(master_request->auth_request);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenmaster_input_request(struct auth_master_connection *conn, const char *args)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen const char *const *list;
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* <id> <client-pid> <client-id> */
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen if (list[0] == NULL || list[1] == NULL || list[2] == NULL) {
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);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen client_conn = auth_client_connection_lookup(conn, client_pid);
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen master_request = i_new(struct master_userdb_request, 1);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen userdb->lookup(request, userdb_callback, master_request);
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainenmaster_input_die(struct auth_master_connection *conn)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen struct auth_master_connection *conn = context;
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) {
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen /* ignore unknown command */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct auth_master_connection *conn = context;
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);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenauth_master_connection_set_fd(struct auth_master_connection *conn, int fd)
73bfdbe28c2ce6d143eadf0bab8ccfbe4cab0faeTimo Sirainen conn->input = i_stream_create_file(fd, default_pool,
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->output = o_stream_create_file(fd, default_pool,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen o_stream_set_flush_callback(conn->output, master_output, conn);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen conn->io = io_add(fd, IO_READ, master_input, conn);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenauth_master_connection_create(int fd, unsigned int pid)
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainen conn = i_new(struct auth_master_connection, 1);
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen conn->listeners_buf = buffer_create_dynamic(default_pool, 64);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenvoid auth_master_connection_send_handshake(struct auth_master_connection *conn)
4b8c92b4773677a7b4064816e469eeafc976ba75Timo Sirainen master_send(conn, "VERSION\t%u\t%u\nSPID\t%u\n",
2cb3e318bdfee05d1de2d8c8942ff790edd3ea3fTimo Sirainen AUTH_MASTER_PROTOCOL_MINOR_VERSION, conn->pid);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenstatic void auth_master_connection_close(struct auth_master_connection *conn)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainenvoid auth_master_connection_destroy(struct auth_master_connection *conn)
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen l = buffer_get_modifyable_data(conn->listeners_buf, &size);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen size /= sizeof(*l);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen for (i = 0; i < size; i++) {
2a90d8a14b0e7cc1508814bc87d3dfa598ef46a8Timo Sirainenstatic int auth_master_connection_unref(struct auth_master_connection *conn)
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen (void)auth_client_connection_create(l->master, fd);
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen /* we'll just replace the previous master.. */
6b46a500174ace25494b8f0547283eb60dc13756Timo Sirainen auth_master_connection_send_handshake(l->master);
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainenvoid auth_master_connection_add_listener(struct auth_master_connection *conn,
76213404317a7ed17bec0beadb5137c82785d816Timo Sirainen buffer_append(conn->listeners_buf, &l, sizeof(l));