~ubuntu-branches/ubuntu/utopic/dovecot/utopic-proposed

« back to all changes in this revision

Viewing changes to src/pop3-login/pop3-proxy.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (4.1.35 sid)
  • Revision ID: package-import@ubuntu.com-20140108093549-i72o93pux8p0dlaf
Tags: 1:2.2.9-1ubuntu1
* Merge from Debian unstable, remaining changes:
  + Add mail-stack-delivery package:
    - Update d/rules
    - d/control: convert existing dovecot-postfix package to a dummy
      package and add new mail-stack-delivery package.
    - Update maintainer scripts.
    - Rename d/dovecot-postfix.* to debian/mail-stack-delivery.*
    - d/mail-stack-delivery.preinst: Move previously installed backups and
      config files to a new package namespace.
    - d/mail-stack-delivery.prerm: Added to handle downgrades.
  + Use Snakeoil SSL certificates by default:
    - d/control: Depend on ssl-cert.
    - d/dovecot-core.postinst: Relax grep for SSL_* a bit.
  + Add autopkgtest to debian/tests/*.
  + Add ufw integration:
    - d/dovecot-core.ufw.profile: new ufw profile.
    - d/rules: install profile in dovecot-core.
    - d/control: dovecot-core - suggest ufw.
  + d/dovecot-core.dirs: Added usr/share/doc/dovecot-core
  + Add apport hook:
    - d/rules, d/source_dovecot.py
  + Add upstart job:
    - d/rules, d/dovecot-core.dovecot.upstart, d/control,
      d/dovecot-core.dirs, dovecot-imapd.{postrm, postinst, prerm},
      d/dovecot-pop3d.{postinst, postrm, prerm}.
      d/mail-stack-deliver.postinst: Convert init script to upstart.
  + Use the autotools-dev dh addon to update config.guess/config.sub for
    arm64.
* Dropped changes, included in Debian:
  - Update Dovecot name to reflect distribution in login greeting.
  - Update Drac plugin for >= 2.0.0 support.
* d/control: Drop dovecot-postfix package as its no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2004-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2004-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "login-common.h"
4
4
#include "ioloop.h"
8
8
#include "safe-memset.h"
9
9
#include "str.h"
10
10
#include "str-sanitize.h"
 
11
#include "dsasl-client.h"
11
12
#include "client.h"
12
13
#include "pop3-proxy.h"
13
14
 
20
21
        i_free_and_null(client->proxy_password);
21
22
}
22
23
 
23
 
static void get_plain_auth(struct client *client, string_t *dest)
24
 
{
25
 
        string_t *str;
26
 
 
27
 
        str = t_str_new(128);
28
 
        str_append(str, client->proxy_user);
29
 
        str_append_c(str, '\0');
30
 
        str_append(str, client->proxy_master_user);
31
 
        str_append_c(str, '\0');
32
 
        str_append(str, client->proxy_password);
33
 
        base64_encode(str_data(str), str_len(str), dest);
34
 
}
35
 
 
36
 
static void proxy_send_login(struct pop3_client *client, struct ostream *output)
37
 
{
38
 
        string_t *str;
39
 
 
 
24
static int proxy_send_login(struct pop3_client *client, struct ostream *output)
 
25
{
 
26
        struct dsasl_client_settings sasl_set;
 
27
        const unsigned char *sasl_output;
 
28
        unsigned int len;
 
29
        const char *mech_name, *error;
 
30
        string_t *str;
 
31
 
 
32
        i_assert(client->common.proxy_ttl > 1);
40
33
        if (client->proxy_xclient) {
41
34
                /* remote supports XCLIENT, send it */
42
 
                (void)o_stream_send_str(output, t_strdup_printf(
43
 
                        "XCLIENT ADDR=%s PORT=%u SESSION=%s\r\n",
 
35
                o_stream_nsend_str(output, t_strdup_printf(
 
36
                        "XCLIENT ADDR=%s PORT=%u SESSION=%s TTL=%u\r\n",
44
37
                        net_ip2addr(&client->common.ip),
45
38
                        client->common.remote_port,
46
 
                        client_get_session_id(&client->common)));
 
39
                        client_get_session_id(&client->common),
 
40
                        client->common.proxy_ttl - 1));
47
41
                client->common.proxy_state = POP3_PROXY_XCLIENT;
48
42
        } else {
49
43
                client->common.proxy_state = POP3_PROXY_LOGIN1;
50
44
        }
51
45
 
52
46
        str = t_str_new(128);
53
 
        if (client->common.proxy_master_user == NULL) {
 
47
        if (client->common.proxy_mech == NULL) {
54
48
                /* send USER command */
55
49
                str_append(str, "USER ");
56
50
                str_append(str, client->common.proxy_user);
57
51
                str_append(str, "\r\n");
58
 
        } else {
59
 
                /* master user login - use AUTH PLAIN. */
60
 
                str_append(str, "AUTH PLAIN\r\n");
61
 
        }
62
 
        (void)o_stream_send(output, str_data(str), str_len(str));
 
52
                o_stream_nsend(output, str_data(str), str_len(str));
 
53
                return 0;
 
54
        }
 
55
 
 
56
        i_assert(client->common.proxy_sasl_client == NULL);
 
57
        memset(&sasl_set, 0, sizeof(sasl_set));
 
58
        sasl_set.authid = client->common.proxy_master_user != NULL ?
 
59
                client->common.proxy_master_user : client->common.proxy_user;
 
60
        sasl_set.authzid = client->common.proxy_user;
 
61
        sasl_set.password = client->common.proxy_password;
 
62
        client->common.proxy_sasl_client =
 
63
                dsasl_client_new(client->common.proxy_mech, &sasl_set);
 
64
        mech_name = dsasl_client_mech_get_name(client->common.proxy_mech);
 
65
 
 
66
        str_printfa(str, "AUTH %s ", mech_name);
 
67
        if (dsasl_client_output(client->common.proxy_sasl_client,
 
68
                                &sasl_output, &len, &error) < 0) {
 
69
                client_log_err(&client->common, t_strdup_printf(
 
70
                        "proxy: SASL mechanism %s init failed: %s",
 
71
                        mech_name, error));
 
72
                return -1;
 
73
        }
 
74
        if (len == 0)
 
75
                str_append_c(str, '=');
 
76
        else
 
77
                base64_encode(sasl_output, len, str);
 
78
        str_append(str, "\r\n");
 
79
        o_stream_nsend(output, str_data(str), str_len(str));
 
80
 
 
81
        proxy_free_password(&client->common);
 
82
        if (client->common.proxy_state != POP3_PROXY_XCLIENT)
 
83
                client->common.proxy_state = POP3_PROXY_LOGIN2;
 
84
        return 0;
 
85
}
 
86
 
 
87
static int
 
88
pop3_proxy_continue_sasl_auth(struct client *client, struct ostream *output,
 
89
                              const char *line)
 
90
{
 
91
        string_t *str;
 
92
        const unsigned char *data;
 
93
        unsigned int data_len;
 
94
        const char *error;
 
95
        int ret;
 
96
 
 
97
        str = t_str_new(128);
 
98
        if (base64_decode(line, strlen(line), NULL, str) < 0) {
 
99
                client_log_err(client, "proxy: Server sent invalid base64 data in AUTH response");
 
100
                return -1;
 
101
        }
 
102
        ret = dsasl_client_input(client->proxy_sasl_client,
 
103
                                 str_data(str), str_len(str), &error);
 
104
        if (ret == 0) {
 
105
                ret = dsasl_client_output(client->proxy_sasl_client,
 
106
                                          &data, &data_len, &error);
 
107
        }
 
108
        if (ret < 0) {
 
109
                client_log_err(client, t_strdup_printf(
 
110
                        "proxy: Server sent invalid authentication data: %s",
 
111
                        error));
 
112
                return -1;
 
113
        }
 
114
        i_assert(ret == 0);
 
115
 
 
116
        str_truncate(str, 0);
 
117
        base64_encode(data, data_len, str);
 
118
        str_append(str, "\r\n");
 
119
 
 
120
        o_stream_nsend(output, str_data(str), str_len(str));
 
121
        return 0;
63
122
}
64
123
 
65
124
int pop3_proxy_parse_line(struct client *client, const char *line)
67
126
        struct pop3_client *pop3_client = (struct pop3_client *)client;
68
127
        struct ostream *output;
69
128
        enum login_proxy_ssl_flags ssl_flags;
70
 
        string_t *str;
71
129
 
72
130
        i_assert(!client->destroyed);
73
131
 
87
145
 
88
146
                ssl_flags = login_proxy_get_ssl_flags(client->login_proxy);
89
147
                if ((ssl_flags & PROXY_SSL_FLAG_STARTTLS) == 0) {
90
 
                        proxy_send_login(pop3_client, output);
 
148
                        if (proxy_send_login(pop3_client, output) < 0) {
 
149
                                client_proxy_failed(client, TRUE);
 
150
                                return -1;
 
151
                        }
91
152
                } else {
92
 
                        (void)o_stream_send_str(output, "STLS\r\n");
 
153
                        o_stream_nsend_str(output, "STLS\r\n");
93
154
                        client->proxy_state = POP3_PROXY_STARTTLS;
94
155
                }
95
156
                return 0;
107
168
                }
108
169
                /* i/ostreams changed. */
109
170
                output = login_proxy_get_ostream(client->login_proxy);
110
 
                proxy_send_login(pop3_client, output);
 
171
                if (proxy_send_login(pop3_client, output) < 0) {
 
172
                        client_proxy_failed(client, TRUE);
 
173
                        return -1;
 
174
                }
111
175
                return 1;
112
176
        case POP3_PROXY_XCLIENT:
113
177
                if (strncmp(line, "+OK", 3) != 0) {
117
181
                        client_proxy_failed(client, TRUE);
118
182
                        return -1;
119
183
                }
120
 
                client->proxy_state = POP3_PROXY_LOGIN1;
 
184
                client->proxy_state = client->proxy_sasl_client == NULL ?
 
185
                        POP3_PROXY_LOGIN1 : POP3_PROXY_LOGIN2;
121
186
                return 0;
122
187
        case POP3_PROXY_LOGIN1:
123
 
                str = t_str_new(128);
124
 
                if (client->proxy_master_user == NULL) {
125
 
                        if (strncmp(line, "+OK", 3) != 0)
126
 
                                break;
 
188
                i_assert(client->proxy_sasl_client == NULL);
 
189
                if (strncmp(line, "+OK", 3) != 0)
 
190
                        break;
127
191
 
128
 
                        /* USER successful, send PASS */
129
 
                        str_append(str, "PASS ");
130
 
                        str_append(str, client->proxy_password);
131
 
                        str_append(str, "\r\n");
132
 
                } else {
133
 
                        if (*line != '+')
134
 
                                break;
135
 
                        /* AUTH successful, send the authentication data */
136
 
                        get_plain_auth(client, str);
137
 
                        str_append(str, "\r\n");
138
 
                }
139
 
                (void)o_stream_send(output, str_data(str), str_len(str));
 
192
                /* USER successful, send PASS */
 
193
                o_stream_nsend_str(output, t_strdup_printf(
 
194
                        "PASS %s\r\n", client->proxy_password));
140
195
                proxy_free_password(client);
141
196
                client->proxy_state = POP3_PROXY_LOGIN2;
142
197
                return 0;
143
198
        case POP3_PROXY_LOGIN2:
 
199
                if (strncmp(line, "+ ", 2) == 0 &&
 
200
                    client->proxy_sasl_client != NULL) {
 
201
                        /* continue SASL authentication */
 
202
                        if (pop3_proxy_continue_sasl_auth(client, output,
 
203
                                                          line+2) < 0) {
 
204
                                client_proxy_failed(client, TRUE);
 
205
                                return -1;
 
206
                        }
 
207
                        return 0;
 
208
                }
144
209
                if (strncmp(line, "+OK", 3) != 0)
145
210
                        break;
146
211
 
147
212
                /* Login successful. Send this line to client. */
148
213
                line = t_strconcat(line, "\r\n", NULL);
149
 
                (void)o_stream_send_str(client->output, line);
 
214
                o_stream_nsend_str(client->output, line);
150
215
 
151
216
                client_proxy_finish_destroy_client(client);
152
217
                return 1;
168
233
           shouldn't be a real problem since of course everyone will
169
234
           be using only Dovecot as their backend :) */
170
235
        if (strncmp(line, "-ERR ", 5) != 0) {
171
 
                client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAILED,
172
 
                                 AUTH_FAILED_MSG);
 
236
                client_send_reply(client, POP3_CMD_REPLY_ERROR,
 
237
                                  AUTH_FAILED_MSG);
173
238
        } else {
174
239
                client_send_raw(client, t_strconcat(line, "\r\n", NULL));
175
240
        }
188
253
{
189
254
        client->proxy_state = POP3_PROXY_BANNER;
190
255
}
 
256
 
 
257
void pop3_proxy_error(struct client *client, const char *text)
 
258
{
 
259
        client_send_reply(client, POP3_CMD_REPLY_ERROR, text);
 
260
}