1 /* Copyright (C) 2010 Trend Micro Inc.
4 * This program is a free software; you can redistribute it
5 * and/or modify it under the terms of the GNU General Public
6 * License (version 2) as published by the FSF - Free Software
9 * In addition, as a special exception, the copyright holders give
10 * permission to link the code of portions of this program with the
11 * OpenSSL library under certain conditions as described in each
12 * individual source file, and distribute linked combinations
15 * You must obey the GNU General Public License in all respects
16 * for all of the code used other than OpenSSL. If you modify
17 * file(s) with this exception, you may extend this exception to your
18 * version of the file(s), but you are not obligated to do so. If you
19 * do not wish to do so, delete this exception statement from your
20 * version. If you delete this exception statement from all source
21 * files in the program, then also delete it here.
28 #include "check_cert.h"
30 #ifndef LIBOPENSSL_ENABLED
34 printf("ERROR: Not compiled. Missing OpenSSL support.\n");
40 #include <openssl/ssl.h>
43 static void help_agent_auth(void) __attribute__((noreturn));
45 /* Print help statement */
46 static void help_agent_auth()
49 print_out(" %s: -[Vhdt] [-g group] [-D dir] [-m IP address] [-p port] [-A name] [-c ciphers] [-v path] [-x path] [-k path]", ARGV0);
50 print_out(" -V Version and license message");
51 print_out(" -h This help message");
52 print_out(" -d Execute in debug mode. This parameter");
53 print_out(" can be specified multiple times");
54 print_out(" to increase the debug level.");
55 print_out(" -t Test configuration");
56 print_out(" -g <group> Group to run as (default: %s)", GROUPGLOBAL);
57 print_out(" -D <dir> Directory to chroot into (default: %s)", DEFAULTDIR);
58 print_out(" -m <addr> Manager IP address");
59 print_out(" -p <port> Manager port (default: %s)", DEFAULT_PORT);
60 print_out(" -A <name> Agent name (default: hostname)");
61 print_out(" -c SSL cipher list (default: %s)", DEFAULT_CIPHERS);
62 print_out(" -v <path> Full path to CA certificate used to verify the server");
63 print_out(" -x <path> Full path to agent certificate");
64 print_out(" -k <path> Full path to agent key");
65 print_out(" -P <path> Authorization password file [default: /var/ossec/etc/authd.pass");
70 int main(int argc, char **argv)
80 int sock = 0, portnum, ret = 0;
81 char *port = DEFAULT_PORT;
82 char *ciphers = DEFAULT_CIPHERS;
83 const char *dir = DEFAULTDIR;
84 const char *group = GROUPGLOBAL;
85 char *authpass = NULL;
86 const char *manager = NULL;
87 const char *agentname = NULL;
88 const char *agent_cert = NULL;
89 const char *agent_key = NULL;
90 const char *ca_cert = NULL;
91 char lhostname[512 + 1];
106 while ((c = getopt(argc, argv, "Vdhtg:m:p:A:c:v:x:k:D:P:")) != -1) {
119 ErrorExit("%s: -g needs an argument", ARGV0);
125 ErrorExit("%s: -g needs an argument", ARGV0);
134 ErrorExit("%s: -%c needs an argument", ARGV0, c);
140 ErrorExit("%s: -%c needs an argument", ARGV0, c);
146 ErrorExit("%s: -%c needs an argument", ARGV0, c);
148 portnum = atoi(optarg);
149 if (portnum <= 0 || portnum >= 65536) {
150 ErrorExit("%s: Invalid port: %s", ARGV0, optarg);
156 ErrorExit("%s: -%c needs an argument", ARGV0, c);
162 ErrorExit("%s: -%c needs an argument", ARGV0, c);
168 ErrorExit("%s: -%c needs an argument", ARGV0, c);
174 ErrorExit("%s: -%c needs an argument", ARGV0, c);
180 ErrorExit("%s: -%c needs an argument", ARGV0, c);
192 debug1(STARTED_MSG, ARGV0);
195 /* Check if the user/group given are valid */
196 gid = Privsep_GetGroup(group);
197 if (gid == (gid_t) - 1) {
198 ErrorExit(USER_ERROR, ARGV0, "", group);
201 /* Exit here if test config is set */
206 /* Privilege separation */
207 if (Privsep_SetGroup(gid) < 0) {
208 ErrorExit(SETGID_ERROR, ARGV0, group, errno, strerror(errno));
211 /* Signal manipulation */
214 /* Create PID files */
215 if (CreatePID(ARGV0, getpid()) < 0) {
216 ErrorExit(PID_ERROR, ARGV0);
219 /* Initialize Windows socket stuff */
220 if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
221 ErrorExit("%s: WSAStartup() failed", ARGV0);
225 /* Start up message */
226 verbose(STARTUP_MSG, ARGV0, (int)getpid());
228 if (agentname == NULL) {
229 lhostname[512] = '\0';
230 if (gethostname(lhostname, 512 - 1) != 0) {
231 merror("%s: ERROR: Unable to extract hostname. Custom agent name not set.", ARGV0);
234 agentname = lhostname;
238 ctx = os_ssl_keys(0, dir, ciphers, agent_cert, agent_key, ca_cert);
240 merror("%s: ERROR: SSL error. Exiting.", ARGV0);
245 merror("%s: ERROR: Manager IP not set.", ARGV0);
249 /* Checking if there is a custom password file */
250 if (authpass != NULL && authenticate > 0) {
252 fp = fopen(authpass, "r");
254 fprintf(stderr, "Cannot open %s: %s\n", authpass, strerror(errno));
261 fgets(buf, 4095, fp);
263 if (strlen(buf) > 2) {
264 authpass = strndup(buf, 32);
266 fprintf(stderr, "Could not set the authpass: %s", strerror(errno));
272 printf("INFO: Using specified password.\n");
276 printf("WARN: No authentication password provided. Insecure mode started.\n");
279 /* Connect via TCP */
280 sock = OS_ConnectTCP(port, manager);
282 merror("%s: Unable to connect to %s:%s", ARGV0, manager, port);
286 /* Connect the SSL socket */
288 sbio = BIO_new_socket(sock, BIO_NOCLOSE);
289 SSL_set_bio(ssl, sbio, sbio);
291 ret = SSL_connect(ssl);
293 ERR_print_errors_fp(stderr);
294 merror("%s: ERROR: SSL error (%d). Exiting.", ARGV0, ret);
298 printf("INFO: Connected to %s:%s\n", manager, port);
300 /* Additional verification of the manager's certificate if a hostname
301 * rather than an IP address is given on the command line. Could change
302 * this to do the additional validation on IP addresses as well if needed.
305 printf("INFO: Verifying manager's certificate\n");
306 if (check_x509_cert(ssl, manager) != VERIFY_TRUE) {
307 debug1("%s: DEBUG: Unable to verify server certificate.", ARGV0);
312 printf("INFO: Using agent name as: %s\n", agentname);
314 memset(buf, 0, sizeof(buf));
316 snprintf(buf, 2048, "OSSEC PASS: %s OSSEC A:'%s'\n", authpass, agentname);
319 snprintf(buf, 2048, "OSSEC A:'%s'\n", agentname);
322 ret = SSL_write(ssl, buf, strlen(buf));
324 printf("SSL write error (unable to send message.)\n");
325 ERR_print_errors_fp(stderr);
329 printf("INFO: Send request to manager. Waiting for reply.\n");
332 ret = SSL_read(ssl, buf, sizeof(buf) - 1);
333 switch (SSL_get_error(ssl, ret)) {
336 if (strncmp(buf, "ERROR", 5) == 0) {
338 tmpstr = strchr(buf, '\n');
342 printf("%s (from manager)\n", buf);
343 } else if (strncmp(buf, "OSSEC K:'", 9) == 0) {
347 printf("INFO: Received response with agent key\n");
351 tmpstr = strchr(key, '\'');
353 printf("ERROR: Invalid key received. Closing connection.\n");
357 entry = OS_StrBreak(' ', key, 4);
358 if (!OS_IsValidID(entry[0]) || !OS_IsValidName(entry[1]) ||
359 !OS_IsValidName(entry[2]) || !OS_IsValidName(entry[3])) {
360 printf("ERROR: Invalid key received (2). Closing connection.\n");
366 fp = fopen(KEYSFILE_PATH, "w");
368 printf("ERROR: Unable to open key file: %s", KEYSFILE_PATH);
371 fprintf(fp, "%s\n", key);
375 printf("INFO: Valid key created. Finished.\n");
378 case SSL_ERROR_ZERO_RETURN:
379 case SSL_ERROR_SYSCALL:
380 if (key_added == 0) {
381 printf("ERROR: Unable to create key. Either wrong password or connection not accepted by the manager.\n");
383 printf("INFO: Connection closed.\n");
387 printf("ERROR: SSL read (unable to receive message)\n");
394 /* Shut down the socket */
395 if (key_added == 0) {
396 printf("ERROR: Unable to create key. Either wrong password or connection not accepted by the manager.\n");
404 #endif /* LIBOPENSSL_ENABLED */