1 /*
2    neon SSL/TLS support using GNU TLS
3    Copyright (C) 2002-2008, Joe Orton <joe@manyfish.co.uk>
4    Copyright (C) 2004, Aleix Conchillo Flaque <aleix@member.fsf.org>
5 
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10 
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public
17    License along with this library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19    MA 02111-1307, USA
20 */
21 
22 #include "config.h"
23 
24 #include <sys/types.h>
25 
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #endif
29 
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 
35 #include <gnutls/gnutls.h>
36 #include <gnutls/pkcs12.h>
37 
38 #ifdef NE_HAVE_TS_SSL
39 #include <errno.h>
40 #include <pthread.h>
41 #include <gcrypt.h>
42 GCRY_THREAD_OPTION_PTHREAD_IMPL;
43 #else
44 #include <gcrypt.h>
45 #endif
46 
47 #ifdef HAVE_ICONV
48 #include <iconv.h>
49 #endif
50 
51 #include "ne_ssl.h"
52 #include "ne_string.h"
53 #include "ne_session.h"
54 #include "ne_internal.h"
55 
56 #include "ne_private.h"
57 #include "ne_privssl.h"
58 
59 struct ne_ssl_dname_s {
60     int subject; /* non-zero if this is the subject DN object */
61     gnutls_x509_crt cert;
62 };
63 
64 struct ne_ssl_certificate_s {
65     ne_ssl_dname subj_dn, issuer_dn;
66     gnutls_x509_crt subject;
67     ne_ssl_certificate *issuer;
68     char *identity;
69 };
70 
71 struct ne_ssl_client_cert_s {
72     gnutls_pkcs12 p12;
73     int decrypted; /* non-zero if successfully decrypted. */
74     int keyless;
75     ne_ssl_certificate cert;
76     gnutls_x509_privkey pkey;
77     char *friendly_name;
78 };
79 
80 /* Returns the highest used index in subject (or issuer) DN of
81  * certificate CERT for OID, or -1 if no RDNs are present in the DN
82  * using that OID. */
oid_find_highest_index(gnutls_x509_crt cert,int subject,const char * oid)83 static int oid_find_highest_index(gnutls_x509_crt cert, int subject, const char *oid)
84 {
85     int ret, idx = -1;
86 
87     do {
88         size_t len = 0;
89 
90         if (subject)
91             ret = gnutls_x509_crt_get_dn_by_oid(cert, oid, ++idx, 0,
92                                                 NULL, &len);
93         else
94             ret = gnutls_x509_crt_get_issuer_dn_by_oid(cert, oid, ++idx, 0,
95                                                        NULL, &len);
96     } while (ret == GNUTLS_E_SHORT_MEMORY_BUFFER);
97 
98     return idx - 1;
99 }
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
convert_dirstring(ne_buffer * buf,const char * charset,gnutls_datum * data)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 
append_dirstring(ne_buffer * buf,gnutls_datum * data,unsigned long tag)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 
ne_ssl_readable_dname(const ne_ssl_dname * name)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 
227 /* Appends the value of RDN with given oid from certitifcate x5
228  * subject (if subject is non-zero), or issuer DN to buffer 'buf': */
append_rdn(ne_buffer * buf,gnutls_x509_crt x5,int subject,const char * oid)229 static void append_rdn(ne_buffer *buf, gnutls_x509_crt x5, int subject, const char *oid)
230 {
231     int idx, top, ret;
232     char rdn[50];
233 
234     top = oid_find_highest_index(x5, subject, oid);
235 
236     for (idx = top; idx >= 0; idx--) {
237         size_t rdnlen = sizeof rdn;
238 
239         if (subject)
240             ret = gnutls_x509_crt_get_dn_by_oid(x5, oid, idx, 0, rdn, &rdnlen);
241         else
242             ret = gnutls_x509_crt_get_issuer_dn_by_oid(x5, oid, idx, 0, rdn, &rdnlen);
243 
244         if (ret < 0)
245             return;
246 
247         if (buf->used > 1) {
248             ne_buffer_append(buf, ", ", 2);
249         }
250 
251         ne_buffer_append(buf, rdn, rdnlen);
252     }
253 }
254 
ne_ssl_readable_dname(const ne_ssl_dname * name)255 char *ne_ssl_readable_dname(const ne_ssl_dname *name)
256 {
257     ne_buffer *buf = ne_buffer_create();
258     int ret, idx = 0;
259 
260     do {
261         char oid[32] = {0};
262         size_t oidlen = sizeof oid;
263 
264         ret = name->subject
265             ? gnutls_x509_crt_get_dn_oid(name->cert, idx, oid, &oidlen)
266             : gnutls_x509_crt_get_issuer_dn_oid(name->cert, idx, oid, &oidlen);
267 
268         if (ret == 0) {
269             append_rdn(buf, name->cert, name->subject, oid);
270             idx++;
271         }
272     } while (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
273 
274     return ne_buffer_finish(buf);
275 }
276 #endif /* HAVE_GNUTLS_X509_DN_GET_RDN_AVA */
277 
ne_ssl_dname_cmp(const ne_ssl_dname * dn1,const ne_ssl_dname * dn2)278 int ne_ssl_dname_cmp(const ne_ssl_dname *dn1, const ne_ssl_dname *dn2)
279 {
280     char c1[1024], c2[1024];
281     size_t s1 = sizeof c1, s2 = sizeof c2;
282     int ret;
283 
284     if (dn1->subject)
285         ret = gnutls_x509_crt_get_dn(dn1->cert, c1, &s1);
286     else
287         ret = gnutls_x509_crt_get_issuer_dn(dn1->cert, c1, &s1);
288     if (ret)
289         return 1;
290 
291     if (dn2->subject)
292         ret = gnutls_x509_crt_get_dn(dn2->cert, c2, &s2);
293     else
294         ret = gnutls_x509_crt_get_issuer_dn(dn2->cert, c2, &s2);
295     if (ret)
296         return -1;
297 
298     if (s1 != s2)
299         return s2 - s1;
300 
301     return memcmp(c1, c2, s1);
302 }
303 
ne_ssl_clicert_free(ne_ssl_client_cert * cc)304 void ne_ssl_clicert_free(ne_ssl_client_cert *cc)
305 {
306     if (cc->p12)
307         gnutls_pkcs12_deinit(cc->p12);
308     if (cc->decrypted) {
309         if (cc->cert.identity) ne_free(cc->cert.identity);
310         if (cc->pkey) gnutls_x509_privkey_deinit(cc->pkey);
311         if (cc->cert.subject) gnutls_x509_crt_deinit(cc->cert.subject);
312     }
313     if (cc->friendly_name) ne_free(cc->friendly_name);
314     ne_free(cc);
315 }
316 
ne_ssl_cert_validity_time(const ne_ssl_certificate * cert,time_t * from,time_t * until)317 void ne_ssl_cert_validity_time(const ne_ssl_certificate *cert,
318                                time_t *from, time_t *until)
319 {
320     if (from) {
321         *from = gnutls_x509_crt_get_activation_time(cert->subject);
322     }
323     if (until) {
324         *until = gnutls_x509_crt_get_expiration_time(cert->subject);
325     }
326 }
327 
328 /* Return non-zero if hostname from certificate (cn) matches hostname
329  * used for session (hostname).  (Wildcard matching is no longer
330  * mandated by RFC3280, but certs are deployed which use wildcards) */
match_hostname(char * cn,const char * hostname)331 static int match_hostname(char *cn, const char *hostname)
332 {
333     const char *dot;
334     dot = strchr(hostname, '.');
335     if (dot == NULL) {
336 	char *pnt = strchr(cn, '.');
337 	/* hostname is not fully-qualified; unqualify the cn. */
338 	if (pnt != NULL) {
339 	    *pnt = '\0';
340 	}
341     }
342     else if (strncmp(cn, "*.", 2) == 0) {
343 	hostname = dot + 1;
344 	cn += 2;
345     }
346     return !ne_strcasecmp(cn, hostname);
347 }
348 
349 /* Check certificate identity.  Returns zero if identity matches; 1 if
350  * identity does not match, or <0 if the certificate had no identity.
351  * If 'identity' is non-NULL, store the malloc-allocated identity in
352  * *identity.  If 'server' is non-NULL, it must be the network address
353  * of the server in use, and identity must be NULL. */
check_identity(const ne_uri * server,gnutls_x509_crt cert,char ** identity)354 static int check_identity(const ne_uri *server, gnutls_x509_crt cert,
355                           char **identity)
356 {
357     char name[255];
358     unsigned int critical;
359     int ret, seq = 0;
360     int match = 0, found = 0;
361     size_t len;
362     const char *hostname;
363 
364     hostname = server ? server->host : "";
365 
366     do {
367         len = sizeof name - 1;
368         ret = gnutls_x509_crt_get_subject_alt_name(cert, seq, name, &len,
369                                                    &critical);
370         switch (ret) {
371         case GNUTLS_SAN_DNSNAME:
372             name[len] = '\0';
373             if (identity && !found) *identity = ne_strdup(name);
374             match = match_hostname(name, hostname);
375             found = 1;
376             break;
377         case GNUTLS_SAN_IPADDRESS: {
378             ne_inet_addr *ia;
379             if (len == 4)
380                 ia = ne_iaddr_make(ne_iaddr_ipv4, (unsigned char *)name);
381             else if (len == 16)
382                 ia = ne_iaddr_make(ne_iaddr_ipv6, (unsigned char *)name);
383             else
384                 ia = NULL;
385             if (ia) {
386                 char buf[128];
387 
388                 match = strcmp(hostname,
389                                ne_iaddr_print(ia, buf, sizeof buf)) == 0;
390                 if (identity) *identity = ne_strdup(buf);
391                 found = 1;
392                 ne_iaddr_free(ia);
393             } else {
394                 NE_DEBUG(NE_DBG_SSL, "iPAddress name with unsupported "
395                          "address type (length %" NE_FMT_SIZE_T "), skipped.\n",
396                          len);
397             }
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 
425         default:
426             break;
427         }
428         seq++;
429     } while (!match && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
430 
431     /* Check against the commonName if no DNS alt. names were found,
432      * as per RFC3280. */
433     if (!found) {
434         seq = oid_find_highest_index(cert, 1, GNUTLS_OID_X520_COMMON_NAME);
435 
436         if (seq >= 0) {
437             len = sizeof name;
438             name[0] = '\0';
439             ret = gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME,
440                                                 seq, 0, name, &len);
441             if (ret == 0) {
442                 if (identity) *identity = ne_strdup(name);
443                 match = match_hostname(name, hostname);
444             }
445         } else {
446             return -1;
447         }
448     }
449 
450     if (*hostname)
451         NE_DEBUG(NE_DBG_SSL, "ssl: Identity match for '%s': %s\n", hostname,
452                  match ? "good" : "bad");
453 
454     return match ? 0 : 1;
455 }
456 
457 /* Populate an ne_ssl_certificate structure from an X509 object. */
populate_cert(ne_ssl_certificate * cert,gnutls_x509_crt x5)458 static ne_ssl_certificate *populate_cert(ne_ssl_certificate *cert,
459                                          gnutls_x509_crt x5)
460 {
461     cert->subj_dn.cert = x5;
462     cert->subj_dn.subject = 1;
463     cert->issuer_dn.cert = x5;
464     cert->issuer_dn.subject = 0;
465     cert->issuer = NULL;
466     cert->subject = x5;
467     cert->identity = NULL;
468     check_identity(NULL, x5, &cert->identity);
469     return cert;
470 }
471 
472 /* Returns a copy certificate of certificate SRC. */
x509_crt_copy(gnutls_x509_crt src)473 static gnutls_x509_crt x509_crt_copy(gnutls_x509_crt src)
474 {
475     int ret;
476     size_t size;
477     gnutls_datum tmp;
478     gnutls_x509_crt dest;
479 
480     if (gnutls_x509_crt_init(&dest) != 0) {
481         return NULL;
482     }
483 
484     if (gnutls_x509_crt_export(src, GNUTLS_X509_FMT_DER, NULL, &size)
485         != GNUTLS_E_SHORT_MEMORY_BUFFER) {
486         gnutls_x509_crt_deinit(dest);
487         return NULL;
488     }
489 
490     tmp.data = ne_malloc(size);
491     ret = gnutls_x509_crt_export(src, GNUTLS_X509_FMT_DER, tmp.data, &size);
492     if (ret == 0) {
493         tmp.size = size;
494         ret = gnutls_x509_crt_import(dest, &tmp, GNUTLS_X509_FMT_DER);
495     }
496 
497     if (ret) {
498         gnutls_x509_crt_deinit(dest);
499         dest = NULL;
500     }
501 
502     ne_free(tmp.data);
503     return dest;
504 }
505 
506 /* Duplicate a client certificate, which must be in the decrypted state. */
dup_client_cert(const ne_ssl_client_cert * cc)507 static ne_ssl_client_cert *dup_client_cert(const ne_ssl_client_cert *cc)
508 {
509     int ret;
510     ne_ssl_client_cert *newcc = ne_calloc(sizeof *newcc);
511 
512     newcc->decrypted = 1;
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 
525     newcc->cert.subject = x509_crt_copy(cc->cert.subject);
526     if (!newcc->cert.subject) goto dup_error;
527 
528     if (cc->friendly_name) newcc->friendly_name = ne_strdup(cc->friendly_name);
529 
530     populate_cert(&newcc->cert, newcc->cert.subject);
531     return newcc;
532 
533 dup_error:
534     if (newcc->pkey) gnutls_x509_privkey_deinit(newcc->pkey);
535     if (newcc->cert.subject) gnutls_x509_crt_deinit(newcc->cert.subject);
536     ne_free(newcc);
537     return NULL;
538 }
539 
540 /* Callback invoked when the SSL server requests a client certificate.  */
provide_client_cert(gnutls_session session,const gnutls_datum * req_ca_rdn,int nreqs,const gnutls_pk_algorithm * sign_algos,int sign_algos_length,gnutls_retr_st * st)541 static int provide_client_cert(gnutls_session session,
542                                const gnutls_datum *req_ca_rdn, int nreqs,
543                                const gnutls_pk_algorithm *sign_algos,
544                                int sign_algos_length, gnutls_retr_st *st)
545 {
546     ne_session *sess = gnutls_session_get_ptr(session);
547 
548     if (!sess) {
549         return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
550     }
551 
552     if (!sess->client_cert && sess->ssl_provide_fn) {
553         /* The dname array cannot be converted without better dname
554          * support from GNUTLS. */
555         sess->ssl_provide_fn(sess->ssl_provide_ud, sess,
556                              NULL, 0);
557     }
558 
559     NE_DEBUG(NE_DBG_SSL, "In client cert provider callback.\n");
560 
561     if (sess->client_cert) {
562         gnutls_certificate_type type = gnutls_certificate_type_get(session);
563         if (type == GNUTLS_CRT_X509) {
564             NE_DEBUG(NE_DBG_SSL, "Supplying client certificate.\n");
565 
566             st->type = type;
567             st->ncerts = 1;
568             st->cert.x509 = &sess->client_cert->cert.subject;
569             st->key.x509 = sess->client_cert->pkey;
570 
571             /* tell GNU TLS not to deallocate the certs. */
572             st->deinit_all = 0;
573         } else {
574             return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
575         }
576     } else {
577         NE_DEBUG(NE_DBG_SSL, "No client certificate supplied.\n");
578         return GNUTLS_E_NO_CERTIFICATE_FOUND;
579     }
580 
581     return 0;
582 }
583 
ne_ssl_set_clicert(ne_session * sess,const ne_ssl_client_cert * cc)584 void ne_ssl_set_clicert(ne_session *sess, const ne_ssl_client_cert *cc)
585 {
586     sess->client_cert = dup_client_cert(cc);
587 }
588 
ne_ssl_context_create(int flags)589 ne_ssl_context *ne_ssl_context_create(int flags)
590 {
591     ne_ssl_context *ctx = ne_calloc(sizeof *ctx);
592     gnutls_certificate_allocate_credentials(&ctx->cred);
593     if (flags == NE_SSL_CTX_CLIENT) {
594         gnutls_certificate_client_set_retrieve_function(ctx->cred,
595                                                         provide_client_cert);
596     }
597     return ctx;
598 }
599 
ne_ssl_context_keypair(ne_ssl_context * ctx,const char * cert,const char * key)600 int ne_ssl_context_keypair(ne_ssl_context *ctx,
601                            const char *cert, const char *key)
602 {
603     gnutls_certificate_set_x509_key_file(ctx->cred, cert, key,
604                                          GNUTLS_X509_FMT_PEM);
605     return 0;
606 }
607 
ne_ssl_context_set_verify(ne_ssl_context * ctx,int required,const char * ca_names,const char * verify_cas)608 int ne_ssl_context_set_verify(ne_ssl_context *ctx, int required,
609                               const char *ca_names, const char *verify_cas)
610 {
611     ctx->verify = required;
612     if (verify_cas) {
613         gnutls_certificate_set_x509_trust_file(ctx->cred, verify_cas,
614                                                GNUTLS_X509_FMT_PEM);
615     }
616     /* gnutls_certificate_send_x509_rdn_sequence in gnutls >= 1.2 can
617      * be used to *suppress* sending the CA names, but not control it,
618      * it seems. */
619     return 0;
620 }
621 
ne_ssl_context_set_flag(ne_ssl_context * ctx,int flag,int value)622 void ne_ssl_context_set_flag(ne_ssl_context *ctx, int flag, int value)
623 {
624     /* SSLv2 not supported. */
625 }
626 
ne_ssl_context_destroy(ne_ssl_context * ctx)627 void ne_ssl_context_destroy(ne_ssl_context *ctx)
628 {
629     gnutls_certificate_free_credentials(ctx->cred);
630     if (ctx->cache.client.data) {
631         ne_free(ctx->cache.client.data);
632     } else if (ctx->cache.server.key.data) {
633         gnutls_free(ctx->cache.server.key.data);
634         gnutls_free(ctx->cache.server.data.data);
635     }
636     ne_free(ctx);
637 }
638 
639 /* Return the certificate chain sent by the peer, or NULL on error. */
make_peers_chain(gnutls_session sock)640 static ne_ssl_certificate *make_peers_chain(gnutls_session sock)
641 {
642     ne_ssl_certificate *current = NULL, *top = NULL;
643     const gnutls_datum *certs;
644     unsigned int n, count;
645 
646     certs = gnutls_certificate_get_peers(sock, &count);
647     if (!certs) {
648         return NULL;
649     }
650 
651     for (n = 0; n < count; n++) {
652         ne_ssl_certificate *cert;
653         gnutls_x509_crt x5;
654 
655         if (gnutls_x509_crt_init(&x5) ||
656             gnutls_x509_crt_import(x5, &certs[n], GNUTLS_X509_FMT_DER)) {
657             ne_ssl_cert_free(top);
658             return NULL;
659         }
660 
661         cert = populate_cert(ne_malloc(sizeof *cert), x5);
662 
663         if (top == NULL) {
664             current = top = cert;
665         } else {
666             current->issuer = cert;
667             current = cert;
668         }
669     }
670 
671     return top;
672 }
673 
674 /* Verifies an SSL server certificate. */
check_certificate(ne_session * sess,gnutls_session sock,ne_ssl_certificate * chain)675 static int check_certificate(ne_session *sess, gnutls_session sock,
676                              ne_ssl_certificate *chain)
677 {
678     time_t before, after, now = time(NULL);
679     int ret, failures = 0;
680     ne_uri server;
681 
682     before = gnutls_x509_crt_get_activation_time(chain->subject);
683     after = gnutls_x509_crt_get_expiration_time(chain->subject);
684 
685     if (now < before)
686         failures |= NE_SSL_NOTYETVALID;
687     else if (now > after)
688         failures |= NE_SSL_EXPIRED;
689 
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 
695     if (ret < 0) {
696         ne_set_error(sess, _("Server certificate was missing commonName "
697                              "attribute in subject name"));
698         return NE_ERROR;
699     } else if (ret > 0) {
700         failures |= NE_SSL_IDMISMATCH;
701     }
702 
703     if (gnutls_certificate_verify_peers(sock)) {
704         failures |= NE_SSL_UNTRUSTED;
705     }
706 
707     NE_DEBUG(NE_DBG_SSL, "Failures = %d\n", failures);
708 
709     if (failures == 0) {
710         ret = NE_OK;
711     } else {
712         ne__ssl_set_verify_err(sess, failures);
713         ret = NE_ERROR;
714         if (sess->ssl_verify_fn
715             && sess->ssl_verify_fn(sess->ssl_verify_ud, failures, chain) == 0)
716             ret = NE_OK;
717     }
718 
719     return ret;
720 }
721 
722 /* Negotiate an SSL connection. */
ne__negotiate_ssl(ne_session * sess)723 int ne__negotiate_ssl(ne_session *sess)
724 {
725     ne_ssl_context *const ctx = sess->ssl_context;
726     ne_ssl_certificate *chain;
727     gnutls_session sock;
728 
729     NE_DEBUG(NE_DBG_SSL, "Negotiating SSL connection.\n");
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 
735     if (ne_sock_connect_ssl(sess->socket, ctx, sess)) {
736 	ne_set_error(sess, _("SSL negotiation failed: %s"),
737 		     ne_sock_error(sess->socket));
738 	return NE_ERROR;
739     }
740 
741     sock = ne__sock_sslsock(sess->socket);
742 
743     chain = make_peers_chain(sock);
744     if (chain == NULL) {
745         ne_set_error(sess, _("Server did not send certificate chain"));
746         return NE_ERROR;
747     }
748 
749     if (sess->server_cert && ne_ssl_cert_cmp(sess->server_cert, chain) == 0) {
750         /* Same cert as last time; presume OK.  This is not optimal as
751          * make_peers_chain() has already gone through and done the
752          * expensive DER parsing stuff for the whole chain by now. */
753         ne_ssl_cert_free(chain);
754         return NE_OK;
755     }
756 
757     if (check_certificate(sess, sock, chain)) {
758         ne_ssl_cert_free(chain);
759         return NE_ERROR;
760     }
761 
762     sess->server_cert = chain;
763 
764     return NE_OK;
765 }
766 
ne_ssl_cert_issuer(const ne_ssl_certificate * cert)767 const ne_ssl_dname *ne_ssl_cert_issuer(const ne_ssl_certificate *cert)
768 {
769     return &cert->issuer_dn;
770 }
771 
ne_ssl_cert_subject(const ne_ssl_certificate * cert)772 const ne_ssl_dname *ne_ssl_cert_subject(const ne_ssl_certificate *cert)
773 {
774     return &cert->subj_dn;
775 }
776 
ne_ssl_cert_signedby(const ne_ssl_certificate * cert)777 const ne_ssl_certificate *ne_ssl_cert_signedby(const ne_ssl_certificate *cert)
778 {
779     return cert->issuer;
780 }
781 
ne_ssl_cert_identity(const ne_ssl_certificate * cert)782 const char *ne_ssl_cert_identity(const ne_ssl_certificate *cert)
783 {
784     return cert->identity;
785 }
786 
ne_ssl_context_trustcert(ne_ssl_context * ctx,const ne_ssl_certificate * cert)787 void ne_ssl_context_trustcert(ne_ssl_context *ctx, const ne_ssl_certificate *cert)
788 {
789     gnutls_x509_crt certs = cert->subject;
790     gnutls_certificate_set_x509_trust(ctx->cred, &certs, 1);
791 }
792 
ne_ssl_trust_default_ca(ne_session * sess)793 void ne_ssl_trust_default_ca(ne_session *sess)
794 {
795 #ifdef NE_SSL_CA_BUNDLE
796     gnutls_certificate_set_x509_trust_file(sess->ssl_context->cred,
797                                            NE_SSL_CA_BUNDLE,
798                                            GNUTLS_X509_FMT_PEM);
799 #endif
800 }
801 
802 /* Read the contents of file FILENAME into *DATUM. */
read_to_datum(const char * filename,gnutls_datum * datum)803 static int read_to_datum(const char *filename, gnutls_datum *datum)
804 {
805     FILE *f = fopen(filename, "r");
806     ne_buffer *buf;
807     char tmp[4192];
808     size_t len;
809 
810     if (!f) {
811         return -1;
812     }
813 
814     buf = ne_buffer_ncreate(8192);
815     while ((len = fread(tmp, 1, sizeof tmp, f)) > 0) {
816         ne_buffer_append(buf, tmp, len);
817     }
818 
819     if (!feof(f)) {
820         fclose(f);
821         ne_buffer_destroy(buf);
822         return -1;
823     }
824 
825     fclose(f);
826 
827     datum->size = ne_buffer_size(buf);
828     datum->data = (unsigned char *)ne_buffer_finish(buf);
829     return 0;
830 }
831 
832 /* Parses a PKCS#12 structure and loads the certificate, private key
833  * and friendly name if possible.  Returns zero on success, non-zero
834  * on error. */
pkcs12_parse(gnutls_pkcs12 p12,gnutls_x509_privkey * pkey,gnutls_x509_crt * x5,char ** friendly_name,const char * password)835 static int pkcs12_parse(gnutls_pkcs12 p12, gnutls_x509_privkey *pkey,
836                         gnutls_x509_crt *x5, char **friendly_name,
837                         const char *password)
838 {
839     gnutls_pkcs12_bag bag = NULL;
840     int i, j, ret = 0;
841 
842     for (i = 0; ret == 0; ++i) {
843         if (bag) gnutls_pkcs12_bag_deinit(bag);
844 
845         ret = gnutls_pkcs12_bag_init(&bag);
846         if (ret < 0) continue;
847 
848         ret = gnutls_pkcs12_get_bag(p12, i, bag);
849         if (ret < 0) continue;
850 
851         gnutls_pkcs12_bag_decrypt(bag, password);
852 
853         for (j = 0; ret == 0 && j < gnutls_pkcs12_bag_get_count(bag); ++j) {
854             gnutls_pkcs12_bag_type type;
855             gnutls_datum data;
856 
857             if (friendly_name && *friendly_name == NULL) {
858                 char *name = NULL;
859                 gnutls_pkcs12_bag_get_friendly_name(bag, j, &name);
860                 if (name) {
861                     if (name[0] == '.') name++; /* weird GnuTLS bug? */
862                     *friendly_name = ne_strdup(name);
863                 }
864             }
865 
866             type = gnutls_pkcs12_bag_get_type(bag, j);
867             switch (type) {
868             case GNUTLS_BAG_PKCS8_KEY:
869             case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY:
870                 gnutls_x509_privkey_init(pkey);
871 
872                 ret = gnutls_pkcs12_bag_get_data(bag, j, &data);
873                 if (ret < 0) continue;
874 
875                 ret = gnutls_x509_privkey_import_pkcs8(*pkey, &data,
876                                                        GNUTLS_X509_FMT_DER,
877                                                        password,
878                                                        0);
879                 if (ret < 0) continue;
880                 break;
881             case GNUTLS_BAG_CERTIFICATE:
882                 gnutls_x509_crt_init(x5);
883 
884                 ret = gnutls_pkcs12_bag_get_data(bag, j, &data);
885                 if (ret < 0) continue;
886 
887                 ret = gnutls_x509_crt_import(*x5, &data, GNUTLS_X509_FMT_DER);
888                 if (ret < 0) continue;
889 
890                 break;
891             default:
892                 break;
893             }
894         }
895     }
896 
897     /* Make sure last bag is freed */
898     if (bag) gnutls_pkcs12_bag_deinit(bag);
899 
900     /* Free in case of error */
901     if (ret < 0 && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
902         if (*x5) gnutls_x509_crt_deinit(*x5);
903         if (*pkey) gnutls_x509_privkey_deinit(*pkey);
904         if (friendly_name && *friendly_name) ne_free(*friendly_name);
905     }
906 
907     if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) ret = 0;
908     return ret;
909 }
910 
ne_ssl_clicert_read(const char * filename)911 ne_ssl_client_cert *ne_ssl_clicert_read(const char *filename)
912 {
913     int ret;
914     gnutls_datum data;
915     gnutls_pkcs12 p12;
916     ne_ssl_client_cert *cc;
917     char *friendly_name = NULL;
918     gnutls_x509_crt cert = NULL;
919     gnutls_x509_privkey pkey = NULL;
920 
921     if (read_to_datum(filename, &data))
922         return NULL;
923 
924     if (gnutls_pkcs12_init(&p12) != 0) {
925         return NULL;
926     }
927 
928     ret = gnutls_pkcs12_import(p12, &data, GNUTLS_X509_FMT_DER, 0);
929     ne_free(data.data);
930     if (ret < 0) {
931         gnutls_pkcs12_deinit(p12);
932         return NULL;
933     }
934 
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 
942         cc = ne_calloc(sizeof *cc);
943         cc->pkey = pkey;
944         cc->decrypted = 1;
945         cc->friendly_name = friendly_name;
946         populate_cert(&cc->cert, cert);
947         gnutls_pkcs12_deinit(p12);
948         cc->p12 = NULL;
949         return cc;
950     } else {
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 
ne__ssl_clicert_exkey_import(const unsigned char * der,size_t der_len)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;
981 }
982 
ne_ssl_clicert_encrypted(const ne_ssl_client_cert * cc)983 int ne_ssl_clicert_encrypted(const ne_ssl_client_cert *cc)
984 {
985     return !cc->decrypted;
986 }
987 
ne_ssl_clicert_decrypt(ne_ssl_client_cert * cc,const char * password)988 int ne_ssl_clicert_decrypt(ne_ssl_client_cert *cc, const char *password)
989 {
990     int ret;
991     gnutls_x509_crt cert = NULL;
992     gnutls_x509_privkey pkey = NULL;
993 
994     if (gnutls_pkcs12_verify_mac(cc->p12, password) != 0) {
995         return -1;
996     }
997 
998     ret = pkcs12_parse(cc->p12, &pkey, &cert, NULL, password);
999     if (ret < 0)
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     }
1007 
1008     gnutls_pkcs12_deinit(cc->p12);
1009     populate_cert(&cc->cert, cert);
1010     cc->pkey = pkey;
1011     cc->decrypted = 1;
1012     cc->p12 = NULL;
1013     return 0;
1014 }
1015 
ne_ssl_clicert_owner(const ne_ssl_client_cert * cc)1016 const ne_ssl_certificate *ne_ssl_clicert_owner(const ne_ssl_client_cert *cc)
1017 {
1018     return &cc->cert;
1019 }
1020 
ne_ssl_clicert_name(const ne_ssl_client_cert * ccert)1021 const char *ne_ssl_clicert_name(const ne_ssl_client_cert *ccert)
1022 {
1023     return ccert->friendly_name;
1024 }
1025 
ne_ssl_cert_read(const char * filename)1026 ne_ssl_certificate *ne_ssl_cert_read(const char *filename)
1027 {
1028     int ret;
1029     gnutls_datum data;
1030     gnutls_x509_crt x5;
1031 
1032     if (read_to_datum(filename, &data))
1033         return NULL;
1034 
1035     if (gnutls_x509_crt_init(&x5) != 0)
1036         return NULL;
1037 
1038     ret = gnutls_x509_crt_import(x5, &data, GNUTLS_X509_FMT_PEM);
1039     ne_free(data.data);
1040     if (ret < 0) {
1041         gnutls_x509_crt_deinit(x5);
1042         return NULL;
1043     }
1044 
1045     return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), x5);
1046 }
1047 
ne_ssl_cert_write(const ne_ssl_certificate * cert,const char * filename)1048 int ne_ssl_cert_write(const ne_ssl_certificate *cert, const char *filename)
1049 {
1050     unsigned char buffer[10*1024];
1051     size_t len = sizeof buffer;
1052 
1053     FILE *fp = fopen(filename, "w");
1054 
1055     if (fp == NULL) return -1;
1056 
1057     if (gnutls_x509_crt_export(cert->subject, GNUTLS_X509_FMT_PEM, buffer,
1058                                &len) < 0) {
1059         fclose(fp);
1060         return -1;
1061     }
1062 
1063     if (fwrite(buffer, len, 1, fp) != 1) {
1064         fclose(fp);
1065         return -1;
1066     }
1067 
1068     if (fclose(fp) != 0)
1069         return -1;
1070 
1071     return 0;
1072 }
1073 
ne_ssl_cert_free(ne_ssl_certificate * cert)1074 void ne_ssl_cert_free(ne_ssl_certificate *cert)
1075 {
1076     gnutls_x509_crt_deinit(cert->subject);
1077     if (cert->identity) ne_free(cert->identity);
1078     if (cert->issuer) ne_ssl_cert_free(cert->issuer);
1079     ne_free(cert);
1080 }
1081 
ne_ssl_cert_cmp(const ne_ssl_certificate * c1,const ne_ssl_certificate * c2)1082 int ne_ssl_cert_cmp(const ne_ssl_certificate *c1, const ne_ssl_certificate *c2)
1083 {
1084     char digest1[NE_SSL_DIGESTLEN], digest2[NE_SSL_DIGESTLEN];
1085 
1086     if (ne_ssl_cert_digest(c1, digest1) || ne_ssl_cert_digest(c2, digest2)) {
1087         return -1;
1088     }
1089 
1090     return strcmp(digest1, digest2);
1091 }
1092 
1093 /* The certificate import/export format is the base64 encoding of the
1094  * raw DER; PEM without the newlines and wrapping. */
1095 
ne_ssl_cert_import(const char * data)1096 ne_ssl_certificate *ne_ssl_cert_import(const char *data)
1097 {
1098     int ret;
1099     size_t len;
1100     unsigned char *der;
1101     gnutls_datum buffer = { NULL, 0 };
1102     gnutls_x509_crt x5;
1103 
1104     if (gnutls_x509_crt_init(&x5) != 0)
1105         return NULL;
1106 
1107     /* decode the base64 to get the raw DER representation */
1108     len = ne_unbase64(data, &der);
1109     if (len == 0) return NULL;
1110 
1111     buffer.data = der;
1112     buffer.size = len;
1113 
1114     ret = gnutls_x509_crt_import(x5, &buffer, GNUTLS_X509_FMT_DER);
1115     ne_free(der);
1116 
1117     if (ret < 0) {
1118         gnutls_x509_crt_deinit(x5);
1119         return NULL;
1120     }
1121 
1122     return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), x5);
1123 }
1124 
ne_ssl_cert_export(const ne_ssl_certificate * cert)1125 char *ne_ssl_cert_export(const ne_ssl_certificate *cert)
1126 {
1127     unsigned char *der;
1128     size_t len = 0;
1129     char *ret;
1130 
1131     /* find the length of the DER encoding. */
1132     if (gnutls_x509_crt_export(cert->subject, GNUTLS_X509_FMT_DER, NULL, &len) !=
1133         GNUTLS_E_SHORT_MEMORY_BUFFER) {
1134         return NULL;
1135     }
1136 
1137     der = ne_malloc(len);
1138     if (gnutls_x509_crt_export(cert->subject, GNUTLS_X509_FMT_DER, der, &len)) {
1139         ne_free(der);
1140         return NULL;
1141     }
1142 
1143     ret = ne_base64(der, len);
1144     ne_free(der);
1145     return ret;
1146 }
1147 
ne_ssl_cert_digest(const ne_ssl_certificate * cert,char * digest)1148 int ne_ssl_cert_digest(const ne_ssl_certificate *cert, char *digest)
1149 {
1150     char sha1[20], *p;
1151     int j;
1152     size_t len = sizeof sha1;
1153 
1154     if (gnutls_x509_crt_get_fingerprint(cert->subject, GNUTLS_DIG_SHA,
1155                                         sha1, &len) < 0)
1156         return -1;
1157 
1158     for (j = 0, p = digest; j < 20; j++) {
1159         *p++ = NE_HEX2ASC((sha1[j] >> 4) & 0x0f);
1160         *p++ = NE_HEX2ASC(sha1[j] & 0x0f);
1161         *p++ = ':';
1162     }
1163 
1164     *--p = '\0';
1165     return 0;
1166 }
1167 
ne__ssl_init(void)1168 int ne__ssl_init(void)
1169 {
1170 #ifdef NE_HAVE_TS_SSL
1171     gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
1172 #endif
1173     gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
1174     return gnutls_global_init();
1175 }
1176 
ne__ssl_exit(void)1177 void ne__ssl_exit(void)
1178 {
1179     /* No way to unregister the thread callbacks.  Doomed. */
1180 #if LIBGNUTLS_VERSION_MAJOR > 1 || LIBGNUTLS_VERSION_MINOR > 3 \
1181     || (LIBGNUTLS_VERSION_MINOR == 3 && LIBGNUTLS_VERSION_PATCH >= 3)
1182     /* It's safe to call gnutls_global_deinit() here only with
1183      * gnutls >= 1.3., since older versions don't refcount and
1184      * doing so would prevent any other use of gnutls within
1185      * the process. */
1186     gnutls_global_deinit();
1187 #endif
1188 }
1189