1 /* @(#) $Id: msgs.c,v 1.10 2009/08/10 14:27:37 dcid Exp $ */
3 /* Copyright (C) 2009 Trend Micro Inc.
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 3) as published by the FSF - Free Software
11 * License details at the LICENSE file included with OSSEC or
12 * online at: http://www.ossec.net/en/licensing.html
18 #include "headers/sec.h"
20 #include "os_zlib/os_zlib.h"
21 #include "os_crypto/md5/md5_op.h"
22 #include "os_crypto/blowfish/bf_op.h"
25 /** Sending counts **/
26 unsigned int global_count = 0;
27 unsigned int local_count = 0;
30 /** Average compression rates **/
33 unsigned int c_orig_size = 0;
34 unsigned int c_comp_size = 0;
37 /** Static variables (read from define file) **/
38 int _s_comp_print = 0;
39 int _s_recv_flush = 0;
41 int _s_verify_counter = 1;
45 * Read counters for each agent.
47 void OS_StartCounter(keystore *keys)
50 char rids_file[OS_FLSIZE +1];
52 rids_file[OS_FLSIZE] = '\0';
55 debug1("%s: OS_StartCounter: keysize: %d", __local_name, keys->keysize);
58 /* Starting receiving counter */
59 for(i = 0; i<=keys->keysize; i++)
61 /* On i == keysize, we deal with the
64 if(i == keys->keysize)
66 snprintf(rids_file, OS_FLSIZE, "%s/%s",
72 snprintf(rids_file, OS_FLSIZE, "%s/%s",
74 keys->keyentries[i]->id);
77 keys->keyentries[i]->fp = fopen(rids_file, "r+");
79 /* If nothing is there, try to open as write only */
80 if(!keys->keyentries[i]->fp)
82 keys->keyentries[i]->fp = fopen(rids_file, "w");
83 if(!keys->keyentries[i]->fp)
87 /* Just in case we run out of file descriptiors */
88 if((keys->keyentries[i -1]->fp) && (i > 10))
90 fclose(keys->keyentries[i -1]->fp);
92 if(keys->keyentries[i -2]->fp)
94 fclose(keys->keyentries[i -2]->fp);
98 merror("%s: Unable to open agent file. errno: %d",
99 __local_name, my_error);
100 ErrorExit(FOPEN_ERROR, __local_name, rids_file);
105 unsigned int g_c = 0, l_c = 0;
106 if(fscanf(keys->keyentries[i]->fp,"%u:%u", &g_c, &l_c) != 2)
108 if(i == keys->keysize)
110 verbose("%s: INFO: No previous sender counter.", __local_name);
114 verbose("%s: INFO: No previous counter available for '%s'.",
116 keys->keyentries[i]->name);
123 if(i == keys->keysize)
125 verbose("%s: INFO: Assigning sender counter: %d:%d",
126 __local_name, g_c, l_c);
132 verbose("%s: INFO: Assigning counter for agent %s: '%d:%d'.",
133 __local_name, keys->keyentries[i]->name, g_c, l_c);
135 keys->keyentries[i]->global = g_c;
136 keys->keyentries[i]->local = l_c;
141 debug2("%s: DEBUG: Stored counter.", __local_name);
143 /* Getting counter values */
144 if(_s_recv_flush == 0)
146 _s_recv_flush = getDefine_Int("remoted",
147 "recv_counter_flush",
151 /* Average printout values */
152 if(_s_comp_print == 0)
154 _s_comp_print = getDefine_Int("remoted",
155 "comp_average_printout",
160 _s_verify_counter = getDefine_Int("remoted", "verify_msg_id" , 0, 1);
165 /** OS_RemoveCounter(char *id)
166 * Remove the ID counter.
168 void OS_RemoveCounter(char *id)
170 char rids_file[OS_FLSIZE +1];
171 snprintf(rids_file, OS_FLSIZE, "%s/%s",RIDS_DIR, id);
176 /** StoreSenderCounter((keystore *keys, int global, int local)
177 * Store sender counter.
179 void StoreSenderCounter(keystore *keys, int global, int local)
181 /* Writting at the beginning of the file */
182 fseek(keys->keyentries[keys->keysize]->fp, 0, SEEK_SET);
183 fprintf(keys->keyentries[keys->keysize]->fp, "%u:%u:", global, local);
187 /* StoreCount(keystore *keys, int id, int global, int local)
188 * Store the global and local count of events.
190 void StoreCounter(keystore *keys, int id, int global, int local)
192 /* Writting at the beginning of the file */
193 fseek(keys->keyentries[id]->fp, 0, SEEK_SET);
194 fprintf(keys->keyentries[id]->fp, "%u:%u:", global, local);
198 /* CheckSum v0.1: 2005/02/15
199 * Verify the checksum of the message.
200 * Returns NULL on error or the message on success.
202 char *CheckSum(char *msg)
209 strncpy(recvd_sum,msg,32);
214 OS_MD5_Str(msg, checksum);
215 if(strncmp(checksum,recvd_sum,32) != 0)
225 /* ReadSecMSG v0.2: 2005/02/10 */
226 char *ReadSecMSG(keystore *keys, char *buffer, char *cleartext,
227 int id, int buffer_size)
230 unsigned int msg_global;
231 unsigned int msg_local;
242 merror(ENCFORMAT_ERROR, __local_name, keys->keyentries[id]->ip->ip);
246 /* Decrypting message */
247 if(!OS_BF_Str(buffer, cleartext, keys->keyentries[id]->key,
248 buffer_size, OS_DECRYPT))
250 merror(ENCKEY_ERROR, __local_name, keys->keyentries[id]->ip->ip);
256 else if(cleartext[0] == '!')
258 cleartext[buffer_size] = '\0';
262 /* Removing padding */
263 while(*cleartext == '!')
270 cmp_size = os_uncompress(cleartext, buffer, buffer_size, OS_MAXSTR);
273 merror(UNCOMPRESS_ERR, __local_name);
277 /* Checking checksum */
278 f_msg = CheckSum(buffer);
281 merror(ENCSUM_ERROR, __local_name, keys->keyentries[id]->ip->ip);
285 /* Removing random */
289 /* Checking count -- protecting against replay attacks */
290 msg_global = atoi(f_msg);
293 /* Checking for the right message format */
296 merror(ENCFORMAT_ERROR, __local_name,keys->keyentries[id]->ip->ip);
301 msg_local = atoi(f_msg);
305 /* Returning the message if we don't need to verify the counbter. */
306 if(!_s_verify_counter)
308 /* Updating currently counts */
309 keys->keyentries[id]->global = msg_global;
310 keys->keyentries[id]->local = msg_local;
311 if(rcv_count >= _s_recv_flush)
313 StoreCounter(keys, id, msg_global, msg_local);
321 if((msg_global > keys->keyentries[id]->global)||
322 ((msg_global == keys->keyentries[id]->global) &&
323 (msg_local > keys->keyentries[id]->local)))
325 /* Updating currently counts */
326 keys->keyentries[id]->global = msg_global;
327 keys->keyentries[id]->local = msg_local;
329 if(rcv_count >= _s_recv_flush)
331 StoreCounter(keys, id, msg_global, msg_local);
339 /* Checking if it is a duplicated message */
340 if(msg_global == keys->keyentries[id]->global)
346 /* Warn about duplicated messages */
347 merror("%s: WARN: Duplicate error: global: %d, local: %d, "
348 "saved global: %d, saved local:%d",
352 keys->keyentries[id]->global,
353 keys->keyentries[id]->local);
355 merror(ENCTIME_ERROR, __local_name, keys->keyentries[id]->name);
360 else if(cleartext[0] == ':')
366 cleartext[buffer_size] = '\0';
369 /* Checking checksum */
371 f_msg = CheckSum(cleartext);
374 merror(ENCSUM_ERROR, __local_name, keys->keyentries[id]->ip->ip);
379 /* Checking time -- protecting against replay attacks */
380 msg_time = atoi(f_msg);
383 msg_count = atoi(f_msg);
387 /* Returning the message if we don't need to verify the counbter. */
388 if(!_s_verify_counter)
390 /* Updating currently counts */
391 keys->keyentries[id]->global = msg_time;
392 keys->keyentries[id]->local = msg_local;
394 f_msg = strchr(f_msg, ':');
403 if((msg_time > keys->keyentries[id]->global) ||
404 ((msg_time == keys->keyentries[id]->global)&&
405 (msg_count > keys->keyentries[id]->local)))
407 /* Updating currently time and count */
408 keys->keyentries[id]->global = msg_time;
409 keys->keyentries[id]->local = msg_count;
411 f_msg = strchr(f_msg, ':');
419 /* Checking if it is a duplicated message */
420 if((msg_count == keys->keyentries[id]->local) &&
421 (msg_time == keys->keyentries[id]->global))
427 /* Warn about duplicated message */
428 merror("%s: WARN: Duplicate error: msg_count: %d, time: %d, "
429 "saved count: %d, saved_time:%d",
433 keys->keyentries[id]->local,
434 keys->keyentries[id]->global);
436 merror(ENCTIME_ERROR, __local_name, keys->keyentries[id]->name);
440 merror(ENCFORMAT_ERROR, __local_name, keys->keyentries[id]->ip->ip);
446 /* Creat a encrypted message.
447 * Returns the size of it
449 int CreateSecMSG(keystore *keys, char *msg, char *msg_encrypted, int id)
457 char _tmpmsg[OS_MAXSTR + 2];
458 char _finmsg[OS_MAXSTR + 2];
462 msg_size = strlen(msg);
465 /* Checking for invalid msg sizes */
466 if((msg_size > (OS_MAXSTR - OS_HEADER_SIZE))||(msg_size < 1))
468 merror(ENCSIZE_ERROR, __local_name, msg);
473 rand1 = (u_int16_t)random();
476 _tmpmsg[OS_MAXSTR +1] = '\0';
477 _finmsg[OS_MAXSTR +1] = '\0';
478 msg_encrypted[OS_MAXSTR] = '\0';
481 /* Increasing local and global counters */
482 if(local_count >= 9997)
490 snprintf(_tmpmsg, OS_MAXSTR,"%05hu%010u:%04hu:%s",
491 rand1, global_count, local_count,
495 /* Generating md5sum of the unencrypted string */
496 OS_MD5_Str(_tmpmsg, md5sum);
500 /* Generating final msg to be compressed */
501 snprintf(_finmsg, OS_MAXSTR,"%s%s",md5sum,_tmpmsg);
502 msg_size = strlen(_finmsg);
505 /* Compressing message.
506 * We assing the first 8 bytes for padding.
508 cmp_size = os_compress(_finmsg, _tmpmsg + 8, msg_size, OS_MAXSTR - 12);
511 merror(COMPRESS_ERR, __local_name, _finmsg);
516 /* Padding the message (needs to be div by 8) */
517 bfsize = 8 - (cmp_size % 8);
533 /* Getting average sizes */
534 c_orig_size+= msg_size;
535 c_comp_size+= cmp_size;
536 if(evt_count > _s_comp_print)
538 verbose("%s: INFO: Event count after '%u': %u->%u (%d%%)", __local_name,
542 (c_comp_size * 100)/c_orig_size);
549 /* If the ip is dynamic (not single host, append agent id
552 if(!isSingleHost(keys->keyentries[id]->ip) && isAgent)
554 snprintf(msg_encrypted, 16, "!%s!:", keys->keyentries[id]->id);
555 msg_size = strlen(msg_encrypted);
559 /* Setting beginning of the message */
560 msg_encrypted[0] = ':';
565 /* msg_size is the ammount of non-encrypted message
566 * appended to the buffer. On dynamic ips, it will
567 * include the agent id.
570 /* Encrypting everything */
571 OS_BF_Str(_tmpmsg + (7 - bfsize), msg_encrypted + msg_size,
572 keys->keyentries[id]->key,
577 /* Storing before leaving */
578 StoreSenderCounter(keys, global_count, local_count);
580 return(cmp_size + msg_size);