diff -Nrup linux-ftpd-0.17.orig/ftpd/Makefile linux-ftpd-0.17/ftpd/Makefile
--- linux-ftpd-0.17.orig/ftpd/Makefile	1999-12-12 13:04:58.000000000 -0500
+++ linux-ftpd-0.17/ftpd/Makefile	2005-11-06 08:19:35.000000000 -0500
@@ -1,7 +1,7 @@
 include ../MCONFIG
 
-CFLAGS+=-I../support
-LIBS+=-L../support -lsupport
+CFLAGS+=-I../support -DUSE_SSL -g
+LIBS+=-L../support -lsupport -lssl -lcrypto
 
 
 OBJS=ftpd.o ftpcmd.o logutmp.o logwtmp.o popen.o
diff -Nrup linux-ftpd-0.17.orig/ftpd/ftpcmd.y linux-ftpd-0.17/ftpd/ftpcmd.y
--- linux-ftpd-0.17.orig/ftpd/ftpcmd.y	1999-10-08 22:32:12.000000000 -0400
+++ linux-ftpd-0.17/ftpd/ftpcmd.y	2005-11-06 08:19:35.000000000 -0500
@@ -1,3 +1,15 @@
+/* 
+ * The modifications to support SSLeay we done by Tim Hudson
+ * tjh@mincom.oz.au
+ *
+ * You can do whatever you like with these patches except pretend that
+ * you wrote them. 
+ *
+ * Email ssl-users-request@mincom.oz.au to get instructions on how to
+ * join the mailing list that discusses SSLeay and also these patches.
+ *
+ */
+
 /*
  * Copyright (c) 1985, 1988, 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -92,6 +104,19 @@ extern  char tmpline[];
 extern	int portcheck;
 extern	struct sockaddr_in his_addr;
 
+#ifdef USE_SSL
+/*#include "ssl_port.h"*/
+typedef struct ssl_st SSL;
+int     SSL_write(SSL *ssl,const char *buf,int num);
+extern int do_ssl_start(void);
+extern int ssl_secure_flag;
+extern int ssl_active_flag;
+extern SSL *ssl_con;
+#define FFLUSH(X)         (ssl_active_flag && (((X)==cin)||((X)==cout)) ? 1 : fflush((X)) )
+#define GETC(X)           (ssl_active_flag && (((X)==cin)||((X)==cout)) ? ssl_getc(ssl_con) : getc((X)) )
+extern FILE *cin, *cout;
+#endif /* USE_SSL */
+
 off_t	restart_point;
 
 static	int cmd_type;
@@ -129,7 +154,7 @@ extern struct tab sitetab[];
 	STAT	HELP	NOOP	MKD	RMD	PWD
 	CDUP	STOU	SMNT	SYST	SIZE	MDTM
 
-	UMASK	IDLE	CHMOD
+	UMASK	IDLE	CHMOD   AUTH
 
 	LEXERR
 
@@ -138,7 +163,7 @@ extern struct tab sitetab[];
 
 %type	<i> check_login octal_number byte_size
 %type	<i> struct_code mode_code type_code form_code
-%type	<s> pathstring pathname password username
+%type	<s> pathstring pathname password username auth_type
 %type	<i> host_port
 
 %start	cmd_list
@@ -156,13 +181,43 @@ cmd_list
 	;
 
 cmd
-	: USER SP username CRLF
+	: AUTH SP auth_type CRLF
+		{
+			if (!strncmp((char *) $3,"SSL",3)) {
+#ifdef USE_SSL
+				reply(334, "AUTH SSL OK.");
+
+				/* now do all the hard work :-) */
+				do_ssl_start();
+
+#else /* !USE_SSL */
+				reply(504,"AUTH type not supported.");
+#endif /* USE_SSL */
+			} else {
+				reply(504,"AUTH type not supported.");
+			}
+			if ($3 != NULL)
+				free((char *)$3);
+		}
+	| USER SP username CRLF
 		{
+#ifdef USE_SSL
+			if (ssl_secure_flag && !ssl_active_flag) {
+			    reply(504,"SSL is mandatory.");
+			    break;
+			}
+#endif /* USE_SSL */
 			user($3);
 			free($3);
 		}
 	| PASS SP password CRLF
 		{
+#ifdef USE_SSL
+			if (ssl_secure_flag && !ssl_active_flag) {
+			    reply(504,"SSL is mandatory.");
+			    break;
+			}
+#endif /* USE_SSL */
 			pass($3);
 			memset($3, 0, strlen($3));
 			free($3);
@@ -607,6 +662,10 @@ username
 	: STRING
 	;
 
+auth_type
+	: STRING
+	;
+
 password
 	: /* empty */
 		{
@@ -841,6 +900,7 @@ struct tab {
 };
 
 struct tab cmdtab[] = {		/* In order defined in RFC 765 */
+        { "AUTH", AUTH, STR1, 1,	"<sp> auth_type" },
 	{ "USER", USER, STR1, 1,	"<sp> username" },
 	{ "PASS", PASS, ZSTR1, 1,	"<sp> password" },
 	{ "ACCT", ACCT, STR1, 0,	"(specify account)" },
@@ -923,6 +983,7 @@ char * ftpd_getline(char *s, int n, FILE
 {
 	int c;
 	register char *cs;
+	char buf[16];
 
 	cs = s;
 /* tmpline may contain saved command from urgent mode interruption */
@@ -938,23 +999,34 @@ char * ftpd_getline(char *s, int n, FILE
 		if (c == 0)
 			tmpline[0] = '\0';
 	}
-	while ((c = getc(iop)) != EOF) {
+	while ((c = GETC(iop)) != EOF) {
 		c &= 0377;
 		if (c == IAC) {
-		    if ((c = getc(iop)) != EOF) {
+		    if ((c = GETC(iop)) != EOF) {
 			c &= 0377;
 			switch (c) {
 			case WILL:
 			case WONT:
-				c = getc(iop);
-				printf("%c%c%c", IAC, DONT, 0377&c);
-				(void) fflush(stdout);
+				c = GETC(iop);
+				sprintf(buf,"%c%c%c", IAC, DONT, 0377&c);
+#ifdef USE_SSL
+				if (ssl_active_flag)
+					SSL_write(ssl_con,buf,strlen(buf));
+				else
+#endif /* USE_SSL */
+					fwrite(buf,strlen(buf),1,stdout);
+				(void) FFLUSH(stdout);
 				continue;
 			case DO:
 			case DONT:
-				c = getc(iop);
-				printf("%c%c%c", IAC, WONT, 0377&c);
-				(void) fflush(stdout);
+				c = GETC(iop);
+				sprintf(buf,"%c%c%c", IAC, WONT, 0377&c);
+#ifdef USE_SSL
+				if (ssl_active_flag)
+					SSL_write(ssl_con,buf,strlen(buf));
+				else
+#endif /* USE_SSL */
+				(void) FFLUSH(stdout);
 				continue;
 			case IAC:
 				break;
diff -Nrup linux-ftpd-0.17.orig/ftpd/ftpd.c linux-ftpd-0.17/ftpd/ftpd.c
--- linux-ftpd-0.17.orig/ftpd/ftpd.c	2000-07-22 23:34:56.000000000 -0400
+++ linux-ftpd-0.17/ftpd/ftpd.c	2005-11-06 09:36:51.000000000 -0500
@@ -1,3 +1,15 @@
+/* 
+ * The modifications to support SSLeay were done by Tim Hudson
+ * tjh@cryptsoft.com
+ *
+ * You can do whatever you like with these patches except pretend that
+ * you wrote them. 
+ *
+ * Email ssl-users-request@lists.cryptsoft.com to get instructions on how to
+ * join the mailing list that discusses SSLeay and also these patches.
+ *
+ */
+
 /*
  * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
  *	The Regents of the University of California.  All rights reserved.
@@ -126,6 +138,41 @@ typedef unsigned int useconds_t;
 #include "pathnames.h"
 #include "extern.h"
 
+#ifdef USE_SSL
+
+#include "sslapp.c"
+
+BIO *bio_err;
+SSL *ssl_data_con;
+int ssl_auto_login=0;
+
+static char *auth_ssl_name=NULL;
+FILE *cin, *cout;
+
+int ssl_data_active_flag=0;
+
+/* for the moment this is a compile time option only --tjh */
+int ssl_encrypt_data=1;
+
+char ssl_file_path[1024];    /* don't look at that nasty value to the left */
+
+X509 *ssl_public_cert;
+RSA *ssl_private_key;
+
+static char *my_ssl_key_file=NULL;
+static char *my_ssl_cert_file=NULL;
+
+#include "ssl_port.h"
+
+int 
+ssl_getc(SSL *ssl_con);
+static int 
+ssl_putc(SSL *ssl_con,int oneint);
+static int
+ssl_putc_flush(SSL *ssl_con);
+
+#endif /* USE_SSL */
+
 #ifdef __STDC__
 #include <stdarg.h>
 #else
@@ -294,7 +341,7 @@ main(int argc, char *argv[], char **envp
 	socklen_t addrlen;
 	char *cp, line[LINE_MAX];
 	FILE *fd;
-	const char *argstr = "AdDhlMSt:T:u:UvP";
+	const char *argstr = "AdDhlMSt:T:u:UvPz:";
 	struct hostent *hp;
 
 #ifdef __linux__
@@ -390,12 +437,78 @@ main(int argc, char *argv[], char **envp
 			debug = 1;
 			break;
 
+#ifdef USE_SSL
+                case 'z':
+		        if (strcmp(optarg, "debug") == 0 ) {
+			    ssl_debug_flag=1;
+			}
+		        if (strcmp(optarg, "verbose") == 0 ) {
+			    ssl_verbose_flag=1;
+			}
+		        if (strcmp(optarg, "ssl") == 0 ) {
+			    ssl_only_flag=1;
+			}
+		        if (strcmp(optarg, "secure") == 0 ) {
+			    ssl_secure_flag=1;
+			}
+                        if (strcmp(optarg, "certsok") == 0) {
+                            ssl_certsok_flag=1;
+                        }
+		        if (strncmp(optarg, "verify=", strlen("verify=")) == 0 ) {
+			    ssl_verify_flag=atoi(optarg+strlen("verify="));
+
+			}
+		        if (strncmp(optarg, "cert=", strlen("cert=")) == 0 ) {
+			    my_ssl_cert_file=optarg+strlen("cert=");
+			}
+		        if (strncmp(optarg, "key=", strlen("key=")) == 0 ) {
+			    my_ssl_key_file=optarg+strlen("key=");
+			}
+			/* we have swallowed an extra arg */
+			/*argc--;
+			argv++;*/
+			break;
+#endif /* USE_SSL */
+
 		default:
 			warnx("unknown flag -%c ignored", optopt);
 			break;
 		}
 	}
 
+#ifdef USE_SSL
+        /* make sure we have access to the required certificate
+	 * and key files now ... before we perhaps chroot and 
+	 * do the other "muck" for anon-ftp style setup ... though
+	 * why we want to run SSL for anon I don't know
+	 */
+
+        {
+	    /* keep the macros that are common between the client
+	     * and the server happy 
+	     */
+	    cin=stdin;
+	    cout=stderr;
+
+	    /* do things the "default" way */
+	    if (my_ssl_cert_file==NULL) {
+		snprintf(ssl_file_path, sizeof(ssl_file_path), "%s/%s", X509_get_default_cert_dir(),
+			    "ftpd.pem");
+		ssl_cert_file=ssl_file_path;
+	    } else {
+	    	ssl_cert_file=my_ssl_cert_file;
+	    }
+
+	    if (!do_ssleay_init(1)) {
+		fprintf(stderr,"ftpd: SSLeay initialisation failed\n");
+		fflush(stderr);
+		sleep(1);
+		exit(1);
+	    }
+
+        }
+#endif /* USE_SSL */
+
 	(void) freopen(_PATH_DEVNULL, "w", stderr);
 
 	/*
@@ -552,16 +665,16 @@ main(int argc, char *argv[], char **envp
 	/* Make sure hostname is fully qualified. */
 	hp = gethostbyname(hostname);
 	if (hp != NULL)
-		strcpy(hostname, hp->h_name);
+		strncpy(hostname, hp->h_name, sizeof(hostname));
 
 	if (multihome) {
 		hp = gethostbyaddr((char *) &ctrl_addr.sin_addr,
 		    sizeof (struct in_addr), AF_INET);
 		if (hp != NULL) {
-			strcpy(dhostname, hp->h_name);
+			strncpy(dhostname, hp->h_name, sizeof(dhostname));
 		} else {
 			/* Default. */
-			strcpy(dhostname, inet_ntoa(ctrl_addr.sin_addr));
+			strncpy(dhostname, inet_ntoa(ctrl_addr.sin_addr), sizeof(dhostname));
 		}
 	}
 
@@ -648,6 +761,9 @@ static int login_attempts;	/* number of 
 static int askpasswd;		/* had user command, ask for passwd */
 static char curname[16];	/* current USER name */
 
+int
+good_ssl_user(char *name);
+
 /*
  * USER command.
  * Sets global passwd pointer pw if named account exists and is acceptable;
@@ -718,6 +834,12 @@ void user(char *name)
 		strncpy(curname, name, sizeof(curname)-1);
 		curname[sizeof(curname)-1] = '\0';
 	}
+#ifdef USE_SSL
+        if (pw && good_ssl_user(name)) {
+                reply(331, "Send dummy password to login.");
+                ssl_auto_login = 1;
+        } else
+#endif
 #ifdef SKEY
 	if (!skey_haskey(name)) {
 		char *myskey, *skey_keyinfo __P((char *name));
@@ -797,7 +919,11 @@ void pass(char *passwd)
 		return;
 	}
 	askpasswd = 0;
-	if (!guest) {		/* "ftp" is only account allowed no password */
+	if (!guest
+#ifdef USE_SSL
+             && !ssl_auto_login
+#endif
+	   ) {		/* "ftp" is only account allowed no password */
 		if (pw == NULL) {
 			useconds_t us;
 
@@ -1072,6 +1198,15 @@ void retrieve(const char *cmd, const cha
 		  (restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode)));
 	if ((cmd == 0) && stats)
 		logxfer(name, st.st_size, start);
+
+#ifdef USE_SSL
+	if (ssl_data_active_flag && (ssl_data_con!=NULL)) {
+	    SSL_free(ssl_data_con);
+	    ssl_data_active_flag=0;
+	    ssl_data_con=NULL;
+	}
+#endif /* USE_SSL */
+
 	(void) fclose(dout);
 	data = -1;
 	pdata = -1;
@@ -1276,8 +1411,72 @@ static FILE * dataconn(const char *name,
 		(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
 		    sizeof(int));
 #endif
+#ifdef USE_SSL
+		/* time to negotiate SSL on the data connection ...
+		 * do this via SSL_accept (as we are still the server
+		 * even though things are started around the other way)
+		 * 
+		 * note: we really *must* make sure the session stuff
+		 *       is copied correctly as we cannot afford a full
+		 *       SSL negotiation for each data socket!
+		 */
+		/* TODO XXXX fill in the blanks :-)
+		 */
+		ssl_data_active_flag=0;
+		if (ssl_active_flag && ssl_encrypt_data) {
+		    /* do SSL */
+
+		    reply(150, "Opening %s mode SSL data connection for %s%s.",
+			 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+
+		    if (ssl_data_con!=NULL) {
+		      SSL_free(ssl_data_con);
+		      ssl_data_con=NULL;
+		    }
+		    ssl_data_con=(SSL *)SSL_new(ssl_ctx);
+
+		    /* copy session details ... */
+		    SSL_copy_session_id(ssl_data_con,ssl_con);
+
+		    /* for 0.5.2 - want to change the timeout value etc ... */
+
+		    SSL_set_fd(ssl_data_con,pdata);
+		    SSL_set_verify(ssl_data_con,ssl_verify_flag,NULL);
+
+		    /* if is "safe" to read ahead */
+		    /* SSL_set_read_ahead(ssl_data_con,1); */
+
+		    if (ssl_debug_flag)
+			BIO_printf(bio_err,"===>START SSL_accept on DATA\n");
+
+		    if (SSL_accept(ssl_data_con)<=0) {
+			static char errbuf[1024];
+
+			snprintf(errbuf, sizeof(errbuf), "ftpd: SSL_accept DATA error %s\n",
+				    ERR_error_string(ERR_get_error(),NULL));
+			perror_reply(425, errbuf);
+			/* abort time methinks ... */
+			fclose(file);
+			return NULL;
+		    } else {
+			if (ssl_debug_flag) {
+			    BIO_printf(bio_err,"[SSL DATA Cipher %s]\n",
+					    SSL_get_cipher(ssl_con));
+			}
+			ssl_data_active_flag=1;
+		    }
+
+		    if (ssl_debug_flag)
+			BIO_printf(bio_err,"===>DONE SSL_accept on DATA\n");
+
+		} else {
+		    reply(150, "Opening %s mode data connection for %s%s.",
+			 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+		}
+#else /* !USE_SSL */
 		reply(150, "Opening %s mode data connection for '%s'%s.",
 		     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+#endif /* USE_SSL */
 		return (fdopen(pdata, mode));
 	}
 	if (data >= 0) {
@@ -1327,8 +1526,71 @@ static FILE * dataconn(const char *name,
 		data = -1;
 		return (NULL);
 	}
+#ifdef USE_SSL
+        /* time to negotiate SSL on the data connection ...
+	 * do this via SSL_accept (as we are still the server
+	 * even though things are started around the other way)
+	 * 
+	 * note: we really *must* make sure the session stuff
+	 *       is copied correctly as we cannot afford a full
+	 *       SSL negotiation for each data socket!
+	 */
+	/* TODO XXXX fill in the blanks :-)
+	 */
+	ssl_data_active_flag=0;
+	if (ssl_active_flag && ssl_encrypt_data) {
+	    /* do SSL */
+
+	    reply(150, "Opening %s mode SSL data connection for %s%s.",
+		 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+
+	    if (ssl_data_con!=NULL) {
+	      SSL_free(ssl_data_con);
+	      ssl_data_con=NULL;
+	    }
+	    ssl_data_con=(SSL *)SSL_new(ssl_ctx);
+
+            /* copy session details ... */
+	    SSL_copy_session_id(ssl_data_con,ssl_con);
+
+	    /* for 0.5.2 - want to change the timeout value etc ... */
+
+	    SSL_set_fd(ssl_data_con,data);
+	    SSL_set_verify(ssl_data_con,ssl_verify_flag,NULL);
+
+	    /* if is "safe" to read ahead */
+            /* SSL_set_read_ahead(ssl_data_con,1); */
+
+	    if (ssl_debug_flag)
+		BIO_printf(bio_err,"===>START SSL_accept on DATA\n");
+
+	    if (SSL_accept(ssl_data_con)<=0) {
+                static char errbuf[1024];
+
+	        snprintf(errbuf, sizeof(errbuf), "ftpd: SSL_accept DATA error %s\n",
+			    ERR_error_string(ERR_get_error(),NULL));
+		perror_reply(425, errbuf);
+		/* abort time methinks ... */
+		fclose(file);
+		return NULL;
+	    } else {
+		if (ssl_debug_flag)
+		    BIO_printf(bio_err,"[SSL DATA Cipher %s]\n",
+			            SSL_get_cipher(ssl_con));
+		ssl_data_active_flag=1;
+	    }
+
+	    if (ssl_debug_flag) 
+		BIO_printf(bio_err,"===>DONE SSL_accept on DATA\n");
+
+	} else {
+	    reply(150, "Opening %s mode data connection for %s%s.",
+		 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+	}
+#else /* !USE_SSL */
 	reply(150, "Opening %s mode data connection for '%s'%s.",
 	     type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
+#endif /* USE_SSL */
 	return (file);
 }
 
@@ -1357,11 +1619,11 @@ static void send_data(FILE *instr, FILE 
 			if (c == '\n') {
 				if (ferror(outstr))
 					goto data_err;
-				(void) putc('\r', outstr);
+				(void) DATAPUTC('\r', outstr);
 			}
-			(void) putc(c, outstr);
+			(void) DATAPUTC(c, outstr);
 		}
-		fflush(outstr);
+		DATAFLUSH(outstr);
 		transflag = 0;
 		if (ferror(instr))
 			goto file_err;
@@ -1379,7 +1641,11 @@ static void send_data(FILE *instr, FILE 
 		netfd = fileno(outstr);
 		filefd = fileno(instr);
 
-		if (isreg && filesize < (off_t)16 * 1024 * 1024) {
+		if (
+#ifdef USE_SSL
+		    !ssl_data_active_flag &&
+#endif /* USE_SSL */
+		    isreg && filesize < (off_t)16 * 1024 * 1024) {
 			buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd,
 				   (off_t)0);
 			if (buf==MAP_FAILED || buf==NULL) {
@@ -1420,6 +1686,13 @@ oldway:
 		/* failure is harmless */ 
 		}
 #endif	
+#ifdef USE_SSL
+                if (ssl_data_active_flag) {
+		    while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
+			SSL_write(ssl_data_con, buf, cnt) == cnt)
+			    byte_count += cnt;
+		} else
+#endif /* USE_SSL */
 		while ((cnt = read(filefd, buf, size)) > 0 &&
 		    write(netfd, buf, cnt) == cnt)
 			byte_count += cnt;
@@ -1478,6 +1751,16 @@ static int receive_data(FILE *instr, FIL
 	case TYPE_L:
 		signal (SIGALRM, lostconn);
 
+#ifdef USE_SSL
+                if (ssl_data_active_flag) {
+		    while ((cnt = SSL_read(ssl_data_con,buf,sizeof buf)) > 0) {
+			    if (write(fileno(outstr), buf, cnt) != cnt)
+				    goto file_err;
+			    byte_count += cnt;
+		    }
+		} else 
+#endif /* !USE_SSL */
+                {
 		do {
 			(void) alarm ((unsigned) timeout);
 			cnt = read(fileno(instr), buf, sizeof(buf));
@@ -1489,6 +1772,7 @@ static int receive_data(FILE *instr, FIL
 				byte_count += cnt;
 			}
 		} while (cnt > 0);
+		}
 		if (cnt < 0)
 			goto data_err;
 		transflag = 0;
@@ -1500,14 +1784,14 @@ static int receive_data(FILE *instr, FIL
 		return (-1);
 
 	case TYPE_A:
-		while ((c = getc(instr)) != EOF) {
+		while ((c = DATAGETC(instr)) != EOF) {
 			byte_count++;
 			if (c == '\n')
 				bare_lfs++;
 			while (c == '\r') {
 				if (ferror(outstr))
 					goto data_err;
-				if ((c = getc(instr)) != '\n') {
+				if ((c = DATAGETC(instr)) != '\n') {
 					(void) putc ('\r', outstr);
 					if (c == '\0' || c == EOF)
 						goto contin2;
@@ -1644,12 +1928,33 @@ reply(int n, const char *fmt, ...)
 reply(int n, char *fmt, va_dcl va_alist)
 #endif
 {
+#ifdef USE_SSL
+        char outputbuf[2048];        /* allow for a 2k command string */
+#endif /* USE_SSL */
 	va_list ap;
 #ifdef __STDC__
 	va_start(ap, fmt);
 #else
 	va_start(ap);
 #endif
+#ifdef USE_SSL
+        /* assemble the output into a buffer, checking for length*/
+	sprintf(outputbuf,"%d ",n);
+	vsnprintf(outputbuf+strlen(outputbuf),sizeof(outputbuf)-(strlen(outputbuf) + 3), fmt, ap);
+	strcat(outputbuf,"\r\n");
+
+	if (ssl_debug_flag)
+	    BIO_printf(bio_err,"\n<--- %s",outputbuf);
+
+	if (ssl_active_flag) {
+	    SSL_write(ssl_con,outputbuf,strlen(outputbuf));
+        } else {
+	    fprintf(stdout,"%s",outputbuf);
+	    fflush(stdout);
+	}
+	if (debug)
+	    syslog(LOG_DEBUG, "<--- %s ", outputbuf);
+#else /* !USE_SSL */
 	(void)printf("%d ", n);
 	(void)vprintf(fmt, ap);
 	(void)printf("\r\n");
@@ -1658,6 +1963,8 @@ reply(int n, char *fmt, va_dcl va_alist)
 		syslog(LOG_DEBUG, "<--- %d ", n);
 		vsyslog(LOG_DEBUG, fmt, ap);
 	}
+#endif /* USE_SSL */
+	va_end(ap);
 }
 
 void
@@ -1670,12 +1977,34 @@ lreply(n, fmt, va_alist)
 	va_dcl
 #endif
 {
+#ifdef USE_SSL
+        char outputbuf[2048];        /* allow for a 2k command string */
+#endif /* USE_SSL */
 	va_list ap;
 #ifdef __STDC__
 	va_start(ap, fmt);
 #else
 	va_start(ap);
 #endif
+
+#ifdef USE_SSL
+        /* assemble the output into a buffer */
+	sprintf(outputbuf,"%d- ",n);
+	vsnprintf(outputbuf+strlen(outputbuf), sizeof(outputbuf)-(strlen(outputbuf) + 3), fmt, ap);
+	strcat(outputbuf,"\r\n");
+
+	if (ssl_debug_flag) 
+	    BIO_printf(bio_err,"\n<--- %s",outputbuf);
+
+	if (ssl_active_flag) {
+	    SSL_write(ssl_con,outputbuf,strlen(outputbuf));
+        } else {
+	    fprintf(stdout,"%s",outputbuf);
+	    fflush(stdout);
+	}
+	if (debug)
+	    syslog(LOG_DEBUG, "<--- %s ", outputbuf);
+#else /* !USE_SSL */
 	(void)printf("%d- ", n);
 	(void)vprintf(fmt, ap);
 	(void)printf("\r\n");
@@ -1684,6 +2013,8 @@ lreply(n, fmt, va_alist)
 		syslog(LOG_DEBUG, "<--- %d- ", n);
 		vsyslog(LOG_DEBUG, fmt, ap);
 	}
+#endif /* USE_SSL */
+	va_end(ap);
 }
 
 static void ack(const char *s)
@@ -2046,6 +2377,7 @@ void send_file_list(const char *whichf)
 	volatile int simple = 0;
 	volatile int freeglob = 0;
 	glob_t gl;
+	char buf[1024];
 
 	/* XXX: should the { go away if __linux__? */
 	if (strpbrk(whichf, "~{[*?") != NULL) {
@@ -2106,8 +2438,14 @@ void send_file_list(const char *whichf)
 					goto out;
 				transflag++;
 			}
-			fprintf(dout, "%s%s\n", dirname,
+			snprintf(buf, sizeof(buf), "%s%s\n", dirname,
 				type == TYPE_A ? "\r" : "");
+#ifdef USE_SSL
+			if (ssl_active_flag)
+				SSL_write(ssl_data_con,buf,strlen(buf));
+		    	else
+#endif /* USE_SSL */
+				fwrite(buf,strlen(buf),1,dout);
 			byte_count += strlen(dirname) + 1;
 			continue;
 		} else if (!S_ISDIR(st.st_mode))
@@ -2149,11 +2487,17 @@ void send_file_list(const char *whichf)
 					transflag++;
 				}
 				if (nbuf[0] == '.' && nbuf[1] == '/')
-					fprintf(dout, "%s%s\n", &nbuf[2],
+				        sprintf(buf, "%s%s\n", &nbuf[2],
 						type == TYPE_A ? "\r" : "");
 				else
-					fprintf(dout, "%s%s\n", nbuf,
+				        sprintf(buf, "%s%s\n", nbuf,
 						type == TYPE_A ? "\r" : "");
+#ifdef USE_SSL
+				if (ssl_active_flag)
+				  SSL_write(ssl_data_con,buf,strlen(buf));
+				else
+#endif /* USE_SSL */
+				  fwrite(buf,strlen(buf),1,dout);
 				byte_count += strlen(nbuf) + 1;
 			}
 		}
@@ -2169,6 +2513,13 @@ void send_file_list(const char *whichf)
 
 	transflag = 0;
 	if (dout != NULL)
+#ifdef USE_SSL
+                if (ssl_data_active_flag && (ssl_data_con!=NULL)) {
+		    SSL_free(ssl_data_con);
+		    ssl_data_active_flag=0;
+		    ssl_data_con=NULL;
+		}
+#endif /* USE_SSL */
 		(void) fclose(dout);
 	data = -1;
 	pdata = -1;
@@ -2252,3 +2603,223 @@ static int check_host(struct sockaddr_in
 }
 #endif	/* TCPWRAPPERS */
 
+#ifdef USE_SSL
+
+static 
+int
+verify_callback(int ok,
+		X509_STORE_CTX *ctx);
+
+int
+do_ssl_start(void)
+{
+    static char errstr[1024];
+
+    if (ssl_debug_flag)
+	BIO_printf(bio_err,"do_ssl_start triggered\n");
+
+    /* do the SSL stuff now ... before we play with pty's */
+    ssl_con=(SSL *)SSL_new(ssl_ctx);
+
+    /* we are working with stdin (inetd based) by default */
+    SSL_set_fd(ssl_con,0);
+
+#if 0
+    if (SSL_use_RSAPrivateKey(ssl_con,ssl_private_key)==0) {
+        snprintf(errstr, sizeof(errstr), "ftpd: SSL_use_RSAPrivateKey %s",ERR_error_string(ERR_get_error(),NULL));
+	perror_reply(421, errstr);
+	dologout(1);
+    }
+
+    if (SSL_use_certificate(ssl_con,ssl_public_cert)==0) {
+        snprintf(errstr, sizeof(errstr), "ftpd: SSL_use_certificate %s",ERR_error_string(ERR_get_error(),NULL));
+	perror_reply(421, errstr);
+	dologout(1);
+    }
+#endif
+
+    SSL_set_verify(ssl_con,ssl_verify_flag,
+	    ssl_certsok_flag ? verify_callback : NULL);
+
+    if (SSL_accept(ssl_con)<=0) {
+	snprintf(errstr, sizeof(errstr), "ftpd: SSL_accept %s",ERR_error_string(ERR_get_error(),NULL));
+
+	perror_reply(421, errstr);
+	dologout(1);
+
+	SSL_free(ssl_con);
+	ssl_con=NULL;
+
+	/* we will probably want to know this sort of stuff ...
+	 * at least for the moment I'd like to keep track of
+	 * who is using SSL - later I will probably make this
+	 * just a debug option and only log after the user has
+	 * actually connected --tjh
+	 */
+	if (logging)
+	    syslog(LOG_NOTICE, "SSL FAILED WITH %s", remotehost);
+
+    } else {
+	ssl_active_flag=1;
+
+	if (logging) {
+            if (auth_ssl_name)
+                syslog(LOG_NOTICE, "SSL SUCCEEDED WITH %s as %s", remotehost,
+                    auth_ssl_name);
+            else
+                syslog(LOG_NOTICE, "SSL SUCCEEDED WITH %s", remotehost);
+	}
+    }
+
+    /* ssl_fprintf calls require that this be null to test
+     * for being an ssl stream
+     */
+    if (!ssl_active_flag) {
+	if (ssl_con!=NULL)
+	  SSL_free(ssl_con);
+	ssl_con=NULL;
+    }
+
+    return 0;
+
+}
+
+/* we really shouldn't have code like this! --tjh */
+int 
+ssl_getc(SSL *ssl_con)
+{
+    char onebyte;
+
+    if (SSL_read(ssl_con,&onebyte,1)!=1)
+      return -1;
+    else {
+	if (ssl_debug_flag)
+	    BIO_printf(bio_err,"ssl_getc: SSL_read %d (%c) ",onebyte & 0xff,isprint(onebyte)?onebyte:'.');
+	return onebyte & 0xff;
+    }
+}
+
+
+/* got back to this an implemented some rather "simple" buffering */
+static char putc_buf[BUFSIZ];
+static int putc_buf_pos=0;
+
+static int
+ssl_putc_flush(SSL *ssl_con)
+{
+    if (putc_buf_pos>0) {
+	if (SSL_write(ssl_con,putc_buf,putc_buf_pos)!=putc_buf_pos) {
+	    if (ssl_debug_flag) 
+		BIO_printf(bio_err,"ssl_putc_flush: WRITE FAILED\n");
+	    putc_buf_pos=0;
+	    return -1;
+	}
+    }
+    putc_buf_pos=0;
+    return 0;
+}
+
+static int 
+ssl_putc(SSL *ssl_con,int oneint)
+{
+    char onebyte;
+
+    onebyte = oneint & 0xff;
+
+    /* make sure there is space */
+    if (putc_buf_pos>=BUFSIZ) 
+	if (ssl_putc_flush(ssl_con)!=0)
+	  return EOF;
+    putc_buf[putc_buf_pos++]=onebyte;
+
+    return onebyte;
+}
+
+static 
+int
+verify_callback(int ok,
+		X509_STORE_CTX *ctx)
+{
+    int depth,error;
+    X509 *xs;
+
+    depth=ctx->error_depth;
+    error=ctx->error;
+    xs=X509_STORE_CTX_get_current_cert(ctx);
+
+    /*
+     * If the verification fails, then don't remember the name.  However,
+     * if we don't require a certificate, then return success which will
+     * still allow us to set up an encrypted session.
+     *
+     */
+    if (!ok) {
+	/* If we can't verify the issuer, then don't accept the name. */
+    if (depth != 0 && auth_ssl_name) {
+		free(auth_ssl_name);
+ 		auth_ssl_name = 0;
+ 	}
+ 	ok=ssl_verify_flag & SSL_VERIFY_FAIL_IF_NO_PEER_CERT ? 0 : 1;
+	goto done;
+     }
+     if (depth == 0)
+ 	auth_ssl_name =
+ 	    (char *)ONELINE_NAME(X509_get_subject_name(xs));
+done: ;
+
+     if (ssl_debug_flag)
+     	BIO_printf(bio_err,"verify_callback: returning %d\n",ok);
+
+     return ok;
+}
+
+/* return true if this auth_ssl_name is authorized to use name. */
+int
+good_ssl_user(char *name)
+{
+   FILE *user_fp;
+   char buf[2048];
+
+   if (!auth_ssl_name)
+      return 0;
+   if (!ssl_certsok_flag)
+      return 0;	/* can't happen */
+   user_fp = fopen("/etc/ssl.users", "r");
+   if (!user_fp)
+      return 0;
+   while (fgets(buf, sizeof buf, user_fp)) {
+      char *cp;
+      char *n;
+
+      /* allow for comments in the file ... always nice
+       * to be able to add a little novel in files and
+       * also disable easily --tjh
+       */
+      if (buf[0]=='#')
+	  continue;
+
+      if ((cp = strchr(buf, '\n')))
+	  *cp = '\0';
+      cp = strchr(buf, ':');
+      if (!cp)
+	  continue;
+      *cp++ = '\0';
+      if (strcasecmp(cp, auth_ssl_name) == 0) {
+	  n = buf;
+	  while (n) {
+	      cp = strchr(n, ',');
+	      if (cp)
+		  *cp++ = '\0';
+	      if (!strcmp(name, n)) {
+		  fclose(user_fp);
+		  return 1;
+	      }
+	      n = cp;
+	  }
+      }
+   }
+   fclose(user_fp);
+   return 0;
+}
+
+#endif /* USE_SSL */
diff -Nrup linux-ftpd-0.17.orig/ftpd/ssl_port.h linux-ftpd-0.17/ftpd/ssl_port.h
--- linux-ftpd-0.17.orig/ftpd/ssl_port.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-ftpd-0.17/ftpd/ssl_port.h	2005-11-06 08:19:35.000000000 -0500
@@ -0,0 +1,85 @@
+/* ssl_port.h    - standard porting things 
+ *
+ * The modifications to support SSLeay were done by Tim Hudson
+ * tjh@mincom.oz.au
+ *
+ * You can do whatever you like with these patches except pretend that
+ * you wrote them. 
+ *
+ * Email ssl-users-request@mincom.oz.au to get instructions on how to
+ * join the mailing list that discusses SSLeay and also these patches.
+ *
+ */
+
+#ifndef HEADER_SSL_PORT_H
+#define HEADER_SSL_PORT_H
+
+#ifdef USE_SSL
+
+#include <stdio.h>
+
+#define OLDPROTO NOPROTO
+#define NOPROTO
+#include <openssl/buffer.h>
+#undef NOPROTO
+#define NOPROTO OLDPROTO
+
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+extern SSL *ssl_con;
+extern SSL_CTX *ssl_ctx;
+extern int ssl_debug_flag;
+extern int ssl_only_flag;
+extern int ssl_active_flag;
+extern int ssl_verify_flag;
+extern int ssl_secure_flag;
+extern int ssl_enabled;
+
+extern int ssl_encrypt_data;
+extern SSL *ssl_data_con;
+extern int ssl_data_active_flag;
+
+extern char *my_ssl_cert_file;
+extern char *my_ssl_key_file;
+extern int ssl_certsok_flag;
+
+extern int set_ssl_trace(SSL *s);
+
+extern FILE *cin, *cout;
+
+#define is_ssl_fd(X,Y)    ( (SSL_get_fd((X))==0) || \
+                            (SSL_get_fd((X))==1) || \
+                            (SSL_get_fd((X))==pdata) || \
+			    (SSL_get_fd((X))==(Y)) \
+			  )
+
+#define is_ssl_fp(X,Y)    ( ( (SSL_get_fd((X))==0) && (fileno((Y))==0) ) || \
+                            ( (SSL_get_fd((X))==1) && (fileno((Y))==1) ) || \
+                            ( (SSL_get_fd((X))==pdata) && \
+			    			  (fileno((Y))==pdata) ) || \
+			    (SSL_get_fd((X))==fileno(Y)) \
+			  )
+
+/* these macros make things much easier to handle ... */
+
+#define FFLUSH(X)         (ssl_active_flag && (((X)==cin)||((X)==cout)) ? 1 : fflush((X)) )
+
+#define GETC(X)           (ssl_active_flag && (((X)==cin)||((X)==cout)) ? ssl_getc(ssl_con) : getc((X)) )
+
+#define DATAGETC(X)       (ssl_data_active_flag && ((fileno(X)==data)||(fileno(X)==pdata)) ? ssl_getc(ssl_data_con) : getc((X)) )
+#define DATAPUTC(X,Y)     (ssl_data_active_flag && ((fileno(Y)==data)||(fileno(Y)==pdata)) ? ssl_putc(ssl_data_con,(X)) : putc((X),(Y)) )
+#define DATAFLUSH(X)      (ssl_data_active_flag && ((fileno(X)==data)||(fileno(X)==pdata)) ? ssl_putc_flush(ssl_data_con) : fflush((X)) )
+
+#else
+
+#define GETC(X)           getc((X))
+#define DATAGETC(X)       getc((X))
+#define DATAPUTC(X,Y)     putc((X),(Y))
+#define DATAFLUSH(X)      fflush((X))
+#define FFLUSH(X)         fflush((X))
+
+#endif /* USE_SSL */
+
+#endif /*  HEADER_SSL_PORT_H */
diff -Nrup linux-ftpd-0.17.orig/ftpd/sslapp.c linux-ftpd-0.17/ftpd/sslapp.c
--- linux-ftpd-0.17.orig/ftpd/sslapp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-ftpd-0.17/ftpd/sslapp.c	2005-11-06 08:23:36.000000000 -0500
@@ -0,0 +1,182 @@
+/* sslapp.c	- ssl application code */
+
+/*
+ * The modifications to support SSLeay were done by Tim Hudson
+ * tjh@cryptsoft.com
+ *
+ * You can do whatever you like with these patches except pretend that
+ * you wrote them.
+ *
+ * Email ssl-users-request@lists.cryptsoft.com to get instructions on how to
+ * join the mailing list that discusses SSLeay and also these patches.
+ *
+ */
+
+#ifdef USE_SSL
+
+#include "sslapp.h"
+
+SSL_CTX *ssl_ctx;
+SSL *ssl_con;
+int ssl_debug_flag=0;
+int ssl_only_flag=0;
+int ssl_active_flag=0;
+int ssl_verify_flag=SSL_VERIFY_NONE;
+int ssl_secure_flag=0;
+int ssl_certsok_flag=0;
+int ssl_cert_required=0;
+int ssl_verbose_flag=0;
+int ssl_disabled_flag=0;
+char *ssl_cert_file=NULL;
+char *ssl_key_file=NULL;
+char *ssl_cipher_list=NULL;
+char *ssl_log_file=NULL;
+
+/* fwd decl */
+static void
+client_info_callback(SSL *s, int where, int ret);
+
+int 
+do_ssleay_init(int server)
+{
+  char *p;
+
+  /* make sure we have somewhere we can log errors to */
+  if (bio_err==NULL) {
+    if ((bio_err=BIO_new(BIO_s_file()))!=NULL) {
+      if (ssl_log_file==NULL)
+	BIO_set_fp(bio_err,stderr,BIO_NOCLOSE);
+      else {
+	if (BIO_write_filename(bio_err,ssl_log_file)<=0) {
+	  /* not a lot we can do */
+	}
+      }
+    }
+  }
+
+  /* rather simple things these days ... the old SSL_LOG and SSL_ERR
+   * vars are long gone now SSLeay8 has rolled around and we have 
+   * a clean interface for doing things
+   */
+  if (ssl_debug_flag)
+    BIO_printf(bio_err,"SSL_DEBUG_FLAG on\r\n");
+
+
+  /* init things so we will get meaningful error messages
+   * rather than numbers 
+   */
+  SSL_load_error_strings();
+
+  SSLeay_add_ssl_algorithms();
+  ssl_ctx=(SSL_CTX *)SSL_CTX_new(SSLv23_method());
+
+  /* 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;
+
+      if (ssl_debug_flag)
+	  BIO_printf(bio_err,"Generating temp (512 bit) RSA key ...\r\n");
+      rsa=RSA_generate_key(512,RSA_F4,NULL,NULL);
+      if (ssl_debug_flag)
+	  BIO_printf(bio_err,"Generation of temp (512 bit) RSA key done\r\n");
+   
+      if (!SSL_CTX_set_tmp_rsa(ssl_ctx,rsa)) {
+	BIO_printf(bio_err,"Failed to assign generated temp RSA key!\r\n");
+      }
+      RSA_free(rsa);
+      if (ssl_debug_flag)
+	  BIO_printf(bio_err,"Assigned temp (512 bit) RSA key\r\n");
+    }
+  }
+
+  /* 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);
+
+  /* the user can set whatever ciphers they want to use */
+  if (ssl_cipher_list==NULL) {
+      p=getenv("SSL_CIPHER");
+      if (p!=NULL)
+        SSL_CTX_set_cipher_list(ssl_ctx,p);
+  } else
+      SSL_CTX_set_cipher_list(ssl_ctx,ssl_cipher_list);
+
+  /* for verbose we use the 0.6.x info callback that I got
+   * eric to finally add into the code :-) --tjh
+   */
+  if (ssl_verbose_flag) {
+      SSL_CTX_set_info_callback(ssl_ctx,client_info_callback);
+  }
+
+  /* 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");
+	  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");
+	      return(0);
+	  }
+      }
+  }
+
+  /* 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
+   * exchange rather useless :-)
+   */
+  SSL_CTX_set_default_verify_paths(ssl_ctx);
+
+  /* now create a connection */
+  ssl_con=(SSL *)SSL_new(ssl_ctx);
+  SSL_set_verify(ssl_con,ssl_verify_flag,NULL);
+
+  return(1);
+}
+
+
+static void
+client_info_callback(SSL *s, int where, int ret)
+{
+  if (where==SSL_CB_CONNECT_LOOP) {
+    BIO_printf(bio_err,"SSL_connect:%s %s\r\n",
+		    SSL_state_string(s),SSL_state_string_long(s));
+  } else if (where==SSL_CB_CONNECT_EXIT) {
+    if (ret == 0) {
+      BIO_printf(bio_err,"SSL_connect:failed in %s %s\r\n",
+	      SSL_state_string(s),SSL_state_string_long(s));
+    } else if (ret < 0) {
+      BIO_printf(bio_err,"SSL_connect:error in %s %s\r\n",
+	      SSL_state_string(s),SSL_state_string_long(s));
+    }
+  }
+}
+
+
+#else /* !USE_SSL */
+
+/* something here to stop warnings if we build without SSL support */
+static int dummy_func()
+{
+  int i;
+
+  i++;
+}
+
+#endif /* USE_SSL */
+
diff -Nrup linux-ftpd-0.17.orig/ftpd/sslapp.h linux-ftpd-0.17/ftpd/sslapp.h
--- linux-ftpd-0.17.orig/ftpd/sslapp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-ftpd-0.17/ftpd/sslapp.h	2005-11-06 08:19:35.000000000 -0500
@@ -0,0 +1,63 @@
+/* sslapp.h	- ssl application code */
+
+/*
+ * The modifications to support SSLeay were done by Tim Hudson
+ * tjh@cryptsoft.com
+ *
+ * You can do whatever you like with these patches except pretend that
+ * you wrote them.
+ *
+ * Email ssl-users-request@mincom.oz.au to get instructions on how to
+ * join the mailing list that discusses SSLeay and also these patches.
+ *
+ */
+
+#ifdef USE_SSL
+
+#include <stdio.h>
+
+#include <openssl/crypto.h>
+
+#define SSL_set_pref_cipher(c,n)        SSL_set_cipher_list(c,n)
+#define ONELINE_NAME(X) X509_NAME_oneline(X,NULL,0)
+  
+#define OLDPROTO NOPROTO
+#define NOPROTO
+#include <openssl/bio.h>
+#undef NOPROTO
+#define NOPROTO OLDPROTO
+#undef OLDPROTO
+#include <openssl/buffer.h>
+
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+
+extern BIO *bio_err;
+extern SSL *ssl_con;
+extern SSL_CTX *ssl_ctx;
+extern int ssl_debug_flag;
+extern int ssl_only_flag;
+extern int ssl_active_flag;
+extern int ssl_verify_flag;
+extern int ssl_secure_flag;
+extern int ssl_verbose_flag;
+extern int ssl_disabled_flag;
+extern int ssl_cert_required;
+extern int ssl_certsok_flag;
+
+extern char *ssl_log_file; 
+extern char *ssl_cert_file; 
+extern char *ssl_key_file;
+extern char *ssl_cipher_list;
+
+/* we hide all the initialisation code in a separate file now */
+extern int do_ssleay_init(int server);
+
+/*extern int display_connect_details();
+extern int server_verify_callback();
+extern int client_verify_callback();*/
+
+#endif /* USE_SSL */
+
+
