--- netkit-ftp-0.17/configure +++ netkit-ftp-0.17+ssl-0.2/configure @@ -26,6 +26,7 @@ --binmode=mode Mode for binaries [755] --manmode=mode Mode for manual pages [644] --with-c-compiler=cc Program for compiling C source [guessed] + --enable-ssl Enable SSL support EOF exit 0;; --verbose) ;; @@ -39,6 +40,8 @@ --manmode=*) MANMODE=`echo $1 | sed 's/^[^=]*=//'` ;; --with-c-compiler=*) CC=`echo $1 | sed 's/^[^=]*=//'` ;; --without-readline|--disable-readline) WITHOUT_READLINE=1;; + --disable-ssl) ENABLE_SSL=no;; + --enable-ssl) ENABLE_SSL=yes;; *) echo "Unrecognized option: $1"; exit 1;; esac shift @@ -152,3 +155,17 @@ rm -f __conftest* +################################################## +## Enable SSL +echo -n "Whether to enable SSL support... " +if [ x"$ENABLE_SSL" = x"yes" ]; then + echo yes + CFLAGS="$CFLAGS -DUSE_SSL" +else + echo no +fi + +## we should do tests here, but screw it, i'm lazy :P +LIBS="$LIBS -lssl -lcrypto" + + ################################################## --- netkit-ftp-0.17/ftp/cmds.c +++ netkit-ftp-0.17+ssl-0.2/ftp/cmds.c @@ -207,6 +207,32 @@ } port = ftp_port; if (argc > 2) { +#ifdef USE_SSL + /* not really an SSL enhancement but something that + * should have always been here --tjh + */ + if (!isdigit(argv[2][0])) { + struct servent *destsp; + + destsp = getservbyname(argv[2], "tcp"); + + /* if lookup fails for ssl-ftp we fallback to + * the default (unofficial) port number + */ + if ((strcmp(argv[2],"ssl-ftp")==0) && (destsp==NULL)) + port = 150; + else { + if (destsp == NULL ) { + printf("%s: bad port name-- %s\n",argv[1],argv[2]); + printf ("usage: %s host-name [port]\n",argv[0]); + code = -1; + return; + } else { + port = ntohs(destsp->s_port); + } + } + } else +#endif /* USE_SSL */ port = atoi(argv[2]); if (port < 1) { printf("%s: bad port number-- %s\n", argv[1], argv[2]); --- netkit-ftp-0.17/ftp/ftp.1 +++ netkit-ftp-0.17+ssl-0.2/ftp/ftp.1 @@ -97,6 +97,52 @@ as report on data transfer statistics. .It Fl d Enables debugging. +.It Fl z Ar option +Set SSL (Secure Socket Layer) parameters. The default is to negotiate +via ftp protocoll if SSL is availlable at server side and then to +switch it on. In this mode you can connect to both conventional and +SSL enhanced ftpd's. +.Pp +The SSL parameters are: +.Bl -tag -width Fl +.It Ic Ar debug +Send SSL related debugging information to stderr. +.It Ic Ar authdebug +Enable authentication debugging. +.It Ic Ar ssl +Negotiate SSL at first, then use ftp protocol. ftp protocol +negotiation goes encrypted. (Not yet implemented) +.It Ic Ar nossl, Ar !ssl +switch of SSL negotiation +.It Ic Ar certrequired +client certificate is mandatory +.It Ic Ar secure +Don't switch back to unencrypted mode (no SSL) if SSL is not available. +.It Ic Ar verbose +Be verbose about certificates etc. +.It Ic Ar verify=int +.\" TODO +Set the SSL verify flags (SSL_VERIFY_* in +.Ar ssl/ssl.h +). +.\" TODO +.It Ic Ar cert=cert_file +.\" TODO +Use the certificate(s) in +.Ar cert_file . +.It Ic Ar key=key_file +.\" TODO +Use the key(s) in +.Ar key_file . +.It Ic Ar cipher=ciph_list +.\" TODO +Set the preferred ciphers to +.Ar ciph_list . +.\" TODO: possible values; comma-separated list? +(See +.Ar ssl/ssl.h +). +.El .El .Pp The client host with which --- netkit-ftp-0.17/ftp/ftp.c +++ netkit-ftp-0.17+ssl-0.2/ftp/ftp.c @@ -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, 1989 Regents of the University of California. * All rights reserved. @@ -77,6 +89,17 @@ static sigjmp_buf ptabort; static int ptabflg = 0; static int abrtflag = 0; +#ifdef USE_SSL +static int pdata = -1; +static int +auth_user(char *u,char *p); +static int +ssl_getc(SSL *ssl_con); +static int +ssl_putc_flush(SSL *ssl_con); +static int +ssl_putc(SSL *ssl_con, int oneint); +#endif void lostpeer(int); extern int connected; @@ -243,14 +266,7 @@ else luser = tmp; } - n = command("USER %s", luser); - if (n == CONTINUE) { - if (pass == NULL) { - /* fflush(stdout); */ - pass = getpass("Password:"); - } - n = command("PASS %s", pass); - } + n = auth_user(luser,pass); if (n == CONTINUE) { aflag++; /* fflush(stdout); */ @@ -296,6 +312,9 @@ va_list ap; int r; void (*oldintr)(int); +#ifdef USE_SSL + char outputbuf[8192]; +#endif /* USE_SSL */ abrtflag = 0; if (debug) { @@ -316,10 +335,27 @@ } oldintr = signal(SIGINT, cmdabort); va_start(ap, fmt); +#ifdef USE_SSL + /* assemble the output into a buffer */ + vsnprintf(outputbuf,sizeof(outputbuf),fmt,ap); + strcat(outputbuf,"\r\n"); + if (ssl_active_flag) { + SSL_write(ssl_con,outputbuf,strlen(outputbuf)); + } else { + fprintf(cout,"%s",outputbuf); + fflush(cout); + } +#else /* !USE_SSL */ vfprintf(cout, fmt, ap); +#endif /* USE_SSL */ va_end(ap); + +#ifndef USE_SSL + /* we don't need this as we concatenated it above */ fprintf(cout, "\r\n"); (void) fflush(cout); +#endif /* !USE_SSL */ + cpend = 1; r = getreply(!strcmp(fmt, "QUIT")); if (abrtflag && oldintr != SIG_IGN) @@ -343,25 +379,39 @@ int pflag = 0; size_t px = 0; size_t psize = sizeof(pasv); + char buf[16]; oldintr = signal(SIGINT, cmdabort); for (;;) { dig = n = code = 0; cp = reply_string; - while ((c = getc(cin)) != '\n') { + while ((c = GETC(cin)) != '\n') { if (c == IAC) { /* handle telnet commands */ - switch (c = getc(cin)) { + switch (c = GETC(cin)) { case WILL: case WONT: - c = getc(cin); - fprintf(cout, "%c%c%c", IAC, DONT, c); - (void) fflush(cout); + c = GETC(cin); + sprintf(buf, + "%c%c%c", IAC, DONT, c); +#ifdef USE_SSL + if (ssl_active_flag) + SSL_write(ssl_con,buf,3); + else +#endif /* !USE_SSL */ + fwrite(buf,3,1,cout); + (void) FFLUSH(cout); break; case DO: case DONT: - c = getc(cin); - fprintf(cout, "%c%c%c", IAC, WONT, c); - (void) fflush(cout); + c = GETC(cin); + sprintf(buf, "%c%c%c", IAC, WONT, c); +#ifdef USE_SSL + if (ssl_active_flag) + SSL_write(ssl_con,buf,3); + else +#endif /* !USE_SSL */ + fwrite(buf,3,1,cout); + (void) FFLUSH(cout); break; default: break; @@ -600,9 +650,18 @@ errno = d = 0; while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { bytes += c; +#ifdef USE_SSL + if (ssl_data_active_flag) { + for (bufp = buf; c > 0; c -= d, bufp += d) + if ((d = SSL_write(ssl_data_con, bufp, c)) <= 0) + break; + } else +#endif /* !USE_SSL */ + { for (bufp = buf; c > 0; c -= d, bufp += d) if ((d = write(fileno(dout), bufp, c)) <= 0) break; + } if (hash) { while (bytes >= hashbytes) { (void) putchar('#'); @@ -654,16 +713,17 @@ } if (ferror(dout)) break; - (void) putc('\r', dout); + (void) DATAPUTC('\r', dout); bytes++; } - (void) putc(c, dout); + (void) DATAPUTC(c, dout); bytes++; /* if (c == '\r') { */ /* (void) putc('\0', dout); (* this violates rfc */ /* bytes++; */ /* } */ } + DATAFLUSH(dout); if (hash) { if (bytes < hashbytes) (void) putchar('#'); @@ -688,6 +748,15 @@ if (closefunc != NULL) (*closefunc)(fin); (void) fclose(dout); + +#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 */ + /* closes data as well, so discard it */ data = -1; (void) getreply(0); @@ -714,6 +783,15 @@ (void) close(data); data = -1; } + +#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) getreply(0); code = -1; if (closefunc != NULL && fin != NULL) @@ -908,6 +986,33 @@ return; } errno = d = 0; +#ifdef USE_SSL + if (ssl_data_active_flag) { + while ((c = SSL_read(ssl_data_con, buf, bufsize)) > 0) { + if ((d = write(fileno(fout), buf, c)) != c) + break; + bytes += c; + if (hash) { + while (bytes >= hashbytes) { + (void) putchar('#'); + hashbytes += HASHBYTES; + } + (void) fflush(stdout); + } + } + if ( c < -1 ) { + static char errbuf[1024]; + + sprintf(errbuf,"ftp: SSL_read DATA error %s\n", + ERR_error_string(ERR_get_error(),NULL)); + + /* tell the user ... who else */ + fprintf(stderr,"%s", errbuf); + fflush(stderr); + } + } else +#endif /* !USE_SSL */ + { while ((c = read(fileno(din), buf, bufsize)) > 0) { if ((d = write(fileno(fout), buf, c)) != c) break; @@ -927,6 +1032,7 @@ hashbytes += TICKBYTES; } } + } if (hash && bytes > 0) { if (bytes < HASHBYTES) (void) putchar('#'); @@ -973,7 +1079,7 @@ return; } } - while ((c = getc(din)) != EOF) { + while ((c = DATAGETC(din)) != EOF) { if (c == '\n') bare_lfs++; while (c == '\r') { @@ -991,7 +1097,7 @@ hashbytes += TICKBYTES; } bytes++; - if ((c = getc(din)) != '\n' || tcrflag) { + if ((c = DATAGETC(din)) != '\n' || tcrflag) { if (ferror(fout)) goto break2; (void) putc('\r', fout); @@ -1039,6 +1145,15 @@ (void) signal(SIGPIPE, oldintp); (void) gettimeofday(&stop, (struct timezone *)0); (void) fclose(din); + +#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 */ + /* closes data as well, so discard it */ data = -1; (void) getreply(0); @@ -1071,6 +1186,15 @@ (void) close(data); data = -1; } + +#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 */ + if (bytes > 0) ptransfer("received", bytes, &start, &stop); (void) signal(SIGINT, oldintr); @@ -1207,6 +1331,7 @@ struct sockaddr_in from; int s, tos; socklen_t fromlen = sizeof(from); + int ret; if (passivemode) return (fdopen(data, lmode)); @@ -1224,6 +1349,67 @@ if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) perror("ftp: setsockopt TOS (ignored)"); #endif + +#ifdef USE_SSL + ssl_data_active_flag=0; + if (ssl_active_flag && ssl_encrypt_data) { + /* do SSL */ + if (ssl_data_con!=NULL) { + SSL_free(ssl_data_con); + ssl_data_con=NULL; + } + ssl_data_con=(SSL *)SSL_new(ssl_ctx); + + SSL_set_fd(ssl_data_con,data); + set_ssl_trace(ssl_data_con); + + SSL_set_verify(ssl_data_con,ssl_verify_flag,NULL); + + /* this is the "magic" call that makes + * this quick assuming Eric has this going + * okay! ;-) + */ + SSL_copy_session_id(ssl_data_con,ssl_con); + + /* we are doing I/O and not using select so + * it is "safe" to read ahead + */ + /* SSL_set_read_ahead(ssl_data_con,1); */ + + if (debug) { + fprintf(stderr,"===>START SSL connect on DATA\n"); + fflush(stderr); + } + + if ((ret=SSL_connect(ssl_data_con))<=0) { + static char errbuf[1024]; + + sprintf(errbuf,"ftp: SSL_connect DATA error %d - %s\n", + ret,ERR_error_string(ERR_get_error(),NULL)); + + /* tell the user ... who else */ + fprintf(stderr,"%s", errbuf); + fflush(stderr); + + /* abort time methinks ... */ + close(data); + 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 (debug) { + fprintf(stderr,"===>DONE SSL connect on DATA %d\n",data); + fflush(stderr); + } + + } +#endif /* USE_SSL */ + return (fdopen(data, lmode)); } @@ -1609,3 +1795,142 @@ } (void) getreply(0); } + +static int +auth_user(char *u,char *p) +{ + int n; + +#ifdef USE_SSL + if (ssl_enabled) { + n = command("AUTH SSL"); + if (n == ERROR) { /* do normal USER/PASS */ + printf("SSL not available\n"); + /* spit the dummy as we will only talk ssl + * when running in "secure" mode + */ + if (ssl_secure_flag) + return ERROR; + } else if (n == CONTINUE || n == COMPLETE) { + /* do SSL */ + ssl_con=(SSL *)SSL_new(ssl_ctx); + + SSL_set_fd(ssl_con,fileno(cout)); + set_ssl_trace(ssl_con); + + SSL_set_verify(ssl_con,ssl_verify_flag,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); + 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); + exit(1); + } + } + } + + if (SSL_connect(ssl_con)<=0) { + static char errbuf[1024]; + + sprintf(errbuf,"ftp: SSL_connect error %s\n", + ERR_error_string(ERR_get_error(),NULL)); + perror(errbuf); + /* abort time methinks ... */ + exit(1); + } else { + fprintf(stderr,"[SSL Cipher %s]\n",SSL_get_cipher(ssl_con)); + fflush(stderr); + ssl_active_flag=1; + } + + n = command("USER %s",u); + if (n == CONTINUE) { + if(p == NULL) + p = getpass("Password:"); + n = command("PASS %s",p); + } + return (n); + } + } +#endif /* USE_SSL */ + n = command("USER %s",u); + if (n == CONTINUE) { + if(p == NULL) + p = getpass("Password:"); + n = command("PASS %s",p); + } + return(n); +} + +#ifdef USE_SSL + +/* we really shouldn't have code like this! --tjh */ +static int +ssl_getc(SSL *ssl_con) +{ + char onebyte; + int ret; + + if ((ret=SSL_read(ssl_con,&onebyte,1))!=1) { + /* we want to know this stuff! */ + if (ssl_debug_flag || (ret!=0)) { + fprintf(stderr,"ssl_getc: SSL_read failed %d = %d\n",ret,errno); + fflush(stderr); + } + 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; +} + +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; +} + +#endif /* USE_SSL */ --- netkit-ftp-0.17/ftp/ftp_var.h +++ netkit-ftp-0.17+ssl-0.2/ftp/ftp_var.h @@ -158,3 +158,6 @@ void setpeer(int argc, char *argv[]); void quit(void); void changetype(int newtype, int show); + +#include "sslapp.h" +#include "ssl_port.h" --- netkit-ftp-0.17/ftp/main.c +++ netkit-ftp-0.17+ssl-0.2/ftp/main.c @@ -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, 1989 Regents of the University of California. * All rights reserved. @@ -82,6 +94,75 @@ static void cmdscanner(int top); static char *slurpstring(void); +#ifdef USE_SSL + +/* icky way of doing things ... */ +#include "sslapp.c" + +/* +#include "ssl_err.h" +*/ + +SSL *ssl_con; +SSL *ssl_data_con; +int ssl_data_active_flag=0; + +/* for the moment this is a compile time option only --tjh */ +int ssl_encrypt_data=1; +int ssl_enabled=1; + +char *my_ssl_key_file=NULL; +char *my_ssl_cert_file=NULL; + +BIO *bio_err=NULL; + +static long +bio_dump_cb(BIO *bio, + int cmd, + char *argp, + int argi, + long argl, + long ret) + { + BIO *out; + +/* + out=(BIO *)BIO_get_callback_arg(bio); +*/ + out=bio_err; + if (out == NULL) return(ret); + + if (cmd == (BIO_CB_READ|BIO_CB_RETURN)) + { + BIO_printf(out,"read from %08X (%d bytes => %ld (%X))\n", + bio,argi,ret,ret); + BIO_dump(out,argp,(int)ret); + BIO_flush(out); + } + else if (cmd == (BIO_CB_WRITE|BIO_CB_RETURN)) + { + BIO_printf(out,"write to %08X (%d bytes => %ld (%X))\n", + bio,argi,ret,ret); + BIO_dump(out,argp,(int)ret); + BIO_flush(out); + } + return( (cmd & BIO_CB_RETURN) ? ret : 1); + } + +int +set_ssl_trace(SSL *con) +{ + if (con!=NULL) { + if (ssl_debug_flag) { + BIO_set_callback(SSL_get_rbio(con),bio_dump_cb); + BIO_set_callback_arg(SSL_get_rbio(con),bio_err); + } + } + return 0; +} + +#endif /* USE_SSL */ + static void usage(void) @@ -106,6 +187,7 @@ int top; struct passwd *pw = NULL; char homedir[MAXPATHLEN]; + char *optarg; tick = 0; @@ -134,6 +216,7 @@ argc--, argv++; while (argc > 0 && **argv == '-') { + optarg=*(argv+1); for (cp = *argv + 1; *cp; cp++) switch (*cp) { @@ -174,6 +257,48 @@ usage(); exit(0); +#ifdef USE_SSL + case 'z': + if (!optarg) { + fprintf(stderr, "ftp: the -z option requires an argument\n"); + exit(1); + } + if (strcmp(optarg, "debug") == 0 ) { + ssl_debug_flag=1; + } + if (strcmp(optarg, "ssl") == 0 ) { + ssl_only_flag=1; + } + /* disable *all* ssl stuff */ + if ( (strcmp(optarg, "!ssl") == 0 ) || + (strcmp(optarg, "nossl") == 0 ) ) { + ssl_enabled=0; + } + if (strcmp(optarg, "secure") == 0 ) { + ssl_secure_flag=1; + } + if (strcmp(optarg, "certsok") == 0 ) { + ssl_certsok_flag=1; + } + if (strcmp(optarg, "verbose") == 0 ) { + ssl_verbose_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: fprintf(stdout, "ftp: %c: unknown option\n", *cp); @@ -202,6 +323,18 @@ homedir[sizeof(homedir)-1] = 0; home = homedir; } + +#ifdef USE_SSL + if (ssl_enabled) { + if (!do_ssleay_init(0)) { + fprintf(stderr,"ftp: SSLeay initialisation failed\n"); + fflush(stderr); + ERR_print_errors_fp(stderr); + exit(1); + } + } +#endif /* USE_SSL */ + if (argc > 0) { if (sigsetjmp(toplevel, 1)) exit(0); --- netkit-ftp-0.17/ftp/ssl_port.h +++ netkit-ftp-0.17+ssl-0.2/ftp/ssl_port.h @@ -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 + +#define OLDPROTO NOPROTO +#define NOPROTO +#include +#undef NOPROTO +#define NOPROTO OLDPROTO + +#include +#include +#include + +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 */ --- netkit-ftp-0.17/ftp/sslapp.c +++ netkit-ftp-0.17+ssl-0.2/ftp/sslapp.c @@ -0,0 +1,186 @@ +/* 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); + +#if 0 + SSL_set_verify(ssl_con,ssl_verify_flag,client_verify_callback); +#endif + + 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 */ + --- netkit-ftp-0.17/ftp/sslapp.h +++ netkit-ftp-0.17+ssl-0.2/ftp/sslapp.h @@ -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 + +#include + +#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 +#undef NOPROTO +#define NOPROTO OLDPROTO +#undef OLDPROTO +#include + +#include +#include +#include + +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 */ + +