void aesctr_packet_put(struct buf *b) {

    long long pos;
    crypto_uint8 paddinglen;
    struct buf *sendbuf = &packet.sendbuf;

    pos = sendbuf->len;                         /* get position       */
    buf_putnum32(sendbuf, 0);                   /* packet id, for MAC */
    buf_putnum32(sendbuf, 0);                   /* packet length      */
    buf_putnum8(sendbuf, 0);                    /* padding length     */
    buf_put(sendbuf, b->buf, b->len);           /* add data           */

    /* add padding */
    paddinglen  = 2 * BB - ((sendbuf->len - pos - 4) % BB);
    paddinglen += randommod(2) * BB;
    buf_putpadding(sendbuf, paddinglen);

    /* add space for mac */
    buf_putzerobytes(sendbuf, AB);

    /* add packet ID */
    uint32_pack_big(sendbuf->buf + pos, packet.sendpacketid++);

    /* add packet length */
    uint32_pack_big(sendbuf->buf + pos + 4, sendbuf->len - pos - AB - 4 - 4);

    /* add padding length*/
    sendbuf->buf[pos + 8] = paddinglen;

    /* get mac */
    if (sshcrypto_auth(
        sendbuf->buf + sendbuf->len - AB,       /* a    */
        sendbuf->buf + pos,                     /* m    */
        sendbuf->len - pos - AB,                /* mlen */
        packet.servermackey                     /* k    */
        ) != 0) bug_proto();

    /* encrypt */
    if (sshcrypto_stream_xor(
        sendbuf->buf + pos + 4,                 /* c    */
        sendbuf->buf + pos + 4,                 /* m    */
        sendbuf->len - pos - 4 - AB,            /* mlen */
        packet.servernonce,                     /* n    */
        packet.serverkey                        /* k    */
        ) != 0) bug_proto();


    /* remove packet id */
    byte_copy(sendbuf->buf + pos, sendbuf->len - pos - 4, sendbuf->buf + pos + 4);
    sendbuf->len -= 4;

    /* cleanup */
    purge(sendbuf->buf + sendbuf->len, 4);
}
Example #2
0
int multiipparse(unsigned char *y,const char *x)
{
  long long pos;
  long long pos2;
  long long ynum;
  long long ypos;
  long long j;
  long long k;
  long long d;
  for (j = 0;j < 4 * NUMIP;++j) y[j] = 0;
  ynum = 0;
  while (ynum < 1000) {
    ++ynum;
    ypos = randommod(ynum);
    for (k = 0;k < 4;++k) {
      pos = ypos * 4 + k;
      pos2 = (ynum - 1) * 4 + k;
      if (pos >= 0 && pos < 4 * NUMIP && pos2 >= 0 && pos2 < 4 * NUMIP) y[pos2] = y[pos];
      d = 0;
      for (j = 0;j < 3 && x[j] >= '0' && x[j] <= '9';++j) d = d * 10 + (x[j] - '0');
      if (j == 0) return 0;
      x += j;
      if (pos >= 0 && pos < 4 * NUMIP) y[pos] = d;
      if (k < 3) {
        if (*x != '.') return 0;
        ++x;
      }
    }
    if (!*x) break;
    if (*x != ',') return 0;
    ++x;
  }
  /* if fewer than 8 IP addresses, cycle through them: */
  pos = 0;
  pos2 = ynum * 4;
  while (pos2 < 4 * NUMIP) {
    if (pos >= 0 && pos < 4 * NUMIP && pos2 >= 0 && pos2 < 4 * NUMIP) y[pos2] = y[pos];
    ++pos2;
    ++pos;
  }
  return 1;
}
Example #3
0
File: log.c Project: akerl/tinyssh
void log_init(int level, const char *text, int line, int flagsyslog) {

    long long i;

    loglevel = level;
    logtext  = text;
    logflagfnln  = line;

    for (i = 0; i < sizeof logstring; ++i) {
        logstring[i] = chars[randommod(sizeof chars - 1)];
    }
    logstring[sizeof logstring - 1] = 0;

    if (flagsyslog) {
        openlog(text, 0, LOG_DAEMON);
        logflagsyslog = 1;
    }

    errno = 0;
}
Example #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);
}
Example #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);
}
Example #6
0
int handle_run(uint64_t con_id, struct message_request *request,
    char *pluginkey, struct api_error *error)
{
  uint64_t callid;
  array *meta = NULL;
  string function_name;
  char *targetpluginkey;

  struct message_object args_object;

  if (!error || !request)
    return (-1);

  /* check params size */
  if (request->params.size != 3) {
    error_set(error, API_ERROR_TYPE_VALIDATION,
        "Error dispatching run API request. Invalid params size");
    return (-1);
  }

  if (request->params.obj[0].type == OBJECT_TYPE_ARRAY)
    meta = &request->params.obj[0].data.params;
  else {
    error_set(error, API_ERROR_TYPE_VALIDATION,
        "Error dispatching run API request. meta params has wrong type");
    return (-1);
  }

  if (!meta) {
    error_set(error, API_ERROR_TYPE_VALIDATION,
        "Error dispatching run API request. meta params is NULL");
    return (-1);
  }

  /* meta = [targetpluginkey, nil]*/
  if (meta->size != 2) {
    error_set(error, API_ERROR_TYPE_VALIDATION,
        "Error dispatching run API request. Invalid meta params size");
    return (-1);
  }

  /* extract meta information */
  if (meta->obj[0].type != OBJECT_TYPE_STR) {
    error_set(error, API_ERROR_TYPE_VALIDATION,
        "Error dispatching run API request. meta elements have wrong type");
    return (-1);
  }

  if (!meta->obj[0].data.string.str ||
    meta->obj[0].data.string.length+1 != PLUGINKEY_STRING_SIZE) {
    error_set(error, API_ERROR_TYPE_VALIDATION,
        "Error dispatching run API request. Invalid meta params size");
    return (-1);
  }

  targetpluginkey = meta->obj[0].data.string.str;
  to_upper(targetpluginkey);

  if (meta->obj[1].type != OBJECT_TYPE_NIL) {
    error_set(error, API_ERROR_TYPE_VALIDATION,
        "Error dispatching run API request. meta elements have wrong type");
    return (-1);
  }

  if (request->params.obj[1].type != OBJECT_TYPE_STR) {
    error_set(error, API_ERROR_TYPE_VALIDATION,
        "Error dispatching run API request. function string has wrong type");
    return (-1);
  }

  if (!request->params.obj[1].data.string.str) {
    error_set(error, API_ERROR_TYPE_VALIDATION,
        "Error dispatching register API request. Invalid meta params size");
    return (-1);
  }

  function_name = request->params.obj[1].data.string;

  if (request->params.obj[2].type != OBJECT_TYPE_ARRAY) {
    error_set(error, API_ERROR_TYPE_VALIDATION,
        "Error dispatching run API request. function string has wrong type");
    return (-1);
  }

  args_object = request->params.obj[2];
  callid = (uint64_t) randommod(281474976710656LL);
  LOG_VERBOSE(VERBOSE_LEVEL_1, "generated callid %lu\n", callid);
  hashmap_put(uint64_t, ptr_t)(callids, callid, pluginkey);

  if (api_run(targetpluginkey, function_name, callid, args_object, con_id,
      request->msgid, error) == -1) {
    if (false == error->isset)
      error_set(error, API_ERROR_TYPE_VALIDATION,
         "Error executing run API request.");
    return (-1);
  }

  return (0);
}
Example #7
0
struct plugin *helper_get_example_plugin(void)
{
  struct plugin *p = MALLOC(struct plugin);
  struct function *f = MALLOC(struct function);

  if (!p || !f)
    LOG_ERROR("[test] Failed to alloc mem for example plugin.\n");

  p->key = (string) {.str = "0123456789ABCDEF",
                     .length = sizeof("0123456789ABCDEF") - 1};
  p->name = (string) {.str = "plugin name",
                      .length = sizeof("plugin name") - 1};
  p->description = (string) {.str = "plugin desc",
                             .length = sizeof("plugin desc") - 1};
  p->license = (string) {.str = "plugin license",
                         .length = sizeof("plugin license") - 1};
  p->author = (string) {.str = "plugin author",
                        .length = sizeof("plugin author") - 1};

  p->callid = 0;

  f->name = (string) {.str = "function name",
                      .length = sizeof("function name") - 1};
  f->description = (string) {.str = "function desc",
                             .length = sizeof("function desc") - 1};
  f->args[0] = (string) {.str = "arg 1",
                         .length = sizeof("arg 1") - 1};
  f->args[1] = (string) {.str = "arg 2",
                         .length = sizeof("arg 2") - 1};

  p->function = f;
  return p;
}

void helper_free_plugin(struct plugin *p)
{
  FREE(p->function);
  FREE(p);
}


/* Builds a register call and executes handle_register in order
 * to register the plugin. */
void helper_register_plugin(struct plugin *p)
{
  connection_request_event_info info;
  struct message_request *register_request;
  array *meta, *functions, *func1, *args;
  struct api_error err = ERROR_INIT;

  info.request.msgid = 1;
  register_request = &info.request;
  assert_non_null(register_request);

  info.api_error = err;

  info.con = CALLOC(1, struct connection);
  info.con->closed = true;
  info.con->msgid = 1;
  info.con->id = (uint64_t) randommod(281474976710656LL);

  assert_non_null(info.con);

  strlcpy(info.con->cc.pluginkeystring, p->key.str, p->key.length+1);

  connect_to_db();
  assert_int_equal(0, connection_init());

  /* first level arrays:
   *
   * [meta] args->obj[0]
   * [functions] args->obj[1]
   */
  register_request->params.size = 2;
  register_request->params.obj = CALLOC(2, struct message_object);
  register_request->params.obj[0].type = OBJECT_TYPE_ARRAY;
  register_request->params.obj[1].type = OBJECT_TYPE_ARRAY;

  /* meta array:
   *
   * [name]
   * [desciption]
   * [author]
   * [license]
   */
  meta = &register_request->params.obj[0].data.params;
  meta->size = 4;
  meta->obj = CALLOC(meta->size, struct message_object);
  meta->obj[0].type = OBJECT_TYPE_STR;
  meta->obj[0].data.string = cstring_copy_string(p->name.str);
  meta->obj[1].type = OBJECT_TYPE_STR;
  meta->obj[1].data.string = cstring_copy_string(p->description.str);
  meta->obj[2].type = OBJECT_TYPE_STR;
  meta->obj[2].data.string = cstring_copy_string(p->author.str);
  meta->obj[3].type = OBJECT_TYPE_STR;
  meta->obj[3].data.string = cstring_copy_string(p->license.str);

  functions = &register_request->params.obj[1].data.params;
  functions->size = 1;
  functions->obj = CALLOC(functions->size, struct message_object);
  functions->obj[0].type = OBJECT_TYPE_ARRAY;

  func1 = &functions->obj[0].data.params;
  func1->size = 3;
  func1->obj = CALLOC(3, struct message_object);
  func1->obj[0].type = OBJECT_TYPE_STR;
  func1->obj[0].data.string = cstring_copy_string(p->function->name.str);
  func1->obj[1].type = OBJECT_TYPE_STR;
  func1->obj[1].data.string = cstring_copy_string(p->function->description.str);
  func1->obj[2].type = OBJECT_TYPE_ARRAY;

  /* function arguments */
  args = &func1->obj[2].data.params;
  args->size = 2;
  args->obj = CALLOC(2, struct message_object);
  args->obj[0].type = OBJECT_TYPE_STR;
  args->obj[0].data.string = cstring_copy_string(p->function->args[0].str);
  args->obj[1].type = OBJECT_TYPE_STR;
  args->obj[1].data.string = cstring_copy_string(p->function->args[1].str);

  /* before running function, it must be registered successfully */
  info.api_error.isset = false;
  expect_check(__wrap_crypto_write, &deserialized,
                validate_register_response,
                NULL);

  info.con->refcount++;

  connection_hashmap_put(info.con->id, info.con);
  pluginkeys_hashmap_put(info.con->cc.pluginkeystring, info.con->id);

  assert_int_equal(0, handle_register(info.con->id, &info.request,
      info.con->cc.pluginkeystring, &info.api_error));
  assert_false(info.api_error.isset);

  //hashmap_put(uint64_t, ptr_t)(connections, info.con->id, info.con);
  free_params(register_request->params);
  //FREE(args->obj);
  //FREE(func1->obj);
  //FREE(functions->obj);
  //FREE(meta->obj);
  //FREE(register_request->params.obj);
}

/* Builds a run request */
void helper_build_run_request(struct message_request *rr,
    struct plugin *plugin,
    message_object_type metaarraytype,
    size_t metasize,
    message_object_type metaclientidtype,
    message_object_type metacallidtype,
    message_object_type functionnametype,
    message_object_type argstype
)
{
  array argsarray = ARRAY_INIT;
  array *meta;

  rr->msgid = 1;

  rr->params.size = 3;
  rr->params.obj = CALLOC(rr->params.size, struct message_object);
  rr->params.obj[0].type = metaarraytype;

  meta = &rr->params.obj[0].data.params;
  meta->size = metasize;
  meta->obj = CALLOC(meta->size, struct message_object);
  meta->obj[0].type = metaclientidtype;
  meta->obj[0].data.string = cstring_copy_string(plugin->key.str);
  meta->obj[1].type = metacallidtype;

  rr->params.obj[1].type = functionnametype;
  rr->params.obj[1].data.string = cstring_copy_string(plugin->function->name.str);

  argsarray.size = 2;
  argsarray.obj = CALLOC(argsarray.size, struct message_object);
  argsarray.obj[0].type = OBJECT_TYPE_STR; /* first argument */
  argsarray.obj[0].data.string = cstring_copy_string(plugin->function->args[0].str);
  argsarray.obj[1].type = OBJECT_TYPE_STR; /* second argument */
  argsarray.obj[1].data.string = cstring_copy_string(plugin->function->args[1].str);

  rr->params.obj[2].type = argstype;
  rr->params.obj[2].data.params = argsarray;
}


void helper_build_result_request(struct message_request *rr,
    struct plugin *plugin,
    message_object_type metaarraytype,
    size_t metasize,
    message_object_type metacallidtype,
    message_object_type argstype)
{
  array argsarray = ARRAY_INIT;
  array *meta;

  rr->msgid = 1;

  rr->params.size = 2;
  rr->params.obj = CALLOC(rr->params.size, struct message_object);
  rr->params.obj[0].type = metaarraytype;
  meta = &rr->params.obj[0].data.params;
  meta->size = metasize;
  meta->obj = CALLOC(meta->size, struct message_object);
  meta->obj[0].type = metacallidtype;
  meta->obj[0].data.uinteger = plugin->callid;

  argsarray.size = 2;
  argsarray.obj = CALLOC(argsarray.size, struct message_object);
  argsarray.obj[0].type = OBJECT_TYPE_STR; /* first argument */
  argsarray.obj[0].data.string = cstring_copy_string(plugin->function->args[0].str);
  argsarray.obj[1].type = OBJECT_TYPE_STR; /* second argument */
  argsarray.obj[1].data.string = cstring_copy_string(plugin->function->args[1].str);

  rr->params.obj[1].type = argstype;
  rr->params.obj[1].data.params = argsarray;
}

void helper_request_set_callid(struct message_request *rr,
  message_object_type callidtype)
{
  array *meta = &rr->params.obj[0].data.params;

  meta->obj[0].type = callidtype;
}

void helper_request_set_meta_size(struct message_request *rr,
  message_object_type metatype, uint64_t metasize)
{
  rr->params.obj[0].type = metatype;
  rr->params.obj[0].data.params.size = metasize;
}

void helper_request_set_args_size(struct message_request *rr,
  message_object_type argstype, uint64_t argssize)
{
  rr->params.obj[1].type = argstype;
  rr->params.obj[1].data.params.size = argssize;
}

void helper_request_set_function_name(struct message_request *rr,
  message_object_type nametype, char *name)
{
  free_string(rr->params.obj[1].data.string);
  rr->params.obj[1].type = nametype;
  rr->params.obj[1].data.string = cstring_copy_string(name);
}

void helper_request_set_pluginkey_type(struct message_request *rr,
  message_object_type pluginkeytype, char *pluginkey)
{
  array *meta = &rr->params.obj[0].data.params;

  free_string(meta->obj[0].data.string);
  meta->obj[0].data.string = cstring_copy_string(pluginkey);
  meta->obj[0].type = pluginkeytype;
}
Example #8
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();
}