ShellBanner
System:Linux MiraNet 3.0.0-14-generic-pae #23-Ubuntu SMP Mon Nov 21 22:07:10 UTC 2011 i686
Software:Apache. PHP/5.3.6-13ubuntu3.10
ID:uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
Safe Mode:OFF
Open_Basedir:OFF
Freespace:27.58 GB of 70.42 GB (39.17%)
MySQL: ON MSSQL: OFF Oracle: OFF PostgreSQL: OFF Curl: OFF Sockets: ON Fetch: OFF Wget: ON Perl: ON
Disabled Functions: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,

/ usr/ src/ courier-0.66.1/ tcpd/ - drwxrwxrwx

Directory:
Viewing file:     tcpd.c (33 KB)      -rw-rw-rw-
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
** Copyright 1998 - 2009 Double Precision, Inc.
** See COPYING for distribution information.
*/

#if    HAVE_CONFIG_H
#include    "config.h"
#endif

/*
** OK - the poop is that if we include socks.h after stdio.h, SOCKSfwrite
** does not get prototyped.
** If we include socks.h before stdio.h, gcc will complain about getc being
** redefined.  The easiest solution is to simply undef getc, because we
** don't use it here.
*/

#include    "soxwrap/soxwrap.h"
#include    <stdio.h>


#include    <sys/types.h>
#include    <sys/time.h>
#include    <arpa/inet.h>
#include    <pwd.h>
#include    <grp.h>
#include    <stdlib.h>
#include    <string.h>
#include    <ctype.h>
#include    <stdio.h>
#include    <errno.h>
#include    <signal.h>
#if    HAVE_SYS_STAT_H
#include    <sys/stat.h>
#endif
#if    HAVE_FCNTL_H
#include    <fcntl.h>
#endif
#if    HAVE_SYS_IOCTL_H
#include    <sys/ioctl.h>
#endif
#if HAVE_UNISTD_H
#include    <unistd.h>
#endif
#include    "waitlib/waitlib.h"
#include    "rfc1035/rfc1035.h"
#include    "liblock/config.h"
#include    "liblock/liblock.h"
#include    "tcpremoteinfo.h"
#include    "numlib/numlib.h"
#include    "argparse.h"

#include    <netdb.h>


static const char *accessarg=0;
static const char *accesslocal=0;
static const char *denymsgarg=0;
static const char *listenarg=0;
static const char *ipaddrarg=0;
static const char *userarg=0;
static const char *grouparg=0;
static const char *maxprocsarg=0;
static const char *warnarg=0;
static const char *maxperiparg=0;
static const char *maxpercarg=0;
static const char *droparg=0;
static const char *nodnslookup=0;
static const char *noidentlookup=0;
static const char *stderrarg=0;
static const char *stderrloggerarg=0;
static const char *pidarg=0;
static const char *proxyarg=0;
static const char *restartarg=0;
static const char *stoparg=0;
static const char *stderrloggername=0;

static char *lockfilename;

static void setup_block(const char *);

static struct args arginfo[]={
    {"access", &accessarg},
    {"accesslocal", &accesslocal},
    {"denymsg", &denymsgarg},
    {"drop", &droparg},
    {"address", &ipaddrarg},
    {"block", 0, setup_block},
    {"group", &grouparg},
    {"listen", &listenarg},
    {"maxperc", &maxpercarg},
    {"maxperip", &maxperiparg},
    {"maxprocs", &maxprocsarg},
    {"warn", &warnarg},
    {"nodnslookup", &nodnslookup},
    {"noidentlookup", &noidentlookup},
    {"pid", &pidarg},
    {"restart", &restartarg},
    {"stderr", &stderrarg},
    {"stderrlogger", &stderrloggerarg},
    {"stderrloggername", &stderrloggername},
    {"stop", &stoparg},
    {"user", &userarg},
    {"proxy", &proxyarg},
    {0}
    } ;

/* Ports we're listening on: */

static struct portinfo {
    struct portinfo *next;
    const char *ipaddr;    /* Specific IP addr, or 0 */
    const char *servname;    /* Service name/port */

    int fd1, fd2;        /* BSD may need both IPv4 and IPv6 sockets */
} *fdlist=0;
static int maxfd;

static int nprocs, maxperc, maxperip, nwarn;
static pid_t *pids;
static time_t last_alert=0, last_warn=0;
static RFC1035_ADDR *addrs;

static int sighup_received=0;

struct blocklist_s {
    struct blocklist_s *next;
    char *zone;
    char *var;
    struct in_addr ia;    /* 0, anything */
    char *msg;        /* NULL, query for TXT record */
    } *blocklist=0;

extern int openaccess(const char *);
extern void closeaccess();
extern char *chkaccess(const char *);

static void setup_block(const char *blockinfo)
{
struct blocklist_s *newbl=(struct blocklist_s *)malloc(sizeof(*blocklist));
char    *p;
struct blocklist_s **blptr;

    for (blptr= &blocklist; *blptr; blptr=&(*blptr)->next)
        ;

    if (!newbl || (newbl->zone=malloc(strlen(blockinfo)+1)) == 0)
    {
        perror("malloc");
        exit(1);
    }

    *blptr=newbl;
    newbl->next=0;
    strcpy(newbl->zone, blockinfo);
    newbl->var=strchr(newbl->zone, ',');
    newbl->msg=0;
    newbl->ia.s_addr=INADDR_ANY;

    if (newbl->var)
        *newbl->var++=0;
    if (newbl->var && *newbl->var)
        newbl->msg=strchr(newbl->var, ',');
    if (newbl->msg)
        *newbl->msg++=0;
    if (newbl->var && (p=strchr(newbl->var, '/')) != 0)
    {
        *p++=0;
        rfc1035_aton_ipv4(p, &newbl->ia);
    }
}

static int isid(const char *p)
{
    while (*p)
    {
        if (*p < '0' || *p > '9')    return (0);
        ++p;
    }
    return (1);
}

static RETSIGTYPE sigexit(int n)
{
    kill( -getpid(), SIGTERM);
    _exit(0);

#if RETSIGTYPE != void
    return (0)
#endif
}

static RETSIGTYPE sighup(int n)
{
    sighup_received=1;

    signal(SIGHUP, sighup);

#if RETSIGTYPE != void
    return (0)
#endif
}

/*
** Initialize a single listening socket
*/

static struct portinfo *createport(const char *a, const char *s)
{
    struct portinfo *p=(struct portinfo *)malloc(sizeof(struct portinfo));

    if (!p)
    {
        perror("malloc");
        return (NULL);
    }

    p->next=fdlist;
    fdlist=p;
    p->ipaddr=a;
    p->servname=s;
    p->fd1=p->fd2= -1;
    return (p);
}

static int parseaddr(const char *p)
{
    char *buf=strdup(p);
    char *q, *a, *s;

    if (!buf)
    {
        perror("malloc");
        return (-1);
    }

    for (q=buf; (q=strtok(q, ",")) != NULL; q=0)
    {
        if ((s=strrchr(q, '.')) != 0)
        {
            *s++=0;
            a=q;
        }
        else
        {
            a=0;
            s=q;
        }

        if (createport(a, s) == NULL)
            return (-1);
    }

    if (ipaddrarg)
    {
        struct portinfo *p;

        for (p=fdlist; p; p=p->next)
        {
            if (p->ipaddr && strcmp(p->ipaddr, "0"))
                continue;
            p->ipaddr=ipaddrarg;
        }
    }

    return (0);
}

/*
** Create one socket, bound to a specific host/port
*/

static int mksocket(const char *ipaddrarg,    /* Host/IP address */
            const char *servname,    /* Service/port */
            int flags)

#define MKS_USEAFINET4 1
#define MKS_ERROK 2

{
    struct servent *servptr;
    int    port;
    int    fd;

    RFC1035_ADDR addr;
    RFC1035_NETADDR  netaddr;
    const struct sockaddr *sinaddr;
    int    sinaddrlen;

#if    RFC1035_IPV6
    struct sockaddr_in6    sin6;
#endif

    struct sockaddr_in    sin4;

    int    af;

    servptr=getservbyname(servname, "tcp");
    if (servptr)
        port=servptr->s_port;
    else
    {
        port=atoi(servname);
        if (port <= 0 || port > 65535)
        {
            fprintf(stderr, "Invalid port: %s\n", servname);
            return (-1);
        }
        port=htons(port);
    }

    /* Create an IPv6 or an IPv4 socket */

#if    RFC1035_IPV6
    if (flags & MKS_USEAFINET4)
    {
        fd=socket(PF_INET, SOCK_STREAM, 0);
        af=AF_INET;
    }
    else
#endif
        fd=rfc1035_mksocket(SOCK_STREAM, 0, &af);

    if (fd < 0)
    {
        perror("socket");
        return (-1);
    }

    /* Figure out what to bind based on what socket we created */

    if (ipaddrarg && strcmp(ipaddrarg, "0"))
    {
        if (rfc1035_aton(ipaddrarg, &addr) < 0)
        {
            fprintf(stderr,"Invalid IP address: %s\n", ipaddrarg);
            close(fd);
            return (-1);
        }

        if (rfc1035_mkaddress(af, &netaddr, &addr, port, &sinaddr,
                &sinaddrlen))
        {
            fprintf(stderr,"Unable to bind IP address: %s\n",
                ipaddrarg);
            close(fd);
            return (-1);
        }
    }
    else    /* Bind default address */
    {
#if    RFC1035_IPV6
        if (af == AF_INET6)
        {
            memset(&sin6, 0, sizeof(sin6));
            sin6.sin6_family=AF_INET6;
            sin6.sin6_addr=in6addr_any;
            sin6.sin6_port=port;
            sinaddr=(const struct sockaddr *)&sin6;
            sinaddrlen=sizeof(sin6);
        }
        else
#endif
            if (af == AF_INET)
            {
                sin4.sin_family=AF_INET;
                sin4.sin_addr.s_addr=INADDR_ANY;
                sin4.sin_port=port;
                sinaddr=(const struct sockaddr *)&sin4;
                sinaddrlen=sizeof(sin4);
            }
            else
            {
                errno=EAFNOSUPPORT;
                perror("socket");
                close(fd);
                return (-1);
            }
    }

    {
        int dummy=1;

        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
               (const char *)&dummy, sizeof(dummy)) < 0)
        {
            perror("setsockopt");
        }
    }

    if (fcntl(fd, F_SETFD, FD_CLOEXEC))
    {
        perror("fcntl");
        close(fd);
        return (-1);
    }

    if (fcntl(fd, F_SETFL, O_NONBLOCK))
    {
        perror("fcntl");
        close(fd);
        return (-1);
    }

    if (sox_bind(fd, (struct sockaddr *)sinaddr, sinaddrlen) < 0)
    {
        if (flags & MKS_ERROK)
        {
            close(fd);
            return (-2);
        }

        perror("bind");
        close(fd);
        return (-1);
    }

    if (sox_listen(fd,
#ifdef    SOMAXCONN
               SOMAXCONN
#else
               5
#endif
               ))
    {
        if (flags && MKS_ERROK)
        {
            close(fd);
            return (-2);
        }
        perror("listen");
        close(fd);
        return (-1);
    }
    return (fd);
}

static int mksockets()
{
    struct portinfo *p;

    maxfd= -1;

    for (p=fdlist; p; p=p->next)
    {
        int fd;
        struct in_addr addr;
        int fd_flag=0;

        if (p->ipaddr && strcmp(p->ipaddr, "0"))
        {
            /* FreeBSD needs AF_INET binds for IPv4 addys */

            if (rfc1035_aton_ipv4(p->ipaddr, &addr) == 0)
            {
                fd_flag=MKS_USEAFINET4;
            }
        }

        fd=mksocket(p->ipaddr, p->servname, fd_flag);

        if (fd < 0)
            break;

        p->fd1=fd;

        if (fd > maxfd)
            maxfd=fd;

        /* BSD requires both an IPv6 and an IPv4 socket */

#if    RFC1035_IPV6
        if (p->ipaddr == 0 || strcmp(p->ipaddr, "0") == 0)
        {
            fd=mksocket(p->ipaddr, p->servname,
                    (MKS_USEAFINET4|MKS_ERROK));

            if (fd == -2)
                continue;    /* Ok if bind failed */
            if (fd < 0)
                break;

            if (fd > maxfd)
                maxfd=fd;
            p->fd2=fd;
        }
#endif

    }

    if (p)    /* Clean up after ourselves, after an error */
    {
        for (p=fdlist; p; p=p->next)
        {
            if (p->fd1 >= 0)
                close(p->fd1);
            if (p->fd2 >= 0)
                close(p->fd2);
        }
        return (-1);
    }

    return (0);
}

static int init(int argc, char **argv)
{
int    argn;

struct    group *gr;
int    i;
gid_t    gid=0;
const    char *servname;
int    forced=0;
int    lockfd=-1;
 
    argn=argparse(argc, argv, arginfo);

    if ((stoparg || restartarg) && pidarg == 0)
    {
        fprintf(stderr, "%s: -pid argument is required.\n", argv[0]);
        return (-1);
    }

    if (pidarg)
    {
        lockfilename=malloc(strlen(pidarg)+sizeof(".lock"));
        if (!lockfilename)
        {
            perror("malloc");
            return (-1);
        }
        strcat(strcpy(lockfilename, pidarg), ".lock");
    }

    if (stoparg)
    {
        ll_daemon_stop(lockfilename, pidarg);
        exit(0);
    }

    if (restartarg)
    {
        ll_daemon_restart(lockfilename, pidarg);
        exit(0);
    }

    if (argc - argn < 2)
    {
        fprintf(stderr, "Usage: %s [options] port prog arg1 arg2...\n",
            argv[0]);
        return (-1);
    }

    if (pidarg) { /* -start implied for backwards compatibility */
        lockfd=ll_daemon_start(lockfilename);
        if (lockfd < 0)
        {
            perror("ll_daemon_start");
            return (-1);
        }
    }

    servname=argv[argn++];

    if (parseaddr(servname))
    {
        close(lockfd);
        return (-1);
    }

    if (mksockets())
    {
        close(lockfd);
        return (-1);
    }

    signal(SIGINT, sigexit);
    signal(SIGHUP, sighup);
    signal(SIGTERM, sigexit);

#if 0
    {
    int    fd2;
    int    dummy;

        perror("bind");
        if (!forcebindarg || errno != EADDRINUSE)
        {
            sox_close(fd);
            return (-1);
        }

        /* Poke around */

        if ((fd2=rfc1035_mksocket(SOCK_STREAM, 0, &dummy)) < 0)
            /* Better get same socket as fd */
        {
            perror("socket");
            sox_close(fd);
            return (-1);
        }

        if (sox_connect(fd2, (struct sockaddr *)sinaddr,
            sinaddrlen) == 0)
        {
            sox_close(fd2);
            sox_close(fd);
            return (-1);
        }
        sox_close(fd2);
        savepid();
        sleep(60);
        forced=1;
    }
#endif

    if (pidarg)
        ll_daemon_started(pidarg, lockfd);

    if (grouparg)
    {
        if (isid(grouparg))
            gid=atoi(grouparg);
        else if ((gr=getgrnam(grouparg)) == 0)
        {
            fprintf(stderr, "Group not found: %s\n", grouparg);
            close(lockfd);
            return (-1);
        }
        else    gid=gr->gr_gid;

        libmail_changegroup(gid);
    }

    if (userarg)
    {
    uid_t    uid;

        if (isid(userarg))
        {
            uid=atoi(userarg);
            libmail_changeuidgid(uid, getgid());
        }
        else
        {
        gid_t    g=getgid(), *gp=0;

            if (grouparg)    gp= &g;
            libmail_changeusername(userarg, gp);
        }
    }

    if (pidarg && ll_daemon_resetio())
    {
        perror("ll_daemon_resetio");
        close(lockfd);
        return (-1);
    }

    if (stderrloggerarg)
    {
    pid_t    p;
    int    waitstat;
    int    pipefd[2];
    const char *progname=argv[argn];

        if (pipe(pipefd) < 0)
        {
            perror("pipe");
            return (-1);
        }

        signal(SIGCHLD, SIG_DFL);
        while ((p=fork()) == -1)
        {
            sleep(5);
        }

        if (p == 0)
        {
            signal(SIGHUP, SIG_IGN);
            sox_close(0);
            sox_dup(pipefd[0]);
            sox_close(pipefd[0]);
            sox_close(pipefd[1]);
            sox_close(1);
            open("/dev/null", O_WRONLY);
            sox_close(2);
            sox_dup(1);
            closeaccess();
            while ((p=fork()) == -1)
            {
                sleep(5);
            }
            if (p == 0)
            {
            const char *p=strrchr(progname, '/');

                if (p)    ++p;
                else p=progname;

                if (stderrloggername && *stderrloggername)
                    p=stderrloggername;

                execl(stderrloggerarg, stderrloggerarg,
                        p, (char *)0);
                perror(stderrloggerarg);
                _exit(5);
            }
            _exit(0);
        }
        sox_close(2);
        sox_dup(pipefd[1]);
        sox_close(pipefd[0]);
        sox_close(pipefd[1]);
        while (wait(&waitstat) != p)
            ;
    }
    else if (stderrarg)
    {
    int    fd=open(stderrarg, O_WRONLY|O_APPEND|O_CREAT, 0660);

        if (!fd)
        {
            perror(stderrarg);
            return (-1);
        }
        sox_close(2);
        sox_dup(fd);
        sox_close(fd);
    }

    nprocs=40;
    if (maxprocsarg)
    {
        nprocs=atoi(maxprocsarg);
        if (nprocs <= 0)
        {
            fprintf(stderr, "Invalid -maxprocsarg option.\n");
            return (-1);
        }
    }

    nwarn= nprocs - (nprocs / 10 + 1);

    if (warnarg)
    {
        int c=atoi(warnarg);

        if (c >= 0 && c <= nprocs)
            nwarn=c;
    }

    if ((pids=malloc(sizeof(*pids)*nprocs)) == 0)
    {
        perror("malloc");
        return (-1);
    }
    if ((addrs=malloc(sizeof(*addrs)*nprocs)) == 0)
    {
        free(pids);
        perror("malloc");
        return (-1);
    }


    for (i=0; i<nprocs; i++)
        pids[i]= -1;

    maxperc=nprocs;
    maxperip=4;

    if (maxpercarg)
    {
        maxperc=atoi(maxpercarg);
        if (maxperc <= 0)
        {
            fprintf(stderr, "Invalid -maxperc option.\n");
            free(pids);
            free(addrs);
            return (-1);
        }
    }
    if (maxperiparg)
    {
        maxperip=atoi(maxperiparg);
        if (maxperip <= 0)
        {
            fprintf(stderr, "Invalid -maxperip option.\n");
            free(pids);
            free(addrs);
            return (-1);
        }
    }
    if (forced)
    {
        fprintf(stderr, "couriertcpd: ready.\n");
        fflush(stderr);
    }
    return (argn);
}

static void run(int, const RFC1035_ADDR *, int, const char *, char **);

static void doreap(pid_t p, int wait_stat)
{
int    n;

    for (n=0; n<nprocs; n++)
        if (p == pids[n])
        {
            pids[n]= -1;
            break;
        }
}

static RETSIGTYPE childsig(int signum)
{
    signum=signum;
    wait_reap(doreap, childsig);
#if RETSIGTYPE != void
    return (0);
#endif
}

static int doallowaccess(char *, int);

#if    RFC1035_IPV6

static int allowaccess(const RFC1035_ADDR *sin, int port)
{
char    buf[RFC1035_MAXNAMESIZE+1+6];
char    *q;
int    i;

    if (IN6_IS_ADDR_V4MAPPED(sin))
    {
    const char *p=inet_ntop(AF_INET6, sin, buf, sizeof(buf)-6);

        if (p && (q=strrchr(buf, ':')) != 0)
            return (doallowaccess(q+1, port));
        return (1);
    }
    q=buf;
    for (i=0; i<sizeof(*sin); i += 2)
    {
#define    B(i) ((unsigned long)((unsigned char *)sin)[i])
    unsigned long n=(B(i) << 8) | B(i+1);
#undef    B
        sprintf(q, ":%04lx", n);
        q += 5;
    }
    *q=0;
    return (doallowaccess(buf, port));
}

#else
static int allowaccess(const RFC1035_ADDR *sin, int port)
{
char    buf[RFC1035_NTOABUFSIZE+6];

    rfc1035_ntoa(sin, buf);
    return (doallowaccess(buf, port));
}
#endif

static int doallowaccess(char *buf, int port)
{
char    *accessptr;
char *p, *q, *r;
int    quote=0;
int    l;

    if (accessarg == 0)    return (1);

    if (port) snprintf(buf+strlen(buf), 7, ".%d", ntohs(port));
    while ((accessptr= *buf ? chkaccess(buf):0) == 0)
    {
        if ((accessptr=strrchr(buf, '.')) == 0
#if RFC1035_IPV6
            && (accessptr=strrchr(buf, ':')) == 0
#endif
            )
        {
            if (port)
            {
                snprintf(buf, 8, "*.%d", ntohs(port));
                if ((accessptr=chkaccess(buf)) != 0)
                    break;
            }
            if ((accessptr=chkaccess("*")) != 0)
                break;
            return (1);
        }
        *accessptr=0;
    }

    if (strncmp(accessptr, "deny", 4) == 0)
    {
        free(accessptr);
        return (0);
    }

    p=accessptr;
    if (strncmp(accessptr, "allow", 5) == 0)
    {
        p += 5;
        if (*p == ',')    ++p;
    }

    while ( p && *p )
    {
        q=p;
        r=q;
        while (*p)
        {
            if (*p == ',' && !quote)
            {
                *p++=0;
                break;
            }
            if (!quote && (*p == '"' || *p == '\''))
            {
                quote=*p;
                p++;
                continue;
            }
            if (quote && *p == quote)
            {
                quote=0;
                p++;
                continue;
            }
            *r++=*p++;
        }
        *r=0;
        if (strchr(q, '=') == 0)
        {
        char    *r=malloc(strlen(q)+2);

            if (!r)
            {
                perror("malloc");
                return (0);
            }
            q=strcat(strcpy(r, q), "=");
        }

        while (*q && isspace((int)(unsigned char)*q))    ++q;
        while ((l=strlen(q)) > 0
               && isspace((int)(unsigned char)q[l-1]))
            q[--l]=0;
        putenv(q);
    }
    return (1);
}

/* Wait until we have at least one available slot left */

static int getfreeslot(int *pidptr)
{
    int n;

    for (;;)
    {
        wait_block();

        for (n=0; n<nprocs; n++)
        {
            if (pids[*pidptr] == (pid_t)-1)    break;
            if (++*pidptr >= nprocs)    *pidptr=0;
        }
        if (pids[*pidptr] != (pid_t)-1)
        {
            wait_forchild(doreap, childsig);
            continue;
        }
        break;
    }
    wait_clear(childsig);
    return (*pidptr);
}

static void accepted(int, int, RFC1035_NETADDR *, int, const char *, char **);

static int doit(int argn, int argc, char **argv)
{
    char    **ptrs;
    int    pidptr;
    struct portinfo *pi;
    fd_set fdr, fdrcopy;
    int    dummy;

    ptrs=(char **)malloc((argc-argn+1) * sizeof(char *));
    if (!ptrs)
    {
        perror("malloc");
        return (-1);
    }
    for (dummy=0; dummy<argc-argn; dummy++)
    {
        ptrs[dummy]=argv[argn+dummy];
    }
    ptrs[dummy]=0;

    if (listenarg)
    {
        dummy=atoi(listenarg);
        if (dummy <= 0)
        {
            fprintf(stderr, "Invalid -listen option.\n");
            exit(1);
        }
    }

    FD_ZERO(&fdrcopy);
    for (pi=fdlist; pi; pi=pi->next)
    {
        if (pi->fd1 >= 0)
            FD_SET(pi->fd1, &fdrcopy);

        if (pi->fd2 >= 0)
            FD_SET(pi->fd2, &fdrcopy);
    }

    pidptr=0;

    signal(SIGCHLD, childsig);

#if    HAVE_SETPGRP
#if    SETPGRP_VOID
    setpgrp();
#else
    setpgrp(0, 0);
#endif
#else
#if    HAVE_SETPGID
    setpgid(0, 0);
#endif
#endif
#ifdef  TIOCNOTTY

    {
    int fd=open("/dev/tty", O_RDWR);

        if (fd >= 0)
        {
            ioctl(fd, TIOCNOTTY, 0);
            close(fd);
        }
    }
#endif

    signal(SIGPIPE, SIG_IGN);
    for (;;)
    {
        int n;
        int sockfd;
        RFC1035_NETADDR    sin;
        socklen_t    sinl;

        fdr=fdrcopy;

        if (select(maxfd+1, &fdr, NULL, NULL, NULL) <= 0)
        {
            if (errno != EINTR)
                perror("accept");
            continue;
        }

        for (pi=fdlist; pi; pi=pi->next)
        {
            if (pi->fd1 >= 0 && FD_ISSET(pi->fd1, &fdr) &&
                ((n=getfreeslot(&pidptr)),
                 (sinl = sizeof(sin)),
                 (sockfd=sox_accept(pi->fd1,
                        (struct sockaddr *)&sin,
                        &sinl))) >= 0)
            {
                accepted(n, sockfd, &sin, sinl,
                     argv[argn], ptrs);
            }

            if (pi->fd2 >= 0 && FD_ISSET(pi->fd2, &fdr) &&
                ((n=getfreeslot(&pidptr)),
                 (sinl = sizeof(sin)), 
                 (sockfd=sox_accept(pi->fd2,
                        (struct sockaddr *)&sin,
                        &sinl))) >= 0)
            {
                accepted(n, sockfd, &sin, sinl,
                     argv[argn], ptrs);
            }
        }
    }
}

static void denied(int sockfd)
{
    if (denymsgarg) {
        if (write(sockfd, denymsgarg, strlen(denymsgarg)) < 0 ||
            write(sockfd, "\n", 1) < 0)
        {
            sox_close(sockfd);
            _exit(1);
        }
    }
    sox_close(sockfd);
    _exit(0);
}

static void accepted(int n, int sockfd, RFC1035_NETADDR *sin, int sinl,
             const char *prog,
             char **args)
{
    RFC1035_ADDR addr;
    int    addrport;
#ifdef    SO_LINGER
    int    dummy;
    struct    linger l;
#endif
    pid_t    p;
    int cnt;

    if (rfc1035_sockaddrip(sin, sinl, &addr)
        || rfc1035_sockaddrport(sin, sinl, &addrport))
    {
        sox_close(sockfd);
        return;
    }

    /* Turn off the CLOEXEC and NONBLOCK bits */

    if (fcntl(sockfd, F_SETFD, 0))
    {
        perror("fcntl");
        sox_close(sockfd);
        return;
    }

    if (fcntl(sockfd, F_SETFL, 0))
    {
        perror("fcntl");
        sox_close(sockfd);
        return;
    }

    if (sighup_received)
    {
        sighup_received=0;
        if (accessarg)
        {
            closeaccess();
            if (openaccess(accessarg))
                perror(accessarg);
        }
    }

#ifdef    SO_KEEPALIVE
    dummy=1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
               (const char *)&dummy, sizeof(dummy)) < 0)
    {
        perror("setsockopt");
    }
#endif

#ifdef    SO_LINGER
    l.l_onoff=0;
    l.l_linger=0;

    if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
               (const char *)&l, sizeof(l)) < 0)
    {
        perror("setsockopt");
    }
#endif
    wait_block();
    if ((p=fork()) == -1)
    {
        perror("fork");
        sox_close(sockfd);
        return;
    }

    if (p == 0)
    {
        wait_restore(childsig);

        if (accesslocal) /* Lookup local interface address too? */
        {
        RFC1035_NETADDR lsin;
        RFC1035_ADDR laddr;
        int    lport;
        socklen_t    i=sizeof(lsin);
        
            if (sox_getsockname(sockfd, (struct sockaddr *)&lsin, &i) == 0 &&
                rfc1035_sockaddrip(&lsin, i, &laddr) == 0 &&
                rfc1035_sockaddrport(&lsin, i, &lport) == 0 &&
                allowaccess(&laddr,lport) == 0)
            {
                sox_close(sockfd);
                _exit(0);
            }
        }

        if (allowaccess(&addr,0) == 0)
        {
            denied(sockfd);
        }

        run(sockfd, &addr, addrport, prog, args);
    }
    pids[n]=p;

    memcpy(addrs+n, &addr, sizeof(addr));
    sox_close(sockfd);
    wait_clear(childsig);

    for (cnt=n=0; n<nprocs; n++)
        if (pids[n] != (pid_t)-1)
            ++cnt;

    if (cnt == nprocs)
    {
        time_t t;

        time(&t);
        if (last_alert == 0 || last_alert > t || last_alert < t - 60)
        {
            last_alert=t;
            fprintf(stderr,
                "ALERT: %d maximum active connections.\n",
                nprocs);
        }
    }
    else if (cnt >= nwarn)
    {
        time_t t;

        time(&t);
        if (last_warn == 0 || last_warn > t || last_warn < t - 60)
        {
            last_warn=t;
            fprintf(stderr, "WARN: %d active connections.\n",
                cnt);
        }
    }
}

static void mysetenv(const char *name, const char *val)
{
char    *p=malloc(strlen(name)+strlen(val)+2);

    if (!p)
    {
        perror("malloc");
        _exit(1);
    }
    putenv(strcat(strcat(strcpy(p, name), "="), val));
}

/*
** Convert IP address to host name.  Make sure the IP address resolves
** backwards and forwards.
*/

static void ip2host(const RFC1035_ADDR *addr, const char *env)
{
const char *remotehost="softdnserr";
char    buf[RFC1035_MAXNAMESIZE+1];

    if (nodnslookup)    return;

    rfc1035_ntoa(addr, buf);

#if TCPDUSERFC1035

    if (rfc1035_ptr(&rfc1035_default_resolver, addr, buf) != 0)
    {
        if (errno == ENOENT)
            remotehost=0;
    }
    else
    {
    RFC1035_ADDR *ias;
    unsigned nias, n;

        if (rfc1035_a(&rfc1035_default_resolver, buf, &ias, &nias) != 0)
        {
            if (errno == ENOENT)
                remotehost=0;
        }
        else
        {
            remotehost=0;
            for (n=0; n<nias; n++)
            {
            char    a[RFC1035_MAXNAMESIZE];
            char    b[RFC1035_MAXNAMESIZE];

                rfc1035_ntoa(&ias[n], a);
                rfc1035_ntoa(addr, b);

                if (strcmp(a, b) == 0)
                {
                    remotehost=buf;
                }
            }
        }
    }
#else

    {
    struct hostent *he;
    unsigned n;
    struct    in_addr in;

#if    RFC1035_IPV6

        if (IN6_IS_ADDR_V4MAPPED(addr))
            memcpy(&in, (char *)addr + 12, 4);
        else    return;
#else
        in= *addr;
#endif

        he=gethostbyaddr( (char *)&in, sizeof(in), AF_INET);
        if (!he)
        {
            switch (h_errno)    {
            case HOST_NOT_FOUND:
            case NO_DATA:
                remotehost=0;
                break;
            }
        }
        else
        {
            strcpy(buf, he->h_name);
            he=gethostbyname(buf);
            if (!he)
            {
                switch (h_errno)    {
                case HOST_NOT_FOUND:
                case NO_DATA:
                    remotehost=0;
                    break;
                }
            }
            else for (n=0, remotehost=0; he->h_addr_list[n]; n++)
            {
            struct in_addr hin;

                if (he->h_addrtype != AF_INET ||
                    he->h_length < sizeof(hin))
                    break;
                memcpy((char *)&hin, he->h_addr_list[n],
                    sizeof(hin));
                if (hin.s_addr == in.s_addr)
                {
                    remotehost=buf;
                    break;
                }
            }

        }
    }
#endif
    if (remotehost)
        mysetenv(env, remotehost);
}

static void mkmymsg(const char *varname, const char *msg)
{
const char *p=getenv("TCPREMOTEIP");
char *q=malloc(strlen(msg)+1+strlen(p));
char *r;

    if (!q)
    {
        perror("malloc");
        exit(1);
    }

    for (r=q; *msg; msg++)
    {
        if (*msg == '@')
        {
            strcpy(r, p);
            while (*r)    r++;
            ++msg;
            break;
        }
        *r++=*msg;
    }
    while (*msg)
        *r++=*msg++;
    *r=0;
    mysetenv(varname, q);
    free(q);
}

/*
** check_blocklist is called once for each blocklist query to process.
*/

static void docheckblocklist(struct blocklist_s *p, const char *nameptr)
{
const char *q;
const char *varname=p->var;
char    hostname[RFC1035_MAXNAMESIZE+1];
char    buf[RFC1035_MAXNAMESIZE+1];
int    hasnotxt;
struct blocklist_s *pp;
struct rfc1035_reply *replyp;
int i;

    hostname[0]=0;
    strncat(hostname, nameptr, RFC1035_MAXNAMESIZE);

    if (!varname)    varname="BLOCK";

    if ((q=getenv(varname)) != 0)    return;
                    /* Env var already set */

    if (p->ia.s_addr == INADDR_ANY)
    {
        /* We're not looking for a particular token IP address */

        if (p->msg == 0 || *p->msg == 0)
        {
            /*
            ** We don't have a predefined error message, therefore
            ** we expect TXT records.
            */
            if ((i=rfc1035_resolve_cname(&rfc1035_default_resolver,
                    RFC1035_RESOLVE_RECURSIVE,
                    hostname,
                    RFC1035_TYPE_TXT,
                    RFC1035_CLASS_IN, &replyp, 0)) >= 0)
            {
                rfc1035_rr_gettxt(replyp->allrrs[i], 0,
                    hostname);
                mysetenv(varname, hostname);
            }
        }
        else
        {
            /*
            ** A predefined error message has been supplied, so
            ** just look for the IP address.  Perhaps the
            ** blacklist does not provide TXT records, so query
            ** for A records only.
            */

            if ((i=rfc1035_resolve_cname(&rfc1035_default_resolver,
                    RFC1035_RESOLVE_RECURSIVE,
                    hostname,
                    RFC1035_TYPE_A,
                    RFC1035_CLASS_IN, &replyp, 0)) >= 0)
            {
                mkmymsg(varname, p->msg);
            }
        }

        if (replyp)    rfc1035_replyfree(replyp);
        return;
    }

    /*
    ** Looking for a specific A record in the blacklist.  Possibly due
    ** to different messages for different A records.
    ** See if all -block options for the same zone have predefined
    ** error messages, so we can be satisfied with an A query only.
    */

    hasnotxt=0;

    for (pp=p; pp; pp=pp->next)
    {
        if (strcmp(pp->zone, p->zone))    continue;
        if (pp->msg == 0 || *pp->msg == 0)    hasnotxt=1;
    }

    /*
    ** If no text were provided, we need both A and TXT records, so
    ** issue an ANY query, and parse the results.
    */

    (void)rfc1035_resolve_cname(&rfc1035_default_resolver,
            RFC1035_RESOLVE_RECURSIVE,
            hostname,
            hasnotxt ? RFC1035_TYPE_ANY:RFC1035_TYPE_A,
            RFC1035_CLASS_IN, &replyp, 0);

    if (!replyp)    return;

    for (i=0; i<replyp->ancount+replyp->nscount+replyp->arcount; i++)
    {
    int    j;

        /*
        ** Go through the DNS response, and check every A record
        ** in there.
        */
        rfc1035_replyhostname(replyp, replyp->allrrs[i]->rrname, buf);
        if (rfc1035_hostnamecmp(buf, hostname))    continue;
        if (replyp->allrrs[i]->rrtype != RFC1035_TYPE_A)
            continue;

        /*
        ** Go through the remaining blocklist, and set the environment
        ** variable for each block entry for this zone and IP address.
        */
        for (pp=p; pp; pp=pp->next)
        {
        const char *vvarname=pp->var;

            if (strcmp(pp->zone, p->zone))    continue;

            if (pp->ia.s_addr != replyp->allrrs[i]->rr.inaddr.s_addr)
                continue;

            if (!vvarname)    vvarname="BLOCK";

            /*
            ** The -block option was kind enough to supply the
            ** error message.
            */

            if (pp->msg && *pp->msg)
            {
                mkmymsg(vvarname, pp->msg);
                continue;
            }

            /* No predefined message, look for a TXT record. */

            if ((j=rfc1035_replysearch_all(&rfc1035_default_resolver,
                               replyp, hostname,
                               RFC1035_TYPE_TXT,
                               RFC1035_CLASS_IN, 0)) >= 0)
            {
                rfc1035_rr_gettxt(replyp->allrrs[j], 0, buf);
                mysetenv(vvarname, buf);
            }
            else    mysetenv(vvarname, "Access denied.");
        }
    }
    rfc1035_replyfree(replyp);
}

static void check_blocklist_ipv4(struct blocklist_s *p,
    const struct in_addr *ia)
{
unsigned a,b,c,d;
char    hostname[RFC1035_MAXNAMESIZE+1];
const unsigned char *q=(const unsigned char *)ia;

    /* Calculate DNS query hostname */

    a=q[0];
    b=q[1];
    c=q[2];
    d=q[3];

    sprintf(hostname, "%u.%u.%u.%u.%s", d, c, b, a, p->zone);
    docheckblocklist(p, hostname);
}

#if    RFC1035_IPV6

static void check_blocklist(struct blocklist_s *p, const RFC1035_ADDR *ia)
{
    if (IN6_IS_ADDR_V4MAPPED(ia))
    {
    struct in_addr ia4;

        memcpy(&ia4, (const char *)ia + 12, 4);
        check_blocklist_ipv4(p, &ia4);
    }
}

#else
static void check_blocklist(struct blocklist_s *p, const RFC1035_ADDR *ia)
{
    check_blocklist_ipv4(p, ia);
}
#endif

static void check_drop(int sockfd)
{
    const char *p, *q;
    char *r;

    p=droparg;

    if (p && !*p)
        p="BLOCK";

    for (; p && *p; q=p)
    {
        if (*p == ',')
        {
            q= ++p;
            continue;
        }

        for (q=p; *q; ++q)
            if (*q == ',')
                break;

        r=malloc(q-p+1);

        if (!r)
        {
            perror("malloc");
            _exit(1);
        }

        memcpy(r, p, q-p);
        r[q-p]=0;

        p=getenv(r);
        free(r);

        if (p && *p)
        {
            fprintf(stderr,
                "WARN: dropped blocked connection from %s\n",
                getenv("TCPREMOTEIP"));
            denied(sockfd);
        }
    }
}

static void proxy();

static void run(int fd, const RFC1035_ADDR *addr, int addrport,
    const char *prog, char **argv)
{
RFC1035_NETADDR lsin;
RFC1035_ADDR laddr;
int    lport;

socklen_t    i;
int    ipcnt, ccnt;
char    buf[RFC1035_MAXNAMESIZE+128];
struct blocklist_s *bl;
const char *remoteinfo;
const char *p;

    i=sizeof(lsin);
    if (sox_getsockname(fd, (struct sockaddr *)&lsin, &i) ||
        rfc1035_sockaddrip(&lsin, i, &laddr) ||
        rfc1035_sockaddrport(&lsin, i, &lport))
    {
        fprintf(stderr, "getsockname failed.\n");
        exit(1);
    }

    if (!noidentlookup && (remoteinfo=tcpremoteinfo(
        &laddr, lport,
        addr, addrport, 0)) != 0)
    {
    char    *q=malloc(sizeof("TCPREMOTEINFO=")+strlen(remoteinfo));

        if (!q)
        {
            perror("malloc");
            _exit(1);
        }

        strcat(strcpy(q, "TCPREMOTEINFO="), remoteinfo);
        putenv(q);
    }

/* check if it's an exception to the global ip limit */
    if( (p=getenv("MAXCPERIP")) != NULL )
    {
        int j = atoi(p);

        if( j > 0 )
            maxperip = j;
    }

    for (i=0, ipcnt=ccnt=0; i<nprocs; i++)
    {
    RFC1035_ADDR *psin;
    int    j;

        if (pids[i] == (pid_t)-1)    continue;

        psin=addrs+i;

        for (j=0; j<sizeof(*addr); j++)
            if ( ((char *)addr)[j] != ((char *)psin)[j])
                break;

        if (j >= sizeof(*addr) &&
            ++ipcnt >= maxperip)
        {
            rfc1035_ntoa(addr, buf);
            fprintf(stderr,"ALERT: Maximum connection limit reached for %s\n",buf);
            _exit(0);    /* Too many from same IP address */
        }

        if ( j >= sizeof(*addr)-1 &&
            ++ccnt >= maxperc)
            _exit(0);    /* Too many from same netblock */

    }

    rfc1035_ntoa(addr, buf);
    mysetenv("TCPREMOTEIP", buf);
    sprintf(buf, "%d", ntohs(addrport));
    mysetenv("TCPREMOTEPORT", buf);
    ip2host(addr, "TCPREMOTEHOST");

    rfc1035_ntoa(&laddr, buf);
    mysetenv("TCPLOCALIP", buf);
    sprintf(buf, "%d", ntohs(lport));
    mysetenv("TCPLOCALPORT", buf);
    ip2host(&laddr, "TCPLOCALHOST");

    for (bl=blocklist; bl; bl=bl->next)
        check_blocklist(bl, addr);

    check_drop(fd);
    sox_close(0);
    sox_close(1);
    sox_dup(fd);
    sox_dup(fd);
    sox_close(fd);
    if (stderrarg && strcmp(stderrarg, "socket") == 0)
    {
        sox_close(2);
        sox_dup(1);
    }
    proxy();
    signal(SIGPIPE, SIG_DFL);

    execv(prog, argv);
    perror(prog);
    exit(1);
}

int main(int argc, char **argv)
{
int argn=init(argc, argv);
int rc;

    if (argn < 0)
    {
        exit(1);
    }
    if (accessarg && openaccess(accessarg))
        perror(accessarg);
    if (accesslocal && !accessarg)
        fprintf(stderr,"-accesslocal requires -access\n");
    rc=doit(argn, argc, argv);
    kill( -getpid(), SIGTERM);
    exit(rc);
    return (0);
}

#if 1

static void proxy()
{
}

#else

/*
** SOCKSv5 does not support wildcards binds, for now, so there's no
** reason to manually proxy anything, yet.
*/


/***************************************************************************

Manual proxy, to support SOCKS encryption.  Because encrypted connection to
the SOCKS server is supported transparently in libsocks5, we can't just
run the app, because we'll lose libsocks5's intercept of read/write, et al

***************************************************************************/

struct proxybuf {
    char buffer[BUFSIZ];
    char    *p;
    int buffered;
    int rfd, wfd;
    } ;

static void proxy_init(struct proxybuf *b, int r, int w)
{
    b->buffered=0;
    b->rfd=r;
    b->wfd=w;
}

static int proxy_setfd(struct proxybuf *b, fd_set *r, fd_set *w, int *max)
{
    /* If we have something buffered, write it out */

    if (b->buffered)
    {
        FD_SET(b->wfd, w);
        if (b->wfd > *max)    *max=b->wfd;
        return (1);
    }

    if (b->rfd < 0)
    {
        if (b->wfd >= 0)
        {
            sox_close(b->wfd);
            b->wfd= -1;
        }
        return (0);    /* Nothing else to do */
    }

    if (b->rfd > *max)    *max=b->rfd;
    FD_SET(b->rfd, r);
    return (1);
}

static void proxy_dofd(struct proxybuf *b, fd_set *r, fd_set *w)
{
    if (b->buffered)
    {
        if (FD_ISSET(b->wfd, w))
        {
        int    n=sox_write(b->wfd, b->p, b->buffered);

            if (n <= 0)
            {
                sox_close(b->rfd);
                sox_close(b->wfd);
                b->rfd=b->wfd= -1;
                b->buffered=0;
                return;
            }
            b->p += n;
            b->buffered -= n;
        }
        return;
    }

    if (b->rfd >= 0 && FD_ISSET(b->rfd, r))
    {
    int    n=sox_read(b->rfd, b->buffer, sizeof(b->buffer));

        if (n <= 0)
        {
            sox_close(b->rfd);
            sox_close(b->wfd);
            b->rfd=b->wfd= -1;
            b->buffered=0;
            return;
        }
        b->p = b->buffer;
        b->buffered=n;
    }
}

static void proxy_do(struct proxybuf *);

static void proxy()
{
int    pipefd0[2], pipefd1[2], pipefd2[2];
pid_t    p, p2;
int    waitstat;
struct proxybuf proxy_[3];

    if (!proxyarg)    return;

    if (pipe(pipefd0) || pipe(pipefd1) || pipe(pipefd2))
    {
        perror("pipe");
        exit(1);
    }

    p=fork();
    if (p == -1)
    {
        perror("fork");
        exit(1);
    }

    /*
    ** The parent goes on its merry way, but first makes sure that the
    ** child process is OK.
    */

    if (p)
    {
        while ((p2=wait(&waitstat)) != p)
        {
            if (p2 == -1 && errno != EINTR)
            {
                perror("wait");
                exit(1);
            }
        }
        if (waitstat)
            exit(0);
        sox_close(0);
        sox_close(1);
        sox_close(2);
        errno=EINVAL;
        if (sox_dup(pipefd0[0]) != 0 ||
            sox_dup(pipefd1[1]) != 1 ||
            sox_dup(pipefd2[1]) != 2)
        {
            perror("dup(app)");
            exit(1);
        }
        sox_close(pipefd0[0]);
        sox_close(pipefd0[1]);
        sox_close(pipefd1[0]);
        sox_close(pipefd1[1]);
        sox_close(pipefd2[0]);
        sox_close(pipefd2[1]);
        return;
    }

    p=fork();
    if (p == -1)    exit(1);
    if (p)    exit(0);

    sox_close(pipefd0[0]);
    sox_close(pipefd1[1]);
    sox_close(pipefd2[1]);

    proxy_init(&proxy_[0], 0, pipefd0[1]);
    proxy_init(&proxy_[1], pipefd1[0], 1);
    proxy_init(&proxy_[2], pipefd2[0], 2);
    proxy_do(proxy_);
    exit(0);
}

static void proxy_do(struct proxybuf *p)
{
fd_set    r, w;

    for (;;)
    {
    int    m=0;
    int    rc0, rc1, rc2;

        FD_ZERO(&r);
        FD_ZERO(&w);

        rc0=proxy_setfd(p, &r, &w, &m);
        rc1=proxy_setfd(p+1, &r, &w, &m);
        rc2=proxy_setfd(p+2, &r, &w, &m);

        if (rc0 == 0 && rc1 == 0 && rc2 == 0)
            break;

        if (rc0 == 0 || rc1 == 0 || rc2 == 0)
            alarm(10);

        if (select(m+1, &r, &w, 0, 0) < 0)
        {
            perror("select");
            break;
        }

        proxy_dofd(p, &r, &w);
        proxy_dofd(p+1, &r, &w);
        proxy_dofd(p+2, &r, &w);
    }
}
#endif
Command:
Quick Commands:
Upload:
[OK] Max size: 100MB
PHP Filesystem: <@ Ú
Search File:
regexp
Create File:
Overwrite [OK]
View File:
Mass Defacement:
[+] Main Directory: [+] Defacement Url:
LmfaoX Shell - Private Build [BETA] - v0.1 -; Generated: 0.239 seconds