/* Receive events from the server */ int receive_msg() { ssize_t recv_b; netsize_t length; int reads = 0; char buffer[OS_MAXSTR + 1]; char cleartext[OS_MAXSTR + 1]; char *tmp_msg; memset(cleartext, '\0', OS_MAXSTR + 1); memset(buffer, '\0', OS_MAXSTR + 1); /* Read until no more messages are available */ while (1) { if (agt->protocol == TCP_PROTO) { /* Only one read per call */ if (reads++) { break; } recv_b = recv(agt->sock, (char*)&length, sizeof(length), MSG_WAITALL); /* Manager disconnected */ if (recv_b <= 0) { return -1; } recv_b = recv(agt->sock, buffer, length, MSG_WAITALL); if (recv_b != length) { merror(RECV_ERROR, ARGV0); continue; } } else { recv_b = recv(agt->sock, buffer, OS_SIZE_1024, MSG_DONTWAIT); if (recv_b <= 0) { break; } } buffer[recv_b] = '\0'; tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b - 1); if (tmp_msg == NULL) { merror(MSG_ERROR, ARGV0, agt->rip[agt->rip_id]); continue; } /* Check for commands */ if (IsValidHeader(tmp_msg)) { available_server = (int)time(NULL); #ifdef WIN32 /* Run timeout commands */ if (agt->execdq >= 0) { WinTimeoutRun(available_server); } #endif /* If it is an active response message */ if (strncmp(tmp_msg, EXECD_HEADER, strlen(EXECD_HEADER)) == 0) { tmp_msg += strlen(EXECD_HEADER); #ifndef WIN32 if (agt->execdq >= 0) { if (OS_SendUnix(agt->execdq, tmp_msg, 0) < 0) { merror("%s: Error communicating with execd", ARGV0); } } #else /* Run on Windows */ if (agt->execdq >= 0) { WinExecdRun(tmp_msg); } #endif continue; } /* Restart syscheck */ else if (strcmp(tmp_msg, HC_SK_RESTART) == 0) { os_set_restart_syscheck(); continue; } /* Ack from server */ else if (strcmp(tmp_msg, HC_ACK) == 0) { continue; } /* Close any open file pointer if it was being written to */ if (fp) { fclose(fp); fp = NULL; } /* File update message */ if (strncmp(tmp_msg, FILE_UPDATE_HEADER, strlen(FILE_UPDATE_HEADER)) == 0) { char *validate_file; tmp_msg += strlen(FILE_UPDATE_HEADER); /* Going to after the file sum */ validate_file = strchr(tmp_msg, ' '); if (!validate_file) { continue; } *validate_file = '\0'; /* Copy the file sum */ strncpy(file_sum, tmp_msg, 33); /* Set tmp_msg to the beginning of the file name */ validate_file++; tmp_msg = validate_file; if ((validate_file = strchr(tmp_msg, '\n')) != NULL) { *validate_file = '\0'; } while ((validate_file = strchr(tmp_msg, '/')) != NULL) { *validate_file = '-'; } if (tmp_msg[0] == '.') { tmp_msg[0] = '-'; } snprintf(file, OS_SIZE_1024, "%s/%s", SHAREDCFG_DIR, tmp_msg); fp = fopen(file, "w"); if (!fp) { merror(FOPEN_ERROR, ARGV0, file, errno, strerror(errno)); } } else if (strncmp(tmp_msg, FILE_CLOSE_HEADER, strlen(FILE_CLOSE_HEADER)) == 0) { /* No error */ os_md5 currently_md5; /* Close for the rename to work */ if (fp) { fclose(fp); fp = NULL; } if (file[0] == '\0') { /* Nothing to be done */ } else if (OS_MD5_File(file, currently_md5, OS_TEXT) < 0) { /* Remove file */ unlink(file); file[0] = '\0'; } else { if (strcmp(currently_md5, file_sum) != 0) { debug1("%s: ERROR: Failed md5 for: %s -- deleting.", ARGV0, file); unlink(file); } else { char *final_file; /* Rename the file to its original name */ final_file = strrchr(file, '/'); if (final_file) { if (strcmp(final_file + 1, SHAREDCFG_FILENAME) == 0) { UnmergeFiles(file, SHAREDCFG_DIR); } } else { /* Remove file */ unlink(file); } } file[0] = '\0'; } } else { merror("%s: WARN: Unknown message received from server.", ARGV0); } } else if (fp) { available_server = (int)time(NULL); fprintf(fp, "%s", tmp_msg); } else { merror("%s: WARN: Unknown message received. No action defined.", ARGV0); } } return 0; }
/* receiver_thread: * Receive events from the server. */ void *receiver_thread(void *none) { int recv_b; char file[OS_SIZE_1024 +1]; char buffer[OS_MAXSTR +1]; char cleartext[OS_MAXSTR + 1]; char *tmp_msg; char file_sum[34]; fd_set fdset; struct timeval selecttime; FILE *fp; /* Setting FP to null, before starting */ fp = NULL; memset(cleartext, '\0', OS_MAXSTR +1); memset(buffer, '\0', OS_MAXSTR +1); memset(file, '\0', OS_SIZE_1024 +1); memset(file_sum, '\0', 34); while(1) { /* sock must be set. */ if(agt->sock == -1) { sleep(5); continue; } FD_ZERO(&fdset); FD_SET(agt->sock, &fdset); /* Wait for 30 seconds. */ selecttime.tv_sec = 30; selecttime.tv_usec = 0; /* Wait with a timeout for any descriptor */ recv_b = select(0, &fdset, NULL, NULL, &selecttime); if(recv_b == -1) { merror(SELECT_ERROR, ARGV0); sleep(30); continue; } else if(recv_b == 0) { continue; } /* Read until no more messages are available */ while((recv_b = recv(agt->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) { merror(MSG_ERROR,ARGV0,agt->rip[agt->rip_id]); continue; } /* Check for commands */ if(IsValidHeader(tmp_msg)) { /* This is the only thread that modifies it */ available_server = (int)time(NULL); /* Run timeout commands. */ if(agt->execdq >= 0) WinTimeoutRun(available_server); /* If it is an active response message */ if(strncmp(tmp_msg, EXECD_HEADER, strlen(EXECD_HEADER)) == 0) { tmp_msg+=strlen(EXECD_HEADER); /* Run on windows. */ if(agt->execdq >= 0) { WinExecdRun(tmp_msg); } continue; } /* Restart syscheck. */ else if(strcmp(tmp_msg, HC_SK_RESTART) == 0) { os_set_restart_syscheck(); continue; } /* Ack from server */ else if(strcmp(tmp_msg, HC_ACK) == 0) { continue; } /* Close any open file pointer if it was being written to */ if(fp) { fclose(fp); fp = NULL; } /* File update message */ if(strncmp(tmp_msg, FILE_UPDATE_HEADER, strlen(FILE_UPDATE_HEADER)) == 0) { char *validate_file; tmp_msg+=strlen(FILE_UPDATE_HEADER); /* Going to after the file sum */ validate_file = strchr(tmp_msg, ' '); if(!validate_file) { continue; } *validate_file = '\0'; /* copying the file sum */ strncpy(file_sum, tmp_msg, 33); /* Setting tmp_msg to the beginning of the file name */ validate_file++; tmp_msg = validate_file; if((validate_file = strchr(tmp_msg, '\n')) != NULL) { *validate_file = '\0'; } while((validate_file = strchr(tmp_msg, '/')) != NULL) { *validate_file = '-'; } if(tmp_msg[0] == '.') tmp_msg[0] = '-'; snprintf(file, OS_SIZE_1024, "%s/%s", SHAREDCFG_DIR, tmp_msg); fp = fopen(file, "w"); if(!fp) { merror(FOPEN_ERROR, ARGV0, file); } } else if(strncmp(tmp_msg, FILE_CLOSE_HEADER, strlen(FILE_CLOSE_HEADER)) == 0) { /* no error */ os_md5 currently_md5; /* Making sure to close for the rename to work */ if(fp) { fclose(fp); fp = NULL; } if(file[0] == '\0') { /* nada */ } else if(OS_MD5_File(file, currently_md5) < 0) { /* Removing file */ unlink(file); file[0] = '\0'; } else { if(strcmp(currently_md5, file_sum) != 0) { debug1("%s: Failed md5 for: %s -- deleting.", ARGV0, file); unlink(file); } else { char *final_file; /* Renaming the file to its orignal name */ final_file = strrchr(file, '/'); if(final_file) { if(strcmp(final_file + 1, SHAREDCFG_FILENAME) == 0) { UnmergeFiles(file, SHAREDCFG_DIR); } } else { unlink(file); } } file[0] = '\0'; } } else { merror("%s: WARN: Unknown message received from server.", ARGV0); } } else if(fp) { available_server = (int)time(NULL); fprintf(fp, "%s", tmp_msg); } else { merror("%s: WARN: Unknown message received. No action defined.", ARGV0); } } } /* Cleaning up */ if(fp) { fclose(fp); if(file[0] != '\0') unlink(file); } return(NULL); }
/* start_agent: Sends the synchronization message to * the server and waits for the ack. */ void start_agent(int is_startup) { int recv_b = 0, attempts = 0, g_attempts = 1; char *tmp_msg; char msg[OS_MAXSTR +2]; char buffer[OS_MAXSTR +1]; char cleartext[OS_MAXSTR +1]; char fmsg[OS_MAXSTR +1]; memset(msg, '\0', OS_MAXSTR +2); memset(buffer, '\0', OS_MAXSTR +1); memset(cleartext, '\0', OS_MAXSTR +1); memset(fmsg, '\0', OS_MAXSTR +1); snprintf(msg, OS_MAXSTR, "%s%s", CONTROL_HEADER, HC_STARTUP); #ifdef ONEWAY return; #endif /* Sending start message and waiting for the ack */ while(1) { /* Sending start up message */ send_msg(0, msg); attempts = 0; /* Read until our reply comes back */ while(((recv_b = recv(agt->sock, buffer, OS_MAXSTR, MSG_DONTWAIT)) >= 0) || (attempts <= 5)) { if(recv_b <= 0) { /* Sleep five seconds before trying to get the reply from * the server again. */ attempts++; sleep(attempts); /* Sending message again (after three attempts) */ if(attempts >= 3) { send_msg(0, msg); } continue; } /* Id of zero -- only one key allowed */ tmp_msg = ReadSecMSG(&keys, buffer, cleartext, 0, recv_b -1); if(tmp_msg == NULL) { merror(MSG_ERROR, ARGV0, agt->rip[agt->rip_id]); continue; } /* Check for commands */ if(IsValidHeader(tmp_msg)) { /* If it is an ack reply */ if(strcmp(tmp_msg, HC_ACK) == 0) { available_server = time(0); verbose(AG_CONNECTED, ARGV0, agt->rip[agt->rip_id], agt->port); if(is_startup) { /* Send log message about start up */ snprintf(msg, OS_MAXSTR, OS_AG_STARTED, keys.keyentries[0]->name, keys.keyentries[0]->ip->ip); snprintf(fmsg, OS_MAXSTR, "%c:%s:%s", LOCALFILE_MQ, "ossec", msg); send_msg(0, fmsg); } return; } } } /* Waiting for servers reply */ merror(AG_WAIT_SERVER, ARGV0, agt->rip[agt->rip_id]); /* If we have more than one server, try all. */ if(agt->rip[1]) { int curr_rip = agt->rip_id; merror("%s: INFO: Trying next server ip in the line: '%s'.", ARGV0, agt->rip[agt->rip_id + 1] != NULL?agt->rip[agt->rip_id + 1]:agt->rip[0]); connect_server(agt->rip_id +1); if(agt->rip_id == curr_rip) { sleep(g_attempts); g_attempts+=(attempts * 3); } else { g_attempts+=5; sleep(g_attempts); } } else { sleep(g_attempts); g_attempts+=(attempts * 3); connect_server(0); } } return; }
/* Handle secure connections */ void HandleSecure() { int agentid; 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_in peer_info; socklen_t peer_size; /* Send msg init */ send_msg_init(); /* Initialize key mutex */ keyupdate_init(); /* Initialize manager */ manager_init(0); /* Create Active Response forwarder thread */ if (CreateThread(AR_Forward, (void *)NULL) != 0) { ErrorExit(THREAD_ERROR, ARGV0); } /* Create wait_for_msgs thread */ if (CreateThread(wait_for_msgs, (void *)NULL) != 0) { ErrorExit(THREAD_ERROR, ARGV0); } /* Connect to the message queue * Exit if it fails. */ if ((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); } verbose(AG_AX_AGENTS, ARGV0, MAX_AGENTS); /* Read authentication keys */ verbose(ENC_READ, ARGV0); OS_ReadKeys(&keys); OS_StartCounter(&keys); /* Set up peer size */ peer_size = sizeof(peer_info); logr.peer_size = sizeof(peer_info); /* Initialize some variables */ memset(buffer, '\0', OS_MAXSTR + 1); memset(cleartext_msg, '\0', OS_MAXSTR + 1); memset(srcmsg, '\0', OS_FLSIZE + 1); tmp_msg = NULL; while (1) { /* Receive message */ recv_b = recvfrom(logr.sock, buffer, OS_MAXSTR, 0, (struct sockaddr *)&peer_info, &peer_size); /* Nothing received */ if (recv_b <= 0) { continue; } /* Set the source IP */ strncpy(srcip, inet_ntoa(peer_info.sin_addr), IPSIZE); srcip[IPSIZE] = '\0'; /* Get a valid agent id */ if (buffer[0] == '!') { tmp_msg = buffer; tmp_msg++; /* We need to make sure that we have a valid id * and that we reduce the recv buffer size */ while (isdigit((int)*tmp_msg)) { tmp_msg++; recv_b--; } if (*tmp_msg != '!') { merror(ENCFORMAT_ERROR, __local_name, srcip); continue; } *tmp_msg = '\0'; tmp_msg++; recv_b -= 2; agentid = OS_IsAllowedDynamicID(&keys, buffer + 1, srcip); if (agentid == -1) { if (check_keyupdate()) { agentid = OS_IsAllowedDynamicID(&keys, buffer + 1, srcip); if (agentid == -1) { merror(ENC_IP_ERROR, ARGV0, srcip); continue; } } else { merror(ENC_IP_ERROR, ARGV0, srcip); continue; } } } else { agentid = OS_IsAllowedIP(&keys, srcip); if (agentid < 0) { if (check_keyupdate()) { agentid = OS_IsAllowedIP(&keys, srcip); if (agentid == -1) { merror(DENYIP_WARN, ARGV0, srcip); continue; } } else { merror(DENYIP_WARN, ARGV0, srcip); continue; } } tmp_msg = buffer; } /* Decrypt the message */ tmp_msg = ReadSecMSG(&keys, tmp_msg, cleartext_msg, agentid, recv_b - 1); if (tmp_msg == NULL) { /* If duplicated, a warning was already generated */ continue; } /* Check if it is a control message */ if (IsValidHeader(tmp_msg)) { /* We need to save the peerinfo if it is a control msg */ memcpy(&keys.keyentries[agentid]->peer_info, &peer_info, peer_size); keys.keyentries[agentid]->rcvd = time(0); save_controlmsg((unsigned)agentid, tmp_msg); continue; } /* Generate srcmsg */ snprintf(srcmsg, OS_FLSIZE, "(%s) %s", keys.keyentries[agentid]->name, keys.keyentries[agentid]->ip->ip); /* If we can't send the message, try to connect to the * socket again. If it not exit. */ if (SendMSG(logr.m_queue, tmp_msg, srcmsg, SECURE_MQ) < 0) { merror(QUEUE_ERROR, ARGV0, DEFAULTQUEUE, strerror(errno)); if ((logr.m_queue = StartMQ(DEFAULTQUEUE, WRITE)) < 0) { ErrorExit(QUEUE_FATAL, ARGV0, DEFAULTQUEUE); } } } }