Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unixsock v2.4 #3199

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 21 additions & 14 deletions scripts/suricatasc/src/suricatasc.py
Expand Up @@ -25,10 +25,10 @@
import select
import sys

SURICATASC_VERSION = "0.9"
SURICATASC_VERSION = "1.0"

VERSION = "0.1"
SIZE = 4096
VERSION = "0.2"
INC_SIZE = 1024

class SuricataException(Exception):
"""
Expand Down Expand Up @@ -86,19 +86,15 @@ def __init__(self, sck_path, verbose=False):

def json_recv(self):
cmdret = None
i = 0
data = ""
while i < 5:
i += 1
while True:
if sys.version < '3':
data += self.socket.recv(SIZE)
data += self.socket.recv(INC_SIZE)
else:
data += self.socket.recv(SIZE).decode('iso-8859-1')
try:
data += self.socket.recv(INC_SIZE).decode('iso-8859-1')
if data.endswith('\n'):
cmdret = json.loads(data)
break
except:
sleep(0.3)
return cmdret

def send_command(self, command, arguments = None):
Expand All @@ -111,10 +107,11 @@ def send_command(self, command, arguments = None):
cmdmsg['arguments'] = arguments
if self.verbose:
print("SND: " + json.dumps(cmdmsg))
cmdmsg_str = json.dumps(cmdmsg) + "\n"
if sys.version < '3':
self.socket.send(json.dumps(cmdmsg))
self.socket.send(cmdmsg_str)
else:
self.socket.send(bytes(json.dumps(cmdmsg), 'iso-8859-1'))
self.socket.send(bytes(cmdmsg_str, 'iso-8859-1'))

ready = select.select([self.socket], [], [], 600)
if ready[0]:
Expand Down Expand Up @@ -378,7 +375,17 @@ def interactive(self):
except SuricataCommandException as err:
print(err)
continue
cmdret = self.send_command(cmd, arguments)
try:
cmdret = self.send_command(cmd, arguments)
except IOError as err:
# try to reconnect and resend command
print("Connection lost, trying to reconnect")
try:
self.connect()
except SuricataNetException as err:
print("Can't reconnect to suricata socket, discarding command")
continue
cmdret = self.send_command(cmd, arguments)
#decode json message
if cmdret["return"] == "NOK":
print("Error:")
Expand Down
115 changes: 96 additions & 19 deletions src/unix-manager.c
@@ -1,4 +1,4 @@
/* Copyright (C) 2013 Open Information Security Foundation
/* Copyright (C) 2013-2018 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
Expand Down Expand Up @@ -78,6 +78,7 @@ typedef struct Task_ {
typedef struct UnixClient_ {
int fd;
MemBuffer *mbuf; /**< buffer for response construction */
int version;
TAILQ_ENTRY(UnixClient_) next;
} UnixClient;

Expand Down Expand Up @@ -278,7 +279,10 @@ static void UnixCommandClose(UnixCommand *this, int fd)
}

#define UNIX_PROTO_VERSION_LENGTH 200
#define UNIX_PROTO_VERSION "0.1"
#define UNIX_PROTO_VERSION_V1 "0.1"
#define UNIX_PROTO_V1 1
#define UNIX_PROTO_VERSION "0.2"
#define UNIX_PROTO_V2 2

static int UnixCommandSendJSONToClient(UnixClient *client, json_t *js)
{
Expand All @@ -297,6 +301,13 @@ static int UnixCommandSendJSONToClient(UnixClient *client, json_t *js)
return -1;
}

if (client->version > UNIX_PROTO_V1) {
if (MEMBUFFER_OFFSET(client->mbuf) + 1 >= MEMBUFFER_SIZE(client->mbuf)) {
MemBufferExpand(&client->mbuf, 1);
}
MemBufferWriteRaw(client->mbuf, "\n", 1);
}

if (send(client->fd, (const char *)MEMBUFFER_BUFFER(client->mbuf),
MEMBUFFER_OFFSET(client->mbuf), MSG_NOSIGNAL) == -1)
{
Expand Down Expand Up @@ -328,6 +339,7 @@ static int UnixCommandAccept(UnixCommand *this)
json_t *version;
json_error_t jerror;
int client;
int client_version;
int ret;
UnixClient *uclient = NULL;

Expand Down Expand Up @@ -374,7 +386,8 @@ static int UnixCommandAccept(UnixCommand *this)
}

/* check client version */
if (strcmp(json_string_value(version), UNIX_PROTO_VERSION) != 0) {
if ((strcmp(json_string_value(version), UNIX_PROTO_VERSION) != 0)
&& (strcmp(json_string_value(version), UNIX_PROTO_VERSION_V1) != 0)) {
SCLogInfo("Unix socket: invalid client version: \"%s\"",
json_string_value(version));
json_decref(client_msg);
Expand All @@ -383,6 +396,11 @@ static int UnixCommandAccept(UnixCommand *this)
} else {
SCLogDebug("Unix socket: client version: \"%s\"",
json_string_value(version));
if (strcmp(json_string_value(version), UNIX_PROTO_VERSION_V1) == 0) {
client_version = UNIX_PROTO_V1;
} else {
client_version = UNIX_PROTO_V2;
}
}

json_decref(client_msg);
Expand All @@ -402,6 +420,7 @@ static int UnixCommandAccept(UnixCommand *this)
return 0;
}
uclient->fd = client;
uclient->version = client_version;

if (UnixCommandSendJSONToClient(uclient, server_msg) != 0) {
SCLogWarning(SC_ERR_SOCKET, "Unable to send command");
Expand All @@ -416,7 +435,6 @@ static int UnixCommandAccept(UnixCommand *this)

/* client connected */
SCLogDebug("Unix socket: client connected");

TAILQ_INSERT_TAIL(&this->clients, uclient, next);
UnixCommandSetMaxFD(this);
return 1;
Expand Down Expand Up @@ -526,23 +544,82 @@ static void UnixCommandRun(UnixCommand * this, UnixClient *client)
{
char buffer[4096];
int ret;
ret = recv(client->fd, buffer, sizeof(buffer) - 1, 0);
if (ret <= 0) {
if (ret == 0) {
SCLogDebug("Unix socket: lost connection with client");
} else {
SCLogError(SC_ERR_SOCKET, "Unix socket: error on recv() from client: %s",
strerror(errno));
if (client->version <= UNIX_PROTO_V1) {
ret = recv(client->fd, buffer, sizeof(buffer) - 1, 0);
if (ret <= 0) {
if (ret == 0) {
SCLogDebug("Unix socket: lost connection with client");
} else {
SCLogError(SC_ERR_SOCKET, "Unix socket: error on recv() from client: %s",
strerror(errno));
}
UnixCommandClose(this, client->fd);
return;
}
if (ret >= (int)(sizeof(buffer)-1)) {
SCLogError(SC_ERR_SOCKET, "Command server: client command is too long, "
"disconnect him.");
UnixCommandClose(this, client->fd);
}
buffer[ret] = 0;
} else {
int try = 0;
int offset = 0;
int cmd_over = 0;
ret = recv(client->fd, buffer + offset, sizeof(buffer) - offset - 1, 0);
do {
if (ret <= 0) {
if (ret == 0) {
SCLogInfo("Unix socket: lost connection with client");
} else {
SCLogInfo("Unix socket: error on recv() from client: %s",
strerror(errno));
}
UnixCommandClose(this, client->fd);
return;
}
if (ret >= (int)(sizeof(buffer)- offset - 1)) {
SCLogInfo("Command server: client command is too long, "
"disconnect him.");
UnixCommandClose(this, client->fd);
}
if (buffer[ret - 1] == '\n') {
buffer[ret-1] = 0;
cmd_over = 1;
} else {
struct timeval tv;
fd_set select_set;
offset += ret;
do {
FD_ZERO(&select_set);
FD_SET(client->fd, &select_set);
tv.tv_sec = 0;
tv.tv_usec = 200 * 1000;
try++;
ret = select(client->fd, &select_set, NULL, NULL, &tv);
/* catch select() error */
if (ret == -1) {
/* Signal was caught: just ignore it */
if (errno != EINTR) {
SCLogInfo("Unix socket: lost connection with client");
UnixCommandClose(this, client->fd);
return;
}
}
} while (ret == 0 && try < 3);
if (ret > 0) {
ret = recv(client->fd, buffer + offset,
sizeof(buffer) - offset - 1, 0);
}
}
} while (try < 3 && cmd_over == 0);

if (try == 3 && cmd_over == 0) {
SCLogInfo("Unix socket: imcomplete client message, closing connection");
UnixCommandClose(this, client->fd);
return;
}
UnixCommandClose(this, client->fd);
return;
}
if (ret >= (int)(sizeof(buffer)-1)) {
SCLogInfo("Command server: client command is too long, "
"disconnect him.");
UnixCommandClose(this, client->fd);
}
buffer[ret] = 0;
UnixCommandExecute(this, buffer, client);
}

Expand Down