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

📄 ciped.c

📁 cipe 编程
💻 C
📖 第 1 页 / 共 2 页
字号:
	   parameter. See output.c why. */	*OA(socks)=*OA(peer);	*OA(peer)=a;    }    return fd;}/* Check whether the SOCKS5 server has closed the connection */const char * const eofsocks_str[] = {    "no error", "exception", "read error", "EOF"};int eofsocks(int fd) {    fd_set ifd, efd;    struct timeval t={0,0};    FD_ZERO(&ifd);    FD_ZERO(&efd);    FD_SET(fd, &ifd);    FD_SET(fd, &efd);    if (select(fd+1, &ifd, NULL, &efd, &t)>0) {	if (FD_ISSET(fd, &efd)) {	    return 1;	}	if (FD_ISSET(fd, &ifd)) {	    int e;	    char c;	    if ((e=read(fd, &c, 1))<=0) {		return e<0 ? 2 : 3;	    }	}    }    return 0;}/*** Signal handler. See also cipelib.h ***/void sighandnot(int s){    /* Dummy */}void sighandexit(int s){    /* exit parent */    exit(0);}/*** Control message handling ***/time_t pingtime=MAXINT, pongtime=MAXINT;void dprintct(const char *h, char c){    switch(c) {    case CT_DUMMY: 	dprintf(("%s CT_DUMMY\n", h));  	break;    case CT_DEBUG: 	dprintf(("%s CT_DEBUG\n", h));  	break;    case CT_PING:  	dprintf(("%s CT_PING\n", h));  	 	break;    case CT_PONG:  	dprintf(("%s CT_PONG\n", h));   	break;    case CT_KILL:  	dprintf(("%s CT_KILL\n",h));   	 	break;    case CT_CONFREQ:  	dprintf(("%s CT_CONFREQ\n",h));    	break;    case CT_CONF:  	dprintf(("%s CT_CONF\n",h));    	break;    default:       	dprintf(("%s %d\n", h, c));    }}/* send a control */int sendctl(int f, const char *msg, int len, int v, int flags){    int e;    dprintct("sending", msg[0]);    if (OI(nokey))        return -1; /* unencrypted cant handle controls */    if ((e=send(f, msg, len, flags))<0) {	if (v)	    Log(LOG_ERR, "sendctl: %m");    }    return e;}/* handle control message */void ctrl(int f, char *msg, int len){    char buf[64];    struct confinfo *ci;    if (OI(nokey))        return; /* unencrypted cant handle controls */    dprintct("received", msg[0]);    switch (msg[0]) {    case CT_DEBUG:        /* Log it */        Log(LOG_NOTICE, "peer: %s", msg+1);	/* fall thru */    case CT_DUMMY:        break;    case CT_PING:        msg[0]=CT_PONG;        sendctl(f, msg, len, 1, 0);        break;    case CT_PONG:        pongtime=MAXINT;        break;    case CT_KILL:        Log(LOG_NOTICE, "Shutting down at peer request %s", msg+1);        gotsig=SIGHUP;        break;    case CT_CONFREQ:#ifndef DONT_SEND_CONF	myconfinfo.cmd=CT_CONF;	sendctl(f, (char *)&myconfinfo, sizeof(myconfinfo), 1, MSG_OOB);#endif	/* fall thru */    case CT_CONF:	ci=(struct confinfo *)msg;	if (memcmp(&ci->magic, "CIPE", 4))	    break;	snprintf(buf, sizeof(buf),		 "proto=%d, crypto=%c, version=%d.%d, %s key parser",		 ci->protocol, ci->crypto, ci->swmaj, ci->swmin,		 ci->keyright?"correct":"broken");	Log(LOG_INFO, "peer configuration info: %s", buf);#define check(v,s) \	if (ci->v!=myconfinfo.v) \	    Log(LOG_ERR, s " mismatch to peer, this will not work!\n");	check(protocol, "Protocol version");	check(crypto, "Cipher algorithm");	check(keyright, "Key parser");	break;#undef check    default:        Log(LOG_NOTICE, "unknown control %d", msg[0]);    }}/*** The key exchange procedure ***/#define REM 	256	/* How many keys to remember *//* Cache last valid key CRCs. */static int dupcheck(crc c){    static crc ca[REM];    static int caf=0, cal=0;    int i;    for (i=cal; i<caf; ++i)	if (ca[i%REM]==c)	    return 1;    if (caf-cal>=REM)	if (++cal>REM) {	    caf-=REM;	    cal-=REM;	}    ca[caf%REM]=c;    ++caf;    return 0;}#define K_SUCCESS 1#define K_TIMEOUT 0#define K_HARDERR -1#define K_SOFTERR -2int kxchg(int f, int r){    int x=0, e=0;    crc c;    #define kx_typ       (LM->kxbuf[0])    #define kx_nkind_key (LM->kxbuf+1)    #define kx_ts        ntohl(*(time_t *)(LM->kxbuf+KEYXCHGTSPOS))    #define get_kx_nkind_crc(x) memcpy((x), LM->kxbuf+1+userKeySize, 4)    #define put_kx_nkind_crc(x) memcpy(LM->kxbuf+1+userKeySize, (x), 4)    #define get_kx_nkack_crc(x) memcpy((x), LM->kxbuf+1, 4)    #define put_kx_nkack_crc(x) memcpy(LM->kxbuf+1, (x), 4)    if ((x=recv(f, LM->kxbuf, KEYXCHGBLKMIN, 0))<=0) {	if (errno==EAGAIN || errno==EINTR)	     /* This is normal, would be even after select */	    return K_TIMEOUT;	Log(LOG_INFO, "kxchg: recv: %m");	if (errno==ENXIO)	    /* Device was closed */	    return K_HARDERR;	/* allow for some amount of ECONNREFUSED etc. */	return K_SOFTERR;    }#if 0    hexdump(LM->kxbuf, x);#endif    if (LM->kxbuf[0]>=CT_DUMMY) {        LM->kxbuf[55]='\0'; /* max length of message */        ctrl(f, LM->kxbuf, x);        return K_SUCCESS;    }    if (OI(tokxts) && (abs(time(0)-kx_ts)>OI(tokxts))) {        Log(LOG_NOTICE, "KX: timestamp error: %02x %lx %x\n",            kx_typ, time(0), kx_ts);        return K_SUCCESS;    }    switch(kx_typ) {    case NK_RREQ:	kx_typ=NK_REQ;	dprintf(("KX: [NK_RREQ] sending NK_REQ\n"));	x=send(f, &LM->kxbuf, sizeof(LM->kxbuf), 0); e=errno;	++ks.rreq;	break;    case NK_REQ:	kx_typ=NK_IND;	if (read(r, &LM->skey, userKeySize)!=userKeySize) {	    Log(LOG_ERR, "kxchg: read(r): %m");	    return K_HARDERR;	}	memcpy(kx_nkind_key, LM->skey, userKeySize);	LM->scrc=htonl(crc32(0, LM->skey, userKeySize));        put_kx_nkind_crc(&LM->scrc);	dprintf(("KX: [NK_REQ] sending NK_IND " CRCFORM "\n", LM->scrc));	x=send(f, &LM->kxbuf, sizeof(LM->kxbuf), 0); e=errno;        LM->sio.which=KEY_INVAL+KEY_SEND;        if (ioctl_setkey(f, device, &LM->sio)<0)            Log(LOG_ERR, "setkey: %m");	++ks.req;	break;    case NK_IND:        get_kx_nkind_crc(&c);	if (	    crc32(0, kx_nkind_key, userKeySize)==ntohl(c)	    ) {	    if (dupcheck(c)) {		dprintf(("KX: [NK_IND] duplicate\n"));		++ks.indb;	    } else {		LM->sio.which=KEY_RECV;		memcpy(&LM->sio.thekey, kx_nkind_key, userKeySize);                LM->sio.keylen=userKeySize;		if (ioctl_setkey(f, device, &LM->sio)<0)		    perror("setkey");		else {		    kx_typ=NK_ACK;                    put_kx_nkack_crc(&c); /* XX */		    dprintf(("KX: [NK_IND] sending NK_ACK " CRCFORM "\n", c));		    x=send(f, &LM->kxbuf, sizeof(LM->kxbuf), 0); e=errno;		}		++ks.ind;	    }	} else {	    dprintf(("KX: [NK_IND] invalid\n"));	    ++ks.indb;	}	break;    case NK_ACK:        get_kx_nkack_crc(&c);	if (LM->scrc==c) {	    if (dupcheck(c)) {		dprintf(("KX: [NK_ACK] duplicate\n"));		++ks.ackb;	    } else {		LM->sio.which=KEY_SEND;		memcpy(&LM->sio.thekey, &LM->skey, userKeySize);                LM->sio.keylen=userKeySize;		dprintf(("KX: [NK_ACK] got " CRCFORM "\n", LM->scrc));		if (ioctl_setkey(f, device, &LM->sio)<0)		    perror("setkey");		++ks.ack;		memset(&LM->skey, 0, sizeof(LM->skey));	    }	} else {	    dprintf(("KX: [NK_ACK] unknown " CRCFORM "\n", c));	    ++ks.ackb;	}	break;    default:	dprintf(("KX: invalid type %02X\n", kx_typ));	++ks.bogus;    }    memset(LM->kxbuf, 0, sizeof(LM->kxbuf));    if (x<0) {	errno=e;	Log(LOG_NOTICE, "kxchg: send: %m");	if (e==ENXIO)	    return K_HARDERR;        return K_SOFTERR;    }    return K_SUCCESS;}#define M_SUCCESS 1#define M_SOFTERR 0#define M_HARDERR -1int mainloop(int fd, int sd, int ur){    int i, j;    time_t t;    while (1) {        i=kxchg(fd, ur);        if (i==K_HARDERR)            return M_HARDERR;        if (gotsig) {            Log(LOG_NOTICE, "%s", strsignal(gotsig));            return M_HARDERR;        }        if ((sd>=0) && ((j=eofsocks(sd)))) {            Log(LOG_NOTICE, "%s on socks connection", eofsocks_str[j]);            return M_HARDERR;        }        t=time(0);        if (t>=pongtime) {            Log(LOG_NOTICE, "keepalive timeout");            pongtime=MAXINT;            return M_SOFTERR;        }        if (t>=pingtime) {            char buf=CT_PING;            sendctl(fd, &buf, 1, 1, 0);            pingtime=t+OI(ping);            pongtime=t+OI(toping);        }        if (i==K_SUCCESS) {            return M_SUCCESS;        }        if (i==K_SOFTERR)            return M_SOFTERR;    }}/*** Call the ip-up, ip-down scripts ***/void pspawn(char *s){    int p, c;    if (secchk(s, 0022, 0022, 0))        return;    p=getpid();    if ((c=fork())<0) {	Log(LOG_ERR, "pspawn: fork: %m");	return;    }    if (c) {	(void) wait(NULL); /* exactly one child is active */    } else {	/* call <interface> <my-addr> <daemon-pid> <local> <remote> <arg> */	char bufa[32], bufb[32], bufc[32], bufd[32];	char *na[]={s, device, bufa, bufb, bufc, bufd, OS(arg), NULL};        struct options *o = opts;	sprintf(bufa, "%s:%d", inet_ntoa(OAaddr(me)), ntohs(OAport(me)));	sprintf(bufb, "%d", p);	sprintf(bufc, "%s", inet_ntoa(OAaddr(ipaddr)));	sprintf(bufd, "%s", inet_ntoa(OAaddr(ptpaddr)));        /* put all non-secret options into environment */        for (o=opts+1; o->oname; ++o)            if (o->otyp!=Tsecret)                putenv(strdup(optstr(o)));        /* should closelog(); ? */	close(0); close(1); close(2);	(void) open("/dev/null", O_RDWR);	(void) dup(0); (void) dup(0);	execv(s, na);	Log(LOG_WARNING, "pspawn: exec %s: %m", s);	exit(1);    }}/*** Main program ***/int main(int argc, char *argv[]){    int i=1, ur, fd, sd=-1, isup, errcnt;    pid_t pa=0;    char pidfile[128]="";    char *st;    char *pn=strrchr(argv[0], '/');    if (pn)	++pn;    else	pn=argv[0];    if (getuid() || geteuid()) {	fprintf(stderr, "This program must be run by root.\n");	exit(1);        /* This program is not setuid-safe. If run by local users with           arbitrary options, it could easily be tricked into executing           any code as root. */    }    if (!(LM=malloc(sizeof(struct lockmem)))) {        perror("malloc");        exit(1);    }    memset(LM, 0, sizeof(struct lockmem));    xmlock(LM, sizeof(struct lockmem));    openlog(pn, LOG_CONS|LOG_NDELAY|LOG_PID, LOGFAC);    /* Snarf options from: standard options file, user-supplied file and       finally, command line */    setopt_file(CTLDIR "/options", 0);    while ((i=getopt(argc, argv, "is:S:o:"))!=EOF) {        switch(i) {        case 'i': inetd=1; break;	case 's': usesock=atoi(optarg); break;	case 'S': sd=atoi(optarg); break;        case 'o': if (setopt_file(optarg, 1)<0) exit(1); break;        default: usage(pn);        }    }    setopt_cmdline(argc-optind, argv+optind);    if (!OI(maxerr))	OI(maxerr)=8; /* compatibility */    for (i=getdtablesize()-1; i>2; --i)	if (i!=usesock)	    (void) close(i);    if (OI(debug)) {        closelog();	printf("CIPE daemon vers %s (c) Olaf Titz 1996-2003\n",	       daemon_version);        logstderr=1;	dumpopt();    } else if (!inetd) {	/* daemonize */	gotsig=0;	setsig(SIGUSR1, sighandexit);	setsig(SIGCHLD, sighand);	if ((i=fork())<0) {	    perror("fork"); exit(1);	}	if (i) {            /* wait until the child is ready - will send SIGUSR1 */            while (1) {                int s;                if (wait(&s)==i)                    exit(WIFEXITED(s)?WEXITSTATUS(s):255);            }	    exit(0);        }        setsig(SIGCHLD, SIG_DFL);        /* re-lock after fork */        xmlock(LM, sizeof(struct lockmem));        pa=getppid();	close(0); close(1); close(2);	setsid();	syslog(LOG_INFO, "CIPE daemon vers %s (c) Olaf Titz 1996-2003",	       daemon_version);    }    setsig(SIGHUP, sighand);    setsig(SIGINT, sighand);    setsig(SIGTERM, sighand);    setsig(SIGPIPE, sighand);    setsig(SIGUSR1, sighand);    if ((ur=open("/dev/urandom", O_RDONLY))<0) {	Log(LOG_ERR, "open(/dev/urandom): %m"); exit(1);    }    i=MAXINT;    if (OA(socks)) {        i=30; /* set timeout for control socket check */	if (sd<0)	    sd=opensocks();	if (sd<0)	    exit(1);    }    if ((fd=opendev())<0)	exit(1);    /* write PID file - contains some PKCIPE compat magic */    if (OS(piddir) && strlen(OS(piddir))) {        FILE *f;        int j=snprintf(pidfile, sizeof(pidfile),                       "%s/%s.pid", OS(piddir),                       OS(arg) ? OS(arg) : device);        if (j<0 || j>sizeof(pidfile)) {            Log(LOG_ERR, "pidfile path too long"); exit(1);        }        if (!(f=fopen(pidfile, "w"))) {            Log(LOG_ERR, "open(pidfile): %m"); exit(1);        }        fprintf(f, "%d %s\n", getpid(), device);        fclose(f);    }    pspawn(OS(ipup) ? OS(ipup) : CTLDIR "/ip-up");    /* Set timer for periodic checks: ping, ping-timeout */    if (OI(ping)) {        pingtime=time(0);        if (OI(ping)<i)            i=OI(ping);    }    if (OI(toping)) {        if (OI(toping)<i)            i=OI(toping);    }    if (i<MAXINT) {	struct itimerval t;	setsig(SIGALRM, sighandnot);	t.it_interval.tv_sec = i;	t.it_interval.tv_usec = 0;	t.it_value.tv_sec = i+10;	t.it_value.tv_usec = 0;	setitimer(ITIMER_REAL, &t, 0);    }    if (pa>1)        kill(pa, SIGUSR1);#if 0    sendctl(fd, "\x71starting up", 13, 1, 0);#endif#ifndef DONT_SEND_CONF    myconfinfo.cmd=CT_CONFREQ;    sendctl(fd, (char *)&myconfinfo, sizeof(myconfinfo), 1, MSG_OOB);#endif    gotsig=0;    isup=1;    errcnt=OI(maxerr);    if (OI(stayalive)) {        while ((i=mainloop(fd, sd, ur))!=M_HARDERR) {            if (i==M_SOFTERR && isup && OI(maxerr)>=0 && --errcnt<0) {                isup=0;                pspawn(OS(ipdown) ? OS(ipdown) : CTLDIR "/ip-down");            }            if (i==M_SUCCESS) {                errcnt=OI(maxerr);                if (!isup) {                    isup=1;                    pspawn(OS(ipup) ? OS(ipup) : CTLDIR "/ip-up");                }            }        }    } else {        while ((i=mainloop(fd, sd, ur))!=M_HARDERR) {            if (i==M_SOFTERR && OI(maxerr)>=0 && --errcnt<0)                break;            if (i==M_SUCCESS)                errcnt=OI(maxerr);        }    }    gotsig=-1;#if 1    sendctl(fd, "\x71going down", 12, 0, 0);#endif    if ((st=getstats()))        Log(LOG_INFO, "Interface stats %s\n", st);    Log(LOG_INFO, "KX stats: rreq=%d, req=%d, ind=%d, indb=%d, ack=%d,"        " ackb=%d, unknown=%d\n", ks.rreq, ks.req, ks.ind, ks.indb,        ks.ack, ks.ackb, ks.bogus);    if (isup)        pspawn(OS(ipdown) ? OS(ipdown) : CTLDIR "/ip-down");    closedev(fd);    if (pidfile[0])        unlink(pidfile);    Log(LOG_INFO, "%s: daemon exiting", device);    return 0;}

⌨️ 快捷键说明

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