~ubuntu-branches/ubuntu/wily/dovecot/wily

« back to all changes in this revision

Viewing changes to src/lib-auth/auth-master.c

  • Committer: Package Import Robot
  • Author(s): Jaldhar H. Vyas
  • Date: 2013-09-09 00:57:32 UTC
  • mfrom: (1.13.11)
  • mto: (4.8.5 experimental) (1.16.1)
  • mto: This revision was merged to the branch mainline in revision 97.
  • Revision ID: package-import@ubuntu.com-20130909005732-dn1eell8srqbhh0e
Tags: upstream-2.2.5
ImportĀ upstreamĀ versionĀ 2.2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2005-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "lib-signals.h"
5
5
#include "array.h"
6
6
#include "ioloop.h"
7
7
#include "eacces-error.h"
8
 
#include "network.h"
 
8
#include "net.h"
9
9
#include "istream.h"
10
10
#include "ostream.h"
11
11
#include "str.h"
31
31
        enum auth_master_flags flags;
32
32
 
33
33
        int fd;
34
 
        struct ioloop *ioloop;
 
34
        struct ioloop *ioloop, *prev_ioloop;
35
35
        struct io *io;
36
36
        struct istream *input;
37
37
        struct ostream *output;
61
61
 
62
62
struct auth_master_user_list_ctx {
63
63
        struct auth_master_connection *conn;
64
 
        pool_t pool;
65
 
        ARRAY_TYPE(const_string) users;
66
 
        const char *const *user_strings;
67
 
        unsigned int idx, user_count;
 
64
        string_t *username;
 
65
        bool finished;
68
66
        bool failed;
69
67
};
70
68
 
192
190
                        array_append(&new_args, &args[i], 1);
193
191
                }
194
192
        }
195
 
        (void)array_append_space(&new_args);
 
193
        array_append_zero(&new_args);
196
194
        return array_idx(&new_args, 0);
197
195
}
198
196
 
289
287
 
290
288
        while ((line = i_stream_next_line(conn->input)) != NULL) {
291
289
                T_BEGIN {
 
290
                        io_loop_set_current(conn->prev_ioloop);
292
291
                        ret = auth_handle_line(conn, line);
 
292
                        io_loop_set_current(conn->ioloop);
293
293
                } T_END;
294
294
                if (!ret)
295
295
                        return;
335
335
 
336
336
static void auth_master_set_io(struct auth_master_connection *conn)
337
337
{
 
338
        if (conn->ioloop != NULL)
 
339
                return;
 
340
 
338
341
        if (conn->to != NULL)
339
342
                timeout_remove(&conn->to);
340
343
 
 
344
        conn->prev_ioloop = current_ioloop;
341
345
        conn->ioloop = io_loop_create();
342
346
        conn->input = i_stream_create_fd(conn->fd, MAX_INBUF_SIZE, FALSE);
343
347
        conn->output = o_stream_create_fd(conn->fd, MAX_OUTBUF_SIZE, FALSE);
347
351
        lib_signals_reset_ioloop();
348
352
}
349
353
 
350
 
static void auth_master_unset_io(struct auth_master_connection *conn,
351
 
                                 struct ioloop *prev_ioloop)
 
354
static void auth_master_unset_io(struct auth_master_connection *conn)
352
355
{
353
 
        if (prev_ioloop != NULL) {
354
 
                io_loop_set_current(prev_ioloop);
 
356
        if (conn->prev_ioloop != NULL) {
 
357
                io_loop_set_current(conn->prev_ioloop);
355
358
                lib_signals_reset_ioloop();
356
359
        }
357
 
        io_loop_set_current(conn->ioloop);
 
360
        if (conn->ioloop != NULL) {
 
361
                io_loop_set_current(conn->ioloop);
358
362
 
359
 
        timeout_remove(&conn->to);
360
 
        io_remove(&conn->io);
361
 
        i_stream_unref(&conn->input);
362
 
        o_stream_unref(&conn->output);
363
 
        io_loop_destroy(&conn->ioloop);
 
363
                timeout_remove(&conn->to);
 
364
                io_remove(&conn->io);
 
365
                i_stream_unref(&conn->input);
 
366
                o_stream_unref(&conn->output);
 
367
                io_loop_destroy(&conn->ioloop);
 
368
        }
364
369
 
365
370
        if ((conn->flags & AUTH_MASTER_FLAG_NO_IDLE_TIMEOUT) == 0) {
366
 
                if (prev_ioloop == NULL)
 
371
                if (conn->prev_ioloop == NULL)
367
372
                        auth_connection_close(conn);
368
373
                else {
 
374
                        i_assert(conn->to == NULL);
369
375
                        conn->to = timeout_add(1000*AUTH_MASTER_IDLE_SECS,
370
376
                                               auth_idle_timeout, conn);
371
377
                }
385
391
        return TRUE;
386
392
}
387
393
 
388
 
static int auth_master_run_cmd(struct auth_master_connection *conn,
389
 
                               const char *cmd)
 
394
static int auth_master_run_cmd_pre(struct auth_master_connection *conn,
 
395
                                   const char *cmd)
390
396
{
391
 
        struct ioloop *prev_ioloop;
392
397
        const char *str;
393
398
 
394
399
        if (conn->fd == -1) {
395
400
                if (auth_master_connect(conn) < 0)
396
401
                        return -1;
397
402
        }
398
 
 
399
 
        prev_ioloop = current_ioloop;
400
403
        auth_master_set_io(conn);
401
404
 
402
405
        o_stream_cork(conn->output);
403
406
        if (!conn->sent_handshake) {
404
407
                str = t_strdup_printf("VERSION\t%d\t%d\n",
405
408
                                      AUTH_PROTOCOL_MAJOR, AUTH_PROTOCOL_MINOR);
406
 
                o_stream_send_str(conn->output, str);
 
409
                o_stream_nsend_str(conn->output, str);
407
410
                conn->sent_handshake = TRUE;
408
411
        }
409
412
 
410
 
        o_stream_send_str(conn->output, cmd);
 
413
        o_stream_nsend_str(conn->output, cmd);
411
414
        o_stream_uncork(conn->output);
412
415
 
413
 
        if (conn->output->stream_errno != 0) {
414
 
                errno = conn->output->stream_errno;
 
416
        if (o_stream_nfinish(conn->output) < 0) {
415
417
                i_error("write(auth socket) failed: %m");
416
 
                conn->aborted = TRUE;
417
 
        } else {
418
 
                io_loop_run(conn->ioloop);
 
418
                auth_master_unset_io(conn);
 
419
                auth_connection_close(conn);
 
420
                return -1;
419
421
        }
 
422
        return 0;
 
423
}
420
424
 
421
 
        auth_master_unset_io(conn, prev_ioloop);
 
425
static int auth_master_run_cmd_post(struct auth_master_connection *conn)
 
426
{
 
427
        auth_master_unset_io(conn);
422
428
        if (conn->aborted) {
423
429
                conn->aborted = FALSE;
424
430
                auth_connection_close(conn);
427
433
        return 0;
428
434
}
429
435
 
 
436
static int auth_master_run_cmd(struct auth_master_connection *conn,
 
437
                               const char *cmd)
 
438
{
 
439
        if (auth_master_run_cmd_pre(conn, cmd) < 0)
 
440
                return -1;
 
441
        io_loop_run(conn->ioloop);
 
442
        return auth_master_run_cmd_post(conn);
 
443
}
 
444
 
430
445
static unsigned int
431
446
auth_master_next_request_id(struct auth_master_connection *conn)
432
447
{
524
539
                        reply_r->home = p_strdup(pool, *fields + 5);
525
540
                else if (strncmp(*fields, "chroot=", 7) == 0)
526
541
                        reply_r->chroot = p_strdup(pool, *fields + 7);
 
542
                else if (strcmp(*fields, "anonymous") == 0)
 
543
                        reply_r->anonymous = TRUE;
527
544
                else {
528
545
                        const char *field = p_strdup(pool, *fields);
529
546
                        array_append(&reply_r->extra_fields, &field, 1);
576
593
        unsigned int *countp = context;
577
594
 
578
595
        if (strcmp(cmd, "OK") != 0)
579
 
                *countp = -1U;
 
596
                *countp = UINT_MAX;
580
597
        else if (args[0] == NULL || str_to_uint(args[0], countp) < 0)
581
 
                *countp = -1U;
 
598
                *countp = UINT_MAX;
582
599
 
583
600
        io_loop_stop(current_ioloop);
584
601
        return TRUE;
589
606
{
590
607
        string_t *str;
591
608
 
592
 
        *count_r = -1U;
 
609
        *count_r = UINT_MAX;
593
610
 
594
611
        conn->reply_callback = auth_cache_flush_reply_callback;
595
612
        conn->reply_context = count_r;
599
616
        if (users != NULL) {
600
617
                for (; *users != NULL; users++) {
601
618
                        str_append_c(str, '\t');
602
 
                        str_tabescape_write(str, *users);
 
619
                        str_append_tabescaped(str, *users);
603
620
                }
604
621
        }
605
622
        str_append_c(str, '\n');
608
625
        (void)auth_master_run_cmd(conn, str_c(str));
609
626
        conn->prefix = DEFAULT_USERDB_LOOKUP_PREFIX;
610
627
 
611
 
        return *count_r == -1U ? -1 : 0;
 
628
        return *count_r == UINT_MAX ? -1 : 0;
612
629
}
613
630
 
614
631
static bool
616
633
                              void *context)
617
634
{
618
635
        struct auth_master_user_list_ctx *ctx = context;
619
 
        const char *user;
620
636
 
621
637
        timeout_reset(ctx->conn->to);
 
638
        str_truncate(ctx->username, 0);
 
639
        io_loop_stop(ctx->conn->ioloop);
622
640
 
623
641
        if (strcmp(cmd, "DONE") == 0) {
624
 
                io_loop_stop(ctx->conn->ioloop);
625
642
                if (args[0] != NULL && strcmp(args[0], "fail") == 0) {
626
643
                        i_error("User listing returned failure");
627
644
                        ctx->failed = TRUE;
628
645
                }
629
 
                return TRUE;
630
 
        }
631
 
        if (strcmp(cmd, "LIST") == 0 && args[0] != NULL) {
 
646
                ctx->finished = TRUE;
 
647
        } else if (strcmp(cmd, "LIST") == 0 && args[0] != NULL) {
632
648
                /* we'll just read all the users into memory. otherwise we'd
633
649
                   have to use a separate connection for listing and there's
634
650
                   a higher chance of a failure since the connection could be
635
651
                   open to dovecot-auth for a long time. */
636
 
                user = p_strdup(ctx->pool, args[0]);
637
 
                array_append(&ctx->users, &user, 1);
638
 
                return TRUE;
 
652
                str_append(ctx->username, args[0]);
 
653
        } else {
 
654
                i_error("User listing returned invalid input");
 
655
                ctx->failed = TRUE;
639
656
        }
640
657
        return FALSE;
641
658
}
647
664
{
648
665
        struct auth_master_user_list_ctx *ctx;
649
666
        string_t *str;
650
 
        pool_t pool;
651
667
 
652
 
        pool = pool_alloconly_create("auth master user list", 10240);
653
 
        ctx = p_new(pool, struct auth_master_user_list_ctx, 1);
654
 
        ctx->pool = pool;
 
668
        ctx = i_new(struct auth_master_user_list_ctx, 1);
655
669
        ctx->conn = conn;
656
 
        i_array_init(&ctx->users, 128);
 
670
        ctx->username = str_new(default_pool, 128);
657
671
 
658
672
        conn->reply_callback = auth_user_list_reply_callback;
659
673
        conn->reply_context = ctx;
661
675
        str = t_str_new(128);
662
676
        str_printfa(str, "LIST\t%u",
663
677
                    auth_master_next_request_id(conn));
664
 
        if (user_mask != NULL && *user_mask != '\0')
 
678
        if (*user_mask != '\0')
665
679
                str_printfa(str, "\tuser=%s", user_mask);
666
680
        if (info != NULL)
667
681
                auth_user_info_export(str, info);
668
682
        str_append_c(str, '\n');
669
683
 
670
684
        conn->prefix = "userdb list";
671
 
        if (auth_master_run_cmd(conn, str_c(str)) < 0)
 
685
 
 
686
        if (auth_master_run_cmd_pre(conn, str_c(str)) < 0)
672
687
                ctx->failed = TRUE;
673
 
        ctx->user_strings = array_get(&ctx->users, &ctx->user_count);
 
688
        io_loop_set_current(conn->prev_ioloop);
674
689
        conn->prefix = DEFAULT_USERDB_LOOKUP_PREFIX;
675
690
        return ctx;
676
691
}
677
692
 
678
693
const char *auth_master_user_list_next(struct auth_master_user_list_ctx *ctx)
679
694
{
680
 
        if (ctx->idx == ctx->user_count)
681
 
                return NULL;
682
 
        return ctx->user_strings[ctx->idx++];
683
 
}
684
 
 
685
 
unsigned int auth_master_user_list_count(struct auth_master_user_list_ctx *ctx)
686
 
{
687
 
        return ctx->user_count;
 
695
        const char *line;
 
696
 
 
697
        if (ctx->conn->input == NULL)
 
698
                return NULL;
 
699
 
 
700
        /* try to read already buffered input */
 
701
        line = i_stream_next_line(ctx->conn->input);
 
702
        if (line != NULL) {
 
703
                T_BEGIN {
 
704
                        auth_handle_line(ctx->conn, line);
 
705
                } T_END;
 
706
        } else {
 
707
                /* wait for more data */
 
708
                io_loop_set_current(ctx->conn->ioloop);
 
709
                io_loop_run(ctx->conn->ioloop);
 
710
                io_loop_set_current(ctx->conn->prev_ioloop);
 
711
        }
 
712
 
 
713
        if (ctx->finished || ctx->failed)
 
714
                return NULL;
 
715
        return str_c(ctx->username);
688
716
}
689
717
 
690
718
int auth_master_user_list_deinit(struct auth_master_user_list_ctx **_ctx)
693
721
        int ret = ctx->failed ? -1 : 0;
694
722
 
695
723
        *_ctx = NULL;
696
 
        array_free(&ctx->users);
697
 
        pool_unref(&ctx->pool);
 
724
        auth_master_run_cmd_post(ctx->conn);
 
725
        str_free(&ctx->username);
 
726
        i_free(ctx);
698
727
        return ret;
699
728
}