|
Lines 1-3
Link Here
|
|
|
1 |
/* |
| 2 |
* The modifications to support SSLeay were done by Tim Hudson |
| 3 |
* tjh@cryptsoft.com |
| 4 |
* |
| 5 |
* You can do whatever you like with these patches except pretend that |
| 6 |
* you wrote them. |
| 7 |
* |
| 8 |
* Email ssl-users-request@lists.cryptsoft.com to get instructions on how to |
| 9 |
* join the mailing list that discusses SSLeay and also these patches. |
| 10 |
* |
| 11 |
*/ |
| 12 |
|
| 1 |
/* |
13 |
/* |
| 2 |
* Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 |
14 |
* Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 |
| 3 |
* The Regents of the University of California. All rights reserved. |
15 |
* The Regents of the University of California. All rights reserved. |
|
Lines 126-131
typedef unsigned int useconds_t;
Link Here
|
| 126 |
#include "pathnames.h" |
138 |
#include "pathnames.h" |
| 127 |
#include "extern.h" |
139 |
#include "extern.h" |
| 128 |
|
140 |
|
|
|
141 |
#ifdef USE_SSL |
| 142 |
|
| 143 |
#include "sslapp.c" |
| 144 |
|
| 145 |
BIO *bio_err; |
| 146 |
SSL *ssl_data_con; |
| 147 |
int ssl_auto_login=0; |
| 148 |
|
| 149 |
static char *auth_ssl_name=NULL; |
| 150 |
FILE *cin, *cout; |
| 151 |
|
| 152 |
int ssl_data_active_flag=0; |
| 153 |
|
| 154 |
/* for the moment this is a compile time option only --tjh */ |
| 155 |
int ssl_encrypt_data=1; |
| 156 |
|
| 157 |
char ssl_file_path[1024]; /* don't look at that nasty value to the left */ |
| 158 |
|
| 159 |
X509 *ssl_public_cert; |
| 160 |
RSA *ssl_private_key; |
| 161 |
|
| 162 |
static char *my_ssl_key_file=NULL; |
| 163 |
static char *my_ssl_cert_file=NULL; |
| 164 |
|
| 165 |
#include "ssl_port.h" |
| 166 |
|
| 167 |
int |
| 168 |
ssl_getc(SSL *ssl_con); |
| 169 |
static int |
| 170 |
ssl_putc(SSL *ssl_con,int oneint); |
| 171 |
static int |
| 172 |
ssl_putc_flush(SSL *ssl_con); |
| 173 |
|
| 174 |
#endif /* USE_SSL */ |
| 175 |
|
| 129 |
#ifdef __STDC__ |
176 |
#ifdef __STDC__ |
| 130 |
#include <stdarg.h> |
177 |
#include <stdarg.h> |
| 131 |
#else |
178 |
#else |
|
Lines 294-300
main(int argc, char *argv[], char **envp
Link Here
|
| 294 |
socklen_t addrlen; |
341 |
socklen_t addrlen; |
| 295 |
char *cp, line[LINE_MAX]; |
342 |
char *cp, line[LINE_MAX]; |
| 296 |
FILE *fd; |
343 |
FILE *fd; |
| 297 |
const char *argstr = "AdDhlMSt:T:u:UvP"; |
344 |
const char *argstr = "AdDhlMSt:T:u:UvPz:"; |
| 298 |
struct hostent *hp; |
345 |
struct hostent *hp; |
| 299 |
|
346 |
|
| 300 |
#ifdef __linux__ |
347 |
#ifdef __linux__ |
|
Lines 390-401
main(int argc, char *argv[], char **envp
Link Here
|
| 390 |
debug = 1; |
437 |
debug = 1; |
| 391 |
break; |
438 |
break; |
| 392 |
|
439 |
|
|
|
440 |
#ifdef USE_SSL |
| 441 |
case 'z': |
| 442 |
if (strcmp(optarg, "debug") == 0 ) { |
| 443 |
ssl_debug_flag=1; |
| 444 |
} |
| 445 |
if (strcmp(optarg, "verbose") == 0 ) { |
| 446 |
ssl_verbose_flag=1; |
| 447 |
} |
| 448 |
if (strcmp(optarg, "ssl") == 0 ) { |
| 449 |
ssl_only_flag=1; |
| 450 |
} |
| 451 |
if (strcmp(optarg, "secure") == 0 ) { |
| 452 |
ssl_secure_flag=1; |
| 453 |
} |
| 454 |
if (strcmp(optarg, "certsok") == 0) { |
| 455 |
ssl_certsok_flag=1; |
| 456 |
} |
| 457 |
if (strncmp(optarg, "verify=", strlen("verify=")) == 0 ) { |
| 458 |
ssl_verify_flag=atoi(optarg+strlen("verify=")); |
| 459 |
|
| 460 |
} |
| 461 |
if (strncmp(optarg, "cert=", strlen("cert=")) == 0 ) { |
| 462 |
my_ssl_cert_file=optarg+strlen("cert="); |
| 463 |
} |
| 464 |
if (strncmp(optarg, "key=", strlen("key=")) == 0 ) { |
| 465 |
my_ssl_key_file=optarg+strlen("key="); |
| 466 |
} |
| 467 |
/* we have swallowed an extra arg */ |
| 468 |
/*argc--; |
| 469 |
argv++;*/ |
| 470 |
break; |
| 471 |
#endif /* USE_SSL */ |
| 472 |
|
| 393 |
default: |
473 |
default: |
| 394 |
warnx("unknown flag -%c ignored", optopt); |
474 |
warnx("unknown flag -%c ignored", optopt); |
| 395 |
break; |
475 |
break; |
| 396 |
} |
476 |
} |
| 397 |
} |
477 |
} |
| 398 |
|
478 |
|
|
|
479 |
#ifdef USE_SSL |
| 480 |
/* make sure we have access to the required certificate |
| 481 |
* and key files now ... before we perhaps chroot and |
| 482 |
* do the other "muck" for anon-ftp style setup ... though |
| 483 |
* why we want to run SSL for anon I don't know |
| 484 |
*/ |
| 485 |
|
| 486 |
{ |
| 487 |
/* keep the macros that are common between the client |
| 488 |
* and the server happy |
| 489 |
*/ |
| 490 |
cin=stdin; |
| 491 |
cout=stderr; |
| 492 |
|
| 493 |
/* do things the "default" way */ |
| 494 |
if (my_ssl_cert_file==NULL) { |
| 495 |
snprintf(ssl_file_path, sizeof(ssl_file_path), "%s/%s", X509_get_default_cert_dir(), |
| 496 |
"ftpd.pem"); |
| 497 |
ssl_cert_file=ssl_file_path; |
| 498 |
} else { |
| 499 |
ssl_cert_file=my_ssl_cert_file; |
| 500 |
} |
| 501 |
|
| 502 |
if (!do_ssleay_init(1)) { |
| 503 |
fprintf(stderr,"ftpd: SSLeay initialisation failed\n"); |
| 504 |
fflush(stderr); |
| 505 |
sleep(1); |
| 506 |
exit(1); |
| 507 |
} |
| 508 |
|
| 509 |
} |
| 510 |
#endif /* USE_SSL */ |
| 511 |
|
| 399 |
(void) freopen(_PATH_DEVNULL, "w", stderr); |
512 |
(void) freopen(_PATH_DEVNULL, "w", stderr); |
| 400 |
|
513 |
|
| 401 |
/* |
514 |
/* |
|
Lines 552-567
main(int argc, char *argv[], char **envp
Link Here
|
| 552 |
/* Make sure hostname is fully qualified. */ |
665 |
/* Make sure hostname is fully qualified. */ |
| 553 |
hp = gethostbyname(hostname); |
666 |
hp = gethostbyname(hostname); |
| 554 |
if (hp != NULL) |
667 |
if (hp != NULL) |
| 555 |
strcpy(hostname, hp->h_name); |
668 |
strncpy(hostname, hp->h_name, sizeof(hostname)); |
| 556 |
|
669 |
|
| 557 |
if (multihome) { |
670 |
if (multihome) { |
| 558 |
hp = gethostbyaddr((char *) &ctrl_addr.sin_addr, |
671 |
hp = gethostbyaddr((char *) &ctrl_addr.sin_addr, |
| 559 |
sizeof (struct in_addr), AF_INET); |
672 |
sizeof (struct in_addr), AF_INET); |
| 560 |
if (hp != NULL) { |
673 |
if (hp != NULL) { |
| 561 |
strcpy(dhostname, hp->h_name); |
674 |
strncpy(dhostname, hp->h_name, sizeof(dhostname)); |
| 562 |
} else { |
675 |
} else { |
| 563 |
/* Default. */ |
676 |
/* Default. */ |
| 564 |
strcpy(dhostname, inet_ntoa(ctrl_addr.sin_addr)); |
677 |
strncpy(dhostname, inet_ntoa(ctrl_addr.sin_addr), sizeof(dhostname)); |
| 565 |
} |
678 |
} |
| 566 |
} |
679 |
} |
| 567 |
|
680 |
|
|
Lines 648-653
static int login_attempts; /* number of
Link Here
|
| 648 |
static int askpasswd; /* had user command, ask for passwd */ |
761 |
static int askpasswd; /* had user command, ask for passwd */ |
| 649 |
static char curname[16]; /* current USER name */ |
762 |
static char curname[16]; /* current USER name */ |
| 650 |
|
763 |
|
|
|
764 |
int |
| 765 |
good_ssl_user(char *name); |
| 766 |
|
| 651 |
/* |
767 |
/* |
| 652 |
* USER command. |
768 |
* USER command. |
| 653 |
* Sets global passwd pointer pw if named account exists and is acceptable; |
769 |
* Sets global passwd pointer pw if named account exists and is acceptable; |
|
Lines 718-723
void user(char *name)
Link Here
|
| 718 |
strncpy(curname, name, sizeof(curname)-1); |
834 |
strncpy(curname, name, sizeof(curname)-1); |
| 719 |
curname[sizeof(curname)-1] = '\0'; |
835 |
curname[sizeof(curname)-1] = '\0'; |
| 720 |
} |
836 |
} |
|
|
837 |
#ifdef USE_SSL |
| 838 |
if (pw && good_ssl_user(name)) { |
| 839 |
reply(331, "Send dummy password to login."); |
| 840 |
ssl_auto_login = 1; |
| 841 |
} else |
| 842 |
#endif |
| 721 |
#ifdef SKEY |
843 |
#ifdef SKEY |
| 722 |
if (!skey_haskey(name)) { |
844 |
if (!skey_haskey(name)) { |
| 723 |
char *myskey, *skey_keyinfo __P((char *name)); |
845 |
char *myskey, *skey_keyinfo __P((char *name)); |
|
Lines 797-803
void pass(char *passwd)
Link Here
|
| 797 |
return; |
919 |
return; |
| 798 |
} |
920 |
} |
| 799 |
askpasswd = 0; |
921 |
askpasswd = 0; |
| 800 |
if (!guest) { /* "ftp" is only account allowed no password */ |
922 |
if (!guest |
|
|
923 |
#ifdef USE_SSL |
| 924 |
&& !ssl_auto_login |
| 925 |
#endif |
| 926 |
) { /* "ftp" is only account allowed no password */ |
| 801 |
if (pw == NULL) { |
927 |
if (pw == NULL) { |
| 802 |
useconds_t us; |
928 |
useconds_t us; |
| 803 |
|
929 |
|
|
Lines 1072-1077
void retrieve(const char *cmd, const cha
Link Here
|
| 1072 |
(restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode))); |
1198 |
(restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode))); |
| 1073 |
if ((cmd == 0) && stats) |
1199 |
if ((cmd == 0) && stats) |
| 1074 |
logxfer(name, st.st_size, start); |
1200 |
logxfer(name, st.st_size, start); |
|
|
1201 |
|
| 1202 |
#ifdef USE_SSL |
| 1203 |
if (ssl_data_active_flag && (ssl_data_con!=NULL)) { |
| 1204 |
SSL_free(ssl_data_con); |
| 1205 |
ssl_data_active_flag=0; |
| 1206 |
ssl_data_con=NULL; |
| 1207 |
} |
| 1208 |
#endif /* USE_SSL */ |
| 1209 |
|
| 1075 |
(void) fclose(dout); |
1210 |
(void) fclose(dout); |
| 1076 |
data = -1; |
1211 |
data = -1; |
| 1077 |
pdata = -1; |
1212 |
pdata = -1; |
|
Lines 1276-1283
static FILE * dataconn(const char *name,
Link Here
|
| 1276 |
(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, |
1411 |
(void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, |
| 1277 |
sizeof(int)); |
1412 |
sizeof(int)); |
| 1278 |
#endif |
1413 |
#endif |
|
|
1414 |
#ifdef USE_SSL |
| 1415 |
/* time to negotiate SSL on the data connection ... |
| 1416 |
* do this via SSL_accept (as we are still the server |
| 1417 |
* even though things are started around the other way) |
| 1418 |
* |
| 1419 |
* note: we really *must* make sure the session stuff |
| 1420 |
* is copied correctly as we cannot afford a full |
| 1421 |
* SSL negotiation for each data socket! |
| 1422 |
*/ |
| 1423 |
/* TODO XXXX fill in the blanks :-) |
| 1424 |
*/ |
| 1425 |
ssl_data_active_flag=0; |
| 1426 |
if (ssl_active_flag && ssl_encrypt_data) { |
| 1427 |
/* do SSL */ |
| 1428 |
|
| 1429 |
reply(150, "Opening %s mode SSL data connection for %s%s.", |
| 1430 |
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); |
| 1431 |
|
| 1432 |
if (ssl_data_con!=NULL) { |
| 1433 |
SSL_free(ssl_data_con); |
| 1434 |
ssl_data_con=NULL; |
| 1435 |
} |
| 1436 |
ssl_data_con=(SSL *)SSL_new(ssl_ctx); |
| 1437 |
|
| 1438 |
/* copy session details ... */ |
| 1439 |
SSL_copy_session_id(ssl_data_con,ssl_con); |
| 1440 |
|
| 1441 |
/* for 0.5.2 - want to change the timeout value etc ... */ |
| 1442 |
|
| 1443 |
SSL_set_fd(ssl_data_con,pdata); |
| 1444 |
SSL_set_verify(ssl_data_con,ssl_verify_flag,NULL); |
| 1445 |
|
| 1446 |
/* if is "safe" to read ahead */ |
| 1447 |
/* SSL_set_read_ahead(ssl_data_con,1); */ |
| 1448 |
|
| 1449 |
if (ssl_debug_flag) |
| 1450 |
BIO_printf(bio_err,"===>START SSL_accept on DATA\n"); |
| 1451 |
|
| 1452 |
if (SSL_accept(ssl_data_con)<=0) { |
| 1453 |
static char errbuf[1024]; |
| 1454 |
|
| 1455 |
snprintf(errbuf, sizeof(errstr), "ftpd: SSL_accept DATA error %s\n", |
| 1456 |
ERR_error_string(ERR_get_error(),NULL)); |
| 1457 |
perror_reply(425, errbuf); |
| 1458 |
/* abort time methinks ... */ |
| 1459 |
fclose(file); |
| 1460 |
return NULL; |
| 1461 |
} else { |
| 1462 |
if (ssl_debug_flag) { |
| 1463 |
BIO_printf(bio_err,"[SSL DATA Cipher %s]\n", |
| 1464 |
SSL_get_cipher(ssl_con)); |
| 1465 |
} |
| 1466 |
ssl_data_active_flag=1; |
| 1467 |
} |
| 1468 |
|
| 1469 |
if (ssl_debug_flag) |
| 1470 |
BIO_printf(bio_err,"===>DONE SSL_accept on DATA\n"); |
| 1471 |
|
| 1472 |
} else { |
| 1473 |
reply(150, "Opening %s mode data connection for %s%s.", |
| 1474 |
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); |
| 1475 |
} |
| 1476 |
#else /* !USE_SSL */ |
| 1279 |
reply(150, "Opening %s mode data connection for '%s'%s.", |
1477 |
reply(150, "Opening %s mode data connection for '%s'%s.", |
| 1280 |
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); |
1478 |
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); |
|
|
1479 |
#endif /* USE_SSL */ |
| 1281 |
return (fdopen(pdata, mode)); |
1480 |
return (fdopen(pdata, mode)); |
| 1282 |
} |
1481 |
} |
| 1283 |
if (data >= 0) { |
1482 |
if (data >= 0) { |
|
Lines 1327-1334
static FILE * dataconn(const char *name,
Link Here
|
| 1327 |
data = -1; |
1526 |
data = -1; |
| 1328 |
return (NULL); |
1527 |
return (NULL); |
| 1329 |
} |
1528 |
} |
|
|
1529 |
#ifdef USE_SSL |
| 1530 |
/* time to negotiate SSL on the data connection ... |
| 1531 |
* do this via SSL_accept (as we are still the server |
| 1532 |
* even though things are started around the other way) |
| 1533 |
* |
| 1534 |
* note: we really *must* make sure the session stuff |
| 1535 |
* is copied correctly as we cannot afford a full |
| 1536 |
* SSL negotiation for each data socket! |
| 1537 |
*/ |
| 1538 |
/* TODO XXXX fill in the blanks :-) |
| 1539 |
*/ |
| 1540 |
ssl_data_active_flag=0; |
| 1541 |
if (ssl_active_flag && ssl_encrypt_data) { |
| 1542 |
/* do SSL */ |
| 1543 |
|
| 1544 |
reply(150, "Opening %s mode SSL data connection for %s%s.", |
| 1545 |
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); |
| 1546 |
|
| 1547 |
if (ssl_data_con!=NULL) { |
| 1548 |
SSL_free(ssl_data_con); |
| 1549 |
ssl_data_con=NULL; |
| 1550 |
} |
| 1551 |
ssl_data_con=(SSL *)SSL_new(ssl_ctx); |
| 1552 |
|
| 1553 |
/* copy session details ... */ |
| 1554 |
SSL_copy_session_id(ssl_data_con,ssl_con); |
| 1555 |
|
| 1556 |
/* for 0.5.2 - want to change the timeout value etc ... */ |
| 1557 |
|
| 1558 |
SSL_set_fd(ssl_data_con,data); |
| 1559 |
SSL_set_verify(ssl_data_con,ssl_verify_flag,NULL); |
| 1560 |
|
| 1561 |
/* if is "safe" to read ahead */ |
| 1562 |
/* SSL_set_read_ahead(ssl_data_con,1); */ |
| 1563 |
|
| 1564 |
if (ssl_debug_flag) |
| 1565 |
BIO_printf(bio_err,"===>START SSL_accept on DATA\n"); |
| 1566 |
|
| 1567 |
if (SSL_accept(ssl_data_con)<=0) { |
| 1568 |
static char errbuf[1024]; |
| 1569 |
|
| 1570 |
snprintf(errbuf, sizeof(errstr), "ftpd: SSL_accept DATA error %s\n", |
| 1571 |
ERR_error_string(ERR_get_error(),NULL)); |
| 1572 |
perror_reply(425, errbuf); |
| 1573 |
/* abort time methinks ... */ |
| 1574 |
fclose(file); |
| 1575 |
return NULL; |
| 1576 |
} else { |
| 1577 |
if (ssl_debug_flag) |
| 1578 |
BIO_printf(bio_err,"[SSL DATA Cipher %s]\n", |
| 1579 |
SSL_get_cipher(ssl_con)); |
| 1580 |
ssl_data_active_flag=1; |
| 1581 |
} |
| 1582 |
|
| 1583 |
if (ssl_debug_flag) |
| 1584 |
BIO_printf(bio_err,"===>DONE SSL_accept on DATA\n"); |
| 1585 |
|
| 1586 |
} else { |
| 1587 |
reply(150, "Opening %s mode data connection for %s%s.", |
| 1588 |
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); |
| 1589 |
} |
| 1590 |
#else /* !USE_SSL */ |
| 1330 |
reply(150, "Opening %s mode data connection for '%s'%s.", |
1591 |
reply(150, "Opening %s mode data connection for '%s'%s.", |
| 1331 |
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); |
1592 |
type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); |
|
|
1593 |
#endif /* USE_SSL */ |
| 1332 |
return (file); |
1594 |
return (file); |
| 1333 |
} |
1595 |
} |
| 1334 |
|
1596 |
|
|
Lines 1357-1367
static void send_data(FILE *instr, FILE
Link Here
|
| 1357 |
if (c == '\n') { |
1619 |
if (c == '\n') { |
| 1358 |
if (ferror(outstr)) |
1620 |
if (ferror(outstr)) |
| 1359 |
goto data_err; |
1621 |
goto data_err; |
| 1360 |
(void) putc('\r', outstr); |
1622 |
(void) DATAPUTC('\r', outstr); |
| 1361 |
} |
1623 |
} |
| 1362 |
(void) putc(c, outstr); |
1624 |
(void) DATAPUTC(c, outstr); |
| 1363 |
} |
1625 |
} |
| 1364 |
fflush(outstr); |
1626 |
DATAFLUSH(outstr); |
| 1365 |
transflag = 0; |
1627 |
transflag = 0; |
| 1366 |
if (ferror(instr)) |
1628 |
if (ferror(instr)) |
| 1367 |
goto file_err; |
1629 |
goto file_err; |
|
Lines 1379-1385
static void send_data(FILE *instr, FILE
Link Here
|
| 1379 |
netfd = fileno(outstr); |
1641 |
netfd = fileno(outstr); |
| 1380 |
filefd = fileno(instr); |
1642 |
filefd = fileno(instr); |
| 1381 |
|
1643 |
|
| 1382 |
if (isreg && filesize < (off_t)16 * 1024 * 1024) { |
1644 |
if ( |
|
|
1645 |
#ifdef USE_SSL |
| 1646 |
!ssl_data_active_flag && |
| 1647 |
#endif /* USE_SSL */ |
| 1648 |
isreg && filesize < (off_t)16 * 1024 * 1024) { |
| 1383 |
buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd, |
1649 |
buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd, |
| 1384 |
(off_t)0); |
1650 |
(off_t)0); |
| 1385 |
if (buf==MAP_FAILED || buf==NULL) { |
1651 |
if (buf==MAP_FAILED || buf==NULL) { |
|
Lines 1420-1425
oldway:
Link Here
|
| 1420 |
/* failure is harmless */ |
1686 |
/* failure is harmless */ |
| 1421 |
} |
1687 |
} |
| 1422 |
#endif |
1688 |
#endif |
|
|
1689 |
#ifdef USE_SSL |
| 1690 |
if (ssl_data_active_flag) { |
| 1691 |
while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && |
| 1692 |
SSL_write(ssl_data_con, buf, cnt) == cnt) |
| 1693 |
byte_count += cnt; |
| 1694 |
} else |
| 1695 |
#endif /* USE_SSL */ |
| 1423 |
while ((cnt = read(filefd, buf, size)) > 0 && |
1696 |
while ((cnt = read(filefd, buf, size)) > 0 && |
| 1424 |
write(netfd, buf, cnt) == cnt) |
1697 |
write(netfd, buf, cnt) == cnt) |
| 1425 |
byte_count += cnt; |
1698 |
byte_count += cnt; |
|
Lines 1478-1483
static int receive_data(FILE *instr, FIL
Link Here
|
| 1478 |
case TYPE_L: |
1751 |
case TYPE_L: |
| 1479 |
signal (SIGALRM, lostconn); |
1752 |
signal (SIGALRM, lostconn); |
| 1480 |
|
1753 |
|
|
|
1754 |
#ifdef USE_SSL |
| 1755 |
if (ssl_data_active_flag) { |
| 1756 |
while ((cnt = SSL_read(ssl_data_con,buf,sizeof buf)) > 0) { |
| 1757 |
if (write(fileno(outstr), buf, cnt) != cnt) |
| 1758 |
goto file_err; |
| 1759 |
byte_count += cnt; |
| 1760 |
} |
| 1761 |
} else |
| 1762 |
#endif /* !USE_SSL */ |
| 1763 |
{ |
| 1481 |
do { |
1764 |
do { |
| 1482 |
(void) alarm ((unsigned) timeout); |
1765 |
(void) alarm ((unsigned) timeout); |
| 1483 |
cnt = read(fileno(instr), buf, sizeof(buf)); |
1766 |
cnt = read(fileno(instr), buf, sizeof(buf)); |
|
Lines 1489-1494
static int receive_data(FILE *instr, FIL
Link Here
|
| 1489 |
byte_count += cnt; |
1772 |
byte_count += cnt; |
| 1490 |
} |
1773 |
} |
| 1491 |
} while (cnt > 0); |
1774 |
} while (cnt > 0); |
|
|
1775 |
} |
| 1492 |
if (cnt < 0) |
1776 |
if (cnt < 0) |
| 1493 |
goto data_err; |
1777 |
goto data_err; |
| 1494 |
transflag = 0; |
1778 |
transflag = 0; |
|
Lines 1500-1513
static int receive_data(FILE *instr, FIL
Link Here
|
| 1500 |
return (-1); |
1784 |
return (-1); |
| 1501 |
|
1785 |
|
| 1502 |
case TYPE_A: |
1786 |
case TYPE_A: |
| 1503 |
while ((c = getc(instr)) != EOF) { |
1787 |
while ((c = DATAGETC(instr)) != EOF) { |
| 1504 |
byte_count++; |
1788 |
byte_count++; |
| 1505 |
if (c == '\n') |
1789 |
if (c == '\n') |
| 1506 |
bare_lfs++; |
1790 |
bare_lfs++; |
| 1507 |
while (c == '\r') { |
1791 |
while (c == '\r') { |
| 1508 |
if (ferror(outstr)) |
1792 |
if (ferror(outstr)) |
| 1509 |
goto data_err; |
1793 |
goto data_err; |
| 1510 |
if ((c = getc(instr)) != '\n') { |
1794 |
if ((c = DATAGETC(instr)) != '\n') { |
| 1511 |
(void) putc ('\r', outstr); |
1795 |
(void) putc ('\r', outstr); |
| 1512 |
if (c == '\0' || c == EOF) |
1796 |
if (c == '\0' || c == EOF) |
| 1513 |
goto contin2; |
1797 |
goto contin2; |
|
Lines 1644-1655
reply(int n, const char *fmt, ...)
Link Here
|
| 1644 |
reply(int n, char *fmt, va_dcl va_alist) |
1928 |
reply(int n, char *fmt, va_dcl va_alist) |
| 1645 |
#endif |
1929 |
#endif |
| 1646 |
{ |
1930 |
{ |
|
|
1931 |
#ifdef USE_SSL |
| 1932 |
char outputbuf[2048]; /* allow for a 2k command string */ |
| 1933 |
#endif /* USE_SSL */ |
| 1647 |
va_list ap; |
1934 |
va_list ap; |
| 1648 |
#ifdef __STDC__ |
1935 |
#ifdef __STDC__ |
| 1649 |
va_start(ap, fmt); |
1936 |
va_start(ap, fmt); |
| 1650 |
#else |
1937 |
#else |
| 1651 |
va_start(ap); |
1938 |
va_start(ap); |
| 1652 |
#endif |
1939 |
#endif |
|
|
1940 |
#ifdef USE_SSL |
| 1941 |
/* assemble the output into a buffer, checking for length*/ |
| 1942 |
sprintf(outputbuf,"%d ",n); |
| 1943 |
vsnprintf(outputbuf+strlen(outputbuf),sizeof(outputbuf)-(strlen(outputbuf) + 3), fmt, ap); |
| 1944 |
strcat(outputbuf,"\r\n"); |
| 1945 |
|
| 1946 |
if (ssl_debug_flag) |
| 1947 |
BIO_printf(bio_err,"\n<--- %s",outputbuf); |
| 1948 |
|
| 1949 |
if (ssl_active_flag) { |
| 1950 |
SSL_write(ssl_con,outputbuf,strlen(outputbuf)); |
| 1951 |
} else { |
| 1952 |
fprintf(stdout,"%s",outputbuf); |
| 1953 |
fflush(stdout); |
| 1954 |
} |
| 1955 |
if (debug) |
| 1956 |
syslog(LOG_DEBUG, "<--- %s ", outputbuf); |
| 1957 |
#else /* !USE_SSL */ |
| 1653 |
(void)printf("%d ", n); |
1958 |
(void)printf("%d ", n); |
| 1654 |
(void)vprintf(fmt, ap); |
1959 |
(void)vprintf(fmt, ap); |
| 1655 |
(void)printf("\r\n"); |
1960 |
(void)printf("\r\n"); |
|
Lines 1658-1663
reply(int n, char *fmt, va_dcl va_alist)
Link Here
|
| 1658 |
syslog(LOG_DEBUG, "<--- %d ", n); |
1963 |
syslog(LOG_DEBUG, "<--- %d ", n); |
| 1659 |
vsyslog(LOG_DEBUG, fmt, ap); |
1964 |
vsyslog(LOG_DEBUG, fmt, ap); |
| 1660 |
} |
1965 |
} |
|
|
1966 |
#endif /* USE_SSL */ |
| 1967 |
va_end(ap); |
| 1661 |
} |
1968 |
} |
| 1662 |
|
1969 |
|
| 1663 |
void |
1970 |
void |
|
Lines 1670-1681
lreply(n, fmt, va_alist)
Link Here
|
| 1670 |
va_dcl |
1977 |
va_dcl |
| 1671 |
#endif |
1978 |
#endif |
| 1672 |
{ |
1979 |
{ |
|
|
1980 |
#ifdef USE_SSL |
| 1981 |
char outputbuf[2048]; /* allow for a 2k command string */ |
| 1982 |
#endif /* USE_SSL */ |
| 1673 |
va_list ap; |
1983 |
va_list ap; |
| 1674 |
#ifdef __STDC__ |
1984 |
#ifdef __STDC__ |
| 1675 |
va_start(ap, fmt); |
1985 |
va_start(ap, fmt); |
| 1676 |
#else |
1986 |
#else |
| 1677 |
va_start(ap); |
1987 |
va_start(ap); |
| 1678 |
#endif |
1988 |
#endif |
|
|
1989 |
|
| 1990 |
#ifdef USE_SSL |
| 1991 |
/* assemble the output into a buffer */ |
| 1992 |
sprintf(outputbuf,"%d- ",n); |
| 1993 |
vsnprintf(outputbuf+strlen(outputbuf), sizeof(outputbuf)-(strlen(outputbuf) + 3) fmt, ap); |
| 1994 |
strcat(outputbuf,"\r\n"); |
| 1995 |
|
| 1996 |
if (ssl_debug_flag) |
| 1997 |
BIO_printf(bio_err,"\n<--- %s",outputbuf); |
| 1998 |
|
| 1999 |
if (ssl_active_flag) { |
| 2000 |
SSL_write(ssl_con,outputbuf,strlen(outputbuf)); |
| 2001 |
} else { |
| 2002 |
fprintf(stdout,"%s",outputbuf); |
| 2003 |
fflush(stdout); |
| 2004 |
} |
| 2005 |
if (debug) |
| 2006 |
syslog(LOG_DEBUG, "<--- %s ", outputbuf); |
| 2007 |
#else /* !USE_SSL */ |
| 1679 |
(void)printf("%d- ", n); |
2008 |
(void)printf("%d- ", n); |
| 1680 |
(void)vprintf(fmt, ap); |
2009 |
(void)vprintf(fmt, ap); |
| 1681 |
(void)printf("\r\n"); |
2010 |
(void)printf("\r\n"); |
|
Lines 1684-1689
lreply(n, fmt, va_alist)
Link Here
|
| 1684 |
syslog(LOG_DEBUG, "<--- %d- ", n); |
2013 |
syslog(LOG_DEBUG, "<--- %d- ", n); |
| 1685 |
vsyslog(LOG_DEBUG, fmt, ap); |
2014 |
vsyslog(LOG_DEBUG, fmt, ap); |
| 1686 |
} |
2015 |
} |
|
|
2016 |
#endif /* USE_SSL */ |
| 2017 |
va_end(ap); |
| 1687 |
} |
2018 |
} |
| 1688 |
|
2019 |
|
| 1689 |
static void ack(const char *s) |
2020 |
static void ack(const char *s) |
|
Lines 2046-2051
void send_file_list(const char *whichf)
Link Here
|
| 2046 |
volatile int simple = 0; |
2377 |
volatile int simple = 0; |
| 2047 |
volatile int freeglob = 0; |
2378 |
volatile int freeglob = 0; |
| 2048 |
glob_t gl; |
2379 |
glob_t gl; |
|
|
2380 |
char buf[1024]; |
| 2049 |
|
2381 |
|
| 2050 |
/* XXX: should the { go away if __linux__? */ |
2382 |
/* XXX: should the { go away if __linux__? */ |
| 2051 |
if (strpbrk(whichf, "~{[*?") != NULL) { |
2383 |
if (strpbrk(whichf, "~{[*?") != NULL) { |
|
Lines 2106-2113
void send_file_list(const char *whichf)
Link Here
|
| 2106 |
goto out; |
2438 |
goto out; |
| 2107 |
transflag++; |
2439 |
transflag++; |
| 2108 |
} |
2440 |
} |
| 2109 |
fprintf(dout, "%s%s\n", dirname, |
2441 |
snprintf(buf, sizeof(buf), "%s%s\n", dirname, |
| 2110 |
type == TYPE_A ? "\r" : ""); |
2442 |
type == TYPE_A ? "\r" : ""); |
|
|
2443 |
#ifdef USE_SSL |
| 2444 |
if (ssl_active_flag) |
| 2445 |
SSL_write(ssl_data_con,buf,strlen(buf)); |
| 2446 |
else |
| 2447 |
#endif /* USE_SSL */ |
| 2448 |
fwrite(buf,strlen(buf),1,dout); |
| 2111 |
byte_count += strlen(dirname) + 1; |
2449 |
byte_count += strlen(dirname) + 1; |
| 2112 |
continue; |
2450 |
continue; |
| 2113 |
} else if (!S_ISDIR(st.st_mode)) |
2451 |
} else if (!S_ISDIR(st.st_mode)) |
|
Lines 2149-2159
void send_file_list(const char *whichf)
Link Here
|
| 2149 |
transflag++; |
2487 |
transflag++; |
| 2150 |
} |
2488 |
} |
| 2151 |
if (nbuf[0] == '.' && nbuf[1] == '/') |
2489 |
if (nbuf[0] == '.' && nbuf[1] == '/') |
| 2152 |
fprintf(dout, "%s%s\n", &nbuf[2], |
2490 |
sprintf(buf, "%s%s\n", &nbuf[2], |
| 2153 |
type == TYPE_A ? "\r" : ""); |
2491 |
type == TYPE_A ? "\r" : ""); |
| 2154 |
else |
2492 |
else |
| 2155 |
fprintf(dout, "%s%s\n", nbuf, |
2493 |
sprintf(buf, "%s%s\n", nbuf, |
| 2156 |
type == TYPE_A ? "\r" : ""); |
2494 |
type == TYPE_A ? "\r" : ""); |
|
|
2495 |
#ifdef USE_SSL |
| 2496 |
if (ssl_active_flag) |
| 2497 |
SSL_write(ssl_data_con,buf,strlen(buf)); |
| 2498 |
else |
| 2499 |
#endif /* USE_SSL */ |
| 2500 |
fwrite(buf,strlen(buf),1,dout); |
| 2157 |
byte_count += strlen(nbuf) + 1; |
2501 |
byte_count += strlen(nbuf) + 1; |
| 2158 |
} |
2502 |
} |
| 2159 |
} |
2503 |
} |
|
Lines 2169-2174
void send_file_list(const char *whichf)
Link Here
|
| 2169 |
|
2513 |
|
| 2170 |
transflag = 0; |
2514 |
transflag = 0; |
| 2171 |
if (dout != NULL) |
2515 |
if (dout != NULL) |
|
|
2516 |
#ifdef USE_SSL |
| 2517 |
if (ssl_data_active_flag && (ssl_data_con!=NULL)) { |
| 2518 |
SSL_free(ssl_data_con); |
| 2519 |
ssl_data_active_flag=0; |
| 2520 |
ssl_data_con=NULL; |
| 2521 |
} |
| 2522 |
#endif /* USE_SSL */ |
| 2172 |
(void) fclose(dout); |
2523 |
(void) fclose(dout); |
| 2173 |
data = -1; |
2524 |
data = -1; |
| 2174 |
pdata = -1; |
2525 |
pdata = -1; |
|
Lines 2252-2254
static int check_host(struct sockaddr_in
Link Here
|
| 2252 |
} |
2603 |
} |
| 2253 |
#endif /* TCPWRAPPERS */ |
2604 |
#endif /* TCPWRAPPERS */ |
| 2254 |
|
2605 |
|
|
|
2606 |
#ifdef USE_SSL |
| 2607 |
|
| 2608 |
static |
| 2609 |
int |
| 2610 |
verify_callback(int ok, |
| 2611 |
X509_STORE_CTX *ctx); |
| 2612 |
|
| 2613 |
int |
| 2614 |
do_ssl_start(void) |
| 2615 |
{ |
| 2616 |
static char errstr[1024]; |
| 2617 |
|
| 2618 |
if (ssl_debug_flag) |
| 2619 |
BIO_printf(bio_err,"do_ssl_start triggered\n"); |
| 2620 |
|
| 2621 |
/* do the SSL stuff now ... before we play with pty's */ |
| 2622 |
ssl_con=(SSL *)SSL_new(ssl_ctx); |
| 2623 |
|
| 2624 |
/* we are working with stdin (inetd based) by default */ |
| 2625 |
SSL_set_fd(ssl_con,0); |
| 2626 |
|
| 2627 |
#if 0 |
| 2628 |
if (SSL_use_RSAPrivateKey(ssl_con,ssl_private_key)==0) { |
| 2629 |
snprintf(errstr, sizeof(errstr), "ftpd: SSL_use_RSAPrivateKey %s",ERR_error_string(ERR_get_error(),NULL)); |
| 2630 |
perror_reply(421, errstr); |
| 2631 |
dologout(1); |
| 2632 |
} |
| 2633 |
|
| 2634 |
if (SSL_use_certificate(ssl_con,ssl_public_cert)==0) { |
| 2635 |
snprintf(errstr, sizeof(errstr), "ftpd: SSL_use_certificate %s",ERR_error_string(ERR_get_error(),NULL)); |
| 2636 |
perror_reply(421, errstr); |
| 2637 |
dologout(1); |
| 2638 |
} |
| 2639 |
#endif |
| 2640 |
|
| 2641 |
SSL_set_verify(ssl_con,ssl_verify_flag, |
| 2642 |
ssl_certsok_flag ? verify_callback : NULL); |
| 2643 |
|
| 2644 |
if (SSL_accept(ssl_con)<=0) { |
| 2645 |
snprintf(errstr, sizeof(errstr), "ftpd: SSL_accept %s",ERR_error_string(ERR_get_error(),NULL)); |
| 2646 |
|
| 2647 |
perror_reply(421, errstr); |
| 2648 |
dologout(1); |
| 2649 |
|
| 2650 |
SSL_free(ssl_con); |
| 2651 |
ssl_con=NULL; |
| 2652 |
|
| 2653 |
/* we will probably want to know this sort of stuff ... |
| 2654 |
* at least for the moment I'd like to keep track of |
| 2655 |
* who is using SSL - later I will probably make this |
| 2656 |
* just a debug option and only log after the user has |
| 2657 |
* actually connected --tjh |
| 2658 |
*/ |
| 2659 |
if (logging) |
| 2660 |
syslog(LOG_NOTICE, "SSL FAILED WITH %s", remotehost); |
| 2661 |
|
| 2662 |
} else { |
| 2663 |
ssl_active_flag=1; |
| 2664 |
|
| 2665 |
if (logging) { |
| 2666 |
if (auth_ssl_name) |
| 2667 |
syslog(LOG_NOTICE, "SSL SUCCEEDED WITH %s as %s", remotehost, |
| 2668 |
auth_ssl_name); |
| 2669 |
else |
| 2670 |
syslog(LOG_NOTICE, "SSL SUCCEEDED WITH %s", remotehost); |
| 2671 |
} |
| 2672 |
} |
| 2673 |
|
| 2674 |
/* ssl_fprintf calls require that this be null to test |
| 2675 |
* for being an ssl stream |
| 2676 |
*/ |
| 2677 |
if (!ssl_active_flag) { |
| 2678 |
if (ssl_con!=NULL) |
| 2679 |
SSL_free(ssl_con); |
| 2680 |
ssl_con=NULL; |
| 2681 |
} |
| 2682 |
|
| 2683 |
return 0; |
| 2684 |
|
| 2685 |
} |
| 2686 |
|
| 2687 |
/* we really shouldn't have code like this! --tjh */ |
| 2688 |
int |
| 2689 |
ssl_getc(SSL *ssl_con) |
| 2690 |
{ |
| 2691 |
char onebyte; |
| 2692 |
|
| 2693 |
if (SSL_read(ssl_con,&onebyte,1)!=1) |
| 2694 |
return -1; |
| 2695 |
else { |
| 2696 |
if (ssl_debug_flag) |
| 2697 |
BIO_printf(bio_err,"ssl_getc: SSL_read %d (%c) ",onebyte & 0xff,isprint(onebyte)?onebyte:'.'); |
| 2698 |
return onebyte & 0xff; |
| 2699 |
} |
| 2700 |
} |
| 2701 |
|
| 2702 |
|
| 2703 |
/* got back to this an implemented some rather "simple" buffering */ |
| 2704 |
static char putc_buf[BUFSIZ]; |
| 2705 |
static int putc_buf_pos=0; |
| 2706 |
|
| 2707 |
static int |
| 2708 |
ssl_putc_flush(SSL *ssl_con) |
| 2709 |
{ |
| 2710 |
if (putc_buf_pos>0) { |
| 2711 |
if (SSL_write(ssl_con,putc_buf,putc_buf_pos)!=putc_buf_pos) { |
| 2712 |
if (ssl_debug_flag) |
| 2713 |
BIO_printf(bio_err,"ssl_putc_flush: WRITE FAILED\n"); |
| 2714 |
putc_buf_pos=0; |
| 2715 |
return -1; |
| 2716 |
} |
| 2717 |
} |
| 2718 |
putc_buf_pos=0; |
| 2719 |
return 0; |
| 2720 |
} |
| 2721 |
|
| 2722 |
static int |
| 2723 |
ssl_putc(SSL *ssl_con,int oneint) |
| 2724 |
{ |
| 2725 |
char onebyte; |
| 2726 |
|
| 2727 |
onebyte = oneint & 0xff; |
| 2728 |
|
| 2729 |
/* make sure there is space */ |
| 2730 |
if (putc_buf_pos>=BUFSIZ) |
| 2731 |
if (ssl_putc_flush(ssl_con)!=0) |
| 2732 |
return EOF; |
| 2733 |
putc_buf[putc_buf_pos++]=onebyte; |
| 2734 |
|
| 2735 |
return onebyte; |
| 2736 |
} |
| 2737 |
|
| 2738 |
static |
| 2739 |
int |
| 2740 |
verify_callback(int ok, |
| 2741 |
X509_STORE_CTX *ctx) |
| 2742 |
{ |
| 2743 |
int depth,error; |
| 2744 |
X509 *xs; |
| 2745 |
|
| 2746 |
depth=ctx->error_depth; |
| 2747 |
error=ctx->error; |
| 2748 |
xs=X509_STORE_CTX_get_current_cert(ctx); |
| 2749 |
|
| 2750 |
/* |
| 2751 |
* If the verification fails, then don't remember the name. However, |
| 2752 |
* if we don't require a certificate, then return success which will |
| 2753 |
* still allow us to set up an encrypted session. |
| 2754 |
* |
| 2755 |
*/ |
| 2756 |
if (!ok) { |
| 2757 |
/* If we can't verify the issuer, then don't accept the name. */ |
| 2758 |
if (depth != 0 && auth_ssl_name) { |
| 2759 |
free(auth_ssl_name); |
| 2760 |
auth_ssl_name = 0; |
| 2761 |
} |
| 2762 |
ok=ssl_verify_flag & SSL_VERIFY_FAIL_IF_NO_PEER_CERT ? 0 : 1; |
| 2763 |
goto done; |
| 2764 |
} |
| 2765 |
if (depth == 0) |
| 2766 |
auth_ssl_name = |
| 2767 |
(char *)ONELINE_NAME(X509_get_subject_name(xs)); |
| 2768 |
done: ; |
| 2769 |
|
| 2770 |
if (ssl_debug_flag) |
| 2771 |
BIO_printf(bio_err,"verify_callback: returning %d\n",ok); |
| 2772 |
|
| 2773 |
return ok; |
| 2774 |
} |
| 2775 |
|
| 2776 |
/* return true if this auth_ssl_name is authorized to use name. */ |
| 2777 |
int |
| 2778 |
good_ssl_user(char *name) |
| 2779 |
{ |
| 2780 |
FILE *user_fp; |
| 2781 |
char buf[2048]; |
| 2782 |
|
| 2783 |
if (!auth_ssl_name) |
| 2784 |
return 0; |
| 2785 |
if (!ssl_certsok_flag) |
| 2786 |
return 0; /* can't happen */ |
| 2787 |
user_fp = fopen("/etc/ssl.users", "r"); |
| 2788 |
if (!user_fp) |
| 2789 |
return 0; |
| 2790 |
while (fgets(buf, sizeof buf, user_fp)) { |
| 2791 |
char *cp; |
| 2792 |
char *n; |
| 2793 |
|
| 2794 |
/* allow for comments in the file ... always nice |
| 2795 |
* to be able to add a little novel in files and |
| 2796 |
* also disable easily --tjh |
| 2797 |
*/ |
| 2798 |
if (buf[0]=='#') |
| 2799 |
continue; |
| 2800 |
|
| 2801 |
if ((cp = strchr(buf, '\n'))) |
| 2802 |
*cp = '\0'; |
| 2803 |
cp = strchr(buf, ':'); |
| 2804 |
if (!cp) |
| 2805 |
continue; |
| 2806 |
*cp++ = '\0'; |
| 2807 |
if (strcasecmp(cp, auth_ssl_name) == 0) { |
| 2808 |
n = buf; |
| 2809 |
while (n) { |
| 2810 |
cp = strchr(n, ','); |
| 2811 |
if (cp) |
| 2812 |
*cp++ = '\0'; |
| 2813 |
if (!strcmp(name, n)) { |
| 2814 |
fclose(user_fp); |
| 2815 |
return 1; |
| 2816 |
} |
| 2817 |
n = cp; |
| 2818 |
} |
| 2819 |
} |
| 2820 |
} |
| 2821 |
fclose(user_fp); |
| 2822 |
return 0; |
| 2823 |
} |
| 2824 |
|
| 2825 |
#endif /* USE_SSL */ |