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;