
werrstr() takes a format string as its first argument. a common error is to pass user controlled string buffers into werrstr() that might contain format string escapes causing werrstr() to take bogus arguments from the stack and crash. so instead of doing: werrstr(buf); we want todo: werrstr("%s", buf); or if we have a local ERRMAX sized buffer that we can override: errstr(buf, sizeof buf);
180 lines
3.1 KiB
C
180 lines
3.1 KiB
C
#include <u.h>
|
|
#include <libc.h>
|
|
#include <venti.h>
|
|
|
|
int ventidoublechecksha1 = 1;
|
|
|
|
static int
|
|
vtfcallrpc(VtConn *z, VtFcall *ou, VtFcall *in)
|
|
{
|
|
Packet *p;
|
|
|
|
p = vtfcallpack(ou);
|
|
if(p == nil)
|
|
return -1;
|
|
if((p = _vtrpc(z, p, ou)) == nil)
|
|
return -1;
|
|
if(vtfcallunpack(in, p) < 0){
|
|
packetfree(p);
|
|
return -1;
|
|
}
|
|
if(chattyventi)
|
|
fprint(2, "%s <- %F\n", argv0, in);
|
|
if(in->msgtype == VtRerror){
|
|
werrstr("%s", in->error);
|
|
vtfcallclear(in);
|
|
packetfree(p);
|
|
return -1;
|
|
}
|
|
if(in->msgtype != ou->msgtype+1){
|
|
werrstr("type mismatch: sent %c%d got %c%d",
|
|
"TR"[ou->msgtype&1], ou->msgtype>>1,
|
|
"TR"[in->msgtype&1], in->msgtype>>1);
|
|
vtfcallclear(in);
|
|
packetfree(p);
|
|
return -1;
|
|
}
|
|
packetfree(p);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
vthello(VtConn *z)
|
|
{
|
|
VtFcall tx, rx;
|
|
|
|
memset(&tx, 0, sizeof tx);
|
|
tx.msgtype = VtThello;
|
|
tx.version = z->version;
|
|
tx.uid = z->uid;
|
|
if(tx.uid == nil)
|
|
tx.uid = "anonymous";
|
|
if(vtfcallrpc(z, &tx, &rx) < 0)
|
|
return -1;
|
|
z->sid = rx.sid;
|
|
rx.sid = 0;
|
|
vtfcallclear(&rx);
|
|
return 0;
|
|
}
|
|
|
|
Packet*
|
|
vtreadpacket(VtConn *z, uchar score[VtScoreSize], uint type, int n)
|
|
{
|
|
VtFcall tx, rx;
|
|
|
|
if(memcmp(score, vtzeroscore, VtScoreSize) == 0)
|
|
return packetalloc();
|
|
|
|
memset(&tx, 0, sizeof tx);
|
|
tx.msgtype = VtTread;
|
|
tx.blocktype = type;
|
|
tx.count = n;
|
|
memmove(tx.score, score, VtScoreSize);
|
|
if(vtfcallrpc(z, &tx, &rx) < 0)
|
|
return nil;
|
|
if(packetsize(rx.data) > n){
|
|
werrstr("read returned too much data");
|
|
packetfree(rx.data);
|
|
return nil;
|
|
}
|
|
if(ventidoublechecksha1){
|
|
packetsha1(rx.data, tx.score);
|
|
if(memcmp(score, tx.score, VtScoreSize) != 0){
|
|
werrstr("read asked for %V got %V", score, tx.score);
|
|
packetfree(rx.data);
|
|
return nil;
|
|
}
|
|
}
|
|
return rx.data;
|
|
}
|
|
|
|
int
|
|
vtread(VtConn *z, uchar score[VtScoreSize], uint type, uchar *buf, int n)
|
|
{
|
|
int nn;
|
|
Packet *p;
|
|
|
|
if((p = vtreadpacket(z, score, type, n)) == nil)
|
|
return -1;
|
|
nn = packetsize(p);
|
|
if(packetconsume(p, buf, nn) < 0)
|
|
abort();
|
|
packetfree(p);
|
|
return nn;
|
|
}
|
|
|
|
int
|
|
vtwritepacket(VtConn *z, uchar score[VtScoreSize], uint type, Packet *p)
|
|
{
|
|
VtFcall tx, rx;
|
|
|
|
if(packetsize(p) == 0){
|
|
memmove(score, vtzeroscore, VtScoreSize);
|
|
return 0;
|
|
}
|
|
tx.msgtype = VtTwrite;
|
|
tx.blocktype = type;
|
|
tx.data = p;
|
|
if(ventidoublechecksha1)
|
|
packetsha1(p, score);
|
|
if(vtfcallrpc(z, &tx, &rx) < 0)
|
|
return -1;
|
|
if(ventidoublechecksha1){
|
|
if(memcmp(score, rx.score, VtScoreSize) != 0){
|
|
werrstr("sha1 hash mismatch: want %V got %V", score, rx.score);
|
|
return -1;
|
|
}
|
|
}else
|
|
memmove(score, rx.score, VtScoreSize);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
vtwrite(VtConn *z, uchar score[VtScoreSize], uint type, uchar *buf, int n)
|
|
{
|
|
Packet *p;
|
|
int nn;
|
|
|
|
p = packetforeign(buf, n, 0, nil);
|
|
nn = vtwritepacket(z, score, type, p);
|
|
packetfree(p);
|
|
return nn;
|
|
}
|
|
|
|
int
|
|
vtsync(VtConn *z)
|
|
{
|
|
VtFcall tx, rx;
|
|
|
|
tx.msgtype = VtTsync;
|
|
return vtfcallrpc(z, &tx, &rx);
|
|
}
|
|
|
|
int
|
|
vtping(VtConn *z)
|
|
{
|
|
VtFcall tx, rx;
|
|
|
|
tx.msgtype = VtTping;
|
|
return vtfcallrpc(z, &tx, &rx);
|
|
}
|
|
|
|
int
|
|
vtconnect(VtConn *z)
|
|
{
|
|
if(vtversion(z) < 0)
|
|
return -1;
|
|
if(vthello(z) < 0)
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
vtgoodbye(VtConn *z)
|
|
{
|
|
VtFcall tx, rx;
|
|
|
|
tx.msgtype = VtTgoodbye;
|
|
vtfcallrpc(z, &tx, &rx); /* always fails: no VtRgoodbye */
|
|
return 0;
|
|
}
|