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):
"""
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):
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]:
-/* 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
typedef struct UnixClient_ {
int fd;
MemBuffer *mbuf; /**< buffer for response construction */
+ int version;
TAILQ_ENTRY(UnixClient_) next;
} UnixClient;
}
#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)
{
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)
{
json_t *version;
json_error_t jerror;
int client;
+ int client_version;
int ret;
UnixClient *uclient = NULL;
}
/* 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);
} 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);
return 0;
}
uclient->fd = client;
+ uclient->version = client_version;
if (UnixCommandSendJSONToClient(uclient, server_msg) != 0) {
SCLogWarning(SC_ERR_SOCKET, "Unable to send command");
/* client connected */
SCLogDebug("Unix socket: client connected");
-
TAILQ_INSERT_TAIL(&this->clients, uclient, next);
UnixCommandSetMaxFD(this);
return 1;
{
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);
}