Mercurial > dovecot > core-2.2
comparison src/director/login-connection.c @ 18675:52cdf321fa07
director: Added "authreply" socket type.
This allows defining a socket, which receives auth replies. Director then
adds the "host" field to it if it's missing and returns back the original
string. The idea is that eventually a director ring could be running
independently from Dovecot proxies.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 13 May 2015 16:22:27 +0300 |
parents | d54dc360cd3c |
children | aabfe48db1cf |
comparison
equal
deleted
inserted
replaced
18674:c97d10467b62 | 18675:52cdf321fa07 |
---|---|
1 /* Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file */ | 1 /* Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file */ |
2 | 2 |
3 #include "lib.h" | 3 #include "lib.h" |
4 #include "ioloop.h" | 4 #include "ioloop.h" |
5 #include "net.h" | 5 #include "net.h" |
6 #include "istream.h" | |
6 #include "ostream.h" | 7 #include "ostream.h" |
7 #include "llist.h" | 8 #include "llist.h" |
8 #include "master-service.h" | 9 #include "master-service.h" |
9 #include "director.h" | 10 #include "director.h" |
10 #include "director-request.h" | 11 #include "director-request.h" |
11 #include "auth-connection.h" | 12 #include "auth-connection.h" |
12 #include "login-connection.h" | 13 #include "login-connection.h" |
13 | 14 |
14 #include <unistd.h> | 15 #include <unistd.h> |
15 | 16 |
17 #define AUTHREPLY_PROTOCOL_MAJOR_VERSION 1 | |
18 #define AUTHREPLY_PROTOCOL_MINOR_VERSION 0 | |
19 | |
16 struct login_connection { | 20 struct login_connection { |
17 struct login_connection *prev, *next; | 21 struct login_connection *prev, *next; |
18 | 22 |
19 int refcount; | 23 int refcount; |
24 enum login_connection_type type; | |
20 | 25 |
21 int fd; | 26 int fd; |
22 struct io *io; | 27 struct io *io; |
28 struct istream *input; | |
23 struct ostream *output; | 29 struct ostream *output; |
24 struct auth_connection *auth; | 30 struct auth_connection *auth; |
25 struct director *dir; | 31 struct director *dir; |
26 | 32 |
33 unsigned int handshaked:1; | |
27 unsigned int destroyed:1; | 34 unsigned int destroyed:1; |
28 unsigned int userdb:1; | |
29 }; | 35 }; |
30 | 36 |
31 struct login_host_request { | 37 struct login_host_request { |
32 struct login_connection *conn; | 38 struct login_connection *conn; |
33 char *line, *username; | 39 char *line, *username; |
38 bool director_proxy_maybe; | 44 bool director_proxy_maybe; |
39 }; | 45 }; |
40 | 46 |
41 static struct login_connection *login_connections; | 47 static struct login_connection *login_connections; |
42 | 48 |
49 static void auth_input_line(const char *line, void *context); | |
43 static void login_connection_unref(struct login_connection **_conn); | 50 static void login_connection_unref(struct login_connection **_conn); |
44 | 51 |
45 static void login_connection_input(struct login_connection *conn) | 52 static void login_connection_input(struct login_connection *conn) |
46 { | 53 { |
47 struct ostream *output; | 54 struct ostream *output; |
59 login_connection_deinit(&conn); | 66 login_connection_deinit(&conn); |
60 return; | 67 return; |
61 } | 68 } |
62 output = auth_connection_get_output(conn->auth); | 69 output = auth_connection_get_output(conn->auth); |
63 o_stream_nsend(output, buf, ret); | 70 o_stream_nsend(output, buf, ret); |
71 } | |
72 | |
73 static void login_connection_authreply_input(struct login_connection *conn) | |
74 { | |
75 const char *line; | |
76 | |
77 while ((line = i_stream_read_next_line(conn->input)) != NULL) T_BEGIN { | |
78 if (!conn->handshaked) { | |
79 if (!version_string_verify(line, "director-authreply-client", | |
80 AUTHREPLY_PROTOCOL_MAJOR_VERSION)) { | |
81 i_error("authreply client sent invalid handshake: %s", line); | |
82 login_connection_deinit(&conn); | |
83 return; | |
84 } | |
85 conn->handshaked = TRUE; | |
86 } else { | |
87 auth_input_line(line, conn); | |
88 } | |
89 } T_END; | |
90 if (conn->input->eof) { | |
91 if (conn->input->stream_errno != 0 && | |
92 conn->input->stream_errno != ECONNRESET) { | |
93 i_error("read(authreply connection) failed: %s", | |
94 i_stream_get_error(conn->input)); | |
95 } | |
96 login_connection_deinit(&conn); | |
97 } | |
64 } | 98 } |
65 | 99 |
66 static void | 100 static void |
67 login_connection_send_line(struct login_connection *conn, const char *line) | 101 login_connection_send_line(struct login_connection *conn, const char *line) |
68 { | 102 { |
136 if (line == NULL) { | 170 if (line == NULL) { |
137 /* auth connection died -> kill also this login connection */ | 171 /* auth connection died -> kill also this login connection */ |
138 login_connection_deinit(&conn); | 172 login_connection_deinit(&conn); |
139 return; | 173 return; |
140 } | 174 } |
141 if (!conn->userdb && strncmp(line, "OK\t", 3) == 0) | 175 if (conn->type != LOGIN_CONNECTION_TYPE_USERDB && |
176 strncmp(line, "OK\t", 3) == 0) | |
142 line_params = line + 3; | 177 line_params = line + 3; |
143 else if (conn->userdb && strncmp(line, "PASS\t", 5) == 0) | 178 else if (conn->type == LOGIN_CONNECTION_TYPE_USERDB && |
179 strncmp(line, "PASS\t", 5) == 0) | |
144 line_params = line + 5; | 180 line_params = line + 5; |
145 else { | 181 else { |
146 login_connection_send_line(conn, line); | 182 login_connection_send_line(conn, line); |
147 return; | 183 return; |
148 } | 184 } |
206 director_request(conn->dir, username, tag, login_host_callback, request); | 242 director_request(conn->dir, username, tag, login_host_callback, request); |
207 } | 243 } |
208 | 244 |
209 struct login_connection * | 245 struct login_connection * |
210 login_connection_init(struct director *dir, int fd, | 246 login_connection_init(struct director *dir, int fd, |
211 struct auth_connection *auth, bool userdb) | 247 struct auth_connection *auth, |
248 enum login_connection_type type) | |
212 { | 249 { |
213 struct login_connection *conn; | 250 struct login_connection *conn; |
214 | 251 |
215 conn = i_new(struct login_connection, 1); | 252 conn = i_new(struct login_connection, 1); |
216 conn->refcount = 1; | 253 conn->refcount = 1; |
217 conn->fd = fd; | 254 conn->fd = fd; |
218 conn->auth = auth; | |
219 conn->dir = dir; | 255 conn->dir = dir; |
220 conn->output = o_stream_create_fd(conn->fd, (size_t)-1, FALSE); | 256 conn->output = o_stream_create_fd(conn->fd, (size_t)-1, FALSE); |
221 o_stream_set_no_error_handling(conn->output, TRUE); | 257 o_stream_set_no_error_handling(conn->output, TRUE); |
222 conn->io = io_add(conn->fd, IO_READ, login_connection_input, conn); | 258 if (type != LOGIN_CONNECTION_TYPE_AUTHREPLY) { |
223 conn->userdb = userdb; | 259 i_assert(auth != NULL); |
224 | 260 conn->auth = auth; |
225 auth_connection_set_callback(conn->auth, auth_input_line, conn); | 261 conn->io = io_add(conn->fd, IO_READ, |
262 login_connection_input, conn); | |
263 auth_connection_set_callback(conn->auth, auth_input_line, conn); | |
264 } else { | |
265 i_assert(auth == NULL); | |
266 conn->input = i_stream_create_fd(conn->fd, IO_BLOCK_SIZE, FALSE); | |
267 conn->io = io_add(conn->fd, IO_READ, | |
268 login_connection_authreply_input, conn); | |
269 o_stream_nsend_str(conn->output, t_strdup_printf( | |
270 "VERSION\tdirector-authreply-server\t%d\t%d\n", | |
271 AUTHREPLY_PROTOCOL_MAJOR_VERSION, | |
272 AUTHREPLY_PROTOCOL_MINOR_VERSION)); | |
273 } | |
274 conn->type = type; | |
275 | |
226 DLLIST_PREPEND(&login_connections, conn); | 276 DLLIST_PREPEND(&login_connections, conn); |
227 return conn; | 277 return conn; |
228 } | 278 } |
229 | 279 |
230 void login_connection_deinit(struct login_connection **_conn) | 280 void login_connection_deinit(struct login_connection **_conn) |
237 return; | 287 return; |
238 conn->destroyed = TRUE; | 288 conn->destroyed = TRUE; |
239 | 289 |
240 DLLIST_REMOVE(&login_connections, conn); | 290 DLLIST_REMOVE(&login_connections, conn); |
241 io_remove(&conn->io); | 291 io_remove(&conn->io); |
292 if (conn->input != NULL) | |
293 i_stream_destroy(&conn->input); | |
242 o_stream_destroy(&conn->output); | 294 o_stream_destroy(&conn->output); |
243 if (close(conn->fd) < 0) | 295 if (close(conn->fd) < 0) |
244 i_error("close(login connection) failed: %m"); | 296 i_error("close(login connection) failed: %m"); |
245 conn->fd = -1; | 297 conn->fd = -1; |
246 | 298 |
247 auth_connection_deinit(&conn->auth); | 299 if (conn->auth != NULL) |
300 auth_connection_deinit(&conn->auth); | |
248 login_connection_unref(&conn); | 301 login_connection_unref(&conn); |
249 | 302 |
250 master_service_client_connection_destroyed(master_service); | 303 master_service_client_connection_destroyed(master_service); |
251 } | 304 } |
252 | 305 |