static void stringstringparser_test1(void) { unsigned char *buf; long long i, pos = 0; unsigned char *x; long long xlen, len; for (i = 0; testvectors[i].buf; ++i) { buf = (unsigned char *)testvectors[i].buf; len = str_len(testvectors[i].buf); pos = 0; pos = stringparser(buf, len, pos, &x, &xlen); if (!pos) fail("parsing error"); if (xlen != 3) fail("parsing error"); if (!byte_isequal(x, xlen, "aaa")) fail("parsing error"); pos = stringparser(buf, len, pos, &x, &xlen); if (!pos) fail("parsing error"); if (xlen != 2) fail("parsing error"); if (!byte_isequal(x, xlen, "bb")) fail("parsing error"); pos = stringparser(buf, len, pos, &x, &xlen); if (!pos) fail("parsing error"); if (xlen != 1) fail("parsing error"); if (!byte_isequal(x, xlen, "c")) fail("parsing error"); if (stringparser(buf, len, pos, &x, &xlen)) fail("overflow"); } }
int main(void) { unsigned char b1[32]; unsigned char b2[32]; long long i, j; const char *x = "abcdefgh"; char y[8]; /* byte_zero test */ for (i = 0; i < 32; ++i) { for (j = 0; j < sizeof b1; ++j) b1[j] = 0; for (j = 0; j < sizeof b2; ++j) b2[j] = 0; b1[i] = 0xff; b2[i] = 0xff; byte_zero(b1, sizeof b1); if (byte_isequal(b1, 32, b2) != 0) fail("byte_zero failure"); } /* byte_isequal test */ for (i = 0; i < sizeof b1; ++i) b1[i] = 0xff; for (i = 0; i < sizeof b2; ++i) b2[i] = 0xff; if (byte_isequal(b1, 32, b2) == 0) fail("byte_isequal failure"); for (i = 0; i < 32; ++i) { b1[i] = 0; if (byte_isequal(b1, 32, b2) != 0) fail("byte_isequal failure"); b1[i] = 0xff; } /* byte_copy test */ for (i = 0; i < sizeof b1; ++i) b1[i] = 0xff; for (i = 0; i < sizeof b2; ++i) b2[i] = 0x00; byte_copy(b1, 32, b2); if (byte_isequal(b1, 32, b2) == 0) fail("byte_copy failure"); for (i = 0; i < 32; ++i) { b1[i] = 0; byte_copy(b1, 32, b2); if (byte_isequal(b1, 32, b2) == 0) fail("byte_copy failure"); b1[i] = 0xff; } byte_zero(y, 8); if (!byte_isequal(y, 8, "\0\0\0\0\0\0\0\0")) fail("byte_zero/byte_isequal failure"); byte_copy(y, 8, x); if (!byte_isequal(y, 8, x)) fail("byte_copy/byte_isequal failure"); byte_copy(y, 7, y + 1); if (!byte_isequal(y, 8, "bcdefghh")) fail("byte_copy/byte_isequal failure"); byte_zero(y, 8); if (!byte_isequal(y, 8, "\0\0\0\0\0\0\0\0")) fail("byte_zero/byte_isequal failure"); return 0; }
static void run(void (*op)(void), const char *exp) { pid_t pid; int status, fromchild[2]; long long r, i; if (pipe(fromchild) == -1) fail("pipe() failure"); pid = fork(); if (pid == -1) fail("fork() failure"); if (pid == 0) { close(fromchild[0]); if (dup2(fromchild[1], 2) == -1) _exit(111); op(); _exit(0); } close(fromchild[1]); r = readall(fromchild[0], logbuf, sizeof logbuf); if (r == -1) fail("read() failure"); for (i = 0; i < r; ++i) if (logbuf[i] == '\n') break; r = i; for (i = 0; i < r; ++i) if (logbuf[i] == '/') break; r -= i; byte_copy(logbuf, r, logbuf + i); /* fprintf(stderr, "xxx: %s\n", logbuf); fflush(stderr); */ if (r < globalpathlen + 1) fail("log error"); if (!byte_isequal(globalpath, globalpathlen, logbuf)) fail("log error"); r -= globalpathlen + 1; byte_copy(logbuf, r, logbuf + globalpathlen + 1); for (i = 0; i < r; ++i) if (logbuf[i] == '{') break; r = i; logbuf[r] = 0; while (waitpid(pid, &status, 0) != pid) {}; if (!WIFEXITED(status)) fail("process killed"); if (WEXITSTATUS(status)) fail("process exited with status != 0"); i = str_len(exp); if (r != i) fail("failed"); if (!byte_isequal(logbuf, i, exp)) fail("failed"); }
/* The 'iptostr(strbuf,ip)' function converts IP address 'ip' from network byte order into the 0-terminated string. The 'ip' length is always 16 bytes. The caller must allocate at least IPTOSTR_LEN bytes for 'strbuf'. */ char *iptostr(char *strbuf, const unsigned char *ip) { static char staticbuf[IPTOSTR_LEN]; if (!strbuf) strbuf = staticbuf; /* not thread-safe */ if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { return iptostr4(strbuf, ip + 12); } return iptostr6(strbuf, ip); }
static int xsocket_connect4(int s, const unsigned char *ip, const unsigned char *port, long long id) { struct sockaddr_in sa; if (!byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { errno = EPROTO; return -1; } byte_zero(&sa, sizeof sa); sa.sin_family = PF_INET; byte_copy(&sa.sin_addr, 4, ip + 12); byte_copy(&sa.sin_port, 2, port); return connect(s, (struct sockaddr *)&sa, sizeof sa); }
static int xsocket_connect6(int s, const unsigned char *ip, const unsigned char *port, long long id) { #ifdef HASIPV6 struct sockaddr_in6 sa; if (byte_isequal("\0\0\0\0\0\0\0\0\0\0\377\377", 12, ip)) { errno = EPROTO; return -1; } byte_zero(&sa, sizeof sa); sa.sin6_family = PF_INET6; byte_copy(&sa.sin6_addr, 16, ip); byte_copy(&sa.sin6_port, 2, port); sa.sin6_scope_id = id; return connect(s, (struct sockaddr *)&sa, sizeof sa); #else errno = EPROTONOSUPPORT; return -1; #endif }
void dns_sortip(unsigned char *s, long long nn) { long long i; long long n = nn; if (nn < 0) return; n >>= 4; while (n > 1) { i = fastrandommod(n); --n; swap(s + 16 * i, 16, s + 16 * n); } for (i = 0; i + 16 <= nn; i += 16) { if (!byte_isequal(s + i, 12, "\0\0\0\0\0\0\0\0\0\0\377\377")) { swap(s + i, 16, s); break; } } }
int packet_auth(struct buf *b, struct buf *b2) { crypto_uint8 ch, flagsignature; long long pos, i, count, sign_bytes = 0; crypto_uint32 len; const char *pkname; int (*sign_open)(unsigned char *,unsigned long long *,const unsigned char *,unsigned long long,const unsigned char *) = 0; int (*parsesignpk)(unsigned char *, const unsigned char *, long long) = 0; int (*parsesignature)(unsigned char *, const unsigned char *, long long) = 0; void (*putsignpk)(struct buf *, const unsigned char *) = 0; void (*putsignpkbase64)(struct buf *, const unsigned char *) = 0; unsigned char pk[sshcrypto_sign_PUBLICKEYMAX]; unsigned char sig[sshcrypto_sign_MAX]; unsigned long long smlen; buf_purge(b); /* parse "ssh-userauth" */ pos = 0; if (!packet_getall(b, SSH_MSG_SERVICE_REQUEST)) bug(); pos = packetparser_uint8(b->buf, b->len, pos, &ch); /* SSH_MSG_SERVICE_REQUEST */ if (ch != SSH_MSG_SERVICE_REQUEST) bug_proto(); pos = packetparser_uint32(b->buf, b->len, pos, &len); /* "ssh-userauth" */ if (len != 12) bug_proto(); pos = packetparser_skip(b->buf, b->len, pos, len); if (!byte_isequal(b->buf + pos - len, len, "ssh-userauth")) bug_proto(); pos = packetparser_end(b->buf, b->len, pos); /* send service accept */ b->buf[0] = SSH_MSG_SERVICE_ACCEPT; packet_put(b); if (!packet_sendall()) bug(); for (count = 0; count < 32; ++count) { /* receive userauth request */ pkname = "unknown"; pos = 0; buf_purge(b); if (!packet_getall(b, SSH_MSG_USERAUTH_REQUEST)) bug(); pos = packetparser_uint8(b->buf, b->len, pos, &ch); /* SSH_MSG_USERAUTH_REQUEST */ if (ch != SSH_MSG_USERAUTH_REQUEST) bug_proto(); pos = packetparser_uint32(b->buf, b->len, pos, &len); /* name */ if (len >= PACKET_NAMESIZE) bug_proto(); pos = packetparser_copy(b->buf, b->len, pos, (unsigned char *)packet.name, len); packet.name[len] = 0; pos = packetparser_uint32(b->buf, b->len, pos, &len); /* "ssh-connection" */ if (len != 14) bug_proto(); pos = packetparser_skip(b->buf, b->len, pos, len); if (!byte_isequal(b->buf + pos - len, len, "ssh-connection")) bug_proto(); pos = packetparser_uint32(b->buf, b->len, pos, &len); /* publickey/password/hostbased/none */ pos = packetparser_skip(b->buf, b->len, pos, len); if (str_equaln((char *)b->buf + pos - len, len, "none")) pkname = "none"; if (str_equaln((char *)b->buf + pos - len, len, "password")) pkname = "password"; if (str_equaln((char *)b->buf + pos - len, len, "hostbased")) pkname = "hostbased"; if (str_equaln((char *)b->buf + pos - len, len, "publickey")) { pos = packetparser_uint8(b->buf, b->len, pos, &flagsignature); pos = packetparser_uint32(b->buf, b->len, pos, &len); /* public key algorithm name */ pos = packetparser_skip(b->buf, b->len, pos, len); if (b->buf[pos] != 0) bug_proto(); pkname = (char *)b->buf + pos - len; /* XXX */ sign_open = 0; parsesignpk = 0; putsignpk = 0; putsignpkbase64 = 0; parsesignature = 0; sign_bytes = 0; for (i = 0; sshcrypto_keys[i].name; ++i) { if (!sshcrypto_keys[i].sign_flagclient) continue; if (!str_equaln(pkname, len, sshcrypto_keys[i].name)) continue; pkname = sshcrypto_keys[i].name; sign_open = sshcrypto_keys[i].sign_open; parsesignature = sshcrypto_keys[i].parsesignature; parsesignpk = sshcrypto_keys[i].parsesignpk; putsignpk = sshcrypto_keys[i].buf_putsignpk; putsignpkbase64 = sshcrypto_keys[i].buf_putsignpkbase64; sign_bytes = sshcrypto_keys[i].sign_bytes; break; } if (sign_open && parsesignpk && putsignpk && putsignpkbase64 && parsesignature) { pos = packetparser_uint32(b->buf, b->len, pos, &len); /* public key blob */ pos = packetparser_skip(b->buf, b->len, pos, len); if (!parsesignpk(pk, b->buf + pos - len, len)) bug_proto(); if (!flagsignature) { /* 'publickey' ... without signature */ buf_purge(b); buf_putnum8(b, SSH_MSG_USERAUTH_PK_OK); buf_putstring(b, pkname); putsignpk(b, pk); packet_put(b); if (!packet_sendall()) bug(); continue; } /* 'publickey' ... with signature */ pos = packetparser_uint32(b->buf, b->len, pos, &len); /* signature blob */ pos = packetparser_skip(b->buf, b->len, pos, len); if (!parsesignature(sig, b->buf + pos - len, len)) bug_proto(); pos = packetparser_end(b->buf, b->len, pos); purge(b->buf + b->len - len - 4, len + 4); b->len -= len + 4; /* authenticate user - verify signature */ buf_purge(b2); buf_put(b2, sig, sign_bytes); buf_putstringlen(b2, packet.sessionid, sshcrypto_hash_bytes); buf_put(b2, b->buf, b->len); buf_purge(b); if (b->alloc <= b2->len) bug_nomem(); if (sign_open(b->buf, &smlen, b2->buf, b2->len, pk) != 0) { errno = EAUTH; bug(); } b->len = smlen; buf_purge(b); /* authorize user - using authorized_keys */ buf_purge(b); putsignpkbase64(b, pk); buf_putnum8(b, 0); if (subprocess_auth(packet.name, pkname, (char *)b->buf) == 0) goto authorized; } } /* reject */ log_i5("auth: ", packet.name, ": ", pkname, " rejected"); buf_purge(b); buf_putnum8(b, SSH_MSG_USERAUTH_FAILURE); buf_putstring(b,"publickey"); buf_putnum8(b, 0); packet_put(b); if (!packet_sendall()) bug(); } log_w1("auth: too many authentication tries"); return 0; authorized: /* authenticated + authorized */ log_i5("auth: ", packet.name, ": ", pkname, " accepted"); buf_purge(b); buf_putnum8(b, SSH_MSG_USERAUTH_SUCCESS); buf_putstring(b,"ssh-connection"); packet_put(b); if (!packet_sendall()) bug(); purge(pk, sizeof pk); purge(sig, sizeof sig); return 1; }
void dns_sortipkey(unsigned char *s, unsigned char *t, long long nn) { long long i, j, k; long long n; unsigned char *key; nn >>=4; n = nn; while (n > 1) { i = fastrandommod(n); --n; swap(s + 16 * i, 16, s + 16 * n); swap(t + 33 * i, 33, t + 33 * n); } n = nn; j = 0; k = 0; for (i = k; i < n; ++i) { key = t + 33 * i; if (key[0] == 1) { swap(s + 16 * i, 16, s + 16 * j); swap(t + 33 * i, 33, t + 33 * j); ++j; } } for (i = k; i < j; ++i) { key = t + 33 * i; if (key[0] != 1) continue; if (!byte_isequal(s + 16 * i, 12, "\0\0\0\0\0\0\0\0\0\0\377\377")) { swap(s + 16 * i, 16, s + 16 * k); swap(t + 33 * i, 33, t + 33 * k); break; } } k = j; for (i = k; i < n; ++i) { key = t + 33 * i; if (key[0] == 2) { swap(s + 16 * i, 16, s + 16 * j); swap(t + 33 * i, 33, t + 33 * j); ++j; } } for (i = k; i < j; ++i) { key = t + 33 * i; if (key[0] != 2) continue; if (!byte_isequal(s + 16 * i, 12, "\0\0\0\0\0\0\0\0\0\0\377\377")) { swap(s + 16 * i, 16, s + 16 * k); swap(t + 33 * i, 33, t + 33 * k); break; } } k = j; for (i = k; i < n; ++i) { key = t + 33 * i; if (!byte_isequal(s + 16 * i, 16, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")) { swap(s + 16 * i, 16, s + 16 * j); swap(t + 33 * i, 33, t + 33 * j); ++j; } } for (i = k; i < j; ++i) { key = t + 33 * i; if (key[0] != 0) continue; if (!byte_isequal(s + 16 * i, 12, "\0\0\0\0\0\0\0\0\0\0\377\377")) { swap(s + 16 * i, 16, s + 16 * k); swap(t + 33 * i, 33, t + 33 * k); break; } } }
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); }