aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2020-06-19 18:03:08 +0200
committerTom Smeding <tom.smeding@gmail.com>2020-06-19 18:03:08 +0200
commit7a8d4d0934cb51c8ad7f7af84669bb0197c7b89e (patch)
treebaee714d2e4e2c9558b2496576e47fbc63ca9d67
parentdc8a5e4b433c2e6142060e4701fd456082461e72 (diff)
Zero incoming passwords in memory using libsodium
-rw-r--r--Makefile6
-rw-r--r--command.c167
-rw-r--r--main.c5
3 files changed, 101 insertions, 77 deletions
diff --git a/Makefile b/Makefile
index 03ad55b..0ed32b2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,8 @@
CC = gcc
-CFLAGS = -Wall -Wextra -std=c11 -g -fwrapv -D_DEFAULT_SOURCE
-LDFLAGS = -lsqlite3 -ldl
+CFLAGS = -Wall -Wextra -std=c11 -g -O2 -fwrapv -D_DEFAULT_SOURCE
+LDFLAGS = -ldl
+CFLAGS += $(shell pkg-config --cflags sqlite3 libsodium)
+LDFLAGS += $(shell pkg-config --libs sqlite3 libsodium)
TARGETS = tomsg_server
diff --git a/command.c b/command.c
index e4d75d3..04e9fe0 100644
--- a/command.c
+++ b/command.c
@@ -5,6 +5,7 @@
#include <errno.h>
#include <sys/time.h>
#include <sys/socket.h>
+#include <sodium.h>
#include "broadcast.h"
#include "command.h"
#include "db.h"
@@ -15,17 +16,31 @@
#include "util.h"
-static bool cmd_register(struct conn_data *data,const char *tag,const char **args){
+struct cmd_retval{
+ bool socket_close;
+ bool memzero;
+};
+#define RET_OK ((struct cmd_retval){.socket_close=false,.memzero=false})
+#define RET_CLOSE(close_) ((struct cmd_retval){.socket_close=(close_),.memzero=false})
+#define RET_MEMZERO ((struct cmd_retval){.socket_close=false,.memzero=true})
+#define RET_MEMZERO_CLOSE(close_) ((struct cmd_retval){.socket_close=(close_),.memzero=true})
+
+static struct cmd_retval cmd_register(struct conn_data *data,const char *tag,const char **args){
i64 userid=db_find_user(args[0]);
if(userid!=-1){
net_send_error(data->fd,tag,"Username already exists");
- return false;
+ return RET_OK;
}
db_create_user(args[0],args[1]);
- return net_send_ok(data->fd,tag);
+ return RET_MEMZERO_CLOSE(net_send_ok(data->fd,tag));
}
-static bool cmd_login(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_login(struct conn_data *data,const char *tag,const char **args){
+ // TODO: use sodium_mlock correctly for the password
+
+ // Note: this function has exactly ONE return point, so that it is easier
+ // to see that we indeed return MEMZERO.
+
i64 userid=db_find_user(args[0]);
if(userid==-1){
net_send_error(data->fd,tag,"User not found");
@@ -34,28 +49,28 @@ static bool cmd_login(struct conn_data *data,const char *tag,const char **args){
broadcast_online_change(data->userid);
data->userid=-1;
}
- return false;
- }
- char *pass=db_get_pass(userid);
- bool success=strcmp(args[1],pass)==0;
- free(pass);
- if(data->userid!=-1){
- userdata_unregister(data->userid,data->fd);
- broadcast_online_change(data->userid);
- }
- if(success){
- data->userid=userid;
- userdata_register(userid,data->fd);
- net_send_ok(data->fd,tag);
- broadcast_online_change(userid);
} else {
- data->userid=-1;
- net_send_error(data->fd,tag,"Incorrect password");
+ char *pass=db_get_pass(userid);
+ bool success=strcmp(args[1],pass)==0;
+ free(pass);
+ if(data->userid!=-1){
+ userdata_unregister(data->userid,data->fd);
+ broadcast_online_change(data->userid);
+ }
+ if(success){
+ data->userid=userid;
+ userdata_register(userid,data->fd);
+ net_send_ok(data->fd,tag);
+ broadcast_online_change(userid);
+ } else {
+ data->userid=-1;
+ net_send_error(data->fd,tag,"Incorrect password");
+ }
}
- return false;
+ return RET_MEMZERO;
}
-static bool cmd_logout(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_logout(struct conn_data *data,const char *tag,const char **args){
(void)args;
if(data->userid!=-1){
userdata_unregister(data->userid,data->fd);
@@ -63,19 +78,19 @@ static bool cmd_logout(struct conn_data *data,const char *tag,const char **args)
data->userid=-1;
}
net_send_ok(data->fd,tag);
- return false;
+ return RET_OK;
}
-static bool cmd_list_rooms(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_list_rooms(struct conn_data *data,const char *tag,const char **args){
(void)args;
if(data->userid==-1){
net_send_error(data->fd,tag,"Not logged in");
- return false;
+ return RET_OK;
}
struct db_room_list rl=db_list_rooms(data->userid);
if(rl.count<=0){
db_nullify_room_list(rl);
- return net_send_list(data->fd,tag,0,NULL);
+ return RET_CLOSE(net_send_list(data->fd,tag,0,NULL));
}
const char *names[rl.count];
for(i64 i=0;i<rl.count;i++){
@@ -83,28 +98,28 @@ static bool cmd_list_rooms(struct conn_data *data,const char *tag,const char **a
}
bool closed=net_send_list(data->fd,tag,rl.count,names);
db_nullify_room_list(rl);
- return closed;
+ return RET_CLOSE(closed);
}
-static bool cmd_list_members(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_list_members(struct conn_data *data,const char *tag,const char **args){
if(data->userid==-1){
net_send_error(data->fd,tag,"Not logged in");
- return false;
+ return RET_OK;
}
i64 roomid=db_find_room(args[0]);
if(roomid==-1){
net_send_error(data->fd,tag,"Room not found");
- return false;
+ return RET_OK;
}
if(!db_is_member(roomid,data->userid)){
net_send_error(data->fd,tag,"Not in that room");
- return false;
+ return RET_OK;
}
struct db_user_list ul=db_list_members(roomid);
if(ul.count<=0){
db_nullify_user_list(ul);
- return net_send_list(data->fd,tag,0,NULL);
+ return RET_CLOSE(net_send_list(data->fd,tag,0,NULL));
}
const char *names[ul.count];
for(i64 i=0;i<ul.count;i++){
@@ -112,49 +127,49 @@ static bool cmd_list_members(struct conn_data *data,const char *tag,const char *
}
bool closed=net_send_list(data->fd,tag,ul.count,names);
db_nullify_user_list(ul);
- return closed;
+ return RET_CLOSE(closed);
}
-static bool cmd_create_room(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_create_room(struct conn_data *data,const char *tag,const char **args){
(void)args;
if(data->userid==-1){
net_send_error(data->fd,tag,"Not logged in");
- return false;
+ return RET_OK;
}
userdata_mark_active(data->userid,data->fd,true);
struct db_name_id room=db_create_room();
db_add_member(room.id,data->userid);
bool closed=net_send_name(data->fd,tag,room.name);
db_nullify_name_id(room);
- return closed;
+ return RET_CLOSE(closed);
}
-static bool cmd_invite(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_invite(struct conn_data *data,const char *tag,const char **args){
if(data->userid==-1){
net_send_error(data->fd,tag,"Not logged in");
- return false;
+ return RET_OK;
}
userdata_mark_active(data->userid,data->fd,true);
const char *roomname=args[0];
i64 roomid=db_find_room(roomname);
if(roomid==-1){
net_send_error(data->fd,tag,"Room not found");
- return false;
+ return RET_OK;
}
i64 user2=db_find_user(args[1]);
if(user2==-1){
net_send_error(data->fd,tag,"User not found");
- return false;
+ return RET_OK;
}
if(!db_is_member(roomid,data->userid)){
net_send_error(data->fd,tag,"Not in that room");
- return false;
+ return RET_OK;
}
if(db_is_member(roomid,user2)){
net_send_error(data->fd,tag,"User already in that room");
- return false;
+ return RET_OK;
}
db_add_member(roomid,user2);
@@ -187,13 +202,13 @@ static bool cmd_invite(struct conn_data *data,const char *tag,const char **args)
free(joinbuf);
free(invitebuf);
- return net_send_ok(data->fd,tag);
+ return RET_CLOSE(net_send_ok(data->fd,tag));
}
-static bool cmd_send(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_send(struct conn_data *data,const char *tag,const char **args){
if(data->userid==-1){
net_send_error(data->fd,tag,"Not logged in");
- return false;
+ return RET_OK;
}
userdata_mark_active(data->userid,data->fd,true);
const char *roomname=args[0];
@@ -201,11 +216,11 @@ static bool cmd_send(struct conn_data *data,const char *tag,const char **args){
i64 roomid=db_find_room(roomname);
if(roomid==-1){
net_send_error(data->fd,tag,"Room not found");
- return false;
+ return RET_OK;
}
if(!db_is_member(roomid,data->userid)){
net_send_error(data->fd,tag,"Not in that room");
- return false;
+ return RET_OK;
}
i64 timestamp=make_timestamp();
@@ -236,10 +251,10 @@ static bool cmd_send(struct conn_data *data,const char *tag,const char **args){
db_nullify_user_list(members);
free(pushbuf);
- return closed;
+ return RET_CLOSE(closed);
}
-static bool history_cmd_helper(
+static struct cmd_retval history_cmd_helper(
struct conn_data *data,const char *tag,const char **args,
const char *cmdname,i64 beforeid){
char *endp;
@@ -247,22 +262,22 @@ static bool history_cmd_helper(
if(args[1][0]=='\0'||*endp!='\0'||nrequested<0){
debug("Connection fd=%d sent an invalid number for '%s': '%s'",
data->fd,cmdname,args[1]);
- return true;
+ return RET_CLOSE(true);
}
if(data->userid==-1){
net_send_error(data->fd,tag,"Not logged in");
- return false;
+ return RET_OK;
}
const char *roomname=args[0];
i64 roomid=db_find_room(roomname);
if(roomid==-1){
net_send_error(data->fd,tag,"Room not found");
- return false;
+ return RET_OK;
}
if(!db_is_member(roomid,data->userid)){
net_send_error(data->fd,tag,"Not in that room");
- return false;
+ return RET_OK;
}
struct db_message_list ml=db_get_messages_before(roomid,nrequested,beforeid);
@@ -273,7 +288,7 @@ static bool history_cmd_helper(
if(closed){
db_nullify_message_list(ml);
- return true;
+ return RET_CLOSE(true);
}
for(i64 i=ml.count-1;i>=0;i--){
@@ -287,73 +302,73 @@ static bool history_cmd_helper(
}
db_nullify_message_list(ml);
- return closed;
+ return RET_CLOSE(closed);
}
-static bool cmd_history(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_history(struct conn_data *data,const char *tag,const char **args){
return history_cmd_helper(data,tag,args,"history",-1);
}
-static bool cmd_history_before(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_history_before(struct conn_data *data,const char *tag,const char **args){
char *endp;
i64 beforeid=strtoll(args[2],&endp,10);
if(args[2][0]=='\0'||*endp!='\0'){
debug("Connection fd=%d sent an invalid id for 'history_before': '%s'",
data->fd,args[2]);
- return true;
+ return RET_CLOSE(true);
}
if(beforeid<0)beforeid=INT64_MAX;
return history_cmd_helper(data,tag,args,"history_before",beforeid);
}
-static bool cmd_ping(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_ping(struct conn_data *data,const char *tag,const char **args){
(void)args;
- return net_send_pong(data->fd,tag);
+ return RET_CLOSE(net_send_pong(data->fd,tag));
}
-static bool cmd_is_online(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_is_online(struct conn_data *data,const char *tag,const char **args){
i64 userid=db_find_user(args[0]);
if(userid==-1){
net_send_error(data->fd,tag,"User not found");
- return false;
+ return RET_OK;
}
i64 nfds;
(void)userdata_online(userid,&nfds);
- return net_send_number(data->fd,tag,nfds);
+ return RET_CLOSE(net_send_number(data->fd,tag,nfds));
}
-static bool cmd_firebase_token(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_firebase_token(struct conn_data *data,const char *tag,const char **args){
if(data->userid==-1){
net_send_error(data->fd,tag,"Not logged in");
- return false;
+ return RET_OK;
}
db_add_token(data->userid,args[0]);
- return net_send_ok(data->fd,tag);
+ return RET_CLOSE(net_send_ok(data->fd,tag));
}
-static bool cmd_delete_firebase_token(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_delete_firebase_token(struct conn_data *data,const char *tag,const char **args){
if(data->userid==-1){
net_send_error(data->fd,tag,"Not logged in");
- return false;
+ return RET_OK;
}
db_delete_token(data->userid,args[0]);
- return net_send_ok(data->fd,tag);
+ return RET_CLOSE(net_send_ok(data->fd,tag));
}
-static bool cmd_user_active(struct conn_data *data,const char *tag,const char **args){
+static struct cmd_retval cmd_user_active(struct conn_data *data,const char *tag,const char **args){
if(data->userid==-1){
net_send_error(data->fd,tag,"Not logged in");
- return false;
+ return RET_OK;
}
char *endp;
i64 active=strtoll(args[0],&endp,10);
if(args[0][0]=='\0'||*endp!='\0'||active<0){
debug("Connection fd=%d sent an invalid number for 'user_active': '%s'",data->fd,args[0]);
- return true;
+ return RET_CLOSE(true);
}
userdata_mark_active(data->userid,data->fd,active>0);
- return net_send_ok(data->fd,tag);
+ return RET_CLOSE(net_send_ok(data->fd,tag));
}
@@ -361,7 +376,7 @@ struct cmd_info{
const char *cmdname;
int nargs;
bool longlast; // whether the last argument should span the rest of the input line
- bool (*handler)(struct conn_data *data,const char *tag,const char **args);
+ struct cmd_retval (*handler)(struct conn_data *data,const char *tag,const char **args);
};
static const struct cmd_info commands[]={
@@ -437,5 +452,7 @@ bool handle_input_line(struct conn_data *data,char *line,size_t linelen){
return true;
}
- return commands[cmdi].handler(data,tag,(const char**)args);
+ struct cmd_retval retval=commands[cmdi].handler(data,tag,(const char**)args);
+ if(retval.memzero)sodium_memzero(line,linelen);
+ return retval.socket_close;
}
diff --git a/main.c b/main.c
index 6388fe2..497f66e 100644
--- a/main.c
+++ b/main.c
@@ -8,6 +8,7 @@
#include <netinet/in.h>
#include <errno.h>
#include <assert.h>
+#include <sodium.h>
#include "broadcast.h"
#include "command.h"
#include "conn_data.h"
@@ -157,6 +158,10 @@ void signal_handler(int sig){
int main(int argc,char **argv){
srandomdev();
+ if(sodium_init()<0){
+ fprintf(stderr,"Could not initialise libsodium!\n");
+ return 1;
+ }
signal(SIGPIPE,signal_handler);