X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?p=ossec-hids.git;a=blobdiff_plain;f=src%2Fos_auth%2Fmain-server.c;fp=src%2Fos_auth%2Fmain-server.c;h=cf7982a760ca1df1a31375cfd175b014c7d546b4;hp=0000000000000000000000000000000000000000;hb=ff0e686ac67bbd82b60c277eb324910dbc60f65f;hpb=33a81e69474ae91ecec4e991debe59e26bb330fd diff --git a/src/os_auth/main-server.c b/src/os_auth/main-server.c new file mode 100755 index 0000000..cf7982a --- /dev/null +++ b/src/os_auth/main-server.c @@ -0,0 +1,379 @@ +/* @(#) $Id$ */ + +/* Copyright (C) 2010 Trend Micro Inc. + * All rights reserved. + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 2) as published by the FSF - Free Software + * Foundation + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + * + */ + + +#include "shared.h" +#include "auth.h" + +/* TODO: Pulled this value out of the sky, may or may not be sane */ +int POOL_SIZE = 512; + +/* ossec-reportd - Runs manual reports. */ +void report_help() +{ +} + +#ifndef USE_OPENSSL +int main() +{ + printf("ERROR: Not compiled. Missing OpenSSL support.\n"); + exit(0); +} +#else + + +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; + char *cfg = 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 + usleep(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); + ret = SSL_accept(ssl); + if(ret <= 0) + { + merror("%s: ERROR: SSL Accept error (%d)", ARGV0, ret); + ERR_print_errors_fp(stderr); + } + + verbose("%s: INFO: New connection from %s", ARGV0, srcip); + + ret = SSL_read(ssl, buf, sizeof(buf)); + sleep(1); + if(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); + } + } + } + else + { + merror("%s: ERROR: SSL read error (%d)", ARGV0, ret); + ERR_print_errors_fp(stderr); + } + SSL_CTX_free(ctx); + close(client_sock); + exit(0); + } + } + } + + + /* Shutdown the socket */ + SSL_CTX_free(ctx); + close(sock); + + exit(0); +} + + +#endif +/* EOF */