⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpd.c

📁 功能强大的ftp服务器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#include <config.h>#define DEFINE_GLOBALS#include "messages.h"#include "ftpd_p.h"#include "ipv4stack.h"#include "dynamic.h"#include "ftpwho-update.h"#include "ftpwho-read.h"#include "globals.h"#include "caps.h"#if defined(WITH_UPLOAD_SCRIPT)# include "upload-pipe.h"#endif#ifdef WITH_ALTLOG# include "altlog.h"#endif#ifdef QUOTAS# include "quotas.h"#endif#ifdef WITH_DIRALIASES# include "diraliases.h"#endif#include "ftpd.h"#include "bsd-glob.h"#include "getloadavg.h"#ifdef WITH_PRIVSEP# include "privsep.h"#endif#ifdef WITH_TLS# include "tls.h"#endif#ifdef WITH_DMALLOC# include <dmalloc.h>#endif#ifndef HAVE_SYS_FSUID_Hvoid disablesignals(void){    sigset_t sigs;    sigfillset(&sigs);    if (sigprocmask(SIG_BLOCK, &sigs, &old_sigmask) < 0) {        _EXIT(EXIT_FAILURE);    }}static void enablesignals(void){    if (sigprocmask(SIG_SETMASK, &old_sigmask, NULL) < 0) {        _EXIT(EXIT_FAILURE);    }}void usleep2(const unsigned long microsec){    disablesignals();    usleep(microsec);    enablesignals();}#endifint safe_write(const int fd, const void *buf_, size_t count){    ssize_t written;        register const char *buf = (const char *) buf_;    while (count > (size_t) 0U) {        for (;;) {            if ((written = write(fd, buf, count)) <= (ssize_t) 0) {                if (errno == EAGAIN) {                    sleep(1);                } else if (errno != EINTR) {                    return -1;                }                continue;            }            break;        }        buf += written;        count -= written;    }    return 0;}static void overlapcpy(register char *d, register const char *s){    while (*s != 0) {        *d++ = *s++;    }    *d = 0;}static void safe_fd_set(const int fd, fd_set * const fds){    if (fd == -1) {        return;    }    FD_SET(fd, fds);    }static int safe_fd_isset(const int fd, const fd_set * const fds){    if (fd == -1) {        return 0;    }    return FD_ISSET(fd, fds);}void simplify(char *subdir){    char *a;    if (subdir == NULL || *subdir == 0) {        return;    }    while ((a = strstr(subdir, "//")) != NULL) {        overlapcpy(a, a + 1);    }    while ((a = strstr(subdir, "/./")) != NULL) {        overlapcpy(a, a + 2);    }    while (strncmp(subdir, "../", 3) == 0) {        subdir += 3;    }    a = strstr(subdir, "/../");    if (a != NULL) {        if (a == subdir) {            while (strncmp(subdir, "/../", 4) == 0) {                overlapcpy(subdir, subdir + 3);            }            a = strstr(subdir, "/../");        }        while (a != NULL) {            char *nextcomponent = a + 4;            if (a != subdir && *a == '/') {                a--;            }            while (a != subdir && *a != '/') {                a--;            }            if (*a == '/') {                a++;            }            overlapcpy(a, nextcomponent);            a = strstr(subdir, "/../");        }    }    a = subdir;    if (*a == '.') {        a++;        if (*a == 0) {            return;        }        if (*a == '/') {            while (*a == '/') {                a++;            }            overlapcpy(subdir, a);        }    }}int checkprintable(register const char *s){    register int ret = 0;        register unsigned char c;        while ((c = (unsigned char) *s) != 0U) {        if (ISCTRLCODE(c)) {            ret--;            break;        }        s++;    }        return ret;    }void die(const int err, const int priority, const char * const format, ...){    va_list va;    char line[MAX_SYSLOG_LINE];    va_start(va, format);#ifndef HAVE_SYS_FSUID_H    disablesignals();#endif    vsnprintf(line, sizeof line, format, va);    printf("%d %s\r\n", err, line);    fflush(stdout);    logfile(priority, "%s", line);    va_end(va);    _EXIT(-priority - 1);}void die_mem(void){    die(421, LOG_ERR, MSG_OUT_OF_MEMORY);}static RETSIGTYPE sigurg(int sig){    int olderrno;    int readen;    unsigned char fodder;        (void) sig;    if (xferfd == -1) {        return;    }    olderrno = errno;    closedata();#ifndef HAVE_SYS_FSUID_H    disablesignals();#endif    addreply_noformat(426, MSG_ABORTED);    doreply();    do {        if ((readen = read(0, &fodder, (size_t) 1U)) < (ssize_t) 0 &&             errno == EINTR) {            continue;        }    } while (readen > (ssize_t) 0 && fodder != '\n');    addreply_noformat(226, MSG_ABORTED);    doreply();#ifndef HAVE_SYS_FSUID_H    enablesignals();#endif    errno = olderrno;}static RETSIGTYPE sigalarm(int sig){    (void) sig;#ifndef HAVE_SYS_FSUID_H    disablesignals();#endif        die(421, LOG_INFO, MSG_TIMEOUT);}#ifndef NO_STANDALONEstatic RETSIGTYPE sigchild(int sig){    const int olderrno = errno;    pid_t pid;    (void) sig;#ifdef HAVE_WAITPID    while ((pid = waitpid((pid_t) -1, NULL, WNOHANG)) > (pid_t) 0) {        if (nb_children > 0U) {            nb_children--;        }# ifdef FTPWHO        ftpwho_unlinksbfile(pid);# endif        iptrack_delete_pid(pid);    }#else    while ((pid = wait3(NULL, WNOHANG, NULL)) > (pid_t) 0) {        if (nb_children > 0U) {            nb_children--;        }# ifdef FTPWHO        ftpwho_unlinksbfile(pid);# endif        iptrack_delete_pid(pid);    }#endif    errno = olderrno;}#endifstatic RETSIGTYPE sigterm_client(int sig){    (void) sig;    #ifndef HAVE_SYS_FSUID_H    disablesignals();#endif    _EXIT(EXIT_SUCCESS);}#ifndef NO_STANDALONEstatic RETSIGTYPE sigterm(int sig){    const int olderrno = errno;    (void) sig;    stop_server = 1;    if (listenfd != -1) {        shutdown(listenfd, 2);        (void) close(listenfd);    }    errno = olderrno;}static void set_cloexec_flag(const int fd){    fcntl(fd, F_SETFD, FD_CLOEXEC);}#endifstatic void clearargs(int argc, char **argv){#ifndef NO_PROCNAME_CHANGE# if defined(__linux__) && !defined(HAVE_SETPROCTITLE)    int i;    for (i = 0; environ[i] != NULL; i++);    argv0 = argv;    if (i > 0) {        argv_lth = environ[i-1] + strlen(environ[i-1]) - argv0[0];    } else {        argv_lth = argv0[argc-1] + strlen(argv0[argc-1]) - argv0[0];    }    if (environ != NULL) {        char **new_environ;        unsigned int env_nb = 0U;        while (environ[env_nb] != NULL) {            env_nb++;        }        if ((new_environ = malloc((1U + env_nb) * sizeof (char *))) == NULL) {            abort();        }        new_environ[env_nb] = NULL;        while (env_nb > 0U) {            env_nb--;            /* Can any bad thing happen if strdup() ever fails? */            new_environ[env_nb] = strdup(environ[env_nb]);        }        environ = new_environ;    }# else    (void) argc;    (void) argv;# endif#endif}void setprogname(const char * const title){#ifndef NO_PROCNAME_CHANGE# ifdef HAVE_SETPROCTITLE    setproctitle("-%s", title);# elif defined(__linux__)    if (argv0 != NULL) {        memset(argv0[0], 0, argv_lth);        strncpy(argv0[0], title, argv_lth - 2);        argv0[1] = NULL;    }# elif defined(__hpux__)    union pstun pst;        pst.pst_command = title;    pstat(PSTAT_SETCMD, pst, strlen(title), 0, 0);# endif#endif    (void) title;}/* Check whether an address is valid, return 1 if ok, 0 otherwise. * Unfortunately, multicasting with the FTP protocol is impossible, * you have to use things like MTP instead. So prohibit multicast. */static int checkvalidaddr(const struct sockaddr_storage * const addr){    if (addr == NULL) {        return 0;    }    if (STORAGE_FAMILY(*addr) == AF_INET6) {        if (IN6_IS_ADDR_MULTICAST(&STORAGE_SIN_ADDR6_NF(*addr)) ||            IN6_IS_ADDR_UNSPECIFIED(&STORAGE_SIN_ADDR6_NF(*addr))) {            return 0;        }        return 1;    } else if (STORAGE_FAMILY(*addr) == AF_INET) {        if (ntohl(STORAGE_SIN_ADDR(*addr)) == INADDR_ANY ||            ntohl(STORAGE_SIN_ADDR(*addr)) == INADDR_NONE ||            ntohl(STORAGE_SIN_ADDR(*addr)) == INADDR_BROADCAST ||            IN_MULTICAST(ntohl(STORAGE_SIN_ADDR(*addr))) ||            IN_BADCLASS(ntohl(STORAGE_SIN_ADDR(*addr)))) {            return 0;        }        return 1;    }    return 0;}/* Convert a 4-in-6 address in pure IPv4 */static void fourinsix(struct sockaddr_storage *v6){    struct sockaddr_storage v4;    if (v6ready == 0 || STORAGE_FAMILY(*v6) != AF_INET6 ||        IN6_IS_ADDR_V4MAPPED(&STORAGE_SIN_ADDR6_NF(*v6)) == 0) {        return;    }    memset(&v4, 0, sizeof v4);    STORAGE_FAMILY(v4) = AF_INET;    memcpy(&STORAGE_SIN_ADDR(v4),           (unsigned char *) &STORAGE_SIN_ADDR6(*v6) + 12,           sizeof STORAGE_SIN_ADDR(v4));    STORAGE_PORT(v4) = STORAGE_PORT6(*v6);    SET_STORAGE_LEN(v4, sizeof(struct sockaddr_in));    *v6 = v4;}/* Return 0 if s1 == s2 , 1 if s1 != s2 , -1 if error */static int addrcmp(const struct sockaddr_storage * const s1,                   const struct sockaddr_storage * const s2){    if (STORAGE_FAMILY(*s1) == AF_INET6) {        if (STORAGE_FAMILY(*s2) != AF_INET6) {            return 1;        }        if (IN6_ARE_ADDR_EQUAL(&STORAGE_SIN_ADDR6_NF(*s1), &STORAGE_SIN_ADDR6_NF(*s2))) {            return 0;        } else {            return 1;        }    } else if (STORAGE_FAMILY(*s1) == AF_INET) {        if (STORAGE_FAMILY(*s2) != AF_INET) {            return 1;        }        if (STORAGE_SIN_ADDR(*s1) == STORAGE_SIN_ADDR(*s2)) {            return 0;        } else {            return 1;        }    }    return -1;}static int generic_aton(const char *src, struct sockaddr_storage *a){    if (inet_pton(AF_INET6, src, &STORAGE_SIN_ADDR6(*a)) > 0) {        STORAGE_FAMILY(*a) = AF_INET6;        return 0;    }    if (inet_pton(AF_INET, src, &STORAGE_SIN_ADDR(*a)) > 0) {        STORAGE_FAMILY(*a) = AF_INET;        return 0;    }    memset(a, 0, sizeof *a);    return -1;}void logfile(const int crit, const char *format, ...){#ifdef NON_ROOT_FTP    (void) crit;    (void) format;#else    const char *urgency;        va_list va;    char line[MAX_SYSLOG_LINE];    if (no_syslog != 0) {        return;    }    va_start(va, format);    vsnprintf(line, sizeof line, format, va);    switch (crit) {    case LOG_INFO:        urgency = "[INFO] ";        break;    case LOG_WARNING:        urgency = "[WARNING] ";        break;    case LOG_ERR:        urgency = "[ERROR] ";        break;    case LOG_NOTICE:        urgency = "[NOTICE] ";        break;    case LOG_DEBUG:        urgency = "[DEBUG] ";        break;    default:        urgency = "";    }# ifdef SAVE_DESCRIPTORS    openlog("pure-ftpd", log_pid, syslog_facility);# endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -