/* Initialize sockets for file transfer to other host * * Args: * char *hostname: host name or IP address of receiver * int portno: port number of receiver */ int file_agent_init_socket(char *hostname, int portno) { struct sockaddr_in serv_addr; struct hostent *server; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { FILE_FATAL_ERROR("File inspect: ERROR creating socket!\n"); return -1; } /*get the address info by either host name or IP address*/ server = gethostbyname(hostname); if (server == NULL) { _dpd.errMsg("File inspect: ERROR, no such host\n"); close(sockfd); return -1; } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; memcpy((char *)&serv_addr.sin_addr.s_addr, (char *)server->h_addr, server->h_length); serv_addr.sin_port = htons(portno); if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) { _dpd.errMsg("File inspect: ERROR connecting host %s: %d!\n", hostname, portno); close(sockfd); return -1; } _dpd.logMsg("File inspect: Connection established on host: %s, port: %d\n", hostname, portno); return 0; }
static void file_agent_thread_init() { int rval; const struct timespec thread_sleep = { 0, 100 }; sigset_t mask; stop_file_capturing = false; /* Spin off the file capture handler thread. */ sigemptyset(&mask); sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGQUIT); sigaddset(&mask, SIGPIPE); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGUSR1); sigaddset(&mask, SIGUSR2); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGURG); sigaddset(&mask, SIGVTALRM); pthread_sigmask(SIG_SETMASK, &mask, NULL); FileInspectConf *conf = sfPolicyUserDataGetDefault(file_config); if ((rval = pthread_create(&capture_thread_tid, NULL, &FileCaptureThread, conf)) != 0) { sigemptyset(&mask); pthread_sigmask(SIG_SETMASK, &mask, NULL); FILE_FATAL_ERROR("File capture: Unable to create a " "processing thread: %s", strerror(rval)); } while (!capture_thread_running) nanosleep(&thread_sleep, NULL); sigemptyset(&mask); pthread_sigmask(SIG_SETMASK, &mask, NULL); _dpd.logMsg("File capture thread started tid=%p (pid=%u)\n", (void *) capture_thread_tid, capture_thread_pid); }
/* Add another thread for file capture to disk or network * When settings are changed, snort must be restarted to get it applied */ void file_agent_init(FileInspectConf* conf) { /*Need to check configuration to decide whether to enable them*/ if (conf->file_type_enabled) { _dpd.fileAPI->enable_file_type(file_agent_type_callback); file_type_enabled = true; } if (conf->file_signature_enabled) { _dpd.fileAPI->enable_file_signature(file_agent_signature_callback); file_signature_enabled = true; } if (conf->file_capture_enabled) { _dpd.fileAPI->enable_file_capture(file_agent_signature_callback); file_capture_enabled = true; } if (conf->hostname) { file_agent_init_socket(conf->hostname, conf->portno); } file_list = cbuffer_init(conf->file_capture_queue_size); if(!file_list) { FILE_FATAL_ERROR("File capture: Unable to create file capture queue!"); } file_agent_thread_init(); #ifndef WIN32 /* In daemon mode we need to re-create cbuffer consumer thread */ pthread_atfork(file_agent_close,NULL,file_agent_thread_init); #endif }
/* Add another thread for file capture to disk or network * When settings are changed, snort must be restarted to get it applied */ void file_agent_init(FileInspectConf* conf) { int rval; const struct timespec thread_sleep = { 0, 100 }; sigset_t mask; /*Need to check configuration to decide whether to enable them*/ if (conf->file_type_enabled) { _dpd.fileAPI->enable_file_type(file_agent_type_callback); file_type_enabled = true; } if (conf->file_signature_enabled) { _dpd.fileAPI->enable_file_signature(file_agent_signature_callback); file_signature_enabled = true; } if (conf->file_capture_enabled) { _dpd.fileAPI->enable_file_capture(file_agent_signature_callback); file_capture_enabled = true; } if (conf->hostname) { file_agent_init_socket(conf->hostname, conf->portno); } /* Spin off the file capture handler thread. */ sigemptyset(&mask); sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGQUIT); sigaddset(&mask, SIGPIPE); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGUSR1); sigaddset(&mask, SIGUSR2); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGURG); sigaddset(&mask, SIGVTALRM); pthread_sigmask(SIG_SETMASK, &mask, NULL); file_list = cbuffer_init(conf->file_capture_queue_size); if(!file_list) { FILE_FATAL_ERROR("File capture: Unable to create file capture queue!"); } if ((rval = pthread_create(&capture_thread_tid, NULL, &FileCaptureThread, conf)) != 0) { sigemptyset(&mask); pthread_sigmask(SIG_SETMASK, &mask, NULL); FILE_FATAL_ERROR("File capture: Unable to create a " "processing thread: %s", strerror(rval)); } while (!capture_thread_running) nanosleep(&thread_sleep, NULL); sigemptyset(&mask); pthread_sigmask(SIG_SETMASK, &mask, NULL); _dpd.logMsg("File capture thread started tid=%p (pid=%u)\n", (void *) capture_thread_tid, capture_thread_pid); }
/* * Load file list signature file * * Arguments: * filename: file name string * FileSigInfo *: The file signature information. * FileInspectConf *: The configuration to be update. * * Returns: * None */ static void file_config_signature(char *filename, FileSigInfo *sig_info, FileInspectConf *config) { FILE *fp = NULL; char linebuf[MAX_SIG_LINE_LENGTH]; char full_path_filename[PATH_MAX+1]; int line_number = 0; /* check table first, create one if not exist*/ if (config->sig_table == NULL) { config->sig_table = sha_table_new(SHA256_HASH_SIZE); } if (config->sig_table == NULL) { FILE_FATAL_ERROR("%s(%d) Could not create file signature hash.\n", *(_dpd.config_file), *(_dpd.config_line)); } /* parse the file line by line, each signature one entry*/ _dpd.logMsg("File inspect: processing file %s\n", filename); UpdatePathToFile(full_path_filename, PATH_MAX, filename); if((fp = fopen(full_path_filename, "r")) == NULL) { char errBuf[STD_BUF]; #ifdef WIN32 snprintf(errBuf, STD_BUF, "%s", strerror(errno)); #else strerror_r(errno, errBuf, STD_BUF); #endif errBuf[STD_BUF-1] = '\0'; FILE_FATAL_ERROR("%s(%d) => Unable to open signature file %s, " "Error: %s\n", *(_dpd.config_file), *(_dpd.config_line), filename, errBuf); return; } while( fgets(linebuf, MAX_SIG_LINE_LENGTH, fp) ) { char *cmt = NULL; char *sha256; FileSigInfo *old_info; DEBUG_WRAP(DebugMessage(DEBUG_FILE, "File signatures: %s\n",linebuf );); line_number++; /* Remove comments */ if( (cmt = strchr(linebuf, '#')) ) *cmt = '\0'; /* Remove newline as well, prevent double newline in logging.*/ if( (cmt = strchr(linebuf, '\n')) ) *cmt = '\0'; if (!strlen(linebuf)) continue; sha256 = malloc(SHA256_HASH_SIZE); if (!sha256) { FILE_FATAL_ERROR("%s(%d) => No memory for file: %s (%d), \n" "signature: %s\n", *(_dpd.config_file), *(_dpd.config_line), filename, line_number, linebuf); } if (str_to_sha(linebuf, sha256, strlen(linebuf)) < 0) { FILE_FATAL_ERROR("%s(%d) => signature format at file: %s (%d), \n" "signature: %s\n", *(_dpd.config_file), *(_dpd.config_line), filename, line_number, linebuf); } old_info = (FileSigInfo *)sha_table_find(config->sig_table, sha256); if (old_info) { free(sha256); _dpd.errMsg("%s(%d) => signature redefined at file: %s (%d), \n" "signature: %s\n", *(_dpd.config_file), *(_dpd.config_line), filename, line_number, linebuf); } else { sha_table_add(config->sig_table, sha256, sig_info); } }