6397ea3f13c066aca24171f59cc89e869a39c84b
[ossec-hids.git] / main-client.c
1 /* @(#) $Id: ./src/os_auth/main-client.c, 2012/02/07 dcid Exp $
2  */
3
4 /* Copyright (C) 2010 Trend Micro Inc.
5  * All rights reserved.
6  *
7  * This program is a free software; you can redistribute it
8  * and/or modify it under the terms of the GNU General Public
9  * License (version 2) as published by the FSF - Free Software
10  * Foundation
11  *
12  * In addition, as a special exception, the copyright holders give
13  * permission to link the code of portions of this program with the
14  * OpenSSL library under certain conditions as described in each
15  * individual source file, and distribute linked combinations
16  * including the two.
17  *
18  * You must obey the GNU General Public License in all respects
19  * for all of the code used other than OpenSSL.  If you modify
20  * file(s) with this exception, you may extend this exception to your
21  * version of the file(s), but you are not obligated to do so.  If you
22  * do not wish to do so, delete this exception statement from your
23  * version.  If you delete this exception statement from all source
24  * files in the program, then also delete it here.
25  *
26  */
27
28 #include "shared.h"
29
30 #ifndef USE_OPENSSL
31
32 int main()
33 {
34     printf("ERROR: Not compiled. Missing OpenSSL support.\n");
35     exit(0);
36 }
37
38
39 #else
40
41 #include <openssl/ssl.h>
42 #include "auth.h"
43
44
45
46 void report_help()
47 {
48     printf("\nOSSEC HIDS %s: Connects to the manager to extract the agent key.\n", ARGV0);
49     printf("Available options:\n");
50     printf("\t-h                  This help message.\n");
51     printf("\t-m <manager ip>     Manager IP Address.\n");
52     printf("\t-p <port>           Manager port (default 1515).\n");
53     printf("\t-A <agent name>     Agent name (default is the hostname).\n");
54     printf("\t-D <OSSEC Dir>      Location where OSSEC is installed.\n");
55     exit(1);
56 }
57
58
59
60 int main(int argc, char **argv)
61 {
62     int c;
63     // TODO: implement or delete
64     int test_config __attribute__((unused)) = 0;
65     #ifndef WIN32
66     int gid = 0;
67     #endif
68
69     int sock = 0, port = 1515, ret = 0;
70     // TODO: implement or delete
71     char *dir __attribute__((unused)) = DEFAULTDIR;
72     char *user = USER;
73     char *group = GROUPGLOBAL;
74     // TODO: implement or delete
75     char *cfg __attribute__((unused)) = DEFAULTCPATH;
76     char *manager = NULL;
77     char *agentname = NULL;
78     char lhostname[512 + 1];
79     char buf[2048 +1];
80     SSL_CTX *ctx;
81     SSL *ssl;
82     BIO *sbio;
83
84
85     bio_err = 0;
86     buf[2048] = '\0';
87
88
89     /* Setting the name */
90     OS_SetName(ARGV0);
91
92     while((c = getopt(argc, argv, "Vdhu:g:D:c:m:p:A:")) != -1)
93     {
94         switch(c){
95             case 'V':
96                 print_version();
97                 break;
98             case 'h':
99                 report_help();
100                 break;
101             case 'd':
102                 nowDebug();
103                 break;
104             case 'u':
105                 if(!optarg)
106                     ErrorExit("%s: -u needs an argument",ARGV0);
107                 user=optarg;
108                 break;
109             case 'g':
110                 if(!optarg)
111                     ErrorExit("%s: -g needs an argument",ARGV0);
112                 group=optarg;
113                 break;
114             case 'D':
115                 if(!optarg)
116                     ErrorExit("%s: -D needs an argument",ARGV0);
117                 dir=optarg;
118                 break;
119             case 'c':
120                 if(!optarg)
121                     ErrorExit("%s: -c needs an argument",ARGV0);
122                 cfg = optarg;
123                 break;
124             case 't':
125                 test_config = 1;
126                 break;
127             case 'm':
128                if(!optarg)
129                     ErrorExit("%s: -%c needs an argument",ARGV0, c);
130                 manager = optarg;
131                 break;
132             case 'A':
133                if(!optarg)
134                     ErrorExit("%s: -%c needs an argument",ARGV0, c);
135                 agentname = optarg;
136                 break;
137             case 'p':
138                if(!optarg)
139                     ErrorExit("%s: -%c needs an argument",ARGV0, c);
140                 port = atoi(optarg);
141                 if(port <= 0 || port >= 65536)
142                 {
143                     ErrorExit("%s: Invalid port: %s", ARGV0, optarg);
144                 }
145                 break;
146             default:
147                 report_help();
148                 break;
149         }
150     }
151
152     /* Starting daemon */
153     debug1(STARTED_MSG,ARGV0);
154
155
156     #ifndef WIN32
157     /* Check if the user/group given are valid */
158     gid = Privsep_GetGroup(group);
159     if(gid < 0)
160         ErrorExit(USER_ERROR,ARGV0,user,group);
161
162
163
164     /* Privilege separation */
165     if(Privsep_SetGroup(gid) < 0)
166         ErrorExit(SETGID_ERROR,ARGV0,group);
167
168
169
170     /* Signal manipulation */
171     StartSIG(ARGV0);
172
173
174
175     /* Creating PID files */
176     if(CreatePID(ARGV0, getpid()) < 0)
177         ErrorExit(PID_ERROR,ARGV0);
178     #endif
179
180
181     /* Start up message */
182     verbose(STARTUP_MSG, ARGV0, (int)getpid());
183
184
185     if(agentname == NULL)
186     {
187         lhostname[512] = '\0';
188         if(gethostname(lhostname, 512 -1) != 0)
189         {
190             merror("%s: ERROR: Unable to extract hostname. Custom agent name not set.", ARGV0);
191             exit(1);
192         }
193         agentname = lhostname;
194     }
195
196
197
198     /* Starting SSL */
199     ctx = os_ssl_keys(1, NULL);
200     if(!ctx)
201     {
202         merror("%s: ERROR: SSL error. Exiting.", ARGV0);
203         exit(1);
204     }
205
206     if(!manager)
207     {
208         merror("%s: ERROR: Manager IP not set.", ARGV0);
209         exit(1);
210     }
211
212
213     /* Check to see if manager is an IP */
214     int is_ip = 1;
215     struct sockaddr_in iptest;
216     memset(&iptest, 0, sizeof(iptest));
217
218     if(inet_pton(AF_INET, manager, &iptest.sin_addr) != 1)
219       is_ip = 0;        /* This is not an IPv4 address */
220
221     /* Not IPv4, IPv6 maybe? */
222     if(is_ip == 0)
223     {
224         struct sockaddr_in6 iptest6;
225         memset(&iptest6, 0, sizeof(iptest6));
226         if(inet_pton(AF_INET6, manager, &iptest6.sin6_addr) != 1)
227             is_ip = 0;
228         else
229             is_ip = 1;  /* This is an IPv6 address */
230     }
231
232
233     /* If it isn't an ip, try to resolve the IP */
234     if(is_ip == 0)
235     {
236         char *ipaddress;
237         ipaddress = OS_GetHost(manager, 3);
238         if(ipaddress != NULL)
239           strncpy(manager, ipaddress, 16);
240         else
241         {
242           printf("Could not resolve hostname: %s\n", manager);
243           return(1);
244         }
245     }
246
247
248     /* Connecting via TCP */
249     sock = OS_ConnectTCP(port, manager, 0);
250     if(sock <= 0)
251     {
252         merror("%s: Unable to connect to %s:%d", ARGV0, manager, port);
253         exit(1);
254     }
255
256
257     /* Connecting the SSL socket */
258     ssl = SSL_new(ctx);
259     sbio = BIO_new_socket(sock, BIO_NOCLOSE);
260     SSL_set_bio(ssl, sbio, sbio);
261
262
263     ret = SSL_connect(ssl);
264     if(ret <= 0)
265     {
266         ERR_print_errors_fp(stderr);
267         merror("%s: ERROR: SSL error (%d). Exiting.", ARGV0, ret);
268         exit(1);
269     }
270
271
272     printf("INFO: Connected to %s:%d\n", manager, port);
273     printf("INFO: Using agent name as: %s\n", agentname);
274
275
276     snprintf(buf, 2048, "OSSEC A:'%s'\n", agentname);
277     ret = SSL_write(ssl, buf, strlen(buf));
278     if(ret < 0)
279     {
280         printf("SSL write error (unable to send message.)\n");
281         ERR_print_errors_fp(stderr);
282         exit(1);
283     }
284
285     printf("INFO: Send request to manager. Waiting for reply.\n");
286
287     while(1)
288     {
289         ret = SSL_read(ssl,buf,sizeof(buf) -1);
290         switch(SSL_get_error(ssl,ret))
291         {
292             case SSL_ERROR_NONE:
293                 buf[ret] = '\0';
294                 if(strncmp(buf, "ERROR", 5) == 0)
295                 {
296                     char *tmpstr;
297                     tmpstr = strchr(buf, '\n');
298                     if(tmpstr) *tmpstr = '\0';
299                     printf("%s (from manager)\n", buf);
300                 }
301                 else if(strncmp(buf, "OSSEC K:'",9) == 0)
302                 {
303                     char *key;
304                     char *tmpstr;
305                     char **entry;
306                     printf("INFO: Received response with agent key\n");
307
308                     key = buf;
309                     key += 9;
310                     tmpstr = strchr(key, '\'');
311                     if(!tmpstr)
312                     {
313                         printf("ERROR: Invalid key received. Closing connection.\n");
314                         exit(1);
315                     }
316                     *tmpstr = '\0';
317                     entry = OS_StrBreak(' ', key, 4);
318                     if(!OS_IsValidID(entry[0]) || !OS_IsValidName(entry[1]) ||
319                        !OS_IsValidName(entry[2]) || !OS_IsValidName(entry[3]))
320                     {
321                         printf("ERROR: Invalid key received (2). Closing connection.\n");
322                         exit(1);
323                     }
324
325                     {
326                         FILE *fp;
327                         fp = fopen(KEYSFILE_PATH,"w");
328                         if(!fp)
329                         {
330                             printf("ERROR: Unable to open key file: %s", KEYSFILE_PATH);
331                             exit(1);
332                         }
333                         fprintf(fp, "%s\n", key);
334                         fclose(fp);
335                     }
336                     printf("INFO: Valid key created. Finished.\n");
337                 }
338                 break;
339             case SSL_ERROR_ZERO_RETURN:
340             case SSL_ERROR_SYSCALL:
341                 printf("INFO: Connection closed.\n");
342                 exit(0);
343                 break;
344             default:
345                 printf("ERROR: SSL read (unable to receive message)\n");
346                 exit(1);
347                 break;
348         }
349
350     }
351
352
353
354     /* Shutdown the socket */
355     SSL_CTX_free(ctx);
356     close(sock);
357
358     exit(0);
359 }
360
361 #endif
362 /* EOF */