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

📄 txfr.c

📁 非常经典的加密算法
💻 C
字号:
/* */#ifdef _POSIX_SOURCE#undef _POSIX_SOURCE	/* otherwise <sys/types.h> won't define fd_set */#endif#include <sys/types.h>		/* BSD type fd_set FD_SET macros */#include <sys/time.h>		/* BSD struct timeval */#ifndef _POSIX_SOURCE		/* in case the above include files defined it */#define _POSIX_SOURCE		/* yes, I know posix doesn't have select */#endif#include <unistd.h>		/* alarm read write */#include <stdlib.h>		/* exit malloc */#include <stdio.h>#include <errno.h>		/* EINTR EAGAIN */#include <signal.h>		/* SIGCHLD */#include <string.h>		/* memset */#include <fcntl.h>		/* O_NONBLOCK */#include <sys/time.h>		/* select */#include "posignal.h"#include "log.h"#include "auth.h"#include "txfr.h"#include "deslogin.h"extern unsigned long inBytes, outBytes;#ifndef sparcvolatile #endifunsigned gotalarm = 0;/* * In POSIX, the read or write call will be interrupted by a signal.  If so,  * the read may return with -1 and errno=EINTR, or, if multi-byte, may return  * a result of the number of bytes read. */void alarmCatcher(sig)   int sig;{   gotalarm++;}#ifndef sparcvolatile #endifunsigned txfrChld = 0;void chldCatcher(sig)   int sig;{   txfrChld++;   if (debug) {      log("%s: (txfr) SIGCHLD #%d\n", progName, txfrChld);   }}int recvData(fd, buf, size, cbuf, cs)   int fd;   char *buf, *cbuf;   unsigned size;   register cipherKey cs;{   register int rcount = read(fd, cbuf, size);   if (debug > 2) {      log("read(%d,%d)=%d(%d)\n", fd, size, rcount, errno);   }   if (rcount <= 0) {      if (rcount < 0) {	 log("%s: (recv) read %d bytes fd %d failed--%s\n",	     progName, size, fd, ERRMSG);      }      return rcount;   }   cipherData(buf, cbuf, rcount, cs);   return rcount;}int sendData(fd, buf, size)   int fd;   char *buf;   unsigned size;{   int wcount;   wcount = write(fd, buf, size);   if (debug > 2) {      log("write(%d,%d)=%d(%d)\n", fd, size, wcount, errno);   }   /*     * We could get -1 and EAGAIN if a write is attempted for less than     * fpathconf(_PC_PIPE_BUF) and there isn't space yet.  In this case,    * if we just returned immediately, we could chew up a lot of CPU time    * with select continually returning true. Gag!    */   if (wcount < 0) {      log("%s: (send) write %d bytes fd %d failed--%s\n",	 progName, size, fd, ERRMSG);      exit(1);   }   if (wcount == 0) {      log("%s: (send) write %d bytes fd %d returned 0\n", progName, size, fd);      exit(1);   }   return wcount;}/* * Set the nonblocking flag for the given fd with error report. * returns the previous nonblock flag or -1 for falure (exits). */int setnonblock(fd, flag)   int fd, flag;{   int res, oldflag;   oldflag = fcntl(fd, F_GETFL);   if (oldflag < 0) {      log("%s: (setnonblock) fcntl(%d) F_GETFL failed--%s\n", 	 progName, fd, ERRMSG);      exit(1);   }   if (flag) {      res = fcntl(fd, F_SETFL, oldflag | O_NONBLOCK);   } else {      res = fcntl(fd, F_SETFL, oldflag & ~O_NONBLOCK);   }   if (res < 0) {      log("%s: (setnonblock) fcntl(%d) F_SETFL failed--%s\n", 	 progName, fd, ERRMSG);      exit(1);   }   return ((oldflag & O_NONBLOCK) == O_NONBLOCK);}/*  * Select on the master pty before the slave has a successful open behaves * totally differently on every machine I tried.  There appears to be no * machine independent way to do both of the following: * *  1) Determine when the slave has been opened *  2) Prevent multiple processes from opening the slave. * * If there was a way to do 2, what we should *really* do is to do a full * bore authentication protocal between the slave and tha master.  Since * there is no way to achieve 2 except file permissions on the slave pty, * there isn't any point; anyone that can break the file permissions can * intercept data between the slave pty and the process using it (which * will be the user shell, so we can't help here. *  * On DEC Alpha, select lies and returns true for read on the master pty when  * the slave hasn't opened it yet.  A subsequent read will fail errno=EIO. * It fails to return true for write at all. * It fails to return true for exception. * * On DEC Ultrix 4.3, select returns true for read on the master pty when  * the slave hasn't opened it yet.  A subsequent read will fail errno=EIO. * It also returns true for write.  * It also returns true for exception. * * Do whatever it takes to make sure that txfr won't abort before the slave * side of the pty has been opened.  Because select is so unpredicable before * the slave is open, we have to throw up our hands and poll until we don't * get an I/O error.  Since we can't poll transparently we have to have * the process on the slave side send us something with mkReady. * * Returns: 0 - if timeout *          1 - success *         <0 - failure (Could be from SIGCHLD) */int waitReady(fd, buf, size, timeout)    int fd;    char *buf;   unsigned size;   unsigned timeout;{   pfv oldHandler;   struct timeval to;   int res = 0;   gotalarm = 0;   oldHandler = posignal(SIGALRM, alarmCatcher);   alarm(timeout / 1000);   while (!res && !gotalarm) {      res = read(fd, buf, size);      if (debug) {	 log("%s: (waitReady) read=%d gotalarm=%d\n", progName, res, gotalarm);      }      if (res < 0) {	 if (errno != EIO) {	    break;	 }	 to.tv_sec  = 0;		/* some selects update to on return */	 to.tv_usec = 500000;		/* 500 ms polling interval */	 res = select(0, 0, 0, 0, &to);		/* wait a short while */	 if (gotalarm) {	    res = 0;	/* it was -1 from select being interrupted by signal */	 } /* res could still be -1 if SIGCHLD */      }   }   alarm(0);   posignal(SIGALRM, oldHandler);   return res;		/* res > 0 for success, < 0 failure, 0 timeout */}int mkReady(fd, buf, size, timeout)    int fd;    char *buf;   unsigned size;   unsigned timeout;{   pfv oldHandler;   struct timeval to;   int res = 0;   gotalarm = 0;   oldHandler = posignal(SIGALRM, alarmCatcher);   alarm(timeout / 1000);   while (!res && !gotalarm) {      res = write(fd, buf, size);      if (debug > 1) {	 log("%s: (mkReady) write=%d gotalarm=%d\n", progName, res, gotalarm);      }      if (res < 0) {	 if (errno != EIO) {	    break;	 }	 to.tv_sec  = 0;		/* some selects update to on return */	 to.tv_usec = 500000;		/* 500 ms polling interval */	 res = select(0, 0, 0, 0, &to);		/* wait a short while */	 if (gotalarm) {	    res = 0;	/* it was -1 from select being interrupted by signal */	 }       }   }   alarm(0);   posignal(SIGALRM, oldHandler);   return res;		/* res > 0 for success, < 0 failure, 0 timeout */}/* * Transfer data bidirectionally using a buffer of given size. * Returns when timeout (ms) expires (0 = timeout) *         or when eof (res = 1) *         or error (res = -1); *         or interrupt (res = -2) (or exception, slave closed pty) * * NOTE: there appears to be a bug in HP-UX where a read can return EAGAIN *       even if select returns true for both read and write on a tty fd. * On the DEC Alpha: *       If the slave side of a pty isn't open yet, the master side's select *       will return true for read, and the read call will fail with  *       EIO. */int txfr(fd1, fdin, fdout, bufSize, timeout, key)   int fd1, fdout, fdin;   unsigned bufSize;   unsigned timeout;   keyType key;{   char 	*cbuf = (char *) malloc(bufSize);   char 	*buf1 = (char *) malloc(bufSize);    char 	*bufin = (char *) malloc(bufSize);    struct timeval to, tov, *top = (struct timeval *) 0;	/* Not POSIX */   unsigned     max_fd = fd1;   fd_set       rmask, wmask, emask;   int 	        result = -1, oldblockin = 0, oldblockout = 0, oldblock1 = 0;   int		fdinEof = 0;   cipherKey    cs1 = (cipherKey) 0, csin = (cipherKey) 0;   pfv		oldChld;   register int res, rcount1 = 0, rcountin = 0, wcount;   register char *bufp1, *bufpin;   if (fdout > max_fd) max_fd = fdout;   if (fdin > max_fd) max_fd = fdin;   if (buf1  == (char *) 0) goto txfr_done;   if (bufin == (char *) 0) goto txfr_done;   if (cbuf  == (char *) 0) goto txfr_done;#if 0   key = (keyType) 0;			/* for debug! */#endif   cs1  = mkCipherKey(key, 1);			/* decrypt */   csin = mkCipherKey(key, 0);			/* encrypt */   if (cs1   == (cipherKey) 0) goto txfr_done;   if (csin  == (cipherKey) 0) goto txfr_done;   bufp1 = buf1;   bufpin = bufin;   if (timeout != 0) {      to.tv_sec  = (timeout / 1000);      to.tv_usec = (timeout % 1000) * 1000;      top = &tov;   }   /*    * We must use non-blocking IO to ensure that write calls won't block.    * Read calls are safe anyway.    */   oldblock1   = setnonblock(fd1, 1);   oldblockin  = setnonblock(fdin, 1);		/* must be before fdout */   oldblockout = setnonblock(fdout, 1);   txfrChld = 0;   oldChld = posignal(SIGCHLD, chldCatcher);   if (oldChld == (pfv) -1) {      log("%s: (txfr) sigaction SIGCHLD failed--%s\n", 	 progName, ERRMSG);      exit(1);   }   FD_ZERO(&emask);    do {      FD_ZERO(&rmask); 	   FD_ZERO(&wmask); 	      FD_SET(fd1, &emask); #if 0		/* we don't want exception checking on tty or files */      FD_SET(fdout, &emask); FD_SET(fdin, &emask);#endif      if (rcount1  != 0) FD_SET(fdout, &wmask); else {	 FD_SET(fd1,  &rmask);       }      if (rcountin != 0) FD_SET(fd1,   &wmask); else if (!fdinEof) {	 FD_SET(fdin, &rmask);      }      if (top != (struct timeval *) 0) {	 tov.tv_sec  = to.tv_sec;	 tov.tv_usec = to.tv_usec;      }      if (debug > 2) {	 log("select(%u,%u,%u,%u)\n", max_fd+1,	    *(unsigned *)&rmask, *(unsigned *)&wmask, *(unsigned *)&emask);      }      if (txfrChld != 0) {		/* must be right next to select */	 break;      }	/* race condition right here */      /*       * HP-UX incorrectly declares select with int * args instead of fd_set       * Ignore the warnings for select for HP-UX.       */      res = select(max_fd+1, &rmask, &wmask, &emask, top);      if (debug > 2) {	 log("select returned: %u(%u,%u,%u)\n", res,	    *(unsigned *)&rmask, *(unsigned *)&wmask, *(unsigned *)&emask);      }      if (res == 0) {			/* timeout */	 result = 0;	 break;      }      if (res < 0) {			/* error */	 if (errno == EINTR) {		/* signal (SIGCHLD occurred) */	    result = -2;	    break;	 } else {	    log("%s: select failed--%s\n", progName, ERRMSG);	    break;	 }      }      /*       * This block will never be triggered because there is no way for a        * close on a slave pty to be detected on non-hpux systems.       */      if (FD_ISSET(fd1, &emask) #if 0      || FD_ISSET(fdout, &emask)       || FD_ISSET(fdin, &emask)#endif      ) {	/* close */	 result = -2;	 break;      }      if (FD_ISSET(fd1, &rmask)) {	 rcount1 = recvData(fd1, buf1, bufSize, cbuf, cs1);	 if (rcount1 <= 0) {	    if (rcount1 == 0) {	       result = 1;	       break;	    } else {	       result = -1;	       break;	    }	 }	 bufp1    = buf1;	 inBytes += rcount1;      }      if (FD_ISSET(fdin, &rmask)) {	 rcountin = recvData(fdin, bufin, bufSize, cbuf, csin);	 if (rcountin <= 0) {	    if (rcountin == 0) {	       fdinEof = 1;	    } else {	       result = -1;	       break;	    }	 }	 bufpin    = bufin;	 outBytes += rcountin;      }      if (FD_ISSET(fd1, &wmask)) {	 wcount    = sendData(fd1, bufpin, rcountin);	 rcountin -= wcount;	 bufpin   += wcount;      }      if (FD_ISSET(fdout, &wmask)) {	 wcount   = sendData(fdout, bufp1, rcount1);	 rcount1 -= wcount;	 bufp1   += wcount;      }   } while (txfrChld == 0);   posignal(SIGCHLD, oldChld);   setnonblock(fd1, oldblock1);   setnonblock(fdin, oldblockin);   /*    * We must blindly assume that we don't want non-blocking I/O when whe    * leave.  The reason is that two fd's may actually be connected to the    * same device.  If this is the case, then it's possible to switch the    * nonblocking mode incorrectly.  (e.g. setting NON_BLOCK in fdin also    * changes it on fdout)    */   setnonblock(fdout, oldblockin);	/* oldblockin is not a bug */txfr_done:   destroyCipherKey(&csin);   destroyCipherKey(&cs1);   free(bufin);   free(buf1);   free(cbuf);   return result;}/* * Input a string of upto size chars with timout terminated by CR LF or NULL * Input: *     size - the maximum number of characters to read * * Output: *     *buf - The characters read not including terminator *            A '\0' character is always added to the end of buf * * Returns: the number of characters read (not including terminator) *          This is true even if we were interrupted by an alarm. */int getString(fd, buf, size, timeout)   int fd;   char *buf;   unsigned size;   unsigned timeout;{   register unsigned count = size;   register char *chp = buf;   char ch;   register unsigned seconds = (unsigned) ((timeout + (1000L-1)) / 1000L);   register int rcount;   pfv oldHandler;   gotalarm = 0;   oldHandler = posignal(SIGALRM, alarmCatcher);   alarm(seconds);   while (count != 0) {      rcount = read(fd, &ch, 1);      if (rcount <= 0 || gotalarm != 0) break;      if (ch == '\r' || ch == '\n' || ch == '\0') break;      *chp   = ch;      count -= rcount;      chp   += rcount;   }   alarm(0);   posignal(SIGALRM, oldHandler);   *chp = '\0';   return size - count;}/* * Read a block of binary data of the given size.   * Return the number of bytes read (0 if timeout, or read error). */int getBlock(fd, buf, size, timeout)   int fd;   char *buf;   unsigned size;   unsigned timeout;{   register unsigned seconds = (unsigned) ((timeout + (1000-1)) / 1000);   register int rcount;   pfv oldHandler;   gotalarm = 0;   oldHandler = posignal(SIGALRM, alarmCatcher);   alarm(seconds);   rcount = read(fd, buf, size);   alarm(0);   posignal(SIGALRM, oldHandler);   /*    * No error checking is reported here. If we got a a signal, we could get    * either -1/errno=EINTR, or a short read, depending upon implementation.    */   if (rcount < 0) {      rcount = 0;   }   return rcount;}/* * Encipher all the data from sfd to dfd.  Send the entire shmeel in timeout * seconds, abort if longer.  This routine is used for sending a nologin * message contained in the file /etc/nologin. */int cipherCopy(dfd, sfd, timeout, key)   int dfd, sfd;   unsigned timeout;   keyType key;{   int 		rcount, wcount = 0;   char 	buf[128], cbuf[128];    register char *bufp = buf;   pfv 		oldHandler;   cipherKey 	cs = mkCipherKey(key, 0);			/* encrypt */   if (cs == (cipherKey) 0) return -1;   gotalarm = 0;   oldHandler = posignal(SIGALRM, alarmCatcher);   alarm(timeout);   do {      while ((rcount = read(sfd, bufp, 1)) > 0) {	 if (*bufp == '\n') {	    *bufp++ = '\r';	    *bufp   = '\n';	 }	 bufp++;	 if (bufp >= buf + 127 || gotalarm != 0) break;      }      if (gotalarm != 0) break;      rcount = bufp - buf;      bufp   = buf;      cipherData(cbuf, buf, rcount, cs);      wcount = write(dfd, cbuf, rcount);      if (wcount <= 0) break;   } while (gotalarm == 0);   alarm(0);   posignal(SIGALRM, oldHandler);   destroyCipherKey(&cs);   if (rcount < 0 || wcount < 0) return -1;   return 0;}

⌨️ 快捷键说明

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