Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 72306 Details for
Bug 111573
net-ftp/ftpd: remote hole in linux-ftpd-ssl (CVE-2005-3524)
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
linux-ftpd-0.17-ssl.patch
linux-ftpd-0.17-ssl.patch (text/plain), 35.60 KB, created by
solar (RETIRED)
on 2005-11-06 06:55:14 UTC
(
hide
)
Description:
linux-ftpd-0.17-ssl.patch
Filename:
MIME Type:
Creator:
solar (RETIRED)
Created:
2005-11-06 06:55:14 UTC
Size:
35.60 KB
patch
obsolete
>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(errstr), "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(errstr), "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 */ >+ >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 111573
:
72248
| 72306