Mercurial > dovecot > original-hg > dovecot-1.2
changeset 2768:d344be0bb70f HEAD
Added IMAP and POP3 proxying support.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Mon, 18 Oct 2004 22:21:40 +0300 |
parents | 54dfccbe7f11 |
children | 0058f0b70402 |
files | src/auth/auth-client-connection.c src/auth/mech.h src/auth/passdb-sql.c src/imap-login/Makefile.am src/imap-login/client-authenticate.c src/imap-login/client.c src/imap-login/client.h src/imap-login/imap-proxy.c src/imap-login/imap-proxy.h src/login-common/Makefile.am src/login-common/login-proxy.c src/login-common/login-proxy.h src/login-common/main.c src/login-common/sasl-server.c src/pop3-login/Makefile.am src/pop3-login/client-authenticate.c src/pop3-login/client.c src/pop3-login/client.h src/pop3-login/pop3-proxy.c src/pop3-login/pop3-proxy.h |
diffstat | 20 files changed, 556 insertions(+), 48 deletions(-) [+] |
line wrap: on
line diff
--- a/src/auth/auth-client-connection.c Mon Oct 18 11:17:31 2004 +0300 +++ b/src/auth/auth-client-connection.c Mon Oct 18 22:21:40 2004 +0300 @@ -80,10 +80,11 @@ break; case AUTH_CLIENT_RESULT_FAILURE: str = t_str_new(128); - str_printfa(str, "FAIL\t%u", request->id); - str_append_c(str, '\t'); + str_printfa(str, "FAIL\t%u\t", request->id); if (reply != NULL) str_append(str, reply); + if (request->user != NULL) + str_printfa(str, "\tuser=%s", request->user); if (request->extra_fields) { str_append_c(str, '\t'); str_append(str, request->extra_fields);
--- a/src/auth/mech.h Mon Oct 18 11:17:31 2004 +0300 +++ b/src/auth/mech.h Mon Oct 18 22:21:40 2004 +0300 @@ -37,6 +37,7 @@ unsigned int accept_input:1; unsigned int no_failure_delay:1; unsigned int no_login:1; + unsigned int proxy:1; /* ... mechanism specific data ... */ };
--- a/src/auth/passdb-sql.c Mon Oct 18 11:17:31 2004 +0300 +++ b/src/auth/passdb-sql.c Mon Oct 18 22:21:40 2004 +0300 @@ -30,6 +30,7 @@ static struct sql_connection *passdb_sql_conn; static void result_save_extra_fields(struct sql_result *result, + struct passdb_sql_request *sql_request, struct auth_request *auth_request) { unsigned int i, fields_count; @@ -66,6 +67,21 @@ str_append_c(str, '\t'); str_append(str, name); } + } else if (strcmp(name, "proxy") == 0) { + if (*value == 'Y') { + /* we're proxying authentication for this + user. send password back if using plaintext + authentication. */ + auth_request->proxy = TRUE; + if (str_len(str) > 0) + str_append_c(str, '\t'); + str_append(str, name); + + if (*sql_request->password != '\0') { + str_printfa(str, "\tpass=%s", + sql_request->password); + } + } } else { if (str_len(str) > 0) str_append_c(str, '\t'); @@ -102,7 +118,7 @@ get_log_prefix(auth_request)); } else { password = t_strdup(sql_result_get_field_value(result, idx)); - result_save_extra_fields(result, auth_request); + result_save_extra_fields(result, sql_request, auth_request); } if (ret > 0) {
--- a/src/imap-login/Makefile.am Mon Oct 18 11:17:31 2004 +0300 +++ b/src/imap-login/Makefile.am Mon Oct 18 22:21:40 2004 +0300 @@ -10,15 +10,17 @@ imap_login_LDADD = \ ../login-common/liblogin-common.a \ - ../lib-imap/imap-parser.o \ + ../lib-imap/libimap.a \ ../lib-auth/libauth.a \ ../lib/liblib.a \ $(SSL_LIBS) imap_login_SOURCES = \ client.c \ - client-authenticate.c + client-authenticate.c \ + imap-proxy.c noinst_HEADERS = \ client.h \ - client-authenticate.h + client-authenticate.h \ + imap-proxy.h
--- a/src/imap-login/client-authenticate.c Mon Oct 18 11:17:31 2004 +0300 +++ b/src/imap-login/client-authenticate.c Mon Oct 18 22:21:40 2004 +0300 @@ -13,6 +13,9 @@ #include "auth-client.h" #include "client.h" #include "client-authenticate.h" +#include "imap-proxy.h" + +#include <stdlib.h> const char *client_authenticate_get_capabilities(int secured) { @@ -76,39 +79,85 @@ safe_memset(line, 0, strlen(line)); } -static int client_handle_success_args(struct imap_client *client, - const char *const *args, int nologin) +static int client_handle_args(struct imap_client *client, + const char *const *args, int nologin) { - const char *reason = NULL, *referral = NULL; + const char *reason = NULL, *host = NULL, *destuser = NULL, *pass = NULL; string_t *reply; + unsigned int port = 143; + int proxy = FALSE; for (; *args != NULL; args++) { if (strcmp(*args, "nologin") == 0) nologin = TRUE; + else if (strcmp(*args, "proxy") == 0) + proxy = TRUE; else if (strncmp(*args, "reason=", 7) == 0) reason = *args + 7; - else if (strncmp(*args, "referral=", 9) == 0) - referral = *args + 9; + else if (strncmp(*args, "host=", 5) == 0) + host = *args + 5; + else if (strncmp(*args, "port=", 5) == 0) + port = atoi(*args + 5); + else if (strncmp(*args, "destuser=", 9) == 0) + destuser = *args + 9; + else if (strncmp(*args, "pass=", 5) == 0) + pass = *args + 5; } - if (!nologin && referral == NULL) - return FALSE; + if (destuser == NULL) + destuser = client->common.virtual_user; + + if (proxy) { + /* we want to proxy the connection to another server. - reply = t_str_new(128); - str_append(reply, nologin ? "NO " : "OK "); - if (referral != NULL) - str_printfa(reply, "[REFERRAL %s] ", referral); + proxy host=.. [port=..] [destuser=..] pass=.. */ + if (imap_proxy_new(client, host, port, destuser, pass) < 0) + client_destroy_internal_failure(client); + else { + client_destroy(client, t_strconcat( + "Proxy: ", client->common.virtual_user, NULL)); + } + return TRUE; + } else if (host != NULL) { + /* IMAP referral + + [nologin] referral host=.. [port=..] [destuser=..] + [reason=..] - if (reason != NULL) - str_append(reply, reason); - else if (!nologin) - str_append(reply, "Logged in."); - else if (referral != NULL) - str_append(reply, "Try this server instead."); - else - str_append(reply, "Login disabled."); + NO [REFERRAL imap://destuser;AUTH=..@host:port/] Can't login. + OK [...] Logged in, but you should use this server instead. + .. [REFERRAL ..] (Reason from auth server) + */ + reply = t_str_new(128); + str_append(reply, nologin ? "NO " : "OK "); + str_printfa(reply, "[REFERRAL imap://%s;AUTH=%s@%s", + destuser, client->common.auth_mech_name, host); + if (port != 143) + str_printfa(reply, ":%u", port); + str_append(reply, "/] "); + if (reason != NULL) + str_append(reply, reason); + else if (nologin) + str_append(reply, "Try this server instead."); + else { + str_append(reply, "Logged in, but you should use " + "this server instead."); + } + client_send_tagline(client, str_c(reply)); + } else if (nologin) { + /* Authentication went ok, but for some reason user isn't + allowed to log in. Shouldn't probably happen. */ + reply = t_str_new(128); + if (reason != NULL) + str_printfa(reply, "NO %s", reason); + else + str_append(reply, "NO Login not allowed."); + client_send_tagline(client, str_c(reply)); + } else { + /* normal login/failure */ + return FALSE; + } - client_send_tagline(client, str_c(reply)); if (!nologin) { client_destroy(client, t_strconcat( "Login: ", client->common.virtual_user, NULL)); @@ -133,7 +182,7 @@ switch (reply) { case SASL_SERVER_REPLY_SUCCESS: if (args != NULL) { - if (client_handle_success_args(client, args, FALSE)) + if (client_handle_args(client, args, FALSE)) break; } @@ -143,7 +192,7 @@ break; case SASL_SERVER_REPLY_AUTH_FAILED: if (args != NULL) { - if (client_handle_success_args(client, args, TRUE)) + if (client_handle_args(client, args, TRUE)) break; } @@ -161,11 +210,7 @@ client_input, client); break; case SASL_SERVER_REPLY_MASTER_FAILED: - client_send_line(client, "* BYE Internal login failure. " - "Refer to server log for more information."); - client_destroy(client, t_strconcat("Internal login failure: ", - client->common.virtual_user, - NULL)); + client_destroy_internal_failure(client); break; case SASL_SERVER_REPLY_CONTINUE: data_len = strlen(data);
--- a/src/imap-login/client.c Mon Oct 18 11:17:31 2004 +0300 +++ b/src/imap-login/client.c Mon Oct 18 22:21:40 2004 +0300 @@ -15,6 +15,7 @@ #include "client-authenticate.h" #include "auth-client.h" #include "ssl-proxy.h" +#include "imap-proxy.h" /* max. size of one parameter in line, or max reply length in SASL authentication */ @@ -442,7 +443,8 @@ hash_remove(clients, client); i_stream_close(client->input); - o_stream_close(client->output); + if (client->output != NULL) + o_stream_close(client->output); if (client->common.auth_request != NULL) { auth_client_request_abort(client->common.auth_request); @@ -467,6 +469,14 @@ client_unref(client); } +void client_destroy_internal_failure(struct imap_client *client) +{ + client_send_line(client, "* BYE Internal login failure. " + "Refer to server log for more information."); + client_destroy(client, t_strconcat("Internal login failure: ", + client->common.virtual_user, NULL)); +} + void client_ref(struct imap_client *client) { client->refcount++; @@ -480,7 +490,8 @@ imap_parser_destroy(client->parser); i_stream_unref(client->input); - o_stream_unref(client->output); + if (client->output != NULL) + o_stream_unref(client->output); i_free(client->common.virtual_user); i_free(client->common.auth_mech_name);
--- a/src/imap-login/client.h Mon Oct 18 11:17:31 2004 +0300 +++ b/src/imap-login/client.h Mon Oct 18 22:21:40 2004 +0300 @@ -28,6 +28,7 @@ }; void client_destroy(struct imap_client *client, const char *reason); +void client_destroy_internal_failure(struct imap_client *client); void client_send_line(struct imap_client *client, const char *line); void client_send_tagline(struct imap_client *client, const char *line);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/imap-login/imap-proxy.c Mon Oct 18 22:21:40 2004 +0300 @@ -0,0 +1,41 @@ +/* Copyright (C) 2004 Timo Sirainen */ + +#include "common.h" +#include "ioloop.h" +#include "str.h" +#include "client.h" +#include "imap-quote.h" +#include "login-proxy.h" +#include "imap-proxy.h" + +int imap_proxy_new(struct imap_client *client, const char *host, + unsigned int port, const char *user, const char *password) +{ + string_t *str; + + i_assert(user != NULL); + + if (password == NULL) { + i_error("proxy(%s): password not given", + client->common.virtual_user); + return -1; + } + + str = t_str_new(128); + str_append(str, client->cmd_tag); + str_append(str, " LOGIN "); + imap_quote_append_string(str, user, FALSE); + str_append_c(str, ' '); + imap_quote_append_string(str, password, FALSE); + str_append(str, "\r\n"); + + if (login_proxy_new(&client->common, host, port, str_c(str)) < 0) + return -1; + + if (client->io != NULL) { + io_remove(client->io); + client->io = NULL; + } + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/imap-login/imap-proxy.h Mon Oct 18 22:21:40 2004 +0300 @@ -0,0 +1,7 @@ +#ifndef __IMAP_PROXY_H +#define __IMAP_PROXY_H + +int imap_proxy_new(struct imap_client *client, const char *host, + unsigned int port, const char *user, const char *password); + +#endif
--- a/src/login-common/Makefile.am Mon Oct 18 11:17:31 2004 +0300 +++ b/src/login-common/Makefile.am Mon Oct 18 22:21:40 2004 +0300 @@ -8,6 +8,7 @@ liblogin_common_a_SOURCES = \ client-common.c \ + login-proxy.c \ main.c \ master.c \ sasl-server.c \ @@ -17,6 +18,7 @@ noinst_HEADERS = \ client-common.h \ + login-proxy.h \ common.h \ master.h \ sasl-server.h \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/login-common/login-proxy.c Mon Oct 18 22:21:40 2004 +0300 @@ -0,0 +1,266 @@ +/* Copyright (C) 2004 Timo Sirainen */ + +#include "common.h" +#include "ioloop.h" +#include "istream.h" +#include "ostream.h" +#include "safe-memset.h" +#include "hash.h" +#include "client-common.h" +#include "login-proxy.h" + +#define MAX_INBUF_SIZE 4096 +#define OUTBUF_THRESHOLD 1024 + +struct login_proxy { + struct client *client; + + int client_fd, proxy_fd; + struct io *client_io, *proxy_io; + struct ostream *client_output, *proxy_output; + + char *host, *user, *login_cmd; + unsigned int port; +}; + +static struct hash_table *login_proxies; + +static void login_proxy_free(struct login_proxy *proxy); + +static void proxy_input(void *context) +{ + struct login_proxy *proxy = context; + unsigned char buf[OUTBUF_THRESHOLD]; + ssize_t ret; + + if (o_stream_get_buffer_used_size(proxy->client_output) > + OUTBUF_THRESHOLD) { + /* client's output buffer is already quite full. + don't send more until we're below threshold. */ + io_remove(proxy->proxy_io); + proxy->proxy_io = NULL; + return; + } + + ret = net_receive(proxy->proxy_fd, buf, sizeof(buf)); + if (ret > 0) + (void)o_stream_send(proxy->client_output, buf, ret); + else if (ret < 0) + login_proxy_free(proxy); +} + +static void proxy_client_input(void *context) +{ + struct login_proxy *proxy = context; + unsigned char buf[OUTBUF_THRESHOLD]; + ssize_t ret; + + if (o_stream_get_buffer_used_size(proxy->proxy_output) > + OUTBUF_THRESHOLD) { + /* proxy's output buffer is already quite full. + don't send more until we're below threshold. */ + io_remove(proxy->client_io); + proxy->client_io = NULL; + return; + } + + ret = net_receive(proxy->client_fd, buf, sizeof(buf)); + if (ret > 0) + (void)o_stream_send(proxy->proxy_output, buf, ret); + else if (ret < 0) + login_proxy_free(proxy); +} + +static void proxy_output(void *context) +{ + struct login_proxy *proxy = context; + + if (o_stream_flush(proxy->proxy_output) < 0) { + login_proxy_free(proxy); + return; + } + + if (proxy->client_io == NULL && + o_stream_get_buffer_used_size(proxy->proxy_output) < + OUTBUF_THRESHOLD) { + /* there's again space in proxy's output buffer, so we can + read more from client. */ + proxy->client_io = io_add(proxy->client_fd, IO_READ, + proxy_client_input, proxy); + } +} + +static void proxy_client_output(void *context) +{ + struct login_proxy *proxy = context; + + if (o_stream_flush(proxy->client_output) < 0) { + login_proxy_free(proxy); + return; + } + + if (proxy->proxy_io == NULL && + o_stream_get_buffer_used_size(proxy->client_output) < + OUTBUF_THRESHOLD) { + /* there's again space in client's output buffer, so we can + read more from proxy. */ + proxy->proxy_io = + io_add(proxy->proxy_fd, IO_READ, proxy_input, proxy); + } +} + +static void proxy_prelogin_input(void *context) +{ + struct login_proxy *proxy = context; + unsigned char buf[1024]; + ssize_t ret; + + ret = net_receive(proxy->proxy_fd, buf, sizeof(buf)); + if (ret < 0) { + /* disconnected */ + login_proxy_free(proxy); + return; + } + + /* we just want to eat away the first banner line. be dummy and don't + check any errors, so we don't need any IMAP/POP3-specific things + here (except for assuming the banner line..) */ + if (buf[ret-1] != '\n') + return; + + /* send LOGIN command */ + (void)o_stream_send_str(proxy->proxy_output, proxy->login_cmd); + + safe_memset(proxy->login_cmd, 0, strlen(proxy->login_cmd)); + i_free(proxy->login_cmd); + proxy->login_cmd = NULL; + + /* from now on, just do dummy proxying */ + io_remove(proxy->proxy_io); + proxy->proxy_io = io_add(proxy->proxy_fd, IO_READ, proxy_input, proxy); + proxy->client_io = io_add(proxy->client_fd, IO_READ, + proxy_client_input, proxy); + + proxy->client_output = + o_stream_create_file(proxy->client_fd, default_pool, + (size_t)-1, FALSE); + + o_stream_set_flush_callback(proxy->client_output, + proxy_client_output, proxy); + o_stream_set_flush_callback(proxy->proxy_output, proxy_output, proxy); +} + +static void proxy_wait_connect(void *context) +{ + struct login_proxy *proxy = context; + int err; + + err = net_geterror(proxy->proxy_fd); + if (err != 0) { + i_error("proxy: connect(%s, %u) failed: %s", + proxy->host, proxy->port, strerror(err)); + login_proxy_free(proxy); + return; + } + + /* initialize proxy's streams */ + proxy->proxy_output = + o_stream_create_file(proxy->proxy_fd, default_pool, + (size_t)-1, FALSE); + + io_remove(proxy->proxy_io); + proxy->proxy_io = + io_add(proxy->proxy_fd, IO_READ, proxy_prelogin_input, proxy); +} + +int login_proxy_new(struct client *client, const char *host, + unsigned int port, const char *login_cmd) +{ + struct login_proxy *proxy; + struct ip_addr ip; + int fd; + + if (host == NULL) { + i_error("proxy(%s): host not given", client->virtual_user); + return -1; + } + + if (net_addr2ip(host, &ip) < 0) { + i_error("proxy(%s): %s is not a valid IP", + client->virtual_user, host); + return -1; + } + + fd = net_connect_ip(&ip, port, NULL); + if (fd < 0) { + i_error("proxy(%s): connect(%s, %u) failed: %m", + client->virtual_user, host, port); + return -1; + } + + proxy = i_new(struct login_proxy, 1); + proxy->host = i_strdup(host); + proxy->login_cmd = i_strdup(login_cmd); + proxy->port = port; + + proxy->proxy_fd = fd; + proxy->proxy_io = io_add(fd, IO_WRITE, proxy_wait_connect, proxy); + + /* move client fd */ + proxy->client_fd = client->fd; + client->fd = -1; + + if (login_proxies == NULL) { + login_proxies = hash_create(default_pool, default_pool, + 0, NULL, NULL); + } + hash_insert(login_proxies, proxy, proxy); + + proxy->client = client; + main_ref(); + return 0; +} + +static void login_proxy_free(struct login_proxy *proxy) +{ + main_unref(); + + hash_remove(login_proxies, proxy); + + if (proxy->proxy_io != NULL) + io_remove(proxy->proxy_io); + if (proxy->proxy_output != NULL) + o_stream_unref(proxy->proxy_output); + + if (proxy->client_io != NULL) + io_remove(proxy->client_io); + if (proxy->client_output != NULL) + o_stream_unref(proxy->client_output); + + net_disconnect(proxy->proxy_fd); + net_disconnect(proxy->client_fd); + + if (proxy->login_cmd != NULL) { + safe_memset(proxy->login_cmd, 0, strlen(proxy->login_cmd)); + i_free(proxy->login_cmd); + } + + i_free(proxy->host); + i_free(proxy->user); + i_free(proxy); +} + +void login_proxy_deinit(void) +{ + struct hash_iterate_context *iter; + void *key, *value; + + if (login_proxies == NULL) + return; + + iter = hash_iterate_init(login_proxies); + while (hash_iterate(iter, &key, &value)) + login_proxy_free(value); + hash_iterate_deinit(iter); + hash_destroy(login_proxies); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/login-common/login-proxy.h Mon Oct 18 22:21:40 2004 +0300 @@ -0,0 +1,11 @@ +#ifndef __LOGIN_PROXY_H +#define __LOGIN_PROXY_H + +/* Create a proxy to given host. Returns -1 if failed, or 0 if ok. + In any case the client should be destroyed after this call. */ +int login_proxy_new(struct client *client, const char *host, + unsigned int port, const char *login_cmd); + +void login_proxy_deinit(void); + +#endif
--- a/src/login-common/main.c Mon Oct 18 11:17:31 2004 +0300 +++ b/src/login-common/main.c Mon Oct 18 22:21:40 2004 +0300 @@ -12,6 +12,7 @@ #include "client-common.h" #include "auth-client.h" #include "ssl-proxy.h" +#include "login-proxy.h" #include <stdlib.h> #include <unistd.h> @@ -219,6 +220,7 @@ if (io_ssl_listen != NULL) io_remove(io_ssl_listen); ssl_proxy_deinit(); + login_proxy_deinit(); auth_client_free(auth_client); clients_deinit();
--- a/src/login-common/sasl-server.c Mon Oct 18 11:17:31 2004 +0300 +++ b/src/login-common/sasl-server.c Mon Oct 18 22:21:40 2004 +0300 @@ -88,6 +88,16 @@ case -1: client->auth_request = NULL; + if (args != NULL) { + for (i = 0; args[i] != NULL; i++) { + if (strncmp(args[i], "user=", 5) == 0) { + i_free(client->virtual_user); + client->virtual_user = + i_strdup(args[i] + 5); + } + } + } + /* base64 contains error message, if there is one */ if (verbose_auth && data_base64 != NULL) { client_syslog(client, "Authenticate %s failed: %s",
--- a/src/pop3-login/Makefile.am Mon Oct 18 11:17:31 2004 +0300 +++ b/src/pop3-login/Makefile.am Mon Oct 18 22:21:40 2004 +0300 @@ -15,8 +15,10 @@ pop3_login_SOURCES = \ client.c \ - client-authenticate.c + client-authenticate.c \ + pop3-proxy.c noinst_HEADERS = \ client.h \ - client-authenticate.h + client-authenticate.h \ + pop3-proxy.h
--- a/src/pop3-login/client-authenticate.c Mon Oct 18 11:17:31 2004 +0300 +++ b/src/pop3-login/client-authenticate.c Mon Oct 18 22:21:40 2004 +0300 @@ -15,6 +15,9 @@ #include "ssl-proxy.h" #include "client.h" #include "client-authenticate.h" +#include "pop3-proxy.h" + +#include <stdlib.h> int cmd_capa(struct pop3_client *client, const char *args __attr_unused__) { @@ -77,18 +80,45 @@ safe_memset(line, 0, strlen(line)); } -static int client_handle_success_args(struct pop3_client *client, - const char *const *args) +static int client_handle_args(struct pop3_client *client, + const char *const *args, int nologin) { - const char *reason = NULL; + const char *reason = NULL, *host = NULL, *destuser = NULL, *pass = NULL; string_t *reply; - int nologin = FALSE; + unsigned int port = 110; + int proxy = FALSE; for (; *args != NULL; args++) { if (strcmp(*args, "nologin") == 0) nologin = TRUE; + else if (strcmp(*args, "proxy") == 0) + proxy = TRUE; else if (strncmp(*args, "reason=", 7) == 0) reason = *args + 7; + else if (strncmp(*args, "host=", 5) == 0) + host = *args + 5; + else if (strncmp(*args, "port=", 5) == 0) + port = atoi(*args + 5); + else if (strncmp(*args, "destuser=", 9) == 0) + destuser = *args + 9; + else if (strncmp(*args, "pass=", 5) == 0) + pass = *args + 5; + } + + if (destuser == NULL) + destuser = client->common.virtual_user; + + if (proxy) { + /* we want to proxy the connection to another server. + + proxy host=.. [port=..] [destuser=..] pass=.. */ + if (pop3_proxy_new(client, host, port, destuser, pass) < 0) + client_destroy_internal_failure(client); + else { + client_destroy(client, t_strconcat( + "Proxy: ", client->common.virtual_user, NULL)); + } + return TRUE; } if (!nologin) @@ -122,7 +152,7 @@ switch (reply) { case SASL_SERVER_REPLY_SUCCESS: if (args != NULL) { - if (client_handle_success_args(client, args)) + if (client_handle_args(client, args, FALSE)) break; } @@ -131,6 +161,11 @@ "Login: ", client->common.virtual_user, NULL)); break; case SASL_SERVER_REPLY_AUTH_FAILED: + if (args != NULL) { + if (client_handle_args(client, args, TRUE)) + break; + } + if (data == NULL) client_send_line(client, "-ERR Authentication failed"); else { @@ -145,12 +180,7 @@ client_input, client); break; case SASL_SERVER_REPLY_MASTER_FAILED: - client_send_line(client, - "-ERR [IN-USE] Internal login failure. " - "Refer to server log for more information."); - client_destroy(client, t_strconcat("Internal login failure: ", - client->common.virtual_user, - NULL)); + client_destroy_internal_failure(client); break; case SASL_SERVER_REPLY_CONTINUE: data_len = strlen(data);
--- a/src/pop3-login/client.c Mon Oct 18 11:17:31 2004 +0300 +++ b/src/pop3-login/client.c Mon Oct 18 22:21:40 2004 +0300 @@ -366,6 +366,14 @@ client_unref(client); } +void client_destroy_internal_failure(struct pop3_client *client) +{ + client_send_line(client, "-ERR [IN-USE] Internal login failure. " + "Refer to server log for more information."); + client_destroy(client, t_strconcat("Internal login failure: ", + client->common.virtual_user, NULL)); +} + void client_ref(struct pop3_client *client) { client->refcount++;
--- a/src/pop3-login/client.h Mon Oct 18 11:17:31 2004 +0300 +++ b/src/pop3-login/client.h Mon Oct 18 22:21:40 2004 +0300 @@ -30,6 +30,7 @@ }; void client_destroy(struct pop3_client *client, const char *reason); +void client_destroy_internal_failure(struct pop3_client *client); void client_send_line(struct pop3_client *client, const char *line);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pop3-login/pop3-proxy.c Mon Oct 18 22:21:40 2004 +0300 @@ -0,0 +1,44 @@ +/* Copyright (C) 2004 Timo Sirainen */ + +#include "common.h" +#include "ioloop.h" +#include "base64.h" +#include "str.h" +#include "client.h" +#include "login-proxy.h" +#include "pop3-proxy.h" + +int pop3_proxy_new(struct pop3_client *client, const char *host, + unsigned int port, const char *user, const char *password) +{ + string_t *auth, *str; + + i_assert(user != NULL); + + if (password == NULL) { + i_error("proxy(%s): password not given", + client->common.virtual_user); + return -1; + } + + auth = t_str_new(128); + str_append_c(auth, '\0'); + str_append(auth, user); + str_append_c(auth, '\0'); + str_append(auth, password); + + str = t_str_new(128); + str_append(str, "AUTH "); + base64_encode(str_data(auth), str_len(auth), str); + str_append(str, "\r\n"); + + if (login_proxy_new(&client->common, host, port, str_c(str)) < 0) + return -1; + + if (client->io != NULL) { + io_remove(client->io); + client->io = NULL; + } + + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pop3-login/pop3-proxy.h Mon Oct 18 22:21:40 2004 +0300 @@ -0,0 +1,7 @@ +#ifndef __POP3_PROXY_H +#define __POP3_PROXY_H + +int pop3_proxy_new(struct pop3_client *client, const char *host, + unsigned int port, const char *user, const char *password); + +#endif