1 /*
2  * lftp - file transfer program
3  *
4  * Copyright (c) 1996-2017 by Alexander V. Lukyanov (lav@yars.free.net)
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include <config.h>
21 
22 #if USE_SSL
23 #include <sys/types.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <errno.h>
29 #include <string.h>
30 #include "lftp_ssl.h"
31 #include "xmalloc.h"
32 #include "ResMgr.h"
33 #include "log.h"
34 #include "misc.h"
35 #include "network.h"
36 #include "buffer.h"
37 #if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER
38 #define X509_STORE_CTX_get_by_subject X509_STORE_get_by_subject
39 #endif
40 extern "C" {
41 #include "c-ctype.h"
42 #include "quotearg.h"
43 #include "quote.h"
44 }
45 
lftp_ssl_base(int fd1,handshake_mode_t m,const char * h)46 lftp_ssl_base::lftp_ssl_base(int fd1,handshake_mode_t m,const char *h)
47    : hostname(h)
48 {
49    fd=fd1;
50    handshake_done=false;
51    handshake_mode=m;
52    fatal=false;
53    cert_error=false;
54 }
set_error(const char * s1,const char * s2)55 void lftp_ssl_base::set_error(const char *s1,const char *s2)
56 {
57    if(s2)
58       error.vset(s1,": ",s2,NULL);
59    else
60       error.set(s1);
61 }
set_cert_error(const char * s,const xstring & fp)62 void lftp_ssl_base::set_cert_error(const char *s,const xstring& fp)
63 {
64    bool verify_default=ResMgr::QueryBool("ssl:verify-certificate",hostname);
65    bool verify=ResMgr::QueryBool("ssl:verify-certificate",hostname);
66    xstring fp_hex;
67    if(fp) {
68       for(unsigned i=0; i<fp.length(); i++)
69 	 fp_hex.appendf("%02X:",(unsigned char)fp[i]);
70       fp_hex.chomp(':');
71       if(verify && verify_default)
72 	 verify=ResMgr::QueryBool("ssl:verify-certificate",fp_hex);
73       s=xstring::format("%s (%s)",s,fp_hex.get());
74    }
75    const char *const warn=verify?"ERROR":"WARNING";
76    Log::global->Format(0,"%s: Certificate verification: %s\n",warn,s);
77    if(verify && !error)
78    {
79       set_error("Certificate verification",s);
80       fatal=true;
81       cert_error=true;
82    }
83 }
84 
85 #if USE_GNUTLS
86 
87 /* Helper functions to load a certificate and key
88  * files into memory. They use mmap for simplicity.
89  */
mmap_file(const char * file)90 static gnutls_datum_t mmap_file(const char *file)
91 {
92     int fd;
93     gnutls_datum_t mmaped_file = { NULL, 0 };
94     struct stat stat_st;
95     void *ptr;
96 
97     fd = open(file, 0);
98     if (fd == -1)
99 	return mmaped_file;
100 
101     fstat(fd, &stat_st);
102 
103     if ((ptr =
104 	 mmap(NULL, stat_st.st_size, PROT_READ, MAP_SHARED, fd,
105 	      0)) == MAP_FAILED)
106     {
107       close(fd);
108 	return mmaped_file;
109     }
110    close(fd);
111 
112     mmaped_file.data = (unsigned char*)ptr;
113     mmaped_file.size = stat_st.st_size;
114 
115     return mmaped_file;
116 }
117 
munmap_file(gnutls_datum_t data)118 static void munmap_file(gnutls_datum_t data)
119 {
120     munmap(data.data, data.size);
121 }
122 
123 #if LFTP_LIBGNUTLS_VERSION_CODE < 0x010201
124 #define gnutls_x509_crt_list_import lftp_gnutls_x509_crt_list_import
125 #define GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED 1
126 static
127 int gnutls_x509_crt_list_import(gnutls_x509_crt_t *certs, unsigned int* cert_max,
128     const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, unsigned int flags);
129 #endif
130 
LoadCA()131 void lftp_ssl_gnutls_instance::LoadCA()
132 {
133    // free CA first
134    for(unsigned i=0; i<ca_list_size; i++)
135       gnutls_x509_crt_deinit(ca_list[i]);
136    xfree(ca_list);
137    ca_list=0;
138    ca_list_size=0;
139 
140    const char *ca_file=ResMgr::Query("ssl:ca-file",0);
141    if(!ca_file || !ca_file[0])
142       return;
143 
144    gnutls_datum_t ca_pem=mmap_file(ca_file);
145    if(!ca_pem.data)
146    {
147       Log::global->Format(0,"%s: %s\n",ca_file,strerror(errno));
148       return;
149    }
150 
151    ca_list_size=64;
152    ca_list=(gnutls_x509_crt_t*)xmalloc(ca_list_size*sizeof(gnutls_x509_crl_t));
153    int res=gnutls_x509_crt_list_import(ca_list,&ca_list_size,&ca_pem,GNUTLS_X509_FMT_PEM,GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
154    if(res==GNUTLS_E_SHORT_MEMORY_BUFFER)
155    {
156       ca_list=(gnutls_x509_crt_t*)xrealloc(ca_list,ca_list_size*sizeof(gnutls_x509_crl_t));
157       res=gnutls_x509_crt_list_import(ca_list,&ca_list_size,&ca_pem,GNUTLS_X509_FMT_PEM,0);
158    }
159    if(res<0)
160    {
161       Log::global->Format(0,"gnutls_x509_crt_list_import: %s\n",gnutls_strerror(res));
162       xfree(ca_list);
163       ca_list=0;
164       ca_list_size=0;
165    }
166 
167    munmap_file(ca_pem);
168 }
LoadCRL()169 void lftp_ssl_gnutls_instance::LoadCRL()
170 {
171    // free CRL first
172    for(unsigned i=0; i<crl_list_size; i++)
173       gnutls_x509_crl_deinit(crl_list[i]);
174    xfree(crl_list);
175    crl_list=0;
176    crl_list_size=0;
177 
178    const char *crl_file=ResMgr::Query("ssl:crl-file",0);
179    if(!crl_file || !crl_file[0])
180       return;
181 
182    gnutls_datum_t crl_pem=mmap_file(crl_file);
183    if(!crl_pem.data)
184    {
185       Log::global->Format(0,"%s: %s\n",crl_file,strerror(errno));
186       return;
187    }
188    crl_list_size=1;
189    crl_list=(gnutls_x509_crl_t*)xmalloc(crl_list_size*sizeof(gnutls_x509_crl_t));
190    int res=gnutls_x509_crl_import(crl_list[0],&crl_pem,GNUTLS_X509_FMT_PEM);
191    if(res<0)
192    {
193       Log::global->Format(0,"gnutls_x509_crl_import: %s\n",gnutls_strerror(res));
194       xfree(crl_list);
195       crl_list=0;
196       crl_list_size=0;
197    }
198 
199    munmap_file(crl_pem);
200 }
Reconfig(const char * name)201 void lftp_ssl_gnutls_instance::Reconfig(const char *name)
202 {
203    if(!name || !strcmp(name,"ssl:ca-file"))
204       LoadCA();
205    if(!name || !strcmp(name,"ssl:crl-file"))
206       LoadCRL();
207 }
208 
lftp_ssl_find_ca_file()209 static const char *lftp_ssl_find_ca_file()
210 {
211    // a few possible locations of ca-bundle.crt
212    static const char *const ca_file_location[]={
213       "/etc/pki/tls/certs/ca-bundle.crt",
214       "/etc/certs/ca-bundle.crt",
215       "/usr/share/ssl/certs/ca-bundle.crt",
216       "/etc/ssl/certs/ca-certificates.crt",
217       "/usr/local/ssl/certs/ca-bundle.crt",
218       "/etc/apache/ssl.crt/ca-bundle.crt",
219       "/usr/share/curl/curl-ca-bundle.crt",
220       0};
221    for(int i=0; ca_file_location[i]; i++)
222    {
223       if(access(ca_file_location[i], R_OK)==0)
224 	 return ca_file_location[i];
225    }
226    return 0;
227 }
228 
lftp_ssl_gnutls_log_func(int level,const char * msg)229 static void lftp_ssl_gnutls_log_func(int level, const char *msg)
230 {
231    if(!strncmp(msg,"ASSERT",6)
232    || !strncmp(msg,"READ",4)
233    || !strncmp(msg,"WRITE",5))
234       level+=10;
235    Log::global->Format(9+level,"GNUTLS: %s",msg);
236 }
237 
lftp_ssl_gnutls_instance()238 lftp_ssl_gnutls_instance::lftp_ssl_gnutls_instance()
239 {
240    ca_list=0;
241    ca_list_size=0;
242    crl_list=0;
243    crl_list_size=0;
244 
245    gnutls_global_init();
246    gnutls_global_set_log_function(lftp_ssl_gnutls_log_func);
247    gnutls_global_set_log_level(9);
248 
249    const char *ca_file=ResMgr::Query("ssl:ca-file",0);
250    if(!ca_file || !ca_file[0])
251       ResMgr::Set("ssl:ca-file",0,lftp_ssl_find_ca_file());
252 
253    Reconfig(0);
254 }
~lftp_ssl_gnutls_instance()255 lftp_ssl_gnutls_instance::~lftp_ssl_gnutls_instance()
256 {
257    gnutls_global_deinit();
258 }
259 
260 
261 Ref<lftp_ssl_gnutls_instance> lftp_ssl_gnutls::instance;
262 
global_init()263 void lftp_ssl_gnutls::global_init()
264 {
265    if(!instance)
266       instance=new lftp_ssl_gnutls_instance();
267 }
global_deinit()268 void lftp_ssl_gnutls::global_deinit()
269 {
270    instance=0;
271 }
272 
273 #ifndef GNUTLS_NONBLOCK // for gnutls < 3.0
274 #  define add_GNUTLS_NONBLOCK
275 # else
276 #  define add_GNUTLS_NONBLOCK |GNUTLS_NONBLOCK
277 #endif
278 
lftp_ssl_gnutls(int fd1,handshake_mode_t m,const char * h)279 lftp_ssl_gnutls::lftp_ssl_gnutls(int fd1,handshake_mode_t m,const char *h)
280    : lftp_ssl_base(fd1,m,h)
281 {
282    global_init();
283 
284    cred=0;
285 
286    gnutls_init(&session,(m==CLIENT?GNUTLS_CLIENT:GNUTLS_SERVER)add_GNUTLS_NONBLOCK);
287    gnutls_set_default_priority(session);
288 
289    gnutls_transport_set_ptr(session,(gnutls_transport_ptr_t)fd);
290 
291    const char *priority=ResMgr::Query("ssl:priority", 0);
292    if(!priority || !*priority)
293    {
294       // hack for some ftp servers
295       const char *auth=ResMgr::Query("ftp:ssl-auth", hostname);
296       if(auth && !strncmp(auth, "SSL", 3))
297          priority="NORMAL:+VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-TLS1.2";
298    }
299    if(priority && *priority)
300    {
301       int res = gnutls_priority_set_direct(session, priority, 0);
302       if(res != GNUTLS_E_SUCCESS)
303 	 Log::global->Format(0,"gnutls_priority_set_direct(`%s'): %s\n",priority,gnutls_strerror(res));
304    }
305 
306    if(h && ResMgr::QueryBool("ssl:use-sni",h)) {
307       if(gnutls_server_name_set(session, GNUTLS_NAME_DNS, h, xstrlen(h)) < 0)
308 	 fprintf(stderr,"WARNING: failed to configure server name indication (SNI) TLS extension\n");
309    }
310 }
load_keys()311 void lftp_ssl_gnutls::load_keys()
312 {
313    gnutls_certificate_allocate_credentials(&cred);
314    int res;
315 #if 0
316    const char *ca_file=ResMgr::Query("ssl:ca-file",hostname);
317    const char *ca_file0=ResMgr::Query("ssl:ca-file",0);
318    if(ca_file && ca_file[0] && xstrcmp(ca_file,ca_file0))
319    {
320       res=gnutls_certificate_set_x509_trust_file(cred,ca_file,GNUTLS_X509_FMT_PEM);
321       if(res<0)
322 	 Log::global->Format(0,"gnutls_certificate_set_x509_trust_file(%s): %s\n",ca_file,gnutls_strerror(res));
323    }
324    const char *crl_file=ResMgr::Query("ssl:crl-file",hostname);
325    const char *crl_file0=ResMgr::Query("ssl:crl-file",0);
326    if(crl_file && crl_file[0] && xstrcmp(crl_file,crl_file0))
327    {
328       res=gnutls_certificate_set_x509_crl_file(cred,crl_file,GNUTLS_X509_FMT_PEM);
329       if(res<0)
330 	 Log::global->Format(0,"gnutls_certificate_set_x509_crl_file(%s): %s\n",crl_file,gnutls_strerror(res));
331    }
332 #endif
333    const char *key_file =ResMgr::Query("ssl:key-file",hostname);
334    const char *cert_file=ResMgr::Query("ssl:cert-file",hostname);
335    if(key_file && key_file[0] && cert_file && cert_file[0])
336    {
337       res=gnutls_certificate_set_x509_key_file(cred,cert_file,key_file,GNUTLS_X509_FMT_PEM);
338       if(res<0)
339 	 Log::global->Format(0,"gnutls_certificate_set_x509_key_file(%s,%s): %s\n",cert_file,key_file,gnutls_strerror(res));
340    }
341    gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
342 }
shutdown()343 void lftp_ssl_gnutls::shutdown()
344 {
345    if(handshake_done)
346       gnutls_bye(session,GNUTLS_SHUT_RDWR);  // FIXME - E_AGAIN
347 }
~lftp_ssl_gnutls()348 lftp_ssl_gnutls::~lftp_ssl_gnutls()
349 {
350    if(cred)
351       gnutls_certificate_free_credentials(cred);
352    gnutls_deinit(session);
353    session=0;
354 }
355 
356 /* This function will try to verify the peer's certificate chain, and
357  * also check if the hostname matches, and the activation, expiration dates.
358  */
verify_certificate_chain(const gnutls_datum_t * cert_chain,int cert_chain_length)359 void lftp_ssl_gnutls::verify_certificate_chain(const gnutls_datum_t *cert_chain,int cert_chain_length)
360 {
361    int i;
362    gnutls_x509_crt_t *cert=(gnutls_x509_crt_t*)alloca(cert_chain_length*sizeof(gnutls_x509_crt_t));
363 
364    /* Import all the certificates in the chain to
365     * native certificate format.
366     */
367    for (i = 0; i < cert_chain_length; i++)
368    {
369       gnutls_x509_crt_init(&cert[i]);
370       gnutls_x509_crt_import(cert[i],&cert_chain[i],GNUTLS_X509_FMT_DER);
371    }
372 
373    /* Now verify the certificates against their issuers
374     * in the chain.
375     */
376    for (i = 1; i < cert_chain_length; i++)
377       verify_cert2(cert[i - 1], cert[i]);
378 
379     /* Here we must verify the last certificate in the chain against
380      * our trusted CA list.
381      */
382    verify_last_cert(cert[cert_chain_length - 1]);
383 
384    /* Check if the name in the first certificate matches our destination!
385     */
386    bool check_hostname = ResMgr::QueryBool("ssl:check-hostname", hostname);
387    if(check_hostname) {
388       if(!gnutls_x509_crt_check_hostname(cert[0], hostname))
389 	 set_cert_error(xstring::format("certificate common name doesn't match requested host name %s",quote(hostname)),get_fp(cert[0]));
390    } else {
391       Log::global->Format(0, "WARNING: Certificate verification: hostname checking disabled\n");
392    }
393 
394    for (i = 0; i < cert_chain_length; i++)
395       gnutls_x509_crt_deinit(cert[i]);
396 }
397 
398 
399 /* Verifies a certificate against an other certificate
400  * which is supposed to be it's issuer. Also checks the
401  * crl_list if the certificate is revoked.
402  */
verify_cert2(gnutls_x509_crt_t crt,gnutls_x509_crt_t issuer)403 void lftp_ssl_gnutls::verify_cert2(gnutls_x509_crt_t crt,gnutls_x509_crt_t issuer)
404 {
405    int ret;
406    time_t now = SMTask::now;
407    size_t name_size;
408    char name[256];
409 
410    /* Print information about the certificates to
411     * be checked.
412     */
413    name_size = sizeof(name);
414    gnutls_x509_crt_get_dn(crt, name, &name_size);
415 
416    Log::global->Format(9, "Certificate: %s\n", name);
417 
418    name_size = sizeof(name);
419    gnutls_x509_crt_get_issuer_dn(crt, name, &name_size);
420 
421    Log::global->Format(9, " Issued by:        %s\n", name);
422 
423    /* Get the DN of the issuer cert.
424     */
425    name_size = sizeof(name);
426    gnutls_x509_crt_get_dn(issuer, name, &name_size);
427 
428    Log::global->Format(9, " Checking against: %s\n", name);
429 
430    /* Do the actual verification.
431     */
432    unsigned crt_status=0;
433    unsigned issuer_status=0;
434    gnutls_x509_crt_verify(crt, &issuer, 1, 0, &crt_status);
435    if(crt_status&GNUTLS_CERT_SIGNER_NOT_CA)
436    {
437       // recheck the issuer certificate against CA
438       gnutls_x509_crt_verify(issuer, instance->ca_list, instance->ca_list_size, 0, &issuer_status);
439       if(issuer_status==0)
440 	 crt_status&=~GNUTLS_CERT_SIGNER_NOT_CA;
441       if(crt_status==GNUTLS_CERT_INVALID)
442 	 crt_status=0;
443    }
444    if (crt_status & GNUTLS_CERT_INVALID)
445    {
446       char msg[256];
447       strcpy(msg,"Not trusted");
448       if(crt_status & GNUTLS_CERT_SIGNER_NOT_FOUND)
449 	 strcat(msg,": no issuer was found");
450       if(crt_status & GNUTLS_CERT_SIGNER_NOT_CA)
451 	 strcat(msg,": issuer is not a CA");
452       set_cert_error(msg,get_fp(crt));
453    }
454    else
455       Log::global->Format(9, "  Trusted\n");
456 
457 
458     /* Now check the expiration dates.
459      */
460     if (gnutls_x509_crt_get_activation_time(crt) > now)
461 	set_cert_error("Not yet activated",get_fp(crt));
462 
463     if (gnutls_x509_crt_get_expiration_time(crt) < now)
464 	set_cert_error("Expired",get_fp(crt));
465 
466     /* Check if the certificate is revoked.
467      */
468     ret = gnutls_x509_crt_check_revocation(crt, instance->crl_list, instance->crl_list_size);
469     if (ret == 1) {		/* revoked */
470 	set_cert_error("Revoked",get_fp(crt));
471     }
472 }
473 
474 
475 /* Verifies a certificate against the trusted CA list.
476  * Also checks the crl_list if the certificate is revoked.
477  */
verify_last_cert(gnutls_x509_crt_t crt)478 void lftp_ssl_gnutls::verify_last_cert(gnutls_x509_crt_t crt)
479 {
480    unsigned int crt_status;
481    int ret;
482    time_t now = SMTask::now;
483    size_t name_size;
484    char name[256];
485 
486    /* Print information about the certificates to
487     * be checked.
488     */
489    name_size = sizeof(name);
490    gnutls_x509_crt_get_dn(crt, name, &name_size);
491 
492    Log::global->Format(9, "Certificate: %s\n", name);
493 
494    name_size = sizeof(name);
495    gnutls_x509_crt_get_issuer_dn(crt, name, &name_size);
496 
497    Log::global->Format(9, " Issued by: %s\n", name);
498 
499    /* Do the actual verification.
500     */
501    gnutls_x509_crt_verify(crt, instance->ca_list, instance->ca_list_size, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, &crt_status);
502 
503    if (crt_status & GNUTLS_CERT_INVALID)
504    {
505       char msg[256];
506       strcpy(msg,"Not trusted");
507       if (crt_status & GNUTLS_CERT_SIGNER_NOT_CA)
508 	 strcat(msg,": Issuer is not a CA");
509       set_cert_error(msg,get_fp(crt));
510    }
511    else
512       Log::global->Format(9, "  Trusted\n");
513 
514 
515    /* Now check the expiration dates.
516     */
517    if(gnutls_x509_crt_get_activation_time(crt) > now)
518       set_cert_error("Not yet activated",get_fp(crt));
519 
520    if(gnutls_x509_crt_get_expiration_time(crt) < now)
521       set_cert_error("Expired",get_fp(crt));
522 
523    /* Check if the certificate is revoked.
524     */
525    ret = gnutls_x509_crt_check_revocation(crt, instance->crl_list, instance->crl_list_size);
526    if (ret == 1) {		/* revoked */
527       set_cert_error("Revoked",get_fp(crt));
528    }
529 }
530 
check_fatal(int res)531 bool lftp_ssl_gnutls::check_fatal(int res)
532 {
533    if(!gnutls_error_is_fatal(res))
534       return false;
535    if((res==GNUTLS_E_UNEXPECTED_PACKET_LENGTH
536        || res==GNUTLS_E_PUSH_ERROR || res==GNUTLS_E_PULL_ERROR
537        || res==GNUTLS_E_DECRYPTION_FAILED)
538    && (!errno || temporary_network_error(errno)))
539       return false;
540    return true;
541 }
542 
do_handshake()543 int lftp_ssl_gnutls::do_handshake()
544 {
545    if(handshake_done)
546       return DONE;
547    errno=0;
548    int res=gnutls_handshake(session);
549    if(res<0)
550    {
551       if(res==GNUTLS_E_AGAIN || res==GNUTLS_E_INTERRUPTED)
552 	 return RETRY;
553       else // error
554       {
555 	 fatal=check_fatal(res);
556 	 set_error("gnutls_handshake",gnutls_strerror(res));
557 	 return ERROR;
558       }
559    }
560    handshake_done=true;
561    SMTask::current->Timeout(0);
562 
563    if(gnutls_certificate_type_get(session)!=GNUTLS_CRT_X509)
564    {
565       set_cert_error("Unsupported certificate type",xstring::null);
566       return DONE; // FIXME: handle openpgp as well
567    }
568 
569    unsigned cert_list_size=0;
570    const gnutls_datum_t *cert_list=gnutls_certificate_get_peers(session,&cert_list_size);
571    if(cert_list==NULL || cert_list_size==0)
572       set_cert_error("No certificate was found!",xstring::null);
573    else
574       verify_certificate_chain(cert_list,cert_list_size);
575 
576    return DONE;
577 }
578 
579 #ifndef GNUTLS_E_PREMATURE_TERMINATION // for gnutls < 3.0
580 # define GNUTLS_E_PREMATURE_TERMINATION GNUTLS_E_UNEXPECTED_PACKET_LENGTH
581 #endif
582 
read(char * buf,int size)583 int lftp_ssl_gnutls::read(char *buf,int size)
584 {
585    if(error)
586       return ERROR;
587    int res=do_handshake();
588    if(res!=DONE)
589       return res;
590    errno=0;
591    res=gnutls_record_recv(session,buf,size);
592    if(res<0)
593    {
594       if(res==GNUTLS_E_AGAIN || res==GNUTLS_E_INTERRUPTED)
595 	 return RETRY;
596       else if(res==GNUTLS_E_UNEXPECTED_PACKET_LENGTH || res==GNUTLS_E_PREMATURE_TERMINATION)
597       {
598 	 Log::global->Format(7,"gnutls_record_recv: %s Assuming EOF.\n",gnutls_strerror(res));
599 	 return 0;
600       }
601       else // error
602       {
603 	 fatal=check_fatal(res);
604 	 set_error("gnutls_record_recv",gnutls_strerror(res));
605 	 return ERROR;
606       }
607    }
608    return res;
609 }
write(const char * buf,int size)610 int lftp_ssl_gnutls::write(const char *buf,int size)
611 {
612    if(error)
613       return ERROR;
614    int res=do_handshake();
615    if(res!=DONE)
616       return res;
617    if(size==0)
618       return 0;
619    errno=0;
620    res=gnutls_record_send(session,buf,size);
621    if(res<0)
622    {
623       if(res==GNUTLS_E_AGAIN || res==GNUTLS_E_INTERRUPTED)
624 	 return RETRY;
625       else // error
626       {
627 	 fatal=check_fatal(res);
628 	 set_error("gnutls_record_send",gnutls_strerror(res));
629 	 return ERROR;
630       }
631    }
632    return res;
633 }
want_in()634 bool lftp_ssl_gnutls::want_in()
635 {
636    return gnutls_record_get_direction(session)==0;
637 }
want_out()638 bool lftp_ssl_gnutls::want_out()
639 {
640    return gnutls_record_get_direction(session)==1;
641 }
copy_sid(const lftp_ssl_gnutls * o)642 void lftp_ssl_gnutls::copy_sid(const lftp_ssl_gnutls *o)
643 {
644    size_t session_data_size=0;
645    void *session_data;
646    int res=gnutls_session_get_data(o->session,NULL,&session_data_size);
647    if(res!=GNUTLS_E_SUCCESS && res!=GNUTLS_E_SHORT_MEMORY_BUFFER)
648       return;
649    session_data=xmalloc(session_data_size);
650    if(gnutls_session_get_data(o->session,session_data,&session_data_size)!=GNUTLS_E_SUCCESS)
651       return;
652    gnutls_session_set_data(session,session_data,session_data_size);
653 }
654 
655 #include <sha1.h>
get_fp(gnutls_x509_crt_t cert)656 const xstring& lftp_ssl_gnutls::get_fp(gnutls_x509_crt_t cert)
657 {
658    static xstring fp;
659    fp.truncate();
660    size_t fp_len=SHA1_DIGEST_SIZE;
661    if(gnutls_x509_crt_get_fingerprint(cert,GNUTLS_DIG_SHA1,fp.add_space(fp_len),&fp_len))
662       return xstring::null;
663    fp.add_commit(fp_len);
664    return fp;
665 }
666 
667 #if LFTP_LIBGNUTLS_VERSION_CODE < 0x010201
668 #define PEM_CERT_SEP2 "-----BEGIN X509 CERTIFICATE"
669 #define PEM_CERT_SEP "-----BEGIN CERTIFICATE"
670 #define CLEAR_CERTS \
671     for(j=0;j<count;j++) gnutls_x509_crt_deinit( certs[j])
672 /**
673   * gnutls_x509_crt_list_import - This function will import a PEM encoded certificate list
674   * @certs: The structures to store the parsed certificate. Must not be initialized.
675   * @cert_max: Initially must hold the maximum number of certs. It will be updated with the number of certs available.
676   * @data: The PEM encoded certificate.
677   * @format: One of DER or PEM. Only PEM is supported for now.
678   * @flags: must be zero or an OR'd sequence of gnutls_certificate_import_flags.
679   *
680   * This function will convert the given PEM encoded certificate list
681   * to the native gnutls_x509_crt_t format. The output will be stored in @certs.
682   * They will be automatically initialized.
683   *
684   * If the Certificate is PEM encoded it should have a header of "X509 CERTIFICATE", or
685   * "CERTIFICATE".
686   *
687   * Returns the number of certificates read or a negative error value.
688   *
689   */
690 static
gnutls_x509_crt_list_import(gnutls_x509_crt_t * certs,unsigned int * cert_max,const gnutls_datum_t * data,gnutls_x509_crt_fmt_t format,unsigned int flags)691 int gnutls_x509_crt_list_import(gnutls_x509_crt_t *certs, unsigned int* cert_max,
692     const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format, unsigned int flags)
693 {
694     int size;
695     const char *ptr;
696     gnutls_datum_t tmp;
697     int ret, nocopy=0;
698     unsigned int count=0,j;
699 
700     /* move to the certificate
701      */
702     ptr = (const char *)memmem(data->data, data->size,
703 		 PEM_CERT_SEP, sizeof(PEM_CERT_SEP) - 1);
704     if (ptr == NULL)
705 	ptr = (const char *)memmem(data->data, data->size,
706 		     PEM_CERT_SEP2, sizeof(PEM_CERT_SEP2) - 1);
707 
708     if (ptr == NULL) {
709 	return GNUTLS_E_BASE64_DECODING_ERROR;
710     }
711     size = data->size - (ptr - (char*)data->data);
712 
713     count = 0;
714 
715     do {
716         if (count >= *cert_max) {
717             if (!(flags & GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED))
718                 break;
719             else
720                 nocopy = 1;
721         }
722 
723 	if (!nocopy) {
724 	    ret = gnutls_x509_crt_init( &certs[count]);
725 	    if (ret < 0) {
726                 goto error;
727             }
728 
729 	    tmp.data = (unsigned char*)ptr;
730 	    tmp.size = size;
731 
732 	    ret = gnutls_x509_crt_import( certs[count], &tmp, GNUTLS_X509_FMT_PEM);
733 	    if (ret < 0) {
734                 goto error;
735             }
736         }
737 
738 	/* now we move ptr after the pem header
739 	 */
740 	ptr++;
741 	/* find the next certificate (if any)
742 	 */
743 	size = data->size - (ptr - (char*)data->data);
744 
745 	if (size > 0) {
746 	    const char *ptr2;
747 
748 	    ptr2 =
749 		(const char *)memmem(ptr, size, PEM_CERT_SEP, sizeof(PEM_CERT_SEP) - 1);
750 	    if (ptr2 == NULL)
751 		ptr2 = (const char *)memmem(ptr, size, PEM_CERT_SEP2,
752 			      sizeof(PEM_CERT_SEP2) - 1);
753 
754 	    ptr = ptr2;
755 	} else
756 	    ptr = NULL;
757 
758 	count++;
759     } while (ptr != NULL);
760 
761     *cert_max = count;
762 
763     if (nocopy==0)
764         return count;
765     else
766         return GNUTLS_E_SHORT_MEMORY_BUFFER;
767 
768 error:
769     CLEAR_CERTS;
770     return ret;
771 }
772 #endif
773 
774 /*=============================== OpenSSL ====================================*/
775 #elif USE_OPENSSL
776 //static int lftp_ssl_passwd_callback(char *buf,int size,int rwflag,void *userdata);
777 
778 #if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER
779 // for compatibility with older versions
X509_OBJECT_new()780 X509_OBJECT *X509_OBJECT_new()
781 {
782     X509_OBJECT *ret;
783     return (X509_OBJECT*)OPENSSL_malloc(sizeof(*ret));
784 }
X509_OBJECT_free(X509_OBJECT * a)785 void X509_OBJECT_free(X509_OBJECT *a)
786 {
787     if (a == NULL)
788         return;
789     X509_OBJECT_free_contents(a);
790     OPENSSL_free(a);
791 }
X509_OBJECT_get0_X509_CRL(X509_OBJECT * a)792 X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a)
793 {
794     if (a == NULL) return NULL;
795     if (a->type != X509_LU_CRL) return NULL;
796     return a->data.crl;
797 }
798 # define X509_CRL_get0_nextUpdate(x) X509_CRL_get_nextUpdate(x)
799 # define ASN1_STRING_get0_data(x) ASN1_STRING_data(x)
800 # define X509_REVOKED_get0_serialNumber(x) (x->serialNumber)
801 #endif // OPENSSL_VERSION_NUMBER < 0x10100000L
802 
803 Ref<lftp_ssl_openssl_instance> lftp_ssl_openssl::instance;
804 
805 static char file[256];
lftp_ssl_write_rnd()806 static void lftp_ssl_write_rnd()
807 {
808    RAND_write_file(file);
809 }
810 
global_init()811 void lftp_ssl_openssl::global_init()
812 {
813    if(!instance)
814       instance=new lftp_ssl_openssl_instance();
815 }
global_deinit()816 void lftp_ssl_openssl::global_deinit()
817 {
818    instance=0;
819 }
820 
821 #ifndef SSL_OP_NO_TICKET
822 # define SSL_OP_NO_TICKET 0
823 #endif
824 
lftp_ssl_openssl_instance()825 lftp_ssl_openssl_instance::lftp_ssl_openssl_instance()
826 {
827    crl_store=0;
828    ssl_ctx=0;
829 
830 #ifdef WINDOWS
831    RAND_screen();
832 #endif
833 
834    RAND_file_name(file,sizeof(file));
835 
836    if(RAND_load_file(file,-1) && RAND_status()!=0)
837       atexit(lftp_ssl_write_rnd);
838 
839 #if OPENSSL_VERSION_NUMBER < 0x0800
840    ssl_ctx=SSL_CTX_new();
841    X509_set_default_verify_paths(ssl_ctx->cert);
842 #else
843 #if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER
844    SSLeay_add_ssl_algorithms();
845 #endif
846    ssl_ctx=SSL_CTX_new(SSLv23_client_method());
847    long options=SSL_OP_ALL|SSL_OP_NO_TICKET|SSL_OP_NO_SSLv2;
848    const char *priority=ResMgr::Query("ssl:priority", 0);
849    if(priority && *priority)
850    {
851       static const struct ssl_option {
852 	 const char name[8];
853 	 long option;
854       } opt_table[]={
855 	 {"-SSL3.0",SSL_OP_NO_SSLv3},
856 	 {"-TLS1.0",SSL_OP_NO_TLSv1},
857 	 {"-TLS1.1",SSL_OP_NO_TLSv1_1},
858 	 {"-TLS1.2",SSL_OP_NO_TLSv1_2},
859 	 {"",0}
860       };
861       char *to_parse=alloca_strdup(priority);
862       for(char *ptr=strtok(to_parse,":"); ptr; ptr=strtok(NULL,":")) {
863 	 if(*ptr && !strncmp(ptr+1,"VERS-",5)) {
864 	    ptr[5]=ptr[0];
865 	    ptr+=5;
866 	 }
867 	 for(const ssl_option *opt=opt_table; opt->name[0]; opt++) {
868 	    if(!strcmp(ptr,opt->name)) {
869 	       options|=opt->option;
870 	       Log::global->Format(9,"ssl: applied %s option\n",ptr);
871 	       break;
872 	    }
873 	 }
874       }
875    }
876    SSL_CTX_set_options(ssl_ctx, options);
877    SSL_CTX_set_cipher_list(ssl_ctx, "ALL:!aNULL:!eNULL:!SSLv2:!LOW:!EXP:!MD5:@STRENGTH");
878    SSL_CTX_set_verify(ssl_ctx,SSL_VERIFY_PEER,lftp_ssl_openssl::verify_callback);
879 //    SSL_CTX_set_default_passwd_cb(ssl_ctx,lftp_ssl_passwd_callback);
880 
881    const char *ca_file=ResMgr::Query("ssl:ca-file",0);
882    const char *ca_path=ResMgr::Query("ssl:ca-path",0);
883    if(ca_file && !*ca_file)
884       ca_file=0;
885    if(ca_path && !*ca_path)
886       ca_path=0;
887    if(ca_file || ca_path)
888    {
889       if(!SSL_CTX_load_verify_locations(ssl_ctx,ca_file,ca_path))
890       {
891 	 fprintf(stderr,"WARNING: SSL_CTX_load_verify_locations(%s,%s) failed\n",
892 	    ca_file?ca_file:"NULL",
893 	    ca_path?ca_path:"NULL");
894 	 SSL_CTX_set_default_verify_paths(ssl_ctx);
895       }
896    }
897    else
898    {
899       SSL_CTX_set_default_verify_paths(ssl_ctx);
900    }
901 
902    const char *crl_file=ResMgr::Query("ssl:crl-file",0);
903    const char *crl_path=ResMgr::Query("ssl:crl-path",0);
904    if(crl_file && !*crl_file)
905       crl_file=0;
906    if(crl_path && !*crl_path)
907       crl_path=0;
908    if(crl_file || crl_path)
909    {
910       crl_store=X509_STORE_new();
911       if(!X509_STORE_load_locations(crl_store,crl_file,crl_path))
912       {
913 	 fprintf(stderr,"WARNING: X509_STORE_load_locations(%s,%s) failed\n",
914 	    crl_file?crl_file:"NULL",
915 	    crl_path?crl_path:"NULL");
916       }
917    }
918 #endif /* SSLEAY_VERSION_NUMBER < 0x0800 */
919 }
~lftp_ssl_openssl_instance()920 lftp_ssl_openssl_instance::~lftp_ssl_openssl_instance()
921 {
922    SSL_CTX_free(ssl_ctx);
923    X509_STORE_free(crl_store);
924 }
925 
lftp_ssl_openssl(int fd1,handshake_mode_t m,const char * h)926 lftp_ssl_openssl::lftp_ssl_openssl(int fd1,handshake_mode_t m,const char *h)
927    : lftp_ssl_base(fd1,m,h)
928 {
929    if(!instance)
930       global_init();
931 
932    ssl=SSL_new(instance->ssl_ctx);
933    SSL_set_fd(ssl,fd);
934    SSL_ctrl(ssl,SSL_CTRL_MODE,SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER,0);
935 
936    if(h && ResMgr::QueryBool("ssl:use-sni",h)) {
937       if(!SSL_set_tlsext_host_name(ssl, h))
938 	 fprintf(stderr,"WARNING: failed to configure server name indication (SNI) TLS extension\n");
939    }
940 }
load_keys()941 void lftp_ssl_openssl::load_keys()
942 {
943    const char *key_file =ResMgr::Query("ssl:key-file",hostname);
944    const char *cert_file=ResMgr::Query("ssl:cert-file",hostname);
945    if(key_file && !*key_file)
946       key_file=0;
947    if(cert_file && !*cert_file)
948       cert_file=0;
949 
950    if(cert_file)
951    {
952       if(!key_file)
953 	 key_file=cert_file;
954       if(SSL_use_certificate_file(ssl,cert_file,SSL_FILETYPE_PEM)<=0)
955       {
956 	 // FIXME
957       }
958       if(SSL_use_PrivateKey_file(ssl,key_file,SSL_FILETYPE_PEM)<=0)
959       {
960 	 // FIXME
961       }
962       if(!SSL_check_private_key(ssl))
963       {
964 	 // FIXME
965       }
966    }
967 }
shutdown()968 void lftp_ssl_openssl::shutdown()
969 {
970    if(handshake_done)
971       SSL_shutdown(ssl);
972 }
~lftp_ssl_openssl()973 lftp_ssl_openssl::~lftp_ssl_openssl()
974 {
975    SSL_free(ssl);
976    ssl=0;
977 }
978 
979 static lftp_ssl_openssl *verify_callback_ssl;
980 
check_fatal(int res)981 bool lftp_ssl_openssl::check_fatal(int res)
982 {
983    return !(SSL_get_error(ssl,res)==SSL_ERROR_SYSCALL
984 	    && (ERR_get_error()==0 || temporary_network_error(errno)));
985 }
986 
do_handshake()987 int lftp_ssl_openssl::do_handshake()
988 {
989    if(handshake_done)
990       return DONE;
991    if(handshake_mode==SERVER)
992    {
993       // FIXME: SSL_accept
994       return RETRY;
995    }
996    errno=0;
997    verify_callback_ssl=this;
998    int res=SSL_connect(ssl);
999    verify_callback_ssl=0;
1000    if(res<=0)
1001    {
1002       if(BIO_sock_should_retry(res))
1003 	 return RETRY;
1004       else if (SSL_want_x509_lookup(ssl))
1005 	 return RETRY;
1006       else // error
1007       {
1008 	 fatal=check_fatal(res);
1009 	 set_error("SSL_connect",strerror());
1010 	 return ERROR;
1011       }
1012    }
1013    handshake_done=true;
1014    check_certificate();
1015    SMTask::current->Timeout(0);
1016    return DONE;
1017 }
read(char * buf,int size)1018 int lftp_ssl_openssl::read(char *buf,int size)
1019 {
1020    if(error)
1021       return ERROR;
1022    int res=do_handshake();
1023    if(res!=DONE)
1024       return res;
1025    errno=0;
1026    res=SSL_read(ssl,buf,size);
1027    if(res<0)
1028    {
1029       if(BIO_sock_should_retry(res))
1030 	 return RETRY;
1031       else if (SSL_want_x509_lookup(ssl))
1032 	 return RETRY;
1033       else // error
1034       {
1035 	 fatal=check_fatal(res);
1036 	 set_error("SSL_read",strerror());
1037 	 return ERROR;
1038       }
1039    }
1040    return res;
1041 }
write(const char * buf,int size)1042 int lftp_ssl_openssl::write(const char *buf,int size)
1043 {
1044    if(error)
1045       return ERROR;
1046    int res=do_handshake();
1047    if(res!=DONE)
1048       return res;
1049    if(size==0)
1050       return 0;
1051    errno=0;
1052    res=SSL_write(ssl,buf,size);
1053    if(res<0)
1054    {
1055       if(BIO_sock_should_retry(res))
1056 	 return RETRY;
1057       else if (SSL_want_x509_lookup(ssl))
1058 	 return RETRY;
1059       else // error
1060       {
1061 	 fatal=check_fatal(res);
1062 	 set_error("SSL_write",strerror());
1063 	 return ERROR;
1064       }
1065    }
1066    return res;
1067 }
want_in()1068 bool lftp_ssl_openssl::want_in()
1069 {
1070    return SSL_want_read(ssl);
1071 }
want_out()1072 bool lftp_ssl_openssl::want_out()
1073 {
1074    return SSL_want_write(ssl);
1075 }
copy_sid(const lftp_ssl_openssl * o)1076 void lftp_ssl_openssl::copy_sid(const lftp_ssl_openssl *o)
1077 {
1078    SSL_copy_session_id(ssl,o->ssl);
1079 }
1080 
strerror()1081 const char *lftp_ssl_openssl::strerror()
1082 {
1083 #if OPENSSL_VERSION_NUMBER < 0x10100000L || LIBRESSL_VERSION_NUMBER
1084    SSL_load_error_strings();
1085 #endif
1086    int error=ERR_get_error();
1087    const char *ssl_error=0;
1088    if(ERR_GET_LIB(error)==ERR_LIB_SSL)
1089       ssl_error=ERR_reason_error_string(error);
1090    else
1091       ssl_error=ERR_error_string(error,NULL);
1092    if(!ssl_error)
1093       ssl_error="error";
1094    return ssl_error;
1095 }
1096 
1097 /* This one is (very much!) based on work by Ralf S. Engelschall <rse@engelschall.com>.
1098  * Comments by Ralf. */
verify_crl(X509_STORE_CTX * ctx)1099 int lftp_ssl_openssl::verify_crl(X509_STORE_CTX *ctx)
1100 {
1101     X509_OBJECT *obj=0;
1102     X509_NAME *subject=0;
1103     X509_NAME *issuer=0;
1104     X509 *xs=0;
1105     X509_CRL *crl=0;
1106     X509_REVOKED *revoked=0;
1107     X509_STORE_CTX *store_ctx=0;
1108     long serial;
1109     int i, n, rc;
1110     char *cp=0;
1111 
1112     /*
1113      * Unless a revocation store for CRLs was created we
1114      * cannot do any CRL-based verification, of course.
1115      */
1116     if (!instance->crl_store)
1117         return 1;
1118 
1119     /*
1120      * Determine certificate ingredients in advance
1121      */
1122     xs      = X509_STORE_CTX_get_current_cert(ctx);
1123     subject = X509_get_subject_name(xs);
1124     issuer  = X509_get_issuer_name(xs);
1125 
1126     /*
1127      * OpenSSL provides the general mechanism to deal with CRLs but does not
1128      * use them automatically when verifying certificates, so we do it
1129      * explicitly here. We will check the CRL for the currently checked
1130      * certificate, if there is such a CRL in the store.
1131      *
1132      * We come through this procedure for each certificate in the certificate
1133      * chain, starting with the root-CA's certificate. At each step we've to
1134      * both verify the signature on the CRL (to make sure it's a valid CRL)
1135      * and it's revocation list (to make sure the current certificate isn't
1136      * revoked).  But because to check the signature on the CRL we need the
1137      * public key of the issuing CA certificate (which was already processed
1138      * one round before), we've a little problem. But we can both solve it and
1139      * at the same time optimize the processing by using the following
1140      * verification scheme (idea and code snippets borrowed from the GLOBUS
1141      * project):
1142      *
1143      * 1. We'll check the signature of a CRL in each step when we find a CRL
1144      *    through the _subject_ name of the current certificate. This CRL
1145      *    itself will be needed the first time in the next round, of course.
1146      *    But we do the signature processing one round before this where the
1147      *    public key of the CA is available.
1148      *
1149      * 2. We'll check the revocation list of a CRL in each step when
1150      *    we find a CRL through the _issuer_ name of the current certificate.
1151      *    This CRLs signature was then already verified one round before.
1152      *
1153      * This verification scheme allows a CA to revoke its own certificate as
1154      * well, of course.
1155      */
1156 
1157     /*
1158      * Try to retrieve a CRL corresponding to the _subject_ of
1159      * the current certificate in order to verify it's integrity.
1160      */
1161     obj = X509_OBJECT_new();
1162     store_ctx = X509_STORE_CTX_new();
1163     X509_STORE_CTX_init(store_ctx, instance->crl_store, NULL, NULL);
1164     rc = X509_STORE_CTX_get_by_subject(store_ctx, X509_LU_CRL, subject, obj);
1165     X509_STORE_CTX_free(store_ctx); store_ctx=0;
1166     crl = X509_OBJECT_get0_X509_CRL(obj);
1167     if (rc > 0 && crl != NULL) {
1168         /*
1169          * Verify the signature on this CRL
1170          */
1171         if (X509_CRL_verify(crl, X509_get_pubkey(xs)) <= 0) {
1172             Log::global->Format(0,"Invalid signature on CRL!\n");
1173             X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_SIGNATURE_FAILURE);
1174             X509_OBJECT_free(obj); obj=0;
1175             return 0;
1176         }
1177 
1178         /*
1179          * Check date of CRL to make sure it's not expired
1180          */
1181         i = X509_cmp_current_time(X509_CRL_get0_nextUpdate(crl));
1182         if (i == 0) {
1183             Log::global->Format(0,"Found CRL has invalid nextUpdate field.\n");
1184             X509_STORE_CTX_set_error(ctx, X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
1185             X509_OBJECT_free(obj); obj=0;
1186             return 0;
1187         }
1188         if (i < 0) {
1189             Log::global->Format(0,"Found CRL is expired - revoking all certificates until you get updated CRL.\n");
1190             X509_STORE_CTX_set_error(ctx, X509_V_ERR_CRL_HAS_EXPIRED);
1191             X509_OBJECT_free(obj); obj=0;
1192             return 0;
1193         }
1194         X509_OBJECT_free(obj); obj=0;
1195     }
1196 
1197     /*
1198      * Try to retrieve a CRL corresponding to the _issuer_ of
1199      * the current certificate in order to check for revocation.
1200      */
1201     obj = X509_OBJECT_new();
1202     store_ctx = X509_STORE_CTX_new();
1203     X509_STORE_CTX_init(store_ctx, instance->crl_store, NULL, NULL);
1204     rc = X509_STORE_CTX_get_by_subject(store_ctx, X509_LU_CRL, issuer, obj);
1205     X509_STORE_CTX_free(store_ctx); store_ctx=0;
1206     crl = X509_OBJECT_get0_X509_CRL(obj);
1207     if (rc > 0 && crl != NULL) {
1208         /*
1209          * Check if the current certificate is revoked by this CRL
1210          */
1211         n = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
1212         for (i = 0; i < n; i++) {
1213             revoked = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
1214 	    const ASN1_INTEGER *revoked_serial = X509_REVOKED_get0_serialNumber(revoked);
1215             if (ASN1_INTEGER_cmp(revoked_serial, X509_get_serialNumber(xs)) == 0) {
1216                 serial = ASN1_INTEGER_get(revoked_serial);
1217                 cp = X509_NAME_oneline(issuer, NULL, 0);
1218                 Log::global->Format(0,
1219 		    "Certificate with serial %ld (0x%lX) revoked per CRL from issuer %s\n",
1220                         serial, serial, cp ? cp : "(ERROR)");
1221                 free(cp); cp=0;
1222 
1223                 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
1224                 X509_OBJECT_free(obj); obj=0;
1225                 return 0;
1226             }
1227         }
1228         X509_OBJECT_free(obj); obj=0;
1229     }
1230     return 1;
1231 }
1232 
convert_from_utf8(char * str,int len)1233 static bool convert_from_utf8(char *str,int len)
1234 {
1235    DirectedBuffer translate(DirectedBuffer::GET);
1236    translate.SetTranslation("UTF-8",false);
1237    translate.PutTranslated(str,len);
1238    const char *str1,*str2;
1239    int len1,len2;
1240    translate.Get(&str1,&len1);
1241    if(len1>len)
1242       return false;  // no room to store expanded string
1243 
1244    // be safe and try to convert back to UTF-8
1245    DirectedBuffer translate_back(DirectedBuffer::PUT);
1246    translate_back.SetTranslation("UTF-8",false);
1247    translate_back.PutTranslated(str1,len1);
1248    translate_back.Get(&str2,&len2);
1249    if(len2!=len || memcmp(str2,str,len))
1250       return false;  // conversion error
1251 
1252    memcpy(str,str1,len1);
1253    str[len1]=0;
1254    return true;
1255 }
1256 
1257 /* begin curl code */
1258 /* Copyright (c) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se> */
1259 #define Curl_raw_toupper c_toupper
1260 #define Curl_raw_equal !strcmp
1261 #define Curl_raw_nequal !strncmp
1262 #define Curl_inet_pton inet_pton
1263 #if INET6
1264 # define ENABLE_IPV6 1
1265 #endif
1266 
1267 /*
1268  * Match a hostname against a wildcard pattern.
1269  * E.g.
1270  *  "foo.host.com" matches "*.host.com".
1271  *
1272  * We use the matching rule described in RFC6125, section 6.4.3.
1273  * http://tools.ietf.org/html/rfc6125#section-6.4.3
1274  *
1275  * In addition: ignore trailing dots in the host names and wildcards, so that
1276  * the names are used normalized. This is what the browsers do.
1277  *
1278  * Do not allow wildcard matching on IP numbers. There are apparently
1279  * certificates being used with an IP address in the CN field, thus making no
1280  * apparent distinction between a name and an IP. We need to detect the use of
1281  * an IP address and not wildcard match on such names.
1282  *
1283  * NOTE: hostmatch() gets called with copied buffers so that it can modify the
1284  * contents at will.
1285  */
1286 #define CURL_HOST_NOMATCH 0
1287 #define CURL_HOST_MATCH   1
1288 
hostmatch(char * hostname,char * pattern)1289 static int hostmatch(char *hostname, char *pattern)
1290 {
1291   const char *pattern_label_end, *pattern_wildcard, *hostname_label_end;
1292   int wildcard_enabled;
1293   size_t prefixlen, suffixlen;
1294   struct in_addr ignored;
1295 #ifdef ENABLE_IPV6
1296   struct sockaddr_in6 si6;
1297 #endif
1298 
1299   /* normalize pattern and hostname by stripping off trailing dots */
1300   size_t len = strlen(hostname);
1301   if(hostname[len-1]=='.')
1302     hostname[len-1]=0;
1303   len = strlen(pattern);
1304   if(pattern[len-1]=='.')
1305     pattern[len-1]=0;
1306 
1307   pattern_wildcard = strchr(pattern, '*');
1308   if(pattern_wildcard == NULL)
1309     return Curl_raw_equal(pattern, hostname) ?
1310       CURL_HOST_MATCH : CURL_HOST_NOMATCH;
1311 
1312   /* detect IP address as hostname and fail the match if so */
1313   if(Curl_inet_pton(AF_INET, hostname, &ignored) > 0)
1314     return CURL_HOST_NOMATCH;
1315 #ifdef ENABLE_IPV6
1316   else if(Curl_inet_pton(AF_INET6, hostname, &si6.sin6_addr) > 0)
1317     return CURL_HOST_NOMATCH;
1318 #endif
1319 
1320   /* We require at least 2 dots in pattern to avoid too wide wildcard
1321      match. */
1322   wildcard_enabled = 1;
1323   pattern_label_end = strchr(pattern, '.');
1324   if(pattern_label_end == NULL || strchr(pattern_label_end+1, '.') == NULL ||
1325      pattern_wildcard > pattern_label_end ||
1326      Curl_raw_nequal(pattern, "xn--", 4)) {
1327     wildcard_enabled = 0;
1328   }
1329   if(!wildcard_enabled)
1330     return Curl_raw_equal(pattern, hostname) ?
1331       CURL_HOST_MATCH : CURL_HOST_NOMATCH;
1332 
1333   hostname_label_end = strchr(hostname, '.');
1334   if(hostname_label_end == NULL ||
1335      !Curl_raw_equal(pattern_label_end, hostname_label_end))
1336     return CURL_HOST_NOMATCH;
1337 
1338   /* The wildcard must match at least one character, so the left-most
1339      label of the hostname is at least as large as the left-most label
1340      of the pattern. */
1341   if(hostname_label_end - hostname < pattern_label_end - pattern)
1342     return CURL_HOST_NOMATCH;
1343 
1344   prefixlen = pattern_wildcard - pattern;
1345   suffixlen = pattern_label_end - (pattern_wildcard+1);
1346   return Curl_raw_nequal(pattern, hostname, prefixlen) &&
1347     Curl_raw_nequal(pattern_wildcard+1, hostname_label_end - suffixlen,
1348                     suffixlen) ?
1349     CURL_HOST_MATCH : CURL_HOST_NOMATCH;
1350 }
1351 
cert_hostcheck(const char * match_pattern,const char * hostname)1352 static int cert_hostcheck(const char *match_pattern, const char *hostname)
1353 {
1354   char *matchp;
1355   char *hostp;
1356   int res = 0;
1357   if(!match_pattern || !*match_pattern ||
1358       !hostname || !*hostname) /* sanity check */
1359     ;
1360   else {
1361     matchp = strdup(match_pattern);
1362     if(matchp) {
1363       hostp = strdup(hostname);
1364       if(hostp) {
1365         if(hostmatch(hostp, matchp) == CURL_HOST_MATCH)
1366           res= 1;
1367         free(hostp);
1368       }
1369       free(matchp);
1370     }
1371   }
1372 
1373   return res;
1374 }
1375 
1376 /* Quote from RFC2818 section 3.1 "Server Identity"
1377 
1378    If a subjectAltName extension of type dNSName is present, that MUST
1379    be used as the identity. Otherwise, the (most specific) Common Name
1380    field in the Subject field of the certificate MUST be used. Although
1381    the use of the Common Name is existing practice, it is deprecated and
1382    Certification Authorities are encouraged to use the dNSName instead.
1383 
1384    Matching is performed using the matching rules specified by
1385    [RFC2459].  If more than one identity of a given type is present in
1386    the certificate (e.g., more than one dNSName name, a match in any one
1387    of the set is considered acceptable.) Names may contain the wildcard
1388    character * which is considered to match any single domain name
1389    component or component fragment. E.g., *.a.com matches foo.a.com but
1390    not bar.foo.a.com. f*.com matches foo.com but not bar.com.
1391 
1392    In some cases, the URI is specified as an IP address rather than a
1393    hostname. In this case, the iPAddress subjectAltName must be present
1394    in the certificate and must exactly match the IP in the URI.
1395 
1396 */
check_certificate()1397 void lftp_ssl_openssl::check_certificate()
1398 {
1399   X509 *server_cert = SSL_get_peer_certificate (ssl);
1400   if (!server_cert)
1401     {
1402       set_cert_error(xstring::format(_("No certificate presented by %s.\n"),
1403                  quotearg_style (escape_quoting_style, hostname)),xstring::null);
1404       return;
1405     }
1406 
1407   bool check_hostname = ResMgr::QueryBool("ssl:check-hostname", hostname);
1408   if(!check_hostname) {
1409     Log::global->Format(0, "WARNING: Certificate verification: hostname checking disabled\n");
1410     return;
1411   }
1412 
1413   int matched = -1; /* -1 is no alternative match yet, 1 means match and 0
1414                        means mismatch */
1415   int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */
1416   size_t addrlen = 0;
1417   STACK_OF(GENERAL_NAME) *altnames;
1418 #ifdef ENABLE_IPV6
1419   struct in6_addr addr;
1420 #else
1421   struct in_addr addr;
1422 #endif
1423 
1424   sockaddr_u fd_addr;
1425   socklen_t fd_addr_len = sizeof(fd_addr);
1426   getsockname(fd,&fd_addr.sa,&fd_addr_len);
1427 
1428 #ifdef ENABLE_IPV6
1429   if(fd_addr.sa.sa_family==AF_INET6 &&
1430      Curl_inet_pton(AF_INET6, hostname, &addr)) {
1431     target = GEN_IPADD;
1432     addrlen = sizeof(struct in6_addr);
1433   }
1434   else
1435 #endif
1436     if(Curl_inet_pton(AF_INET, hostname, &addr)) {
1437       target = GEN_IPADD;
1438       addrlen = sizeof(struct in_addr);
1439     }
1440 
1441   /* get a "list" of alternative names */
1442   altnames = (STACK_OF(GENERAL_NAME)*)X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL);
1443 
1444   if(altnames) {
1445     int numalts;
1446     int i;
1447 
1448     /* get amount of alternatives, RFC2459 claims there MUST be at least
1449        one, but we don't depend on it... */
1450     numalts = sk_GENERAL_NAME_num(altnames);
1451 
1452     /* loop through all alternatives while none has matched */
1453     for (i=0; (i<numalts) && (matched != 1); i++) {
1454       /* get a handle to alternative name number i */
1455       const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i);
1456 
1457       /* only check alternatives of the same type the target is */
1458       if(check->type == target) {
1459         /* get data and length */
1460         const char *altptr = (char *)ASN1_STRING_get0_data(check->d.ia5);
1461         size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5);
1462 
1463         switch(target) {
1464         case GEN_DNS: /* name/pattern comparison */
1465           /* The OpenSSL man page explicitly says: "In general it cannot be
1466              assumed that the data returned by ASN1_STRING_get0_data() is null
1467              terminated or does not contain embedded nulls." But also that
1468              "The actual format of the data will depend on the actual string
1469              type itself: for example for and IA5String the data will be ASCII"
1470 
1471              Gisle researched the OpenSSL sources:
1472              "I checked the 0.9.6 and 0.9.8 sources before my patch and
1473              it always 0-terminates an IA5String."
1474           */
1475           if((altlen == strlen(altptr)) &&
1476              /* if this isn't true, there was an embedded zero in the name
1477                 string and we cannot match it. */
1478              cert_hostcheck(altptr, hostname))
1479             matched = 1;
1480           else
1481             matched = 0;
1482           break;
1483 
1484         case GEN_IPADD: /* IP address comparison */
1485           /* compare alternative IP address if the data chunk is the same size
1486              our server IP address is */
1487           if((altlen == addrlen) && !memcmp(altptr, &addr, altlen))
1488             matched = 1;
1489           else
1490             matched = 0;
1491           break;
1492         }
1493       }
1494     }
1495     GENERAL_NAMES_free(altnames);
1496   }
1497 
1498   if(matched == 1)
1499     /* an alternative name matched the server hostname */
1500     Log::global->Format(9, "Certificate verification: subjectAltName: %s matched\n", quote(hostname));
1501   else if(matched == 0) {
1502     /* an alternative name field existed, but didn't match and then
1503        we MUST fail */
1504     set_cert_error(xstring::format("subjectAltName does not match %s", quote(hostname)),get_fp(server_cert));
1505   }
1506   else {
1507     /* we have to look to the last occurence of a commonName in the
1508        distinguished one to get the most significant one. */
1509     int j,i=-1 ;
1510 
1511 /* The following is done because of a bug in 0.9.6b */
1512 
1513     unsigned char *nulstr = (unsigned char *)"";
1514     unsigned char *peer_CN = nulstr;
1515 
1516     X509_NAME *name = X509_get_subject_name(server_cert) ;
1517     if(name)
1518       while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i))>=0)
1519         i=j;
1520 
1521     /* we have the name entry and we will now convert this to a string
1522        that we can use for comparison. Doing this we support BMPstring,
1523        UTF8 etc. */
1524 
1525     if(i>=0) {
1526       ASN1_STRING *tmp = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
1527 
1528       /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input
1529          is already UTF-8 encoded. We check for this case and copy the raw
1530          string manually to avoid the problem. This code can be made
1531          conditional in the future when OpenSSL has been fixed. Work-around
1532          brought by Alexis S. L. Carvalho. */
1533       if(tmp) {
1534         if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) {
1535           j = ASN1_STRING_length(tmp);
1536           if(j >= 0) {
1537             peer_CN = (unsigned char*)OPENSSL_malloc(j+1);
1538             if(peer_CN) {
1539               memcpy(peer_CN, ASN1_STRING_get0_data(tmp), j);
1540               peer_CN[j] = '\0';
1541             }
1542           }
1543         }
1544         else /* not a UTF8 name */
1545           j = ASN1_STRING_to_UTF8(&peer_CN, tmp);
1546 
1547         if(peer_CN && ((int)strlen((char *)peer_CN) != j)) {
1548           /* there was a terminating zero before the end of string, this
1549              cannot match and we return failure! */
1550           set_cert_error("illegal cert name field (contains NUL character)",get_fp(server_cert));
1551         }
1552       }
1553     }
1554 
1555     if(peer_CN == nulstr)
1556        peer_CN = NULL;
1557     else {
1558       /* convert peer_CN from UTF8 */
1559       if(!convert_from_utf8((char*)peer_CN, strlen((char*)peer_CN)))
1560 	 set_cert_error("invalid cert name field (cannot convert from UTF8)",get_fp(server_cert));
1561     }
1562 
1563     if(cert_error)
1564       /* error already detected, pass through */
1565       ;
1566     else if(!peer_CN) {
1567       set_cert_error("unable to obtain common name from peer certificate",get_fp(server_cert));
1568     }
1569     else if(!cert_hostcheck((const char *)peer_CN, hostname)) {
1570         set_cert_error(xstring::format("certificate subject name %s does not match "
1571               "target host name %s", quote_n(0,(const char *)peer_CN), quote_n(1,hostname)),get_fp(server_cert));
1572     }
1573     else {
1574       Log::global->Format(9, "Certificate verification: common name: %s matched\n", quote((char*)peer_CN));
1575     }
1576     if(peer_CN)
1577       OPENSSL_free(peer_CN);
1578   }
1579 }
1580 /* end curl code */
1581 
1582 #include <sha1.h>
get_fp(X509 * cert)1583 const xstring&  lftp_ssl_openssl::get_fp(X509 *cert)
1584 {
1585    static xstring fp;
1586    fp.truncate();
1587    unsigned fp_len=SHA1_DIGEST_SIZE;
1588    if(!X509_digest(cert, EVP_sha1(), (unsigned char*)fp.add_space(fp_len), &fp_len))
1589       return xstring::null;
1590    fp.add_commit(fp_len);
1591    return fp;
1592 }
1593 
verify_callback(int ok,X509_STORE_CTX * ctx)1594 int lftp_ssl_openssl::verify_callback(int ok,X509_STORE_CTX *ctx)
1595 {
1596    static X509 *prev_cert=0;
1597    X509 *cert=X509_STORE_CTX_get_current_cert(ctx);
1598 
1599    if(cert!=prev_cert)
1600    {
1601       int depth          = X509_STORE_CTX_get_error_depth(ctx);
1602       X509_NAME *subject = X509_get_subject_name(cert);
1603       X509_NAME *issuer  = X509_get_issuer_name(cert);
1604       char *subject_line = X509_NAME_oneline(subject, NULL, 0);
1605       char *issuer_line  = X509_NAME_oneline(issuer, NULL, 0);
1606       Log::global->Format(3,"Certificate depth: %d; subject: %s; issuer: %s\n",
1607 			  depth,subject_line,issuer_line);
1608       free(subject_line);
1609       free(issuer_line);
1610    }
1611 
1612    if(ok && !verify_crl(ctx))
1613       ok=0;
1614 
1615    int error=X509_STORE_CTX_get_error(ctx);
1616    if(!ok)
1617       verify_callback_ssl->set_cert_error(X509_verify_cert_error_string(error),get_fp(cert));
1618 
1619    prev_cert=cert;
1620    return 1;
1621 }
1622 #endif // USE_OPENSSL
1623 
1624 #endif // USE_SSL
1625