commit 2942d44a51881b74a16907f083c4e0c08228fd07
parent a2c0fa314c98321ca42d17a0bf306d292f5f7c0c
Author: Remy Noulin <loader2x@gmail.com>
Date: Mon, 22 Aug 2022 04:12:56 -0400
check packet and string sizes and free disk space
to avoid buffer overflows.
NOTES.md | 1 +
serverPackage.yml | 2 +-
sserver.c | 40 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 42 insertions(+), 1 deletion(-)
Diffstat:
3 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/NOTES.md b/NOTES.md
@@ -2,6 +2,7 @@
- create tests
- send errors from server to client
- make daemon
+- add timeouts in server to close the connection when a client is too slow
..- tls
..- check inputs, add limits
..- add rate limiter, ban wrong token for 15minutes
diff --git a/serverPackage.yml b/serverPackage.yml
@@ -1,6 +1,6 @@
---
name: tuyauServer
- version: 0.0.4
+ version: 0.0.5
description: "Server for copying files with tuyau"
bin: ./tuyauServer.c
#cflags: -DA -g3 -std=gnu11 -fPIC -pipe
diff --git a/sserver.c b/sserver.c
@@ -27,6 +27,9 @@
// basename
#include <libgen.h>
+// statvfs
+#include <sys/statvfs.h>
+
#include "libsheepyObject.h"
#include "netFrame.h"
#include "shpPackages/short/short.h"
@@ -196,6 +199,8 @@ int main(int ARGC, char** ARGV) {
void saveReceivedData(void *receiveB, size_t sz) {
logVarG(sz);
if (packetCount == 0) {
+ // check packet size
+ if (sz < (1/*command*/ + 8/*token*/)) ret;
// receive a new command
// header
u8 *command = (u8*) receiveB;
@@ -214,18 +219,26 @@ void saveReceivedData(void *receiveB, size_t sz) {
if (*command == 0) {
// receive file
+ // check packet size
+ if (sz < (1/*command*/ + 8/*token*/ + 2 /*filenameLength*/ + 1 /*filename*/)) ret;
u16 *filenameLength = (u16*)(receiveB + 9);
if (*filenameLength > 4096) ret;
+ // check that filenameLength is correct
+ if (sz < (1/*command*/ + 8/*token*/ + 2 /*filenameLength*/ + *filenameLength /*filename*/)) ret;
// receiveB + 11 = filename
cleanCharP(filename) = malloc(*filenameLength + 1);
filename[*filenameLength] = 0;
memcpy(filename, receiveB + 11, *filenameLength);
u32 bufi = 11 + *filenameLength;
+ // check that filemode and path are in the buffer
+ if (sz < (bufi + 2 /*filemode*/ + 2 /*pathLength*/)) ret;
u16 *filemode = (u16*)(receiveB + bufi);
bufi += 2;
u16 *pathLength = (u16*)(receiveB + bufi);
if (*pathLength > 4096) ret;
bufi += 2;
+ // check path length is correct and that filesize is in the buffer
+ if (sz < (bufi + *pathLength + 8 /*filesize*/)) ret;
cleanCharP(destPath) = null;
if (*pathLength) {
destPath = malloc(*pathLength + 1);
@@ -264,9 +277,27 @@ void saveReceivedData(void *receiveB, size_t sz) {
ret;
}
filenameInDestPath = yes;
+ // check if there is enough free space on disk
+ struct statvfs fs;
+ if (statvfs(dir, &fs) == -1) {
+ shperror("statvfs check free space");
+ ret;
+ }
+ if (*filesize >= fs.f_bsize * fs.f_bavail) {
+ logE("Not enough free space available in path %s", path);
+ }
}
//lv(filenameInDestPath);
if (not filenameInDestPath) {
+ // check if there is enough free space on disk
+ struct statvfs fs;
+ if (statvfs(path, &fs) == -1) {
+ shperror("statvfs check free space");
+ ret;
+ }
+ if (*filesize >= fs.f_bsize * fs.f_bavail) {
+ logE("Not enough free space available in path %s", path);
+ }
pErrorNULL(iAppendManyS(&path, "/", filename));
}
lv(path);
@@ -295,9 +326,14 @@ void saveReceivedData(void *receiveB, size_t sz) {
}
elif (*command == 1) {
// mkdir
+
+ // check packet size
+ if (sz < (1/*command*/ + 8/*token*/ + 2 /*filemode*/ + 2 /*pathLength*/ + 1 /*path*/)) ret;
u16 *filemode = (u16*)(receiveB + 9);
u16 *pathLength = (u16*)(receiveB + 11);
if (*pathLength > 4096) ret;
+ // check that pathLength is correct, path has to be at least 1 byte
+ if (sz < (1/*command*/ + 8/*token*/ + 2 /*filemode*/ + 2 /*pathLength*/ + *pathLength /*path*/)) ret;
cleanCharP(destPath) = malloc(*pathLength + 1);
memcpy(destPath, receiveB + 13, *pathLength);
destPath[*pathLength] = 0;
@@ -310,9 +346,13 @@ void saveReceivedData(void *receiveB, size_t sz) {
pError0(fileChmod(path, *filemode));
}
elif (*command == 2) {
+ // check packet size, sendFile path has to be at least 1 byte
+ if (sz < (1/*command*/ + 8/*token*/ + 2 /*sendFileLength*/ + 1 /*sendFile*/)) ret;
logD("send files to client");
u16 *sendFileLength = (u16*)(receiveB + 9);
if (*sendFileLength > 4096) ret;
+ // check that sendFileLength is correct
+ if (sz < (1/*command*/ + 8/*token*/ + 2 /*sendFileLength*/ + *sendFileLength)) ret;
cleanCharP(sendFile) = malloc(*sendFileLength + 1);
memcpy(sendFile, receiveB + 11, *sendFileLength);
sendFile[*sendFileLength] = 0;