diff --git a/etc/rules/ossec_rules.xml b/etc/rules/ossec_rules.xml
index a580298ad..01cfba041 100755
--- a/etc/rules/ossec_rules.xml
+++ b/etc/rules/ossec_rules.xml
@@ -131,6 +131,13 @@
OSSEC process monitoring rules.
process_monitor,
+
+
+ 500
+ Duplicated IP
+ Trying to add an agent with duplicated IP.
+ pci_dss_10.6.1,
+
530
diff --git a/src/Makefile b/src/Makefile
index ed6343c33..72fc8482e 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -7,6 +7,7 @@ EXTERNAL_LUA=external/lua/
EXTERNAL_ZLIB=external/zlib-1.2.8/
LUA_PLAT=posix
MAXAGENTS?=2048
+REUSE_ID?=no
# XXX Becareful NO EXTRA Spaces here
PREFIX?=/var/ossec
PG_CONFIG?=pg_config
@@ -39,6 +40,10 @@ DEFINES+=-DGROUPGLOBAL=\"${OSSEC_GROUP}\"
DEFINES+=-DMAILUSER=\"${OSSEC_USER_MAIL}\"
DEFINES+=-D${uname_S}
+ifneq (,$(filter ${REUSE_ID},yes y Y 1))
+ DEFINES+=-DREUSE_ID
+endif
+
OSSEC_LDFLAGS=${LDFLAGS} -lm
ifneq (${TARGET},winagent)
@@ -468,6 +473,8 @@ endif
install -d -m 0750 -o ${OSSEC_USER} -g ${OSSEC_GROUP} ${PREFIX}/queue/agentless
install -d -m 0750 -o ${OSSEC_USER_REM} -g ${OSSEC_GROUP} ${PREFIX}/queue/rids
+ install -d -m 0550 -o root -g ${OSSEC_GROUP} ${PREFIX}/backup
+ install -d -m 0750 -o ${OSSEC_USER} -g ${OSSEC_GROUP} ${PREFIX}/backup/agents
install -m 0640 -o root -g ${OSSEC_GROUP} ../etc/decoder.xml ${PREFIX}/etc/
@@ -491,6 +498,7 @@ help: failtarget
@echo " make DEBUG=1 Build with symbols and without optimization"
@echo " make PREFIX=/path Install OSSEC to '/path'. Defaults to /var/ossec"
@echo " make MAXAGENTS=NUMBER Set the number of maximum agents to NUMBER. Defaults to 2048"
+ @echo " make REUSE_ID=yes Enables agent ID re-use"
@echo
@echo "Database options: "
@echo " make DATABASE=mysql Build with MYSQL Support"
@@ -515,6 +523,7 @@ settings:
@echo " DEBUGAD ${DEBUGAD}"
@echo " PREFIX: ${PREFIX}"
@echo " MAXAGENTS: ${MAXAGENTS}"
+ @echo " REUSE_ID: ${REUSE_ID}"
@echo " DATABASE: ${DATABASE}"
@echo " ONEWAY: ${ONEWAY}"
@echo " CLEANFULL: ${CLEANFULL}"
diff --git a/src/addagent/manage_agents.c b/src/addagent/manage_agents.c
index 2e05bb280..e497c3741 100644
--- a/src/addagent/manage_agents.c
+++ b/src/addagent/manage_agents.c
@@ -364,7 +364,9 @@ int remove_agent()
user_input = getenv("OSSEC_ACTION_CONFIRMED");
if (user_input == NULL) {
user_input = read_from_user();
- } else {
+ OS_BackupAgentInfo(id_exist);
+
+ } else {
printf("%s\n", user_input);
}
diff --git a/src/addagent/manage_agents.h b/src/addagent/manage_agents.h
index c376a0265..b51b4ff77 100644
--- a/src/addagent/manage_agents.h
+++ b/src/addagent/manage_agents.h
@@ -33,8 +33,12 @@ int OS_IsValidName(const char *u_name);
int OS_IsValidID(const char *id);
int IDExist(const char *id);
int NameExist(const char *u_name);
+char *IPExist(const char *u_name);
char *getFullnameById(const char *id);
char *OS_AddNewAgent(const char *name, const char *ip, const char *id);
+int OS_RemoveAgent(const char *id);
+double OS_AgentAntiquity(const char *id);
+void OS_BackupAgentInfo(const char *id);
void FormatID(char *id);
/* Print available agents */
diff --git a/src/addagent/validate.c b/src/addagent/validate.c
index c57de1150..805430352 100644
--- a/src/addagent/validate.c
+++ b/src/addagent/validate.c
@@ -7,11 +7,19 @@
* Foundation
*/
+#include
#include "manage_agents.h"
#include "os_crypto/md5/md5_op.h"
/* Global variables */
fpos_t fp_pos;
+#ifdef WIN32
+#define chmod(x,y)
+#define mkdir(x,y) 0
+#define link(x,y)
+#define difftime(x,y) 0
+#endif
+
char *OS_AddNewAgent(const char *name, const char *ip, const char *id)
@@ -23,11 +31,9 @@ char *OS_AddNewAgent(const char *name, const char *ip, const char *id)
char str2[STR_SIZE + 1];
char *muname;
char *finals;
-
char nid[9] = { '\0' }, nid_p[9] = { '\0' };
srandom_init();
-
muname = getuname();
snprintf(str1, STR_SIZE, "%d%s%d%s", (int)time(0), name, (int)random(), muname);
@@ -66,7 +72,7 @@ char *OS_AddNewAgent(const char *name, const char *ip, const char *id)
id = nid;
}
- fp = fopen(KEYSFILE_PATH, "a");
+ fp = fopen(AUTH_FILE, "a");
if (!fp) {
return (NULL);
}
@@ -83,6 +89,69 @@ char *OS_AddNewAgent(const char *name, const char *ip, const char *id)
return (finals);
}
+int OS_RemoveAgent(const char *u_id) {
+ FILE *fp;
+ int id_exist;
+
+ id_exist = IDExist(u_id);
+
+ if (!id_exist)
+ return 0;
+
+ fp = fopen(isChroot() ? AUTH_FILE : KEYSFILE_PATH, "r+");
+
+ if (!fp)
+ return 0;
+
+
+#ifdef REUSE_ID
+ long fp_seek;
+ size_t fp_read;
+ char *buffer;
+ char buf_discard[OS_BUFFER_SIZE];
+ struct stat fp_stat;
+
+ if (stat(AUTH_FILE, &fp_stat) < 0) {
+ fclose(fp);
+ return 0;
+ }
+
+ buffer = malloc(fp_stat.st_size);
+ if (!buffer) {
+ fclose(fp);
+ return 0;
+ }
+
+ fsetpos(fp, &fp_pos);
+ fp_seek = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ fp_read = fread(buffer, sizeof(char), fp_seek, fp);
+ fgets(buf_discard, OS_BUFFER_SIZE - 1, fp);
+
+ if (!feof(fp))
+ fp_read += fread(buffer + fp_read, sizeof(char), fp_stat.st_size, fp);
+
+ fclose(fp);
+ fp = fopen(AUTH_FILE, "w");
+
+ if (!fp) {
+ free(buffer);
+ return 0;
+ }
+
+ fwrite(buffer, sizeof(char), fp_read, fp);
+
+#else
+ /* Remove the agent, but keep the id */
+ fsetpos(fp, &fp_pos);
+ fprintf(fp, "%s #*#*#*#*#*#*#*#*#*#*#", u_id);
+#endif
+ fclose(fp);
+
+ /* Remove counter for ID */
+ OS_RemoveCounter(u_id);
+ return 1;
+}
int OS_IsValidID(const char *id)
{
@@ -95,6 +164,7 @@ int OS_IsValidID(const char *id)
id_len = strlen(id);
+
/* Check ID length, it should contain max. 8 characters */
if (id_len > 8) {
return (0);
@@ -311,6 +381,82 @@ int NameExist(const char *u_name)
return (0);
}
+/* Returns the ID of an agent, or NULL if not found */
+char *IPExist(const char *u_ip)
+{
+ FILE *fp;
+ char *name, *ip, *pass;
+ char line_read[FILE_SIZE + 1];
+ line_read[FILE_SIZE] = '\0';
+
+ if (!(u_ip && strncmp(u_ip, "any", 3)))
+ return NULL;
+
+ if (isChroot())
+ fp = fopen(AUTH_FILE, "r");
+ else
+ fp = fopen(KEYSFILE_PATH, "r");
+
+ if (!fp)
+ return NULL;
+
+ fseek(fp, 0, SEEK_SET);
+ fgetpos(fp, &fp_pos);
+
+ while (fgets(line_read, FILE_SIZE - 1, fp) != NULL) {
+ if (line_read[0] == '#') {
+ continue;
+ }
+
+ name = strchr(line_read, ' ');
+ if (name) {
+ name++;
+
+ if (*name == '#') {
+ continue;
+ }
+
+ ip = strchr(name, ' ');
+ if (ip) {
+ ip++;
+
+ pass = strchr(ip, ' ');
+ if (pass) {
+ *pass = '\0';
+ if (strcmp(u_ip, ip) == 0) {
+ fclose(fp);
+ name[-1] = '\0';
+ return strdup(line_read);
+ }
+ }
+ }
+ }
+
+ fgetpos(fp, &fp_pos);
+ }
+
+ fclose(fp);
+ return NULL;
+}
+
+/* Returns the number of seconds since last agent connection, or -1 if error. */
+double OS_AgentAntiquity(const char *id)
+{
+ struct stat file_stat;
+ char file_name[OS_FLSIZE];
+ char *full_name = getFullnameById(id);
+
+ if (!full_name)
+ return -1;
+
+ snprintf(file_name, OS_FLSIZE - 1, "%s/%s", AGENTINFO_DIR, full_name);
+
+ if (stat(file_name, &file_stat) < 0)
+ return -1;
+
+ return difftime(time(NULL), file_stat.st_mtime);
+}
+
/* Print available agents */
int print_agents(int print_status, int active_only, int csv_output)
{
@@ -435,3 +581,95 @@ void FormatID(char *id) {
}
}
}
+
+/* Backup agent information before force deleting */
+void OS_BackupAgentInfo(const char *id)
+{
+ char path_backup[OS_FLSIZE];
+ char path_src[OS_FLSIZE];
+ char path_dst[OS_FLSIZE];
+ char timestamp[40];
+ char *name = getFullnameById(id);
+ char *ip;
+ time_t timer = time(NULL);
+
+ if (!name) {
+ merror("%s: ERROR: Agent id %s not found.", ARGV0, id);
+ return;
+ }
+
+ snprintf(path_src, OS_FLSIZE, "%s/%s", AGENTINFO_DIR, name);
+
+ ip = strchr(name, '-');
+ *(ip++) = 0;
+
+ strftime(timestamp, 40, "%Y-%m-%d %H:%M:%S", localtime(&timer));
+ snprintf(path_backup, OS_FLSIZE, "%s/%s-%s %s", AGNBACKUP_DIR, name, ip, timestamp);
+
+ if (mkdir(path_backup, 0750) >= 0) {
+ /* agent-info */
+ snprintf(path_dst, OS_FLSIZE, "%s/syscheck", path_backup);
+ link(path_src, path_dst);
+
+ snprintf(path_src, OS_FLSIZE, "%s/.(%s) %s->syscheck.cpt", SYSCHECK_DIR, name, ip);
+ snprintf(path_dst, OS_FLSIZE, "%s/syscheck", path_backup);
+ link(path_src, path_dst);
+
+ snprintf(path_src, OS_FLSIZE, "%s/.(%s) %s->syscheck.cpt", SYSCHECK_DIR, name, ip);
+ snprintf(path_dst, OS_FLSIZE, "%s/syscheck.cpt", path_backup);
+ link(path_src, path_dst);
+
+ snprintf(path_src, OS_FLSIZE, "%s/(%s) %s->syscheck-registry", SYSCHECK_DIR, name, ip);
+ snprintf(path_dst, OS_FLSIZE, "%s/syscheck-registry", path_backup);
+ link(path_src, path_dst);
+
+ snprintf(path_src, OS_FLSIZE, "%s/.(%s) %s->syscheck-registry.cpt", SYSCHECK_DIR, name, ip);
+ snprintf(path_dst, OS_FLSIZE, "%s/syscheck-registry.cpt", path_backup);
+ link(path_src, path_dst);
+
+ /* rootcheck */
+ snprintf(path_src, OS_FLSIZE, "%s/(%s) %s->rootcheck", ROOTCHECK_DIR, name, ip);
+ snprintf(path_dst, OS_FLSIZE, "%s/rootcheck", path_backup);
+ link(path_src, path_dst);
+ } else {
+ merror("%s: ERROR: Couldn't create backup directory.", ARGV0);
+ }
+
+ free(name);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/client-agent/agentd.c b/src/client-agent/agentd.c
index 347c2d2ab..0d305dc75 100644
--- a/src/client-agent/agentd.c
+++ b/src/client-agent/agentd.c
@@ -53,6 +53,7 @@ void AgentdStart(const char *dir, int uid, int gid, const char *user, const char
maxfd = agt->m_queue;
agt->sock = -1;
+ agt->sock_r = -1;
/* Create PID file */
if (CreatePID(ARGV0, getpid()) < 0) {
diff --git a/src/client-agent/config.c b/src/client-agent/config.c
index a16d279fe..2350c5b50 100644
--- a/src/client-agent/config.c
+++ b/src/client-agent/config.c
@@ -30,6 +30,7 @@ int ClientConf(const char *cfgfile)
agt->rip_id = 0;
agt->execdq = 0;
agt->profile = NULL;
+ agt->protocol = UDP_PROTO;
modules |= CCLIENT;
@@ -39,4 +40,3 @@ int ClientConf(const char *cfgfile)
return (1);
}
-
diff --git a/src/client-agent/receiver-win.c b/src/client-agent/receiver-win.c
index d55c116f1..3233c8e0a 100644
--- a/src/client-agent/receiver-win.c
+++ b/src/client-agent/receiver-win.c
@@ -20,9 +20,11 @@
void *receiver_thread(__attribute__((unused)) void *none)
{
int recv_b;
+ int sock;
char file[OS_SIZE_1024 + 1];
char buffer[OS_MAXSTR + 1];
+ char srcip[IPSIZE + 1];
char cleartext[OS_MAXSTR + 1];
char *tmp_msg;
@@ -66,8 +68,14 @@ void *receiver_thread(__attribute__((unused)) void *none)
continue;
}
+ if (agt->protocol == TCP_PROTO) {
+ OS_AcceptTCP(agt->sock, srcip, IPSIZE);
+ } else {
+ sock = agt->sock;
+ }
+
/* Read until no more messages are available */
- while ((recv_b = recv(agt->sock, buffer, OS_SIZE_1024, 0)) > 0) {
+ while ((recv_b = recv(sock, buffer, OS_SIZE_1024, 0)) > 0) {
/* Id of zero -- only one key allowed */
tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b - 1);
if (tmp_msg == NULL) {
@@ -214,6 +222,10 @@ void *receiver_thread(__attribute__((unused)) void *none)
ARGV0);
}
}
+
+ if (agt->protocol == TCP_PROTO) {
+ close(sock);
+ }
}
/* Clean up */
diff --git a/src/client-agent/receiver.c b/src/client-agent/receiver.c
index 50744cf2e..193e61b2b 100644
--- a/src/client-agent/receiver.c
+++ b/src/client-agent/receiver.c
@@ -27,13 +27,21 @@ void *receive_msg()
ssize_t recv_b;
char buffer[OS_MAXSTR + 1];
char cleartext[OS_MAXSTR + 1];
+ char srcip[IPSIZE + 1];
char *tmp_msg;
+ int sock;
memset(cleartext, '\0', OS_MAXSTR + 1);
memset(buffer, '\0', OS_MAXSTR + 1);
+ if (agt->protocol == TCP_PROTO) {
+ sock = OS_AcceptTCP(agt->sock, srcip, IPSIZE);
+ } else {
+ sock = agt->sock;
+ }
+
/* Read until no more messages are available */
- while ((recv_b = recv(agt->sock, buffer, OS_SIZE_1024, MSG_DONTWAIT)) > 0) {
+ while ((recv_b = recv(sock, buffer, OS_SIZE_1024, MSG_DONTWAIT)) > 0) {
buffer[recv_b] = '\0';
tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b - 1);
@@ -193,6 +201,10 @@ void *receive_msg()
}
}
+ if (agt->protocol == TCP_PROTO) {
+ close(sock);
+ }
+
return (NULL);
}
diff --git a/src/client-agent/sendmsg.c b/src/client-agent/sendmsg.c
index 454c2e714..041d34c62 100644
--- a/src/client-agent/sendmsg.c
+++ b/src/client-agent/sendmsg.c
@@ -17,7 +17,7 @@ int send_msg(int agentid, const char *msg)
{
size_t msg_size;
char crypt_msg[OS_MAXSTR + 1];
-
+
msg_size = CreateSecMSG(&keys, msg, crypt_msg, agentid);
if (msg_size == 0) {
merror(SEC_ERROR, ARGV0);
@@ -25,12 +25,32 @@ int send_msg(int agentid, const char *msg)
}
/* Send msg_size of crypt_msg */
- if (OS_SendUDPbySize(agt->sock, msg_size, crypt_msg) < 0) {
- merror(SEND_ERROR, ARGV0, "server");
- sleep(1);
- return (-1);
+ if (agt->protocol == UDP_PROTO) {
+ if (OS_SendUDPbySize(agt->sock, msg_size, crypt_msg) < 0) {
+ merror(SEND_ERROR, ARGV0, "server");
+ sleep(1);
+ return (-1);
+ }
+ } else {
+ if (agt->sock_r >= 0) {
+ close(agt->sock_r);
+ }
+
+ agt->sock_r = OS_ConnectTCP(agt->port, (const) (char) *strchr(agt->rip[agt->rip_id], ':') != NULL);
+
+
+ if (agt->sock_r < 0) {
+ merror(CONNS_ERROR, ARGV0, agt->rip[agt->rip_id]);
+ sleep(1);
+ return -1;
+ }
+
+ if (OS_SendTCPbySize(agt->sock_r, msg_size, crypt_msg) < 0) {
+ merror(SEND_ERROR, ARGV0, "server");
+ sleep(1);
+ return (-1);
+ }
}
return (0);
}
-
diff --git a/src/client-agent/start_agent.c b/src/client-agent/start_agent.c
index 9c40bd000..02340833a 100644
--- a/src/client-agent/start_agent.c
+++ b/src/client-agent/start_agent.c
@@ -37,7 +37,6 @@ int connect_server(int initial_id)
agt->rip[rc],
agt->port);
}
-
}
while (agt->rip[rc]) {
@@ -46,6 +45,18 @@ int connect_server(int initial_id)
verbose("%s: INFO: Trying to connect to server %s, port %s.", ARGV0,
agt->rip[rc],
agt->port);
+ if (agt->protocol == UDP_PROTO) {
+ const char *tmp_str = strchr(tmp_str, ':');
+ if (tmp_str != NULL) {
+ agt->sock = OS_ConnectUDP(agt->port, tmp_str);
+ }
+ agt->sock_r = agt->sock;
+ } else {
+ const char *tmp_str = strchr(tmp_str, ':');
+ if (tmp_str != NULL){
+ agt->sock = OS_ConnectTCP(agt->port, tmp_str);
+ }
+ }
agt->sock = OS_ConnectUDP(agt->port, agt->rip[rc]);
@@ -79,6 +90,20 @@ int connect_server(int initial_id)
#endif
agt->rip_id = rc;
+
+ if (agt->protocol == TCP_PROTO) {
+ close(agt->sock);
+ if(!agt->lip || strchr(agt->lip, ':') != NULL){
+ agt->sock = OS_Bindporttcp(agt->port, agt->lip);
+ }
+ if (agt->sock < 0) {
+ merror(CONNS_ERROR, ARGV0, agt->lip);
+ return 0;
+ }
+
+ listen(agt->sock, BACKLOG);
+ }
+
return (1);
}
}
@@ -114,7 +139,7 @@ void start_agent(int is_startup)
attempts = 0;
/* Read until our reply comes back */
- while (((recv_b = recv(agt->sock, buffer, OS_MAXSTR,
+ while (((recv_b = recv(agt->sock_r, buffer, OS_MAXSTR,
MSG_DONTWAIT)) >= 0) || (attempts <= 5)) {
if (recv_b <= 0) {
/* Sleep five seconds before trying to get the reply from
@@ -188,4 +213,3 @@ void start_agent(int is_startup)
return;
}
-
diff --git a/src/config/client-config.c b/src/config/client-config.c
index e670fe6cb..16cea6436 100644
--- a/src/config/client-config.c
+++ b/src/config/client-config.c
@@ -26,6 +26,7 @@ int Read_Client(XML_NODE node, void *d1, __attribute__((unused)) void *d2)
const char *xml_notify_time = "notify_time";
const char *xml_max_time_reconnect_try = "time-reconnect";
const char *xml_profile_name = "config-profile";
+ const char *xml_protocol = "protocol";
agent *logr;
@@ -129,6 +130,15 @@ int Read_Client(XML_NODE node, void *d1, __attribute__((unused)) void *d2)
} else if (strcmp(node[i]->element, xml_profile_name) == 0) {
/* Profile name can be anything hence no validation */
os_strdup(node[i]->content, logr->profile);
+ } else if (strcmp(node[i]->element, xml_protocol) == 0) {
+ if (strcmp(node[i]->content, "tcp") == 0) {
+ logr->protocol = TCP_PROTO;
+ } else if (strcmp(node[i]->content, "udp") == 0) {
+ logr->protocol = UDP_PROTO;
+ } else {
+ merror(XML_VALUEERR, __local_name, node[i]->element, node[i]->content);
+ return (OS_INVALID);
+ }
} else {
merror(XML_INVELEM, __local_name, node[i]->element);
return (OS_INVALID);
@@ -142,4 +152,3 @@ int Read_Client(XML_NODE node, void *d1, __attribute__((unused)) void *d2)
return (0);
}
-
diff --git a/src/config/client-config.h b/src/config/client-config.h
index 876db0990..731b2048b 100644
--- a/src/config/client-config.h
+++ b/src/config/client-config.h
@@ -14,7 +14,8 @@
typedef struct _agent {
char *port;
int m_queue;
- int sock;
+ int sock; /* Socket for UDP and receiving over TCP */
+ int sock_r; /* Remote socket, for sending over TCP */
int execdq;
int rip_id;
char *lip;
@@ -22,7 +23,7 @@ typedef struct _agent {
int notify_time;
int max_time_reconnect_try;
char *profile;
+ int protocol;
} agent;
#endif /* __CAGENTD_H */
-
diff --git a/src/config/config.h b/src/config/config.h
index 7acc2acf4..5920fa314 100644
--- a/src/config/config.h
+++ b/src/config/config.h
@@ -27,6 +27,9 @@
#define CAGENT_CONFIG 0010000
+#define UDP_PROTO 6
+#define TCP_PROTO 17
+
#include "os_xml/os_xml.h"
/* Main function to read the config */
diff --git a/src/config/remote-config.c b/src/config/remote-config.c
index 7958797d0..ca4817d38 100644
--- a/src/config/remote-config.c
+++ b/src/config/remote-config.c
@@ -204,10 +204,6 @@ int Read_Remote(XML_NODE node, void *d1, __attribute__((unused)) void *d2)
logr->proto[pl] = IPPROTO_UDP;
}
- /* Secure connections only run on UDP */
- if ((logr->conn[pl] == SECURE_CONN) && (logr->proto[pl] == IPPROTO_TCP)) {
- logr->proto[pl] = IPPROTO_UDP;
- }
return (0);
}
diff --git a/src/config/remote-config.h b/src/config/remote-config.h
index e40e50d3c..83291f7d7 100644
--- a/src/config/remote-config.h
+++ b/src/config/remote-config.h
@@ -12,6 +12,8 @@
#define SYSLOG_CONN 1
#define SECURE_CONN 2
+#define UDP_PROTO 6
+#define TCP_PROTO 17
#include "shared.h"
@@ -29,6 +31,7 @@ typedef struct _remoted {
int m_queue;
int sock;
socklen_t peer_size;
+ int position;
} remoted;
#endif /* __CLOGREMOTE_H */
diff --git a/src/headers/defs.h b/src/headers/defs.h
index 618c454c8..6217073df 100644
--- a/src/headers/defs.h
+++ b/src/headers/defs.h
@@ -36,6 +36,8 @@
#define OS_HEADER_SIZE OS_SIZE_128 /* Maximum header size */
#define OS_LOG_HEADER OS_SIZE_256 /* Maximum log header size */
#define IPSIZE INET6_ADDRSTRLEN /* IP Address size */
+#define POOL_SIZE 512 /* Max number of children */
+#define BACKLOG SOMAXCONN /* Socket input queue length */
/* Some global names */
#define __ossec_name "OSSEC HIDS"
@@ -125,6 +127,9 @@ published by the Free Software Foundation. For more details, go to \n\
/* Rootcheck directory */
#define ROOTCHECK_DIR "/queue/rootcheck"
+/* Backup directory for agents */
+#define AGNBACKUP_DIR "/backup/agents"
+
/* Diff queue */
#define DIFF_DIR "/queue/diff"
#define DIFF_DIR_PATH DEFAULTDIR DIFF_DIR
diff --git a/src/headers/mq_op.h b/src/headers/mq_op.h
index b425c53c1..99bc3d113 100644
--- a/src/headers/mq_op.h
+++ b/src/headers/mq_op.h
@@ -21,6 +21,7 @@
/* Queues for additional log types */
#define MYSQL_MQ 'a'
#define POSTGRESQL_MQ 'b'
+#define AUTH_MQ 'c'
int StartMQ(const char *key, short int type) __attribute__((nonnull));
diff --git a/src/headers/sec.h b/src/headers/sec.h
index 674f608d0..4eca0584c 100644
--- a/src/headers/sec.h
+++ b/src/headers/sec.h
@@ -19,12 +19,13 @@ typedef struct _keyentry {
unsigned int keyid;
unsigned int global;
+
char *id;
char *key;
char *name;
os_ip *ip;
- struct sockaddr_storage peer_info;
+ struct sockaddr_in peer_info;
FILE *fp;
} keyentry;
diff --git a/src/os_auth/main-server.c b/src/os_auth/main-server.c
index a59201adb..2ae3348bd 100644
--- a/src/os_auth/main-server.c
+++ b/src/os_auth/main-server.c
@@ -38,9 +38,6 @@ int main()
#include "auth.h"
#include "os_crypto/md5/md5_op.h"
-/* TODO: Pulled this value out of the sky, may or may not be sane */
-#define POOL_SIZE 512
-
/* Prototypes */
static void help_authd(void) __attribute((noreturn));
static int ssl_error(const SSL *ssl, int ret);
@@ -51,7 +48,7 @@ static void clean_exit(SSL_CTX *ctx, int sock) __attribute__((noreturn));
static void help_authd()
{
print_header();
- print_out(" %s: -[Vhdti] [-g group] [-D dir] [-p port] [-v path] [-x path] [-k path]", ARGV0);
+ print_out(" %s: -[Vhdti] [-f sec] [-g group] [-D dir] [-p port] [-v path] [-x path] [-k path]", ARGV0);
print_out(" -V Version and license message");
print_out(" -h This help message");
print_out(" -d Execute in debug mode. This parameter");
@@ -59,6 +56,7 @@ static void help_authd()
print_out(" to increase the debug level.");
print_out(" -t Test configuration");
print_out(" -i Use client's source IP address");
+ print_out(" -f Remove old agents with same IP if disconnected since seconds");
print_out(" -g Group to run as (default: %s)", GROUPGLOBAL);
print_out(" -D Directory to chroot into (default: %s)", DEFAULTDIR);
print_out(" -p Manager port (default: %s)", DEFAULT_PORT);
@@ -147,7 +145,10 @@ int main(int argc, char **argv)
int process_pool[POOL_SIZE];
/* Count of pids we are wait()ing on */
int c = 0, test_config = 0, use_ip_address = 0, pid = 0, status, i = 0, active_processes = 0;
+ int m_queue = 0;
int use_pass = 1;
+ int force_antiquity = -1;
+ char *id_exist;
gid_t gid;
int client_sock = 0, sock = 0, portnum, ret = 0;
char *port = DEFAULT_PORT;
@@ -171,7 +172,9 @@ int main(int argc, char **argv)
/* Set the name */
OS_SetName(ARGV0);
- while ((c = getopt(argc, argv, "Vdhtig:D:m:p:v:x:k:n")) != -1) {
+ while ((c = getopt(argc, argv, "Vdhtig:D:m:p:v:x:k:nf:")) != -1) {
+ char *end;
+
switch (c) {
case 'V':
print_version();
@@ -230,6 +233,16 @@ int main(int argc, char **argv)
ErrorExit("%s: -%c needs an argument", ARGV0, c);
}
server_key = optarg;
+ break;
+ case 'f':
+ if (!optarg)
+ ErrorExit("%s: -%c needs an argument", ARGV0, c);
+
+ force_antiquity = strtol(optarg, &end, 10);
+
+ if (optarg == end || force_antiquity < 0)
+ ErrorExit("%s: Invalid number for -f", ARGV0);
+
break;
default:
help_authd();
@@ -328,6 +341,20 @@ int main(int argc, char **argv)
fcntl(sock, F_SETFL, O_NONBLOCK);
debug1("%s: DEBUG: Going into listening mode.", ARGV0);
+ /* Setup random */
+ srandom_init();
+
+ /* Chroot */
+ if (Privsep_Chroot(dir) < 0)
+ ErrorExit(CHROOT_ERROR, ARGV0, dir, errno, strerror(errno));
+
+ nowChroot();
+
+ /* Queue for sending alerts */
+ if ((m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) {
+ merror("%s: ERROR: Can't connect to queue.", ARGV0);
+ }
+
while (1) {
/* No need to completely pin the cpu, 100ms should be fast enough */
usleep(100 * 1000);
@@ -451,7 +478,7 @@ int main(int argc, char **argv)
exit(0);
}
- /* Check for duplicate names */
+ /* Check for duplicated names */
strncpy(fname, agentname, 2048);
while (NameExist(fname)) {
snprintf(fname, 2048, "%s%d", agentname, acount);
@@ -468,12 +495,48 @@ int main(int argc, char **argv)
}
agentname = fname;
+ /* Check for duplicated IP */
+
+ if (use_ip_address) {
+ id_exist = IPExist(srcip);
+ if (id_exist) {
+ double antiquity = OS_AgentAntiquity(id_exist);
+ if (force_antiquity >= 0 && (antiquity >= force_antiquity || antiquity < 0)) {
+ verbose("INFO: Duplicated IP. Saving backup");
+ OS_BackupAgentInfo(id_exist);
+ OS_RemoveAgent(id_exist);
+ } else {
+ merror("%s: ERROR: Duplicated IP %s", ARGV0, srcip);
+ snprintf(response, 2048, "ERROR: Duplicated IP: %s\n\n", srcip);
+
+ if (m_queue >= 0) {
+ char buffer[64];
+ snprintf(buffer, 64, "ossec: Duplicated IP %s", srcip);
+ if (SendMSG(m_queue, buffer, "ossec-authd", AUTH_MQ) < 0) {
+ merror("%s: ERROR: Can't send event across socket.", ARGV0);
+ }
+ }
+
+ SSL_write(ssl, response, strlen(response));
+ snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
+ SSL_write(ssl, response, strlen(response));
+ sleep(1);
+ exit(0);
+ }
+ }
+ }
+
/* Add the new agent */
if (use_ip_address) {
- finalkey = OS_AddNewAgent(agentname, srcip, NULL);
- } else {
+#ifdef REUSE_ID
+ if (id_exist)
+ finalkey = OS_AddNewAgent(agentname, srcip, id_exist);
+ else
+#endif
+ finalkey = OS_AddNewAgent(agentname, srcip, NULL);
+ } else
finalkey = OS_AddNewAgent(agentname, NULL, NULL);
- }
+
if (!finalkey) {
merror("%s: ERROR: Unable to add agent: %s (internal error)", ARGV0, agentname);
snprintf(response, 2048, "ERROR: Internal manager error adding agent: %s\n\n", agentname);
diff --git a/src/os_net/os_net.c b/src/os_net/os_net.c
index d9c8e9a92..6ca956093 100644
--- a/src/os_net/os_net.c
+++ b/src/os_net/os_net.c
@@ -331,13 +331,13 @@ int OS_Connect(char *_port, unsigned int protocol, const char *_ip)
/* Open a TCP socket */
-int OS_ConnectTCP(char *_port, const char *_ip)
+int OS_ConnectTCP(const char *_port, const char *_ip)
{
return (OS_Connect(_port, IPPROTO_TCP, _ip));
}
/* Open a UDP socket */
-int OS_ConnectUDP(char *_port, const char *_ip)
+int OS_ConnectUDP(const char *_port, const char *_ip)
{
return (OS_Connect(_port, IPPROTO_UDP, _ip));
}
diff --git a/src/os_net/os_net.h b/src/os_net/os_net.h
index 838b01a0b..d9cdbcec9 100644
--- a/src/os_net/os_net.h
+++ b/src/os_net/os_net.h
@@ -46,8 +46,8 @@ int OS_getsocketsize(int ossock);
/* OS_Connect
* Connect to a TCP/UDP socket
*/
-int OS_ConnectTCP(char *_port, const char *_ip);
-int OS_ConnectUDP(char *_port, const char *_ip);
+int OS_ConnectTCP(const char *_port, const char *_ip);
+int OS_ConnectUDP(const char *_port, const char *_ip);
/* OS_RecvUDP
* Receive a UDP packet. Return NULL if failed
diff --git a/src/remoted/README b/src/remoted/README
index 27886e1ba..81cec17b5 100644
--- a/src/remoted/README
+++ b/src/remoted/README
@@ -2,7 +2,7 @@ How Remoted works:
Three daemons (forked):
--Secured (udp port 1514)
+-Secured (tcp/udp port 1514)
-Syslogd (udp port 514)
-Syslogd (tcp port 514)
diff --git a/src/remoted/ar-forward.c b/src/remoted/ar-forward.c
index d04ecd700..7025c15b3 100644
--- a/src/remoted/ar-forward.c
+++ b/src/remoted/ar-forward.c
@@ -119,7 +119,7 @@ void *AR_Forward(__attribute__((unused)) void *arg)
if (ar_location & ALL_AGENTS) {
unsigned int i;
for (i = 0; i < keys.keysize; i++) {
- send_msg(i, msg_to_send);
+ send_msg(i, msg_to_send, 0);
}
}
@@ -132,7 +132,7 @@ void *AR_Forward(__attribute__((unused)) void *arg)
continue;
}
- send_msg((unsigned)agent_id, msg_to_send);
+ send_msg((unsigned)agent_id, msg_to_send, 0);
}
/* Send to a pre-defined agent */
@@ -147,7 +147,7 @@ void *AR_Forward(__attribute__((unused)) void *arg)
continue;
}
- send_msg((unsigned)agent_id, msg_to_send);
+ send_msg((unsigned)agent_id, msg_to_send, 0);
}
/* Lock use of keys */
diff --git a/src/remoted/main.c b/src/remoted/main.c
index 94fdf78f0..1c37bd812 100644
--- a/src/remoted/main.c
+++ b/src/remoted/main.c
@@ -171,7 +171,8 @@ int main(int argc, char **argv)
if (fork() == 0) {
/* On the child */
debug1("%s: DEBUG: Forking remoted: '%d'.", ARGV0, i);
- HandleRemote(i, uid);
+ logr.position = i;
+ HandleRemote(uid);
} else {
i++;
continue;
@@ -180,4 +181,3 @@ int main(int argc, char **argv)
return (0);
}
-
diff --git a/src/remoted/manager.c b/src/remoted/manager.c
index 8794ee19d..701d8827f 100644
--- a/src/remoted/manager.c
+++ b/src/remoted/manager.c
@@ -52,7 +52,7 @@ void save_controlmsg(unsigned int agentid, char *r_msg)
/* Reply to the agent */
snprintf(msg_ack, OS_FLSIZE, "%s%s", CONTROL_HEADER, HC_ACK);
- send_msg(agentid, msg_ack);
+ send_msg(agentid, msg_ack, 1);
/* Check if there is a keep alive already for this agent */
if (_keep_alive[agentid] && _msg[agentid] &&
@@ -275,7 +275,7 @@ static int send_file_toagent(unsigned int agentid, const char *name, const char
/* Send the file name first */
snprintf(buf, OS_SIZE_1024, "%s%s%s %s\n",
CONTROL_HEADER, FILE_UPDATE_HEADER, sum, name);
- if (send_msg(agentid, buf) == -1) {
+ if (send_msg(agentid, buf, 0) == -1) {
merror(SEC_ERROR, ARGV0);
fclose(fp);
return (-1);
@@ -285,7 +285,7 @@ static int send_file_toagent(unsigned int agentid, const char *name, const char
while ((n = fread(buf, 1, 900, fp)) > 0) {
buf[n] = '\0';
- if (send_msg(agentid, buf) == -1) {
+ if (send_msg(agentid, buf, 0) == -1) {
merror(SEC_ERROR, ARGV0);
fclose(fp);
return (-1);
@@ -301,7 +301,7 @@ static int send_file_toagent(unsigned int agentid, const char *name, const char
/* Send the message to close the file */
snprintf(buf, OS_SIZE_1024, "%s%s", CONTROL_HEADER, FILE_CLOSE_HEADER);
- if (send_msg(agentid, buf) == -1) {
+ if (send_msg(agentid, buf, 0) == -1) {
merror(SEC_ERROR, ARGV0);
fclose(fp);
return (-1);
diff --git a/src/remoted/remoted.c b/src/remoted/remoted.c
index 8e3d4acfb..da55300d9 100644
--- a/src/remoted/remoted.c
+++ b/src/remoted/remoted.c
@@ -21,8 +21,10 @@ remoted logr;
/* Handle remote connections */
-void HandleRemote(int position, int uid)
+void HandleRemote(int uid)
{
+ int position = logr.position;
+
/* If syslog connection and allowips is not defined, exit */
if (logr.conn[position] == SYSLOG_CONN) {
if (logr.allowips == NULL) {
@@ -68,7 +70,7 @@ void HandleRemote(int position, int uid)
/* If secure connection, deal with it */
if (logr.conn[position] == SECURE_CONN) {
- HandleSecure();
+ HandleSecure(logr.proto[position]);
}
else if (logr.proto[position] == IPPROTO_TCP)
@@ -81,4 +83,3 @@ void HandleRemote(int position, int uid)
HandleSyslog();
}
}
-
diff --git a/src/remoted/remoted.h b/src/remoted/remoted.h
index a261d14e3..223630720 100644
--- a/src/remoted/remoted.h
+++ b/src/remoted/remoted.h
@@ -14,6 +14,7 @@
#define ARGV0 "ossec-remoted"
#endif
+#include "config/config.h"
#include "config/remote-config.h"
#include "sec.h"
@@ -23,7 +24,7 @@
int RemotedConfig(const char *cfgfile, remoted *cfg);
/* Handle Remote connections */
-void HandleRemote(int position, int uid) __attribute__((noreturn));
+void HandleRemote(int uid) __attribute__((noreturn));
/* Handle Syslog */
void HandleSyslog(void) __attribute__((noreturn));
@@ -32,7 +33,7 @@ void HandleSyslog(void) __attribute__((noreturn));
void HandleSyslogTCP(void) __attribute__((noreturn));
/* Handle Secure connections */
-void HandleSecure(void) __attribute__((noreturn));
+void HandleSecure(int procotol) __attribute__((noreturn));
/* Forward active response events */
void *AR_Forward(void *arg) __attribute__((noreturn));
@@ -47,7 +48,7 @@ void *wait_for_msgs(void *none);
void save_controlmsg(unsigned int agentid, char *msg);
/* Send message to agent */
-int send_msg(unsigned int agentid, const char *msg);
+int send_msg(unsigned int agentid, const char *msg, int reply);
/* Initializing send_msg */
void send_msg_init(void);
diff --git a/src/remoted/secure.c b/src/remoted/secure.c
index 76d4e3961..29714674a 100644
--- a/src/remoted/secure.c
+++ b/src/remoted/secure.c
@@ -11,18 +11,18 @@
#include "os_net/os_net.h"
#include "remoted.h"
-
/* Handle secure connections */
-void HandleSecure()
+void HandleSecure(int protocol)
{
int agentid;
+ int socket_server = logr.sock;
char buffer[OS_MAXSTR + 1];
char cleartext_msg[OS_MAXSTR + 1];
char srcip[IPSIZE + 1];
char *tmp_msg;
char srcmsg[OS_FLSIZE + 1];
ssize_t recv_b;
- struct sockaddr_storage peer_info;
+ struct sockaddr_in peer_info;
socklen_t peer_size;
/* Send msg init */
@@ -72,19 +72,43 @@ void HandleSecure()
memset(srcmsg, '\0', OS_FLSIZE + 1);
tmp_msg = NULL;
+ if (protocol == TCP_PROTO) {
+ logr.sock = -1;
+ }
+
+
+
+
while (1) {
/* Receive message */
- recv_b = recvfrom(logr.sock, buffer, OS_MAXSTR, 0,
- (struct sockaddr *)&peer_info, &peer_size);
+
+ if (protocol == TCP_PROTO) {
+ close(logr.sock);
+ logr.sock = OS_AcceptTCP(socket_server, srcip, IPSIZE);
+
+ if (logr.sock < 0) {
+ ErrorExit("ERROR: %s Couldn't accept TCP connections.", ARGV0);
+ }
+
+ peer_info.sin_addr.s_addr = inet_addr(srcip);
+
+ /* Receive message */
+ recv_b = recv(logr.sock, buffer, OS_MAXSTR, 0);
+ } else {
+ recv_b = recvfrom(logr.sock, buffer, OS_MAXSTR, 0, (struct sockaddr *)&peer_info, &peer_size);
+
+ /* Set the source IP */
+ strncpy(srcip, inet_ntoa(peer_info.sin_addr), IPSIZE);
+ srcip[IPSIZE] = '\0';
+ }
/* Nothing received */
if (recv_b <= 0) {
continue;
}
- /* Set the source IP */
- satop((struct sockaddr *) &peer_info, srcip, IPSIZE);
- srcip[IPSIZE] = '\0';
+
+
/* Get a valid agent id */
if (buffer[0] == '!') {
diff --git a/src/remoted/sendmsg.c b/src/remoted/sendmsg.c
index df8279c16..195f5fc3e 100644
--- a/src/remoted/sendmsg.c
+++ b/src/remoted/sendmsg.c
@@ -84,11 +84,12 @@ void send_msg_init()
/* Send message to an agent
* Returns -1 on error
*/
-int send_msg(unsigned int agentid, const char *msg)
+int send_msg(unsigned int agentid, const char *msg, int reply)
{
size_t msg_size, sa_size;
char crypt_msg[OS_MAXSTR + 1];
struct sockaddr * dest_sa;
+ int sock;
/* If we don't have the agent id, ignore it */
if (keys.keyentries[agentid]->rcvd < (time(0) - (2 * NOTIFY_TIME))) {
@@ -101,6 +102,18 @@ int send_msg(unsigned int agentid, const char *msg)
return (-1);
}
+ if (logr.proto[logr.position] == TCP_PROTO && !reply) {
+ char *ip = inet_ntoa(keys.keyentries[agentid]->peer_info.sin_addr);
+ sock = OS_ConnectTCP(logr.port[logr.position], ip != NULL);
+
+ if (sock < 0) {
+ merror(CONNS_ERROR, ARGV0, ip);
+ return (-1);
+ }
+ } else {
+ sock = logr.sock;
+ }
+
/* Lock before using */
if (pthread_mutex_lock(&sendmsg_mutex) != 0) {
merror(MUTEX_ERROR, ARGV0);
@@ -111,7 +124,7 @@ int send_msg(unsigned int agentid, const char *msg)
dest_sa = (struct sockaddr *)&keys.keyentries[agentid]->peer_info;
sa_size = (dest_sa->sa_family == AF_INET) ?
sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
- if (sendto(logr.sock, crypt_msg, msg_size, 0, dest_sa, sa_size) < 0) {
+ if (sendto(sock, crypt_msg, msg_size, 0, dest_sa, sa_size) < 0) {
merror(SEND_ERROR, ARGV0, keys.keyentries[agentid]->id);
}
@@ -121,6 +134,10 @@ int send_msg(unsigned int agentid, const char *msg)
return (-1);
}
+ if (logr.proto[logr.position] == TCP_PROTO && !reply) {
+ close(sock);
+ }
+
return (0);
}
diff --git a/src/win32/win_agent.c b/src/win32/win_agent.c
index 56b8075eb..4784c1fae 100644
--- a/src/win32/win_agent.c
+++ b/src/win32/win_agent.c
@@ -434,9 +434,16 @@ int SendMSG(__attribute__((unused)) int queue, const char *message, const char *
}
/* Send _ssize of crypt_msg */
- if (OS_SendUDPbySize(agt->sock, _ssize, crypt_msg) < 0) {
- merror(SEND_ERROR, ARGV0, "server");
- sleep(1);
+ if (agt->protocol == UDP_PROTO) {
+ if (OS_SendUDPbySize(agt->sock, _ssize, crypt_msg) < 0) {
+ merror(SEND_ERROR, ARGV0, "server");
+ sleep(1);
+ }
+ } else {
+ if (OS_SendTCPbySize(agt->sock, _ssize, crypt_msg) < 0) {
+ merror(SEND_ERROR, ARGV0, "server");
+ sleep(1);
+ }
}
if (!ReleaseMutex(hMutex)) {
@@ -527,9 +534,16 @@ void send_win32_info(time_t curr_time)
}
/* Send UDP message */
- if (OS_SendUDPbySize(agt->sock, msg_size, crypt_msg) < 0) {
- merror(SEND_ERROR, ARGV0, "server");
- sleep(1);
+ if (agt->protocol == UDP_PROTO) {
+ if (OS_SendUDPbySize(agt->sock, msg_size, crypt_msg) < 0) {
+ merror(SEND_ERROR, ARGV0, "server");
+ sleep(1);
+ }
+ } else {
+ if (OS_SendTCPbySize(agt->sock, msg_size, crypt_msg) < 0) {
+ merror(SEND_ERROR, ARGV0, "server");
+ sleep(1);
+ }
}
return;