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