X-Git-Url: http://ftp.carnet.hr/carnet-debian/scm?a=blobdiff_plain;f=src%2Fos_auth%2Fmain-client.c;h=762c3e20f9acf7954cc3e518230bf9807bb64a7b;hb=3f728675941dc69d4e544d3a880a56240a6e394a;hp=6397ea3f13c066aca24171f59cc89e869a39c84b;hpb=789cbc8e52da68eba3517b920ef22e000cf3c9fd;p=ossec-hids.git diff --git a/src/os_auth/main-client.c b/src/os_auth/main-client.c old mode 100755 new mode 100644 index 6397ea3..762c3e2 --- a/src/os_auth/main-client.c +++ b/src/os_auth/main-client.c @@ -1,6 +1,3 @@ -/* @(#) $Id: ./src/os_auth/main-client.c, 2012/02/07 dcid Exp $ - */ - /* Copyright (C) 2010 Trend Micro Inc. * All rights reserved. * @@ -25,9 +22,12 @@ * */ +#include +#include #include "shared.h" +#include "check_cert.h" -#ifndef USE_OPENSSL +#ifndef LIBOPENSSL_ENABLED int main() { @@ -35,248 +35,292 @@ int main() exit(0); } - #else #include #include "auth.h" +static void help_agent_auth(void) __attribute__((noreturn)); - -void report_help() +/* Print help statement */ +static void help_agent_auth() { - printf("\nOSSEC HIDS %s: Connects to the manager to extract the agent key.\n", ARGV0); - printf("Available options:\n"); - printf("\t-h This help message.\n"); - printf("\t-m Manager IP Address.\n"); - printf("\t-p Manager port (default 1515).\n"); - printf("\t-A Agent name (default is the hostname).\n"); - printf("\t-D Location where OSSEC is installed.\n"); + print_header(); + print_out(" %s: -[Vhdt] [-g group] [-D dir] [-m IP address] [-p port] [-A name] [-c ciphers] [-v path] [-x path] [-k path]", ARGV0); + print_out(" -V Version and license message"); + print_out(" -h This help message"); + print_out(" -d Execute in debug mode. This parameter"); + print_out(" can be specified multiple times"); + print_out(" to increase the debug level."); + print_out(" -t Test configuration"); + print_out(" -g Group to run as (default: %s)", GROUPGLOBAL); + print_out(" -D Directory to chroot into (default: %s)", DEFAULTDIR); + print_out(" -m Manager IP address"); + print_out(" -p Manager port (default: %s)", DEFAULT_PORT); + print_out(" -A Agent name (default: hostname)"); + print_out(" -c SSL cipher list (default: %s)", DEFAULT_CIPHERS); + print_out(" -v Full path to CA certificate used to verify the server"); + print_out(" -x Full path to agent certificate"); + print_out(" -k Full path to agent key"); + print_out(" -P Authorization password file [default: /var/ossec/etc/authd.pass"); + print_out(" "); exit(1); } - - int main(int argc, char **argv) { + int key_added = 0; int c; - // TODO: implement or delete - int test_config __attribute__((unused)) = 0; - #ifndef WIN32 - int gid = 0; - #endif - - int sock = 0, port = 1515, ret = 0; - // TODO: implement or delete - char *dir __attribute__((unused)) = DEFAULTDIR; - char *user = USER; - char *group = GROUPGLOBAL; - // TODO: implement or delete - char *cfg __attribute__((unused)) = DEFAULTCPATH; - char *manager = NULL; - char *agentname = NULL; + int test_config = 0; + int authenticate = 0; +#ifndef WIN32 + gid_t gid = 0; +#endif + + int sock = 0, portnum, ret = 0; + char *port = DEFAULT_PORT; + char *ciphers = DEFAULT_CIPHERS; + const char *dir = DEFAULTDIR; + const char *group = GROUPGLOBAL; + char *authpass = NULL; + const char *manager = NULL; + const char *agentname = NULL; + const char *agent_cert = NULL; + const char *agent_key = NULL; + const char *ca_cert = NULL; char lhostname[512 + 1]; - char buf[2048 +1]; + char buf[4096 + 1]; SSL_CTX *ctx; SSL *ssl; BIO *sbio; - - bio_err = 0; - buf[2048] = '\0'; + buf[4096] = '\0'; +#ifdef WIN32 + WSADATA wsaData; +#endif - /* Setting the name */ + /* Set the name */ OS_SetName(ARGV0); - while((c = getopt(argc, argv, "Vdhu:g:D:c:m:p:A:")) != -1) - { - switch(c){ + while ((c = getopt(argc, argv, "Vdhtg:m:p:A:c:v:x:k:D:P:")) != -1) { + switch (c) { case 'V': print_version(); break; case 'h': - report_help(); + help_agent_auth(); 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; + 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; + if (!optarg) { + ErrorExit("%s: -g needs an argument", ARGV0); + } + dir = optarg; + break; case 't': test_config = 1; break; case 'm': - if(!optarg) - ErrorExit("%s: -%c needs an argument",ARGV0, c); + 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); + 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) - { + if (!optarg) { + ErrorExit("%s: -%c needs an argument", ARGV0, c); + } + portnum = atoi(optarg); + if (portnum <= 0 || portnum >= 65536) { ErrorExit("%s: Invalid port: %s", ARGV0, optarg); } + port = optarg; + break; + case 'c': + if (!optarg) { + ErrorExit("%s: -%c needs an argument", ARGV0, c); + } + ciphers = optarg; + break; + case 'v': + if (!optarg) { + ErrorExit("%s: -%c needs an argument", ARGV0, c); + } + ca_cert = optarg; + break; + case 'x': + if (!optarg) { + ErrorExit("%s: -%c needs an argument", ARGV0, c); + } + agent_cert = optarg; + break; + case 'k': + if (!optarg) { + ErrorExit("%s: -%c needs an argument", ARGV0, c); + } + agent_key = optarg; + break; + case 'P': + if (!optarg) { + ErrorExit("%s: -%c needs an argument", ARGV0, c); + } + authpass = optarg; + authenticate++; break; default: - report_help(); + help_agent_auth(); break; } } - /* Starting daemon */ - debug1(STARTED_MSG,ARGV0); + /* Start daemon */ + debug1(STARTED_MSG, ARGV0); - - #ifndef WIN32 +#ifndef WIN32 /* Check if the user/group given are valid */ gid = Privsep_GetGroup(group); - if(gid < 0) - ErrorExit(USER_ERROR,ARGV0,user,group); - + if (gid == (gid_t) - 1) { + ErrorExit(USER_ERROR, ARGV0, "", 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); - - + if (Privsep_SetGroup(gid) < 0) { + ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno)); + } /* Signal manipulation */ StartSIG(ARGV0); - - - /* Creating PID files */ - if(CreatePID(ARGV0, getpid()) < 0) - ErrorExit(PID_ERROR,ARGV0); - #endif - + /* Create PID files */ + if (CreatePID(ARGV0, getpid()) < 0) { + ErrorExit(PID_ERROR, ARGV0); + } +#else + /* Initialize Windows socket stuff */ + if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { + ErrorExit("%s: WSAStartup() failed", ARGV0); + } +#endif /* WIN32 */ /* Start up message */ verbose(STARTUP_MSG, ARGV0, (int)getpid()); - - if(agentname == NULL) - { + if (agentname == NULL) { lhostname[512] = '\0'; - if(gethostname(lhostname, 512 -1) != 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) - { + /* Start SSL */ + ctx = os_ssl_keys(0, dir, ciphers, agent_cert, agent_key, ca_cert); + if (!ctx) { merror("%s: ERROR: SSL error. Exiting.", ARGV0); exit(1); } - if(!manager) - { + if (!manager) { merror("%s: ERROR: Manager IP not set.", ARGV0); exit(1); } + /* Checking if there is a custom password file */ + if (authpass != NULL && authenticate > 0) { + FILE *fp; + fp = fopen(authpass, "r"); + if(!fp) { + fprintf(stderr, "Cannot open %s: %s\n", authpass, strerror(errno)); + exit(1); + } + buf[0] = '\0'; - /* 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 (fp) { + buf[4096] = '\0'; + fgets(buf, 4095, fp); + if (strlen(buf) > 2) { + authpass = strndup(buf, 32); + if(!authpass) { + fprintf(stderr, "Could not set the authpass: %s", strerror(errno)); + exit(1); + } + } - /* 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); + fclose(fp); + printf("INFO: Using specified password.\n"); } } + if (!authpass) { + printf("WARN: No authentication password provided. Insecure mode started.\n"); + } - - /* Connecting via TCP */ - sock = OS_ConnectTCP(port, manager, 0); - if(sock <= 0) - { - merror("%s: Unable to connect to %s:%d", ARGV0, manager, port); + /* Connect via TCP */ + sock = OS_ConnectTCP(port, manager); + if (sock <= 0) { + merror("%s: Unable to connect to %s:%s", ARGV0, manager, port); exit(1); } - - /* Connecting the SSL socket */ + /* Connect 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) - { + if (ret <= 0) { ERR_print_errors_fp(stderr); merror("%s: ERROR: SSL error (%d). Exiting.", ARGV0, ret); exit(1); } + printf("INFO: Connected to %s:%s\n", manager, port); + + /* Additional verification of the manager's certificate if a hostname + * rather than an IP address is given on the command line. Could change + * this to do the additional validation on IP addresses as well if needed. + */ + if (ca_cert) { + printf("INFO: Verifying manager's certificate\n"); + if (check_x509_cert(ssl, manager) != VERIFY_TRUE) { + debug1("%s: DEBUG: Unable to verify server certificate.", ARGV0); + exit(1); + } + } - printf("INFO: Connected to %s:%d\n", manager, port); printf("INFO: Using agent name as: %s\n", agentname); + memset(buf, 0, sizeof(buf)); + if (authpass) { + snprintf(buf, 2048, "OSSEC PASS: %s OSSEC A:'%s'\n", authpass, agentname); + } + else { + snprintf(buf, 2048, "OSSEC A:'%s'\n", agentname); + } - snprintf(buf, 2048, "OSSEC A:'%s'\n", agentname); ret = SSL_write(ssl, buf, strlen(buf)); - if(ret < 0) - { + if (ret < 0) { printf("SSL write error (unable to send message.)\n"); ERR_print_errors_fp(stderr); exit(1); @@ -284,22 +328,19 @@ int main(int argc, char **argv) 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)) - { + 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) - { + if (strncmp(buf, "ERROR", 5) == 0) { char *tmpstr; tmpstr = strchr(buf, '\n'); - if(tmpstr) *tmpstr = '\0'; + if (tmpstr) { + *tmpstr = '\0'; + } printf("%s (from manager)\n", buf); - } - else if(strncmp(buf, "OSSEC K:'",9) == 0) - { + } else if (strncmp(buf, "OSSEC K:'", 9) == 0) { char *key; char *tmpstr; char **entry; @@ -308,36 +349,37 @@ int main(int argc, char **argv) key = buf; key += 9; tmpstr = strchr(key, '\''); - if(!tmpstr) - { + 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])) - { + 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) - { + 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); } + key_added = 1; printf("INFO: Valid key created. Finished.\n"); } break; case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_SYSCALL: + if (key_added == 0) { + printf("ERROR: Unable to create key. Either wrong password or connection not accepted by the manager.\n"); + } printf("INFO: Connection closed.\n"); exit(0); break; @@ -349,14 +391,14 @@ int main(int argc, char **argv) } - - - /* Shutdown the socket */ + /* Shut down the socket */ + if (key_added == 0) { + printf("ERROR: Unable to create key. Either wrong password or connection not accepted by the manager.\n"); + } SSL_CTX_free(ctx); close(sock); exit(0); } -#endif -/* EOF */ +#endif /* LIBOPENSSL_ENABLED */