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

📄 ftpd.c

📁 功能强大的ftp服务器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        addreply_noformat(530, MSG_WHOAREYOU);        return;    }    authresult = pw_check(account, password, &ctrlconn, &peer);    {        /* Clear password from memory, paranoia */                register volatile char *password_ = (volatile char *) password;                while (*password_ != 0) {            *password_++ = 0;        }    }    if (authresult.auth_ok != 1) {        addreply_noformat(530, MSG_AUTH_FAILED);        doreply();        if (tapping >= MAX_PASSWD_TRIES) {            toomanytries:            logfile(LOG_ERR, MSG_AUTH_TOOMANY);            _EXIT(EXIT_FAILURE);        }        logfile(LOG_WARNING, MSG_AUTH_FAILED_LOG, account);        randomsleep:        tapping++;        usleep2((unsigned long) (zrand() % PASSWD_FAILURE_DELAY));                usleep2(tapping * PASSWD_FAILURE_DELAY);        return;    }    if (authresult.uid < useruid) {        logfile(LOG_WARNING, MSG_ACCOUNT_DISABLED, account);        if (tapping >= MAX_PASSWD_TRIES) {            goto toomanytries;        }        addreply_noformat(530, MSG_NOTRUST);        goto randomsleep;    }#ifdef PER_USER_LIMITS    if (per_user_max > 0U && ftpwho_read_count(account) >= per_user_max) {        addreply(421, MSG_PERUSER_MAX, (unsigned long) per_user_max);        doreply();        _EXIT(1);    }#endif        /* Add username to the uid/name cache */    (void) getname(authresult.uid);    if (#if defined(WITH_LDAP) || defined(WITH_MYSQL) || defined(WITH_PGSQL) || defined(WITH_PUREDB) || defined(WITH_EXTAUTH)        doinitsupgroups(NULL, authresult.uid, authresult.gid) != 0#else        doinitsupgroups(account, (uid_t) -1, authresult.gid) != 0#endif        ) {#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)        (void) 0;#else        die(421, LOG_WARNING, MSG_NOTRUST);#endif    }            /* handle /home/user/./public_html form */    if ((root_directory = strdup(authresult.dir)) == NULL) {        die_mem();    }    hd = strstr(root_directory, "/./");    if (hd != NULL) {        *++hd = 0;        hd++;        if (chrooted != 0) {            die(421, LOG_DEBUG, MSG_CANT_DO_TWICE);        }        if (create_home_and_chdir(root_directory) ||            chroot(root_directory) || chdir(hd)) {            die(421, LOG_ERR, MSG_NO_HOMEDIR);        }        chrooted = 1;#ifdef RATIOS        if (ratio_for_non_anon == 0) {            ratio_upload = ratio_download = 0U;        }        if (check_trustedgroup(authresult.uid, authresult.gid) != 0) {            dot_write_ok = dot_read_ok = 1;            ratio_upload = ratio_download = 0U;            keepallfiles = 0;        }#endif    } else {        (void) free(root_directory);        root_directory = (char *) "/";        if (create_home_and_chdir(authresult.dir)) {            /* non-chrooted users can see everything, so let them             in anyway */            if (userchroot == 0) {                addreply(0, MSG_NO_HOMEDIR2 " [%s].",                         authresult.dir, strerror(errno));                addreply_noformat(0, MSG_START_SLASH);                chdir("/");            } else {                die(421, LOG_ERR, MSG_NO_HOMEDIR);            }        }    }    if (getcwd(wd, sizeof wd - (size_t) 1U) == NULL) {        wd[0] = '/';        wd[1] = 0;    }#ifdef HAVE_SYS_FSUID_H    setfsuid(authresult.uid);#endif#ifndef NON_ROOT_FTP    if (setgid(authresult.gid) ||        setegid(authresult.gid)) {        _EXIT(EXIT_FAILURE);    }# ifndef HAVE_SYS_FSUID_H    if (seteuid(authresult.uid) != 0) {        _EXIT(EXIT_FAILURE);    }# endif#endif    if (check_trustedgroup(authresult.uid, authresult.gid) != 0) {        userchroot = 0;        dot_write_ok = dot_read_ok = 1;        keepallfiles = 0;#ifdef RATIOS        ratio_upload = ratio_download = 0U;#endif#ifdef QUOTAS        user_quota_files = user_quota_size = ULONG_LONG_MAX;#endif    }#ifdef QUOTAS    if (hasquota() == 0) {        userchroot = 1;    }#endif    if (loggedin == 0) {        candownload = 1;        /* real users can always download */    }#ifdef THROTTLING    if ((throttling == 2) || (guest != 0 && throttling == 1)) {        addreply_noformat(0, MSG_BANDWIDTH_RESTRICTED);        nice(NICE_VALUE);    } else {        throttling_delay = throttling_bandwidth_dl =            throttling_bandwidth_ul = 0UL;    }#endif#if !defined(MINIMAL) && defined(HAVE_GETGROUPS)# ifdef SAFE_GETGROUPS_0    ngroups = getgroups(0, NULL);    if (ngroups > ngroups_max) {	ngroups_max = ngroups;	    }# elif defined(_SC_NGROUPS_MAX)    /* get the run time value */    ngroups = (int) sysconf(_SC_NGROUPS_MAX);    if (ngroups > ngroups_max) {	ngroups_max = ngroups;	    }    # endif    if ((groups = malloc(sizeof(GETGROUPS_T) * ngroups_max)) == NULL) {	die_mem();    }    ngroups = getgroups(ngroups_max, groups);    if (guest == 0 && ngroups > 0) {        size_t p;        const char *q;        char reply[80];        if (SNCHECK(snprintf(reply, sizeof reply,                             MSG_USER_GROUP_ACCESS ": ", account),                    sizeof reply)) {            _EXIT(EXIT_FAILURE);        }        p = strlen(reply);        do {            ngroups--;            if ((ngroups != 0 && groups[ngroups] == groups[0]) ||                (q = getgroup(groups[ngroups])) == NULL) {                continue;            }            if (p + strlen(q) > 75) {                reply[p] = 0;                addreply(0, "%s", reply);                *reply = 0;                p = (size_t) 0U;            }            reply[p++] = ' ';            while (*q != 0 && p < sizeof reply) {                reply[p++] = *q++;            }        } while (ngroups > 0);        reply[p] = 0;        addreply(0, "%s", reply);    }    free(groups);#endif    if (guest == 0 && allowfxp == 1) {        addreply_noformat(0, MSG_FXP_SUPPORT);    }#ifdef RATIOS    if (ratio_for_non_anon != 0 && ratio_upload > 0) {        addreply(0, MSG_RATIO, ratio_upload, ratio_download);    }#endif    if (userchroot != 0 && chrooted == 0) {#ifndef NON_ROOT_FTP# ifndef HAVE_SYS_FSUID_H        disablesignals();        seteuid((uid_t) 0);# endif#endif        if (chdir(wd) || chroot(wd)) {    /* should never fail */#ifdef WITH_PRIVSEP            (void) setuid(authresult.uid);            (void) seteuid(authresult.uid);#else# ifndef HAVE_SYS_FSUID_H#  ifndef NON_ROOT_FTP            (void) seteuid(authresult.uid);#  endif# endif#endif            die(421, LOG_ERR, MSG_CHROOT_FAILED);        }#ifdef WITH_PRIVSEP        if (setuid(authresult.uid) != 0 || seteuid(authresult.uid) != 0) {            _EXIT(EXIT_FAILURE);        }        enablesignals();        #else# ifndef NON_ROOT_FTP#  ifndef HAVE_SYS_FSUID_H        if (seteuid(authresult.uid) != 0) {            _EXIT(EXIT_FAILURE);        }        enablesignals();#  endif# endif#endif#ifdef USE_CAPABILITIES        drop_login_caps();#endif                chrooted = 1;#ifdef RATIOS        if (ratio_for_non_anon == 0) {            ratio_upload = ratio_download = 0U;        }#endif        {            const size_t rd_len = strlen(wd) + sizeof "/";                        if ((root_directory = malloc(rd_len)) == NULL) {                die_mem();            }            snprintf(root_directory, rd_len, "%s/", wd);        }        wd[0] = '/';        wd[1] = 0;        if (chdir(wd)) {            _EXIT(EXIT_FAILURE);        }        addreply(230, MSG_CURRENT_RESTRICTED_DIR_IS, wd);    } else {        addreply(230, MSG_CURRENT_DIR_IS, wd);    }    logfile(LOG_INFO, MSG_IS_NOW_LOGGED_IN, account);#ifdef FTPWHO    if (shm_data_cur != NULL) {        ftpwho_lock();        strncpy(shm_data_cur->account, account,                sizeof shm_data_cur->account - (size_t) 1U);        shm_data_cur->account[sizeof shm_data_cur->account - 1U] = 0;        ftpwho_unlock();        state_needs_update = 1;    }#endif    loggedin = 1;    if (getcwd(wd, sizeof wd - (size_t) 1U) == NULL) {        wd[0] = '/';        wd[1] = 0;    }#ifndef MINIMAL    dobanner(0);#endif#ifdef QUOTAS    displayquota(NULL);#endif}void docwd(const char *dir){#ifndef MINIMAL    static unsigned long failures = 0UL;#endif    const char *where;    char buffer[MAXPATHLEN + 256U];    if (loggedin == 0) {        goto kaboom;    }    /*     * secure and conformant tilde expansion routine. Need to be packaged in     * a function so that it can be called in other commands and avoid     * duplicate code in ls.c             -frank.     */    where = dir;    if (dir == NULL || *dir == 0) {        goto gohome;    }    if (*dir == '~') {        const struct passwd *pw;        if (dir[1] == 0) {         /* cd ~ */            gohome:            strncpy(buffer, chrooted != 0 ? "/" : authresult.dir,                    sizeof buffer);            buffer[sizeof buffer - (size_t) 1U] = 0;            where = buffer;        } else {                   /* cd ~user or cd ~user/ */            char *bufpnt = buffer;            size_t s = sizeof buffer;            const char *dirscan = dir + 1;            while (*dirscan != 0 && *dirscan != '/') {                if (--s <= 0) {                    goto kaboom;   /* script kiddy's playing */                }                *bufpnt++ = *dirscan++;            }            *bufpnt = 0;            if (*buffer == 0) {        /* ~/... */                snprintf(buffer, sizeof buffer, "%s%s",                         chrooted != 0 ? "/" : authresult.dir, dirscan);                where = buffer;            } else if (authresult.slow_tilde_expansion == 0) {                if (chrooted != 0 || guest != 0 ||                    (pw = getpwnam(buffer)) == NULL || pw->pw_dir == NULL) {                    /* try with old where = dir */                } else {                    snprintf(buffer, sizeof buffer, "%s%s", pw->pw_dir, dirscan);                    where = buffer;                }            }        }    }    if (checknamesanity(where, dot_read_ok) != 0) {        addreply(550, MSG_SANITY_FILE_FAILURE, where);        return;    }    if (chdir(where) != 0) {        #ifdef WITH_DIRALIASES        const int real_errno = errno;        const char *where_alias;                if ((where_alias = lookup_alias(where)) == NULL ||            chdir(where_alias) != 0) {            errno = real_errno;        } else {            goto chdir_success;        }#endif	        if (SNCHECK(snprintf(buffer, sizeof buffer,                             MSG_CANT_CHANGE_DIR ": %s",                             dir, strerror(errno)), sizeof buffer)) {            _EXIT(EXIT_FAILURE);        }        logfile(LOG_INFO, "%s", buffer);        addreply(550, "%s", buffer);	#ifndef MINIMAL# ifndef NO_DIRSCAN_DELAY	if (failures >= MAX_DIRSCAN_TRIES) {	    _EXIT(EXIT_FAILURE);	}	usleep2(failures * DIRSCAN_FAILURE_DELAY);		failures++;# endif#endif	        return;    }    #ifdef WITH_DIRALIASES    chdir_success:#endif    #ifndef MINIMAL    failures = 0UL;    dobanner(1);#endif    if (getcwd(wd, sizeof wd - (size_t) 1U) == NULL) {        if (*dir == '/') {            if (SNCHECK(snprintf(wd, sizeof wd, "%s", dir), sizeof wd)) { /* already checked */                _EXIT(EXIT_FAILURE);            }        } else {            if (SNCHECK(snprintf(wd, sizeof wd, "%s/%s", wd, dir),                        sizeof wd)) {                kaboom:                die(421, LOG_ERR, MSG_PATH_TOO_LONG);            }        }    }    addreply(250, MSG_CURRENT_DIR_IS, wd);}static void iptropize(const struct sockaddr_storage *ss){    size_t t = sizeof *ss;    register const unsigned char *s = (const unsigned char *) ss;    iptropy = getpid();    do {        iptropy += (iptropy << 5);        iptropy ^= (int) *s++;    } while (--t > 0U);}#ifdef PROBE_RANDOM_AT_RUNTIMEstatic void pw_zrand_probe(void){    static const char * const devices[] = {        "/dev/arandom", "/dev/urandom", "/dev/random", NULL    };    register const char * const *device = devices;        do {        if (access(*device, F_OK | R_OK) == 0) {            random_device = *device;            break;        }        device++;    } while (*device != NULL);}#endifunsigned int zrand(void){    int fd;    int ret;    if (chrooted != 0 ||#ifdef PROBE_RANDOM_AT_RUNTIME        ((fd = open(random_device, O_RDONLY | O_NONBLOCK)) == -1)        #elif defined(HAVE_DEV_ARANDOM)        ((fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK)) == -1)#elif defined(HAVE_DEV_URANDOM)        ((fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) == -1)#else        ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) == -1)#endif        ) {        nax:#ifdef HAVE_RANDOM        return (unsigned int) (random() ^ iptropy);        #else        return (unsigned int) (rand() ^ iptropy);#endif    }    if (read(fd, &ret, sizeof ret) != (ssize_t) sizeof ret) {        (void) close(fd);        goto nax;    }    (void) close(fd);    return (unsigned int) (ret ^ iptropy);}static void keepalive(const int fd, int keep){#ifdef SO_KEEPALIVE    {        setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &keep, sizeof keep);    }#endif#ifdef SO_LINGER    {        struct linger li;        li.l_onoff = li.l_linger = 0;        setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof li);    }#endif}/* psvtype = 0: PASV *//* psvtype = 1: EPSV *//* psvtype = 2: SPSV */

⌨️ 快捷键说明

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