~james-page/ubuntu/raring/dovecot/autopkgtest

« back to all changes in this revision

Viewing changes to src/lib-ssl-iostream/iostream-openssl-context.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-06-11 11:11:54 UTC
  • mfrom: (1.15.2) (4.1.27 sid)
  • Revision ID: package-import@ubuntu.com-20120611111154-678cwbdj6ktgsv1h
Tags: 1:2.1.7-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/{control,rules}: enable PIE hardening.
  + 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.
  + d/control: Added Pre-Depends: dpkg (>= 1.15.6) to dovecot-dbg to support
    xz compression in Ubuntu.
  + d/control: Demote dovecot-common Recommends: to Suggests: to prevent
    install of extra packages on upgrade.
  + d/patches/dovecot-drac.patch: Updated with version for dovecot >= 2.0.0.
  + d/control: Drop B-D on systemd.
* Dropped changes:
  + d/patches/fix-racey-restart.patch: part of 2.1.x, no longer required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2009-2012 Dovecot authors, see the included COPYING file */
 
2
 
 
3
#include "lib.h"
 
4
#include "safe-memset.h"
 
5
#include "iostream-openssl.h"
 
6
 
 
7
#include <openssl/crypto.h>
 
8
#include <openssl/x509.h>
 
9
#include <openssl/engine.h>
 
10
#include <openssl/pem.h>
 
11
#include <openssl/ssl.h>
 
12
#include <openssl/err.h>
 
13
#include <openssl/rand.h>
 
14
 
 
15
struct ssl_iostream_password_context {
 
16
        const char *password;
 
17
        const char *key_source;
 
18
};
 
19
 
 
20
static bool ssl_global_initialized = FALSE;
 
21
static ENGINE *ssl_iostream_engine;
 
22
int dovecot_ssl_extdata_index;
 
23
 
 
24
static void ssl_iostream_init_global(const struct ssl_iostream_settings *set);
 
25
 
 
26
const char *ssl_iostream_error(void)
 
27
{
 
28
        unsigned long err;
 
29
        char *buf;
 
30
        size_t err_size = 256;
 
31
 
 
32
        err = ERR_get_error();
 
33
        if (err == 0) {
 
34
                if (errno != 0)
 
35
                        return strerror(errno);
 
36
                return "Unknown error";
 
37
        }
 
38
        if (ERR_GET_REASON(err) == ERR_R_MALLOC_FAILURE)
 
39
                i_fatal_status(FATAL_OUTOFMEM, "OpenSSL malloc() failed");
 
40
 
 
41
        buf = t_malloc(err_size);
 
42
        buf[err_size-1] = '\0';
 
43
        ERR_error_string_n(err, buf, err_size-1);
 
44
        return buf;
 
45
}
 
46
 
 
47
const char *ssl_iostream_key_load_error(void)
 
48
{
 
49
       unsigned long err = ERR_peek_error();
 
50
 
 
51
       if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
 
52
           ERR_GET_REASON(err) == X509_R_KEY_VALUES_MISMATCH)
 
53
               return "Key is for a different cert than ssl_cert";
 
54
       else
 
55
               return ssl_iostream_error();
 
56
}
 
57
 
 
58
static RSA *ssl_gen_rsa_key(SSL *ssl ATTR_UNUSED,
 
59
                            int is_export ATTR_UNUSED, int keylength)
 
60
{
 
61
        return RSA_generate_key(keylength, RSA_F4, NULL, NULL);
 
62
}
 
63
 
 
64
static DH *ssl_tmp_dh_callback(SSL *ssl ATTR_UNUSED,
 
65
                               int is_export, int keylength)
 
66
{
 
67
        struct ssl_iostream *ssl_io;
 
68
 
 
69
        ssl_io = SSL_get_ex_data(ssl, dovecot_ssl_extdata_index);
 
70
        /* Well, I'm not exactly sure why the logic in here is this.
 
71
           It's the same as in Postfix, so it can't be too wrong. */
 
72
        if (is_export && keylength == 512 && ssl_io->ctx->dh_512 != NULL)
 
73
                return ssl_io->ctx->dh_512;
 
74
        else
 
75
                return ssl_io->ctx->dh_1024;
 
76
}
 
77
 
 
78
static int
 
79
pem_password_callback(char *buf, int size, int rwflag ATTR_UNUSED,
 
80
                      void *userdata)
 
81
{
 
82
        struct ssl_iostream_password_context *ctx = userdata;
 
83
 
 
84
        if (ctx->password == NULL) {
 
85
                i_error("%s: SSL private key file is password protected, "
 
86
                        "but password isn't given", ctx->key_source);
 
87
                return 0;
 
88
        }
 
89
 
 
90
        if (i_strocpy(buf, userdata, size) < 0) {
 
91
                i_error("%s: SSL private key password is too long",
 
92
                        ctx->key_source);
 
93
                return 0;
 
94
        }
 
95
        return strlen(buf);
 
96
}
 
97
 
 
98
int ssl_iostream_load_key(const struct ssl_iostream_settings *set,
 
99
                          const char *key_source, EVP_PKEY **pkey_r)
 
100
{
 
101
        struct ssl_iostream_password_context ctx;
 
102
        EVP_PKEY *pkey;
 
103
        BIO *bio;
 
104
        char *key;
 
105
 
 
106
        key = t_strdup_noconst(set->key);
 
107
        bio = BIO_new_mem_buf(key, strlen(key));
 
108
        if (bio == NULL) {
 
109
                i_error("BIO_new_mem_buf() failed: %s", ssl_iostream_error());
 
110
                safe_memset(key, 0, strlen(key));
 
111
                return -1;
 
112
        }
 
113
 
 
114
        ctx.password = set->key_password;
 
115
        ctx.key_source = key_source;
 
116
 
 
117
        pkey = PEM_read_bio_PrivateKey(bio, NULL, pem_password_callback, &ctx);
 
118
        if (pkey == NULL) {
 
119
                i_error("%s: Couldn't parse private SSL key: %s",
 
120
                        key_source, ssl_iostream_error());
 
121
        }
 
122
        BIO_free(bio);
 
123
 
 
124
        safe_memset(key, 0, strlen(key));
 
125
        *pkey_r = pkey;
 
126
        return pkey == NULL ? -1 : 0;
 
127
}
 
128
 
 
129
static int
 
130
ssl_iostream_ctx_use_key(struct ssl_iostream_context *ctx,
 
131
                         const struct ssl_iostream_settings *set)
 
132
{
 
133
        EVP_PKEY *pkey;
 
134
        int ret = 0;
 
135
 
 
136
        if (ssl_iostream_load_key(set, ctx->source, &pkey) < 0)
 
137
                return -1;
 
138
        if (!SSL_CTX_use_PrivateKey(ctx->ssl_ctx, pkey)) {
 
139
                i_error("%s: Can't load SSL private key: %s",
 
140
                        ctx->source, ssl_iostream_key_load_error());
 
141
                ret = -1;
 
142
        }
 
143
        EVP_PKEY_free(pkey);
 
144
        return ret;
 
145
}
 
146
 
 
147
static bool is_pem_key(const char *cert)
 
148
{
 
149
        return strstr(cert, "PRIVATE KEY---") != NULL;
 
150
}
 
151
 
 
152
const char *ssl_iostream_get_use_certificate_error(const char *cert)
 
153
{
 
154
        unsigned long err;
 
155
 
 
156
        err = ERR_peek_error();
 
157
        if (ERR_GET_LIB(err) != ERR_LIB_PEM ||
 
158
            ERR_GET_REASON(err) != PEM_R_NO_START_LINE)
 
159
                return ssl_iostream_error();
 
160
        else if (is_pem_key(cert)) {
 
161
                return "The file contains a private key "
 
162
                        "(you've mixed ssl_cert and ssl_key settings)";
 
163
        } else {
 
164
                return "There is no certificate.";
 
165
        }
 
166
}
 
167
 
 
168
static int ssl_ctx_use_certificate_chain(SSL_CTX *ctx, const char *cert)
 
169
{
 
170
        /* mostly just copy&pasted from SSL_CTX_use_certificate_chain_file() */
 
171
        BIO *in;
 
172
        X509 *x;
 
173
        int ret = 0;
 
174
 
 
175
        in = BIO_new_mem_buf(t_strdup_noconst(cert), strlen(cert));
 
176
        if (in == NULL)
 
177
                i_fatal("BIO_new_mem_buf() failed");
 
178
 
 
179
        x = PEM_read_bio_X509(in, NULL, NULL, NULL);
 
180
        if (x == NULL)
 
181
                goto end;
 
182
 
 
183
        ret = SSL_CTX_use_certificate(ctx, x);
 
184
        if (ERR_peek_error() != 0)
 
185
                ret = 0;
 
186
 
 
187
        if (ret != 0) {
 
188
                /* If we could set up our certificate, now proceed to
 
189
                 * the CA certificates.
 
190
                 */
 
191
                X509 *ca;
 
192
                int r;
 
193
                unsigned long err;
 
194
                
 
195
                while ((ca = PEM_read_bio_X509(in,NULL,NULL,NULL)) != NULL) {
 
196
                        r = SSL_CTX_add_extra_chain_cert(ctx, ca);
 
197
                        if (!r) {
 
198
                                X509_free(ca);
 
199
                                ret = 0;
 
200
                                goto end;
 
201
                        }
 
202
                }
 
203
                /* When the while loop ends, it's usually just EOF. */
 
204
                err = ERR_peek_last_error();
 
205
                if (ERR_GET_LIB(err) == ERR_LIB_PEM && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)
 
206
                        ERR_clear_error();
 
207
                else 
 
208
                        ret = 0; /* some real error */
 
209
                }
 
210
 
 
211
end:
 
212
        if (x != NULL) X509_free(x);
 
213
        BIO_free(in);
 
214
        return ret;
 
215
}
 
216
 
 
217
static int load_ca(X509_STORE *store, const char *ca,
 
218
                   STACK_OF(X509_NAME) **xnames_r)
 
219
{
 
220
        /* mostly just copy&pasted from X509_load_cert_crl_file() */
 
221
        STACK_OF(X509_INFO) *inf;
 
222
        STACK_OF(X509_NAME) *xnames;
 
223
        X509_INFO *itmp;
 
224
        X509_NAME *xname;
 
225
        BIO *bio;
 
226
        int i;
 
227
 
 
228
        bio = BIO_new_mem_buf(t_strdup_noconst(ca), strlen(ca));
 
229
        if (bio == NULL)
 
230
                i_fatal("BIO_new_mem_buf() failed");
 
231
        inf = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
 
232
        BIO_free(bio);
 
233
 
 
234
        if (inf == NULL)
 
235
                return -1;
 
236
 
 
237
        xnames = sk_X509_NAME_new_null();
 
238
        if (xnames == NULL)
 
239
                i_fatal("sk_X509_NAME_new_null() failed");
 
240
        for(i = 0; i < sk_X509_INFO_num(inf); i++) {
 
241
                itmp = sk_X509_INFO_value(inf, i);
 
242
                if(itmp->x509) {
 
243
                        X509_STORE_add_cert(store, itmp->x509);
 
244
                        xname = X509_get_subject_name(itmp->x509);
 
245
                        if (xname != NULL)
 
246
                                xname = X509_NAME_dup(xname);
 
247
                        if (xname != NULL)
 
248
                                sk_X509_NAME_push(xnames, xname);
 
249
                }
 
250
                if(itmp->crl)
 
251
                        X509_STORE_add_crl(store, itmp->crl);
 
252
        }
 
253
        sk_X509_INFO_pop_free(inf, X509_INFO_free);
 
254
        *xnames_r = xnames;
 
255
        return 0;
 
256
}
 
257
 
 
258
static int
 
259
ssl_iostream_ctx_verify_remote_cert(struct ssl_iostream_context *ctx,
 
260
                                    STACK_OF(X509_NAME) *ca_names)
 
261
{
 
262
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
 
263
        X509_STORE *store;
 
264
 
 
265
        store = SSL_CTX_get_cert_store(ctx->ssl_ctx);
 
266
        X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK |
 
267
                             X509_V_FLAG_CRL_CHECK_ALL);
 
268
#endif
 
269
 
 
270
        SSL_CTX_set_client_CA_list(ctx->ssl_ctx, ca_names);
 
271
        return 0;
 
272
}
 
273
 
 
274
static struct ssl_iostream_settings *
 
275
ssl_iostream_settings_dup(pool_t pool,
 
276
                          const struct ssl_iostream_settings *old_set)
 
277
{
 
278
        struct ssl_iostream_settings *new_set;
 
279
 
 
280
        new_set = p_new(pool, struct ssl_iostream_settings, 1);
 
281
        new_set->cipher_list = p_strdup(pool, old_set->cipher_list);
 
282
        new_set->cert = p_strdup(pool, old_set->cert);
 
283
        new_set->key = p_strdup(pool, old_set->key);
 
284
        new_set->key_password = p_strdup(pool, old_set->key_password);
 
285
 
 
286
        new_set->verbose = old_set->verbose;
 
287
        return new_set;
 
288
}
 
289
 
 
290
static int
 
291
ssl_iostream_context_set(struct ssl_iostream_context *ctx,
 
292
                         const struct ssl_iostream_settings *set)
 
293
{
 
294
        X509_STORE *store;
 
295
        STACK_OF(X509_NAME) *xnames = NULL;
 
296
 
 
297
        ctx->set = ssl_iostream_settings_dup(ctx->pool, set);
 
298
        if (set->cipher_list != NULL &&
 
299
            !SSL_CTX_set_cipher_list(ctx->ssl_ctx, set->cipher_list)) {
 
300
                i_error("%s: Can't set cipher list to '%s': %s",
 
301
                        ctx->source, set->cipher_list,
 
302
                        ssl_iostream_error());
 
303
                return -1;
 
304
        }
 
305
 
 
306
        if (set->cert != NULL &&
 
307
            ssl_ctx_use_certificate_chain(ctx->ssl_ctx, set->cert) < 0) {
 
308
                i_error("%s: Can't load SSL certificate: %s", ctx->source,
 
309
                        ssl_iostream_get_use_certificate_error(set->cert));
 
310
        }
 
311
        if (set->key != NULL) {
 
312
                if (ssl_iostream_ctx_use_key(ctx, set) < 0)
 
313
                        return -1;
 
314
        }
 
315
 
 
316
        /* set trusted CA certs */
 
317
        if (!set->verify_remote_cert) {
 
318
                /* no CA */
 
319
        } else if (set->ca != NULL) {
 
320
                store = SSL_CTX_get_cert_store(ctx->ssl_ctx);
 
321
                if (load_ca(store, set->ca, &xnames) < 0) {
 
322
                        i_error("%s: Couldn't parse ssl_ca: %s", ctx->source,
 
323
                                ssl_iostream_error());
 
324
                        return -1;
 
325
                }
 
326
                if (ssl_iostream_ctx_verify_remote_cert(ctx, xnames) < 0)
 
327
                        return -1;
 
328
        } else if (set->ca_dir != NULL) {
 
329
                if (!SSL_CTX_load_verify_locations(ctx->ssl_ctx, NULL,
 
330
                                                   set->ca_dir)) {
 
331
                        i_error("%s: Can't load CA certs from directory %s: %s",
 
332
                                ctx->source, set->ca_dir, ssl_iostream_error());
 
333
                        return -1;
 
334
                }
 
335
        } else {
 
336
                i_error("%s: Can't verify remote certs without CA",
 
337
                        ctx->source);
 
338
                return -1;
 
339
        }
 
340
 
 
341
        if (set->cert_username_field != NULL) {
 
342
                ctx->username_nid = OBJ_txt2nid(set->cert_username_field);
 
343
                if (ctx->username_nid == NID_undef) {
 
344
                        i_error("%s: Invalid cert_username_field: %s",
 
345
                                ctx->source, set->cert_username_field);
 
346
                }
 
347
        }
 
348
        return 0;
 
349
}
 
350
 
 
351
static int
 
352
ssl_iostream_context_init_common(struct ssl_iostream_context *ctx,
 
353
                                 const char *source,
 
354
                                 const struct ssl_iostream_settings *set)
 
355
{
 
356
        ctx->pool = pool_alloconly_create("ssl iostream context", 4096);
 
357
        ctx->source = p_strdup(ctx->pool, source);
 
358
 
 
359
        /* enable all SSL workarounds, except empty fragments as it
 
360
           makes SSL more vulnerable against attacks */
 
361
        SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_NO_SSLv2 |
 
362
                            (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS));
 
363
        if (SSL_CTX_need_tmp_RSA(ctx->ssl_ctx))
 
364
                SSL_CTX_set_tmp_rsa_callback(ctx->ssl_ctx, ssl_gen_rsa_key);
 
365
        SSL_CTX_set_tmp_dh_callback(ctx->ssl_ctx, ssl_tmp_dh_callback);
 
366
 
 
367
        return ssl_iostream_context_set(ctx, set);
 
368
}
 
369
 
 
370
int ssl_iostream_context_init_client(const char *source,
 
371
                                     const struct ssl_iostream_settings *set,
 
372
                                     struct ssl_iostream_context **ctx_r)
 
373
{
 
374
        struct ssl_iostream_context *ctx;
 
375
        SSL_CTX *ssl_ctx;
 
376
 
 
377
        ssl_iostream_init_global(set);
 
378
        if ((ssl_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL) {
 
379
                i_error("SSL_CTX_new() failed: %s", ssl_iostream_error());
 
380
                return -1;
 
381
        }
 
382
 
 
383
        ctx = i_new(struct ssl_iostream_context, 1);
 
384
        ctx->ssl_ctx = ssl_ctx;
 
385
        ctx->client_ctx = TRUE;
 
386
        if (ssl_iostream_context_init_common(ctx, source, set) < 0) {
 
387
                ssl_iostream_context_deinit(&ctx);
 
388
                return -1;
 
389
        }
 
390
        *ctx_r = ctx;
 
391
        return 0;
 
392
}
 
393
 
 
394
int ssl_iostream_context_init_server(const char *source,
 
395
                                     const struct ssl_iostream_settings *set,
 
396
                                     struct ssl_iostream_context **ctx_r)
 
397
{
 
398
        struct ssl_iostream_context *ctx;
 
399
        SSL_CTX *ssl_ctx;
 
400
 
 
401
        ssl_iostream_init_global(set);
 
402
        if ((ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
 
403
                i_error("SSL_CTX_new() failed: %s", ssl_iostream_error());
 
404
                return -1;
 
405
        }
 
406
 
 
407
        ctx = i_new(struct ssl_iostream_context, 1);
 
408
        ctx->ssl_ctx = ssl_ctx;
 
409
        if (ssl_iostream_context_init_common(ctx, source, set) < 0) {
 
410
                ssl_iostream_context_deinit(&ctx);
 
411
                return -1;
 
412
        }
 
413
        *ctx_r = ctx;
 
414
        return 0;
 
415
}
 
416
 
 
417
void ssl_iostream_context_deinit(struct ssl_iostream_context **_ctx)
 
418
{
 
419
        struct ssl_iostream_context *ctx = *_ctx;
 
420
 
 
421
        *_ctx = NULL;
 
422
        SSL_CTX_free(ctx->ssl_ctx);
 
423
        ssl_iostream_context_free_params(ctx);
 
424
        pool_unref(&ctx->pool);
 
425
        i_free(ctx);
 
426
}
 
427
 
 
428
static void ssl_iostream_deinit_global(void)
 
429
{
 
430
        if (ssl_iostream_engine != NULL)
 
431
                ENGINE_finish(ssl_iostream_engine);
 
432
        ENGINE_cleanup();
 
433
        EVP_cleanup();
 
434
        ERR_free_strings();
 
435
}
 
436
 
 
437
static void ssl_iostream_init_global(const struct ssl_iostream_settings *set)
 
438
{
 
439
        static char dovecot[] = "dovecot";
 
440
        unsigned char buf;
 
441
 
 
442
        if (ssl_global_initialized)
 
443
                return;
 
444
 
 
445
        atexit(ssl_iostream_deinit_global);
 
446
        ssl_global_initialized = TRUE;
 
447
        SSL_library_init();
 
448
        SSL_load_error_strings();
 
449
        OpenSSL_add_all_algorithms();
 
450
 
 
451
        dovecot_ssl_extdata_index =
 
452
                SSL_get_ex_new_index(0, dovecot, NULL, NULL, NULL);
 
453
 
 
454
        /* PRNG initialization might want to use /dev/urandom, make sure it
 
455
           does it before chrooting. We might not have enough entropy at
 
456
           the first try, so this function may fail. It's still been
 
457
           initialized though. */
 
458
        (void)RAND_bytes(&buf, 1);
 
459
 
 
460
        if (set->crypto_device != NULL && *set->crypto_device != '\0') {
 
461
                ENGINE_load_builtin_engines();
 
462
                ssl_iostream_engine = ENGINE_by_id(set->crypto_device);
 
463
                if (ssl_iostream_engine == NULL) {
 
464
                        i_error("Unknown ssl_crypto_device: %s",
 
465
                                set->crypto_device);
 
466
                } else {
 
467
                        ENGINE_init(ssl_iostream_engine);
 
468
                        ENGINE_set_default_RSA(ssl_iostream_engine);
 
469
                        ENGINE_set_default_DSA(ssl_iostream_engine);
 
470
                        ENGINE_set_default_ciphers(ssl_iostream_engine);
 
471
                }
 
472
        }
 
473
}