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

📄 privsep.c

📁 功能强大的ftp服务器源代码
💻 C
字号:
#include <config.h>#ifdef WITH_PRIVSEP# include "ftpd.h"# include "dynamic.h"# include "ftpwho-update.h"# include "globals.h"# include "privsep_p.h"# include "privsep.h"# ifdef WITH_DMALLOC#  include <dmalloc.h># endifstatic int privsep_sendcmd(const int psfd, const void * const cmdarg,                           const size_t cmdarg_len){    ssize_t sent;        while ((sent = send(psfd, cmdarg, cmdarg_len, 0)) == (ssize_t) -1 &&           errno == EINTR);    if (sent != (ssize_t) cmdarg_len) {	return -1;    }        return 0;}static int privsep_recvcmd(const int psfd, void * const cmdarg,                           const size_t cmdarg_len){    ssize_t received;            while ((received = recv(psfd, cmdarg, cmdarg_len, 0)) == (ssize_t) -1 &&           errno == EINTR);    if (received != (ssize_t) cmdarg_len) {        return -1;    }        return 0;}int privsep_sendfd(const int psfd, const int fd){	    char *buf;    int *fdptr;    struct cmsghdr *cmsg;        struct msghdr msg;    struct iovec vec;    const size_t sizeof_buf = CMSG_SPACE(sizeof *fdptr);    PrivSepCmd fodder = PRIVSEPCMD_ANSWER_FD;    ssize_t sent;        if ((buf = ALLOCA(sizeof_buf)) == NULL) {	return -1;    }    memset(&msg, 0, sizeof msg);    vec.iov_base = (void *) &fodder;    vec.iov_len = sizeof fodder;    msg.msg_name = NULL;    msg.msg_namelen = (socklen_t) 0;    msg.msg_iov = &vec;    msg.msg_iovlen = (size_t) 1U;    msg.msg_control = buf;    msg.msg_controllen = sizeof_buf;    msg.msg_flags = 0;    if ((cmsg = CMSG_FIRSTHDR(&msg)) == NULL) {	ALLOCA_FREE(buf);	return -1;    }    cmsg->cmsg_len = CMSG_LEN(sizeof fd);    cmsg->cmsg_level = SOL_SOCKET;    cmsg->cmsg_type = SCM_RIGHTS;    if ((fdptr = (int *) CMSG_DATA(cmsg)) == NULL) {	ALLOCA_FREE(buf);		return -1;    }    *fdptr = fd;    msg.msg_controllen = cmsg->cmsg_len;    while ((sent = sendmsg(psfd, &msg, 0)) == (ssize_t) -1 && errno == EINTR);    ALLOCA_FREE(buf);        if (sent != (ssize_t) sizeof fodder) {	return -1;    }    return 0;}	int privsep_recvfd(const int psfd){    char *buf;    int *fdptr;        struct cmsghdr *cmsg;    struct msghdr msg;    struct iovec vec;    const size_t sizeof_buf = CMSG_SPACE(sizeof *fdptr);    PrivSepCmd fodder;        ssize_t received;        if ((buf = ALLOCA(sizeof_buf)) == NULL) {	return -1;    }    memset(&msg, 0, sizeof msg);    vec.iov_base = (void *) &fodder;    vec.iov_len = sizeof fodder;    msg.msg_name = NULL;    msg.msg_namelen = (socklen_t) 0;    msg.msg_iov = &vec;    msg.msg_iovlen = (size_t) 1U;    msg.msg_control = buf;    msg.msg_controllen = sizeof_buf;    msg.msg_flags = 0;    if ((cmsg = CMSG_FIRSTHDR(&msg)) == NULL ||	(fdptr = (int *) CMSG_DATA(cmsg)) == NULL) {		ALLOCA_FREE(buf);	return -1;	    }        *fdptr = -1;    while ((received = recvmsg(psfd, &msg, 0)) == (ssize_t) -1 &&            errno == EINTR);    if (received != (ssize_t) sizeof fodder ||	fodder != PRIVSEPCMD_ANSWER_FD ||	(cmsg = CMSG_FIRSTHDR(&msg)) == NULL ||	(fdptr = (int *) CMSG_DATA(cmsg)) == NULL) {	ALLOCA_FREE(buf);	return -1;    }    return *fdptr;}# ifdef FTPWHOstatic int privsep_privpart_removeftpwhoentry(const int psfd){    PrivSepAnswer answer;        if (scoreboardfile == NULL || unlink(scoreboardfile) != 0) {        answer.removeftpwhoentry.cmd = PRIVSEPCMD_ANSWER_ERROR;    } else {        answer.removeftpwhoentry.cmd = PRIVSEPCMD_ANSWER_REMOVEFTPWHOENTRY;    }    return privsep_sendcmd(psfd, &answer, sizeof answer);}int privsep_removeftpwhoentry(void){    PrivSepQuery query;    PrivSepQuery answer;        query.removeftpwhoentry.cmd = PRIVSEPCMD_REMOVEFTPWHOENTRY;    if (privsep_sendcmd(psfd, &query, sizeof query) != 0 ||        privsep_recvcmd(psfd, &answer, sizeof answer) != 0 ||        answer.removeftpwhoentry.cmd != PRIVSEPCMD_ANSWER_REMOVEFTPWHOENTRY) {        return -1;    }    return 0;    }# endifint privsep_privpart_bindresport(const int psfd,                                  const PrivSepQuery * const query){    static const unsigned short portlist[] = FTP_ACTIVE_SOURCE_PORTS;    const unsigned short *portlistpnt = portlist;        int fd;    int on = 1;    int ret;        if ((fd = socket(query->bindresport.protocol,                     SOCK_STREAM, IPPROTO_TCP)) == -1) {        goto bye;    }# ifdef SO_REUSEPORT    (void) setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &on, sizeof on);# else    (void) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof on);# endif    for (;;) {        if (query->bindresport.protocol == PF_INET6) {            STORAGE_PORT6(query->bindresport.ss) = htons(*portlistpnt);        } else {            STORAGE_PORT(query->bindresport.ss) = htons(*portlistpnt);        }        if (bind(fd, (struct sockaddr *) &query->bindresport.ss,                 STORAGE_LEN(query->bindresport.ss)) == 0) {            break;        }# ifdef USE_ONLY_FIXED_DATA_PORT        (void) sleep(1U);# else        if (*portlistpnt == (unsigned short) 0U) {            break;        }        portlistpnt++;# endif            }        bye:        ret = privsep_sendfd(psfd, fd);    ret |= close(fd);        return ret;}int privsep_bindresport(const int protocol, const struct sockaddr_storage ss){    PrivSepQuery query;        query.bindresport.cmd = PRIVSEPCMD_BINDRESPORT;    query.bindresport.protocol = protocol;    query.bindresport.ss = ss;    if (privsep_sendcmd(psfd, &query, sizeof query) != 0) {        return -1;    }    return privsep_recvfd(psfd);}static int privsep_privpart_waitcmd(const int psfd){    PrivSepQuery query;        if (privsep_recvcmd(psfd, &query, sizeof query) != 0) {        return -1;    }    switch (query.cmd.cmd) {# ifdef FTPWHO    case PRIVSEPCMD_REMOVEFTPWHOENTRY:        return privsep_privpart_removeftpwhoentry(psfd);# endif    case PRIVSEPCMD_BINDRESPORT:        return privsep_privpart_bindresport(psfd, &query);    default:        return -1;    }    return 0;}static int privsep_privpart_main(void){    int ret;        while ((ret = privsep_privpart_waitcmd(psfd)) == 0);        if (ret != 1) {        return -1;    }    return 0;}static int privsep_privpart_closejunk(void){    int ret = 0;    # if defined(WITH_UPLOAD_SCRIPT)        if (upload_pipe_fd != -1) {        ret |= close(upload_pipe_fd);    }    if (upload_pipe_lock != -1) {        ret |= close(upload_pipe_lock);    }# endif# ifdef WITH_ALTLOG        if (altlog_fd != -1) {        ret |= close(altlog_fd);    }# endif# ifndef SAVE_DESCRIPTORS    if (no_syslog == 0) {        closelog();    }# endif    (void) close(0);    (void) close(1);        return ret;}int privsep_init(void){    int sv[2];    pid_t pid;        if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sv) != 0) {        return -1;    }    if ((pid = fork()) == (pid_t) -1) {        (void) close(sv[0]);        (void) close(sv[1]);                return -1;    }    if (pid != (pid_t) 0) {        (void) close(sv[1]);                psfd = sv[0];        setprogname("pure-ftpd (PRIV)");        (void) privsep_privpart_closejunk();        _exit(privsep_privpart_main());    }    (void) close(sv[0]);    psfd = sv[1];        return 0;}#endif

⌨️ 快捷键说明

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