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

« back to all changes in this revision

Viewing changes to src/lib-master/master-service-ssl.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) 2013 Dovecot authors, see the included COPYING file */
 
2
 
 
3
#include "lib.h"
 
4
#include "ioloop.h"
 
5
#include "buffer.h"
 
6
#include "iostream-ssl.h"
 
7
#include "master-service-private.h"
 
8
#include "master-service-settings.h"
 
9
#include "master-service-ssl-settings.h"
 
10
#include "master-service-ssl.h"
 
11
 
 
12
#include <unistd.h>
 
13
 
 
14
/* Check every 30 minutes if parameters file has been updated */
 
15
#define SSL_PARAMS_CHECK_INTERVAL (60*30)
 
16
 
 
17
#define SSL_PARAMETERS_PATH "ssl-params"
 
18
 
 
19
static int ssl_refresh_parameters(struct master_service *service)
 
20
{
 
21
#define BUF_APPEND_SIZE 1024
 
22
        const char *path;
 
23
        buffer_t *buf;
 
24
        void *data;
 
25
        ssize_t ret;
 
26
        int fd;
 
27
 
 
28
        if (ioloop_time == 0 ||
 
29
            service->ssl_params_last_refresh > ioloop_time - SSL_PARAMS_CHECK_INTERVAL)
 
30
                return 0;
 
31
        service->ssl_params_last_refresh = ioloop_time;
 
32
 
 
33
        path = t_strdup_printf("%s/"SSL_PARAMETERS_PATH, service->set->base_dir);
 
34
        fd = net_connect_unix(path);
 
35
        if (fd == -1) {
 
36
                i_error("connect(%s) failed: %m", path);
 
37
                return -1;
 
38
        }
 
39
        net_set_nonblock(fd, FALSE);
 
40
 
 
41
        buf = buffer_create_dynamic(default_pool, BUF_APPEND_SIZE*2);
 
42
        for (;;) {
 
43
                data = buffer_append_space_unsafe(buf, BUF_APPEND_SIZE);
 
44
                ret = read(fd, data, BUF_APPEND_SIZE);
 
45
                buffer_set_used_size(buf, buf->used - BUF_APPEND_SIZE +
 
46
                                     (ret < 0 ? 0 : ret));
 
47
                if (ret <= 0)
 
48
                        break;
 
49
        }
 
50
        if (ret < 0)
 
51
                i_error("read(%s) failed: %m", path);
 
52
        else if (ssl_iostream_context_import_params(service->ssl_ctx, buf) < 0) {
 
53
                i_error("Corrupted SSL parameters file in state_dir: "
 
54
                        "ssl-parameters.dat - disabling SSL %u", (int)buf->used);
 
55
                ret = -1;
 
56
        }
 
57
        i_close_fd(&fd);
 
58
        buffer_free(&buf);
 
59
        return ret < 0 ? -1 : 0;
 
60
}
 
61
 
 
62
int master_service_ssl_init(struct master_service *service,
 
63
                            struct istream **input, struct ostream **output,
 
64
                            struct ssl_iostream **ssl_iostream_r,
 
65
                            const char **error_r)
 
66
{
 
67
        const struct master_service_ssl_settings *set;
 
68
        struct ssl_iostream_settings ssl_set;
 
69
 
 
70
        i_assert(service->ssl_ctx_initialized);
 
71
 
 
72
        if (service->ssl_ctx == NULL) {
 
73
                *error_r = "Failed to initialize SSL context";
 
74
                return -1;
 
75
        }
 
76
 
 
77
        (void)ssl_refresh_parameters(service);
 
78
 
 
79
        set = master_service_ssl_settings_get(service);
 
80
 
 
81
        memset(&ssl_set, 0, sizeof(ssl_set));
 
82
        ssl_set.verbose = set->verbose_ssl;
 
83
        ssl_set.verify_remote_cert = set->ssl_verify_client_cert;
 
84
 
 
85
        return io_stream_create_ssl_server(service->ssl_ctx, &ssl_set,
 
86
                                           input, output, ssl_iostream_r, error_r);
 
87
}
 
88
 
 
89
bool master_service_ssl_is_enabled(struct master_service *service)
 
90
{
 
91
        return service->ssl_ctx != NULL;
 
92
}
 
93
 
 
94
void master_service_ssl_ctx_init(struct master_service *service)
 
95
{
 
96
        const struct master_service_ssl_settings *set;
 
97
        struct ssl_iostream_settings ssl_set;
 
98
        const char *error;
 
99
 
 
100
        if (service->ssl_ctx_initialized)
 
101
                return;
 
102
        service->ssl_ctx_initialized = TRUE;
 
103
 
 
104
        /* must be called after master_service_init_finish() so that if
 
105
           initialization fails we can close the SSL listeners */
 
106
        i_assert(service->listeners != NULL || service->socket_count == 0);
 
107
 
 
108
        set = master_service_ssl_settings_get(service);
 
109
 
 
110
        memset(&ssl_set, 0, sizeof(ssl_set));
 
111
        ssl_set.protocols = set->ssl_protocols;
 
112
        ssl_set.cipher_list = set->ssl_cipher_list;
 
113
        ssl_set.ca = set->ssl_ca;
 
114
        ssl_set.cert = set->ssl_cert;
 
115
        ssl_set.key = set->ssl_key;
 
116
        ssl_set.key_password = set->ssl_key_password;
 
117
        ssl_set.cert_username_field = set->ssl_cert_username_field;
 
118
        ssl_set.crypto_device = set->ssl_crypto_device;
 
119
 
 
120
        ssl_set.verbose = set->verbose_ssl;
 
121
        ssl_set.verify_remote_cert = set->ssl_verify_client_cert;
 
122
 
 
123
        if (ssl_iostream_context_init_server(&ssl_set, &service->ssl_ctx,
 
124
                                             &error) < 0) {
 
125
                i_error("SSL context initialization failed, disabling SSL: %s",
 
126
                        error);
 
127
                master_service_ssl_io_listeners_remove(service);
 
128
                return;
 
129
        }
 
130
        if (ssl_refresh_parameters(service) < 0) {
 
131
                i_error("Couldn't initialize SSL parameters, disabling SSL");
 
132
                ssl_iostream_context_deinit(&service->ssl_ctx);
 
133
                master_service_ssl_io_listeners_remove(service);
 
134
                return;
 
135
        }
 
136
}
 
137
 
 
138
void master_service_ssl_ctx_deinit(struct master_service *service)
 
139
{
 
140
        if (service->ssl_ctx != NULL)
 
141
                ssl_iostream_context_deinit(&service->ssl_ctx);
 
142
        service->ssl_ctx_initialized = FALSE;
 
143
}