Frank Denis
11 years ago
64 changed files with 0 additions and 3163 deletions
@ -1,35 +0,0 @@ |
|||
|
|||
AM_CPPFLAGS = \
|
|||
-I$(top_srcdir)/src/libsodium/include/sodium \
|
|||
-Ilibcurvecp |
|||
|
|||
LDADD = \
|
|||
libcurvecp/libcurvecp.la |
|||
|
|||
bin_PROGRAMS = \
|
|||
curvecpprintkey \
|
|||
curvecpmakekey \
|
|||
curvecpclient \
|
|||
curvecpserver \
|
|||
curvecpmessage |
|||
|
|||
curvecpprintkey_SOURCES = \
|
|||
curvecpprintkey.c |
|||
|
|||
curvecpmakekey_SOURCES = \
|
|||
curvecpmakekey.c |
|||
|
|||
curvecpclient_SOURCES = \
|
|||
curvecpclient.c |
|||
|
|||
curvecpserver_SOURCES = \
|
|||
curvecpserver.c |
|||
|
|||
curvecpmessage_SOURCES = \
|
|||
curvecpmessage.c |
|||
|
|||
EXTRA_DIST = \
|
|||
README |
|||
|
|||
SUBDIRS = \
|
|||
libcurvecp |
@ -1,15 +0,0 @@ |
|||
Example of use: |
|||
|
|||
curvecpmakekey serverkey |
|||
|
|||
curvecpprintkey serverkey > serverkey.hex |
|||
|
|||
curvecpserver this.machine.name serverkey \ |
|||
127.0.0.1 10000 31415926535897932384626433832795 \ |
|||
curvecpmessage cat /usr/share/dict/words & |
|||
|
|||
curvecpclient this.machine.name $(cat serverkey.hex) \ |
|||
127.0.0.1 10000 31415926535897932384626433832795 \ |
|||
curvecpmessage -c sh -c 'shasum5.12 <&6' |
|||
|
|||
shasum5.12 < /usr/share/dict/words |
@ -1,476 +0,0 @@ |
|||
#include <signal.h> |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <sys/wait.h> |
|||
#include <fcntl.h> |
|||
#include <poll.h> |
|||
#include <unistd.h> |
|||
#include "e.h" |
|||
#include "die.h" |
|||
#include "load.h" |
|||
#include "open.h" |
|||
#include "byte.h" |
|||
#include "socket.h" |
|||
#include "uint64_pack.h" |
|||
#include "uint64_unpack.h" |
|||
#include "nanoseconds.h" |
|||
#include "hexparse.h" |
|||
#include "nameparse.h" |
|||
#include "portparse.h" |
|||
#include "writeall.h" |
|||
#include "safenonce.h" |
|||
#include "randommod.h" |
|||
|
|||
long long recent = 0; |
|||
|
|||
#define NUMIP 8 |
|||
long long hellowait[NUMIP] = { |
|||
1000000000 |
|||
, 1500000000 |
|||
, 2250000000 |
|||
, 3375000000 |
|||
, 5062500000 |
|||
, 7593750000 |
|||
, 11390625000 |
|||
, 17085937500 |
|||
} ; |
|||
|
|||
#include "crypto_box.h" |
|||
#include "randombytes.h" |
|||
#if crypto_box_PUBLICKEYBYTES != 32 |
|||
error! |
|||
#endif |
|||
#if crypto_box_NONCEBYTES != 24 |
|||
error! |
|||
#endif |
|||
#if crypto_box_BOXZEROBYTES != 16 |
|||
error! |
|||
#endif |
|||
#if crypto_box_ZEROBYTES != 32 |
|||
error! |
|||
#endif |
|||
#if crypto_box_BEFORENMBYTES != 32 |
|||
error! |
|||
#endif |
|||
|
|||
int flagverbose = 1; |
|||
|
|||
#define USAGE "\ |
|||
curvecpclient: how to use:\n\ |
|||
curvecpclient: -q (optional): no error messages\n\ |
|||
curvecpclient: -Q (optional): print error messages (default)\n\ |
|||
curvecpclient: -v (optional): print extra information\n\ |
|||
curvecpclient: -c keydir (optional): use this public-key directory\n\ |
|||
curvecpclient: sname: server's name\n\ |
|||
curvecpclient: pk: server's public key\n\ |
|||
curvecpclient: ip: server's IP address\n\ |
|||
curvecpclient: port: server's UDP port\n\ |
|||
curvecpclient: ext: server's extension\n\ |
|||
curvecpclient: prog: run this client\n\ |
|||
" |
|||
|
|||
void die_usage(const char *s) |
|||
{ |
|||
if (s) die_4(100,USAGE,"curvecpclient: fatal: ",s,"\n"); |
|||
die_1(100,USAGE); |
|||
} |
|||
|
|||
void die_fatal(const char *trouble,const char *d,const char *fn) |
|||
{ |
|||
/* XXX: clean up? OS can do it much more reliably */ |
|||
if (!flagverbose) die_0(111); |
|||
if (d) { |
|||
if (fn) die_9(111,"curvecpclient: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n"); |
|||
die_7(111,"curvecpclient: fatal: ",trouble," ",d,": ",e_str(errno),"\n"); |
|||
} |
|||
if (errno) die_5(111,"curvecpclient: fatal: ",trouble,": ",e_str(errno),"\n"); |
|||
die_3(111,"curvecpclient: fatal: ",trouble,"\n"); |
|||
} |
|||
|
|||
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; |
|||
} |
|||
|
|||
|
|||
/* routing to the client: */ |
|||
unsigned char clientextension[16]; |
|||
long long clientextensionloadtime = 0; |
|||
int udpfd = -1; |
|||
|
|||
void clientextension_init(void) |
|||
{ |
|||
if (recent >= clientextensionloadtime) { |
|||
clientextensionloadtime = recent + 30000000000LL; |
|||
if (load("/etc/curvecpextension",clientextension,16) == -1) |
|||
if (errno == ENOENT || errno == ENAMETOOLONG) |
|||
byte_zero(clientextension,16); |
|||
} |
|||
} |
|||
|
|||
|
|||
/* client security: */ |
|||
char *keydir = 0; |
|||
unsigned char clientlongtermpk[32]; |
|||
unsigned char clientlongtermsk[32]; |
|||
unsigned char clientshorttermpk[32]; |
|||
unsigned char clientshorttermsk[32]; |
|||
crypto_uint64 clientshorttermnonce; |
|||
unsigned char vouch[64]; |
|||
|
|||
void clientshorttermnonce_update(void) |
|||
{ |
|||
++clientshorttermnonce; |
|||
if (clientshorttermnonce) return; |
|||
errno = EPROTO; |
|||
die_fatal("nonce space expired",0,0); |
|||
} |
|||
|
|||
/* routing to the server: */ |
|||
unsigned char serverip[4 * NUMIP]; |
|||
unsigned char serverport[2]; |
|||
unsigned char serverextension[16]; |
|||
|
|||
/* server security: */ |
|||
unsigned char servername[256]; |
|||
unsigned char serverlongtermpk[32]; |
|||
unsigned char servershorttermpk[32]; |
|||
unsigned char servercookie[96]; |
|||
|
|||
/* shared secrets: */ |
|||
unsigned char clientshortserverlong[32]; |
|||
unsigned char clientshortservershort[32]; |
|||
unsigned char clientlongserverlong[32]; |
|||
|
|||
unsigned char allzero[128] = {0}; |
|||
|
|||
unsigned char nonce[24]; |
|||
unsigned char text[2048]; |
|||
|
|||
unsigned char packet[4096]; |
|||
unsigned char packetip[4]; |
|||
unsigned char packetport[2]; |
|||
crypto_uint64 packetnonce; |
|||
int flagreceivedmessage = 0; |
|||
crypto_uint64 receivednonce = 0; |
|||
|
|||
struct pollfd p[3]; |
|||
|
|||
int fdwd = -1; |
|||
|
|||
int tochild[2] = {-1,-1}; |
|||
int fromchild[2] = {-1,-1}; |
|||
pid_t child = -1; |
|||
int childstatus = 0; |
|||
|
|||
unsigned char childbuf[4096]; |
|||
long long childbuflen = 0; |
|||
unsigned char childmessage[2048]; |
|||
long long childmessagelen = 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); |
|||
} |
@ -1,57 +0,0 @@ |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <unistd.h> |
|||
#include "die.h" |
|||
#include "e.h" |
|||
#include "savesync.h" |
|||
#include "randombytes.h" |
|||
#include "crypto_box.h" |
|||
|
|||
void die_usage(void) |
|||
{ |
|||
die_1(111,"curvecpmakekey: usage: curvecpmakekey keydir\n"); |
|||
} |
|||
|
|||
void die_fatal(const char *trouble,const char *d,const char *fn) |
|||
{ |
|||
if (fn) die_9(111,"curvecpmakekey: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n"); |
|||
die_7(111,"curvecpmakekey: fatal: ",trouble," ",d,": ",e_str(errno),"\n"); |
|||
} |
|||
|
|||
unsigned char pk[crypto_box_PUBLICKEYBYTES]; |
|||
unsigned char sk[crypto_box_SECRETKEYBYTES]; |
|||
unsigned char lock[1]; |
|||
unsigned char noncekey[32]; |
|||
unsigned char noncecounter[8]; |
|||
|
|||
void create(const char *d,const char *fn,const unsigned char *x,long long xlen) |
|||
{ |
|||
if (savesync(fn,x,xlen) == -1) die_fatal("unable to create",d,fn); |
|||
} |
|||
|
|||
int main(int argc,char **argv) |
|||
{ |
|||
char *d; |
|||
|
|||
if (!argv[0]) die_usage(); |
|||
if (!argv[1]) die_usage(); |
|||
d = argv[1]; |
|||
|
|||
umask(022); |
|||
if (mkdir(d,0755) == -1) die_fatal("unable to create directory",d,0); |
|||
if (chdir(d) == -1) die_fatal("unable to chdir to directory",d,0); |
|||
if (mkdir(".expertsonly",0700) == -1) die_fatal("unable to create directory",d,".expertsonly"); |
|||
|
|||
crypto_box_keypair(pk,sk); |
|||
create(d,"publickey",pk,sizeof pk); |
|||
|
|||
randombytes(noncekey,sizeof noncekey); |
|||
|
|||
umask(077); |
|||
create(d,".expertsonly/secretkey",sk,sizeof sk); |
|||
create(d,".expertsonly/lock",lock,sizeof lock); |
|||
create(d,".expertsonly/noncekey",noncekey,sizeof noncekey); |
|||
create(d,".expertsonly/noncecounter",noncecounter,sizeof noncecounter); |
|||
|
|||
return 0; |
|||
} |
@ -1,654 +0,0 @@ |
|||
#include <sys/types.h> |
|||
#include <sys/wait.h> |
|||
#include <unistd.h> |
|||
#include <signal.h> |
|||
#include <poll.h> |
|||
#include "open.h" |
|||
#include "blocking.h" |
|||
#include "e.h" |
|||
#include "die.h" |
|||
#include "randommod.h" |
|||
#include "byte.h" |
|||
#include "crypto_uint32.h" |
|||
#include "uint16_pack.h" |
|||
#include "uint32_pack.h" |
|||
#include "uint64_pack.h" |
|||
#include "uint16_unpack.h" |
|||
#include "uint32_unpack.h" |
|||
#include "uint64_unpack.h" |
|||
#include "nanoseconds.h" |
|||
#include "writeall.h" |
|||
|
|||
int flagverbose = 1; |
|||
int flagserver = 1; |
|||
int wantping = 0; /* 1: ping after a second; 2: ping immediately */ |
|||
|
|||
#define USAGE "\ |
|||
curvecpmessage: how to use:\n\ |
|||
curvecpmessage: -q (optional): no error messages\n\ |
|||
curvecpmessage: -Q (optional): print error messages (default)\n\ |
|||
curvecpmessage: -v (optional): print extra information\n\ |
|||
curvecpmessage: -c (optional): program is a client; server starts first\n\ |
|||
curvecpmessage: -C (optional): program is a client that starts first\n\ |
|||
curvecpmessage: -s (optional): program is a server (default)\n\ |
|||
curvecpmessage: prog: run this program\n\ |
|||
" |
|||
|
|||
void die_usage(const char *s) |
|||
{ |
|||
if (s) die_4(100,USAGE,"curvecpmessage: fatal: ",s,"\n"); |
|||
die_1(100,USAGE); |
|||
} |
|||
|
|||
void die_fatal(const char *trouble,const char *d,const char *fn) |
|||
{ |
|||
if (!flagverbose) die_0(111); |
|||
if (d) { |
|||
if (fn) die_9(111,"curvecpmessage: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n"); |
|||
die_7(111,"curvecpmessage: fatal: ",trouble," ",d,": ",e_str(errno),"\n"); |
|||
} |
|||
if (errno) die_5(111,"curvecpmessage: fatal: ",trouble,": ",e_str(errno),"\n"); |
|||
die_3(111,"curvecpmessage: fatal: ",trouble,"\n"); |
|||
} |
|||
|
|||
void die_badmessage(void) |
|||
{ |
|||
errno = EPROTO; |
|||
die_fatal("unable to read from file descriptor 8",0,0); |
|||
} |
|||
|
|||
void die_internalerror(void) |
|||
{ |
|||
errno = EPROTO; |
|||
die_fatal("internal error",0,0); |
|||
} |
|||
|
|||
|
|||
int tochild[2] = {-1,-1}; |
|||
int fromchild[2] = {-1,-1}; |
|||
pid_t child = -1; |
|||
int childstatus; |
|||
|
|||
struct pollfd p[3]; |
|||
|
|||
long long sendacked = 0; /* number of initial bytes sent and fully acknowledged */ |
|||
long long sendbytes = 0; /* number of additional bytes to send */ |
|||
unsigned char sendbuf[131072]; /* circular queue with the additional bytes; size must be power of 2 */ |
|||
long long sendprocessed = 0; /* within sendbytes, number of bytes absorbed into blocks */ |
|||
|
|||
crypto_uint16 sendeof = 0; /* 2048 for normal eof after sendbytes, 4096 for error after sendbytes */ |
|||
int sendeofprocessed = 0; |
|||
int sendeofacked = 0; |
|||
|
|||
long long totalblocktransmissions = 0; |
|||
long long totalblocks = 0; |
|||
|
|||
#define OUTGOING 128 /* must be power of 2 */ |
|||
long long blocknum = 0; /* number of outgoing blocks being tracked */ |
|||
long long blockfirst = 0; /* circular queue */ |
|||
long long blockpos[OUTGOING]; /* position of block's first byte within stream */ |
|||
long long blocklen[OUTGOING]; /* number of bytes in this block */ |
|||
crypto_uint16 blockeof[OUTGOING]; /* 0, 2048, 4096 */ |
|||
long long blocktransmissions[OUTGOING]; |
|||
long long blocktime[OUTGOING]; /* time of last message sending this block; 0 means acked */ |
|||
long long earliestblocktime = 0; /* if nonzero, minimum of active blocktime values */ |
|||
crypto_uint32 blockid[OUTGOING]; /* ID of last message sending this block */ |
|||
|
|||
#define INCOMING 64 /* must be power of 2 */ |
|||
long long messagenum = 0; /* number of messages in incoming queue */ |
|||
long long messagefirst = 0; /* position of first message; circular queue */ |
|||
unsigned char messagelen[INCOMING]; /* times 16 */ |
|||
unsigned char message[INCOMING][1088]; |
|||
unsigned char messagetodo[2048]; |
|||
long long messagetodolen = 0; |
|||
|
|||
long long receivebytes = 0; /* number of initial bytes fully received */ |
|||
long long receivewritten = 0; /* within receivebytes, number of bytes given to child */ |
|||
crypto_uint16 receiveeof = 0; /* 0, 2048, 4096 */ |
|||
long long receivetotalbytes = 0; /* total number of bytes in stream, if receiveeof */ |
|||
unsigned char receivebuf[131072]; /* circular queue beyond receivewritten; size must be power of 2 */ |
|||
unsigned char receivevalid[131072]; /* 1 for byte successfully received; XXX: use buddy structure to speed this up */ |
|||
|
|||
long long maxblocklen = 512; |
|||
crypto_uint32 nextmessageid = 1; |
|||
|
|||
unsigned char buf[4096]; |
|||
|
|||
long long lastblocktime = 0; |
|||
long long nsecperblock = 1000000000; |
|||
long long lastspeedadjustment = 0; |
|||
long long lastedge = 0; |
|||
long long lastdoubling = 0; |
|||
|
|||
long long rtt; |
|||
long long rtt_delta; |
|||
long long rtt_average = 0; |
|||
long long rtt_deviation = 0; |
|||
long long rtt_lowwater = 0; |
|||
long long rtt_highwater = 0; |
|||
long long rtt_timeout = 1000000000; |
|||
long long rtt_seenrecenthigh = 0; |
|||
long long rtt_seenrecentlow = 0; |
|||
long long rtt_seenolderhigh = 0; |
|||
long long rtt_seenolderlow = 0; |
|||
long long rtt_phase = 0; |
|||
|
|||
long long lastpanic = 0; |
|||
|
|||
void earliestblocktime_compute(void) /* XXX: use priority queue */ |
|||
{ |
|||
long long i; |
|||
long long pos; |
|||
earliestblocktime = 0; |
|||
for (i = 0;i < blocknum;++i) { |
|||
pos = (blockfirst + i) & (OUTGOING - 1); |
|||
if (blocktime[pos]) { |
|||
if (!earliestblocktime) |
|||
earliestblocktime = blocktime[pos]; |
|||
else |
|||
if (blocktime[pos] < earliestblocktime) |
|||
earliestblocktime = blocktime[pos]; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void acknowledged(unsigned long long start,unsigned long long stop) |
|||
{ |
|||
long long i; |
|||
long long pos; |
|||
if (stop == start) return; |
|||
for (i = 0;i < blocknum;++i) { |
|||
pos = (blockfirst + i) & (OUTGOING - 1); |
|||
if (blockpos[pos] >= start && blockpos[pos] + blocklen[pos] <= stop) { |
|||
blocktime[pos] = 0; |
|||
totalblocktransmissions += blocktransmissions[pos]; |
|||
totalblocks += 1; |
|||
} |
|||
} |
|||
while (blocknum) { |
|||
pos = blockfirst & (OUTGOING - 1); |
|||
if (blocktime[pos]) break; |
|||
sendacked += blocklen[pos]; |
|||
sendbytes -= blocklen[pos]; |
|||
sendprocessed -= blocklen[pos]; |
|||
++blockfirst; |
|||
--blocknum; |
|||
} |
|||
if (sendeof) |
|||
if (start == 0) |
|||
if (stop > sendacked + sendbytes) |
|||
if (!sendeofacked) { |
|||
sendeofacked = 1; |
|||
} |
|||
earliestblocktime_compute(); |
|||
} |
|||
|
|||
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) |
|||
if (nextaction > lastblocktime + nsecperblock) nextaction = lastblocktime + nsecperblock; |
|||
if (blocknum < OUTGOING) |
|||
if (!(sendeof ? sendeofprocessed : sendprocessed >= sendbytes)) |
|||
if (nextaction > lastblocktime + nsecperblock) nextaction = lastblocktime + nsecperblock; |
|||
if (earliestblocktime) |
|||
if (earliestblocktime + rtt_timeout > lastblocktime + nsecperblock) |
|||
if (earliestblocktime + rtt_timeout < nextaction) |
|||
nextaction = earliestblocktime + rtt_timeout; |
|||
|
|||
if (messagenum) |
|||
if (!watchtochild) |
|||
nextaction = 0; |
|||
|
|||
if (nextaction <= recent) |
|||
timeout = 0; |
|||
else |
|||
timeout = (nextaction - recent) / 1000000 + 1; |
|||
|
|||
if (poll(p,q - p,timeout) < 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: 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); |
|||
|
|||
} |
|||
|
|||
|
|||
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); |
|||
} |
@ -1,46 +0,0 @@ |
|||
#include <unistd.h> |
|||
#include "die.h" |
|||
#include "e.h" |
|||
#include "load.h" |
|||
#include "writeall.h" |
|||
#include "crypto_box.h" |
|||
|
|||
unsigned char pk[crypto_box_PUBLICKEYBYTES]; |
|||
unsigned char out[crypto_box_PUBLICKEYBYTES * 2 + 1]; |
|||
|
|||
void die_usage(void) |
|||
{ |
|||
die_1(111,"curvecpprintkey: usage: curvecpprintkey keydir\n"); |
|||
} |
|||
|
|||
void die_fatal(const char *trouble,const char *d,const char *fn) |
|||
{ |
|||
if (d) { |
|||
if (fn) die_9(111,"curvecpmakekey: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n"); |
|||
die_7(111,"curvecpmakekey: fatal: ",trouble," ",d,": ",e_str(errno),"\n"); |
|||
} |
|||
die_5(111,"curvecpmakekey: fatal: ",trouble,": ",e_str(errno),"\n"); |
|||
} |
|||
|
|||
int main(int argc,char **argv) |
|||
{ |
|||
char *d; |
|||
long long j; |
|||
|
|||
if (!argv[0]) die_usage(); |
|||
if (!argv[1]) die_usage(); |
|||
d = argv[1]; |
|||
|
|||
if (chdir(d) == -1) die_fatal("unable to chdir to directory",d,0); |
|||
if (load("publickey",pk,sizeof pk) == -1) die_fatal("unable to read",d,"publickey"); |
|||
|
|||
for (j = 0;j < crypto_box_PUBLICKEYBYTES;++j) { |
|||
out[2 * j + 0] = "0123456789abcdef"[15 & (int) (pk[j] >> 4)]; |
|||
out[2 * j + 1] = "0123456789abcdef"[15 & (int) (pk[j] >> 0)]; |
|||
} |
|||
out[2 * j] = '\n'; |
|||
|
|||
if (writeall(1,out,sizeof out) == -1) die_fatal("unable to write output",0,0); |
|||
|
|||
return 0; |
|||
} |
@ -1,497 +0,0 @@ |
|||
#include <signal.h> |
|||
#include <stdlib.h> |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <fcntl.h> |
|||
#include <unistd.h> |
|||
#include <poll.h> |
|||
#include "e.h" |
|||
#include "die.h" |
|||
#include "byte.h" |
|||
#include "open.h" |
|||
#include "load.h" |
|||
#include "socket.h" |
|||
#include "uint64_pack.h" |
|||
#include "uint64_unpack.h" |
|||
#include "writeall.h" |
|||
#include "nanoseconds.h" |
|||
#include "safenonce.h" |
|||
#include "nameparse.h" |
|||
#include "hexparse.h" |
|||
#include "portparse.h" |
|||
#include "randommod.h" |
|||
|
|||
#include "randombytes.h" |
|||
#include "crypto_box.h" |
|||
#include "crypto_secretbox.h" |
|||
#if crypto_box_PUBLICKEYBYTES != 32 |
|||
error! |
|||
#endif |
|||
#if crypto_box_NONCEBYTES != 24 |
|||
error! |
|||
#endif |
|||
#if crypto_box_BOXZEROBYTES != 16 |
|||
error! |
|||
#endif |
|||
#if crypto_box_ZEROBYTES != 32 |
|||
error! |
|||
#endif |
|||
#if crypto_box_BEFORENMBYTES != 32 |
|||
error! |
|||
#endif |
|||
#if crypto_secretbox_KEYBYTES != 32 |
|||
error! |
|||
#endif |
|||
#if crypto_secretbox_NONCEBYTES != 24 |
|||
error! |
|||
#endif |
|||
#if crypto_secretbox_BOXZEROBYTES != 16 |
|||
error! |
|||
#endif |
|||
#if crypto_secretbox_ZEROBYTES != 32 |
|||
error! |
|||
#endif |
|||
|
|||
int flagverbose; |
|||
|
|||
#define USAGE "\ |
|||
curvecpserver: how to use:\n\ |
|||
curvecpserver: -q (optional): no error messages\n\ |
|||
curvecpserver: -Q (optional): print error messages (default)\n\ |
|||
curvecpserver: -v (optional): print extra information\n\ |
|||
curvecpserver: -c n (optional): allow at most n clients at once (default 100)\n\ |
|||
curvecpserver: sname: server's name\n\ |
|||
curvecpserver: keydir: use this public-key directory\n\ |
|||
curvecpserver: ip: server's IP address\n\ |
|||
curvecpserver: port: server's UDP port\n\ |
|||
curvecpserver: ext: server's extension\n\ |
|||
curvecpserver: prog: run this server\n\ |
|||
" |
|||
|
|||
void die_usage(const char *s) |
|||
{ |
|||
if (s) die_4(100,USAGE,"curvecpserver: fatal: ",s,"\n"); |
|||
die_1(100,USAGE); |
|||
} |
|||
|
|||
void die_fatal(const char *trouble,const char *d,const char *fn) |
|||
{ |
|||
if (!flagverbose) die_0(111); |
|||
if (d) { |
|||
if (fn) die_9(111,"curvecpserver: fatal: ",trouble," ",d,"/",fn,": ",e_str(errno),"\n"); |
|||
die_7(111,"curvecpserver: fatal: ",trouble," ",d,": ",e_str(errno),"\n"); |
|||
} |
|||
die_5(111,"curvecpserver: fatal: ",trouble,": ",e_str(errno),"\n"); |
|||
} |
|||
|
|||
int ipparse(unsigned char *y,const char *x) |
|||
{ |
|||
long long j; |
|||
long long k; |
|||
long long d; |
|||
|
|||
for (k = 0;k < 4;++k) y[k] = 0; |
|||
for (k = 0;k < 4;++k) { |
|||
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 (k >= 0 && k < 4) y[k] = d; |
|||
if (k < 3) { |
|||
if (*x != '.') return 0; |
|||
++x; |
|||
} |
|||
} |
|||
if (*x) return 0; |
|||
return 1; |
|||
} |
|||
|
|||
int maxparse(long long *y,const char *x) |
|||
{ |
|||
long long d; |
|||
long long j; |
|||
|
|||
d = 0; |
|||
for (j = 0;j < 9 && x[j] >= '0' && x[j] <= '9';++j) d = d * 10 + (x[j] - '0'); |
|||
if (x[j]) return 0; |
|||
if (d < 1) return 0; |
|||
if (d > 65535) return 0; |
|||
*y = d; |
|||
return 1; |
|||
} |
|||
|
|||
/* cookies: */ |
|||
long long nextminute; |
|||
unsigned char minutekey[32]; |
|||
unsigned char lastminutekey[32]; |
|||
|
|||
/* routing to the server: */ |
|||
unsigned char serverip[4]; |
|||
unsigned char serverport[2]; |
|||
unsigned char serverextension[16]; |
|||
int udpfd = -1; |
|||
|
|||
/* server security: */ |
|||
char *keydir = 0; |
|||
unsigned char servername[256]; |
|||
unsigned char serverlongtermsk[32]; |
|||
unsigned char servershorttermpk[32]; |
|||
unsigned char servershorttermsk[32]; |
|||
|
|||
/* routing to the client: */ |
|||
unsigned char clientextension[16]; |
|||
|
|||
/* client security: */ |
|||
unsigned char clientlongtermpk[32]; |
|||
unsigned char clientshorttermpk[32]; |
|||
|
|||
/* shared secrets: */ |
|||
unsigned char clientshortserverlong[32]; |
|||
unsigned char clientshortservershort[32]; |
|||
unsigned char clientlongserverlong[32]; |
|||
|
|||
unsigned char allzero[128] = {0}; |
|||
|
|||
unsigned char nonce[24]; |
|||
unsigned char text[2048]; |
|||
|
|||
unsigned char packetip[4]; |
|||
unsigned char packetport[2]; |
|||
unsigned char packet[4096]; |
|||
crypto_uint64 packetnonce; |
|||
|
|||
#define MESSAGELEN 1104 |
|||
|
|||
struct activeclient { |
|||
unsigned char clientshorttermpk[32]; |
|||
unsigned char clientshortservershort[32]; |
|||
crypto_uint64 receivednonce; |
|||
crypto_uint64 sentnonce; |
|||
long long messagelen; |
|||
pid_t child; |
|||
int tochild; |
|||
int fromchild; |
|||
unsigned char clientextension[16]; |
|||
unsigned char clientip[4]; |
|||
unsigned char clientport[2]; |
|||
unsigned char message[MESSAGELEN]; |
|||
} ; |
|||
|
|||
const char *strmaxactiveclients = "100"; |
|||
long long maxactiveclients = 0; |
|||
long long numactiveclients = 0; |
|||
struct activeclient *activeclients = 0; |
|||
struct pollfd *p; |
|||
|
|||
int fdwd = -1; |
|||
|
|||
int pi0[2]; |
|||
int pi1[2]; |
|||
|
|||
unsigned char childbuf[4096]; |
|||
long long childbuflen = 0; |
|||
unsigned char childmessage[2048]; |
|||
long long childmessagelen = 0; |
|||
|
|||
int main(int argc,char **argv) |
|||
{ |
|||
long long r; |
|||
long long i; |
|||
long long k; |
|||
|
|||
signal(SIGPIPE,SIG_IGN); |
|||
signal(SIGCHLD,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]) { strmaxactiveclients = x + 1; break; } |
|||
if (argv[1]) { strmaxactiveclients = *++argv; break; } |
|||
} |
|||
die_usage(0); |
|||
} |
|||
} |
|||
if (!maxparse(&maxactiveclients,strmaxactiveclients)) die_usage("concurrency must be between 1 and 65535"); |
|||
if (!nameparse(servername,*++argv)) die_usage("sname must be at most 255 bytes, at most 63 bytes between dots"); |
|||
keydir = *++argv; if (!keydir) die_usage("missing keydir"); |
|||
if (!ipparse(serverip,*++argv)) die_usage("ip must be an IPv4 address"); |
|||
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; } |
|||
} |
|||
|
|||
activeclients = malloc(maxactiveclients * sizeof(struct activeclient)); |
|||
if (!activeclients) die_fatal("unable to create activeclients array",0,0); |
|||
randombytes((void *) activeclients,maxactiveclients * sizeof(struct activeclient)); |
|||
for (i = 0;i < maxactiveclients;++i) { |
|||
activeclients[i].child = -1; |
|||
activeclients[i].tochild = -1; |
|||
activeclients[i].fromchild = -1; |
|||
activeclients[i].receivednonce = 0; |
|||
activeclients[i].sentnonce = randommod(281474976710656LL); |
|||
} |
|||
|
|||
p = malloc((1 + maxactiveclients) * sizeof(struct pollfd)); |
|||
if (!p) die_fatal("unable to create poll array",0,0); |
|||
|
|||
fdwd = open_cwd(); |
|||
if (fdwd == -1) die_fatal("unable to open current directory",0,0); |
|||
|
|||
if (chdir(keydir) == -1) die_fatal("unable to chdir to",keydir,0); |
|||
if (load(".expertsonly/secretkey",serverlongtermsk,sizeof serverlongtermsk) == -1) die_fatal("unable to read secret key from",keydir,0); |
|||
|
|||
udpfd = socket_udp(); |
|||
if (udpfd == -1) die_fatal("unable to create socket",0,0); |
|||
if (socket_bind(udpfd,serverip,serverport) == -1) die_fatal("unable to bind socket",0,0); |
|||
|
|||
randombytes(minutekey,sizeof minutekey); |
|||
randombytes(lastminutekey,sizeof lastminutekey); |
|||
nextminute = nanoseconds() + 60000000000ULL; |
|||
|
|||
for (;;) { |
|||
long long timeout = nextminute - nanoseconds(); |
|||
if (timeout <= 0) { |
|||
timeout = 60000000000ULL; |
|||
byte_copy(lastminutekey,sizeof lastminutekey,minutekey); |
|||
randombytes(minutekey,sizeof minutekey); |
|||
nextminute = nanoseconds() + timeout; |
|||
randombytes(packet,sizeof packet); |
|||
randombytes(packetip,sizeof packetip); |
|||
randombytes(packetport,sizeof packetport); |
|||
randombytes(clientshorttermpk,sizeof clientshorttermpk); |
|||
randombytes(clientshortserverlong,sizeof clientshortserverlong); |
|||
randombytes(nonce,sizeof nonce); |
|||
randombytes(text,sizeof text); |
|||
randombytes(childbuf,sizeof childbuf); |
|||
randombytes(childmessage,sizeof childmessage); |
|||
randombytes(servershorttermpk,sizeof servershorttermpk); |
|||
randombytes(servershorttermsk,sizeof servershorttermsk); |
|||
} |
|||
|
|||
for (i = 0;i < numactiveclients;++i) { |
|||
p[i].fd = activeclients[i].fromchild; |
|||
p[i].events = POLLIN; |
|||
} |
|||
p[numactiveclients].fd = udpfd; |
|||
p[numactiveclients].events = POLLIN; |
|||
if (poll(p,1 + numactiveclients,timeout / 1000000 + 1) < 0) continue; |
|||
|
|||
do { /* try receiving a packet: */ |
|||
if (!p[numactiveclients].revents) break; |
|||
r = socket_recv(udpfd,packet,sizeof packet,packetip,packetport); |
|||
if (r < 80) break; |
|||
if (r > 1184) break; |
|||
if (r & 15) break; |
|||
if (!(byte_isequal(packet,7,"QvnQ5Xl") & byte_isequal(packet + 8,16,serverextension))) break; |
|||
byte_copy(clientextension,16,packet + 24); |
|||
if (packet[7] == 'H') { /* Hello packet: */ |
|||
if (r != 224) break; |
|||
byte_copy(clientshorttermpk,32,packet + 40); |
|||
crypto_box_beforenm(clientshortserverlong,clientshorttermpk,serverlongtermsk); |
|||
byte_copy(nonce,16,"CurveCP-client-H"); |
|||
byte_copy(nonce + 16,8,packet + 136); |
|||
byte_zero(text,16); |
|||
byte_copy(text + 16,80,packet + 144); |
|||
if (crypto_box_open_afternm(text,text,96,nonce,clientshortserverlong)) break; |
|||
|
|||
/* send Cookie packet: */ |
|||
|
|||
crypto_box_keypair(servershorttermpk,servershorttermsk); |
|||
byte_zero(text + 64,32); |
|||
byte_copy(text + 96,32,clientshorttermpk); |
|||
byte_copy(text + 128,32,servershorttermsk); |
|||
byte_copy(nonce,8,"minute-k"); |
|||
if (safenonce(nonce + 8,1) == -1) die_fatal("nonce-generation disaster",0,0); |
|||
crypto_secretbox(text + 64,text + 64,96,nonce,minutekey); |
|||
byte_copy(text + 64,16,nonce + 8); |
|||
|
|||
byte_zero(text,32); |
|||
byte_copy(text + 32,32,servershorttermpk); |
|||
byte_copy(nonce,8,"CurveCPK"); /* reusing the other 16 bytes */ |
|||
crypto_box_afternm(text,text,160,nonce,clientshortserverlong); |
|||
|
|||
byte_copy(packet,8,"RL3aNMXK"); |
|||
byte_copy(packet + 8,16,clientextension); |
|||
byte_copy(packet + 24,16,serverextension); |
|||
byte_copy(packet + 40,16,nonce + 8); |
|||
byte_copy(packet + 56,144,text + 16); |
|||
|
|||
socket_send(udpfd,packet,200,packetip,packetport); |
|||
} |
|||
if (packet[7] == 'I') { /* Initiate packet: */ |
|||
if (r < 560) break; |
|||
for (i = 0;i < numactiveclients;++i) /* XXX use better data structure */ |
|||
if (byte_isequal(activeclients[i].clientshorttermpk,32,packet + 40)) |
|||
break; |
|||
if (i < numactiveclients) { |
|||
packetnonce = uint64_unpack(packet + 168); |
|||
if (packetnonce <= activeclients[i].receivednonce) break; |
|||
byte_copy(nonce,16,"CurveCP-client-I"); |
|||
byte_copy(nonce + 16,8,packet + 168); |
|||
byte_zero(text,16); |
|||
byte_copy(text + 16,r - 176,packet + 176); |
|||
if (crypto_box_open_afternm(text,text,r - 160,nonce,activeclients[i].clientshortservershort)) break; |
|||
|
|||
/* XXX: update clientip, clientextension; but not if client has spoken recently */ |
|||
activeclients[i].receivednonce = packetnonce; |
|||
text[383] = (r - 544) >> 4; |
|||
if (writeall(activeclients[i].tochild,text + 383,r - 543) == -1) |
|||
; /* child is gone; will see eof later */ |
|||
break; |
|||
} |
|||
if (i == maxactiveclients) break; |
|||
|
|||
byte_copy(nonce,8,"minute-k"); |
|||
byte_copy(nonce + 8,16,packet + 72); |
|||
byte_zero(text,16); |
|||
byte_copy(text + 16,80,packet + 88); |
|||
if (crypto_secretbox_open(text,text,96,nonce,minutekey)) { |
|||
byte_zero(text,16); |
|||
byte_copy(text + 16,80,packet + 88); |
|||
if (crypto_secretbox_open(text,text,96,nonce,lastminutekey)) break; |
|||
} |
|||
if (!byte_isequal(packet + 40,32,text + 32)) break; |
|||
byte_copy(servershorttermsk,32,text + 64); |
|||
byte_copy(clientshorttermpk,32,packet + 40); |
|||
crypto_box_beforenm(clientshortservershort,clientshorttermpk,servershorttermsk); |
|||
|
|||
byte_copy(nonce,16,"CurveCP-client-I"); |
|||
byte_copy(nonce + 16,8,packet + 168); |
|||
byte_zero(text,16); |
|||
byte_copy(text + 16,r - 176,packet + 176); |
|||
if (crypto_box_open_afternm(text,text,r - 160,nonce,clientshortservershort)) break; |
|||
|
|||
if (!byte_isequal(text + 128,256,servername)) break; |
|||
|
|||
/* XXX skip if client authentication is not desired: */ |
|||
byte_copy(clientlongtermpk,32,text + 32); |
|||
/* XXX impose policy limitations on clients: known, maxconn */ |
|||
/* XXX for known clients, retrieve shared secret from cache: */ |
|||
crypto_box_beforenm(clientlongserverlong,clientlongtermpk,serverlongtermsk); |
|||
byte_copy(nonce,8,"CurveCPV"); |
|||
byte_copy(nonce + 8,16,text + 64); |
|||
byte_zero(text + 64,16); |
|||
if (crypto_box_open_afternm(text + 64,text + 64,64,nonce,clientlongserverlong)) break; |
|||
if (!byte_isequal(text + 96,32,clientshorttermpk)) break; |
|||
|
|||
if (open_pipe(pi0) == -1) break; /* XXX: error message */ |
|||
if (open_pipe(pi1) == -1) { close(pi0[0]); close(pi0[1]); break; } /* XXX: error message */ |
|||
|
|||
activeclients[i].child = fork(); |
|||
if (activeclients[i].child == -1) { |
|||
close(pi0[0]); close(pi0[1]); |
|||
close(pi1[0]); close(pi1[1]); |
|||
break; /* XXX: error message */ |
|||
} |
|||
if (activeclients[i].child == 0) { |
|||
if (fchdir(fdwd) == -1) die_fatal("unable to chdir to original directory",0,0); |
|||
close(8); |
|||
if (dup(pi0[0]) != 8) die_fatal("unable to dup",0,0); |
|||
close(9); |
|||
if (dup(pi1[1]) != 9) die_fatal("unable to dup",0,0); |
|||
/* XXX: set up environment variables */ |
|||
signal(SIGPIPE,SIG_DFL); |
|||
signal(SIGCHLD,SIG_DFL); |
|||
execvp(*argv,argv); |
|||
die_fatal("unable to run",*argv,0); |
|||
} |
|||
|
|||
activeclients[i].tochild = pi0[1]; close(pi0[0]); |
|||
activeclients[i].fromchild = pi1[0]; close(pi1[1]); |
|||
activeclients[i].messagelen = 0; |
|||
byte_copy(activeclients[i].clientshorttermpk,32,clientshorttermpk); |
|||
byte_copy(activeclients[i].clientshortservershort,32,clientshortservershort); |
|||
activeclients[i].receivednonce = uint64_unpack(packet + 168); |
|||
byte_copy(activeclients[i].clientextension,16,clientextension); |
|||
byte_copy(activeclients[i].clientip,4,packetip); |
|||
byte_copy(activeclients[i].clientport,2,packetport); |
|||
++numactiveclients; |
|||
|
|||
text[383] = (r - 544) >> 4; |
|||
if (writeall(activeclients[i].tochild,text + 383,r - 543) == -1) |
|||
; /* child is gone; will see eof later */ |
|||
} |
|||
if (packet[7] == 'M') { /* Message packet: */ |
|||
if (r < 112) break; |
|||
for (i = 0;i < numactiveclients;++i) /* XXX use better data structure */ |
|||
if (byte_isequal(activeclients[i].clientshorttermpk,32,packet + 40)) |
|||
break; |
|||
if (i < numactiveclients) { |
|||
packetnonce = uint64_unpack(packet + 72); |
|||
if (packetnonce <= activeclients[i].receivednonce) break; |
|||
byte_copy(nonce,16,"CurveCP-client-M"); |
|||
byte_copy(nonce + 16,8,packet + 72); |
|||
byte_zero(text,16); |
|||
byte_copy(text + 16,r - 80,packet + 80); |
|||
if (crypto_box_open_afternm(text,text,r - 64,nonce,activeclients[i].clientshortservershort)) break; |
|||
|
|||
/* XXX: update clientip, clientextension */ |
|||
activeclients[i].receivednonce = packetnonce; |
|||
text[31] = (r - 96) >> 4; |
|||
if (writeall(activeclients[i].tochild,text + 31,r - 95) == -1) |
|||
; /* child is gone; will see eof later */ |
|||
break; |
|||
} |
|||
} |
|||
} while (0); |
|||
|
|||
for (i = numactiveclients - 1;i >= 0;--i) { |
|||
do { |
|||
if (!p[i].revents) break; |
|||
r = read(activeclients[i].fromchild,childbuf,sizeof childbuf); |
|||
if (r == -1) if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) break; |
|||
if (r <= 0) goto endconnection; |
|||
childbuflen = r; |
|||
for (k = 0;k < childbuflen;++k) { |
|||
r = activeclients[i].messagelen; |
|||
if (r < 0) goto endconnection; |
|||
if (r >= MESSAGELEN) goto endconnection; |
|||
activeclients[i].message[r] = childbuf[k]; |
|||
if (r == 0) if (childbuf[k] & 128) goto endconnection; |
|||
activeclients[i].messagelen = r + 1; |
|||
if (r == 16 * (unsigned long long) activeclients[i].message[0]) { |
|||
if (r < 16) goto endconnection; |
|||
if (r > 1088) goto endconnection; |
|||
byte_copy(nonce,16,"CurveCP-server-M"); |
|||
uint64_pack(nonce + 16,++activeclients[i].sentnonce); |
|||
byte_zero(text,32); |
|||
byte_copy(text + 32,r,activeclients[i].message + 1); |
|||
crypto_box_afternm(text,text,r + 32,nonce,activeclients[i].clientshortservershort); |
|||
byte_copy(packet,8,"RL3aNMXM"); |
|||
byte_copy(packet + 8,16,clientextension); |
|||
byte_copy(packet + 24,16,serverextension); |
|||
byte_copy(packet + 40,8,nonce + 16); |
|||
byte_copy(packet + 48,r + 16,text + 16); |
|||
socket_send(udpfd,packet,r + 64,activeclients[i].clientip,activeclients[i].clientport); |
|||
activeclients[i].messagelen = 0; |
|||
} |
|||
} |
|||
break; |
|||
|
|||
endconnection: |
|||
|
|||
/* XXX: cache cookie if it's recent */ |
|||
close(activeclients[i].fromchild); activeclients[i].fromchild = -1; |
|||
close(activeclients[i].tochild); activeclients[i].tochild = -1; |
|||
--numactiveclients; |
|||
activeclients[i] = activeclients[numactiveclients]; |
|||
randombytes((void *) &activeclients[numactiveclients],sizeof(struct activeclient)); |
|||
} while (0); |
|||
} |
|||
} |
|||
} |
@ -1,69 +0,0 @@ |
|||
|
|||
noinst_LTLIBRARIES = \
|
|||
libcurvecp.la |
|||
|
|||
libcurvecp_la_SOURCES = \
|
|||
blocking.c \
|
|||
blocking.h \
|
|||
byte.h \
|
|||
byte_copy.c \
|
|||
byte_isequal.c \
|
|||
byte_zero.c \
|
|||
crypto_block.c \
|
|||
crypto_block.h \
|
|||
die.c \
|
|||
die.h \
|
|||
e.c \
|
|||
e.h \
|
|||
hexparse.c \
|
|||
hexparse.h \
|
|||
load.c \
|
|||
load.h \
|
|||
nameparse.c \
|
|||
nameparse.h \
|
|||
nanoseconds.c \
|
|||
nanoseconds.h \
|
|||
open.h \
|
|||
open_cwd.c \
|
|||
open_lock.c \
|
|||
open_pipe.c \
|
|||
open_read.c \
|
|||
open_write.c \
|
|||
portparse.c \
|
|||
portparse.h \
|
|||
randommod.c \
|
|||
randommod.h \
|
|||
safenonce.c \
|
|||
safenonce.h \
|
|||
savesync.c \
|
|||
savesync.h \
|
|||
socket.h \
|
|||
socket_bind.c \
|
|||
socket_recv.c \
|
|||
socket_send.c \
|
|||
socket_udp.c \
|
|||
uint16_pack.c \
|
|||
uint16_pack.h \
|
|||
uint16_unpack.c \
|
|||
uint16_unpack.h \
|
|||
uint32_pack.c \
|
|||
uint32_pack.h \
|
|||
uint32_unpack.c \
|
|||
uint32_unpack.h \
|
|||
uint64_pack.c \
|
|||
uint64_pack.h \
|
|||
uint64_unpack.c \
|
|||
uint64_unpack.h \
|
|||
writeall.c \
|
|||
writeall.h |
|||
|
|||
libcurvecp_la_LIBADD = \
|
|||
$(top_srcdir)/src/libsodium/libsodium.la |
|||
|
|||
libcurvecp_la_LDFLAGS = \
|
|||
$(AM_LDFLAGS) \
|
|||
-no-undefined |
|||
|
|||
libcurvecp_la_CPPFLAGS = \
|
|||
$(LTDLINCL) \
|
|||
-I$(top_srcdir)/src/libsodium/include/sodium |
@ -1,12 +0,0 @@ |
|||
#include <fcntl.h> |
|||
#include "blocking.h" |
|||
|
|||
void blocking_enable(int fd) |
|||
{ |
|||
fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK); |
|||
} |
|||
|
|||
void blocking_disable(int fd) |
|||
{ |
|||
fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK); |
|||
} |
@ -1,7 +0,0 @@ |
|||
#ifndef BLOCKING_H |
|||
#define BLOCKING_H |
|||
|
|||
extern void blocking_enable(int); |
|||
extern void blocking_disable(int); |
|||
|
|||
#endif |
@ -1,8 +0,0 @@ |
|||
#ifndef BYTE_H |
|||
#define BYTE_H |
|||
|
|||
extern void byte_zero(void *,long long); |
|||
extern void byte_copy(void *,long long,const void *); |
|||
extern int byte_isequal(const void *,long long,const void *); |
|||
|
|||
#endif |
@ -1,8 +0,0 @@ |
|||
#include "byte.h" |
|||
|
|||
void byte_copy(void *yv,long long ylen,const void *xv) |
|||
{ |
|||
char *y = yv; |
|||
const char *x = xv; |
|||
while (ylen > 0) { *y++ = *x++; --ylen; } |
|||
} |
@ -1,10 +0,0 @@ |
|||
#include "byte.h" |
|||
|
|||
int byte_isequal(const void *yv,long long ylen,const void *xv) |
|||
{ |
|||
const unsigned char *y = yv; |
|||
const unsigned char *x = xv; |
|||
unsigned char diff = 0; |
|||
while (ylen > 0) { diff |= (*y++ ^ *x++); --ylen; } |
|||
return (256 - (unsigned int) diff) >> 8; |
|||
} |
@ -1,7 +0,0 @@ |
|||
#include "byte.h" |
|||
|
|||
void byte_zero(void *yv,long long ylen) |
|||
{ |
|||
char *y = yv; |
|||
while (ylen > 0) { *y++ = 0; --ylen; } |
|||
} |
@ -1,35 +0,0 @@ |
|||
#include "crypto_block.h" |
|||
#include "crypto_uint64.h" |
|||
#include "uint64_unpack.h" |
|||
#include "uint64_pack.h" |
|||
|
|||
/*
|
|||
TEA with double-size words. |
|||
XXX: Switch to crypto_block_aes256. |
|||
XXX: Build crypto_stream_aes256 on top of crypto_block_aes256. |
|||
*/ |
|||
|
|||
int crypto_block( |
|||
unsigned char *out, |
|||
const unsigned char *in, |
|||
const unsigned char *k |
|||
) |
|||
{ |
|||
crypto_uint64 v0 = uint64_unpack(in + 0); |
|||
crypto_uint64 v1 = uint64_unpack(in + 8); |
|||
crypto_uint64 k0 = uint64_unpack(k + 0); |
|||
crypto_uint64 k1 = uint64_unpack(k + 8); |
|||
crypto_uint64 k2 = uint64_unpack(k + 16); |
|||
crypto_uint64 k3 = uint64_unpack(k + 24); |
|||
crypto_uint64 sum = 0; |
|||
crypto_uint64 delta = 0x9e3779b97f4a7c15; |
|||
int i; |
|||
for (i = 0;i < 32;++i) { |
|||
sum += delta; |
|||
v0 += ((v1<<7) + k0) ^ (v1 + sum) ^ ((v1>>12) + k1); |
|||
v1 += ((v0<<16) + k2) ^ (v0 + sum) ^ ((v0>>8) + k3); |
|||
} |
|||
uint64_pack(out + 0,v0); |
|||
uint64_pack(out + 8,v1); |
|||
return 0; |
|||
} |
@ -1,4 +0,0 @@ |
|||
#define crypto_block_BYTES 16 |
|||
#define crypto_block_KEYBYTES 32 |
|||
|
|||
extern int crypto_block(unsigned char *,const unsigned char *,const unsigned char *); |
@ -1,42 +0,0 @@ |
|||
#include <unistd.h> |
|||
#include "writeall.h" |
|||
#include "die.h" |
|||
|
|||
void die_9(int e |
|||
,const char *s0 |
|||
,const char *s1 |
|||
,const char *s2 |
|||
,const char *s3 |
|||
,const char *s4 |
|||
,const char *s5 |
|||
,const char *s6 |
|||
,const char *s7 |
|||
,const char *s8 |
|||
) |
|||
{ |
|||
const char *s[9]; |
|||
const char *x; |
|||
char buf[1024]; |
|||
int buflen = 0; |
|||
int i; |
|||
|
|||
s[0] = s0; |
|||
s[1] = s1; |
|||
s[2] = s2; |
|||
s[3] = s3; |
|||
s[4] = s4; |
|||
s[5] = s5; |
|||
s[6] = s6; |
|||
s[7] = s7; |
|||
s[8] = s8; |
|||
for (i = 0;i < 9;++i) { |
|||
x = s[i]; |
|||
if (!x) continue; |
|||
while (*x) { |
|||
if (buflen == sizeof buf) { writeall(2,buf,buflen); buflen = 0; } |
|||
buf[buflen++] = *x++; |
|||
} |
|||
} |
|||
writeall(2,buf,buflen); |
|||
_exit(e); |
|||
} |
@ -1,16 +0,0 @@ |
|||
#ifndef DIE_H |
|||
#define DIE_H |
|||
|
|||
extern void die_9(int,const char *,const char *,const char *,const char *,const char *,const char *,const char *,const char *,const char *); |
|||
|
|||
#define die_8(x,a,b,c,d,e,f,g,h) die_9(x,a,b,c,d,e,f,g,h,0) |
|||
#define die_7(x,a,b,c,d,e,f,g) die_8(x,a,b,c,d,e,f,g,0) |
|||
#define die_6(x,a,b,c,d,e,f) die_7(x,a,b,c,d,e,f,0) |
|||
#define die_5(x,a,b,c,d,e) die_6(x,a,b,c,d,e,0) |
|||
#define die_4(x,a,b,c,d) die_5(x,a,b,c,d,0) |
|||
#define die_3(x,a,b,c) die_4(x,a,b,c,0) |
|||
#define die_2(x,a,b) die_3(x,a,b,0) |
|||
#define die_1(x,a) die_2(x,a,0) |
|||
#define die_0(x) die_1(x,0) |
|||
|
|||
#endif |
@ -1,106 +0,0 @@ |
|||
#include "e.h" |
|||
|
|||
#define X(e,s) if (i == e) return s; |
|||
|
|||
const char *e_str(int i) |
|||
{ |
|||
X(0,"no error"); |
|||
X(EINTR,"interrupted system call") |
|||
X(ENOMEM,"out of memory") |
|||
X(ENOENT,"file does not exist") |
|||
X(ETXTBSY,"text busy") |
|||
X(EIO,"input/output error") |
|||
X(EEXIST,"file already exists") |
|||
X(ETIMEDOUT,"timed out") |
|||
X(EINPROGRESS,"operation in progress") |
|||
X(EAGAIN,"temporary failure") |
|||
X(EWOULDBLOCK,"input/output would block") |
|||
X(EPIPE,"broken pipe") |
|||
X(EPERM,"permission denied") |
|||
X(EACCES,"access denied") |
|||
X(ENODEV,"device not configured") |
|||
X(EPROTO,"protocol error") |
|||
X(EISDIR,"is a directory") |
|||
X(ESRCH,"no such process") |
|||
X(E2BIG,"argument list too long") |
|||
X(ENOEXEC,"exec format error") |
|||
X(EBADF,"file descriptor not open") |
|||
X(ECHILD,"no child processes") |
|||
X(EDEADLK,"operation would cause deadlock") |
|||
X(EFAULT,"bad address") |
|||
X(ENOTBLK,"not a block device") |
|||
X(EBUSY,"device busy") |
|||
X(EXDEV,"cross-device link") |
|||
X(ENODEV,"device does not support operation") |
|||
X(ENOTDIR,"not a directory") |
|||
X(EINVAL,"invalid argument") |
|||
X(ENFILE,"system cannot open more files") |
|||
X(EMFILE,"process cannot open more files") |
|||
X(ENOTTY,"not a tty") |
|||
X(EFBIG,"file too big") |
|||
X(ENOSPC,"out of disk space") |
|||
X(ESPIPE,"unseekable descriptor") |
|||
X(EROFS,"read-only file system") |
|||
X(EMLINK,"too many links") |
|||
X(EDOM,"input out of range") |
|||
X(ERANGE,"output out of range") |
|||
X(EALREADY,"operation already in progress") |
|||
X(ENOTSOCK,"not a socket") |
|||
X(EDESTADDRREQ,"destination address required") |
|||
X(EMSGSIZE,"message too long") |
|||
X(EPROTOTYPE,"incorrect protocol type") |
|||
X(ENOPROTOOPT,"protocol not available") |
|||
X(EPROTONOSUPPORT,"protocol not supported") |
|||
X(ESOCKTNOSUPPORT,"socket type not supported") |
|||
X(EOPNOTSUPP,"operation not supported") |
|||
X(EPFNOSUPPORT,"protocol family not supported") |
|||
X(EAFNOSUPPORT,"address family not supported") |
|||
X(EADDRINUSE,"address already used") |
|||
X(EADDRNOTAVAIL,"address not available") |
|||
X(ENETDOWN,"network down") |
|||
X(ENETUNREACH,"network unreachable") |
|||
X(ENETRESET,"network reset") |
|||
X(ECONNABORTED,"connection aborted") |
|||
X(ECONNRESET,"connection reset") |
|||
X(ENOBUFS,"out of buffer space") |
|||
X(EISCONN,"already connected") |
|||
X(ENOTCONN,"not connected") |
|||
X(ESHUTDOWN,"socket shut down") |
|||
X(ETOOMANYREFS,"too many references") |
|||
X(ECONNREFUSED,"connection refused") |
|||
X(ELOOP,"symbolic link loop") |
|||
X(ENAMETOOLONG,"file name too long") |
|||
X(EHOSTDOWN,"host down") |
|||
X(EHOSTUNREACH,"host unreachable") |
|||
X(ENOTEMPTY,"directory not empty") |
|||
X(EPROCLIM,"too many processes") |
|||
X(EUSERS,"too many users") |
|||
X(EDQUOT,"disk quota exceeded") |
|||
X(ESTALE,"stale NFS file handle") |
|||
X(EREMOTE,"too many levels of remote in path") |
|||
X(EBADRPC,"RPC structure is bad") |
|||
X(ERPCMISMATCH,"RPC version mismatch") |
|||
X(EPROGUNAVAIL,"RPC program unavailable") |
|||
X(EPROGMISMATCH,"program version mismatch") |
|||
X(EPROCUNAVAIL,"bad procedure for program") |
|||
X(ENOLCK,"no locks available") |
|||
X(ENOSYS,"system call not available") |
|||
X(EFTYPE,"bad file type") |
|||
X(EAUTH,"authentication error") |
|||
X(ENEEDAUTH,"not authenticated") |
|||
X(ENOSTR,"not a stream device") |
|||
X(ETIME,"timer expired") |
|||
X(ENOSR,"out of stream resources") |
|||
X(ENOMSG,"no message of desired type") |
|||
X(EBADMSG,"bad message type") |
|||
X(EIDRM,"identifier removed") |
|||
X(ENONET,"machine not on network") |
|||
X(EREMOTE,"object not local") |
|||
X(ENOLINK,"link severed") |
|||
X(EADV,"advertise error") |
|||
X(ESRMNT,"srmount error") |
|||
X(ECOMM,"communication error") |
|||
X(EMULTIHOP,"multihop attempted") |
|||
X(EREMCHG,"remote address changed") |
|||
return "unknown error"; |
|||
} |
@ -1,438 +0,0 @@ |
|||
#ifndef E_H |
|||
#define E_H |
|||
|
|||
#include <errno.h> |
|||
|
|||
extern const char *e_str(int); |
|||
|
|||
#ifndef EPERM |
|||
#define EPERM (-5001) |
|||
#endif |
|||
#ifndef ENOENT |
|||
#define ENOENT (-5002) |
|||
#endif |
|||
#ifndef ESRCH |
|||
#define ESRCH (-5003) |
|||
#endif |
|||
#ifndef EINTR |
|||
#define EINTR (-5004) |
|||
#endif |
|||
#ifndef EIO |
|||
#define EIO (-5005) |
|||
#endif |
|||
#ifndef ENXIO |
|||
#define ENXIO (-5006) |
|||
#endif |
|||
#ifndef E2BIG |
|||
#define E2BIG (-5007) |
|||
#endif |
|||
#ifndef ENOEXEC |
|||
#define ENOEXEC (-5008) |
|||
#endif |
|||
#ifndef EBADF |
|||
#define EBADF (-5009) |
|||
#endif |
|||
#ifndef ECHILD |
|||
#define ECHILD (-5010) |
|||
#endif |
|||
#ifndef EAGAIN |
|||
#define EAGAIN (-5011) |
|||
#endif |
|||
#ifndef EWOULDBLOCK |
|||
#define EWOULDBLOCK (-7011) |
|||
#endif |
|||
#ifndef ENOMEM |
|||
#define ENOMEM (-5012) |
|||
#endif |
|||
#ifndef EACCES |
|||
#define EACCES (-5013) |
|||
#endif |
|||
#ifndef EFAULT |
|||
#define EFAULT (-5014) |
|||
#endif |
|||
#ifndef ENOTBLK |
|||
#define ENOTBLK (-5015) |
|||
#endif |
|||
#ifndef EBUSY |
|||
#define EBUSY (-5016) |
|||
#endif |
|||
#ifndef EEXIST |
|||
#define EEXIST (-5017) |
|||
#endif |
|||
#ifndef EXDEV |
|||
#define EXDEV (-5018) |
|||
#endif |
|||
#ifndef ENODEV |
|||
#define ENODEV (-5019) |
|||
#endif |
|||
#ifndef ENOTDIR |
|||
#define ENOTDIR (-5020) |
|||
#endif |
|||
#ifndef EISDIR |
|||
#define EISDIR (-5021) |
|||
#endif |
|||
#ifndef EINVAL |
|||
#define EINVAL (-5022) |
|||
#endif |
|||
#ifndef ENFILE |
|||
#define ENFILE (-5023) |
|||
#endif |
|||
#ifndef EMFILE |
|||
#define EMFILE (-5024) |
|||
#endif |
|||
#ifndef ENOTTY |
|||
#define ENOTTY (-5025) |
|||
#endif |
|||
#ifndef ETXTBSY |
|||
#define ETXTBSY (-5026) |
|||
#endif |
|||
#ifndef EFBIG |
|||
#define EFBIG (-5027) |
|||
#endif |
|||
#ifndef ENOSPC |
|||
#define ENOSPC (-5028) |
|||
#endif |
|||
#ifndef ESPIPE |
|||
#define ESPIPE (-5029) |
|||
#endif |
|||
#ifndef EROFS |
|||
#define EROFS (-5030) |
|||
#endif |
|||
#ifndef EMLINK |
|||
#define EMLINK (-5031) |
|||
#endif |
|||
#ifndef EPIPE |
|||
#define EPIPE (-5032) |
|||
#endif |
|||
#ifndef EDOM |
|||
#define EDOM (-5033) |
|||
#endif |
|||
#ifndef ERANGE |
|||
#define ERANGE (-5034) |
|||
#endif |
|||
#ifndef EDEADLK |
|||
#define EDEADLK (-5035) |
|||
#endif |
|||
#ifndef EDEADLOCK |
|||
#define EDEADLOCK (-7035) |
|||
#endif |
|||
#ifndef ENAMETOOLONG |
|||
#define ENAMETOOLONG (-5036) |
|||
#endif |
|||
#ifndef ENOLCK |
|||
#define ENOLCK (-5037) |
|||
#endif |
|||
#ifndef ENOSYS |
|||
#define ENOSYS (-5038) |
|||
#endif |
|||
#ifndef ENOTEMPTY |
|||
#define ENOTEMPTY (-5039) |
|||
#endif |
|||
#ifndef ELOOP |
|||
#define ELOOP (-5040) |
|||
#endif |
|||
#ifndef ENOMSG |
|||
#define ENOMSG (-5042) |
|||
#endif |
|||
#ifndef EIDRM |
|||
#define EIDRM (-5043) |
|||
#endif |
|||
#ifndef ECHRNG |
|||
#define ECHRNG (-5044) |
|||
#endif |
|||
#ifndef EL2NSYNC |
|||
#define EL2NSYNC (-5045) |
|||
#endif |
|||
#ifndef EL3HLT |
|||
#define EL3HLT (-5046) |
|||
#endif |
|||
#ifndef EL3RST |
|||
#define EL3RST (-5047) |
|||
#endif |
|||
#ifndef ELNRNG |
|||
#define ELNRNG (-5048) |
|||
#endif |
|||
#ifndef EUNATCH |
|||
#define EUNATCH (-5049) |
|||
#endif |
|||
#ifndef ENOCSI |
|||
#define ENOCSI (-5050) |
|||
#endif |
|||
#ifndef EL2HLT |
|||
#define EL2HLT (-5051) |
|||
#endif |
|||
#ifndef EBADE |
|||
#define EBADE (-5052) |
|||
#endif |
|||
#ifndef EBADR |
|||
#define EBADR (-5053) |
|||
#endif |
|||
#ifndef EXFULL |
|||
#define EXFULL (-5054) |
|||
#endif |
|||
#ifndef ENOANO |
|||
#define ENOANO (-5055) |
|||
#endif |
|||
#ifndef EBADRQC |
|||
#define EBADRQC (-5056) |
|||
#endif |
|||
#ifndef EBADSLT |
|||
#define EBADSLT (-5057) |
|||
#endif |
|||
#ifndef EBFONT |
|||
#define EBFONT (-5059) |
|||
#endif |
|||
#ifndef ENOSTR |
|||
#define ENOSTR (-5060) |
|||
#endif |
|||
#ifndef ENODATA |
|||
#define ENODATA (-5061) |
|||
#endif |
|||
#ifndef ETIME |
|||
#define ETIME (-5062) |
|||
#endif |
|||
#ifndef ENOSR |
|||
#define ENOSR (-5063) |
|||
#endif |
|||
#ifndef ENONET |
|||
#define ENONET (-5064) |
|||
#endif |
|||
#ifndef ENOPKG |
|||
#define ENOPKG (-5065) |
|||
#endif |
|||
#ifndef EREMOTE |
|||
#define EREMOTE (-5066) |
|||
#endif |
|||
#ifndef ENOLINK |
|||
#define ENOLINK (-5067) |
|||
#endif |
|||
#ifndef EADV |
|||
#define EADV (-5068) |
|||
#endif |
|||
#ifndef ESRMNT |
|||
#define ESRMNT (-5069) |
|||
#endif |
|||
#ifndef ECOMM |
|||
#define ECOMM (-5070) |
|||
#endif |
|||
#ifndef EPROTO |
|||
#define EPROTO (-5071) |
|||
#endif |
|||
#ifndef EMULTIHOP |
|||
#define EMULTIHOP (-5072) |
|||
#endif |
|||
#ifndef EDOTDOT |
|||
#define EDOTDOT (-5073) |
|||
#endif |
|||
#ifndef EBADMSG |
|||
#define EBADMSG (-5074) |
|||
#endif |
|||
#ifndef EOVERFLOW |
|||
#define EOVERFLOW (-5075) |
|||
#endif |
|||
#ifndef ENOTUNIQ |
|||
#define ENOTUNIQ (-5076) |
|||
#endif |
|||
#ifndef EBADFD |
|||
#define EBADFD (-5077) |
|||
#endif |
|||
#ifndef EREMCHG |
|||
#define EREMCHG (-5078) |
|||
#endif |
|||
#ifndef ELIBACC |
|||
#define ELIBACC (-5079) |
|||
#endif |
|||
#ifndef ELIBBAD |
|||
#define ELIBBAD (-5080) |
|||
#endif |
|||
#ifndef ELIBSCN |
|||
#define ELIBSCN (-5081) |
|||
#endif |
|||
#ifndef ELIBMAX |
|||
#define ELIBMAX (-5082) |
|||
#endif |
|||
#ifndef ELIBEXEC |
|||
#define ELIBEXEC (-5083) |
|||
#endif |
|||
#ifndef EILSEQ |
|||
#define EILSEQ (-5084) |
|||
#endif |
|||
#ifndef ERESTART |
|||
#define ERESTART (-5085) |
|||
#endif |
|||
#ifndef ESTRPIPE |
|||
#define ESTRPIPE (-5086) |
|||
#endif |
|||
#ifndef EUSERS |
|||
#define EUSERS (-5087) |
|||
#endif |
|||
#ifndef ENOTSOCK |
|||
#define ENOTSOCK (-5088) |
|||
#endif |
|||
#ifndef EDESTADDRREQ |
|||
#define EDESTADDRREQ (-5089) |
|||
#endif |
|||
#ifndef EMSGSIZE |
|||
#define EMSGSIZE (-5090) |
|||
#endif |
|||
#ifndef EPROTOTYPE |
|||
#define EPROTOTYPE (-5091) |
|||
#endif |
|||
#ifndef ENOPROTOOPT |
|||
#define ENOPROTOOPT (-5092) |
|||
#endif |
|||
#ifndef EPROTONOSUPPORT |
|||
#define EPROTONOSUPPORT (-5093) |
|||
#endif |
|||
#ifndef ESOCKTNOSUPPORT |
|||
#define ESOCKTNOSUPPORT (-5094) |
|||
#endif |
|||
#ifndef EOPNOTSUPP |
|||
#define EOPNOTSUPP (-5095) |
|||
#endif |
|||
#ifndef EPFNOSUPPORT |
|||
#define EPFNOSUPPORT (-5096) |
|||
#endif |
|||
#ifndef EAFNOSUPPORT |
|||
#define EAFNOSUPPORT (-5097) |
|||
#endif |
|||
#ifndef EADDRINUSE |
|||
#define EADDRINUSE (-5098) |
|||
#endif |
|||
#ifndef EADDRNOTAVAIL |
|||
#define EADDRNOTAVAIL (-5099) |
|||
#endif |
|||
#ifndef ENETDOWN |
|||
#define ENETDOWN (-5100) |
|||
#endif |
|||
#ifndef ENETUNREACH |
|||
#define ENETUNREACH (-5101) |
|||
#endif |
|||
#ifndef ENETRESET |
|||
#define ENETRESET (-5102) |
|||
#endif |
|||
#ifndef ECONNABORTED |
|||
#define ECONNABORTED (-5103) |
|||
#endif |
|||
#ifndef ECONNRESET |
|||
#define ECONNRESET (-5104) |
|||
#endif |
|||
#ifndef ENOBUFS |
|||
#define ENOBUFS (-5105) |
|||
#endif |
|||
#ifndef EISCONN |
|||
#define EISCONN (-5106) |
|||
#endif |
|||
#ifndef ENOTCONN |
|||
#define ENOTCONN (-5107) |
|||
#endif |
|||
#ifndef ESHUTDOWN |
|||
#define ESHUTDOWN (-5108) |
|||
#endif |
|||
#ifndef ETOOMANYREFS |
|||
#define ETOOMANYREFS (-5109) |
|||
#endif |
|||
#ifndef ETIMEDOUT |
|||
#define ETIMEDOUT (-5110) |
|||
#endif |
|||
#ifndef ECONNREFUSED |
|||
#define ECONNREFUSED (-5111) |
|||
#endif |
|||
#ifndef EHOSTDOWN |
|||
#define EHOSTDOWN (-5112) |
|||
#endif |
|||
#ifndef EHOSTUNREACH |
|||
#define EHOSTUNREACH (-5113) |
|||
#endif |
|||
#ifndef EALREADY |
|||
#define EALREADY (-5114) |
|||
#endif |
|||
#ifndef EINPROGRESS |
|||
#define EINPROGRESS (-5115) |
|||
#endif |
|||
#ifndef ESTALE |
|||
#define ESTALE (-5116) |
|||
#endif |
|||
#ifndef EUCLEAN |
|||
#define EUCLEAN (-5117) |
|||
#endif |
|||
#ifndef ENOTNAM |
|||
#define ENOTNAM (-5118) |
|||
#endif |
|||
#ifndef ENAVAIL |
|||
#define ENAVAIL (-5119) |
|||
#endif |
|||
#ifndef EISNAM |
|||
#define EISNAM (-5120) |
|||
#endif |
|||
#ifndef EREMOTEIO |
|||
#define EREMOTEIO (-5121) |
|||
#endif |
|||
#ifndef EDQUOT |
|||
#define EDQUOT (-5122) |
|||
#endif |
|||
#ifndef ENOMEDIUM |
|||
#define ENOMEDIUM (-5123) |
|||
#endif |
|||
#ifndef EMEDIUMTYPE |
|||
#define EMEDIUMTYPE (-5124) |
|||
#endif |
|||
#ifndef ECANCELED |
|||
#define ECANCELED (-5125) |
|||
#endif |
|||
#ifndef ENOKEY |
|||
#define ENOKEY (-5126) |
|||
#endif |
|||
#ifndef EKEYEXPIRED |
|||
#define EKEYEXPIRED (-5127) |
|||
#endif |
|||
#ifndef EKEYREVOKED |
|||
#define EKEYREVOKED (-5128) |
|||
#endif |
|||
#ifndef EKEYREJECTED |
|||
#define EKEYREJECTED (-5129) |
|||
#endif |
|||
#ifndef EOWNERDEAD |
|||
#define EOWNERDEAD (-5130) |
|||
#endif |
|||
#ifndef ENOTRECOVERABLE |
|||
#define ENOTRECOVERABLE (-5131) |
|||
#endif |
|||
#ifndef ERFKILL |
|||
#define ERFKILL (-5132) |
|||
#endif |
|||
#ifndef EPROCLIM |
|||
#define EPROCLIM (-6067) |
|||
#endif |
|||
#ifndef EBADRPC |
|||
#define EBADRPC (-6072) |
|||
#endif |
|||
#ifndef ERPCMISMATCH |
|||
#define ERPCMISMATCH (-6073) |
|||
#endif |
|||
#ifndef EPROGUNAVAIL |
|||
#define EPROGUNAVAIL (-6074) |
|||
#endif |
|||
#ifndef EPROGMISMATCH |
|||
#define EPROGMISMATCH (-6075) |
|||
#endif |
|||
#ifndef EPROCUNAVAIL |
|||
#define EPROCUNAVAIL (-6076) |
|||
#endif |
|||
#ifndef EFTYPE |
|||
#define EFTYPE (-6079) |
|||
#endif |
|||
#ifndef EAUTH |
|||
#define EAUTH (-6080) |
|||
#endif |
|||
#ifndef ENEEDAUTH |
|||
#define ENEEDAUTH (-6081) |
|||
#endif |
|||
#ifndef ENOATTR |
|||
#define ENOATTR (-6087) |
|||
#endif |
|||
#ifndef ENOTCAPABLE |
|||
#define ENOTCAPABLE (-6093) |
|||
#endif |
|||
|
|||
#endif |
@ -1,25 +0,0 @@ |
|||
#include "hexparse.h" |
|||
|
|||
static int hexdigit(char x) |
|||
{ |
|||
if (x >= '0' && x <= '9') return x - '0'; |
|||
if (x >= 'a' && x <= 'f') return 10 + (x - 'a'); |
|||
if (x >= 'A' && x <= 'F') return 10 + (x - 'A'); |
|||
return -1; |
|||
} |
|||
|
|||
int hexparse(unsigned char *y,long long len,const char *x) |
|||
{ |
|||
if (!x) return 0; |
|||
while (len > 0) { |
|||
int digit0; |
|||
int digit1; |
|||
digit0 = hexdigit(x[0]); if (digit0 == -1) return 0; |
|||
digit1 = hexdigit(x[1]); if (digit1 == -1) return 0; |
|||
*y++ = digit1 + 16 * digit0; |
|||
--len; |
|||
x += 2; |
|||
} |
|||
if (x[0]) return 0; |
|||
return 1; |
|||
} |
@ -1,6 +0,0 @@ |
|||
#ifndef HEXPARSE_H |
|||
#define HEXPARSE_H |
|||
|
|||
extern int hexparse(unsigned char *,long long,const char *); |
|||
|
|||
#endif |
@ -1,33 +0,0 @@ |
|||
#include <unistd.h> |
|||
#include "open.h" |
|||
#include "e.h" |
|||
#include "load.h" |
|||
|
|||
static int readall(int fd,void *x,long long xlen) |
|||
{ |
|||
long long r; |
|||
while (xlen > 0) { |
|||
r = xlen; |
|||
if (r > 1048576) r = 1048576; |
|||
r = read(fd,x,r); |
|||
if (r == 0) errno = EPROTO; |
|||
if (r <= 0) { |
|||
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) continue; |
|||
return -1; |
|||
} |
|||
x += r; |
|||
xlen -= r; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
int load(const char *fn,void *x,long long xlen) |
|||
{ |
|||
int fd; |
|||
int r; |
|||
fd = open_read(fn); |
|||
if (fd == -1) return -1; |
|||
r = readall(fd,x,xlen); |
|||
close(fd); |
|||
return r; |
|||
} |
@ -1,6 +0,0 @@ |
|||
#ifndef LOAD_H |
|||
#define LOAD_H |
|||
|
|||
extern int load(const char *,void *,long long); |
|||
|
|||
#endif |
@ -1,19 +0,0 @@ |
|||
#include "nameparse.h" |
|||
|
|||
int nameparse(unsigned char *s,const char *x) |
|||
{ |
|||
long long pos; |
|||
long long j; |
|||
if (!x) return 0; |
|||
for (pos = 0;pos < 256;++pos) s[pos] = 0; |
|||
pos = 0; |
|||
while (*x) { |
|||
if (*x == '.') { ++x; continue; } |
|||
for (j = 0;x[j];++j) if (x[j] == '.') break; |
|||
if (j > 63) return 0; |
|||
if (pos < 0 || pos >= 256) return 0; s[pos++] = j; |
|||
while (j > 0) { if (pos < 0 || pos >= 256) return 0; s[pos++] = *x++; --j; } |
|||
} |
|||
if (pos < 0 || pos >= 256) return 0; s[pos++] = 0; |
|||
return 1; |
|||
} |
@ -1,6 +0,0 @@ |
|||
#ifndef NAMEPARSE_H |
|||
#define NAMEPARSE_H |
|||
|
|||
extern int nameparse(unsigned char *,const char *); |
|||
|
|||
#endif |
@ -1,19 +0,0 @@ |
|||
#include <sys/time.h> |
|||
#include <time.h> |
|||
#include "nanoseconds.h" |
|||
|
|||
/* XXX: Y2036 problems; should upgrade to a 128-bit type for this */ |
|||
/* XXX: nanosecond granularity limits users to 1 terabyte per second */ |
|||
|
|||
long long nanoseconds(void) |
|||
{ |
|||
#if defined(CLOCK_REALTIME) && defined(HAVE_CLOCK_GETTIME) |
|||
struct timespec t; |
|||
if (clock_gettime(CLOCK_REALTIME,&t) != 0) return -1; |
|||
return t.tv_sec * 1000000000LL + t.tv_nsec; |
|||
#else |
|||
struct timeval tv; |
|||
gettimeofday(&tv, NULL); |
|||
return tv.tv_sec * 1000000000LL + tv.tv_usec * 1000LL; |
|||
#endif |
|||
} |
@ -1,6 +0,0 @@ |
|||
#ifndef NANOSECONDS_H |
|||
#define NANOSECONDS_H |
|||
|
|||
extern long long nanoseconds(void); |
|||
|
|||
#endif |
@ -1,10 +0,0 @@ |
|||
#ifndef OPEN_H |
|||
#define OPEN_H |
|||
|
|||
extern int open_read(const char *); |
|||
extern int open_write(const char *); |
|||
extern int open_lock(const char *); |
|||
extern int open_cwd(void); |
|||
extern int open_pipe(int *); |
|||
|
|||
#endif |
@ -1,6 +0,0 @@ |
|||
#include "open.h" |
|||
|
|||
int open_cwd(void) |
|||
{ |
|||
return open_read("."); |
|||
} |
@ -1,21 +0,0 @@ |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "open.h" |
|||
|
|||
int open_lock(const char *fn) |
|||
{ |
|||
#ifdef O_CLOEXEC |
|||
int fd = open(fn,O_RDWR | O_CLOEXEC); |
|||
if (fd == -1) return -1; |
|||
#else |
|||
int fd = open(fn,O_RDWR); |
|||
if (fd == -1) return -1; |
|||
fcntl(fd,F_SETFD,1); |
|||
#endif |
|||
#ifdef F_LOCK |
|||
if (lockf(fd,F_LOCK,0) == -1) { close(fd); return -1; } |
|||
#endif |
|||
return fd; |
|||
} |
@ -1,15 +0,0 @@ |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "open.h" |
|||
#include "blocking.h" |
|||
|
|||
int open_pipe(int *fd) |
|||
{ |
|||
int i; |
|||
if (pipe(fd) == -1) return -1; |
|||
for (i = 0;i < 2;++i) { |
|||
fcntl(fd[i],F_SETFD,1); |
|||
blocking_disable(fd[i]); |
|||
} |
|||
return 0; |
|||
} |
@ -1,17 +0,0 @@ |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "open.h" |
|||
|
|||
int open_read(const char *fn) |
|||
{ |
|||
#ifdef O_CLOEXEC |
|||
return open(fn,O_RDONLY | O_NONBLOCK | O_CLOEXEC); |
|||
#else |
|||
int fd = open(fn,O_RDONLY | O_NONBLOCK); |
|||
if (fd == -1) return -1; |
|||
fcntl(fd,F_SETFD,1); |
|||
return fd; |
|||
#endif |
|||
} |
@ -1,17 +0,0 @@ |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include "open.h" |
|||
|
|||
int open_write(const char *fn) |
|||
{ |
|||
#ifdef O_CLOEXEC |
|||
return open(fn,O_CREAT | O_WRONLY | O_NONBLOCK | O_CLOEXEC,0644); |
|||
#else |
|||
int fd = open(fn,O_CREAT | O_WRONLY | O_NONBLOCK,0644); |
|||
if (fd == -1) return -1; |
|||
fcntl(fd,F_SETFD,1); |
|||
return fd; |
|||
#endif |
|||
} |
@ -1,14 +0,0 @@ |
|||
#include "portparse.h" |
|||
|
|||
int portparse(unsigned char *y,const char *x) |
|||
{ |
|||
long long d = 0; |
|||
long long j; |
|||
for (j = 0;j < 5 && x[j] >= '0' && x[j] <= '9';++j) |
|||
d = d * 10 + (x[j] - '0'); |
|||
if (j == 0) return 0; |
|||
if (x[j]) return 0; |
|||
y[0] = d >> 8; |
|||
y[1] = d; |
|||
return 1; |
|||
} |
@ -1,6 +0,0 @@ |
|||
#ifndef PORTPARSE_H |
|||
#define PORTPARSE_H |
|||
|
|||
extern int portparse(unsigned char *,const char *); |
|||
|
|||
#endif |
@ -1,14 +0,0 @@ |
|||
#include "randombytes.h" |
|||
|
|||
/* XXX: current implementation is limited to n<2^55 */ |
|||
|
|||
long long randommod(long long n) |
|||
{ |
|||
long long result = 0; |
|||
long long j; |
|||
unsigned char r[32]; |
|||
if (n <= 1) return 0; |
|||
randombytes(r,32); |
|||
for (j = 0;j < 32;++j) result = (result * 256 + (unsigned long long) r[j]) % n; |
|||
return result; |
|||
} |
@ -1,6 +0,0 @@ |
|||
#ifndef RANDOMMOD_H |
|||
#define RANDOMMOD_H |
|||
|
|||
extern long long randommod(long long); |
|||
|
|||
#endif |
@ -1,74 +0,0 @@ |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <fcntl.h> |
|||
#include <unistd.h> |
|||
#include "crypto_uint64.h" |
|||
#include "uint64_pack.h" |
|||
#include "uint64_unpack.h" |
|||
#include "savesync.h" |
|||
#include "open.h" |
|||
#include "load.h" |
|||
#include "randombytes.h" |
|||
#include "safenonce.h" |
|||
|
|||
#include "crypto_block.h" |
|||
#if crypto_block_BYTES != 16 |
|||
error! |
|||
#endif |
|||
#if crypto_block_KEYBYTES != 32 |
|||
error! |
|||
#endif |
|||
|
|||
/*
|
|||
Output: 128-bit nonce y[0],...,y[15]. |
|||
Reads and writes existing 8-byte file ".expertsonly/noncecounter", |
|||
locked via existing 1-byte file ".expertsonly/lock". |
|||
Also reads existing 32-byte file ".expertsonly/noncekey". |
|||
Not thread-safe. |
|||
|
|||
Invariants: |
|||
This process is free to use counters that are >=counterlow and <counterhigh. |
|||
The 8-byte file contains a counter that is safe to use and >=counterhigh. |
|||
|
|||
XXX: should rewrite file in background, rather than briefly pausing |
|||
*/ |
|||
|
|||
static crypto_uint64 counterlow = 0; |
|||
static crypto_uint64 counterhigh = 0; |
|||
|
|||
static unsigned char flagkeyloaded = 0; |
|||
static unsigned char noncekey[32]; |
|||
static unsigned char data[16]; |
|||
|
|||
int safenonce(unsigned char *y,int flaglongterm) |
|||
{ |
|||
if (!flagkeyloaded) { |
|||
int fdlock; |
|||
fdlock = open_lock(".expertsonly/lock"); |
|||
if (fdlock == -1) return -1; |
|||
if (load(".expertsonly/noncekey",noncekey,sizeof noncekey) == -1) { close(fdlock); return -1; } |
|||
close(fdlock); |
|||
flagkeyloaded = 1; |
|||
} |
|||
|
|||
if (counterlow >= counterhigh) { |
|||
int fdlock; |
|||
fdlock = open_lock(".expertsonly/lock"); |
|||
if (fdlock == -1) return -1; |
|||
if (load(".expertsonly/noncecounter",data,8) == -1) { close(fdlock); return -1; } |
|||
counterlow = uint64_unpack(data); |
|||
if (flaglongterm) |
|||
counterhigh = counterlow + 1048576; |
|||
else |
|||
counterhigh = counterlow + 1; |
|||
uint64_pack(data,counterhigh); |
|||
if (savesync(".expertsonly/noncecounter",data,8) == -1) { close(fdlock); return -1; } |
|||
close(fdlock); |
|||
} |
|||
|
|||
randombytes(data + 8,8); |
|||
uint64_pack(data,counterlow++); |
|||
crypto_block(y,data,noncekey); |
|||
|
|||
return 0; |
|||
} |
@ -1,6 +0,0 @@ |
|||
#ifndef SAFENONCE_H |
|||
#define SAFENONCE_H |
|||
|
|||
extern int safenonce(unsigned char *,int); |
|||
|
|||
#endif |
@ -1,24 +0,0 @@ |
|||
#include <sys/types.h> |
|||
#include <sys/stat.h> |
|||
#include <fcntl.h> |
|||
#include <unistd.h> |
|||
#include "open.h" |
|||
#include "savesync.h" |
|||
#include "writeall.h" |
|||
|
|||
static int writesync(int fd,const void *x,long long xlen) |
|||
{ |
|||
if (writeall(fd,x,xlen) == -1) return -1; |
|||
return fsync(fd); |
|||
} |
|||
|
|||
int savesync(const char *fn,const void *x,long long xlen) |
|||
{ |
|||
int fd; |
|||
int r; |
|||
fd = open_write(fn); |
|||
if (fd == -1) return -1; |
|||
r = writesync(fd,x,xlen); |
|||
close(fd); |
|||
return r; |
|||
} |
@ -1,6 +0,0 @@ |
|||
#ifndef SAVESYNC_H |
|||
#define SAVESYNC_H |
|||
|
|||
extern int savesync(const char *,const void *,long long); |
|||
|
|||
#endif |
@ -1,9 +0,0 @@ |
|||
#ifndef SOCKET_H |
|||
#define SOCKET_H |
|||
|
|||
extern int socket_udp(void); |
|||
extern int socket_bind(int,const unsigned char *,const unsigned char *); |
|||
extern int socket_send(int,const unsigned char *,long long,const unsigned char *,const unsigned char *); |
|||
extern long long socket_recv(int,unsigned char *,long long,unsigned char *,unsigned char *); |
|||
|
|||
#endif |
@ -1,15 +0,0 @@ |
|||
#include <sys/types.h> |
|||
#include <sys/socket.h> |
|||
#include <netinet/in.h> |
|||
#include <errno.h> |
|||
#include "socket.h" |
|||
#include "byte.h" |
|||
|
|||
int socket_bind(int fd,const unsigned char *ip,const unsigned char *port) |
|||
{ |
|||
struct sockaddr_in sa; |
|||
byte_zero(&sa,sizeof sa); |
|||
byte_copy(&sa.sin_addr,4,ip); |
|||
byte_copy(&sa.sin_port,2,port); |
|||
return bind(fd,(struct sockaddr *) &sa,sizeof sa); |
|||
} |
@ -1,24 +0,0 @@ |
|||
#include <sys/types.h> |
|||
#include <sys/socket.h> |
|||
#include <netinet/in.h> |
|||
#include <errno.h> |
|||
#include "e.h" |
|||
#include "socket.h" |
|||
#include "byte.h" |
|||
|
|||
long long socket_recv(int fd,unsigned char *x,long long xlen,unsigned char *ip,unsigned char *port) |
|||
{ |
|||
struct sockaddr_in sa; |
|||
socklen_t salen; |
|||
int r; |
|||
|
|||
if (xlen < 0) { errno = EPROTO; return -1; } |
|||
if (xlen > 1048576) xlen = 1048576; |
|||
|
|||
byte_zero(&sa,sizeof sa); |
|||
salen = sizeof sa; |
|||
r = recvfrom(fd,x,xlen,0,(struct sockaddr *) &sa,&salen); |
|||
byte_copy(ip,4,&sa.sin_addr); |
|||
byte_copy(port,2,&sa.sin_port); |
|||
return r; |
|||
} |
@ -1,20 +0,0 @@ |
|||
#include <sys/types.h> |
|||
#include <sys/socket.h> |
|||
#include <netinet/in.h> |
|||
#include <errno.h> |
|||
#include "e.h" |
|||
#include "socket.h" |
|||
#include "byte.h" |
|||
|
|||
int socket_send(int fd,const unsigned char *x,long long xlen,const unsigned char *ip,const unsigned char *port) |
|||
{ |
|||
struct sockaddr_in sa; |
|||
|
|||
if (xlen < 0 || xlen > 1048576) { errno = EPROTO; return -1; } |
|||
|
|||
byte_zero(&sa,sizeof sa); |
|||
sa.sin_family = AF_INET; |
|||
byte_copy(&sa.sin_addr,4,ip); |
|||
byte_copy(&sa.sin_port,2,port); |
|||
return sendto(fd,x,xlen,0,(struct sockaddr *) &sa,sizeof sa); |
|||
} |
@ -1,36 +0,0 @@ |
|||
#include <unistd.h> |
|||
#include <fcntl.h> |
|||
#include <sys/types.h> |
|||
#include <sys/socket.h> |
|||
#include <netinet/in.h> |
|||
#include "socket.h" |
|||
#include "blocking.h" |
|||
|
|||
static void enable_bsd_fragmentation(int fd) |
|||
{ |
|||
#ifdef IP_DONTFRAG |
|||
const int x = 0; |
|||
setsockopt(fd,SOL_IP,IP_DONTFRAG,&x,sizeof x); |
|||
#endif |
|||
} |
|||
|
|||
static void enable_linux_fragmentation(int fd) |
|||
{ |
|||
#ifdef IP_MTU_DISCOVER |
|||
#ifdef IP_PMTUDISC_DONT |
|||
const int x = IP_PMTUDISC_DONT; |
|||
setsockopt(fd,SOL_IP,IP_MTU_DISCOVER,&x,sizeof x); |
|||
#endif |
|||
#endif |
|||
} |
|||
|
|||
int socket_udp(void) |
|||
{ |
|||
int fd = socket(PF_INET,SOCK_DGRAM,0); |
|||
if (fd == -1) return -1; |
|||
fcntl(fd,F_SETFD,1); |
|||
blocking_disable(fd); |
|||
enable_bsd_fragmentation(fd); |
|||
enable_linux_fragmentation(fd); |
|||
return fd; |
|||
} |
@ -1,7 +0,0 @@ |
|||
#include "uint16_pack.h" |
|||
|
|||
void uint16_pack(unsigned char *y,crypto_uint16 x) |
|||
{ |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
} |
@ -1,8 +0,0 @@ |
|||
#ifndef UINT16_PACK_H |
|||
#define UINT16_PACK_H |
|||
|
|||
#include "crypto_uint16.h" |
|||
|
|||
extern void uint16_pack(unsigned char *,crypto_uint16); |
|||
|
|||
#endif |
@ -1,9 +0,0 @@ |
|||
#include "uint16_unpack.h" |
|||
|
|||
crypto_uint16 uint16_unpack(const unsigned char *x) |
|||
{ |
|||
crypto_uint16 result; |
|||
result = x[1]; |
|||
result <<= 8; result |= x[0]; |
|||
return result; |
|||
} |
@ -1,8 +0,0 @@ |
|||
#ifndef UINT16_UNPACK_H |
|||
#define UINT16_UNPACK_H |
|||
|
|||
#include "crypto_uint16.h" |
|||
|
|||
extern crypto_uint16 uint16_unpack(const unsigned char *); |
|||
|
|||
#endif |
@ -1,9 +0,0 @@ |
|||
#include "uint32_pack.h" |
|||
|
|||
void uint32_pack(unsigned char *y,crypto_uint32 x) |
|||
{ |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
} |
@ -1,8 +0,0 @@ |
|||
#ifndef UINT32_PACK_H |
|||
#define UINT32_PACK_H |
|||
|
|||
#include "crypto_uint32.h" |
|||
|
|||
extern void uint32_pack(unsigned char *,crypto_uint32); |
|||
|
|||
#endif |
@ -1,11 +0,0 @@ |
|||
#include "uint32_unpack.h" |
|||
|
|||
crypto_uint32 uint32_unpack(const unsigned char *x) |
|||
{ |
|||
crypto_uint32 result; |
|||
result = x[3]; |
|||
result <<= 8; result |= x[2]; |
|||
result <<= 8; result |= x[1]; |
|||
result <<= 8; result |= x[0]; |
|||
return result; |
|||
} |
@ -1,8 +0,0 @@ |
|||
#ifndef UINT32_UNPACK_H |
|||
#define UINT32_UNPACK_H |
|||
|
|||
#include "crypto_uint32.h" |
|||
|
|||
extern crypto_uint32 uint32_unpack(const unsigned char *); |
|||
|
|||
#endif |
@ -1,13 +0,0 @@ |
|||
#include "uint64_pack.h" |
|||
|
|||
void uint64_pack(unsigned char *y,crypto_uint64 x) |
|||
{ |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
*y++ = x; x >>= 8; |
|||
} |
@ -1,8 +0,0 @@ |
|||
#ifndef UINT64_PACK_H |
|||
#define UINT64_PACK_H |
|||
|
|||
#include "crypto_uint64.h" |
|||
|
|||
extern void uint64_pack(unsigned char *,crypto_uint64); |
|||
|
|||
#endif |
@ -1,15 +0,0 @@ |
|||
#include "uint64_unpack.h" |
|||
|
|||
crypto_uint64 uint64_unpack(const unsigned char *x) |
|||
{ |
|||
crypto_uint64 result; |
|||
result = x[7]; |
|||
result <<= 8; result |= x[6]; |
|||
result <<= 8; result |= x[5]; |
|||
result <<= 8; result |= x[4]; |
|||
result <<= 8; result |= x[3]; |
|||
result <<= 8; result |= x[2]; |
|||
result <<= 8; result |= x[1]; |
|||
result <<= 8; result |= x[0]; |
|||
return result; |
|||
} |
@ -1,8 +0,0 @@ |
|||
#ifndef UINT64_UNPACK_H |
|||
#define UINT64_UNPACK_H |
|||
|
|||
#include "crypto_uint64.h" |
|||
|
|||
extern crypto_uint64 uint64_unpack(const unsigned char *); |
|||
|
|||
#endif |
@ -1,27 +0,0 @@ |
|||
#include <poll.h> |
|||
#include <unistd.h> |
|||
#include "e.h" |
|||
#include "writeall.h" |
|||
|
|||
int writeall(int fd,const void *x,long long xlen) |
|||
{ |
|||
long long w; |
|||
while (xlen > 0) { |
|||
w = xlen; |
|||
if (w > 1048576) w = 1048576; |
|||
w = write(fd,x,w); |
|||
if (w < 0) { |
|||
if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { |
|||
struct pollfd p; |
|||
p.fd = fd; |
|||
p.events = POLLOUT | POLLERR; |
|||
poll(&p,1,-1); |
|||
continue; |
|||
} |
|||
return -1; |
|||
} |
|||
x += w; |
|||
xlen -= w; |
|||
} |
|||
return 0; |
|||
} |
@ -1,6 +0,0 @@ |
|||
#ifndef WRITEALL_H |
|||
#define WRITEALL_H |
|||
|
|||
extern int writeall(int,const void *,long long); |
|||
|
|||
#endif |
Loading…
Reference in new issue