bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "lib.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "ioloop.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "net.h"
9de5eb9e1ac3a07c4197a60fdefd412d6cc78eb2Timo Sirainen#include "str.h"
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen#include "istream.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "ostream.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "llist.h"
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen#include "strescape.h"
fe8af34153615d9007f2238fca87df11ff32d614Timo Sirainen#include "master-service.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "director-request.h"
1b418300cc37ca9118f8a9b9e68176276267aef0Timo Sirainen#include "mail-host.h"
3131b0cc20e2e702082c8de4b623d7bd71b3b8e6Timo Sirainen#include "auth-client-interface.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "auth-connection.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "login-connection.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include <unistd.h>
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen#define AUTHREPLY_PROTOCOL_MAJOR_VERSION 1
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen#define AUTHREPLY_PROTOCOL_MINOR_VERSION 0
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstruct login_connection {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct login_connection *prev, *next;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen int refcount;
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen enum login_connection_type type;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen int fd;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct io *io;
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen struct istream *input;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct ostream *output;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct auth_connection *auth;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct director *dir;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool handshaked:1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen bool destroyed:1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen};
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstruct login_host_request {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct login_connection *conn;
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen char *line, *username;
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen struct ip_addr local_ip;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch in_port_t local_port;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch in_port_t dest_port;
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen bool director_proxy_maybe;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen};
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic struct login_connection *login_connections;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainenstatic void auth_input_line(const char *line, void *context);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void login_connection_unref(struct login_connection **_conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void login_connection_input(struct login_connection *conn)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2cc34f340d31125b16f58948bed8cc6a86911fcfTimo Sirainen struct ostream *output;
2cd04598af2b69120948e29f2a0dd1710bebbe1bTimo Sirainen unsigned char buf[4096];
2cd04598af2b69120948e29f2a0dd1710bebbe1bTimo Sirainen ssize_t ret;
2cd04598af2b69120948e29f2a0dd1710bebbe1bTimo Sirainen
2cd04598af2b69120948e29f2a0dd1710bebbe1bTimo Sirainen ret = read(conn->fd, buf, sizeof(buf));
2cd04598af2b69120948e29f2a0dd1710bebbe1bTimo Sirainen if (ret <= 0) {
2cd04598af2b69120948e29f2a0dd1710bebbe1bTimo Sirainen if (ret < 0) {
2cd04598af2b69120948e29f2a0dd1710bebbe1bTimo Sirainen if (errno == EAGAIN)
2cd04598af2b69120948e29f2a0dd1710bebbe1bTimo Sirainen return;
2cd04598af2b69120948e29f2a0dd1710bebbe1bTimo Sirainen if (errno != ECONNRESET)
2cd04598af2b69120948e29f2a0dd1710bebbe1bTimo Sirainen i_error("read(login connection) failed: %m");
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen login_connection_deinit(&conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2cc34f340d31125b16f58948bed8cc6a86911fcfTimo Sirainen output = auth_connection_get_output(conn->auth);
2cc34f340d31125b16f58948bed8cc6a86911fcfTimo Sirainen o_stream_nsend(output, buf, ret);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainenstatic void login_connection_authreply_input(struct login_connection *conn)
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen{
14cac26dcb71108abfdc95ea524e74be1f95774cPhil Carmody bool bail = FALSE;
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen const char *line;
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen
14cac26dcb71108abfdc95ea524e74be1f95774cPhil Carmody while (!bail && (line = i_stream_read_next_line(conn->input)) != NULL) T_BEGIN {
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen if (!conn->handshaked) {
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen if (!version_string_verify(line, "director-authreply-client",
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen AUTHREPLY_PROTOCOL_MAJOR_VERSION)) {
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen i_error("authreply client sent invalid handshake: %s", line);
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen login_connection_deinit(&conn);
14cac26dcb71108abfdc95ea524e74be1f95774cPhil Carmody bail = TRUE; /* don't return from within a T_BEGIN {...} T_END */
14cac26dcb71108abfdc95ea524e74be1f95774cPhil Carmody } else {
14cac26dcb71108abfdc95ea524e74be1f95774cPhil Carmody conn->handshaked = TRUE;
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen }
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen } else {
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen auth_input_line(line, conn);
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen }
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen } T_END;
14cac26dcb71108abfdc95ea524e74be1f95774cPhil Carmody
14cac26dcb71108abfdc95ea524e74be1f95774cPhil Carmody if (bail)
14cac26dcb71108abfdc95ea524e74be1f95774cPhil Carmody return;
14cac26dcb71108abfdc95ea524e74be1f95774cPhil Carmody
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen if (conn->input->eof) {
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen if (conn->input->stream_errno != 0 &&
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen conn->input->stream_errno != ECONNRESET) {
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen i_error("read(authreply connection) failed: %s",
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen i_stream_get_error(conn->input));
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen }
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen login_connection_deinit(&conn);
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen }
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen}
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenlogin_connection_send_line(struct login_connection *conn, const char *line)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct const_iovec iov[2];
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (conn->destroyed)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen iov[0].iov_base = line;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen iov[0].iov_len = strlen(line);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen iov[1].iov_base = "\n";
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen iov[1].iov_len = 1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsendv(conn->output, iov, N_ELEMENTS(iov));
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainenstatic bool login_host_request_is_self(struct login_host_request *request,
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen const struct ip_addr *dest_ip)
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen{
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen if (!net_ip_compare(dest_ip, &request->local_ip))
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen return FALSE;
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen if (request->dest_port != 0 && request->local_port != 0 &&
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen request->dest_port != request->local_port)
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen return FALSE;
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen return TRUE;
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen}
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainenstatic void
1b418300cc37ca9118f8a9b9e68176276267aef0Timo Sirainenlogin_host_callback(const struct mail_host *host, const char *hostname,
9de5eb9e1ac3a07c4197a60fdefd412d6cc78eb2Timo Sirainen const char *errormsg, void *context)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct login_host_request *request = context;
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen struct director *dir = request->conn->dir;
44875c83e0fa7111571262686818d8de43a57b2fTimo Sirainen const char *line, *line_params;
300e4e43ed1ca46d0614459161ca2fb460ef661aTimo Sirainen unsigned int secs;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
1b418300cc37ca9118f8a9b9e68176276267aef0Timo Sirainen if (host == NULL) {
44875c83e0fa7111571262686818d8de43a57b2fTimo Sirainen if (strncmp(request->line, "OK\t", 3) == 0)
44875c83e0fa7111571262686818d8de43a57b2fTimo Sirainen line_params = request->line + 3;
44875c83e0fa7111571262686818d8de43a57b2fTimo Sirainen else if (strncmp(request->line, "PASS\t", 5) == 0)
44875c83e0fa7111571262686818d8de43a57b2fTimo Sirainen line_params = request->line + 5;
44875c83e0fa7111571262686818d8de43a57b2fTimo Sirainen else
44875c83e0fa7111571262686818d8de43a57b2fTimo Sirainen i_panic("BUG: Unexpected line: %s", request->line);
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen i_error("director: User %s host lookup failed: %s",
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen request->username, errormsg);
44875c83e0fa7111571262686818d8de43a57b2fTimo Sirainen line = t_strconcat("FAIL\t", t_strcut(line_params, '\t'),
3131b0cc20e2e702082c8de4b623d7bd71b3b8e6Timo Sirainen "\tcode="AUTH_CLIENT_FAIL_CODE_TEMPFAIL, NULL);
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen } else if (request->director_proxy_maybe &&
1b418300cc37ca9118f8a9b9e68176276267aef0Timo Sirainen login_host_request_is_self(request, &host->ip)) {
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen line = request->line;
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen } else {
9de5eb9e1ac3a07c4197a60fdefd412d6cc78eb2Timo Sirainen string_t *str = t_str_new(64);
7b3acba3f2baf9710bf9b2bb17cdb92ff8937714Timo Sirainen char secs_buf[MAX_INT_STRLEN];
9de5eb9e1ac3a07c4197a60fdefd412d6cc78eb2Timo Sirainen
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen secs = dir->set->director_user_expire / 2;
7b3acba3f2baf9710bf9b2bb17cdb92ff8937714Timo Sirainen str_append(str, request->line);
7b3acba3f2baf9710bf9b2bb17cdb92ff8937714Timo Sirainen str_append(str, "\tproxy_refresh=");
7b3acba3f2baf9710bf9b2bb17cdb92ff8937714Timo Sirainen str_append(str, dec2str_buf(secs_buf, secs));
7b3acba3f2baf9710bf9b2bb17cdb92ff8937714Timo Sirainen str_append(str, "\thost=");
75aae86dfbad237872e214d595530ffa62a49fdaTimo Sirainen if (hostname == NULL || hostname[0] == '\0')
7b3acba3f2baf9710bf9b2bb17cdb92ff8937714Timo Sirainen str_append(str, host->ip_str);
9de5eb9e1ac3a07c4197a60fdefd412d6cc78eb2Timo Sirainen else {
7b3acba3f2baf9710bf9b2bb17cdb92ff8937714Timo Sirainen str_append(str, hostname);
7b3acba3f2baf9710bf9b2bb17cdb92ff8937714Timo Sirainen str_append(str, "\thostip=");
7b3acba3f2baf9710bf9b2bb17cdb92ff8937714Timo Sirainen str_append(str, host->ip_str);
9de5eb9e1ac3a07c4197a60fdefd412d6cc78eb2Timo Sirainen }
9de5eb9e1ac3a07c4197a60fdefd412d6cc78eb2Timo Sirainen line = str_c(str);
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen }
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen login_connection_send_line(request->conn, line);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen login_connection_unref(&request->conn);
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen i_free(request->username);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_free(request->line);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_free(request);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void auth_input_line(const char *line, void *context)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct login_connection *conn = context;
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen struct login_host_request *request, temp_request;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen const char *const *args, *line_params, *username = NULL, *tag = "";
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen bool proxy = FALSE, host = FALSE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (line == NULL) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* auth connection died -> kill also this login connection */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen login_connection_deinit(&conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen if (conn->type != LOGIN_CONNECTION_TYPE_USERDB &&
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen strncmp(line, "OK\t", 3) == 0)
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen line_params = line + 3;
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen else if (conn->type == LOGIN_CONNECTION_TYPE_USERDB &&
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen strncmp(line, "PASS\t", 5) == 0)
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen line_params = line + 5;
b4ddb5b3c3722620a8fef387dd8c47bb411a5643Timo Sirainen else {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen login_connection_send_line(conn, line);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* OK <id> [<parameters>] */
7a60e1dc9e93ef3f7c7fe1af6385a0bfa1e31bc3Timo Sirainen args = t_strsplit_tabescaped(line_params);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (*args != NULL) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* we should always get here, but in case we don't just
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen forward as-is and let login process handle the error. */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen args++;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&temp_request);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen for (; *args != NULL; args++) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (strncmp(*args, "proxy", 5) == 0 &&
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen ((*args)[5] == '=' || (*args)[5] == '\0'))
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen proxy = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen else if (strncmp(*args, "host=", 5) == 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen host = TRUE;
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen else if (strncmp(*args, "lip=", 4) == 0) {
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen if (net_addr2ip((*args) + 4, &temp_request.local_ip) < 0)
f0d8efc20cfcb38c132d333704bb08de2e9c62f1Timo Sirainen i_error("auth sent invalid lip field: %s", (*args) + 6);
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen } else if (strncmp(*args, "lport=", 6) == 0) {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (net_str2port((*args) + 6, &temp_request.local_port) < 0)
f0d8efc20cfcb38c132d333704bb08de2e9c62f1Timo Sirainen i_error("auth sent invalid lport field: %s", (*args) + 6);
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen } else if (strncmp(*args, "port=", 5) == 0) {
009217abb57a24a4076092e8e4e165545747839eStephan Bosch if (net_str2port((*args) + 5, &temp_request.dest_port) < 0)
f0d8efc20cfcb38c132d333704bb08de2e9c62f1Timo Sirainen i_error("auth sent invalid port field: %s", (*args) + 6);
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen } else if (strncmp(*args, "destuser=", 9) == 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen username = *args + 9;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen else if (strncmp(*args, "director_tag=", 13) == 0)
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen tag = *args + 13;
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen else if (strncmp(*args, "director_proxy_maybe", 20) == 0 &&
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen ((*args)[20] == '=' || (*args)[20] == '\0'))
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen temp_request.director_proxy_maybe = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen else if (strncmp(*args, "user=", 5) == 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (username == NULL)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen username = *args + 5;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen if ((!proxy && !temp_request.director_proxy_maybe) ||
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen host || username == NULL) {
456f3c79aafea8f6d009fab3d94946f38047dcd0Timo Sirainen login_connection_send_line(conn, line);
456f3c79aafea8f6d009fab3d94946f38047dcd0Timo Sirainen return;
456f3c79aafea8f6d009fab3d94946f38047dcd0Timo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (*conn->dir->set->master_user_separator != '\0') {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* with master user logins we still want to use only the
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen login username */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen username = t_strcut(username,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *conn->dir->set->master_user_separator);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* we need to add the host. the lookup might be asynchronous */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen request = i_new(struct login_host_request, 1);
0dc72981f5286d60ca9233f6ac7c444d393d24fbTimo Sirainen *request = temp_request;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen request->conn = conn;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen request->line = i_strdup(line);
152db3f90f298b7fb2dbbd4276f0fc30a9bc30f6Timo Sirainen request->username = i_strdup(username);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn->refcount++;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen director_request(conn->dir, username, tag, login_host_callback, request);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstruct login_connection *
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenlogin_connection_init(struct director *dir, int fd,
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen struct auth_connection *auth,
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen enum login_connection_type type)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct login_connection *conn;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn = i_new(struct login_connection, 1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn->refcount = 1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn->fd = fd;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn->dir = dir;
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->output = o_stream_create_fd(conn->fd, (size_t)-1);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_set_no_error_handling(conn->output, TRUE);
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen if (type != LOGIN_CONNECTION_TYPE_AUTHREPLY) {
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen i_assert(auth != NULL);
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen conn->auth = auth;
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen conn->io = io_add(conn->fd, IO_READ,
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen login_connection_input, conn);
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen auth_connection_set_callback(conn->auth, auth_input_line, conn);
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen } else {
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen i_assert(auth == NULL);
e93184a9055c2530366dfe617e07199603c399ddMartti Rannanjärvi conn->input = i_stream_create_fd(conn->fd, IO_BLOCK_SIZE);
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen conn->io = io_add(conn->fd, IO_READ,
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen login_connection_authreply_input, conn);
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen o_stream_nsend_str(conn->output, t_strdup_printf(
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen "VERSION\tdirector-authreply-server\t%d\t%d\n",
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen AUTHREPLY_PROTOCOL_MAJOR_VERSION,
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen AUTHREPLY_PROTOCOL_MINOR_VERSION));
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen }
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen conn->type = type;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen DLLIST_PREPEND(&login_connections, conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return conn;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid login_connection_deinit(struct login_connection **_conn)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct login_connection *conn = *_conn;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *_conn = NULL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (conn->destroyed)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn->destroyed = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen DLLIST_REMOVE(&login_connections, conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen io_remove(&conn->io);
be5773cb4d6edae8a5d9f300c3c7375cdd33826eJosef 'Jeff' Sipek i_stream_destroy(&conn->input);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_destroy(&conn->output);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (close(conn->fd) < 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_error("close(login connection) failed: %m");
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen conn->fd = -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen if (conn->auth != NULL)
db3b95d5a33ddce552d41136ae68d7331f8bf5feTimo Sirainen auth_connection_deinit(&conn->auth);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen login_connection_unref(&conn);
fe8af34153615d9007f2238fca87df11ff32d614Timo Sirainen
fe8af34153615d9007f2238fca87df11ff32d614Timo Sirainen master_service_client_connection_destroyed(master_service);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic void login_connection_unref(struct login_connection **_conn)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct login_connection *conn = *_conn;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen *_conn = NULL;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_assert(conn->refcount > 0);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (--conn->refcount == 0)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_free(conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenvoid login_connections_deinit(void)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen while (login_connections != NULL) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct login_connection *conn = login_connections;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen login_connection_deinit(&conn);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}