Mercurial > dovecot > original-hg > dovecot-1.2
view src/pop3-login/pop3-proxy.c @ 4891:6ab2712f1a93 HEAD
Only imap binary was actually working.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 10 Dec 2006 14:35:02 +0200 |
parents | 32e2b35e3aac |
children | 5b4c9b20eba0 |
line wrap: on
line source
/* Copyright (C) 2004 Timo Sirainen */ #include "common.h" #include "ioloop.h" #include "istream.h" #include "ostream.h" #include "base64.h" #include "safe-memset.h" #include "str.h" #include "client.h" #include "pop3-proxy.h" static void proxy_input(struct istream *input, struct ostream *output, void *context) { struct pop3_client *client = context; string_t *str; const char *line; i_assert(!client->destroyed); if (input == NULL) { if (client->io != NULL) { /* remote authentication failed, we're just freeing the proxy */ return; } /* failed for some reason, probably server disconnected */ client_send_line(client, "-ERR [IN-USE] Temporary login failure."); client_destroy(client, NULL); return; } switch (i_stream_read(input)) { case -2: /* buffer full */ i_error("pop-proxy(%s): Remote input buffer full", client->common.virtual_user); client_destroy_internal_failure(client); return; case -1: /* disconnected */ client_destroy(client, "Proxy: Remote disconnected"); return; } line = i_stream_next_line(input); if (line == NULL) return; switch (client->proxy_state) { case 0: /* this is a banner */ if (strncmp(line, "+OK", 3) != 0) { i_error("pop3-proxy(%s): " "Remote returned invalid banner: %s", client->common.virtual_user, line); client_destroy_internal_failure(client); return; } /* send USER command */ str = t_str_new(128); str_append(str, "USER "); str_append(str, client->proxy_user); str_append(str, "\r\n"); (void)o_stream_send(output, str_data(str), str_len(str)); client->proxy_state++; return; case 1: if (strncmp(line, "+OK", 3) != 0) break; /* USER successful, send PASS */ str = t_str_new(128); str_append(str, "PASS "); str_append(str, client->proxy_password); str_append(str, "\r\n"); (void)o_stream_send(output, str_data(str), str_len(str)); safe_memset(client->proxy_password, 0, strlen(client->proxy_password)); i_free(client->proxy_password); client->proxy_password = NULL; client->proxy_state++; return; case 2: if (strncmp(line, "+OK", 3) != 0) break; /* Login successful. Send this line to client. */ (void)o_stream_send_str(client->output, line); (void)o_stream_send(client->output, "\r\n", 2); login_proxy_detach(client->proxy, client->input, client->output); client->proxy = NULL; client->input = NULL; client->output = NULL; client->common.fd = -1; client_destroy(client, t_strdup_printf("proxy(%s): started", client->common.virtual_user)); return; } /* Login failed. Send our own failure reply so client can't figure out if user exists or not just by looking at the reply string. */ client_send_line(client, "-ERR "AUTH_FAILED_MSG); /* allow client input again */ i_assert(client->io == NULL); client->io = io_add(client->common.fd, IO_READ, client_input, client); login_proxy_free(client->proxy); client->proxy = NULL; if (client->proxy_password != NULL) { safe_memset(client->proxy_password, 0, strlen(client->proxy_password)); i_free(client->proxy_password); client->proxy_password = NULL; } i_free(client->proxy_user); client->proxy_user = NULL; } int pop3_proxy_new(struct pop3_client *client, const char *host, unsigned int port, const char *user, const char *password) { i_assert(user != NULL); i_assert(!client->destroyed); if (password == NULL) { i_error("proxy(%s): password not given", client->common.virtual_user); return -1; } i_assert(client->refcount > 1); connection_queue_add(1); if (client->destroyed) { /* connection_queue_add() decided that we were the oldest connection and killed us. */ return -1; } client->proxy = login_proxy_new(&client->common, host, port, proxy_input, client); if (client->proxy == NULL) return -1; client->proxy_state = 0; client->proxy_user = i_strdup(user); client->proxy_password = i_strdup(password); /* disable input until authentication is finished */ if (client->io != NULL) io_remove(&client->io); return 0; }