Imported Upstream version 2.7
[ossec-hids.git] / src / os_auth / main-server.c
1 /* @(#) $Id$ */
2
3 /* Copyright (C) 2010 Trend Micro Inc.
4  * All rights reserved.
5  *
6  * This program is a free software; you can redistribute it
7  * and/or modify it under the terms of the GNU General Public
8  * License (version 2) as published by the FSF - Free Software
9  * Foundation
10  *
11  * In addition, as a special exception, the copyright holders give
12  * permission to link the code of portions of this program with the
13  * OpenSSL library under certain conditions as described in each
14  * individual source file, and distribute linked combinations
15  * including the two.
16  *
17  * You must obey the GNU General Public License in all respects
18  * for all of the code used other than OpenSSL.  If you modify
19  * file(s) with this exception, you may extend this exception to your
20  * version of the file(s), but you are not obligated to do so.  If you
21  * do not wish to do so, delete this exception statement from your
22  * version.  If you delete this exception statement from all source
23  * files in the program, then also delete it here.
24  *
25  */
26
27
28 #include "shared.h"
29 #include "auth.h"
30
31 /* TODO: Pulled this value out of the sky, may or may not be sane */
32 int POOL_SIZE = 512;
33
34 /* ossec-reportd - Runs manual reports. */
35 void report_help()
36 {
37 }
38
39 #ifndef USE_OPENSSL
40 int main()
41 {
42     printf("ERROR: Not compiled. Missing OpenSSL support.\n");
43     exit(0);
44 }
45 #else
46
47
48 int main(int argc, char **argv)
49 {
50     FILE *fp;
51     // Bucket to keep pids in.
52     int process_pool[POOL_SIZE];
53     // Count of pids we are wait()ing on.
54     int c = 0, test_config = 0, use_ip_address = 0, pid = 0, status, i = 0, active_processes = 0;
55     int gid = 0, client_sock = 0, sock = 0, port = 1515, ret = 0;
56     char *dir  = DEFAULTDIR;
57     char *user = USER;
58     char *group = GROUPGLOBAL;
59     char *cfg = DEFAULTCPATH;
60     char buf[4096 +1];
61     SSL_CTX *ctx;
62     SSL *ssl;
63     char srcip[IPSIZE +1];
64     struct sockaddr_in _nc;
65     socklen_t _ncl;
66
67
68     /* Initializing some variables */
69     memset(srcip, '\0', IPSIZE + 1);
70     memset(process_pool, 0x0, POOL_SIZE);
71
72     bio_err = 0;
73
74
75     /* Setting the name */
76     OS_SetName(ARGV0);
77     /* add an option to use the ip on the socket to tie the name to a
78        specific address */
79     while((c = getopt(argc, argv, "Vdhiu:g:D:c:m:p:")) != -1)
80     {
81         switch(c){
82             case 'V':
83                 print_version();
84                 break;
85             case 'h':
86                 report_help();
87                 break;
88             case 'd':
89                 nowDebug();
90                 break;
91             case 'i':
92                 use_ip_address = 1;
93                 break;
94             case 'u':
95                 if(!optarg)
96                     ErrorExit("%s: -u needs an argument",ARGV0);
97                 user = optarg;
98                 break;
99             case 'g':
100                 if(!optarg)
101                     ErrorExit("%s: -g needs an argument",ARGV0);
102                 group = optarg;
103                 break;
104             case 'D':
105                 if(!optarg)
106                     ErrorExit("%s: -D needs an argument",ARGV0);
107                 dir = optarg;
108                 break;
109             case 'c':
110                 if(!optarg)
111                     ErrorExit("%s: -c needs an argument",ARGV0);
112                 cfg = optarg;
113                 break;
114             case 't':
115                 test_config = 1;
116                 break;
117             case 'p':
118                if(!optarg)
119                     ErrorExit("%s: -%c needs an argument",ARGV0, c);
120                 port = atoi(optarg);
121                 if(port <= 0 || port >= 65536)
122                 {
123                     ErrorExit("%s: Invalid port: %s", ARGV0, optarg);
124                 }
125                 break;
126             default:
127                 report_help();
128                 break;
129         }
130
131     }
132
133     /* Starting daemon -- NB: need to double fork and setsid */
134     debug1(STARTED_MSG,ARGV0);
135
136     /* Check if the user/group given are valid */
137     gid = Privsep_GetGroup(group);
138     if(gid < 0)
139         ErrorExit(USER_ERROR,ARGV0,user,group);
140
141
142
143     /* Exit here if test config is set */
144     if(test_config)
145         exit(0);
146
147
148     /* Privilege separation */
149     if(Privsep_SetGroup(gid) < 0)
150         ErrorExit(SETGID_ERROR,ARGV0,group);
151
152
153     /* chrooting -- TODO: this isn't a chroot. Should also close
154        unneeded open file descriptors (like stdin/stdout)*/
155     chdir(dir);
156
157
158
159     /* Signal manipulation */
160     StartSIG(ARGV0);
161
162
163     /* Creating PID files */
164     if(CreatePID(ARGV0, getpid()) < 0)
165         ErrorExit(PID_ERROR,ARGV0);
166
167     /* Start up message */
168     verbose(STARTUP_MSG, ARGV0, (int)getpid());
169
170
171     fp = fopen(KEYSFILE_PATH,"a");
172     if(!fp)
173     {
174         merror("%s: ERROR: Unable to open %s (key file)", ARGV0, KEYSFILE_PATH);
175         exit(1);
176     }
177
178
179     /* Starting SSL */
180     ctx = os_ssl_keys(0, dir);
181     if(!ctx)
182     {
183         merror("%s: ERROR: SSL error. Exiting.", ARGV0);
184         exit(1);
185     }
186
187
188     /* Connecting via TCP */
189     sock = OS_Bindporttcp(port, NULL, 0);
190     if(sock <= 0)
191     {
192         merror("%s: Unable to bind to port %d", ARGV0, port);
193         exit(1);
194     }
195     fcntl(sock, F_SETFL, O_NONBLOCK);
196
197     debug1("%s: DEBUG: Going into listening mode.", ARGV0);
198     while(1)
199     {
200
201         // no need to completely pin the cpu
202         usleep(0);
203         for (i = 0; i < POOL_SIZE; i++)
204         {
205             int rv = 0;
206             status = 0;
207             if (process_pool[i])
208             {
209                 rv = waitpid(process_pool[i], &status, WNOHANG);
210                 if (rv != 0){
211                     debug1("%s: DEBUG: Process %d exited", ARGV0, process_pool[i]);
212                     process_pool[i] = 0;
213                     active_processes = active_processes - 1;
214                 }
215             }
216         }
217         memset(&_nc, 0, sizeof(_nc));
218         _ncl = sizeof(_nc);
219
220         if((client_sock = accept(sock, (struct sockaddr *) &_nc, &_ncl)) > 0){
221             if (active_processes >= POOL_SIZE)
222             {
223                 merror("%s: Error: Max concurrency reached. Unable to fork", ARGV0);
224                 break;
225             }
226             pid = fork();
227             if(pid)
228             {
229                 active_processes = active_processes + 1;
230                 close(client_sock);
231                 for (i = 0; i < POOL_SIZE; i++)
232                 {
233                     if (! process_pool[i])
234                     {
235                         process_pool[i] = pid;
236                         break;
237                     }
238                 }
239             }
240             else
241             {
242                 strncpy(srcip, inet_ntoa(_nc.sin_addr),IPSIZE -1);
243                 char *agentname = NULL;
244                 ssl = SSL_new(ctx);
245                 SSL_set_fd(ssl, client_sock);
246                 ret = SSL_accept(ssl);
247                 if(ret <= 0)
248                 {
249                     merror("%s: ERROR: SSL Accept error (%d)", ARGV0, ret);
250                     ERR_print_errors_fp(stderr);
251                 }
252
253                 verbose("%s: INFO: New connection from %s", ARGV0, srcip);
254
255                 ret = SSL_read(ssl, buf, sizeof(buf));
256                 sleep(1);
257                 if(ret > 0)
258                 {
259                     int parseok = 0;
260                     if(strncmp(buf, "OSSEC A:'", 9) == 0)
261                     {
262                         char *tmpstr = buf;
263                         agentname = tmpstr + 9;
264                         tmpstr += 9;
265                         while(*tmpstr != '\0')
266                         {
267                             if(*tmpstr == '\'')
268                             {
269                                 *tmpstr = '\0';
270                                 verbose("%s: INFO: Received request for a new agent (%s) from: %s", ARGV0, agentname, srcip);
271                                 parseok = 1;
272                                 break;
273                             }
274                             tmpstr++;
275                         }
276                     }
277                     if(parseok == 0)
278                     {
279                         merror("%s: ERROR: Invalid request for new agent from: %s", ARGV0, srcip);
280                     }
281                     else
282                     {
283                         int acount = 2;
284                         char fname[2048 +1];
285                         char response[2048 +1];
286                         char *finalkey = NULL;
287                         response[2048] = '\0';
288                         fname[2048] = '\0';
289                         if(!OS_IsValidName(agentname))
290                         {
291                             merror("%s: ERROR: Invalid agent name: %s from %s", ARGV0, agentname, srcip);
292                             snprintf(response, 2048, "ERROR: Invalid agent name: %s\n\n", agentname);
293                             ret = SSL_write(ssl, response, strlen(response));
294                             snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
295                             ret = SSL_write(ssl, response, strlen(response));
296                             sleep(1);
297                             exit(0);
298                         }
299
300
301                         /* Checking for a duplicated names. */
302                         strncpy(fname, agentname, 2048);
303                         while(NameExist(fname))
304                         {
305                             snprintf(fname, 2048, "%s%d", agentname, acount);
306                             acount++;
307                             if(acount > 256)
308                             {
309                                 merror("%s: ERROR: Invalid agent name %s (duplicated)", ARGV0, agentname);
310                                 snprintf(response, 2048, "ERROR: Invalid agent name: %s\n\n", agentname);
311                                 ret = SSL_write(ssl, response, strlen(response));
312                                 snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
313                                 ret = SSL_write(ssl, response, strlen(response));
314                                 sleep(1);
315                                 exit(0);
316                             }
317                         }
318                         agentname = fname;
319
320
321                         /* Adding the new agent. */
322                         if (use_ip_address)
323                         {
324                             finalkey = OS_AddNewAgent(agentname, srcip, NULL, NULL);
325                         }
326                         else
327                         {
328                             finalkey = OS_AddNewAgent(agentname, NULL, NULL, NULL);
329                         }
330                         if(!finalkey)
331                         {
332                             merror("%s: ERROR: Unable to add agent: %s (internal error)", ARGV0, agentname);
333                             snprintf(response, 2048, "ERROR: Internal manager error adding agent: %s\n\n", agentname);
334                             ret = SSL_write(ssl, response, strlen(response));
335                             snprintf(response, 2048, "ERROR: Unable to add agent.\n\n");
336                             ret = SSL_write(ssl, response, strlen(response));
337                             sleep(1);
338                             exit(0);
339                         }
340
341
342                         snprintf(response, 2048,"OSSEC K:'%s'\n\n", finalkey);
343                         verbose("%s: INFO: Agent key generated for %s (requested by %s)", ARGV0, agentname, srcip);
344                         ret = SSL_write(ssl, response, strlen(response));
345                         if(ret < 0)
346                         {
347                             merror("%s: ERROR: SSL write error (%d)", ARGV0, ret);
348                             merror("%s: ERROR: Agen key not saved for %s", ARGV0, agentname);
349                             ERR_print_errors_fp(stderr);
350                         }
351                         else
352                         {
353                             verbose("%s: INFO: Agent key created for %s (requested by %s)", ARGV0, agentname, srcip);
354                         }
355                     }
356                 }
357                 else
358                 {
359                     merror("%s: ERROR: SSL read error (%d)", ARGV0, ret);
360                     ERR_print_errors_fp(stderr);
361                 }
362                 SSL_CTX_free(ctx);
363                 close(client_sock);
364                 exit(0);
365             }
366         }
367     }
368
369
370     /* Shutdown the socket */
371     SSL_CTX_free(ctx);
372     close(sock);
373
374     exit(0);
375 }
376
377
378 #endif
379 /* EOF */