/* getfiles: Return the name of the files in a directory */ char *getsharedfiles() { int m_size = 512; char *ret; os_md5 md5sum; if(OS_MD5_File(SHAREDCFG_FILE, md5sum) != 0) { md5sum[0] = 'x'; md5sum[1] = 'x'; md5sum[1] = '\0'; } /* we control these files, max size is m_size */ ret = (char *)calloc(m_size +1, sizeof(char)); if(!ret) { merror(MEM_ERROR, ARGV0); return(NULL); } snprintf(ret, m_size, "%s merged.mg\n", md5sum); return(ret); }
/* Send integrity checking information about a file to the server */ int intcheck_file(const char *file_name, const char *dir) { struct stat statbuf; os_md5 mf_sum; os_sha1 sf_sum; char newsum[912 + 1]; newsum[0] = '\0'; newsum[912] = '\0'; /* Stat the file */ #ifdef WIN32 if (stat(file_name, &statbuf) < 0) #else if (lstat(file_name, &statbuf) < 0) #endif { snprintf(newsum, 911, "%c:%s:-1 %s%s", SYSCHECK_MQ, SYSCHECK, dir, file_name); send_msg(0, newsum); return (1); } /* Generate new checksum */ #ifdef WIN32 if (S_ISREG(statbuf.st_mode)) #else if (S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode)) #endif { /* Generate SHA-1 of the file */ if (OS_SHA1_File(file_name, sf_sum, OS_TEXT) < 0) { strncpy(sf_sum, "xxx", 4); } /* Generate MD5 of the file */ if (OS_MD5_File(file_name, mf_sum, OS_TEXT) < 0) { strncpy(mf_sum, "xxx", 4); } } snprintf(newsum, 911, "%c:%s:%d:%d:%d:%d:%s:%s %s%s", SYSCHECK_MQ, SYSCHECK, (int)statbuf.st_size, (int)statbuf.st_mode, (int)statbuf.st_uid, (int)statbuf.st_gid, mf_sum, sf_sum, dir, file_name); send_msg(0, newsum); return (1); }
int main(int argc, char **argv) { os_md5 filesum; if (argc < 3) { usage(argv); } if (strcmp(argv[1], "file") == 0) { OS_MD5_File(argv[2], filesum, OS_BINARY); } else if (strcmp(argv[1], "str") == 0) { OS_MD5_Str(argv[2], filesum); } else { usage(argv); } printf("MD5Sum for \"%s\" is: %s\n", argv[2], filesum); return (0); }
/* Signs a log file */ void OS_SignLog(const char *logfile, const char *logfile_old, int log_missing) { os_md5 mf_sum; os_md5 mf_sum_old; os_sha1 sf_sum; os_sha1 sf_sum_old; char logfilesum[OS_FLSIZE +1]; char logfilesum_old[OS_FLSIZE +1]; FILE *fp; /* Clearing the memory */ memset(logfilesum, '\0', OS_FLSIZE +1); memset(logfilesum_old, '\0', OS_FLSIZE +1); /* Setting the umask */ umask(0027); /* Creating the checksum file names */ snprintf(logfilesum, OS_FLSIZE, "%s.sum", logfile); snprintf(logfilesum_old, OS_FLSIZE, "%s.sum", logfile_old); /* generating md5 of the old file */ if(OS_MD5_File(logfilesum_old, mf_sum_old) < 0) { merror("%s: No previous md5 checksum found: '%s'. " "Starting over.", ARGV0, logfilesum_old); strncpy(mf_sum_old, "none", 6); } /* generating sha1 of the old file. */ if(OS_SHA1_File(logfilesum_old, sf_sum_old) < 0) { merror("%s: No previous sha1 checksum found: '%s'. " "Starting over.", ARGV0, logfilesum_old); strncpy(sf_sum_old, "none", 6); } /* Generating md5 of the current file */ if(OS_MD5_File(logfile, mf_sum) < 0) { if(log_missing) merror("%s: File '%s' not found. MD5 checksum skipped.", ARGV0, logfile); strncpy(mf_sum, "none", 6); } /* Generating sha1 of the current file */ if(OS_SHA1_File(logfile, sf_sum) < 0) { if(log_missing) merror("%s: File '%s' not found. SHA1 checksum skipped.", ARGV0, logfile); strncpy(sf_sum, "none", 6); } fp = fopen(logfilesum, "w"); if(!fp) { merror(FOPEN_ERROR, ARGV0, logfilesum, errno, strerror(errno)); return; } fprintf(fp, "Current checksum:\n"); fprintf(fp, "MD5 (%s) = %s\n", logfile, mf_sum); fprintf(fp, "SHA1 (%s) = %s\n\n", logfile, sf_sum); fprintf(fp, "Chained checksum:\n"); fprintf(fp, "MD5 (%s) = %s\n", logfilesum_old, mf_sum_old); fprintf(fp, "SHA1 (%s) = %s\n\n", logfilesum_old, sf_sum_old); fclose(fp); return; }
/* run_notify: Send periodically notification to server */ void run_notify() { char keep_alive_random[1024]; char tmp_msg[OS_SIZE_1024 +1]; char *uname; char *shared_files; os_md5 md5sum; keep_alive_random[0] = '\0'; time_t curr_time; curr_time = time(0); #ifndef ONEWAY /* Check if the server has responded */ if((curr_time - available_server) > (3*NOTIFY_TIME)) { /* If response is not available, set lock and * wait for it. */ verbose(SERVER_UNAV, ARGV0); os_setwait(); /* Send sync message */ start_agent(0); verbose(SERVER_UP, ARGV0); os_delwait(); } #endif /* Check if time has elapsed */ if((curr_time - g_saved_time) < (NOTIFY_TIME - 120)) { return; } g_saved_time = curr_time; debug1("%s: DEBUG: Sending agent notification.", ARGV0); /* Send the message. * Message is going to be the * uname\n checksum file\n checksum file\n */ /* Getting uname */ uname = getuname(); if(!uname) { merror(MEM_ERROR,ARGV0); return; } /* get shared files */ shared_files = getsharedfiles(); if(!shared_files) { shared_files = strdup("\0"); if(!shared_files) { free(uname); merror(MEM_ERROR,ARGV0); return; } } rand_keepalive_str2(keep_alive_random, 700); /* creating message */ if((File_DateofChange(AGENTCONFIGINT) > 0 ) && (OS_MD5_File(AGENTCONFIGINT, md5sum) == 0)) { snprintf(tmp_msg, OS_SIZE_1024, "#!-%s / %s\n%s\n%s", uname, md5sum, shared_files, keep_alive_random); } else { snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s\n%s", uname, shared_files, keep_alive_random); } /* Sending status message */ send_msg(0, tmp_msg); free(uname); free(shared_files); return; }
/* 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; }
/* Create the structure with the files and checksums */ static void c_files() { DIR *dp; struct dirent *entry; os_md5 md5sum; unsigned int f_size = 0; f_sum = NULL; /* Create merged file */ os_realloc(f_sum, (f_size + 2) * sizeof(file_sum *), f_sum); os_calloc(1, sizeof(file_sum), f_sum[f_size]); f_sum[f_size]->mark = 0; f_sum[f_size]->name = NULL; f_sum[f_size]->sum[0] = '\0'; MergeAppendFile(SHAREDCFG_FILE, NULL); f_size++; /* Open directory */ dp = opendir(SHAREDCFG_DIR); if (!dp) { merror("%s: Error opening directory: '%s': %s ", ARGV0, SHAREDCFG_DIR, strerror(errno)); return; } /* Read directory */ while ((entry = readdir(dp)) != NULL) { char tmp_dir[512]; /* Ignore . and .. */ if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) { continue; } snprintf(tmp_dir, 512, "%s/%s", SHAREDCFG_DIR, entry->d_name); /* Leave the shared config file for later */ if (strcmp(tmp_dir, SHAREDCFG_FILE) == 0) { continue; } if (OS_MD5_File(tmp_dir, md5sum, OS_TEXT) != 0) { merror("%s: Error accessing file '%s'", ARGV0, tmp_dir); continue; } f_sum = (file_sum **)realloc(f_sum, (f_size + 2) * sizeof(file_sum *)); if (!f_sum) { ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno)); } f_sum[f_size] = (file_sum *) calloc(1, sizeof(file_sum)); if (!f_sum[f_size]) { ErrorExit(MEM_ERROR, ARGV0, errno, strerror(errno)); } strncpy(f_sum[f_size]->sum, md5sum, 32); os_strdup(entry->d_name, f_sum[f_size]->name); f_sum[f_size]->mark = 0; MergeAppendFile(SHAREDCFG_FILE, tmp_dir); f_size++; } if (f_sum != NULL) { f_sum[f_size] = NULL; } closedir(dp); if (OS_MD5_File(SHAREDCFG_FILE, md5sum, OS_TEXT) != 0) { merror("%s: Error accessing file '%s'", ARGV0, SHAREDCFG_FILE); f_sum[0]->sum[0] = '\0'; } strncpy(f_sum[0]->sum, md5sum, 32); os_strdup(SHAREDCFG_FILENAME, f_sum[0]->name); return; }
/* 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); }
/* Send win32 info to server */ void send_win32_info(time_t curr_time) { int msg_size; char tmp_msg[OS_MAXSTR +2]; char crypt_msg[OS_MAXSTR +2]; tmp_msg[OS_MAXSTR +1] = '\0'; crypt_msg[OS_MAXSTR +1] = '\0'; debug1("%s: DEBUG: Sending keep alive message.", ARGV0); verbose("%s Sending keep alive message....", ARGV0); /* fixing time */ __win32_curr_time = curr_time; /* Getting uname. */ if(!__win32_uname) { __win32_uname = getuname(); if(!__win32_uname) { merror("%s: Error generating system information.", ARGV0); os_strdup("Microsoft Windows - Unknown (unable to get system info)", __win32_uname); } } /* Getting shared files list -- every 30 seconds only. */ if((__win32_curr_time - __win32_shared_time) > 30) { if(__win32_shared) { free(__win32_shared); __win32_shared = NULL; } __win32_shared_time = __win32_curr_time; } /* get shared files */ if(!__win32_shared) { __win32_shared = getsharedfiles(); if(!__win32_shared) { __win32_shared = strdup("\0"); if(!__win32_shared) { merror(MEM_ERROR, ARGV0); return; } } } /* creating message */ if(File_DateofChange(AGENTCONFIGINT) > 0) { os_md5 md5sum; if(OS_MD5_File(AGENTCONFIGINT, md5sum) != 0) { snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s", __win32_uname, __win32_shared); } else { snprintf(tmp_msg, OS_SIZE_1024, "#!-%s / %s\n%s", __win32_uname, md5sum, __win32_shared); } } else { snprintf(tmp_msg, OS_SIZE_1024, "#!-%s\n%s", __win32_uname, __win32_shared); } /* creating message */ debug1("%s: DEBUG: Sending keep alive: %s", ARGV0, tmp_msg); msg_size = CreateSecMSG(&keys, tmp_msg, crypt_msg, 0); if(msg_size == 0) { merror(SEC_ERROR, ARGV0); return; } /* Sending UDP message */ if(OS_SendUDPbySize(logr->sock, msg_size, crypt_msg) < 0) { merror(SEND_ERROR, ARGV0, "server"); sleep(1); } return; }