~ubuntu-branches/ubuntu/trusty/dovecot/trusty-updates

« back to all changes in this revision

Viewing changes to src/login-common/client-common-auth.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-01-08 09:35:49 UTC
  • mfrom: (1.15.3) (96.1.1 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20140108093549-814nkqdcxfbvgktg
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) 2002-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
2
2
 
 
3
#include "hostpid.h"
3
4
#include "login-common.h"
4
5
#include "istream.h"
5
6
#include "ostream.h"
6
7
#include "str.h"
7
8
#include "safe-memset.h"
 
9
#include "time-util.h"
8
10
#include "login-proxy.h"
9
11
#include "auth-client.h"
 
12
#include "dsasl-client.h"
 
13
#include "master-service-ssl-settings.h"
10
14
#include "client-common.h"
11
15
 
12
16
#include <stdlib.h>
13
17
 
14
18
#define PROXY_FAILURE_MSG "Account is temporarily unavailable."
15
 
#define LOGIN_DNS_CLIENT_SOCKET_PATH "dns-client"
 
19
#define PROXY_DEFAULT_TIMEOUT_MSECS (1000*30)
16
20
 
17
21
/* If we've been waiting auth server to respond for over this many milliseconds,
18
22
   send a "waiting" message. */
19
23
#define AUTH_WAITING_TIMEOUT_MSECS (30*1000)
20
 
#define GREETING_WARNING_TIMEOUT_MSECS (10*1000)
 
24
#define AUTH_WAITING_WARNING_TIMEOUT_MSECS (10*1000)
21
25
 
22
 
void client_auth_failed(struct client *client)
 
26
static void client_auth_failed(struct client *client)
23
27
{
24
28
        i_free_and_null(client->master_data_prefix);
25
29
        if (client->auth_response != NULL)
37
41
 
38
42
static void client_auth_waiting_timeout(struct client *client)
39
43
{
40
 
        if (!client->greeting_sent) {
 
44
        if (!client->notified_auth_ready) {
41
45
                client_log_warn(client, "Auth process not responding, "
42
 
                                "delayed sending greeting");
 
46
                                "delayed sending initial response (greeting)");
43
47
        }
44
 
        client_send_line(client, CLIENT_CMD_REPLY_STATUS,
45
 
                         client->master_tag == 0 ?
46
 
                         AUTH_SERVER_WAITING_MSG : AUTH_MASTER_WAITING_MSG);
 
48
        client_notify_status(client, FALSE, client->master_tag == 0 ?
 
49
                             AUTH_SERVER_WAITING_MSG : AUTH_MASTER_WAITING_MSG);
47
50
        timeout_remove(&client->to_auth_waiting);
48
51
}
49
52
 
51
54
{
52
55
        i_assert(client->to_auth_waiting == NULL);
53
56
        client->to_auth_waiting =
54
 
                timeout_add(!client->greeting_sent ?
55
 
                            GREETING_WARNING_TIMEOUT_MSECS :
 
57
                timeout_add(!client->notified_auth_ready ?
 
58
                            AUTH_WAITING_WARNING_TIMEOUT_MSECS :
56
59
                            AUTH_WAITING_TIMEOUT_MSECS,
57
60
                            client_auth_waiting_timeout, client);
58
61
}
102
105
                        reply_r->proxy_timeout_msecs = 1000*atoi(value);
103
106
                else if (strcmp(key, "proxy_refresh") == 0)
104
107
                        reply_r->proxy_refresh_secs = atoi(value);
 
108
                else if (strcmp(key, "proxy_mech") == 0)
 
109
                        reply_r->proxy_mech = value;
105
110
                else if (strcmp(key, "master") == 0)
106
111
                        reply_r->master_user = value;
107
112
                else if (strcmp(key, "ssl") == 0) {
165
170
        client_destroy_success(client, str_c(str));
166
171
}
167
172
 
 
173
static void client_proxy_error(struct client *client, const char *text)
 
174
{
 
175
        client->v.proxy_error(client, text);
 
176
}
 
177
 
168
178
void client_proxy_log_failure(struct client *client, const char *line)
169
179
{
170
180
        string_t *str = t_str_new(128);
188
198
void client_proxy_failed(struct client *client, bool send_line)
189
199
{
190
200
        if (send_line) {
191
 
                client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
192
 
                                 PROXY_FAILURE_MSG);
 
201
                client_proxy_error(client, PROXY_FAILURE_MSG);
193
202
        }
194
203
 
 
204
        if (client->proxy_sasl_client != NULL)
 
205
                dsasl_client_free(&client->proxy_sasl_client);
195
206
        login_proxy_free(&client->login_proxy);
196
207
        proxy_free_password(client);
197
208
        i_free_and_null(client->proxy_user);
211
222
static void proxy_input(struct client *client)
212
223
{
213
224
        struct istream *input;
 
225
        struct ostream *output;
214
226
        const char *line;
215
227
        unsigned int duration;
216
228
 
254
266
                return;
255
267
        }
256
268
 
 
269
        output = client->output;
 
270
        o_stream_ref(output);
 
271
        o_stream_cork(output);
257
272
        while ((line = i_stream_next_line(input)) != NULL) {
258
273
                if (client->v.proxy_parse_line(client, line) != 0)
259
274
                        break;
260
275
        }
 
276
        o_stream_uncork(output);
 
277
        o_stream_unref(&output);
261
278
}
262
279
 
263
280
static int proxy_start(struct client *client,
264
281
                       const struct client_auth_reply *reply)
265
282
{
266
283
        struct login_proxy_settings proxy_set;
 
284
        const struct dsasl_client_mech *sasl_mech = NULL;
267
285
 
268
286
        i_assert(reply->destuser != NULL);
269
287
        i_assert(!client->destroyed);
 
288
        i_assert(client->proxy_sasl_client == NULL);
270
289
 
 
290
        client->proxy_mech = NULL;
271
291
        client->v.proxy_reset(client);
272
292
 
273
293
        if (reply->password == NULL) {
274
294
                client_log_err(client, "proxy: password not given");
275
 
                client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
276
 
                                 PROXY_FAILURE_MSG);
 
295
                client_proxy_error(client, PROXY_FAILURE_MSG);
277
296
                return -1;
278
297
        }
279
298
        if (reply->host == NULL || *reply->host == '\0') {
280
299
                client_log_err(client, "proxy: host not given");
281
 
                client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
282
 
                                 PROXY_FAILURE_MSG);
 
300
                client_proxy_error(client, PROXY_FAILURE_MSG);
283
301
                return -1;
284
302
        }
285
303
 
 
304
        if (reply->proxy_mech != NULL) {
 
305
                sasl_mech = dsasl_client_mech_find(reply->proxy_mech);
 
306
                if (sasl_mech == NULL) {
 
307
                        client_log_err(client, t_strdup_printf(
 
308
                                "proxy: Unsupported SASL mechanism %s",
 
309
                                reply->proxy_mech));
 
310
                        client_proxy_error(client, PROXY_FAILURE_MSG);
 
311
                        return -1;
 
312
                }
 
313
        } else if (reply->master_user != NULL) {
 
314
                /* have to use PLAIN authentication with master user logins */
 
315
                sasl_mech = &dsasl_client_mech_plain;
 
316
        }
 
317
 
286
318
        i_assert(client->refcount > 1);
287
319
 
288
320
        if (client->destroyed) {
293
325
        if (login_proxy_is_ourself(client, reply->host, reply->port,
294
326
                                   reply->destuser)) {
295
327
                client_log_err(client, "Proxying loops to itself");
296
 
                client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
297
 
                                 PROXY_FAILURE_MSG);
 
328
                client_proxy_error(client, PROXY_FAILURE_MSG);
298
329
                return -1;
299
330
        }
300
331
 
304
335
            net_addr2ip(reply->hostip, &proxy_set.ip) < 0)
305
336
                proxy_set.ip.family = 0;
306
337
        proxy_set.port = reply->port;
307
 
        proxy_set.dns_client_socket_path = LOGIN_DNS_CLIENT_SOCKET_PATH;
308
338
        proxy_set.connect_timeout_msecs = reply->proxy_timeout_msecs;
 
339
        if (proxy_set.connect_timeout_msecs == 0)
 
340
                proxy_set.connect_timeout_msecs = PROXY_DEFAULT_TIMEOUT_MSECS;
309
341
        proxy_set.notify_refresh_secs = reply->proxy_refresh_secs;
310
342
        proxy_set.ssl_flags = reply->ssl_flags;
311
343
 
312
344
        if (login_proxy_new(client, &proxy_set, proxy_input) < 0) {
313
 
                client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_TEMP,
314
 
                                 PROXY_FAILURE_MSG);
 
345
                client_proxy_error(client, PROXY_FAILURE_MSG);
315
346
                return -1;
316
347
        }
317
348
 
 
349
        client->proxy_mech = sasl_mech;
318
350
        client->proxy_user = i_strdup(reply->destuser);
319
351
        client->proxy_master_user = i_strdup(reply->master_user);
320
352
        client->proxy_password = i_strdup(reply->password);
325
357
        return 0;
326
358
}
327
359
 
 
360
static void ATTR_NULL(3, 4)
 
361
client_auth_result(struct client *client, enum client_auth_result result,
 
362
                   const struct client_auth_reply *reply, const char *text)
 
363
{
 
364
        o_stream_cork(client->output);
 
365
        client->v.auth_result(client, result, reply, text);
 
366
        o_stream_uncork(client->output);
 
367
}
 
368
 
328
369
static bool
329
370
client_auth_handle_reply(struct client *client,
330
371
                         const struct client_auth_reply *reply, bool success)
341
382
                        client_auth_failed(client);
342
383
                return TRUE;
343
384
        }
344
 
        return client->v.auth_handle_reply(client, reply);
 
385
 
 
386
        if (reply->host != NULL) {
 
387
                const char *reason;
 
388
 
 
389
                if (reply->reason != NULL)
 
390
                        reason = reply->reason;
 
391
                else if (reply->nologin)
 
392
                        reason = "Try this server instead.";
 
393
                else
 
394
                        reason = "Logged in, but you should use this server instead.";
 
395
 
 
396
                if (reply->nologin) {
 
397
                        client_auth_result(client,
 
398
                                CLIENT_AUTH_RESULT_REFERRAL_NOLOGIN,
 
399
                                reply, reason);
 
400
                } else {
 
401
                        client_auth_result(client,
 
402
                                CLIENT_AUTH_RESULT_REFERRAL_SUCCESS,
 
403
                                reply, reason);
 
404
                        return TRUE;
 
405
                }
 
406
        } else if (reply->nologin) {
 
407
                /* Authentication went ok, but for some reason user isn't
 
408
                   allowed to log in. Shouldn't probably happen. */
 
409
                if (reply->reason != NULL) {
 
410
                        client_auth_result(client,
 
411
                                CLIENT_AUTH_RESULT_AUTHFAILED_REASON,
 
412
                                reply, reply->reason);
 
413
                } else if (reply->temp) {
 
414
                        const char *timestamp, *msg;
 
415
 
 
416
                        timestamp = t_strflocaltime("%Y-%m-%d %H:%M:%S", ioloop_time);
 
417
                        msg = t_strdup_printf(AUTH_TEMP_FAILED_MSG" [%s:%s]",
 
418
                                      my_hostname, timestamp);
 
419
                        client_auth_result(client, CLIENT_AUTH_RESULT_TEMPFAIL,
 
420
                                           reply, msg);
 
421
                } else if (reply->authz_failure) {
 
422
                        client_auth_result(client,
 
423
                                CLIENT_AUTH_RESULT_AUTHZFAILED, reply,
 
424
                                "Authorization failed");
 
425
                } else {
 
426
                        client_auth_result(client,
 
427
                                CLIENT_AUTH_RESULT_AUTHFAILED, reply,
 
428
                                AUTH_FAILED_MSG);
 
429
                }
 
430
        } else {
 
431
                /* normal login/failure */
 
432
                return FALSE;
 
433
        }
 
434
 
 
435
        i_assert(reply->nologin);
 
436
 
 
437
        if (!client->destroyed)
 
438
                client_auth_failed(client);
 
439
        return TRUE;
 
440
}
 
441
 
 
442
void client_auth_respond(struct client *client, const char *response)
 
443
{
 
444
        client->auth_waiting = FALSE;
 
445
        client_set_auth_waiting(client);
 
446
        auth_client_request_continue(client->auth_request, response);
 
447
        io_remove(&client->io);
 
448
}
 
449
 
 
450
void client_auth_abort(struct client *client)
 
451
{
 
452
        sasl_server_auth_abort(client);
 
453
}
 
454
 
 
455
void client_auth_fail(struct client *client, const char *text)
 
456
{
 
457
        sasl_server_auth_failed(client, text);
345
458
}
346
459
 
347
460
int client_auth_read_line(struct client *client)
377
490
        return i < size;
378
491
}
379
492
 
380
 
int client_auth_parse_response(struct client *client)
 
493
void client_auth_parse_response(struct client *client)
381
494
{
382
 
        int ret;
383
 
 
384
 
        if ((ret = client_auth_read_line(client)) <= 0)
385
 
                return ret;
 
495
        if (client_auth_read_line(client) <= 0)
 
496
                return;
386
497
 
387
498
        if (strcmp(str_c(client->auth_response), "*") == 0) {
388
499
                sasl_server_auth_abort(client);
389
 
                return -1;
 
500
                return;
390
501
        }
391
 
        return 1;
392
 
}
393
 
 
394
 
static void client_auth_input(struct client *client)
395
 
{
396
 
        if (client->v.auth_parse_response(client) <= 0)
397
 
                return;
398
 
 
399
 
        client->auth_waiting = FALSE;
400
 
        client_set_auth_waiting(client);
401
 
        auth_client_request_continue(client->auth_request,
402
 
                                     str_c(client->auth_response));
403
 
        io_remove(&client->io);
404
 
 
 
502
 
 
503
        client_auth_respond(client, str_c(client->auth_response));
405
504
        memset(str_c_modifiable(client->auth_response), 0,
406
505
               str_len(client->auth_response));
407
506
}
408
507
 
 
508
static void client_auth_input(struct client *client)
 
509
{
 
510
        i_assert(client->v.auth_parse_response != NULL);
 
511
        client->v.auth_parse_response(client);
 
512
}
 
513
 
409
514
void client_auth_send_challenge(struct client *client, const char *data)
410
515
{
411
516
        struct const_iovec iov[3];
417
522
        iov[2].iov_base = "\r\n";
418
523
        iov[2].iov_len = 2;
419
524
 
420
 
        (void)o_stream_sendv(client->output, iov, 3);
 
525
        o_stream_nsendv(client->output, iov, 3);
421
526
}
422
527
 
423
528
static void
439
544
                        if (client_auth_handle_reply(client, &reply, TRUE))
440
545
                                break;
441
546
                }
 
547
                client_auth_result(client, CLIENT_AUTH_RESULT_SUCCESS,
 
548
                                   NULL, NULL);
442
549
                client_destroy_success(client, "Login");
443
550
                break;
444
551
        case SASL_SERVER_REPLY_AUTH_FAILED:
453
560
                }
454
561
 
455
562
                if (sasl_reply == SASL_SERVER_REPLY_AUTH_ABORTED) {
456
 
                        client_send_line(client, CLIENT_CMD_REPLY_BAD,
457
 
                                         "Authentication aborted by client.");
 
563
                        client_auth_result(client, CLIENT_AUTH_RESULT_ABORTED,
 
564
                                NULL, "Authentication aborted by client.");
458
565
                } else if (data == NULL) {
459
 
                        client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAILED,
460
 
                                         AUTH_FAILED_MSG);
 
566
                        client_auth_result(client,
 
567
                                CLIENT_AUTH_RESULT_AUTHFAILED, NULL,
 
568
                                AUTH_FAILED_MSG);
461
569
                } else {
462
 
                        client_send_line(client,
463
 
                                         CLIENT_CMD_REPLY_AUTH_FAIL_REASON,
464
 
                                         data);
 
570
                        client_auth_result(client,
 
571
                                CLIENT_AUTH_RESULT_AUTHFAILED_REASON, NULL,
 
572
                                data);
465
573
                }
466
574
 
467
575
                if (!client->destroyed)
471
579
                if (data != NULL) {
472
580
                        /* authentication itself succeeded, we just hit some
473
581
                           internal failure. */
474
 
                        client_send_line(client,
475
 
                                         CLIENT_CMD_REPLY_AUTH_FAIL_TEMP, data);
 
582
                        client_auth_result(client, CLIENT_AUTH_RESULT_TEMPFAIL,
 
583
                                           NULL, data);
476
584
                }
477
585
 
478
586
                /* the fd may still be hanging somewhere in kernel or another
486
594
                        client_destroy_success(client, data);
487
595
                break;
488
596
        case SASL_SERVER_REPLY_CONTINUE:
 
597
                i_assert(client->v.auth_send_challenge != NULL);
489
598
                client->v.auth_send_challenge(client, data);
490
599
 
491
600
                if (client->to_auth_waiting != NULL)
508
617
int client_auth_begin(struct client *client, const char *mech_name,
509
618
                      const char *init_resp)
510
619
{
511
 
        if (!client->secured && strcmp(client->set->ssl, "required") == 0) {
 
620
        if (!client->secured && strcmp(client->ssl_set->ssl, "required") == 0) {
512
621
                if (client->set->auth_verbose) {
513
622
                        client_log(client, "Login failed: "
514
623
                                   "SSL required for authentication");
515
624
                }
516
625
                client->auth_attempts++;
517
 
                client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_NOSSL,
 
626
                client_auth_result(client, CLIENT_AUTH_RESULT_SSL_REQUIRED, NULL,
518
627
                        "Authentication not allowed until SSL/TLS is enabled.");
519
628
                return 1;
520
629
        }
537
646
 
538
647
bool client_check_plaintext_auth(struct client *client, bool pass_sent)
539
648
{
540
 
        if (client->secured || !client->set->disable_plaintext_auth)
 
649
        if (client->secured || (!client->set->disable_plaintext_auth &&
 
650
                                strcmp(client->ssl_set->ssl, "required") != 0))
541
651
                return TRUE;
542
652
 
543
653
        if (client->set->auth_verbose) {
545
655
                           "Plaintext authentication disabled");
546
656
        }
547
657
        if (pass_sent) {
548
 
                client_send_line(client, CLIENT_CMD_REPLY_STATUS_BAD,
 
658
                client_notify_status(client, TRUE,
549
659
                         "Plaintext authentication not allowed "
550
660
                         "without SSL/TLS, but your client did it anyway. "
551
661
                         "If anyone was listening, the password was exposed.");
552
662
        }
553
 
        client_send_line(client, CLIENT_CMD_REPLY_AUTH_FAIL_NOSSL,
554
 
                         AUTH_PLAINTEXT_DISABLED_MSG);
 
663
        client_auth_result(client, CLIENT_AUTH_RESULT_SSL_REQUIRED, NULL,
 
664
                           AUTH_PLAINTEXT_DISABLED_MSG);
555
665
        client->auth_tried_disabled_plaintext = TRUE;
556
666
        client->auth_attempts++;
557
667
        return FALSE;
566
676
 
567
677
                if (client->to_auth_waiting != NULL)
568
678
                        timeout_remove(&client->to_auth_waiting);
569
 
                if (!client->greeting_sent)
570
 
                        client->v.send_greeting(client);
 
679
 
 
680
                client_notify_auth_ready(client);
 
681
 
571
682
                if (client->input_blocked) {
572
683
                        client->input_blocked = FALSE;
573
684
                        client_input(client);