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

📄 ftpd.c

📁 功能强大的ftp服务器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#define MLST_BEGIN "Begin" CRLFvoid domlst(const char * const file){    char line[MAXPATHLEN + 256U] = MLST_BEGIN;    if (modernformat(file, line + (sizeof MLST_BEGIN - 1U),                     sizeof line - (sizeof MLST_BEGIN - 1U)) >= 0) {        addreply_noformat(0, line);        addreply_noformat(250, "End.");    } else {        addreply_noformat(550, MSG_STAT_FAILURE2);    }}void donoop(void){#ifdef BORING_MODE    addreply_noformat(200, "dc.w $4E71");#else    addreply_noformat(200, MSG_SLEEPING);#endif}#endifvoid dositetime(void){    char tmp[64];    const struct tm *tm;    time_t now;        if ((now = time(NULL)) == (time_t) -1 || (tm = localtime(&now)) == NULL) {        addreply_noformat(550, "time()");        return;    }    strftime(tmp, sizeof tmp, "%Y-%m-%d %H:%M:%S", tm);    addreply_noformat(211, tmp);}static int doinitsupgroups(const char *user, const uid_t uid, const gid_t gid){#ifndef NON_ROOT_FTP# ifdef HAVE_SETGROUPS    if (setgroups(1U, &gid) != 0) {        return -1;    }# else    (void) gid;# endif# ifdef HAVE_INITGROUPS                if (user == NULL) {        const struct passwd * const lpwd = getpwuid(uid);                if (lpwd != NULL && lpwd->pw_name != NULL) {            user = lpwd->pw_name;        } else {                    return 0;        }    }    initgroups(user, gid);# else    (void) user;    (void) uid;# endif#else    (void) user;    (void) uid;    (void) gid;    #endif    return 0;}void douser(const char *username){    struct passwd *pw;    if (loggedin) {        if (username) {            if (!guest) {                addreply_noformat(530, MSG_ALREADY_LOGGED);            } else if (broken_client_compat) {                addreply_noformat(331, MSG_ANY_PASSWORD);            } else {                addreply_noformat(230, MSG_ANONYMOUS_LOGGED);                dot_read_ok = dot_read_anon_ok;                dot_write_ok = 0;            }        }        return;    }    if (anon_only <= 0 && username != NULL && *username != 0 &&        strcasecmp(username, "ftp") && strcasecmp(username, "anonymous")) {        strncpy(account, username, sizeof(account) - 1);        account[sizeof(account) - (size_t) 1U] = 0;        addreply(331, MSG_USER_OK, account);        loggedin = 0;    } else if (anon_only < 0) {           /* anonymous, but -E */        if (broken_client_compat != 0) {            addreply(331, MSG_USER_OK, username);            return;        } else {            die(530, LOG_DEBUG, MSG_NO_ANONYMOUS_LOGIN);        }    } else {#ifdef WITH_VIRTUAL_HOSTS        char name[MAXPATHLEN];        char hbuf[NI_MAXHOST];#endif        if (chrooted != 0) {            die(421, LOG_DEBUG, MSG_CANT_DO_TWICE);        }	#ifdef PER_USER_LIMITS        if (per_anon_max > 0U && ftpwho_read_count("ftp") >= per_anon_max) {            addreply(421, MSG_PERUSER_MAX, (unsigned long) per_anon_max);            doreply();            _EXIT(1);        }#endif	        #ifdef NON_ROOT_FTP        {            static struct passwd pw_;            char s[MAXPATHLEN + 1U];                                    if (getcwd(s, sizeof s - (size_t) 1U) == NULL) {                cantsec:                die(421, LOG_ERR, MSG_UNABLE_SECURE_ANON);            }            pw_.pw_uid = geteuid();            pw_.pw_gid = getegid();# if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)            if ((pw_.pw_dir = getenv("WIN32_ANON_DIR")) == NULL) {                pw_.pw_dir = WIN32_ANON_DIR;            }# else            pw_.pw_dir = strdup(s);    /* checked for == NULL later */# endif            pw = &pw_;        }#else        if ((pw = getpwnam("ftp")) == NULL ||            pw->pw_uid == 0 || pw->pw_gid == 0 ||            doinitsupgroups("ftp", (uid_t) -1, pw->pw_gid) != 0 ||            setgid(pw->pw_gid) || setegid(pw->pw_gid)) {            cantsec:            die(421, LOG_ERR, MSG_UNABLE_SECURE_ANON);        }#endif#ifdef WITH_VIRTUAL_HOSTS        if (getnameinfo((struct sockaddr *) &ctrlconn, STORAGE_LEN(ctrlconn),                        hbuf, sizeof hbuf, NULL,                        (size_t) 0U, NI_NUMERICHOST) != 0            || SNCHECK(snprintf(name, sizeof name, VHOST_PATH "/%s", hbuf),                       sizeof name)) {            _EXIT(EXIT_FAILURE);        }        if (chdir(name) != 0)         /* non-virtual */#endif        {            char *hd;            size_t rd_len;                        if (pw->pw_dir == NULL || *pw->pw_dir != '/') {                goto cantsec;            }            if ((hd = strstr(pw->pw_dir, "/./")) != NULL) {                rd_len = (size_t) (hd - pw->pw_dir) + sizeof "/";                if ((root_directory = malloc(rd_len)) == NULL) {                    goto cantsec;                }                memcpy(root_directory, pw->pw_dir, rd_len);                root_directory[rd_len - (size_t) 1U] = 0;                hd += 2;            } else {                rd_len = strlen(pw->pw_dir) + sizeof "/";                if ((root_directory = malloc(rd_len)) == NULL) {                    goto cantsec;                }                snprintf(root_directory, rd_len, "%s/", pw->pw_dir);                hd = (char *) "/";            }            if (chdir(root_directory) || chroot(root_directory) || chdir(hd)) {                goto cantsec;            }            logfile(LOG_INFO, MSG_ANONYMOUS_LOGGED);        }#ifdef WITH_VIRTUAL_HOSTS        else {                       /* virtual host */            const size_t rd_len = strlen(hbuf) + sizeof ":/";                    if ((root_directory = malloc(rd_len)) == NULL ||                chdir(name) || chroot(name) || chdir("/") ||                SNCHECK(snprintf(root_directory, rd_len, "%s:/", hbuf),                        rd_len)) {                goto cantsec;            }            logfile(LOG_INFO, MSG_ANONYMOUS_LOGGED_VIRTUAL ": %s", hbuf);        }#endif        chrooted = 1;        authresult.uid = pw->pw_uid;        authresult.gid = pw->pw_gid;        if ((authresult.dir = strdup(pw->pw_dir)) == NULL) {            die_mem();        }#ifdef THROTTLING        if (throttling != 0) {            addreply_noformat(0, MSG_BANDWIDTH_RESTRICTED);            nice(NICE_VALUE);        } else {            throttling_delay = throttling_bandwidth_ul =                throttling_bandwidth_dl = 0UL;        }#endif#ifndef NON_ROOT_FTP        if (authresult.uid > (uid_t) 0) {# ifdef WITH_PRIVSEP            if (setuid(authresult.uid) != 0 || seteuid(authresult.uid) != 0) {                goto cantsec;            }# else#  ifdef HAVE_SYS_FSUID_H            setfsgid(authresult.gid);            setfsuid(authresult.uid);#  else            if (seteuid(authresult.uid) != 0) {                goto cantsec;            }#  endif# endif        }#endif#ifdef USE_CAPABILITIES        drop_login_caps();#endif#ifndef MINIMAL        dobanner(0);#endif        if (broken_client_compat) {            addreply_noformat(331, MSG_ANONYMOUS_ANY_PASSWORD);        } else {            addreply_noformat(230, MSG_ANONYMOUS_LOGGED);        }        dot_write_ok = 0;        dot_read_ok = dot_read_anon_ok;        strncpy(account, "ftp", sizeof account - (size_t) 1U);        account[(sizeof account) - 1U] = 0;#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 = guest = 1;#ifdef QUOTAS        user_quota_size = user_quota_files = ULONG_LONG_MAX;#endif    }    if (getcwd(wd, sizeof wd - (size_t) 1U) == NULL) {        wd[0] = '/';        wd[1] = 0;    }}static AuthResult pw_check(const char *account, const char *password,                           const struct sockaddr_storage * const sa,                           const struct sockaddr_storage * const peer){    Authentications *auth_scan = first_authentications;    AuthResult result;    result.auth_ok = -1;    while (auth_scan != NULL) {#ifdef THROTTLING	result.throttling_bandwidth_ul = throttling_bandwidth_ul;	result.throttling_bandwidth_dl = throttling_bandwidth_dl;	result.throttling_ul_changed = result.throttling_dl_changed = 0;#endif#ifdef QUOTAS	result.user_quota_size = user_quota_size;	result.user_quota_files = user_quota_files;	result.quota_size_changed = result.quota_files_changed = 0;#endif#ifdef RATIOS	result.ratio_upload = ratio_upload;	result.ratio_download = ratio_download;	result.ratio_ul_changed = result.ratio_dl_changed = 0;#endif#ifdef PER_USER_LIMITS	result.per_user_max = per_user_max;#endif	        auth_scan->auth->check(&result, account, password, sa, peer);        if (result.auth_ok < 0) {	    break;	} else if (result.auth_ok > 0) {#ifdef THROTTLING            if ((result.throttling_ul_changed |                 result.throttling_dl_changed) != 0) {                if (result.throttling_ul_changed != 0 &&                    result.throttling_bandwidth_ul > 0UL) {                    throttling_bandwidth_ul = result.throttling_bandwidth_ul;                    ul_chunk_size = throttling_bandwidth_ul;                    if (ul_chunk_size > MAX_UL_CHUNK_SIZE) {                        ul_chunk_size = MAX_UL_CHUNK_SIZE;                    }                }                if (result.throttling_dl_changed != 0 &&                    result.throttling_bandwidth_dl > 0UL) {                    throttling_bandwidth_dl = result.throttling_bandwidth_dl;                    dl_chunk_size = throttling_bandwidth_dl & ~(map_size - 1);                    if (dl_chunk_size < map_size) {                        dl_chunk_size = map_size;                    }                }                throttling_delay = 1000000 /                    (throttling_bandwidth_dl | throttling_bandwidth_ul);                throttling = 2;            }#endif#ifdef QUOTAS            if (result.quota_size_changed != 0) {                user_quota_size = result.user_quota_size;            }            if (result.quota_files_changed != 0) {                user_quota_files = result.user_quota_files;            }#endif#ifdef RATIOS            if (result.ratio_ul_changed != 0) {                ratio_upload = result.ratio_upload;                ratio_for_non_anon = 1;            }            if (result.ratio_dl_changed != 0) {                ratio_download = result.ratio_download;            }#endif#ifdef PER_USER_LIMITS            per_user_max = result.per_user_max;#endif            #ifdef NON_ROOT_FTP            result.uid = geteuid();            result.gid = getegid();#endif                              return result;        }        auth_scan = auth_scan->next;    }        return result;}/* * Check if an user belongs to the trusted group, either in his * primary group, or his supplementary groups. Root is always trusted. */static int check_trustedgroup(const uid_t uid, const gid_t gid){    GETGROUPS_T *alloca_suppgroups;    int n;    int n2;    int result = 0;    if (uid == (uid_t) 0) {        return 1;    }    if (userchroot == 2) {        return 0;    }    if (gid == chroot_trustedgid) {        return 1;    }#ifdef HAVE_GETGROUPS    if ((n = getgroups(0, NULL)) <= 0) {        return 0;    }    if ((alloca_suppgroups =         ALLOCA(n * (sizeof *alloca_suppgroups))) == NULL) {        die_mem();    }    n2 = getgroups(n, alloca_suppgroups);    /* Jedi's paranoia */    if (n2 < n) {        n = n2;    }    result = 0;    while (n != 0) {        n--;        if (alloca_suppgroups[n] == (GETGROUPS_T) chroot_trustedgid) {            result = 1;            break;        }    };    ALLOCA_FREE(alloca_suppgroups);#endif        return result;}/* * Create a home directory on demand. */static int create_home_and_chdir(const char * const home){    char *pathcomp;    char *z;        size_t len;    const char delim = '/';                if (home == NULL || *home != '/') {        return -1;    }    if (chdir(home) == 0) {        return 0;    }    if (create_home == 0) {        return -1;    }    len = strlen(home) + (size_t) 1U;    if (len < (size_t) 2U || *home != delim) {        return -1;    }    if ((pathcomp = ALLOCA(len)) == NULL) {        return -1;    }    memcpy(pathcomp, home, len);       /* safe, no possible overflow */    z = pathcomp;    for (;;) {        z++;                if (*z == 0) {            break;        }        if (*z == delim) {            *z = 0;                        if (z[1] == 0) {                break;            }            (void) mkdir(pathcomp, (mode_t) 0755);            *z = delim;        }    }    ALLOCA_FREE(pathcomp);    (void) mkdir(home, (mode_t) 0700);    if (chdir(home) != 0) {	return -1;    }    if (chmod(home, (mode_t) 0755 & ~u_mask_d) < 0 ||        chown(home, authresult.uid, authresult.gid) < 0) {	return -1;    }        return chdir(home);}void dopass(char *password){    static unsigned int tapping;        gid_t *groups = NULL;    char *hd;    int ngroups;#if defined(NGROUPS_MAX) && NGROUPS_MAX > 0    int ngroups_max = NGROUPS_MAX; /* Use the compile time value */#else    int ngroups_max = 1; /* use a sane default */#endif        if (loggedin != 0) {        if (guest != 0) {            addreply_noformat(230, MSG_NO_PASSWORD_NEEDED);#ifdef LOG_ANON_EMAIL            snprintf(account, sizeof account, "ftp: <%s> ", password);#endif        } else {            addreply_noformat(530, MSG_CANT_DO_TWICE);        }        return;    }    if (*account == 0) {

⌨️ 快捷键说明

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