440 |
/* LOG_NDELAY sets up the logging connection immediately, |
/* LOG_NDELAY sets up the logging connection immediately, |
441 |
necessary for anonymous ftp's that chroot and can't do it later. */ |
necessary for anonymous ftp's that chroot and can't do it later. */ |
442 |
openlog ("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); |
openlog ("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); |
443 |
(void) freopen (PATH_DEVNULL, "w", stderr); |
freopen (PATH_DEVNULL, "w", stderr); |
444 |
|
|
445 |
/* If not running via inetd, we detach and dup(fd, 0), dup(fd, 1) the |
/* If not running via inetd, we detach and dup(fd, 0), dup(fd, 1) the |
446 |
fd = accept(). tcpd is check if compile with the support */ |
fd = accept(). tcpd is check if compile with the support */ |
460 |
} |
} |
461 |
} |
} |
462 |
|
|
463 |
(void) signal (SIGHUP, sigquit); |
signal (SIGHUP, sigquit); |
464 |
(void) signal (SIGINT, sigquit); |
signal (SIGINT, sigquit); |
465 |
(void) signal (SIGQUIT, sigquit); |
signal (SIGQUIT, sigquit); |
466 |
(void) signal (SIGTERM, sigquit); |
signal (SIGTERM, sigquit); |
467 |
(void) signal (SIGPIPE, lostconn); |
signal (SIGPIPE, lostconn); |
468 |
(void) signal (SIGCHLD, SIG_IGN); |
signal (SIGCHLD, SIG_IGN); |
469 |
if (signal (SIGURG, myoob) == SIG_ERR) |
if (signal (SIGURG, myoob) == SIG_ERR) |
470 |
syslog (LOG_ERR, "signal: %m"); |
syslog (LOG_ERR, "signal: %m"); |
471 |
|
|
526 |
|
|
527 |
/* Display a Welcome message if exists, |
/* Display a Welcome message if exists, |
528 |
N.B. reply(220,) must follow. */ |
N.B. reply(220,) must follow. */ |
529 |
(void) display_file (PATH_FTPWELCOME, 220); |
display_file (PATH_FTPWELCOME, 220); |
530 |
|
|
531 |
hostname = localhost (); |
hostname = localhost (); |
532 |
if (! hostname) |
if (! hostname) |
541 |
|
|
542 |
/* Set the jump, if we have an error parsing, |
/* Set the jump, if we have an error parsing, |
543 |
come here and start fresh. */ |
come here and start fresh. */ |
544 |
(void) setjmp (errcatch); |
setjmp (errcatch); |
545 |
|
|
546 |
/* Roll. */ |
/* Roll. */ |
547 |
for (;;) |
for (;;) |
548 |
(void) yyparse (); |
yyparse (); |
549 |
/* NOTREACHED */ |
/* NOTREACHED */ |
550 |
} |
} |
551 |
|
|
574 |
return (cred.guest ? path+1 : path); |
return (cred.guest ? path+1 : path); |
575 |
} |
} |
576 |
|
|
577 |
static void |
static RETSIGTYPE |
578 |
sigquit (int signo) |
sigquit (int signo) |
579 |
{ |
{ |
580 |
syslog (LOG_ERR, "got signal %s", strsignal (signo)); |
syslog (LOG_ERR, "got signal %s", strsignal (signo)); |
582 |
} |
} |
583 |
|
|
584 |
|
|
585 |
static void |
static RETSIGTYPE |
586 |
lostconn (int signo) |
lostconn (int signo ARG_UNUSED) |
587 |
{ |
{ |
588 |
(void)signo; |
signo; |
589 |
if (debug) |
if (debug) |
590 |
syslog (LOG_DEBUG, "lost connection"); |
syslog (LOG_DEBUG, "lost connection"); |
591 |
dologout (-1); |
dologout (-1); |
624 |
} |
} |
625 |
|
|
626 |
#ifdef HAVE_INITGROUPS |
#ifdef HAVE_INITGROUPS |
627 |
(void) initgroups (pcred->name, pcred->gid); |
initgroups (pcred->name, pcred->gid); |
628 |
#endif |
#endif |
629 |
|
|
630 |
/* open wtmp before chroot */ |
/* open wtmp before chroot */ |
631 |
(void)snprintf (ttyline, sizeof (ttyline), "ftp%d", getpid ()); |
snprintf (ttyline, sizeof (ttyline), "ftp%d", getpid ()); |
632 |
logwtmp_keep_open (ttyline, pcred->name, pcred->remotehost); |
logwtmp_keep_open (ttyline, pcred->name, pcred->remotehost); |
633 |
|
|
634 |
if (pcred->guest) |
if (pcred->guest) |
671 |
|
|
672 |
/* Display a login message, if it exists. |
/* Display a login message, if it exists. |
673 |
N.B. reply(230,) must follow the message. */ |
N.B. reply(230,) must follow the message. */ |
674 |
(void) display_file (PATH_FTPLOGINMESG, 230); |
display_file (PATH_FTPLOGINMESG, 230); |
675 |
|
|
676 |
if (pcred->guest) |
if (pcred->guest) |
677 |
{ |
{ |
697 |
syslog (LOG_INFO, "FTP LOGIN FROM %s as %s", |
syslog (LOG_INFO, "FTP LOGIN FROM %s as %s", |
698 |
pcred->remotehost, pcred->name); |
pcred->remotehost, pcred->name); |
699 |
} |
} |
700 |
(void) umask(defumask); |
umask(defumask); |
701 |
return; |
return; |
702 |
bad: |
bad: |
703 |
/* Forget all about it... */ |
/* Forget all about it... */ |
777 |
{ |
{ |
778 |
char *remotehost = pcred->remotehost; |
char *remotehost = pcred->remotehost; |
779 |
int atype = pcred->auth_type; |
int atype = pcred->auth_type; |
780 |
(void) seteuid ((uid_t)0); |
seteuid ((uid_t)0); |
781 |
if (pcred->logged_in) |
if (pcred->logged_in) |
782 |
logwtmp_keep_open (ttyline, "", ""); |
logwtmp_keep_open (ttyline, "", ""); |
783 |
|
|
920 |
if (dout == NULL) |
if (dout == NULL) |
921 |
goto done; |
goto done; |
922 |
send_data (fin, dout, buffer_size); |
send_data (fin, dout, buffer_size); |
923 |
(void) fclose (dout); |
fclose (dout); |
924 |
data = -1; |
data = -1; |
925 |
pdata = -1; |
pdata = -1; |
926 |
done: |
done: |
999 |
else |
else |
1000 |
reply (226, "Transfer complete."); |
reply (226, "Transfer complete."); |
1001 |
} |
} |
1002 |
(void) fclose (din); |
fclose (din); |
1003 |
data = -1; |
data = -1; |
1004 |
pdata = -1; |
pdata = -1; |
1005 |
done: |
done: |
1014 |
|
|
1015 |
if (data >= 0) |
if (data >= 0) |
1016 |
return fdopen (data, mode); |
return fdopen (data, mode); |
1017 |
(void) seteuid ((uid_t)0); |
seteuid ((uid_t)0); |
1018 |
s = socket (AF_INET, SOCK_STREAM, 0); |
s = socket (AF_INET, SOCK_STREAM, 0); |
1019 |
if (s < 0) |
if (s < 0) |
1020 |
goto bad; |
goto bad; |
1039 |
goto bad; |
goto bad; |
1040 |
sleep (tries); |
sleep (tries); |
1041 |
} |
} |
1042 |
(void) seteuid ((uid_t)cred.uid); |
seteuid ((uid_t)cred.uid); |
1043 |
|
|
1044 |
#if defined (IP_TOS) && defined (IPTOS_THROUGHPUT) && defined (IPPROTO_IP) |
#if defined (IP_TOS) && defined (IPTOS_THROUGHPUT) && defined (IPPROTO_IP) |
1045 |
{ |
{ |
1053 |
bad: |
bad: |
1054 |
/* Return the real value of errno (close may change it) */ |
/* Return the real value of errno (close may change it) */ |
1055 |
t = errno; |
t = errno; |
1056 |
(void) seteuid ((uid_t)cred.uid); |
seteuid ((uid_t)cred.uid); |
1057 |
(void) close(s); |
close(s); |
1058 |
errno = t; |
errno = t; |
1059 |
return NULL; |
return NULL; |
1060 |
} |
} |
1069 |
file_size = size; |
file_size = size; |
1070 |
byte_count = 0; |
byte_count = 0; |
1071 |
if (size != (off_t) -1) |
if (size != (off_t) -1) |
1072 |
(void) snprintf(sizebuf, sizeof(sizebuf), " (%s bytes)", |
snprintf(sizebuf, sizeof(sizebuf), " (%s bytes)", |
1073 |
off_to_str (size)); |
off_to_str (size)); |
1074 |
else |
else |
1075 |
*sizebuf = '\0'; |
*sizebuf = '\0'; |
1078 |
struct sockaddr_in from; |
struct sockaddr_in from; |
1079 |
int s, fromlen = sizeof (from); |
int s, fromlen = sizeof (from); |
1080 |
|
|
1081 |
(void) signal (SIGALRM, toolong); |
signal (SIGALRM, toolong); |
1082 |
(void) alarm ((unsigned) timeout); |
alarm ((unsigned) timeout); |
1083 |
s = accept (pdata, (struct sockaddr *)&from, &fromlen); |
s = accept (pdata, (struct sockaddr *)&from, &fromlen); |
1084 |
(void) alarm (0); |
alarm (0); |
1085 |
if (s < 0) |
if (s < 0) |
1086 |
{ |
{ |
1087 |
reply(425, "Can't open data connection."); |
reply(425, "Can't open data connection."); |
1088 |
(void) close (pdata); |
close (pdata); |
1089 |
pdata = -1; |
pdata = -1; |
1090 |
return NULL; |
return NULL; |
1091 |
} |
} |
1092 |
(void) close (pdata); |
close (pdata); |
1093 |
pdata = s; |
pdata = s; |
1094 |
#if defined (IP_TOS) && defined (IPTOS_THROUGHPUT) && defined (IPPROTO_IP) |
#if defined (IP_TOS) && defined (IPTOS_THROUGHPUT) && defined (IPPROTO_IP) |
1095 |
/* Optimize throughput. */ |
/* Optimize throughput. */ |
1096 |
{ |
{ |
1097 |
int tos = IPTOS_THROUGHPUT; |
int tos = IPTOS_THROUGHPUT; |
1098 |
(void) setsockopt (s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof (int)); |
setsockopt (s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof (int)); |
1099 |
} |
} |
1100 |
#endif |
#endif |
1101 |
#ifdef SO_KEEPALIVE |
#ifdef SO_KEEPALIVE |
1102 |
/* Set keepalives on the socket to detect dropped conns. */ |
/* Set keepalives on the socket to detect dropped conns. */ |
1103 |
{ |
{ |
1104 |
int keepalive = 1; |
int keepalive = 1; |
1105 |
(void) setsockopt (s, SOL_SOCKET, SO_KEEPALIVE, |
setsockopt (s, SOL_SOCKET, SO_KEEPALIVE, |
1106 |
(char *)&keepalive, sizeof (int)); |
(char *)&keepalive, sizeof (int)); |
1107 |
} |
} |
1108 |
#endif |
#endif |
1139 |
continue; |
continue; |
1140 |
} |
} |
1141 |
perror_reply (425, "Can't build data connection"); |
perror_reply (425, "Can't build data connection"); |
1142 |
(void) fclose (file); |
fclose (file); |
1143 |
data = -1; |
data = -1; |
1144 |
return NULL; |
return NULL; |
1145 |
} |
} |
1196 |
{ |
{ |
1197 |
if (ferror (outstr)) |
if (ferror (outstr)) |
1198 |
break; |
break; |
1199 |
(void) putc ('\r', outstr); |
putc ('\r', outstr); |
1200 |
} |
} |
1201 |
(void) putc (buf[len], outstr); |
putc (buf[len], outstr); |
1202 |
len++; |
len++; |
1203 |
} |
} |
1204 |
fflush (outstr); |
fflush (outstr); |
1217 |
{ |
{ |
1218 |
if (ferror (outstr)) |
if (ferror (outstr)) |
1219 |
goto data_err; |
goto data_err; |
1220 |
(void) putc ('\r', outstr); |
putc ('\r', outstr); |
1221 |
} |
} |
1222 |
(void) putc (c, outstr); |
putc (c, outstr); |
1223 |
} |
} |
1224 |
fflush (outstr); |
fflush (outstr); |
1225 |
transflag = 0; |
transflag = 0; |
1263 |
write(netfd, buf, cnt) == cnt) |
write(netfd, buf, cnt) == cnt) |
1264 |
byte_count += cnt; |
byte_count += cnt; |
1265 |
transflag = 0; |
transflag = 0; |
1266 |
(void)free (buf); |
free (buf); |
1267 |
if (cnt != 0) |
if (cnt != 0) |
1268 |
{ |
{ |
1269 |
if (cnt < 0) |
if (cnt < 0) |
1338 |
c = getc (instr); |
c = getc (instr); |
1339 |
if (c != '\n') |
if (c != '\n') |
1340 |
{ |
{ |
1341 |
(void) putc ('\r', outstr); |
putc ('\r', outstr); |
1342 |
if (c == '\0' || c == EOF) |
if (c == '\0' || c == EOF) |
1343 |
goto contin2; |
goto contin2; |
1344 |
} |
} |
1345 |
} |
} |
1346 |
(void) putc (c, outstr); |
putc (c, outstr); |
1347 |
contin2: ; |
contin2: ; |
1348 |
} |
} |
1349 |
fflush(outstr); |
fflush(outstr); |
1356 |
{ |
{ |
1357 |
lreply (226, "WARNING! %d bare linefeeds received in ASCII mode", |
lreply (226, "WARNING! %d bare linefeeds received in ASCII mode", |
1358 |
bare_lfs); |
bare_lfs); |
1359 |
(void)printf (" File may not have transferred correctly.\r\n"); |
printf (" File may not have transferred correctly.\r\n"); |
1360 |
} |
} |
1361 |
return (0); |
return (0); |
1362 |
default: |
default: |
1383 |
int c; |
int c; |
1384 |
char line[LINE_MAX]; |
char line[LINE_MAX]; |
1385 |
|
|
1386 |
(void)snprintf (line, sizeof(line), "/bin/ls -lgA %s", filename); |
snprintf (line, sizeof(line), "/bin/ls -lgA %s", filename); |
1387 |
fin = ftpd_popen (line, "r"); |
fin = ftpd_popen (line, "r"); |
1388 |
lreply (211, "status of %s:", filename); |
lreply (211, "status of %s:", filename); |
1389 |
while ((c = getc (fin)) != EOF) |
while ((c = getc (fin)) != EOF) |
1393 |
if (ferror (stdout)) |
if (ferror (stdout)) |
1394 |
{ |
{ |
1395 |
perror_reply (421, "control connection"); |
perror_reply (421, "control connection"); |
1396 |
(void) ftpd_pclose (fin); |
ftpd_pclose (fin); |
1397 |
dologout (1); |
dologout (1); |
1398 |
/* NOTREACHED */ |
/* NOTREACHED */ |
1399 |
} |
} |
1400 |
if (ferror (fin)) |
if (ferror (fin)) |
1401 |
{ |
{ |
1402 |
perror_reply (551, filename); |
perror_reply (551, filename); |
1403 |
(void) ftpd_pclose (fin); |
ftpd_pclose (fin); |
1404 |
return; |
return; |
1405 |
} |
} |
1406 |
(void) putc ('\r', stdout); |
putc ('\r', stdout); |
1407 |
} |
} |
1408 |
(void) putc (c, stdout); |
putc (c, stdout); |
1409 |
} |
} |
1410 |
(void) ftpd_pclose (fin); |
ftpd_pclose (fin); |
1411 |
reply (211, "End of Status"); |
reply (211, "End of Status"); |
1412 |
} |
} |
1413 |
|
|
1494 |
#else |
#else |
1495 |
va_start (ap); |
va_start (ap); |
1496 |
#endif |
#endif |
1497 |
(void)printf ("%d ", n); |
printf ("%d ", n); |
1498 |
(void)vprintf (fmt, ap); |
vprintf (fmt, ap); |
1499 |
(void)printf ("\r\n"); |
printf ("\r\n"); |
1500 |
(void)fflush (stdout); |
fflush (stdout); |
1501 |
if (debug) |
if (debug) |
1502 |
{ |
{ |
1503 |
syslog (LOG_DEBUG, "<--- %d ", n); |
syslog (LOG_DEBUG, "<--- %d ", n); |
1514 |
#else |
#else |
1515 |
va_start (ap); |
va_start (ap); |
1516 |
#endif |
#endif |
1517 |
(void)printf ("%d- ", n); |
printf ("%d- ", n); |
1518 |
(void)vprintf (fmt, ap); |
vprintf (fmt, ap); |
1519 |
(void)printf ("\r\n"); |
printf ("\r\n"); |
1520 |
(void)fflush (stdout); |
fflush (stdout); |
1521 |
if (debug) |
if (debug) |
1522 |
{ |
{ |
1523 |
syslog (LOG_DEBUG, "<--- %d- ", n); |
syslog (LOG_DEBUG, "<--- %d- ", n); |
1687 |
|
|
1688 |
if (cred.logged_in) |
if (cred.logged_in) |
1689 |
{ |
{ |
1690 |
(void) seteuid ((uid_t)0); |
seteuid ((uid_t)0); |
1691 |
logwtmp_keep_open (ttyline, "", ""); |
logwtmp_keep_open (ttyline, "", ""); |
1692 |
} |
} |
1693 |
/* beware of flushing buffers after a SIGPIPE */ |
/* beware of flushing buffers after a SIGPIPE */ |
1694 |
_exit (status); |
_exit (status); |
1695 |
} |
} |
1696 |
|
|
1697 |
static void |
static RETSIGTYPE |
1698 |
myoob (int signo) |
myoob (int signo ARG_UNUSED) |
1699 |
{ |
{ |
1700 |
char *cp; |
char *cp; |
1701 |
|
|
|
(void)signo; |
|
1702 |
/* only process if transfer occurring */ |
/* only process if transfer occurring */ |
1703 |
if (!transflag) |
if (!transflag) |
1704 |
return; |
return; |
1745 |
} |
} |
1746 |
pasv_addr = ctrl_addr; |
pasv_addr = ctrl_addr; |
1747 |
pasv_addr.sin_port = 0; |
pasv_addr.sin_port = 0; |
1748 |
(void) seteuid ((uid_t)0); |
seteuid ((uid_t)0); |
1749 |
if (bind (pdata, (struct sockaddr *)&pasv_addr, sizeof (pasv_addr)) < 0) |
if (bind (pdata, (struct sockaddr *)&pasv_addr, sizeof (pasv_addr)) < 0) |
1750 |
{ |
{ |
1751 |
(void) seteuid ((uid_t)cred.uid); |
seteuid ((uid_t)cred.uid); |
1752 |
goto pasv_error; |
goto pasv_error; |
1753 |
} |
} |
1754 |
(void) seteuid ((uid_t)cred.uid); |
seteuid ((uid_t)cred.uid); |
1755 |
len = sizeof(pasv_addr); |
len = sizeof(pasv_addr); |
1756 |
if (getsockname (pdata, (struct sockaddr *) &pasv_addr, &len) < 0) |
if (getsockname (pdata, (struct sockaddr *) &pasv_addr, &len) < 0) |
1757 |
goto pasv_error; |
goto pasv_error; |
1767 |
return; |
return; |
1768 |
|
|
1769 |
pasv_error: |
pasv_error: |
1770 |
(void) close (pdata); |
close (pdata); |
1771 |
pdata = -1; |
pdata = -1; |
1772 |
perror_reply (425, "Can't open passive connection"); |
perror_reply (425, "Can't open passive connection"); |
1773 |
return; |
return; |
1806 |
*cp++ = '.'; |
*cp++ = '.'; |
1807 |
for (count = 1; count < 100; count++) |
for (count = 1; count < 100; count++) |
1808 |
{ |
{ |
1809 |
(void)sprintf (cp, "%d", count); |
sprintf (cp, "%d", count); |
1810 |
if (stat (string, &st) < 0) |
if (stat (string, &st) < 0) |
1811 |
return string; |
return string; |
1812 |
} |
} |
1900 |
perror_reply (550, whichf); |
perror_reply (550, whichf); |
1901 |
if (dout != NULL) |
if (dout != NULL) |
1902 |
{ |
{ |
1903 |
(void) fclose (dout); |
fclose (dout); |
1904 |
transflag = 0; |
transflag = 0; |
1905 |
data = -1; |
data = -1; |
1906 |
pdata = -1; |
pdata = -1; |
1962 |
byte_count += strlen (nbuf) + 1; |
byte_count += strlen (nbuf) + 1; |
1963 |
} |
} |
1964 |
} |
} |
1965 |
(void) closedir (dirp); |
closedir (dirp); |
1966 |
} |
} |
1967 |
|
|
1968 |
if (dout == NULL) |
if (dout == NULL) |
1974 |
|
|
1975 |
transflag = 0; |
transflag = 0; |
1976 |
if (dout != NULL) |
if (dout != NULL) |
1977 |
(void) fclose (dout); |
fclose (dout); |
1978 |
data = -1; |
data = -1; |
1979 |
pdata = -1; |
pdata = -1; |
1980 |
out: |
out: |