izmjene licence
[ossec-hids.git] / src / addagent / manage_keys.c
1 /* @(#) $Id: ./src/addagent/manage_keys.c, 2011/09/08 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 #include "manage_agents.h"
18 #include "os_crypto/md5/md5_op.h"
19 #include <stdlib.h>
20
21 /* b64 function prototypes */
22 char *decode_base64(const char *src);
23 char *encode_base64(int size, char *src);
24
25 char *trimwhitespace(char *str)
26 {
27   char *end;
28
29   // Trim leading space
30   while(isspace(*str)) str++;
31
32   if(*str == 0)  // All spaces?
33     return str;
34
35   // Trim trailing space
36   end = str + strlen(str) - 1;
37   while(end > str && isspace(*end)) end--;
38
39   // Write new null terminator
40   *(end+1) = 0;
41
42   return str;
43 }
44
45 /* Import a key */
46 int k_import(char *cmdimport)
47 {
48     FILE *fp;
49     char *user_input;
50     char *b64_dec;
51
52     char *name; char *ip; char *tmp_key;
53
54     char line_read[FILE_SIZE +1];
55
56     #ifdef WIN32
57     int result;
58     int cmdlen;
59     int caclslen;
60     char *comspec;
61     char *cacls;
62     STARTUPINFO si;
63     PROCESS_INFORMATION pi;
64     DWORD exit_code;
65     #endif
66
67
68     /* Parsing user argument. */
69     if(cmdimport)
70     {
71         user_input = cmdimport;
72     }
73     else
74     {
75         printf(IMPORT_KEY);
76
77         user_input = getenv("OSSEC_AGENT_KEY");
78         if (user_input == NULL) {
79           user_input = read_from_user();
80         }
81     }
82
83
84     /* quit */
85     if(strcmp(user_input, QUIT) == 0)
86         return(0);
87
88     b64_dec = decode_base64(user_input);
89     if(b64_dec == NULL)
90     {
91         printf(NO_KEY);
92         printf(PRESS_ENTER);
93         read_from_user();
94         return(0);
95     }
96
97
98     memset(line_read, '\0', FILE_SIZE +1);
99     strncpy(line_read, b64_dec, FILE_SIZE);
100
101
102     name = strchr(b64_dec, ' ');
103     if(name && strlen(line_read) < FILE_SIZE)
104     {
105         *name = '\0';
106         name++;
107         ip = strchr(name, ' ');
108         if(ip)
109         {
110             *ip = '\0';
111             ip++;
112
113             tmp_key = strchr(ip, ' ');
114             if(!tmp_key)
115             {
116                 printf(NO_KEY);
117                 return(0);
118             }
119             *tmp_key = '\0';
120
121             printf("\n");
122             printf(AGENT_INFO, b64_dec, name, ip);
123
124             while(1)
125             {
126                 printf(ADD_CONFIRM);
127                 fflush(stdout);
128
129                 user_input = getenv("OSSEC_ACTION_CONFIRMED");
130                 if (user_input == NULL) {
131                   user_input = read_from_user();
132                 }
133
134                 if(user_input[0] == 'y' || user_input[0] == 'Y')
135                 {
136                     fp = fopen(KEYS_FILE,"w");
137                     if(!fp)
138                     {
139                         ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE);
140                     }
141                     fprintf(fp,"%s\n",line_read);
142                     fclose(fp);
143
144                     #ifndef WIN32
145                     chmod(KEYS_FILE, 0440);
146                     #else
147                     /* Get cmd location from environment */
148                     comspec = getenv("COMSPEC");
149                     if (comspec == NULL || strncmp(comspec, "", strlen(comspec) == 0))
150                     {
151                         if(unlink(KEYS_FILE))
152                         {
153                             verbose(AGENT_DELETE_ERROR, KEYS_FILE);
154                         }
155                         ErrorExit(COMPSEC_ERROR);
156                     }
157
158                     /* Build cacls command */
159                     cacls = "echo y|cacls \"%s\" /T /G Administrators:f";
160                     caclslen = strlen(cacls) + strlen(KEYS_FILE);
161                     char caclscmd[caclslen];
162                     snprintf(caclscmd, caclslen, cacls, KEYS_FILE);
163
164                     /* Build final command */
165                     cmdlen = strlen(comspec) + 5 + caclslen;
166                     char cmd[cmdlen];
167                     snprintf(cmd, cmdlen, "%s /c %s", comspec, caclscmd);
168                     
169                      /* Log command being run */
170                      log2file("%s: INFO: Running the following command (%s)", ARGV0, cmd);
171
172                     ZeroMemory(&si, sizeof(si));
173                     si.cb = sizeof(si);
174                     ZeroMemory(&pi, sizeof(pi));
175
176                     if(!CreateProcess(NULL, cmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL,
177                                       &si, &pi))
178                     {
179                         if(unlink(KEYS_FILE))
180                         {
181                             verbose(AGENT_DELETE_ERROR, KEYS_FILE);
182                         }
183                         ErrorExit(PROC_ERROR, cmd);
184                     }
185
186                     /* Wait until process exits */
187                     WaitForSingleObject(pi.hProcess, INFINITE);
188
189                     /* Get exit code from command */
190                     result = GetExitCodeProcess(pi.hProcess, &exit_code);
191
192                     /* Close process and thread */
193                     CloseHandle(pi.hProcess);
194                     CloseHandle(pi.hThread);
195
196                     if (!result)
197                     {
198                         if(unlink(KEYS_FILE))
199                         {
200                             verbose(AGENT_DELETE_ERROR, KEYS_FILE);
201                         }
202                         ErrorExit(RESULT_ERROR, cmd, GetLastError());
203                     }
204
205                     if (exit_code)
206                     {
207                         if(unlink(KEYS_FILE))
208                         {
209                             verbose(AGENT_DELETE_ERROR, KEYS_FILE);
210                         }
211                         ErrorExit(CACLS_ERROR, cmd, exit_code);
212                     }
213                     #endif
214
215                     /* Removing sender counter. */
216                     OS_RemoveCounter("sender");
217
218                     printf(ADDED);
219                     printf(PRESS_ENTER);
220                     read_from_user();
221                     restart_necessary = 1;
222                     return(1);
223                 }
224                 else /* if(user_input[0] == 'n' || user_input[0] == 'N') */
225                 {
226                     printf("%s", ADD_NOT);
227                     return(0);
228                 }
229             }
230         }
231     }
232
233     printf(NO_KEY);
234     printf(PRESS_ENTER);
235     read_from_user();
236     return(0);
237
238 }
239
240
241 /* extract base64 for a specific agent */
242 int k_extract(char *cmdextract)
243 {
244     FILE *fp;
245     char *user_input;
246     char *b64_enc;
247     char line_read[FILE_SIZE +1];
248     char n_id[USER_SIZE +1];
249
250
251     if(cmdextract)
252     {
253         user_input = cmdextract;
254
255         if(!IDExist(user_input))
256         {
257             printf(NO_ID, user_input);
258             exit(1);
259         }
260     }
261
262     else
263     {
264         if(!print_agents(0, 0, 0))
265         {
266             printf(NO_AGENT);
267             printf(PRESS_ENTER);
268             read_from_user();
269             return(0);
270         }
271
272         do
273         {
274             printf(EXTRACT_KEY);
275             fflush(stdout);
276             user_input = read_from_user();
277
278             /* quit */
279             if(strcmp(user_input, QUIT) == 0)
280                 return(0);
281
282             if(!IDExist(user_input))
283                 printf(NO_ID, user_input);
284
285         } while(!IDExist(user_input));
286     }
287
288
289     /* Trying to open the auth file */
290     fp = fopen(AUTH_FILE, "r");
291     if(!fp)
292     {
293         ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE);
294     }
295
296     fsetpos(fp, &fp_pos);
297
298     memset(n_id, '\0', USER_SIZE +1);
299     strncpy(n_id, user_input, USER_SIZE -1);
300
301
302     if(fgets(line_read, FILE_SIZE, fp) == NULL)
303     {
304         printf(ERROR_KEYS);
305         fclose(fp);
306         exit(1);
307     }
308     chomp(line_read);
309
310
311     b64_enc = encode_base64(strlen(line_read),line_read);
312     if(b64_enc == NULL)
313     {
314         printf(EXTRACT_ERROR);
315         fclose(fp);
316         exit(1);
317     }
318
319     printf(EXTRACT_MSG, n_id, b64_enc);
320     if(!cmdextract)
321     {
322         printf("\n" PRESS_ENTER);
323         read_from_user();
324     }
325
326     free(b64_enc);
327     fclose(fp);
328
329     return(0);
330 }
331
332 /* Bulk generate client keys from file */
333 int k_bulkload(char *cmdbulk)
334 {
335     int i = 1;
336     FILE *fp, *infp;
337     char str1[STR_SIZE +1];
338     char str2[STR_SIZE +1];
339
340     os_md5 md1;
341     os_md5 md2;
342     char line[FILE_SIZE+1];
343     char name[FILE_SIZE +1];
344     char id[FILE_SIZE +1];
345     char ip[FILE_SIZE+1];
346     os_ip *c_ip;
347     char delims[] = ",";
348     char * token = NULL;
349
350     /* Checking if we can open the input file */
351     printf("Opening: [%s]\n", cmdbulk);
352     infp = fopen(cmdbulk,"r");
353     if(!infp)
354     {
355         perror("Failed.");
356         ErrorExit(FOPEN_ERROR, ARGV0, cmdbulk);
357     }
358
359
360     /* Checking if we can open the auth_file */
361     fp = fopen(AUTH_FILE,"a");
362     if(!fp)
363     {
364         ErrorExit(FOPEN_ERROR, ARGV0, AUTH_FILE);
365     }
366     fclose(fp);
367
368     /* Allocating for c_ip */
369     os_calloc(1, sizeof(os_ip), c_ip);
370
371         while(fgets(line, FILE_SIZE - 1, infp) != NULL)
372         {
373                 if (1 >= strlen(trimwhitespace(line)))
374                         continue;
375
376                 memset(ip, '\0', FILE_SIZE +1);
377                 token = strtok(line, delims);
378                 strncpy(ip, trimwhitespace(token),FILE_SIZE -1);
379
380                 memset(name, '\0', FILE_SIZE +1);
381                 token = strtok(NULL, delims);
382                 strncpy(name, trimwhitespace(token),FILE_SIZE -1);
383                         
384                 #ifndef WIN32
385                 chmod(AUTH_FILE, 0440);
386                 #endif
387
388                 /* Setting time 2 */
389                 time2 = time(0);
390
391
392                 /* Source is time1+ time2 +pid + ppid */
393                 #ifndef WIN32
394                         #ifdef __OpenBSD__
395                         srandomdev();
396                         #else
397                         srandom(time2 + time1 + getpid() + getppid());
398                         #endif
399                 #else
400                 srandom(time2 + time1 + getpid());
401                 #endif
402
403                 rand1 = random();
404
405
406                 /* Zeroing strings */
407                 memset(str1,'\0', STR_SIZE +1);
408                 memset(str2,'\0', STR_SIZE +1);
409
410
411                 /* check the name */
412                 if(!OS_IsValidName(name))
413                 {
414                 printf(INVALID_NAME,name);
415                 continue;
416                 }
417
418                 /* Search for name  -- no duplicates */
419                 if(NameExist(name))
420                 {
421                 printf(ADD_ERROR_NAME, name);
422                 continue;
423                 }
424
425
426                 if(!OS_IsValidIP(ip, c_ip))
427                 {
428                         printf(IP_ERROR, ip);
429                         continue;
430                 }
431
432                 /* Default ID */
433                 i = MAX_AGENTS + 32512;
434                 snprintf(id, 8, "%03d", i);
435                 while(!IDExist(id))
436                 {
437                 i--;
438                 snprintf(id, 8, "%03d", i);
439
440                 /* No key present, use id 0 */
441                 if(i <= 0)
442                 {
443                         i = 0;
444                         break;
445                 }
446                 }
447                 snprintf(id, 8, "%03d", i+1);
448
449                 if(!OS_IsValidID(id)) 
450                 {
451                 printf(INVALID_ID, id);
452                 continue;
453                 }
454
455                 /* Search for ID KEY  -- no duplicates */
456                 if(IDExist(id))
457                 {
458                 printf(NO_DEFAULT, i+1);
459                 continue;
460                 }
461
462                 printf(AGENT_INFO, id, name, ip);
463                 fflush(stdout);
464
465
466                 time3 = time(0);
467                 rand2 = random();
468
469                 fp = fopen(AUTH_FILE,"a");
470                 if(!fp)
471                 {
472                 ErrorExit(FOPEN_ERROR, ARGV0, KEYS_FILE);
473                 }
474                 #ifndef WIN32
475                 chmod(AUTH_FILE, 0440);
476                 #endif
477
478
479                 /* Random 1: Time took to write the agent information.
480                 * Random 2: Time took to choose the action.
481                 * Random 3: All of this + time + pid
482                 * Random 4: Md5 all of this + the name, key and ip
483                 * Random 5: Final key
484                 */
485
486                 snprintf(str1, STR_SIZE, "%d%s%d",time3-time2, name, rand1);
487                 snprintf(str2, STR_SIZE, "%d%s%s%d", time2-time1, ip, id, rand2);
488
489                 OS_MD5_Str(str1, md1);
490                 OS_MD5_Str(str2, md2);
491
492                 snprintf(str1, STR_SIZE, "%s%d%d%d",md1,(int)getpid(), (int)random(),
493                                             time3);
494                 OS_MD5_Str(str1, md1);
495
496                 //fprintf(fp,"%s %s %s %s%s\n",id, name, ip, md1,md2);
497                 fprintf(fp,"%s %s %s %s%s\n",id, name, c_ip->ip, md1,md2);
498
499                 fclose(fp);
500
501                 printf(AGENT_ADD);
502                 restart_necessary = 1;
503         };
504
505         fclose(infp);
506         return(0);
507 }
508
509
510 /* EOF */