Imported Upstream version 2.7
[ossec-hids.git] / src / addagent / manage_agents.c
1 /* @(#) $Id: ./src/addagent/manage_agents.c, 2012/02/07 dcid Exp $
2  */
3
4 /* Copyright (C) 2009 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  * License details at the LICENSE file included with OSSEC or
13  * online at: http://www.ossec.net/en/licensing.html
14  */
15
16
17 /* Manage agents tool
18  * Add/extract and remove agents from a server.
19  */
20
21
22 #include "manage_agents.h"
23 #include "os_crypto/md5/md5_op.h"
24 #include <stdlib.h>
25
26
27 /* Global internal variables */
28
29
30
31 /* chomp: remove spaces, new lines, etc from a string */
32 char *chomp(char *str)
33 {
34     char *tmp_str;
35     int size = 0;
36
37     /* Removing spaces from the beginning */
38     while(*str == ' ' || *str == '\t')
39         str++;
40
41
42     /* Removing any trailing new lines or \r */
43     do
44     {
45         tmp_str = strchr(str, '\n');
46         if(tmp_str)
47         {
48             *tmp_str = '\0';
49             continue;
50         }
51
52         tmp_str = strchr(str, '\r');
53         if(tmp_str)
54         {
55             *tmp_str = '\0';
56         }
57     }while(tmp_str != NULL);
58
59
60     /* Removing spaces at the end of the string */
61     tmp_str = str;
62     size = strlen(str)-1;
63
64     while((size >= 0) && (tmp_str[size] == ' ' || tmp_str[size] == '\t'))
65     {
66         tmp_str[size] = '\0';
67         size--;
68     }
69
70     return(str);
71 }
72
73
74
75 /* Add an agent */
76 int add_agent()
77 {
78     int i = 1;
79     FILE *fp;
80     char str1[STR_SIZE +1];
81     char str2[STR_SIZE +1];
82
83     os_md5 md1;
84     os_md5 md2;
85
86     char *user_input;
87     char *_name;
88     char *_id;
89     char *_ip;
90
91     char name[FILE_SIZE +1];
92     char id[FILE_SIZE +1];
93     char ip[FILE_SIZE +1];
94     os_ip *c_ip;
95
96
97     /* Checking if we can open the auth_file */
98     fp = fopen(AUTH_FILE,"a");
99     if(!fp)
100     {
101         ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE);
102     }
103     fclose(fp);
104
105
106     /* Allocating for c_ip */
107     os_calloc(1, sizeof(os_ip), c_ip);
108
109
110     #ifndef WIN32
111     chmod(AUTH_FILE, 0440);
112     #endif
113
114     /* Setting time 2 */
115     time2 = time(0);
116
117
118     /* Source is time1+ time2 +pid + ppid */
119     #ifndef WIN32
120         #ifdef __OpenBSD__
121         srandomdev();
122         #else
123         srandom(time2 + time1 + getpid() + getppid());
124         #endif
125     #else
126     srandom(time2 + time1 + getpid());
127     #endif
128
129     rand1 = random();
130
131
132     /* Zeroing strings */
133     memset(str1,'\0', STR_SIZE +1);
134     memset(str2,'\0', STR_SIZE +1);
135
136
137     printf(ADD_NEW);
138
139
140     /* Getting the name */
141     memset(name, '\0', FILE_SIZE +1);
142
143     do
144     {
145         printf(ADD_NAME);
146         fflush(stdout);
147         /* Read the agent's name from user environment. If it is invalid
148          * we should force user to provide a name from input device. */
149         _name = getenv("OSSEC_AGENT_NAME");
150         if (_name == NULL || NameExist(_name) || !OS_IsValidName(_name))
151           _name = read_from_user();
152
153         if(strcmp(_name, QUIT) == 0)
154             return(0);
155
156         strncpy(name, _name, FILE_SIZE -1);
157
158         /* check the name */
159         if(!OS_IsValidName(name))
160             printf(INVALID_NAME,name);
161
162         /* Search for name  -- no duplicates */
163         if(NameExist(name))
164             printf(ADD_ERROR_NAME, name);
165
166     } while(NameExist(name) || !OS_IsValidName(name));
167
168
169     /* Getting IP */
170     memset(ip, '\0', FILE_SIZE +1);
171
172     do
173     {
174       printf(ADD_IP);
175       fflush(stdout);
176
177       /* Read IP address from user's environment. If that IP is invalid,
178        * force user to provide IP from input device */
179       _ip = getenv("OSSEC_AGENT_IP");
180       if (_ip == NULL || !OS_IsValidIP(_ip, c_ip))
181         _ip = read_from_user();
182
183       /* quit */
184       if(strcmp(_ip, QUIT) == 0)
185           return(0);
186
187       strncpy(ip, _ip, FILE_SIZE -1);
188
189       if(!OS_IsValidIP(ip, c_ip))
190       {
191           printf(IP_ERROR, ip);
192           _ip = NULL;
193       }
194
195     } while(!_ip);
196
197
198     do
199     {
200         /* Default ID */
201         i = MAX_AGENTS + 768;
202         snprintf(id, 8, "%03d", i);
203         while(!IDExist(id))
204         {
205             i--;
206             snprintf(id, 8, "%03d", i);
207
208             /* No key present, use id 0 */
209             if(i <= 0)
210             {
211                 i = 0;
212                 break;
213             }
214         }
215         snprintf(id, 8, "%03d", i+1);
216
217         /* Getting ID */
218         printf(ADD_ID, id);
219         fflush(stdout);
220
221         /* Get Agent id from environment. If 0, use default ID. If null,
222          * get from user input. If value from environment is invalid,
223          * we force user to specify an ID from the terminal. Otherwise,
224          * our program goes to infinite loop. */
225         _id = getenv("OSSEC_AGENT_ID");
226         if (_id == NULL || IDExist(_id) || !OS_IsValidID(_id)) {
227           _id = read_from_user();
228         }
229
230         /* If user specified 0 as Agent ID, he meant use default value.
231          * NOTE: a bad condistion can cause infinite loop. */
232         if (strcmp(_id,"0") == 0) {
233           strncpy(_id, id, FILE_SIZE -1);
234         }
235
236         /* quit */
237         if(strcmp(_id, QUIT) == 0)
238             return(0);
239
240
241         if(_id[0] != '\0')
242         {
243             strncpy(id, _id, FILE_SIZE -1);
244         }
245
246         if(!OS_IsValidID(id))
247             printf(INVALID_ID, id);
248
249         /* Search for ID KEY  -- no duplicates */
250         if(IDExist(id))
251             printf(ADD_ERROR_ID, id);
252
253     } while(IDExist(id) || !OS_IsValidID(id));
254
255
256
257     printf(AGENT_INFO, id, name, ip);
258     fflush(stdout);
259
260     do
261     {
262       printf(ADD_CONFIRM);
263       /* Confirmation by an environment variable. The valid value is y/Y.
264        * If the user provide anything other string, it is considered as
265        * n/N; please note that the old code only accepts y/Y/n/N. So if
266        * the variable OSSEC_ACTION_CONFIRMED is 'foobar', the program will
267        * go into an infinite loop. */
268       user_input = getenv("OSSEC_ACTION_CONFIRMED");
269       if (user_input == NULL) user_input = read_from_user();
270
271       /* If user accepts to add */
272       if(user_input[0] == 'y' || user_input[0] == 'Y')
273       {
274         time3 = time(0);
275         rand2 = random();
276
277         fp = fopen(AUTH_FILE,"a");
278         if(!fp)
279         {
280             ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE);
281         }
282         #ifndef WIN32
283         chmod(AUTH_FILE, 0440);
284         #endif
285
286
287         /* Random 1: Time took to write the agent information.
288          * Random 2: Time took to choose the action.
289          * Random 3: All of this + time + pid
290          * Random 4: Md5 all of this + the name, key and ip
291          * Random 5: Final key
292          */
293
294         snprintf(str1, STR_SIZE, "%d%s%d",time3-time2, name, rand1);
295         snprintf(str2, STR_SIZE, "%d%s%s%d", time2-time1, ip, id, rand2);
296
297         OS_MD5_Str(str1, md1);
298         OS_MD5_Str(str2, md2);
299
300         snprintf(str1, STR_SIZE, "%s%d%d%d",md1,(int)getpid(), (int)random(),
301                                             time3);
302         OS_MD5_Str(str1, md1);
303
304         fprintf(fp,"%s %s %s %s%s\n",id, name, c_ip->ip, md1,md2);
305
306         fclose(fp);
307
308         printf(AGENT_ADD);
309         restart_necessary = 1;
310         break;
311       }
312       else /* if(user_input[0] == 'n' || user_input[0] == 'N') */
313       {
314         printf(ADD_NOT);
315         break;
316       }
317
318     } while(1);
319
320     return(0);
321 }
322
323
324 /* remove an agent */
325 int remove_agent()
326 {
327     FILE *fp;
328     char *user_input;
329     char u_id[FILE_SIZE +1];
330
331     u_id[FILE_SIZE] = '\0';
332
333     if(!print_agents(0, 0, 0))
334     {
335         printf(NO_AGENT);
336         return(0);
337     }
338
339     do
340     {
341       printf(REMOVE_ID);
342       fflush(stdout);
343
344       user_input = getenv("OSSEC_AGENT_ID");
345       if (user_input == NULL || !IDExist(user_input)) {
346         user_input = read_from_user();
347       }
348
349       if(strcmp(user_input, QUIT) == 0)
350           return(0);
351
352       strncpy(u_id, user_input, FILE_SIZE);
353
354       if(!IDExist(user_input))
355       {
356         printf(NO_ID, user_input);
357       }
358     } while(!IDExist(user_input));
359
360     do
361     {
362         printf(REMOVE_CONFIRM);
363         fflush(stdout);
364
365         user_input = getenv("OSSEC_ACTION_CONFIRMED");
366         if (user_input == NULL) {
367           user_input = read_from_user();
368         }
369         /* If user confirm */
370         if(user_input[0] == 'y' || user_input[0] == 'Y')
371         {
372             /* Getting full agent name */
373             char *full_name = getFullnameById(u_id);
374             if(!full_name)
375             {
376                 ErrorExit(MEM_ERROR, ARGV0);
377             }
378
379             fp = fopen(AUTH_FILE, "r+");
380             if(!fp)
381             {
382                 free(full_name);
383                 ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE);
384             }
385             #ifndef WIN32
386             chmod(AUTH_FILE, 0440);
387             #endif
388
389
390             /* Removing the agent, but keeping the id. */
391             fsetpos(fp, &fp_pos);
392             fprintf(fp, "%s #*#*#*#*#*#*#*#*#*#*#", u_id);
393
394             fclose(fp);
395
396
397             /* Remove counter for id */
398             delete_agentinfo(full_name);
399             OS_RemoveCounter(u_id);
400             free(full_name);
401             full_name = NULL;
402
403
404             printf(REMOVE_DONE, u_id);
405             restart_necessary = 1;
406             break;
407         }
408         else /* if(user_input[0] == 'n' || user_input[0] == 'N') */
409         {
410             printf(REMOVE_NOT);
411             break;
412         }
413
414     } while(1);
415
416     return(0);
417 }
418
419
420 int list_agents(int cmdlist)
421 {
422     if(!print_agents(0, 0, 0))
423         printf(NO_AGENT);
424
425     printf("\n");
426     if(!cmdlist)
427     {
428         printf(PRESS_ENTER);
429         read_from_user();
430     }
431
432     return(0);
433
434 }
435
436 /* EOF */