示例#1
0
int main(int argc, char **argv) {

    unsigned char *x;
    unsigned long long xlen;

    if (argv[0])
        if (argv[1]) {
            if (str_equal(argv[1], "-h"))
                die_usage(0);
        }

    /* get password  */
    x = (unsigned char *)env_get("PASSWORD");
    if (!x) { errno = 0; die_usage("$PASSWORD not set"); }
    xlen = str_len((char *)x);

    /* create salt */
    randombytes(s, sizeof s);

    /* derive key  */
    if (sha512hmacpbkdf2(h, sizeof h, x, xlen, s, sizeof s, ROUNDS) == -1) die_fatal("unable to derive keys", 0);
    byte_zero(x, xlen);

    /* create nonce */
    randombytes(n, sizeof n);
    uint64_pack(n, nanoseconds());
    sha512(nk, (unsigned char *)MAGIC, MAGICBYTES);
    crypto_block_aes256vulnerable(n, n, nk);

    /* initialize */
    crypto_init(&ctx, n, h, MAGIC);
    randombytes(h, sizeof h);
    sha512_init(&shactx);

    /* write header */
    if (writeall(1, MAGIC, MAGICBYTES) == -1) die_fatal("unable to write output", 0);
    if (writeall(1, s, sizeof s) == -1) die_fatal("unable to write output", 0);
    randombytes(s, sizeof s);
    if (writeall(1, n, sizeof n) == -1) die_fatal("unable to write output", 0);

    for (;;) {
        inlen = readblock(in, BLOCK);
        if (inlen != BLOCK) break;
        if (sha512_block(&shactx, in, inlen) != 0) die_fatal("unable to compute hash", 0);
        if (crypto_block(&ctx, in, inlen) != 0) die_fatal("unable to encrypt stream", 0);
        if (writeall(1, in, inlen) == -1) die_fatal("unable to write output", 0);
    }
    if (sha512_last(&shactx, h, in, inlen) != 0) die_fatal("unable to compute hash", 0);
    byte_copy(in + inlen, CHECKSUMBYTES, h);
    inlen += CHECKSUMBYTES;
    if (crypto_last(&ctx, in, inlen) != 0) die_fatal("unable to encrypt stream", 0);
    if (writeall(1, in, inlen) == -1) die_fatal("unable to write output", 0);

    if (fsyncfd(1) == -1) die_fatal("unable to write output", 0);
    cleanup();
    _exit(0);
}
示例#2
0
void ttymodes_packt (char *s, ttymodes const *t)
{
  unsigned int i ;
  uint32_pack(s, (uint32)NCCS) ;
  s += 4 ;
  uint64_pack(s, (uint64)t->ti.c_iflag) ;
  s += 8 ;
  uint64_pack(s, (uint64)t->ti.c_oflag) ;
  s += 8 ;
  uint64_pack(s, (uint64)t->ti.c_cflag) ;
  s += 8 ;
  uint64_pack(s, (uint64)t->ti.c_lflag) ;
  s += 8 ;
  for (i = 0 ; i < NCCS ; i++)
  {
    uint64_pack(s, t->ti.c_cc[i]) ;
    s += 8 ;
  }
}
示例#3
0
int validate_crypto_write(unsigned char *buffer, UNUSED(uint64_t length))
{
  unsigned char *block;
  unsigned char *ciphertextpadded;
  unsigned char nonce[crypto_box_NONCEBYTES];
  unsigned char lengthpacked[40];
  unsigned char lengthbox[40] = {0};
  uint64_t unpackedlen;
  uint64_t packetnonce;
  uint64_t ciphertextlen;
  uint64_t blocklen;

  /* unpack nonce and check it's validity */
  packetnonce = uint64_unpack(buffer + 8);
  /* nonce is prefixed with 16-byte string "splonbox-client" */
  memcpy(nonce, "splonebox-server", 16);
  memcpy(nonce + 16, buffer + 8, 8);

  memcpy(lengthbox + 16, buffer + 16, 24);

  if (crypto_box_open_afternm(lengthpacked, lengthbox, 40, nonce,
      cc.clientshortservershort)) {
    return (-1);
  }

  unpackedlen = uint64_unpack(lengthpacked + 32);

  ciphertextlen = unpackedlen - 24;
  blocklen = unpackedlen - 40;

  block = MALLOC_ARRAY(ciphertextlen, unsigned char);
  ciphertextpadded = CALLOC(ciphertextlen, unsigned char);

  if (block == NULL || ciphertextpadded == NULL)
    return (-1);

  memcpy(ciphertextpadded + 16, buffer + 40, blocklen);

  uint64_pack(nonce + 16, packetnonce + 2);

  if (crypto_box_open_afternm(block, ciphertextpadded, ciphertextlen, nonce,
      cc.clientshortservershort)) {
    FREE(block);
    FREE(ciphertextpadded);
    return (-1);
  }

  FREE(block);
  FREE(ciphertextpadded);

  return (0);
}
示例#4
0
int main(int argc,char **argv)
{
  long long pos;
  long long len;
  long long u;
  long long r;
  long long i;
  long long k;
  long long recent;
  long long nextaction;
  long long timeout;
  struct pollfd *q;
  struct pollfd *watch8;
  struct pollfd *watchtochild;
  struct pollfd *watchfromchild;

  signal(SIGPIPE,SIG_IGN);

  if (!argv[0]) die_usage(0);
  for (;;) {
    char *x;
    if (!argv[1]) break;
    if (argv[1][0] != '-') break;
    x = *++argv;
    if (x[0] == '-' && x[1] == 0) break;
    if (x[0] == '-' && x[1] == '-' && x[2] == 0) break;
    while (*++x) {
      if (*x == 'q') { flagverbose = 0; continue; }
      if (*x == 'Q') { flagverbose = 1; continue; }
      if (*x == 'v') { if (flagverbose == 2) flagverbose = 3; else flagverbose = 2; continue; }
      if (*x == 'c') { flagserver = 0; wantping = 2; continue; }
      if (*x == 'C') { flagserver = 0; wantping = 1; continue; }
      if (*x == 's') { flagserver = 1; wantping = 0; continue; }
      die_usage(0);
    }
  }
  if (!*++argv) die_usage("missing prog");

  for (;;) {
    r = open_read("/dev/null");
    if (r == -1) die_fatal("unable to open /dev/null",0,0);
    if (r > 9) { close(r); break; }
  }

  if (open_pipe(tochild) == -1) die_fatal("unable to create pipe",0,0);
  if (open_pipe(fromchild) == -1) die_fatal("unable to create pipe",0,0);

  blocking_enable(tochild[0]);
  blocking_enable(fromchild[1]);

  child = fork();
  if (child == -1) die_fatal("unable to fork",0,0);
  if (child == 0) {
    close(8);
    close(9);
    if (flagserver) {
      close(0);
      if (dup(tochild[0]) != 0) die_fatal("unable to dup",0,0);
      close(1);
      if (dup(fromchild[1]) != 1) die_fatal("unable to dup",0,0);
    } else {
      close(6);
      if (dup(tochild[0]) != 6) die_fatal("unable to dup",0,0);
      close(7);
      if (dup(fromchild[1]) != 7) die_fatal("unable to dup",0,0);
    }
    signal(SIGPIPE,SIG_DFL);
    execvp(*argv,argv);
    die_fatal("unable to run",*argv,0);
  }

  close(tochild[0]);
  close(fromchild[1]);

  recent = nanoseconds();
  lastspeedadjustment = recent;
  if (flagserver) maxblocklen = 1024;

  for (;;) {
    if (sendeofacked)
      if (receivewritten == receivetotalbytes)
        if (receiveeof)
          if (tochild[1] < 0)
	    break; /* XXX: to re-ack should enter a TIME-WAIT state here */

    q = p;

    watch8 = q;
    if (watch8) { q->fd = 8; q->events = POLLIN; ++q; }

    watchtochild = q;
    if (tochild[1] < 0) watchtochild = 0;
    if (receivewritten >= receivebytes) watchtochild = 0;
    if (watchtochild) { q->fd = tochild[1]; q->events = POLLOUT; ++q; }

    watchfromchild = q;
    if (sendeof) watchfromchild = 0;
    if (sendbytes + 4096 > sizeof sendbuf) watchfromchild = 0;
    if (watchfromchild) { q->fd = fromchild[0]; q->events = POLLIN; ++q; }

    nextaction = recent + 60000000000LL;
    if (wantping == 1) nextaction = recent + 1000000000;
    if (wantping == 2) nextaction = 0;
    if (blocknum < OUTGOING)
      if (!(sendeof ? sendeofprocessed : sendprocessed >= sendbytes))
        if (nextaction > lastblocktime + nsecperblock) nextaction = lastblocktime + nsecperblock;
    if (earliestblocktime) {
      long long nextretry = earliestblocktime + rtt_timeout;
      if (nextretry < lastblocktime + nsecperblock) nextretry = lastblocktime + nsecperblock;
      if (nextretry < nextaction) nextaction = nextretry;
    }

    if (messagenum)
      if (!watchtochild)
        nextaction = 0;

    if (nextaction <= recent)
      timeout = 0;
    else
      timeout = (nextaction - recent) / 1000000 + 1;

    /* XXX */
    if (childdied) timeout = 10;
    pollret = poll(p,q - p,timeout);
    if (pollret < 0) {
      watch8 = 0;
      watchtochild = 0;
      watchfromchild = 0;
    } else {
      if (watch8) if (!watch8->revents) watch8 = 0;
      if (watchtochild) if (!watchtochild->revents) watchtochild = 0;
      if (watchfromchild) if (!watchfromchild->revents) watchfromchild = 0;
    }

    /* XXX */
    if (childdied && !pollret) {
        if (childdied++ > 999) goto finish;
    }

    /* XXX: keepalives */

    do { /* try receiving data from child: */
      if (!watchfromchild) break;
      if (sendeof) break;
      if (sendbytes + 4096 > sizeof sendbuf) break;

      pos = (sendacked & (sizeof sendbuf - 1)) + sendbytes;
      if (pos < sizeof sendbuf) {
        r = read(fromchild[0],sendbuf + pos,sizeof sendbuf - pos);
      } else {
        r = read(fromchild[0],sendbuf + pos - sizeof sendbuf,sizeof sendbuf - sendbytes);
      }
      if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break;
      if (r < 0) { sendeof = 4096; break; }
      if (r == 0) { sendeof = 2048; break; }
      sendbytes += r;
      if (sendbytes >= 1152921504606846976LL) die_internalerror();
    } while(0);

    recent = nanoseconds();

    do { /* try re-sending an old block: */
      if (recent < lastblocktime + nsecperblock) break;
      if (earliestblocktime == 0) break;
      if (recent < earliestblocktime + rtt_timeout) break;

      for (i = 0;i < blocknum;++i) {
	pos = (blockfirst + i) & (OUTGOING - 1);
        if (blocktime[pos] == earliestblocktime) {
	  if (recent > lastpanic + 4 * rtt_timeout) {
	    nsecperblock *= 2;
	    lastpanic = recent;
	    lastedge = recent;
	  }
	  goto sendblock;
        }
      }
    } while(0);

    do { /* try sending a new block: */
      if (recent < lastblocktime + nsecperblock) break;
      if (blocknum >= OUTGOING) break;
      if (!wantping)
        if (sendeof ? sendeofprocessed : sendprocessed >= sendbytes) break;
      /* XXX: if any Nagle-type processing is desired, do it here */

      pos = (blockfirst + blocknum) & (OUTGOING - 1);
      ++blocknum;
      blockpos[pos] = sendacked + sendprocessed;
      blocklen[pos] = sendbytes - sendprocessed;
      if (blocklen[pos] > maxblocklen) blocklen[pos] = maxblocklen;
      if ((blockpos[pos] & (sizeof sendbuf - 1)) + blocklen[pos] > sizeof sendbuf)
        blocklen[pos] = sizeof sendbuf - (blockpos[pos] & (sizeof sendbuf - 1));
	/* XXX: or could have the full block in post-buffer space */
      sendprocessed += blocklen[pos];
      blockeof[pos] = 0;
      if (sendprocessed == sendbytes) {
        blockeof[pos] = sendeof;
	if (sendeof) sendeofprocessed = 1;
      }
      blocktransmissions[pos] = 0;

      sendblock:

      blocktransmissions[pos] += 1;
      blocktime[pos] = recent;
      blockid[pos] = nextmessageid;
      if (!++nextmessageid) ++nextmessageid;

      /* constraints: u multiple of 16; u >= 16; u <= 1088; u >= 48 + blocklen[pos] */
      u = 64 + blocklen[pos];
      if (u <= 192) u = 192;
      else if (u <= 320) u = 320;
      else if (u <= 576) u = 576;
      else if (u <= 1088) u = 1088;
      else die_internalerror();
      if (blocklen[pos] < 0 || blocklen[pos] > 1024) die_internalerror();

      byte_zero(buf + 8,u);
      buf[7] = u / 16;
      uint32_pack(buf + 8,blockid[pos]);
      /* XXX: include any acknowledgments that have piled up */
      uint16_pack(buf + 46,blockeof[pos] | (crypto_uint16) blocklen[pos]);
      uint64_pack(buf + 48,blockpos[pos]);
      byte_copy(buf + 8 + u - blocklen[pos],blocklen[pos],sendbuf + (blockpos[pos] & (sizeof sendbuf - 1)));

      if (writeall(9,buf + 7,u + 1) == -1) die_fatal("unable to write descriptor 9",0,0);
      lastblocktime = recent;
      wantping = 0;

      earliestblocktime_compute();
    } while(0);

    do { /* try receiving messages: */
      if (!watch8) break;
      r = read(8,buf,sizeof buf);
      if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break;
      if (r == 0) die_badmessage();
      if (r < 0) die_fatal("unable to read from file descriptor 8",0,0);
      for (k = 0;k < r;++k) {
        messagetodo[messagetodolen++] = buf[k];
	u = 16 * (unsigned long long) messagetodo[0];
	if (u < 16) die_badmessage();
	if (u > 1088) die_badmessage();
	if (messagetodolen == 1 + u) {
	  if (messagenum < INCOMING) {
	    pos = (messagefirst + messagenum) & (INCOMING - 1);
	    messagelen[pos] = messagetodo[0];
	    byte_copy(message[pos],u,messagetodo + 1);
	    ++messagenum;
	  } else {
	    ; /* drop tail */
	  }
	  messagetodolen = 0;
	}
      }
    } while(0);

    do { /* try processing a message: */
      if (!messagenum) break;
      if (tochild[1] >= 0 && receivewritten < receivebytes) break;

      maxblocklen = 1024;

      pos = messagefirst & (INCOMING - 1);
      len = 16 * (unsigned long long) messagelen[pos];
      do { /* handle this message if it's comprehensible: */
	unsigned long long D;
	unsigned long long SF;
	unsigned long long startbyte;
	unsigned long long stopbyte;
	crypto_uint32 id;
	long long i;

        if (len < 48) break;
        if (len > 1088) break;

	id = uint32_unpack(message[pos] + 4);
	for (i = 0;i < blocknum;++i) {
	  k = (blockfirst + i) & (OUTGOING - 1);
	  if (blockid[k] == id) {
	    rtt = recent - blocktime[k];
	    if (!rtt_average) {
	      nsecperblock = rtt;
	      rtt_average = rtt;
	      rtt_deviation = rtt / 2;
	      rtt_highwater = rtt;
	      rtt_lowwater = rtt;
	    }

	    /* Jacobson's retransmission timeout calculation: */
	    rtt_delta = rtt - rtt_average;
	    rtt_average += rtt_delta / 8;
	    if (rtt_delta < 0) rtt_delta = -rtt_delta;
	    rtt_delta -= rtt_deviation;
	    rtt_deviation += rtt_delta / 4;
	    rtt_timeout = rtt_average + 4 * rtt_deviation;
	    /* adjust for delayed acks with anti-spiking: */
	    rtt_timeout += 8 * nsecperblock;

	    /* recognizing top and bottom of congestion cycle: */
	    rtt_delta = rtt - rtt_highwater;
	    rtt_highwater += rtt_delta / 1024;
	    rtt_delta = rtt - rtt_lowwater;
	    if (rtt_delta > 0) rtt_lowwater += rtt_delta / 8192;
	    else rtt_lowwater += rtt_delta / 256;

	    if (rtt_average > rtt_highwater + 5000000) rtt_seenrecenthigh = 1;
	    else if (rtt_average < rtt_lowwater) rtt_seenrecentlow = 1;

	    if (recent >= lastspeedadjustment + 16 * nsecperblock) {
	      if (recent - lastspeedadjustment > 10000000000LL) {
	        nsecperblock = 1000000000; /* slow restart */
		nsecperblock += randommod(nsecperblock / 8);
	      }

	      lastspeedadjustment = recent;

	      if (nsecperblock >= 131072) {
	        /* additive increase: adjust 1/N by a constant c */
	        /* rtt-fair additive increase: adjust 1/N by a constant c every nanosecond */
	        /* approximation: adjust 1/N by cN every N nanoseconds */
	        /* i.e., N <- 1/(1/N + cN) = N/(1 + cN^2) every N nanoseconds */
	        if (nsecperblock < 16777216) {
		  /* N/(1+cN^2) approx N - cN^3 */
		  u = nsecperblock / 131072;
	          nsecperblock -= u * u * u;
	        } else {
	          double d = nsecperblock;
	          nsecperblock = d/(1 + d*d / 2251799813685248.0);
	        }
	      }

	      if (rtt_phase == 0) {
	        if (rtt_seenolderhigh) {
		  rtt_phase = 1;
		  lastedge = recent;
	          nsecperblock += randommod(nsecperblock / 4);
		}
	      } else {
	        if (rtt_seenolderlow) {
		  rtt_phase = 0;
	        }
	      }

	      rtt_seenolderhigh = rtt_seenrecenthigh;
	      rtt_seenolderlow = rtt_seenrecentlow;
	      rtt_seenrecenthigh = 0;
	      rtt_seenrecentlow = 0;
	    }

	    do {
	      if (recent - lastedge < 60000000000LL) {
	        if (recent < lastdoubling + 4 * nsecperblock + 64 * rtt_timeout + 5000000000LL) break;
	      } else {
	        if (recent < lastdoubling + 4 * nsecperblock + 2 * rtt_timeout) break;
	      }
	      if (nsecperblock <= 65535) break;

              nsecperblock /= 2;
	      lastdoubling = recent;
	      if (lastedge) lastedge = recent;
	    } while(0);
	  }
	}

	stopbyte = uint64_unpack(message[pos] + 8);
	acknowledged(0,stopbyte);
	startbyte = stopbyte + (unsigned long long) uint32_unpack(message[pos] + 16);
	stopbyte = startbyte + (unsigned long long) uint16_unpack(message[pos] + 20);
	acknowledged(startbyte,stopbyte);
	startbyte = stopbyte + (unsigned long long) uint16_unpack(message[pos] + 22);
	stopbyte = startbyte + (unsigned long long) uint16_unpack(message[pos] + 24);
	acknowledged(startbyte,stopbyte);
	startbyte = stopbyte + (unsigned long long) uint16_unpack(message[pos] + 26);
	stopbyte = startbyte + (unsigned long long) uint16_unpack(message[pos] + 28);
	acknowledged(startbyte,stopbyte);
	startbyte = stopbyte + (unsigned long long) uint16_unpack(message[pos] + 30);
	stopbyte = startbyte + (unsigned long long) uint16_unpack(message[pos] + 32);
	acknowledged(startbyte,stopbyte);
	startbyte = stopbyte + (unsigned long long) uint16_unpack(message[pos] + 34);
	stopbyte = startbyte + (unsigned long long) uint16_unpack(message[pos] + 36);
	acknowledged(startbyte,stopbyte);

	D = uint16_unpack(message[pos] + 38);
	SF = D & (2048 + 4096);
	D -= SF;
	if (D > 1024) break;
	if (48 + D > len) break;

	startbyte = uint64_unpack(message[pos] + 40);
	stopbyte = startbyte + D;

	if (stopbyte > receivewritten + sizeof receivebuf) {
	  break;
	  /* of course, flow control would avoid this case */
	}

	if (SF) {
	  receiveeof = SF;
	  receivetotalbytes = stopbyte;
	}

	for (k = 0;k < D;++k) {
	  unsigned char ch = message[pos][len - D + k];
	  unsigned long long where = startbyte + k;
	  if (where >= receivewritten && where < receivewritten + sizeof receivebuf) {
	    receivevalid[where & (sizeof receivebuf - 1)] = 1;
	    receivebuf[where & (sizeof receivebuf - 1)] = ch;
	  }
	}
	for (;;) {
	  if (receivebytes >= receivewritten + sizeof receivebuf) break;
	  if (!receivevalid[receivebytes & (sizeof receivebuf - 1)]) break;
	  ++receivebytes;
	}

	if (!uint32_unpack(message[pos])) break; /* never acknowledge a pure acknowledgment */

	/* XXX: delay acknowledgments */
	u = 192;
        byte_zero(buf + 8,u);
        buf[7] = u / 16;
	byte_copy(buf + 12,4,message[pos]);
	if (receiveeof && receivebytes == receivetotalbytes) {
	  uint64_pack(buf + 16,receivebytes + 1);
	} else
	  uint64_pack(buf + 16,receivebytes);
	/* XXX: incorporate selective acknowledgments */
  
        if (writeall(9,buf + 7,u + 1) == -1) die_fatal("unable to write descriptor 9",0,0);
      } while(0);

      ++messagefirst;
      --messagenum;
    } while(0);

    do { /* try sending data to child: */
      if (!watchtochild) break;
      if (tochild[1] < 0) { receivewritten = receivebytes; break; }
      if (receivewritten >= receivebytes) break;

      pos = receivewritten & (sizeof receivebuf - 1);
      len = receivebytes - receivewritten;
      if (pos + len > sizeof receivebuf) len = sizeof receivebuf - pos;
      r = write(tochild[1],receivebuf + pos,len);
      if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break;
      if (r <= 0) {
        close(tochild[1]);
        tochild[1] = -1;
	break;
      }
      byte_zero(receivevalid + pos,r);
      receivewritten += r;
    } while(0);

    do { /* try closing pipe to child: */
      if (!receiveeof) break;
      if (receivewritten < receivetotalbytes) break;
      if (tochild[1] < 0) break;

      if (receiveeof == 4096)
        ; /* XXX: UNIX doesn't provide a way to signal an error through a pipe */
      close(tochild[1]);
      tochild[1] = -1;
    } while(0);

    /* XXX */
    if (!childdied){
        if (waitpid(child,&childstatus, WNOHANG) > 0) {
          close(tochild[1]);
          tochild[1] = -1;
          childdied = 1;
        }
    }
  }

  if (!childdied) {
    do {
      r = waitpid(child,&childstatus,0);
    } while (r == -1 && errno == EINTR);
  }

finish:

  if (!WIFEXITED(childstatus)) { errno = 0; die_fatal("process killed by signal",0,0); }
  return WEXITSTATUS(childstatus);
}
示例#5
0
int main(int argc,char **argv)
{
  long long hellopackets;
  long long r;
  long long nextaction;

  signal(SIGPIPE,SIG_IGN);

  if (!argv[0]) die_usage(0);
  for (;;) {
    char *x;
    if (!argv[1]) break;
    if (argv[1][0] != '-') break;
    x = *++argv;
    if (x[0] == '-' && x[1] == 0) break;
    if (x[0] == '-' && x[1] == '-' && x[2] == 0) break;
    while (*++x) {
      if (*x == 'q') { flagverbose = 0; continue; }
      if (*x == 'Q') { flagverbose = 1; continue; }
      if (*x == 'v') { if (flagverbose == 2) flagverbose = 3; else flagverbose = 2; continue; }
      if (*x == 'c') {
        if (x[1]) { keydir = x + 1; break; }
        if (argv[1]) { keydir = *++argv; break; }
      }
      die_usage(0);
    }
  }
  if (!nameparse(servername,*++argv)) die_usage("sname must be at most 255 bytes, at most 63 bytes between dots");
  if (!hexparse(serverlongtermpk,32,*++argv)) die_usage("pk must be exactly 64 hex characters");
  if (!multiipparse(serverip,*++argv)) die_usage("ip must be a comma-separated series of IPv4 addresses");
  if (!portparse(serverport,*++argv)) die_usage("port must be an integer between 0 and 65535");
  if (!hexparse(serverextension,16,*++argv)) die_usage("ext must be exactly 32 hex characters");
  if (!*++argv) die_usage("missing prog");

  for (;;) {
    r = open_read("/dev/null");
    if (r == -1) die_fatal("unable to open /dev/null",0,0);
    if (r > 9) { close(r); break; }
  }

  if (keydir) {
    fdwd = open_cwd();
    if (fdwd == -1) die_fatal("unable to open current working directory",0,0);
    if (chdir(keydir) == -1) die_fatal("unable to change to directory",keydir,0);
    if (load("publickey",clientlongtermpk,sizeof clientlongtermpk) == -1) die_fatal("unable to read public key from",keydir,0);
    if (load(".expertsonly/secretkey",clientlongtermsk,sizeof clientlongtermsk) == -1) die_fatal("unable to read secret key from",keydir,0);
  } else {
    crypto_box_keypair(clientlongtermpk,clientlongtermsk);
  }

  crypto_box_keypair(clientshorttermpk,clientshorttermsk);
  clientshorttermnonce = randommod(281474976710656LL);
  crypto_box_beforenm(clientshortserverlong,serverlongtermpk,clientshorttermsk);
  crypto_box_beforenm(clientlongserverlong,serverlongtermpk,clientlongtermsk);

  udpfd = socket_udp();
  if (udpfd == -1) die_fatal("unable to create socket",0,0);

  for (hellopackets = 0;hellopackets < NUMIP;++hellopackets) {
    recent = nanoseconds();

    /* send a Hello packet: */

    clientextension_init();

    clientshorttermnonce_update();
    byte_copy(nonce,16,"CurveCP-client-H");
    uint64_pack(nonce + 16,clientshorttermnonce);

    byte_copy(packet,8,"QvnQ5XlH");
    byte_copy(packet + 8,16,serverextension);
    byte_copy(packet + 24,16,clientextension);
    byte_copy(packet + 40,32,clientshorttermpk);
    byte_copy(packet + 72,64,allzero);
    byte_copy(packet + 136,8,nonce + 16);
    crypto_box_afternm(text,allzero,96,nonce,clientshortserverlong);
    byte_copy(packet + 144,80,text + 16);

    socket_send(udpfd,packet,224,serverip + 4 * hellopackets,serverport);

    nextaction = recent + hellowait[hellopackets] + randommod(hellowait[hellopackets]);

    for (;;) {
      long long timeout = nextaction - recent;
      if (timeout <= 0) break;
      p[0].fd = udpfd;
      p[0].events = POLLIN;
      if (poll(p,1,timeout / 1000000 + 1) < 0) p[0].revents = 0;

      do { /* try receiving a Cookie packet: */
        if (!p[0].revents) break;
        r = socket_recv(udpfd,packet,sizeof packet,packetip,packetport);
        if (r != 200) break;
        if (!(byte_isequal(packetip,4,serverip + 4 * hellopackets) &
              byte_isequal(packetport,2,serverport) &
              byte_isequal(packet,8,"RL3aNMXK") &
              byte_isequal(packet + 8,16,clientextension) &
              byte_isequal(packet + 24,16,serverextension)
           )) break;
        byte_copy(nonce,8,"CurveCPK");
        byte_copy(nonce + 8,16,packet + 40);
        byte_zero(text,16);
        byte_copy(text + 16,144,packet + 56);
        if (crypto_box_open_afternm(text,text,160,nonce,clientshortserverlong)) break;
        byte_copy(servershorttermpk,32,text + 32);
        byte_copy(servercookie,96,text + 64);
        byte_copy(serverip,4,serverip + 4 * hellopackets);
        goto receivedcookie;
      } while (0);

      recent = nanoseconds();
    }
  }

  errno = ETIMEDOUT; die_fatal("no response from server",0,0);

  receivedcookie:

  crypto_box_beforenm(clientshortservershort,servershorttermpk,clientshorttermsk);

  byte_copy(nonce,8,"CurveCPV");
  if (keydir) {
    if (safenonce(nonce + 8,0) == -1) die_fatal("nonce-generation disaster",0,0);
  } else {
    randombytes(nonce + 8,16);
  }

  byte_zero(text,32);
  byte_copy(text + 32,32,clientshorttermpk);
  crypto_box_afternm(text,text,64,nonce,clientlongserverlong);
  byte_copy(vouch,16,nonce + 8);
  byte_copy(vouch + 16,48,text + 16);

  /* server is responding, so start child: */

  if (open_pipe(tochild) == -1) die_fatal("unable to create pipe",0,0);
  if (open_pipe(fromchild) == -1) die_fatal("unable to create pipe",0,0);

  child = fork();
  if (child == -1) die_fatal("unable to fork",0,0);
  if (child == 0) {
    if (keydir) if (fchdir(fdwd) == -1) die_fatal("unable to chdir to original directory",0,0);
    close(8);
    if (dup(tochild[0]) != 8) die_fatal("unable to dup",0,0);
    close(9);
    if (dup(fromchild[1]) != 9) die_fatal("unable to dup",0,0);
    /* XXX: set up environment variables */
    signal(SIGPIPE,SIG_DFL);
    execvp(*argv,argv);
    die_fatal("unable to run",*argv,0);
  }

  close(fromchild[1]);
  close(tochild[0]);


  for (;;) {
    p[0].fd = udpfd;
    p[0].events = POLLIN;
    p[1].fd = fromchild[0];
    p[1].events = POLLIN;

    if (poll(p,2,-1) < 0) {
      p[0].revents = 0;
      p[1].revents = 0;
    }

    do { /* try receiving a Message packet: */
      if (!p[0].revents) break;
      r = socket_recv(udpfd,packet,sizeof packet,packetip,packetport);
      if (r < 80) break;
      if (r > 1152) break;
      if (r & 15) break;
      packetnonce = uint64_unpack(packet + 40);
      if (flagreceivedmessage && packetnonce <= receivednonce) break;
      if (!(byte_isequal(packetip,4,serverip + 4 * hellopackets) &
            byte_isequal(packetport,2,serverport) &
            byte_isequal(packet,8,"RL3aNMXM") &
            byte_isequal(packet + 8,16,clientextension) &
            byte_isequal(packet + 24,16,serverextension)
         )) break;
      byte_copy(nonce,16,"CurveCP-server-M");
      byte_copy(nonce + 16,8,packet + 40);
      byte_zero(text,16);
      byte_copy(text + 16,r - 48,packet + 48);
      if (crypto_box_open_afternm(text,text,r - 32,nonce,clientshortservershort)) break;

      if (!flagreceivedmessage) {
        flagreceivedmessage = 1;
	randombytes(clientlongtermpk,sizeof clientlongtermpk);
	randombytes(vouch,sizeof vouch);
	randombytes(servername,sizeof servername);
	randombytes(servercookie,sizeof servercookie);
      }

      receivednonce = packetnonce;
      text[31] = (r - 64) >> 4;
      /* child is responsible for reading all data immediately, so we won't block: */
      if (writeall(tochild[1],text + 31,r - 63) == -1) goto done;
    } while (0);

    do { /* try receiving data from child: */
      long long i;
      if (!p[1].revents) break;
      r = read(fromchild[0],childbuf,sizeof childbuf);
      if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break;
      if (r <= 0) goto done;
      childbuflen = r;
      for (i = 0;i < childbuflen;++i) {
	if (childmessagelen < 0) goto done;
	if (childmessagelen >= sizeof childmessage) goto done;
        childmessage[childmessagelen++] = childbuf[i];
	if (childmessage[0] & 128) goto done;
	if (childmessagelen == 1 + 16 * (unsigned long long) childmessage[0]) {
	  clientextension_init();
	  clientshorttermnonce_update();
          uint64_pack(nonce + 16,clientshorttermnonce);
	  if (flagreceivedmessage) {
	    r = childmessagelen - 1;
	    if (r < 16) goto done;
	    if (r > 1088) goto done;
            byte_copy(nonce,16,"CurveCP-client-M");
	    byte_zero(text,32);
	    byte_copy(text + 32,r,childmessage + 1);
	    crypto_box_afternm(text,text,r + 32,nonce,clientshortservershort);
	    byte_copy(packet,8,"QvnQ5XlM");
	    byte_copy(packet + 8,16,serverextension);
	    byte_copy(packet + 24,16,clientextension);
	    byte_copy(packet + 40,32,clientshorttermpk);
	    byte_copy(packet + 72,8,nonce + 16);
	    byte_copy(packet + 80,r + 16,text + 16);
            socket_send(udpfd,packet,r + 96,serverip,serverport);
	  } else {
	    r = childmessagelen - 1;
	    if (r < 16) goto done;
	    if (r > 640) goto done;
	    byte_copy(nonce,16,"CurveCP-client-I");
	    byte_zero(text,32);
	    byte_copy(text + 32,32,clientlongtermpk);
	    byte_copy(text + 64,64,vouch);
	    byte_copy(text + 128,256,servername);
	    byte_copy(text + 384,r,childmessage + 1);
	    crypto_box_afternm(text,text,r + 384,nonce,clientshortservershort);
	    byte_copy(packet,8,"QvnQ5XlI");
	    byte_copy(packet + 8,16,serverextension);
	    byte_copy(packet + 24,16,clientextension);
	    byte_copy(packet + 40,32,clientshorttermpk);
	    byte_copy(packet + 72,96,servercookie);
	    byte_copy(packet + 168,8,nonce + 16);
	    byte_copy(packet + 176,r + 368,text + 16);
            socket_send(udpfd,packet,r + 544,serverip,serverport);
	  }
	  childmessagelen = 0;
	}
      }
    } while (0);
  }


  done:

  do {
    r = waitpid(child,&childstatus,0);
  } while (r == -1 && errno == EINTR);

  if (!WIFEXITED(childstatus)) { errno = 0; die_fatal("process killed by signal",0,0); }
  return WEXITSTATUS(childstatus);
}
void tai_pack_little (char *s, struct tai const *t)
{
  uint64_pack(s, tai_sec(t)) ;
}
示例#7
0
void functional_crypto(UNUSED(void **state))
{
  unsigned char nonce[crypto_box_NONCEBYTES];
  unsigned char initiatenonce[crypto_box_NONCEBYTES];
  unsigned char hellopacket[192] = {0};
  unsigned char initiatepacket[256] = {0};
  unsigned char messagepacket[120];
  unsigned char messagepacketout[120] = {0};
  unsigned char allzeroboxed[96] = {0};
  unsigned char initiatebox[160] = {0};
  unsigned char pubkeybox[96] = {0};
  unsigned char lengthbox[40] = {0};
  uint64_t plaintextlen;
  uint64_t readlen;
  outputstream write;

  connect_to_db();

  wrap_crypto_write = false;

  assert_int_equal(0, filesystem_load(".keys/server-long-term.pub",
      serverlongtermpk, sizeof serverlongtermpk));

  cc.nonce = (uint64_t) randommod(281474976710656LL);

  if (!ISODD(cc.nonce)) {
    cc.nonce++;
  }

  cc.receivednonce = 0;
  cc.state = TUNNEL_INITIAL;

  memcpy(nonce, "splonebox-client", 16);
  uint64_pack(nonce + 16, cc.nonce);

  /* pack hello packet */
  memcpy(hellopacket, "oqQN2kaH", 8);
  /* pack compressed nonce */
  memcpy(hellopacket + 104, nonce + 16, 8);

  /* generate client ephemeral keys */
  if (crypto_box_keypair(clientlongtermpk, clientlongtermsk) != 0)
    return;
  /* generate client ephemeral keys */
  if (crypto_box_keypair(clientshorttermpk, clientshorttermsk) != 0)
    return;

  memcpy(hellopacket + 8, clientshorttermpk, 32);

  assert_int_equal(0, crypto_box(allzeroboxed, allzeroboxed, 96, nonce,
      serverlongtermpk, clientshorttermsk));

  memcpy(hellopacket + 112, allzeroboxed + 16, 80);

  crypto_init();

  /* positiv test */
  assert_int_equal(0, crypto_recv_hello_send_cookie(&cc, hellopacket, &write));

  /* wrong identifier */
  memcpy(hellopacket, "deadbeef", 8);
  assert_int_not_equal(0, crypto_recv_hello_send_cookie(&cc, hellopacket, &write));
  memcpy(hellopacket, "oqQN2kaH", 8);

  /* wrong nonce */
  cc.receivednonce = cc.nonce + 1;
  assert_int_not_equal(0, crypto_recv_hello_send_cookie(&cc, hellopacket, &write));
  cc.receivednonce = 0;

  /* wrong pubkey */
  memset(hellopacket + 8, '0', 32);
  assert_int_not_equal(0, crypto_recv_hello_send_cookie(&cc, hellopacket, &write));
  memcpy(hellopacket + 8, clientshorttermpk, 32);

  assert_int_equal(0, crypto_recv_hello_send_cookie(&cc, hellopacket, &write));

  /* crypto_recv_initiate() test */

  /* pack initiate packet */
  memcpy(initiatepacket, "oqQN2kaI", 8);
  memcpy(initiatepacket + 8, cookie, 96);
  /* pack compressed nonce */
  memcpy(initiatepacket + 104, nonce + 16, 8);

  memcpy(initiatebox + 32, clientlongtermpk, 32);
  randombytes(initiatebox + 64, 16);
  memcpy(initiatenonce, "splonePV", 8);
  memcpy(initiatenonce + 8, initiatebox + 64, 16);

  memcpy(pubkeybox + 32, clientshorttermpk, 32);
  memcpy(pubkeybox + 64, servershorttermpk, 32);

  assert_int_equal(0, crypto_box(pubkeybox, pubkeybox, 96, initiatenonce,
      serverlongtermpk, clientlongtermsk));

  memcpy(initiatebox + 80, pubkeybox + 16, 80);

  assert_int_equal(0, crypto_box(initiatebox, initiatebox, 160, nonce,
      servershorttermpk, clientshorttermsk));

  memcpy(initiatepacket + 112, initiatebox + 16, 144);

  /* without valid certificate */
  assert_int_not_equal(0, crypto_recv_initiate(&cc, initiatepacket));

  /* all plugins are allowed to connect */
  db_authorized_set_whitelist_all();
  assert_int_equal(0, crypto_recv_initiate(&cc, initiatepacket));

  /* crypto_write() test */
  assert_int_equal(0, crypto_write(&cc, (char*) allzeroboxed,
      sizeof(allzeroboxed), &write));

  /* crypto_read() test */

  /* pack message packet */
  memcpy(messagepacket, "oqQN2kaM", 8);

  /* pack compressed nonce */
  memcpy(nonce, "splonebox-client", 16);
  uint64_pack(nonce + 16, cc.nonce);
  memcpy(messagepacket + 8, nonce + 16, 8);

  uint64_pack(lengthbox + 32, 120);

  assert_int_equal(0, crypto_box(lengthbox, lengthbox, 40, nonce,
      servershorttermpk, clientshorttermsk));

  memcpy(messagepacket + 16, lengthbox + 16, 24);

  uint64_pack(nonce + 16, cc.nonce + 2);

  memset(allzeroboxed, 0, 96);
  assert_int_equal(0, crypto_box_afternm(allzeroboxed, allzeroboxed, 96, nonce,
      cc.clientshortservershort));

  memcpy(messagepacket + 40, allzeroboxed + 16, 80);

  assert_int_equal(0, crypto_verify_header(&cc, messagepacket, &readlen));

  assert_int_equal(0, crypto_read(&cc, messagepacket, (char*)messagepacketout,
      readlen, &plaintextlen));

  db_close();
}
示例#8
0
文件: smb.c 项目: scolytus/gatling
static void uint64_pack_ntdate(char* dest,time_t date) {
  uint64_pack(dest,10000000ll * (date + 11644473600ll));
}