~ubuntu-branches/ubuntu/precise/sitecopy/precise

« back to all changes in this revision

Viewing changes to lib/neon/ne_gnutls.c

  • Committer: Bazaar Package Importer
  • Author(s): Sandro Tosi
  • Date: 2008-07-22 07:31:05 UTC
  • mfrom: (1.1.4 upstream) (4.1.7 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080722073105-cbqs1hnc2wvqejfd
Tags: 1:0.16.6-1
* New upstream release
  - fix a crash with progress bar enabled; Closes: #486378
* debian/control
  - set myself as maintainer, Kartik as uploader
  - set Vcs-{Browser,Git} fields
  - bump Standards-Version to 3.8.0
    + debian/README.source added
  - added DM-Upload-Allowed flag
* debian/patches/05_libneon27_transition.dpatch
  - removed since merged upstream
* debian/copyrightdebian/copyright
  - updated upstream email and copyright years
* debian/patches/10_bts410703_preserve_storage_files_sigint.dpatch
  - added to preserve storage files if SIGINT (Ctrl+C) is sent to sitecopy;
    thanks to Andreas Henriksson for the patch; Closes: #410703

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
   neon SSL/TLS support using GNU TLS
3
 
   Copyright (C) 2002-2006, Joe Orton <joe@manyfish.co.uk>
 
3
   Copyright (C) 2002-2008, Joe Orton <joe@manyfish.co.uk>
4
4
   Copyright (C) 2004, Aleix Conchillo Flaque <aleix@member.fsf.org>
5
5
 
6
6
   This library is free software; you can redistribute it and/or
17
17
   License along with this library; if not, write to the Free
18
18
   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19
19
   MA 02111-1307, USA
20
 
 
21
20
*/
22
21
 
23
22
#include "config.h"
24
23
 
25
 
#include <sys/mman.h>
26
 
#include <sys/stat.h>
27
24
#include <sys/types.h>
28
25
 
29
26
#ifdef HAVE_STRING_H
33
30
#include <stdio.h>
34
31
#include <unistd.h>
35
32
#include <stdlib.h>
 
33
#include <errno.h>
36
34
 
37
35
#include <gnutls/gnutls.h>
38
36
#include <gnutls/pkcs12.h>
42
40
#include <pthread.h>
43
41
#include <gcrypt.h>
44
42
GCRY_THREAD_OPTION_PTHREAD_IMPL;
 
43
#else
 
44
#include <gcrypt.h>
 
45
#endif
 
46
 
 
47
#ifdef HAVE_ICONV
 
48
#include <iconv.h>
45
49
#endif
46
50
 
47
51
#include "ne_ssl.h"
67
71
struct ne_ssl_client_cert_s {
68
72
    gnutls_pkcs12 p12;
69
73
    int decrypted; /* non-zero if successfully decrypted. */
 
74
    int keyless;
70
75
    ne_ssl_certificate cert;
71
76
    gnutls_x509_privkey pkey;
72
77
    char *friendly_name;
93
98
    return idx - 1;
94
99
}
95
100
 
 
101
#ifdef HAVE_GNUTLS_X509_DN_GET_RDN_AVA
 
102
/* New-style RDN handling introduced in GnuTLS 1.7.x. */
 
103
 
 
104
#ifdef HAVE_ICONV
 
105
static void convert_dirstring(ne_buffer *buf, const char *charset, 
 
106
                              gnutls_datum *data)
 
107
{
 
108
    iconv_t id = iconv_open("UTF-8", charset);
 
109
    size_t inlen = data->size, outlen = buf->length - buf->used;
 
110
    char *inbuf = (char *)data->data;
 
111
    char *outbuf = buf->data + buf->used - 1;
 
112
    
 
113
    if (id == (iconv_t)-1) {
 
114
        char err[128], err2[128];
 
115
 
 
116
        ne_snprintf(err, sizeof err, "[unprintable in %s: %s]",
 
117
                    charset, ne_strerror(errno, err2, sizeof err2));
 
118
        ne_buffer_zappend(buf, err);
 
119
        return;
 
120
    }
 
121
    
 
122
    ne_buffer_grow(buf, buf->used + 64);
 
123
    
 
124
    while (inlen && outlen 
 
125
           && iconv(id, &inbuf, &inlen, &outbuf, &outlen) == 0)
 
126
        ;
 
127
    
 
128
    iconv_close(id);
 
129
    buf->used += buf->length - buf->used - outlen;
 
130
    buf->data[buf->used - 1] = '\0';
 
131
}
 
132
#endif
 
133
 
 
134
/* From section 11.13 of the Dubuisson ASN.1 bible: */
 
135
#define TAG_UTF8 (12)
 
136
#define TAG_PRINTABLE (19)
 
137
#define TAG_T61 (20)
 
138
#define TAG_IA5 (22)
 
139
#define TAG_VISIBLE (26)
 
140
#define TAG_UNIVERSAL (28)
 
141
#define TAG_BMP (30)
 
142
 
 
143
static void append_dirstring(ne_buffer *buf, gnutls_datum *data, unsigned long tag)
 
144
{
 
145
    switch (tag) {
 
146
    case TAG_UTF8:
 
147
    case TAG_IA5:
 
148
    case TAG_PRINTABLE:
 
149
    case TAG_VISIBLE:
 
150
        ne_buffer_append(buf, (char *)data->data, data->size);
 
151
        break;
 
152
#ifdef HAVE_ICONV
 
153
    case TAG_T61:
 
154
        convert_dirstring(buf, "ISO-8859-1", data);
 
155
        break;
 
156
    case TAG_BMP:
 
157
        convert_dirstring(buf, "UCS-2BE", data);
 
158
        break;
 
159
#endif
 
160
    default: {
 
161
        char tmp[128];
 
162
        ne_snprintf(tmp, sizeof tmp, _("[unprintable:#%lu]"), tag);
 
163
        ne_buffer_zappend(buf, tmp);
 
164
    } break;
 
165
    }
 
166
}
 
167
 
 
168
/* OIDs to not include in readable DNs by default: */
 
169
#define OID_emailAddress "1.2.840.113549.1.9.1"
 
170
#define OID_commonName "2.5.4.3"
 
171
 
 
172
#define CMPOID(a,o) ((a)->oid.size == sizeof(o)                        \
 
173
                     && memcmp((a)->oid.data, o, strlen(o)) == 0)
 
174
 
 
175
char *ne_ssl_readable_dname(const ne_ssl_dname *name)
 
176
{
 
177
    gnutls_x509_dn_t dn;
 
178
    int ret, rdn = 0, flag = 0;
 
179
    ne_buffer *buf;
 
180
    gnutls_x509_ava_st val;
 
181
 
 
182
    if (name->subject)
 
183
        ret = gnutls_x509_crt_get_subject(name->cert, &dn);
 
184
    else
 
185
        ret = gnutls_x509_crt_get_issuer(name->cert, &dn);
 
186
    
 
187
    if (ret)
 
188
        return ne_strdup(_("[unprintable]"));
 
189
 
 
190
    buf = ne_buffer_create();
 
191
    
 
192
    /* Find the highest rdn... */
 
193
    while (gnutls_x509_dn_get_rdn_ava(dn, rdn++, 0, &val) == 0)
 
194
        ;        
 
195
 
 
196
    /* ..then iterate back to the first: */
 
197
    while (--rdn >= 0) {
 
198
        int ava = 0;
 
199
 
 
200
        /* Iterate through all AVAs for multivalued AVAs; better than
 
201
         * ne_openssl can do! */
 
202
        do {
 
203
            ret = gnutls_x509_dn_get_rdn_ava(dn, rdn, ava, &val);
 
204
 
 
205
            /* If the *only* attribute to append is the common name or
 
206
             * email address, use it; otherwise skip those
 
207
             * attributes. */
 
208
            if (ret == 0 && val.value.size > 0
 
209
                && ((!CMPOID(&val, OID_emailAddress)
 
210
                     && !CMPOID(&val, OID_commonName))
 
211
                    || (buf->used == 1 && rdn == 0))) {
 
212
                flag = 1;
 
213
                if (buf->used > 1) ne_buffer_append(buf, ", ", 2);
 
214
 
 
215
                append_dirstring(buf, &val.value, val.value_tag);
 
216
            }
 
217
            
 
218
            ava++;
 
219
        } while (ret == 0);
 
220
    }
 
221
 
 
222
    return ne_buffer_finish(buf);
 
223
}
 
224
 
 
225
#else /* !HAVE_GNUTLS_X509_DN_GET_RDN_AVA */
 
226
 
96
227
/* Appends the value of RDN with given oid from certitifcate x5
97
228
 * subject (if subject is non-zero), or issuer DN to buffer 'buf': */
98
229
static void append_rdn(ne_buffer *buf, gnutls_x509_crt x5, int subject, const char *oid)
142
273
 
143
274
    return ne_buffer_finish(buf);
144
275
}
 
276
#endif /* HAVE_GNUTLS_X509_DN_GET_RDN_AVA */
145
277
 
146
278
int ne_ssl_dname_cmp(const ne_ssl_dname *dn1, const ne_ssl_dname *dn2)
147
279
{
199
331
static int match_hostname(char *cn, const char *hostname)
200
332
{
201
333
    const char *dot;
202
 
    NE_DEBUG(NE_DBG_SSL, "Match %s on %s...\n", cn, hostname);
203
334
    dot = strchr(hostname, '.');
204
335
    if (dot == NULL) {
205
336
        char *pnt = strchr(cn, '.');
220
351
 * If 'identity' is non-NULL, store the malloc-allocated identity in
221
352
 * *identity.  If 'server' is non-NULL, it must be the network address
222
353
 * of the server in use, and identity must be NULL. */
223
 
static int check_identity(const char *hostname, gnutls_x509_crt cert,
 
354
static int check_identity(const ne_uri *server, gnutls_x509_crt cert,
224
355
                          char **identity)
225
356
{
226
357
    char name[255];
228
359
    int ret, seq = 0;
229
360
    int match = 0, found = 0;
230
361
    size_t len;
 
362
    const char *hostname;
 
363
    
 
364
    hostname = server ? server->host : "";
231
365
 
232
366
    do {
233
 
        len = sizeof name;
 
367
        len = sizeof name - 1;
234
368
        ret = gnutls_x509_crt_get_subject_alt_name(cert, seq, name, &len,
235
369
                                                   &critical);
236
370
        switch (ret) {
237
371
        case GNUTLS_SAN_DNSNAME:
 
372
            name[len] = '\0';
238
373
            if (identity && !found) *identity = ne_strdup(name);
239
374
            match = match_hostname(name, hostname);
240
375
            found = 1;
261
396
                         len);
262
397
            }
263
398
        } break;
 
399
        case GNUTLS_SAN_URI: {
 
400
            ne_uri uri;
 
401
            
 
402
            name[len] = '\0';
 
403
            
 
404
            if (ne_uri_parse(name, &uri) == 0 && uri.host && uri.scheme) {
 
405
                ne_uri tmp;
 
406
                
 
407
                if (identity && !found) *identity = ne_strdup(name);
 
408
                found = 1;
 
409
                
 
410
                if (server) {
 
411
                    /* For comparison purposes, all that matters is
 
412
                     * host, scheme and port; ignore the rest. */
 
413
                    memset(&tmp, 0, sizeof tmp);
 
414
                    tmp.host = uri.host;
 
415
                    tmp.scheme = uri.scheme;
 
416
                    tmp.port = uri.port;
 
417
                    
 
418
                    match = ne_uri_cmp(server, &tmp) == 0;
 
419
                }
 
420
            }
 
421
            
 
422
            ne_uri_free(&uri);
 
423
        } break;
 
424
 
264
425
        default:
265
426
            break;
266
427
        }
286
447
        }
287
448
    }
288
449
 
289
 
    NE_DEBUG(NE_DBG_SSL, "Identity match: %s\n", match ? "good" : "bad");
 
450
    if (*hostname)
 
451
        NE_DEBUG(NE_DBG_SSL, "ssl: Identity match for '%s': %s\n", hostname, 
 
452
                 match ? "good" : "bad");
 
453
 
290
454
    return match ? 0 : 1;
291
455
}
292
456
 
301
465
    cert->issuer = NULL;
302
466
    cert->subject = x5;
303
467
    cert->identity = NULL;
304
 
    check_identity("", x5, &cert->identity);
 
468
    check_identity(NULL, x5, &cert->identity);
305
469
    return cert;
306
470
}
307
471
 
346
510
    ne_ssl_client_cert *newcc = ne_calloc(sizeof *newcc);
347
511
 
348
512
    newcc->decrypted = 1;
349
 
 
350
 
    ret = gnutls_x509_privkey_init(&newcc->pkey);
351
 
    if (ret != 0) goto dup_error;
352
 
 
353
 
    ret = gnutls_x509_privkey_cpy(newcc->pkey, cc->pkey);
354
 
    if (ret != 0) goto dup_error;
355
513
    
 
514
    if (cc->keyless) {
 
515
        newcc->keyless = 1;
 
516
    }
 
517
    else {
 
518
        ret = gnutls_x509_privkey_init(&newcc->pkey);
 
519
        if (ret != 0) goto dup_error;
 
520
        
 
521
        ret = gnutls_x509_privkey_cpy(newcc->pkey, cc->pkey);
 
522
        if (ret != 0) goto dup_error;
 
523
    }    
 
524
 
356
525
    newcc->cert.subject = x509_crt_copy(cc->cert.subject);
357
526
    if (!newcc->cert.subject) goto dup_error;
358
527
 
377
546
    ne_session *sess = gnutls_session_get_ptr(session);
378
547
    
379
548
    if (!sess) {
380
 
        return -1;
 
549
        return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
381
550
    }
382
551
 
383
552
    if (!sess->client_cert && sess->ssl_provide_fn) {
402
571
            /* tell GNU TLS not to deallocate the certs. */
403
572
            st->deinit_all = 0;
404
573
        } else {
405
 
            return -1;
 
574
            return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
406
575
        }
407
576
    } else {
408
577
        NE_DEBUG(NE_DBG_SSL, "No client certificate supplied.\n");
 
578
        return GNUTLS_E_NO_CERTIFICATE_FOUND;
409
579
    }
410
580
 
411
581
    return 0;
507
677
{
508
678
    time_t before, after, now = time(NULL);
509
679
    int ret, failures = 0;
 
680
    ne_uri server;
510
681
 
511
682
    before = gnutls_x509_crt_get_activation_time(chain->subject);
512
683
    after = gnutls_x509_crt_get_expiration_time(chain->subject);
516
687
    else if (now > after)
517
688
        failures |= NE_SSL_EXPIRED;
518
689
 
519
 
    ret = check_identity(sess->server.hostname, chain->subject, NULL);
 
690
    memset(&server, 0, sizeof server);
 
691
    ne_fill_server_uri(sess, &server);
 
692
    ret = check_identity(&server, chain->subject, NULL);
 
693
    ne_uri_free(&server);
 
694
 
520
695
    if (ret < 0) {
521
696
        ne_set_error(sess, _("Server certificate was missing commonName "
522
697
                             "attribute in subject name"));
553
728
 
554
729
    NE_DEBUG(NE_DBG_SSL, "Negotiating SSL connection.\n");
555
730
 
 
731
    /* Pass through the hostname if SNI is enabled. */
 
732
    ctx->hostname = 
 
733
        sess->flags[NE_SESSFLAG_TLS_SNI] ? sess->server.hostname : NULL;
 
734
 
556
735
    if (ne_sock_connect_ssl(sess->socket, ctx, sess)) {
557
736
        ne_set_error(sess, _("SSL negotiation failed: %s"),
558
737
                     ne_sock_error(sess->socket));
638
817
    }
639
818
 
640
819
    if (!feof(f)) {
 
820
        fclose(f);
641
821
        ne_buffer_destroy(buf);
642
822
        return -1;
643
823
    }
644
824
    
 
825
    fclose(f);
 
826
 
645
827
    datum->size = ne_buffer_size(buf);
646
828
    datum->data = (unsigned char *)ne_buffer_finish(buf);
647
829
    return 0;
666
848
        ret = gnutls_pkcs12_get_bag(p12, i, bag);
667
849
        if (ret < 0) continue;
668
850
 
669
 
        gnutls_pkcs12_bag_decrypt(bag, password == NULL ? "" : password);
 
851
        gnutls_pkcs12_bag_decrypt(bag, password);
670
852
 
671
853
        for (j = 0; ret == 0 && j < gnutls_pkcs12_bag_get_count(bag); ++j) {
672
854
            gnutls_pkcs12_bag_type type;
673
855
            gnutls_datum data;
674
856
 
675
857
            if (friendly_name && *friendly_name == NULL) {
676
 
                char *name;
 
858
                char *name = NULL;
677
859
                gnutls_pkcs12_bag_get_friendly_name(bag, j, &name);
678
860
                if (name) {
679
861
                    if (name[0] == '.') name++; /* weird GnuTLS bug? */
750
932
        return NULL;
751
933
    }
752
934
 
753
 
    ret = pkcs12_parse(p12, &pkey, &cert, &friendly_name, NULL);
754
 
 
755
935
    if (gnutls_pkcs12_verify_mac(p12, "") == 0) {
 
936
        if (pkcs12_parse(p12, &pkey, &cert, &friendly_name, "") != 0
 
937
            || !cert || !pkey) {
 
938
            gnutls_pkcs12_deinit(p12);
 
939
            return NULL;
 
940
        }
 
941
 
756
942
        cc = ne_calloc(sizeof *cc);
757
943
        cc->pkey = pkey;
758
944
        cc->decrypted = 1;
762
948
        cc->p12 = NULL;
763
949
        return cc;
764
950
    } else {
765
 
        if (ret == 0) {
766
 
            cc = ne_calloc(sizeof *cc);
767
 
            cc->friendly_name = friendly_name;
768
 
            cc->p12 = p12;
769
 
            return cc;
770
 
        } else {
771
 
            gnutls_pkcs12_deinit(p12);
772
 
            return NULL;
773
 
        }
774
 
    }
 
951
        /* TODO: calling pkcs12_parse() here to find the friendly_name
 
952
         * seems to break horribly.  */
 
953
        cc = ne_calloc(sizeof *cc);
 
954
        cc->p12 = p12;
 
955
        return cc;
 
956
    }
 
957
}
 
958
 
 
959
ne_ssl_client_cert *ne__ssl_clicert_exkey_import(const unsigned char *der,
 
960
                                                 size_t der_len)
 
961
{
 
962
    ne_ssl_client_cert *cc;
 
963
    gnutls_x509_crt x5;
 
964
    gnutls_datum datum;
 
965
 
 
966
    datum.data = (unsigned char *)der;
 
967
    datum.size = der_len;    
 
968
 
 
969
    if (gnutls_x509_crt_init(&x5) 
 
970
        || gnutls_x509_crt_import(x5, &datum, GNUTLS_X509_FMT_DER)) {
 
971
        NE_DEBUG(NE_DBG_SSL, "ssl: crt_import failed.\n");
 
972
        return NULL;
 
973
    }
 
974
    
 
975
    cc = ne_calloc(sizeof *cc);
 
976
    cc->keyless = 1;
 
977
    cc->decrypted = 1;
 
978
    populate_cert(&cc->cert, x5);
 
979
 
 
980
    return cc;    
775
981
}
776
982
 
777
983
int ne_ssl_clicert_encrypted(const ne_ssl_client_cert *cc)
792
998
    ret = pkcs12_parse(cc->p12, &pkey, &cert, NULL, password);
793
999
    if (ret < 0)
794
1000
        return ret;
 
1001
    
 
1002
    if (!cert || (!pkey && !cc->keyless)) {
 
1003
        if (cert) gnutls_x509_crt_deinit(cert);
 
1004
        if (pkey) gnutls_x509_privkey_deinit(pkey);
 
1005
        return -1;
 
1006
    }
795
1007
 
796
1008
    gnutls_pkcs12_deinit(cc->p12);
797
1009
    populate_cert(&cc->cert, cert);
958
1170
#ifdef NE_HAVE_TS_SSL
959
1171
    gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
960
1172
#endif
 
1173
    gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
961
1174
    return gnutls_global_init();
962
1175
}
963
1176
 
964
1177
void ne__ssl_exit(void)
965
1178
{
966
1179
    /* No way to unregister the thread callbacks.  Doomed. */
967
 
#if 0
 
1180
#if LIBGNUTLS_VERSION_MAJOR > 1 || LIBGNUTLS_VERSION_MINOR > 3 \
 
1181
    || (LIBGNUTLS_VERSION_MINOR == 3 && LIBGNUTLS_VERSION_PATCH >= 3)
968
1182
    /* It's safe to call gnutls_global_deinit() here only with
969
 
     * gnutls >= 1.3, since older versions don't refcount and
 
1183
     * gnutls >= 1.3., since older versions don't refcount and
970
1184
     * doing so would prevent any other use of gnutls within
971
1185
     * the process. */
972
1186
    gnutls_global_deinit();