int main(int argc, char **argv) { FILE *fp; // Bucket to keep pids in. 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 gid = 0, client_sock = 0, sock = 0, port = 1515, ret = 0; char *dir = DEFAULTDIR; char *user = USER; char *group = GROUPGLOBAL; // TODO: implement or delete char *cfg __attribute__((unused)) = DEFAULTCPATH; char buf[4096 +1]; SSL_CTX *ctx; SSL *ssl; char srcip[IPSIZE +1]; struct sockaddr_in _nc; socklen_t _ncl; /* Initializing some variables */ memset(srcip, '\0', IPSIZE + 1); memset(process_pool, 0x0, POOL_SIZE); bio_err = 0; /* Setting the name */ OS_SetName(ARGV0); /* add an option to use the ip on the socket to tie the name to a specific address */ while((c = getopt(argc, argv, "Vdhiu:g:D:c:m:p:")) != -1) { switch(c){ case 'V': print_version(); break; case 'h': report_help(); break; case 'd': nowDebug(); break; case 'i': use_ip_address = 1; break; case 'u': if(!optarg) ErrorExit("%s: -u needs an argument",ARGV0); user = optarg; break; case 'g': if(!optarg) ErrorExit("%s: -g needs an argument",ARGV0); group = optarg; break; case 'D': if(!optarg) ErrorExit("%s: -D needs an argument",ARGV0); dir = optarg; break; case 'c': if(!optarg) ErrorExit("%s: -c needs an argument",ARGV0); cfg = optarg; break; case 't': test_config = 1; break; case 'p': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); port = atoi(optarg); if(port <= 0 || port >= 65536) { ErrorExit("%s: Invalid port: %s", ARGV0, optarg); } break; default: report_help(); break; } } /* Starting daemon -- NB: need to double fork and setsid */ debug1(STARTED_MSG,ARGV0); /* Check if the user/group given are valid */ gid = Privsep_GetGroup(group); if(gid < 0) ErrorExit(USER_ERROR,ARGV0,user,group); /* Exit here if test config is set */ if(test_config) exit(0); /* Privilege separation */ if(Privsep_SetGroup(gid) < 0) ErrorExit(SETGID_ERROR,ARGV0,group); /* chrooting -- TODO: this isn't a chroot. Should also close unneeded open file descriptors (like stdin/stdout)*/ chdir(dir); /* Signal manipulation */ StartSIG(ARGV0); /* Creating PID files */ if(CreatePID(ARGV0, getpid()) < 0) ErrorExit(PID_ERROR,ARGV0); /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); fp = fopen(KEYSFILE_PATH,"a"); if(!fp) { merror("%s: ERROR: Unable to open %s (key file)", ARGV0, KEYSFILE_PATH); exit(1); } /* Starting SSL */ ctx = os_ssl_keys(0, dir); if(!ctx) { merror("%s: ERROR: SSL error. Exiting.", ARGV0); exit(1); } /* Connecting via TCP */ sock = OS_Bindporttcp(port, NULL, 0); if(sock <= 0) { merror("%s: Unable to bind to port %d", ARGV0, port); exit(1); } fcntl(sock, F_SETFL, O_NONBLOCK); debug1("%s: DEBUG: Going into listening mode.", ARGV0); while(1) { // no need to completely pin the cpu, 100ms should be fast enough usleep(100*1000); // Only check process-pool if we have active processes if(active_processes > 0){ for (i = 0; i < POOL_SIZE; i++) { int rv = 0; status = 0; if (process_pool[i]) { rv = waitpid(process_pool[i], &status, WNOHANG); if (rv != 0){ debug1("%s: DEBUG: Process %d exited", ARGV0, process_pool[i]); process_pool[i] = 0; active_processes = active_processes - 1; } } } } memset(&_nc, 0, sizeof(_nc)); _ncl = sizeof(_nc); if((client_sock = accept(sock, (struct sockaddr *) &_nc, &_ncl)) > 0){ if (active_processes >= POOL_SIZE) { merror("%s: Error: Max concurrency reached. Unable to fork", ARGV0); break; } pid = fork(); if(pid) { active_processes = active_processes + 1; close(client_sock); for (i = 0; i < POOL_SIZE; i++) { if (! process_pool[i]) { process_pool[i] = pid; break; } } } else { strncpy(srcip, inet_ntoa(_nc.sin_addr),IPSIZE -1); char *agentname = NULL; ssl = SSL_new(ctx); SSL_set_fd(ssl, client_sock); do { ret = SSL_accept(ssl); if (ssl_error(ssl, ret)) clean_exit(ctx, client_sock); } while (ret <= 0); verbose("%s: INFO: New connection from %s", ARGV0, srcip); do { ret = SSL_read(ssl, buf, sizeof(buf)); if (ssl_error(ssl, ret)) clean_exit(ctx, client_sock); } while (ret <= 0); int parseok = 0; if(strncmp(buf, "OSSEC A:'", 9) == 0) { char *tmpstr = buf; agentname = tmpstr + 9; tmpstr += 9; while(*tmpstr != '\0') { if(*tmpstr == '\'') { *tmpstr = '\0'; verbose("%s: INFO: Received request for a new agent (%s) from: %s", ARGV0, agentname, srcip); parseok = 1; break; } tmpstr++; } } if(parseok == 0) { merror("%s: ERROR: Invalid request for new agent from: %s", ARGV0, srcip); } else { int acount = 2; char fname[2048 +1]; char response[2048 +1]; char *finalkey = NULL; response[2048] = '\0'; fname[2048] = '\0'; if(!OS_IsValidName(agentname)) { merror("%s: ERROR: Invalid agent name: %s from %s", ARGV0, agentname, srcip); snprintf(response, 2048, "ERROR: Invalid agent name: %s\n\n", agentname); ret = SSL_write(ssl, response, strlen(response)); snprintf(response, 2048, "ERROR: Unable to add agent.\n\n"); ret = SSL_write(ssl, response, strlen(response)); sleep(1); exit(0); } /* Checking for a duplicated names. */ strncpy(fname, agentname, 2048); while(NameExist(fname)) { snprintf(fname, 2048, "%s%d", agentname, acount); acount++; if(acount > 256) { merror("%s: ERROR: Invalid agent name %s (duplicated)", ARGV0, agentname); snprintf(response, 2048, "ERROR: Invalid agent name: %s\n\n", agentname); ret = SSL_write(ssl, response, strlen(response)); snprintf(response, 2048, "ERROR: Unable to add agent.\n\n"); ret = SSL_write(ssl, response, strlen(response)); sleep(1); exit(0); } } agentname = fname; /* Adding the new agent. */ if (use_ip_address) { finalkey = OS_AddNewAgent(agentname, srcip, NULL, NULL); } else { finalkey = OS_AddNewAgent(agentname, NULL, 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); ret = SSL_write(ssl, response, strlen(response)); snprintf(response, 2048, "ERROR: Unable to add agent.\n\n"); ret = SSL_write(ssl, response, strlen(response)); sleep(1); exit(0); } snprintf(response, 2048,"OSSEC K:'%s'\n\n", finalkey); verbose("%s: INFO: Agent key generated for %s (requested by %s)", ARGV0, agentname, srcip); ret = SSL_write(ssl, response, strlen(response)); if(ret < 0) { merror("%s: ERROR: SSL write error (%d)", ARGV0, ret); merror("%s: ERROR: Agen key not saved for %s", ARGV0, agentname); ERR_print_errors_fp(stderr); } else { verbose("%s: INFO: Agent key created for %s (requested by %s)", ARGV0, agentname, srcip); } } clean_exit(ctx, client_sock); } } } /* Shutdown the socket */ clean_exit(ctx, sock); return (0); }
static int handle_options(const unsigned char *opt) { const unsigned char *n = NULL, *p; if (!strcmp("--version", opt)) { report_version(); } else if (!strcmp("--help", opt)) { report_help(); } else if ((p = check_option("--stdin", opt))) { stdin_file = p; } else if ((p = check_option("--stdout", opt))) { stdout_file = p; } else if ((p = check_option("--stderr", opt))) { stderr_file = p; } else if ((p = check_option("--workdir", opt))) { working_dir = p; } else if ((p = check_option("--test-file", opt))) { test_file = p; } else if ((p = check_option("--corr-file", opt))) { corr_file = p; } else if ((p = check_option("--info-file", opt))) { info_file = p; } else if ((p = check_option("--input-file", opt))) { input_file = p; } else if ((p = check_option("--output-file", opt))) { output_file = p; } else if (!strcmp("--clear-env", opt)) { clear_env_flag = 1; } else if ((p = check_option("--env", opt))) { xexpand(&env_vars); env_vars.v[env_vars.u++] = xstrdup(p); } else if ((p = check_option((n = "--time-limit"), opt))) { parse_int(n, p, &time_limit, 1, 99999); } else if ((p = check_option((n = "--time-limit-millis"), opt))) { parse_int(n, p, &time_limit_millis, 1, 999999999); } else if ((p = check_option((n = "--real-time-limit"), opt))) { parse_int(n, p, &real_time_limit, 1, 99999); } else if (!strcmp("--no-core-dump", opt)) { no_core_dump = 1; } else if ((p = check_option("--kill-signal", opt))) { kill_signal = p; } else if (!strcmp("--memory-limit", opt)) { memory_limit = 1; } else if (!strcmp("--secure-exec", opt)) { secure_exec = 1; } else if (!strcmp("--security-violation", opt)) { security_violation = 1; } else if (!strcmp("--use-stdin", opt)) { use_stdin = 1; } else if (!strcmp("--use-stdout", opt)) { use_stdout = 1; } else if ((p = check_option((n = "--max-vm-size"), opt))) { parse_size(n, p, &max_vm_size, 4096); } else if ((p = check_option((n = "--max-stack-size"), opt))) { parse_size(n, p, &max_stack_size, 4096); } else if ((p = check_option((n = "--max-data-size"), opt))) { parse_size(n, p, &max_data_size, 4096); } else if ((p = check_option((n = "--mode"), opt))) { parse_mode(n, p, &mode); } else if ((p = check_option((n = "--group"), opt))) { parse_group(n, p, &group); } else if ((p = check_option((n = "--test-num"), opt))) { parse_int(n, p, &test_num, 1, 99999); } else if ((p = check_option("--test-pattern", opt))) { test_pattern = p; } else if ((p = check_option("--corr-pattern", opt))) { corr_pattern = p; } else if ((p = check_option("--info-pattern", opt))) { info_pattern = p; } else if ((p = check_option("--tgzdir-pattern", opt))) { tgzdir_pattern = p; } else if (!strcmp("--update-corr", opt)) { update_corr = 1; } else if ((p = check_option("--test-dir", opt))) { test_dir = p; } else if (!strcmp("--all-tests", opt)) { all_tests = 1; } else if (!strcmp("--quiet", opt)) { quiet_flag = 1; } else if (!strcmp("--", opt)) { return 1; } else if (!strncmp("--", opt, 2)) { fatal("invalid option %s"); } else { return 2; } return 0; }
int main(int argc, char **argv) { int c, test_config = 0; int uid=0,gid=0; int do_chroot = 0; char *dir = DEFAULTDIR; char *user = USER; char *group = GROUPGLOBAL; char *cfg = DEFAULTCPATH; char *filter_by = NULL; char *filter_value = NULL; char *related_of = NULL; char *related_values = NULL; report_filter r_filter; /* Setting the name */ OS_SetName(ARGV0); r_filter.group = NULL; r_filter.rule = NULL; r_filter.level = NULL; r_filter.location = NULL; r_filter.srcip = NULL; r_filter.user = NULL; r_filter.files = NULL; r_filter.show_alerts = 0; r_filter.related_group = 0; r_filter.related_rule = 0; r_filter.related_level = 0; r_filter.related_location = 0; r_filter.related_srcip = 0; r_filter.related_user = 0; r_filter.related_file = 0; r_filter.report_name = NULL; while((c = getopt(argc, argv, "Vdhstu:g:D:c:f:v:n:r:NC")) != -1) { switch(c){ case 'V': print_version(); break; case 'h': report_help(); break; case 'd': nowDebug(); break; case 'n': if(!optarg) ErrorExit("%s: -n needs an argument",ARGV0); r_filter.report_name = optarg; break; case 'r': if(!optarg || !argv[optind]) ErrorExit("%s: -r needs two argument",ARGV0); related_of = optarg; related_values = argv[optind]; if(os_report_configfilter(related_of, related_values, &r_filter, REPORT_RELATED) < 0) { ErrorExit(CONFIG_ERROR, ARGV0, "user argument"); } optind++; break; case 'f': if(!optarg) ErrorExit("%s: -f needs two argument",ARGV0); filter_by = optarg; filter_value = argv[optind]; if(os_report_configfilter(filter_by, filter_value, &r_filter, REPORT_FILTER) < 0) { ErrorExit(CONFIG_ERROR, ARGV0, "user argument"); } optind++; break; case 'u': if(!optarg) ErrorExit("%s: -u needs an argument",ARGV0); user=optarg; break; case 'g': if(!optarg) ErrorExit("%s: -g needs an argument",ARGV0); group=optarg; break; case 'D': if(!optarg) ErrorExit("%s: -D needs an argument",ARGV0); dir=optarg; break; case 'c': if(!optarg) ErrorExit("%s: -c needs an argument",ARGV0); cfg = optarg; break; case 't': test_config = 1; break; case 's': r_filter.show_alerts = 1; break; case 'N': do_chroot = 0; break; case 'C': do_chroot = 1; break; default: report_help(); break; } } /* Starting daemon */ debug1(STARTED_MSG,ARGV0); /* Check if the user/group given are valid */ uid = Privsep_GetUser(user); gid = Privsep_GetGroup(group); if((uid < 0)||(gid < 0)) ErrorExit(USER_ERROR,ARGV0,user,group); /* Exit here if test config is set */ if(test_config) exit(0); /* Privilege separation */ if(Privsep_SetGroup(gid) < 0) ErrorExit(SETGID_ERROR,ARGV0,group); /* chrooting */ if (do_chroot) { if(Privsep_Chroot(dir) < 0) ErrorExit(CHROOT_ERROR,ARGV0,dir); nowChroot(); } else { chdir(dir); } /* Changing user */ if(Privsep_SetUser(uid) < 0) ErrorExit(SETUID_ERROR,ARGV0,user); debug1(PRIVSEP_MSG,ARGV0,dir,user); /* Signal manipulation */ StartSIG(ARGV0); /* Creating PID files */ if(CreatePID(ARGV0, getpid()) < 0) ErrorExit(PID_ERROR,ARGV0); /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); /* the real stuff now */ os_ReportdStart(&r_filter); exit(0); }
int main(int argc, char **argv) { int c, test_config = 0; #ifndef WIN32 int gid = 0; #endif int sock = 0, port = 1515, ret = 0; char *dir = DEFAULTDIR; char *user = USER; char *group = GROUPGLOBAL; char *cfg = DEFAULTCPATH; char *manager = NULL; char *agentname = NULL; char lhostname[512 + 1]; char buf[2048 +1]; SSL_CTX *ctx; SSL *ssl; BIO *sbio; bio_err = 0; buf[2048] = '\0'; /* Setting the name */ OS_SetName(ARGV0); while((c = getopt(argc, argv, "Vdhu:g:D:c:m:p:A:")) != -1) { switch(c) { case 'V': print_version(); break; case 'h': report_help(); break; case 'd': nowDebug(); break; case 'u': if(!optarg) ErrorExit("%s: -u needs an argument",ARGV0); user=optarg; break; case 'g': if(!optarg) ErrorExit("%s: -g needs an argument",ARGV0); group=optarg; break; case 'D': if(!optarg) ErrorExit("%s: -D needs an argument",ARGV0); dir=optarg; break; case 'c': if(!optarg) ErrorExit("%s: -c needs an argument",ARGV0); cfg = optarg; break; case 't': test_config = 1; break; case 'm': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); manager = optarg; break; case 'A': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); agentname = optarg; break; case 'p': if(!optarg) ErrorExit("%s: -%c needs an argument",ARGV0, c); port = atoi(optarg); if(port <= 0 || port >= 65536) { ErrorExit("%s: Invalid port: %s", ARGV0, optarg); } break; default: report_help(); break; } } /* Starting daemon */ debug1(STARTED_MSG,ARGV0); #ifndef WIN32 /* Check if the user/group given are valid */ gid = Privsep_GetGroup(group); if(gid < 0) ErrorExit(USER_ERROR,ARGV0,user,group); /* Privilege separation */ if(Privsep_SetGroup(gid) < 0) ErrorExit(SETGID_ERROR,ARGV0,group); /* Signal manipulation */ StartSIG(ARGV0); /* Creating PID files */ if(CreatePID(ARGV0, getpid()) < 0) ErrorExit(PID_ERROR,ARGV0); #endif /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); if(agentname == NULL) { lhostname[512] = '\0'; if(gethostname(lhostname, 512 -1) != 0) { merror("%s: ERROR: Unable to extract hostname. Custom agent name not set.", ARGV0); exit(1); } agentname = lhostname; } /* Starting SSL */ ctx = os_ssl_keys(1, NULL); if(!ctx) { merror("%s: ERROR: SSL error. Exiting.", ARGV0); exit(1); } if(!manager) { merror("%s: ERROR: Manager IP not set.", ARGV0); exit(1); } /* Check to see if manager is an IP */ int is_ip = 1; struct sockaddr_in iptest; memset(&iptest, 0, sizeof(iptest)); if(inet_pton(AF_INET, manager, &iptest.sin_addr) != 1) is_ip = 0; /* This is not an IPv4 address */ /* Not IPv4, IPv6 maybe? */ if(is_ip == 0) { struct sockaddr_in6 iptest6; memset(&iptest6, 0, sizeof(iptest6)); if(inet_pton(AF_INET6, manager, &iptest6.sin6_addr) != 1) is_ip = 0; else is_ip = 1; /* This is an IPv6 address */ } /* If it isn't an ip, try to resolve the IP */ if(is_ip == 0) { char *ipaddress; ipaddress = OS_GetHost(manager, 3); if(ipaddress != NULL) strncpy(manager, ipaddress, 16); else { printf("Could not resolve hostname: %s\n", manager); return(1); } } /* Connecting via TCP */ sock = OS_ConnectTCP(port, manager, 0); if(sock <= 0) { merror("%s: Unable to connect to %s:%d", ARGV0, manager, port); exit(1); } /* Connecting the SSL socket */ ssl = SSL_new(ctx); sbio = BIO_new_socket(sock, BIO_NOCLOSE); SSL_set_bio(ssl, sbio, sbio); ret = SSL_connect(ssl); if(ret <= 0) { ERR_print_errors_fp(stderr); merror("%s: ERROR: SSL error (%d). Exiting.", ARGV0, ret); exit(1); } printf("INFO: Connected to %s:%d\n", manager, port); printf("INFO: Using agent name as: %s\n", agentname); snprintf(buf, 2048, "OSSEC A:'%s'\n", agentname); ret = SSL_write(ssl, buf, strlen(buf)); if(ret < 0) { printf("SSL write error (unable to send message.)\n"); ERR_print_errors_fp(stderr); exit(1); } printf("INFO: Send request to manager. Waiting for reply.\n"); while(1) { ret = SSL_read(ssl,buf,sizeof(buf) -1); switch(SSL_get_error(ssl,ret)) { case SSL_ERROR_NONE: buf[ret] = '\0'; if(strncmp(buf, "ERROR", 5) == 0) { char *tmpstr; tmpstr = strchr(buf, '\n'); if(tmpstr) *tmpstr = '\0'; printf("%s (from manager)\n", buf); } else if(strncmp(buf, "OSSEC K:'",9) == 0) { char *key; char *tmpstr; char **entry; printf("INFO: Received response with agent key\n"); key = buf; key += 9; tmpstr = strchr(key, '\''); if(!tmpstr) { printf("ERROR: Invalid key received. Closing connection.\n"); exit(1); } *tmpstr = '\0'; entry = OS_StrBreak(' ', key, 4); if(!OS_IsValidID(entry[0]) || !OS_IsValidName(entry[1]) || !OS_IsValidName(entry[2]) || !OS_IsValidName(entry[3])) { printf("ERROR: Invalid key received (2). Closing connection.\n"); exit(1); } { FILE *fp; fp = fopen(KEYSFILE_PATH,"w"); if(!fp) { printf("ERROR: Unable to open key file: %s", KEYSFILE_PATH); exit(1); } fprintf(fp, "%s\n", key); fclose(fp); } printf("INFO: Valid key created. Finished.\n"); } break; case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_SYSCALL: printf("INFO: Connection closed.\n"); exit(0); break; default: printf("ERROR: SSL read (unable to receive message)\n"); exit(1); break; } } /* Shutdown the socket */ SSL_CTX_free(ctx); close(sock); exit(0); }