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

📄 ftpd.c

📁 功能强大的ftp服务器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    syslog(crit, "(%s@%s) %s%s",           ((loggedin != 0 && *account != 0) ? account : "?"),           (*host != 0 ? host : "?"),           urgency, line);# ifdef SAVE_DESCRIPTORS    closelog();# endif    va_end(va);#endif}#ifndef NO_STANDALONE/* this is taken from the code examples for Stevens' "Advanced * Programming in the Unix Environment. The code is publicly available * at ftp://ftp.uu.net/published/books/stevens.advprog.tar.Z */static unsigned int open_max(void){    long z;    if ((z = (long) sysconf(_SC_OPEN_MAX)) < 0L) {        perror("_SC_OPEN_MAX");        _EXIT(EXIT_FAILURE);    }    return (unsigned int) z;}#endifstatic void addreply_newline(const char * const str, const size_t size){    struct reply *newline;        if ((newline = (struct reply *) malloc(offsetof(struct reply, line) +                                           size)) == NULL) {        die_mem();    }    if (firstreply == NULL) {        firstreply = newline;    } else {        lastreply->next = newline;    }    newline->next = NULL;    lastreply = newline;    memcpy(newline->line, str, size);    }void addreply_noformat(const int code, const char * const line){    if (code != 0) {        replycode = code;    }    addreply_newline(line, strlen(line) + (size_t) 1U);}void addreply(const int code, const char * const line, ...){    register char *a;    register char *b;    va_list ap;    int last;    char buf[MAX_SERVER_REPLY_LEN];    if (code != 0) {        replycode = code;    }    va_start(ap, line);    vsnprintf(buf, sizeof buf, line, ap);    va_end(ap);    last = 0;    a = buf;    for (;;) {        b = strchr(a, '\n');        if (b != NULL) {            *b = 0;        } else {            b = a;            while (*b != 0) {                b++;            }            last++;        }        addreply_newline(a, (size_t) (b - a) + (size_t) 1U);        if (last != 0) {            break;        }        a = b + 1;    }}void doreply(void){    register struct reply *scannedentry;    register struct reply *nextentry;        if ((scannedentry = firstreply) == NULL) {        return;    }    CORK_ON(1);    do {        nextentry = scannedentry->next;#ifdef WITH_TLS        if (tls_cnx != NULL) {            char buf[MAX_SERVER_REPLY_LEN];                        snprintf(buf, sizeof buf, "%3d%c%s\r\n", replycode,                      nextentry == NULL ? ' ' : '-', scannedentry->line);            SSL_write(tls_cnx, buf, strlen(buf));                    } else#endif        {            printf("%3d%c%s\r\n", replycode, nextentry == NULL ? ' ' : '-',                   scannedentry->line);        }        if (logging > 1) {            logfile(LOG_DEBUG, "%3d%c%s", replycode,                     nextentry == NULL ? ' ' : '-', scannedentry->line);        }           } while ((scannedentry = nextentry) != NULL);    fflush(stdout);        CORK_OFF(1);    /* We don't free() after printf() because of Solaris stream bugs,     * Thanks to Kenneth Stailey */    scannedentry = firstreply;    do {        nextentry = scannedentry->next;        free(scannedentry);    } while ((scannedentry = nextentry) != NULL);    firstreply = lastreply = NULL;}/* Check whether a file name is valid. Files names starting * with a dot are only allowed to root and to users * chroot()ed in their home directories -Jedi. */static int checknamesanity(const char *name, int dot_ok){    register const char *namepnt;#ifdef PARANOID_FILE_NAMES    const char *validchars =        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"        "abcdefgihjklmnopqrstuvwxyz"        "0123456789./-_";#endif        if (name == NULL || *name == 0) {        return -1;    }    /* optimize . and .. */    if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {        return 0;    }    namepnt = name;#ifdef PARANOID_FILE_NAMES    /* we want to make sure we don't get any non-alphanumeric file name */    if (strlen(namepnt) != strspn(namepnt, validchars)) {        return -1;    }#endif#ifdef QUOTAS    if (hasquota() == 0 && strstr(namepnt, QUOTA_FILE) != NULL) {        return -1;                     /* .ftpquota => *NO* */    }#endif    if (strstr(namepnt, PUREFTPD_TMPFILE_PREFIX) != NULL) {        return -1;    }    while (*namepnt != 0) {        if (ISCTRLCODE(*namepnt) || *namepnt == '\\') {            return -1;        }        if (dot_ok == 0) {            if (*namepnt == '/') {                namepnt++;            } else if (namepnt != name) {                namepnt++;                continue;            }            if (namepnt[0] == 0) {     /* /$ */                return 0;            }            if (namepnt[0] == '.') {   /* /. */                if (namepnt[1] == 0) { /* /.$ => ok */                    return 0;                }                if (namepnt[1] == '.') {   /* /.. */                    if (namepnt[2] == 0) {   /* /..$ => ok */                        return 0;                    }                    if (namepnt[2] != '/') {   /* /..[^/] => *NO* */                        return -1;                    }                } else if (namepnt[1] != '/') {   /* /.[^/]/ => *NO* */                    return -1;                }            }            if (namepnt != name) {                continue;            }        }        namepnt++;    }    return 0;}static void do_ipv6_port(char *p, char delim){    char *deb;        struct sockaddr_storage a;    deb = p;    while (*p && strchr("0123456789abcdefABCDEF:", *p) != NULL) {        p++;    }    if (*p != delim || atoi(p + 1) == 0) {        nope:        (void) close(datafd);        datafd = -1;        addreply_noformat(501, MSG_SYNTAX_ERROR_IP);        return;    }    *p++ = 0;    if (generic_aton(deb, &a) != 0) {        goto nope;    }    doport2(a, (unsigned int) atoi(p));}#ifndef MINIMALvoid doesta(void){    struct sockaddr_storage dataconn;        socklen_t socksize;        char hbuf[NI_MAXHOST];    char pbuf[NI_MAXSERV];        if (passive != 0 || datafd == -1) {	addreply_noformat(520, MSG_ACTIVE_DISABLED);	return;    }    if (xferfd == -1) {	opendata();	if (xferfd == -1) {	    addreply_noformat(425, MSG_CANT_CREATE_DATA_SOCKET);	    return;	}    }    socksize = (socklen_t) sizeof dataconn;    if (getsockname(xferfd, (struct sockaddr *) &dataconn, &socksize) < 0 ||	getnameinfo((struct sockaddr *) &dataconn, STORAGE_LEN(dataconn),		    hbuf, sizeof hbuf, pbuf, sizeof pbuf,		    NI_NUMERICHOST | NI_NUMERICSERV) != 0) {	addreply_noformat(425, MSG_GETSOCKNAME_DATA);	closedata();	return;    }    addreply(225, "Connected from (|%c|%s|%s|)",	     STORAGE_FAMILY(dataconn) == AF_INET6 ? '2' : '1', hbuf, pbuf);}void doestp(void){    struct sockaddr_storage dataconn;    socklen_t socksize;            char hbuf[NI_MAXHOST];    char pbuf[NI_MAXSERV];        if (passive == 0 || datafd == -1) {	addreply_noformat(520, MSG_CANT_PASSIVE);	return;    }    if (xferfd == -1) {	opendata();	if (xferfd == -1) {	    addreply_noformat(425, MSG_CANT_CREATE_DATA_SOCKET);	    return;	}    }    socksize = (socklen_t) sizeof dataconn;    if (getpeername(xferfd, (struct sockaddr *) &dataconn, &socksize) < 0 ||	getnameinfo((struct sockaddr *) &dataconn, STORAGE_LEN(dataconn),		    hbuf, sizeof hbuf, pbuf, sizeof pbuf,		    NI_NUMERICHOST | NI_NUMERICSERV) != 0) {	addreply_noformat(425, MSG_GETSOCKNAME_DATA);	closedata();	return;    }    addreply(225, "Connected to (|%c|%s|%s|)",	     STORAGE_FAMILY(dataconn) == AF_INET6 ? '2' : '1', hbuf, pbuf);}#endifvoid doeprt(char *p){    char delim;    int family;    delim = *p++;    family = atoi(p);    while (isdigit((unsigned char) *p)) {        p++;    }    if (*p == delim) {        p++;    } else {        addreply_noformat(501, MSG_SYNTAX_ERROR_IP);        return;    }    if (family == 2 && v6ready) {        do_ipv6_port(p, delim);        return;    }    if (family != 1) {        if (v6ready) {            addreply_noformat(522, MSG_ONLY_IPV4V6);        } else {            addreply_noformat(522, MSG_ONLY_IPV4);        }        return;    }    {        unsigned int a1, a2, a3, a4, port = 0U;        /* there should be dot-decimal ip as rfc2428 states,         * but troll used for some reason "comma-decimal" notation         * so I decided to leave it */        if ((sscanf(p, "%u,%u,%u,%u", &a1, &a2, &a3, &a4) != 4 &&             sscanf(p, "%u.%u.%u.%u", &a1, &a2, &a3, &a4) != 4) ||            a1 > 255U || a2 > 255U || a3 > 255U || a4 > 255U ||            (a1 | a2 | a3 | a4) == 0U) {            addreply_noformat(501, MSG_SYNTAX_ERROR_IP);            return;        }        while (*p && strchr("0123456789.,", *p)) {            p++;        }        if (*p == delim) {            port = (unsigned int) atoi(++p);            while (*p && isdigit((unsigned char) *p)) {                p++;            }        }        if (*p != delim || port > 65535U || port <= 0U) {            addreply_noformat(501, MSG_SYNTAX_ERROR_IP);            return;        } else {            struct sockaddr_storage a;            memset(&a, 0, sizeof a);            STORAGE_FAMILY(a) = AF_INET;            STORAGE_SIN_ADDR(a) =                htonl((a1 << 24) | (a2 << 16) | (a3 << 8) | a4);            SET_STORAGE_LEN(a, sizeof(struct sockaddr_in));            doport2(a, port);        }    }}void stripctrl(char * const buf, size_t len){    if (len <= (size_t) 0U) {        return;    }    do {        len--;        if (ISCTRLCODE(buf[len]) &&            buf[len] != 0 && buf[len] != '\n') {            buf[len] = '_';        }    } while (len != (size_t) 0U);}#ifndef MINIMAL/* * small help routine to display a banner * type = 0 reads .banner/welcome.msg * type = 1 reads .message (after cd'ing into a directory) */void dobanner(const int type){    char buffer[512];        FILE *msg;    size_t buflen;    unsigned int nblines = BANNER_MAXLINES;            switch (type) {    case 0:	if ((msg = fopen(".banner", "r")) == NULL# ifdef WITH_WELCOME_MSG	    && (msg = fopen("welcome.msg", "r")) == NULL# endif	    ) {	    return;	}	break;    case 1:	if ((msg = fopen(".message", "r")) == NULL) {	    return;	}	break;    default:	return;    }	        while (fgets(buffer, sizeof buffer, msg) != NULL && nblines > 0U) {	nblines--;	    	if ((buflen = strlen(buffer)) > (size_t) 0U) {	    buflen--;	    while (buffer[buflen] == '\n' || buffer[buflen] == '\r') {		buffer[buflen] = 0;		if (buflen == (size_t) 0U) {		    break;		}		buflen--;	    }	    stripctrl(buffer, buflen);	}	addreply_noformat(0, buffer);    }    (void) fclose(msg);}#endif#ifndef MINIMALint modernformat(const char *file,                 char *target, size_t target_size){    const char *ft;    struct tm *t;    struct stat st;    int ret = 0;    if (stat(file, &st) != 0 ||        !(t = gmtime((time_t *) &st.st_mtime))) {        return -1;    }    if (S_ISREG(st.st_mode)) {        ft = "file";    } else if (S_ISDIR(st.st_mode)) {        ret = 1;        ft = "dir";        if (*file == '.') {            if (file[1] == '.' && file[2] == 0) {                ft = "pdir";            } else if (file[1] == 0) {                ft = "cdir";            }        } else if (*file == '/' && file[1] == 0) {            ft = "pdir";        }    } else {        ft = "unknown";    }    if (guest != 0) {        if (SNCHECK(snprintf(target, target_size,                             "type=%s;siz%c=%llu;modify=%04d%02d%02d%02d%02d%02d;UNIX.mode=0%o;unique=%xg%llx; %s",                             ft,                             ret ? 'd' : 'e',                             (unsigned long long) st.st_size,                             t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,                             t->tm_hour, t->tm_min, t->tm_sec,                             (unsigned int) st.st_mode & 07777,                             (unsigned int) st.st_dev,                             (unsigned long long) st.st_ino,                             file), target_size)) {            _EXIT(EXIT_FAILURE);        }    } else {        if (SNCHECK(snprintf(target, target_size,                             "type=%s;siz%c=%llu;modify=%04d%02d%02d%02d%02d%02d;UNIX.mode=0%o;UNIX.uid=%lld;UNIX.gid=%lld;unique=%xg%llx; %s",                             ft,                             ret ? 'd' : 'e',                             (unsigned long long) st.st_size,                             t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,                             t->tm_hour, t->tm_min, t->tm_sec,                             (unsigned int) st.st_mode & 07777,                             (unsigned long long) st.st_uid,                             (unsigned long long) st.st_gid,                             (unsigned int) st.st_dev,                             (unsigned long long) st.st_ino,                             file), target_size)) {            _EXIT(EXIT_FAILURE);        }    }    return ret;}

⌨️ 快捷键说明

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