plan9fox/sys/src/libventi/client.c
cinap_lenrek 797cc13c70 fix dangerous werrstr() usages
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);
2014-11-07 12:51:59 +01:00

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;
}