Package: netkit-ftp-ssl / 0.17.34+0.2-4

700_prefer_tls.diff Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
Description: Better contemporary abilities.
 Probe AUTH TLS as first authentication, then fall back
 to AUTH SSL.  Still, only protection level P is accepted.
 .
 Implement the claimed SSL option 'cipher=list'.
 .
 Add a new command line argument 'cacert=file', thus making sense
 of SSL verification mode.  Invoke a verification callback when
 running in verify mode, thereby making additional details known
 about the server's certificate chain, but only in verbose mode.
 .
 Include information about the encryption in use when executing
 the internal status command.  This includes identifiers of subject
 and issuer as stated in the server's certificate.
 .
 Replace cluttered error messages produced by the SSL library.
 .
 Report SSL cipher and encrypted data when in verbose mode.
 .
 Update the manual page.
 .
 The source file sslapp.c is synchronized with that of linux-ftpd-ssl.
 .
Author: Mats Erik Andersson <debian@gisladisker.se>
Forwarded: no
Last-Update: 2017-02-07

diff -Naurp netkit-ftp-0.17.debian/ftp/cmds.c netkit-ftp-0.17/ftp/cmds.c
--- netkit-ftp-0.17.debian/ftp/cmds.c	2016-12-23 00:05:51.820239257 +0100
+++ netkit-ftp-0.17/ftp/cmds.c	2016-12-23 17:47:11.133840700 +0100
@@ -1127,8 +1127,51 @@ status(void)
 {
 	int i;
 
-	if (connected)
+	if (connected) {
 		printf("Connected to %s.\n", hostname);
+#ifdef USE_SSL
+		if (ssl_active_flag && ssl_con) {
+			X509 *x509;
+
+			printf("Active cipher: %s, protocol %s.\n",
+			       SSL_get_cipher_name(ssl_con),
+			       SSL_get_version(ssl_con));
+			x509 = SSL_get_peer_certificate(ssl_con);
+			if (x509) {
+				char *name, *p;
+
+				name = ONELINE_NAME(X509_get_subject_name(x509));
+				p = name;
+				while (*p) {
+					if (*p == '/') *p = ' ';
+					p++;
+				}
+				p = name;
+				while (*p == ' ')
+					p++;
+
+				printf("Details of server certificate:\n");
+				printf(" Subject: %s\n", p);
+				free(name);
+
+				name = ONELINE_NAME(X509_get_issuer_name(x509));
+				p = name;
+				while (*p) {
+					if (*p == '/') *p = ' ';
+					p++;
+				}
+				p = name;
+				while (*p == ' ')
+					p++;
+
+				printf(" Issuer: %s\n", p);
+				free(name);
+			}
+		}
+		else
+			printf("No encryption.\n");
+#endif /* USE_SSL */
+	}
 	else
 		printf("Not connected.\n");
 	if (!proxy) {
diff -Naurp netkit-ftp-0.17.debian/ftp/ftp.1 netkit-ftp-0.17/ftp/ftp.1
--- netkit-ftp-0.17.debian/ftp/ftp.1	2016-12-23 00:05:48.972372225 +0100
+++ netkit-ftp-0.17/ftp/ftp.1	2017-01-05 15:47:23.606720435 +0100
@@ -44,12 +44,13 @@ file transfer program
 .Nm ftp
 .Op Fl 46pinegvd
 .Op Fl z Ar debug
-.Op Fl z Ar authdebug
+.\".Op Fl z Ar authdebug
 .Op Fl z Ar nossl
-.Op Fl z Ar certrequired
+.\".Op Fl z Ar certrequired
 .Op Fl z Ar secure
 .Op Fl z Ar verbose
 .Op Fl z Ar verify=flags
+.Op Fl z Ar cacert=ca_file
 .Op Fl z Ar cert=cert_file
 .Op Fl z Ar key=key_file
 .Op Fl z Ar cipher=list
@@ -57,12 +58,13 @@ file transfer program
 .Nm pftp
 .Op Fl 46inegvd
 .Op Fl z Ar debug
-.Op Fl z Ar authdebug
+.\".Op Fl z Ar authdebug
 .Op Fl z Ar nossl
-.Op Fl z Ar certrequired
+.\".Op Fl z Ar certrequired
 .Op Fl z Ar secure
 .Op Fl z Ar verbose
 .Op Fl z Ar verify=flags
+.Op Fl z Ar cacert=ca_file
 .Op Fl z Ar cert=cert_file
 .Op Fl z Ar key=key_file
 .Op Fl z Ar cipher=list
@@ -131,41 +133,46 @@ The SSL parameters are:
 .Bl -tag -width Fl
 .It Ic debug
 Send SSL related debugging information to stderr.
-.It Ic authdebug
-Enable authentication debugging.
+.\".It Ic authdebug
+.\"Enable authentication debugging.
 .It Ic ssl
-Negotiate SSL at first, then use ftp protocol. ftp protocol
+Negotiate SSL at first, then use FTP protocol. Only the FTP protocol
 negotiation goes encrypted. (Not yet implemented)
 .It Ic nossl, !ssl
-switch of SSL negotiation
-.It Ic certrequired
-client certificate is mandatory
+switch off SSL negotiation
+.\".It Ic certrequired
+.\"client certificate is mandatory
 .It Ic secure
 Don't switch back to unencrypted mode (no SSL) if SSL is not available.
 .It Ic verbose
 Be verbose about certificates etc.
 .It Ic verify= Ns Ar int
 .\" TODO
-Set the SSL verify flags (SSL_VERIFY_* in 
-.Ar ssl/ssl.h
+Set the SSL verify flags.  The only sensible value for a client like
+.Nm ftp
+is 1.  (See the macros SSL_VERIFY_* in 
+.Ar openssl/ssl.h
 ).
-.\" TODO
+.It Ic cacert= Ns Ar ca_file
+Accept the CA-certificates found in
+.Ar ca_file
+as verification of the remote server.
 .It Ic cert= Ns Ar cert_file
-.\" TODO
 Use the certificate(s) in
 .Ar cert_file .
+This file may also carry a key.
 .It Ic key= Ns Ar key_file
-.\" TODO
-Use the key(s) in
-.Ar key_file .
+Read the key(s) from
+.Ar key_file
+whenever the certificate file does not suffice.
 .It Ic cipher= Ns Ar ciph_list
-.\" TODO
 Set the preferred ciphers to
 .Ar ciph_list .
 .\" TODO: possible values; comma-separated list?
+The environment variable SSL_CIPHER serves the same purpose.
 (See 
-.Ar ssl/ssl.h
-).
+.Ar openssl/ssl.h
+for suggestions).
 .El
 .El
 .Pp
@@ -1119,6 +1126,8 @@ For default location of a
 file, if one exists.
 .It Ev SHELL
 For default shell.
+.It Ev SSL_CIPHER
+For acceptable cipher combinations.
 .El
 .Sh SEE ALSO
 .Xr ftpd 8 ,
diff -Naurp netkit-ftp-0.17.debian/ftp/ftp.c netkit-ftp-0.17/ftp/ftp.c
--- netkit-ftp-0.17.debian/ftp/ftp.c	2016-12-23 00:05:52.380213160 +0100
+++ netkit-ftp-0.17/ftp/ftp.c	2017-02-07 23:35:32.871433587 +0100
@@ -1686,12 +1686,17 @@ dataconn(const char *lmode)
 
 	    if ((ret=SSL_connect(ssl_data_con))<=0) {
                 static char errbuf[1024];
+		int err = SSL_get_error(ssl_data_con, ret);
 
-	        sprintf(errbuf,"ftp: SSL_connect DATA error %d - %s\n",
-			    ret,ERR_error_string(ERR_get_error(),NULL));
+		*errbuf = 0;
+		if (err != SSL_ERROR_SYSCALL || ret < 0)
+		    sprintf(errbuf,"ftp: SSL_connect DATA error %d - %s\n",
+			ERR_peek_error() ? ERR_peek_error() : errno,
+			ERR_peek_error() ? ERR_reason_error_string(err) : strerror(errno));
 
 		/* tell the user ... who else */
-		fprintf(stderr,"%s", errbuf);
+		if (*errbuf)
+		    fprintf(stderr,"%s", errbuf);
 		fflush(stderr);
 
 		/* abort time methinks ... */
@@ -2111,16 +2116,50 @@ printbytes(off_t bytes)
 }
 
 #ifdef USE_SSL
+static
+int
+verify_callback(int ok, X509_STORE_CTX *ctx)
+{
+	int depth, error;
+	X509 *xs;
+
+	depth = X509_STORE_CTX_get_error_depth(ctx);
+	error = X509_STORE_CTX_get_error(ctx);
+	xs = X509_STORE_CTX_get_current_cert(ctx);
+
+	if (verbose || ssl_verbose_flag) {
+	    char *p = (char *) ONELINE_NAME(X509_get_subject_name(xs));
+
+	    printf("[Subject %d: %s]\n", depth, p);
+	    free(p);
+
+	    if (ssl_verbose_flag) {
+		p = (char *) ONELINE_NAME(X509_get_issuer_name(xs));
+
+		/* Align position of name string with the previous one! */
+		printf("[Issuer %d:  %s]\n", depth, p);
+		free(p);
+	    }
+
+	    if (!ok)
+		printf("[Verification at depth %d: %s]\n",
+		       depth, X509_verify_cert_error_string(error));
+	}
+
+	return ok;
+} /* verify_callback */
+
 int
 ssl_init(void)
 {
         int n;
-        int use_tls = 0;
+        int use_tls = 1;
+
         if (ssl_enabled) {
-	    n = command("AUTH SSL");
+	    n = command("AUTH TLS");
 	    if (n == ERROR) {
-		use_tls = 1;
-		n = command("AUTH TLS");
+		use_tls = 0;
+		n = command("AUTH SSL");
 	    }
 	    if (n == ERROR) {		/* do normal USER/PASS */
 		printf("SSL not available\n");
@@ -2133,6 +2172,31 @@ ssl_init(void)
 		}
 	    } else if (n == CONTINUE || n == COMPLETE ) {
 		/* do SSL */
+		int ret;
+
+		errno = 0;
+
+		if (my_ssl_cacert_file) {
+		    ret = SSL_CTX_load_verify_locations(ssl_ctx, my_ssl_cacert_file, NULL);
+		    if (!ret) {
+			if (errno) {
+			    fprintf(stderr, "Error loading CA, %s: %s\r\n",
+				    strerror(errno), my_ssl_cacert_file);
+			} else {
+			    const char *e = ERR_func_error_string(ERR_peek_error());
+
+			    if (e)
+				fprintf(stderr, "Error loading CA %s: %s, %s\r\n",
+					my_ssl_cacert_file, e,
+					ERR_reason_error_string(ERR_peek_error()));
+			    else
+				fprintf(stderr, "Broken CA file: %s\n",
+					my_ssl_cacert_file);
+			}
+			exit(1);
+		    }
+		}
+
 		ssl_con=(SSL *)SSL_new(ssl_ctx);
 		if (!ssl_con) {
 		    ERR_print_errors_fp(stderr);
@@ -2142,37 +2206,60 @@ ssl_init(void)
 		SSL_set_fd(ssl_con,fileno(cout));
 		set_ssl_trace(ssl_con);
 
-		SSL_set_verify(ssl_con,ssl_verify_flag,NULL);
+		SSL_set_verify(ssl_con, ssl_verify_flag,
+			       ssl_verify_flag ? verify_callback : NULL);
 
 		/* Add in any certificates if you want to here ... */
 		if (my_ssl_cert_file) {
 		    if (!SSL_use_certificate_file(ssl_con, my_ssl_cert_file,
 			X509_FILETYPE_PEM)) {
-			fprintf(stderr,"%s: ",my_ssl_cert_file);
-			ERR_print_errors_fp(stderr);
+			if (errno) {
+			    fprintf(stderr, "Error loading CRT, %s: %s\r\n",
+				    strerror(errno), my_ssl_cert_file);
+			} else {
+			    fprintf(stderr, "Error loading CRT %s: %s, %s\r\n",
+				    my_ssl_cert_file,
+				    ERR_func_error_string(ERR_peek_error()),
+				    ERR_reason_error_string(ERR_peek_error()));
+			}
 			exit(1);
 		    } else {
 			if (!my_ssl_key_file)
 			    my_ssl_key_file = my_ssl_cert_file;
 			if (!SSL_use_RSAPrivateKey_file(ssl_con, my_ssl_key_file,
 			    X509_FILETYPE_PEM)) {
-			    fprintf(stderr,"%s: ", my_ssl_key_file);
-			    ERR_print_errors_fp(stderr);
+			    if (errno) {
+				fprintf(stderr, "Error loading KEY, %s: %s\r\n",
+					strerror(errno), my_ssl_key_file);
+			    } else {
+				fprintf(stderr, "Error loading KEY %s: %s, %s\r\n",
+					my_ssl_key_file,
+					ERR_func_error_string(ERR_peek_error()),
+					ERR_reason_error_string(ERR_peek_error()));
+			    }
 			    exit(1);
 			}
 		    }
 		}
 
-		if (SSL_connect(ssl_con)<=0) {
+		ret = SSL_connect(ssl_con);
+		if (ret <= 0) {
 		    static char errbuf[1024];
+		    int err = SSL_get_error(ssl_con, ret);
 
-		    sprintf(errbuf,"ftp: SSL_connect error %s\n",
-				ERR_error_string(ERR_get_error(),NULL));
+		    if (err == SSL_ERROR_SSL && ret < 0)
+			fprintf(stderr, "ftp: Certificates: %s\n",
+				X509_verify_cert_error_string(SSL_get_verify_result(ssl_con)));
+		    errno = errno ? errno : 103;	/* ECONNABORTED */
+		    sprintf(errbuf,"ftp: SSL_connect %s",
+				ERR_reason_error_string(ERR_get_error()));
 		    perror(errbuf);
 		    /* abort time methinks ... */
 		    exit(1);
 		} else {
-		    fprintf(stderr,"[SSL Cipher %s]\n",SSL_get_cipher(ssl_con));
+		    if (verbose)
+			fprintf(stderr,"[SSL Cipher %s]\n",
+				SSL_get_cipher(ssl_con));
 		    fflush(stderr);
 		    ssl_active_flag=1;
 		}
@@ -2187,6 +2274,8 @@ ssl_init(void)
 		    fprintf(stderr, "Data connection security level refused.\n");
 		    return ERROR;
 		}
+		if (verbose && use_tls && ssl_encrypt_data)
+		    fprintf(stderr, "[Encrypted data transfer.]\n");
 	    }
 	}
 	return CONTINUE;
diff -Naurp netkit-ftp-0.17.debian/ftp/main.c netkit-ftp-0.17/ftp/main.c
--- netkit-ftp-0.17.debian/ftp/main.c	2016-12-23 00:05:51.524253061 +0100
+++ netkit-ftp-0.17/ftp/main.c	2017-01-05 15:45:23.885255406 +0100
@@ -132,6 +132,7 @@ int ssl_enabled=1;
 
 char *my_ssl_key_file=NULL;
 char *my_ssl_cert_file=NULL;
+char *my_ssl_cacert_file=NULL;
 
 BIO *bio_err=NULL;
 
@@ -209,12 +210,13 @@ usage(void)
 	printf("   -d                     enable debugging\n");
 #ifdef USE_SSL
 	printf("   -z debug               enable SSL debugging\n");
-	printf("   -z authdebug           enable authentication debugging\n");
+	//printf("   -z authdebug           enable authentication debugging\n");
 	printf("   -z nossl               switch off SSL negotiation\n");
-	printf("   -z certrequired        client certificate is mandatory\n");
+	//printf("   -z certrequired        client certificate is mandatory\n");
 	printf("   -z secure              don't allow non-SSL connections\n");
 	printf("   -z verbose             be verbose about certificates, etc.\n");
 	printf("   -z verify=flags        set the SSL verify flags\n");
+	printf("   -z cacert=ca_file      use CA-certificate in ca_file\n");
 	printf("   -z cert=cert_file      use the certificate(s) in cert_file\n");
 	printf("   -z key=key_file        use the key(s) in key_file\n");
 	printf("   -z cipher=cipher_list  set preferred ciphers to cipher_list\n");
@@ -335,6 +337,12 @@ main(volatile int argc, char **volatile
 				if (strncmp(optarg, "cert=", strlen("cert=")) == 0 ) {
 				    my_ssl_cert_file=optarg+strlen("cert=");
 				}
+				if (strncmp(optarg, "cacert=", strlen("cacert=")) == 0 ) {
+				    my_ssl_cacert_file=optarg+strlen("cacert=");
+				}
+				if (strncmp(optarg, "cipher=", strlen("cipher=")) == 0 ) {
+				    ssl_cipher_list=optarg+strlen("cipher=");
+				}
 				if (strncmp(optarg, "key=", strlen("key=")) == 0 ) {
 				    my_ssl_key_file=optarg+strlen("key=");
 				}
@@ -398,7 +406,13 @@ main(volatile int argc, char **volatile
 	    if (!do_ssleay_init(0)) {
 		fprintf(stderr,"ftp: SSLeay initialisation failed\n");
 		fflush(stderr);
-		ERR_print_errors_fp(stderr);
+
+		if (errno)
+		    perror("Error cause:");
+		else
+		    fprintf(stderr, "Error cause: %s, %s\n",
+			    ERR_func_error_string(ERR_peek_error()),
+			    ERR_reason_error_string(ERR_peek_error()));
 		exit(1);
 	    }
 	}
diff -Naurp netkit-ftp-0.17.debian/ftp/sslapp.c netkit-ftp-0.17/ftp/sslapp.c
--- netkit-ftp-0.17.debian/ftp/sslapp.c	2016-12-23 00:05:49.548345304 +0100
+++ netkit-ftp-0.17/ftp/sslapp.c	2017-01-18 17:41:55.268856150 +0100
@@ -14,8 +14,11 @@
 
 #ifdef USE_SSL
 
+#include <syslog.h>
 #include "sslapp.h"
 
+#include <openssl/rand.h>
+
 SSL_CTX *ssl_ctx;
 SSL *ssl_con;
 int ssl_debug_flag=0;
@@ -27,6 +30,7 @@ int ssl_certsok_flag=0;
 int ssl_cert_required=0;
 int ssl_verbose_flag=0;
 int ssl_disabled_flag=0;
+char *ssl_cacert_file=NULL;
 char *ssl_cert_file=NULL;
 char *ssl_key_file=NULL;
 char *ssl_cipher_list=NULL;
@@ -40,6 +44,7 @@ int
 do_ssleay_init(int server)
 {
   char *p;
+  int ret;
 
   /* make sure we have somewhere we can log errors to */
   if (bio_err==NULL) {
@@ -48,6 +53,11 @@ do_ssleay_init(int server)
 	BIO_set_fp(bio_err,stderr,BIO_NOCLOSE);
       else {
 	if (BIO_write_filename(bio_err,ssl_log_file)<=0) {
+	  if (server)
+	    syslog(LOG_ERR | LOG_DAEMON, "No access to log file %s.",
+		   ssl_log_file);
+	  else
+	    fprintf(stderr, "No logging allowed to %s.\n", ssl_log_file);
 	  /* not a lot we can do */
 	}
       }
@@ -58,9 +68,10 @@ do_ssleay_init(int server)
    * vars are long gone now SSLeay8 has rolled around and we have 
    * a clean interface for doing things
    */
-  if (ssl_debug_flag)
+  if (ssl_debug_flag) {
     BIO_printf(bio_err,"SSL_DEBUG_FLAG on\r\n");
-
+    BIO_flush(bio_err);
+  }
 
   /* init things so we will get meaningful error messages
    * rather than numbers 
@@ -68,19 +79,46 @@ do_ssleay_init(int server)
   SSL_load_error_strings();
 
   SSLeay_add_ssl_algorithms();
-  ssl_ctx=(SSL_CTX *)SSL_CTX_new(SSLv23_method());
 
+  ssl_ctx=(SSL_CTX *)SSL_CTX_new(server ? SSLv23_server_method()
+					: SSLv23_method());
+
+# ifndef BUILD_SSL_CLIENT
   /* we may require a temp 512 bit RSA key because of the
    * wonderful way export things work ... if so we generate
    * one now!
    */
   if (server) {
     if (SSL_CTX_need_tmp_RSA(ssl_ctx)) {
-      RSA *rsa;
+      RSA *rsa = NULL;
+      BIGNUM *exp = NULL;
 
       if (ssl_debug_flag)
 	  BIO_printf(bio_err,"Generating temp (512 bit) RSA key ...\r\n");
+
+#  if OPENSSL_VERSION_NUMBER > 0x00090800fL
+      rsa = RSA_new();
+      if (rsa == NULL)
+	return(0);
+
+      if (ssl_debug_flag && RAND_status() != 1) {
+	BIO_printf(bio_err, "Insufficient seeding of PRNG.\r\n");
+	BIO_flush(bio_err);
+      }
+
+      exp = BN_new();
+      if (exp) {
+	if (BN_set_word(exp, RSA_F4) == 1)
+	  RSA_generate_key_ex(rsa, 512, exp, NULL);
+	    
+	BN_free(exp);
+      }
+#  else /* Not later than 0.9.8. */
       rsa=RSA_generate_key(512,RSA_F4,NULL,NULL);
+#  endif
+      if (rsa == NULL)
+	return(0);
+
       if (ssl_debug_flag)
 	  BIO_printf(bio_err,"Generation of temp (512 bit) RSA key done\r\n");
    
@@ -92,20 +130,25 @@ do_ssleay_init(int server)
 	  BIO_printf(bio_err,"Assigned temp (512 bit) RSA key\r\n");
     }
   }
+# endif /* !BUILD_SSL_CLIENT */
 
   /* also switch on all the interoperability and bug
    * workarounds so that we will communicate with people
    * that cannot read poorly written specs :-)
    */
-  SSL_CTX_set_options(ssl_ctx,SSL_OP_ALL);
+  SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
 
   /* the user can set whatever ciphers they want to use */
+  ret = 1;
   if (ssl_cipher_list==NULL) {
       p=getenv("SSL_CIPHER");
       if (p!=NULL)
-        SSL_CTX_set_cipher_list(ssl_ctx,p);
+        ret = SSL_CTX_set_cipher_list(ssl_ctx,p);
   } else
-      SSL_CTX_set_cipher_list(ssl_ctx,ssl_cipher_list);
+      ret = SSL_CTX_set_cipher_list(ssl_ctx,ssl_cipher_list);
+
+  if (!ret)
+    return(0);
 
   /* for verbose we use the 0.6.x info callback that I got
    * eric to finally add into the code :-) --tjh
@@ -114,27 +157,94 @@ do_ssleay_init(int server)
       SSL_CTX_set_info_callback(ssl_ctx,client_info_callback);
   }
 
+  /* Add any requested CA certificates.  */
+  if (ssl_cacert_file) {
+      errno = 0;
+
+      if (!SSL_CTX_load_verify_locations(ssl_ctx, ssl_cacert_file, NULL)) {
+	  if (errno)
+	      BIO_printf(bio_err, "Error loading CA, %s: %s\r\n",
+			 strerror(errno), ssl_cacert_file);
+	  else {
+	      const char *e = ERR_func_error_string(ERR_peek_error());
+
+	      if (e)
+		  BIO_printf(bio_err, "Error loading CA %s: %s, %s\r\n",
+			     ssl_cacert_file, e,
+			     ERR_reason_error_string(ERR_peek_error()));
+	      else
+		  BIO_printf(bio_err, "Broken CA file: %s\r\n",
+			     ssl_cacert_file);
+	      BIO_flush(bio_err);
+	  }
+	  /* This condition is not desirable, but can only make the
+	     chance of later success decrease, not increase!
+	   */
+	  if (server)
+	      syslog(LOG_NOTICE | LOG_DAEMON,
+		     "Error while loading CA file %s.", ssl_cacert_file);
+      }
+# ifndef BUILD_SSL_CLIENT
+      else if (server) {
+	  STACK_OF(X509_NAME) *names;
+
+	  if (ssl_debug_flag)
+	      BIO_printf(bio_err, "Preparing client CA list.\r\n");
+
+	  names = SSL_load_client_CA_file(ssl_cacert_file);
+	  if (names)
+	      SSL_CTX_set_client_CA_list(ssl_ctx, names);
+	  else
+	      BIO_printf(bio_err, "Failed to load client CA list.\r\n");
+      }
+# endif /* !BUILD_SSL_CLIENT */
+  }
+
   /* Add in any certificates if you want to here ... */
   if (ssl_cert_file) {
-      if (!SSL_CTX_use_certificate_file(ssl_ctx, ssl_cert_file, 
-		      X509_FILETYPE_PEM)) {
-	  BIO_printf(bio_err,"Error loading %s: ",ssl_cert_file);
-	  ERR_print_errors(bio_err);
-	  BIO_printf(bio_err,"\r\n");
+      errno = 0;
+
+      if (!SSL_CTX_use_certificate_chain_file(ssl_ctx, ssl_cert_file)) {
+	  if (errno) {
+	      BIO_printf(bio_err, "Error loading CRT, %s: %s\r\n",
+			 strerror(errno), ssl_cert_file);
+	  } else {
+	      BIO_printf(bio_err, "Error loading CRT %s: %s, %s\r\n",
+			 ssl_cert_file,
+			 ERR_func_error_string(ERR_peek_error()),
+			 ERR_reason_error_string(ERR_peek_error()));
+	  }
+	  BIO_flush(bio_err);
 	  return(0);
       } else {
 	  if (!ssl_key_file)
 	      ssl_key_file = ssl_cert_file;
 	  if (!SSL_CTX_use_RSAPrivateKey_file(ssl_ctx, ssl_key_file,
 		      X509_FILETYPE_PEM)) {
-	      BIO_printf(bio_err,"Error loading %s: ",ssl_key_file);
-	      ERR_print_errors(bio_err);
-	      BIO_printf(bio_err,"\r\n");
+	      if (errno) {
+		  BIO_printf(bio_err, "Error loading KEY, %s: %s\r\n",
+			     strerror(errno), ssl_key_file);
+	      } else {
+		  BIO_printf(bio_err, "Error loading KEY %s: %s, %s\r\n",
+			     ssl_key_file,
+			     ERR_func_error_string(ERR_peek_error()),
+			     ERR_reason_error_string(ERR_peek_error()));
+	      }
+	      BIO_flush(bio_err);
 	      return(0);
 	  }
       }
   }
 
+# ifndef BUILD_SSL_CLIENT
+  if (server) {
+    const char *id_ctx = "ftpd-ssl";
+
+    SSL_CTX_set_session_id_context(ssl_ctx, (const unsigned char *) id_ctx,
+				   strlen(id_ctx));
+  }
+# endif /* !BUILD_SSL_CLIENT */
+
   /* make sure we will find certificates in the standard
    * location ... otherwise we don't look anywhere for
    * these things which is going to make client certificate
@@ -150,6 +260,9 @@ do_ssleay_init(int server)
   SSL_set_verify(ssl_con,ssl_verify_flag,client_verify_callback);
 #endif
 
+  if (ssl_debug_flag)
+    BIO_flush(bio_err);
+
   return(1);
 }
 
diff -Naurp netkit-ftp-0.17.debian/ftp/sslapp.h netkit-ftp-0.17/ftp/sslapp.h
--- netkit-ftp-0.17.debian/ftp/sslapp.h	2016-12-23 00:05:50.964279178 +0100
+++ netkit-ftp-0.17/ftp/sslapp.h	2017-01-15 22:43:03.686540857 +0100
@@ -48,6 +48,7 @@ extern int ssl_cert_required;
 extern int ssl_certsok_flag;
 
 extern char *ssl_log_file; 
+extern char *ssl_cacert_file; 
 extern char *ssl_cert_file; 
 extern char *ssl_key_file;
 extern char *ssl_cipher_list;
diff -Naurp netkit-ftp-0.17.debian/ftp/ssl_port.h netkit-ftp-0.17/ftp/ssl_port.h
--- netkit-ftp-0.17.debian/ftp/ssl_port.h	2016-12-23 00:05:49.548345304 +0100
+++ netkit-ftp-0.17/ftp/ssl_port.h	2017-01-03 14:18:05.775193079 +0100
@@ -43,6 +43,7 @@ extern SSL *ssl_data_con;
 extern int ssl_data_active_flag;
 
 extern char *my_ssl_cert_file;
+extern char *my_ssl_cacert_file;
 extern char *my_ssl_key_file;
 extern int ssl_certsok_flag;