1 /* @(#) $Id: ./src/os_crypto/shared/msgs.c, 2011/09/08 dcid Exp $
4 /* Copyright (C) 2009 Trend Micro Inc.
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
12 * License details at the LICENSE file included with OSSEC or
13 * online at: http://www.ossec.net/en/licensing.html
19 #include "headers/sec.h"
21 #include "os_zlib/os_zlib.h"
22 #include "os_crypto/md5/md5_op.h"
23 #include "os_crypto/blowfish/bf_op.h"
26 /** Sending counts **/
27 unsigned int global_count = 0;
28 unsigned int local_count = 0;
31 /** Average compression rates **/
34 unsigned int c_orig_size = 0;
35 unsigned int c_comp_size = 0;
38 /** Static variables (read from define file) **/
39 int _s_comp_print = 0;
40 int _s_recv_flush = 0;
42 int _s_verify_counter = 1;
46 * Read counters for each agent.
48 void OS_StartCounter(keystore *keys)
51 char rids_file[OS_FLSIZE +1];
53 rids_file[OS_FLSIZE] = '\0';
56 debug1("%s: OS_StartCounter: keysize: %d", __local_name, keys->keysize);
59 /* Starting receiving counter */
60 for(i = 0; i<=keys->keysize; i++)
62 /* On i == keysize, we deal with the
65 if(i == keys->keysize)
67 snprintf(rids_file, OS_FLSIZE, "%s/%s",
73 snprintf(rids_file, OS_FLSIZE, "%s/%s",
75 keys->keyentries[i]->id);
78 keys->keyentries[i]->fp = fopen(rids_file, "r+");
80 /* If nothing is there, try to open as write only */
81 if(!keys->keyentries[i]->fp)
83 keys->keyentries[i]->fp = fopen(rids_file, "w");
84 if(!keys->keyentries[i]->fp)
88 /* Just in case we run out of file descriptiors */
89 if((keys->keyentries[i -1]->fp) && (i > 10))
91 fclose(keys->keyentries[i -1]->fp);
93 if(keys->keyentries[i -2]->fp)
95 fclose(keys->keyentries[i -2]->fp);
99 merror("%s: Unable to open agent file. errno: %d",
100 __local_name, my_error);
101 ErrorExit(FOPEN_ERROR, __local_name, rids_file);
106 unsigned int g_c = 0, l_c = 0;
107 if(fscanf(keys->keyentries[i]->fp,"%u:%u", &g_c, &l_c) != 2)
109 if(i == keys->keysize)
111 verbose("%s: INFO: No previous sender counter.", __local_name);
115 verbose("%s: INFO: No previous counter available for '%s'.",
117 keys->keyentries[i]->name);
124 if(i == keys->keysize)
126 verbose("%s: INFO: Assigning sender counter: %d:%d",
127 __local_name, g_c, l_c);
133 verbose("%s: INFO: Assigning counter for agent %s: '%d:%d'.",
134 __local_name, keys->keyentries[i]->name, g_c, l_c);
136 keys->keyentries[i]->global = g_c;
137 keys->keyentries[i]->local = l_c;
142 debug2("%s: DEBUG: Stored counter.", __local_name);
144 /* Getting counter values */
145 if(_s_recv_flush == 0)
147 _s_recv_flush = getDefine_Int("remoted",
148 "recv_counter_flush",
152 /* Average printout values */
153 if(_s_comp_print == 0)
155 _s_comp_print = getDefine_Int("remoted",
156 "comp_average_printout",
161 _s_verify_counter = getDefine_Int("remoted", "verify_msg_id" , 0, 1);
166 /** OS_RemoveCounter(char *id)
167 * Remove the ID counter.
169 void OS_RemoveCounter(char *id)
171 char rids_file[OS_FLSIZE +1];
172 snprintf(rids_file, OS_FLSIZE, "%s/%s",RIDS_DIR, id);
177 /** StoreSenderCounter((keystore *keys, int global, int local)
178 * Store sender counter.
180 void StoreSenderCounter(keystore *keys, int global, int local)
182 /* Writting at the beginning of the file */
183 fseek(keys->keyentries[keys->keysize]->fp, 0, SEEK_SET);
184 fprintf(keys->keyentries[keys->keysize]->fp, "%u:%u:", global, local);
188 /* StoreCount(keystore *keys, int id, int global, int local)
189 * Store the global and local count of events.
191 void StoreCounter(keystore *keys, int id, int global, int local)
193 /* Writting at the beginning of the file */
194 fseek(keys->keyentries[id]->fp, 0, SEEK_SET);
195 fprintf(keys->keyentries[id]->fp, "%u:%u:", global, local);
199 /* CheckSum v0.1: 2005/02/15
200 * Verify the checksum of the message.
201 * Returns NULL on error or the message on success.
203 char *CheckSum(char *msg)
210 strncpy(recvd_sum,msg,32);
215 OS_MD5_Str(msg, checksum);
216 if(strncmp(checksum,recvd_sum,32) != 0)
226 /* ReadSecMSG v0.2: 2005/02/10 */
227 char *ReadSecMSG(keystore *keys, char *buffer, char *cleartext,
228 int id, int buffer_size)
231 unsigned int msg_global = 0;
232 unsigned int msg_local = 0;
243 merror(ENCFORMAT_ERROR, __local_name, keys->keyentries[id]->ip->ip);
247 /* Decrypting message */
248 if(!OS_BF_Str(buffer, cleartext, keys->keyentries[id]->key,
249 buffer_size, OS_DECRYPT))
251 merror(ENCKEY_ERROR, __local_name, keys->keyentries[id]->ip->ip);
257 else if(cleartext[0] == '!')
259 cleartext[buffer_size] = '\0';
263 /* Removing padding */
264 while(*cleartext == '!')
271 cmp_size = os_uncompress(cleartext, buffer, buffer_size, OS_MAXSTR);
274 merror(UNCOMPRESS_ERR, __local_name);
278 /* Checking checksum */
279 f_msg = CheckSum(buffer);
282 merror(ENCSUM_ERROR, __local_name, keys->keyentries[id]->ip->ip);
286 /* Removing random */
290 /* Checking count -- protecting against replay attacks */
291 msg_global = atoi(f_msg);
294 /* Checking for the right message format */
297 merror(ENCFORMAT_ERROR, __local_name,keys->keyentries[id]->ip->ip);
302 msg_local = atoi(f_msg);
306 /* Returning the message if we don't need to verify the counbter. */
307 if(!_s_verify_counter)
309 /* Updating currently counts */
310 keys->keyentries[id]->global = msg_global;
311 keys->keyentries[id]->local = msg_local;
312 if(rcv_count >= _s_recv_flush)
314 StoreCounter(keys, id, msg_global, msg_local);
322 if((msg_global > keys->keyentries[id]->global)||
323 ((msg_global == keys->keyentries[id]->global) &&
324 (msg_local > keys->keyentries[id]->local)))
326 /* Updating currently counts */
327 keys->keyentries[id]->global = msg_global;
328 keys->keyentries[id]->local = msg_local;
330 if(rcv_count >= _s_recv_flush)
332 StoreCounter(keys, id, msg_global, msg_local);
340 /* Checking if it is a duplicated message */
341 if(msg_global == keys->keyentries[id]->global)
347 /* Warn about duplicated messages */
348 merror("%s: WARN: Duplicate error: global: %d, local: %d, "
349 "saved global: %d, saved local:%d",
353 keys->keyentries[id]->global,
354 keys->keyentries[id]->local);
356 merror(ENCTIME_ERROR, __local_name, keys->keyentries[id]->name);
361 else if(cleartext[0] == ':')
367 cleartext[buffer_size] = '\0';
370 /* Checking checksum */
372 f_msg = CheckSum(cleartext);
375 merror(ENCSUM_ERROR, __local_name, keys->keyentries[id]->ip->ip);
380 /* Checking time -- protecting against replay attacks */
381 msg_time = atoi(f_msg);
384 msg_count = atoi(f_msg);
388 /* Returning the message if we don't need to verify the counbter. */
389 if(!_s_verify_counter)
391 /* Updating currently counts */
392 keys->keyentries[id]->global = msg_time;
393 keys->keyentries[id]->local = msg_local;
395 f_msg = strchr(f_msg, ':');
404 if((msg_time > keys->keyentries[id]->global) ||
405 ((msg_time == keys->keyentries[id]->global)&&
406 (msg_count > keys->keyentries[id]->local)))
408 /* Updating currently time and count */
409 keys->keyentries[id]->global = msg_time;
410 keys->keyentries[id]->local = msg_count;
412 f_msg = strchr(f_msg, ':');
420 /* Checking if it is a duplicated message */
421 if((msg_count == keys->keyentries[id]->local) &&
422 (msg_time == keys->keyentries[id]->global))
428 /* Warn about duplicated message */
429 merror("%s: WARN: Duplicate error: msg_count: %d, time: %d, "
430 "saved count: %d, saved_time:%d",
434 keys->keyentries[id]->local,
435 keys->keyentries[id]->global);
437 merror(ENCTIME_ERROR, __local_name, keys->keyentries[id]->name);
441 merror(ENCFORMAT_ERROR, __local_name, keys->keyentries[id]->ip->ip);
447 /* Creat a encrypted message.
448 * Returns the size of it
450 int CreateSecMSG(keystore *keys, char *msg, char *msg_encrypted, int id)
458 char _tmpmsg[OS_MAXSTR + 2];
459 char _finmsg[OS_MAXSTR + 2];
463 msg_size = strlen(msg);
466 /* Checking for invalid msg sizes */
467 if((msg_size > (OS_MAXSTR - OS_HEADER_SIZE))||(msg_size < 1))
469 merror(ENCSIZE_ERROR, __local_name, msg);
474 rand1 = (u_int16_t)random();
477 _tmpmsg[OS_MAXSTR +1] = '\0';
478 _finmsg[OS_MAXSTR +1] = '\0';
479 msg_encrypted[OS_MAXSTR] = '\0';
482 /* Increasing local and global counters */
483 if(local_count >= 9997)
491 snprintf(_tmpmsg, OS_MAXSTR,"%05hu%010u:%04hu:%s",
492 rand1, global_count, local_count,
496 /* Generating md5sum of the unencrypted string */
497 OS_MD5_Str(_tmpmsg, md5sum);
501 /* Generating final msg to be compressed */
502 snprintf(_finmsg, OS_MAXSTR,"%s%s",md5sum,_tmpmsg);
503 msg_size = strlen(_finmsg);
506 /* Compressing message.
507 * We assing the first 8 bytes for padding.
509 cmp_size = os_compress(_finmsg, _tmpmsg + 8, msg_size, OS_MAXSTR - 12);
512 merror(COMPRESS_ERR, __local_name, _finmsg);
517 /* Padding the message (needs to be div by 8) */
518 bfsize = 8 - (cmp_size % 8);
534 /* Getting average sizes */
535 c_orig_size+= msg_size;
536 c_comp_size+= cmp_size;
537 if(evt_count > _s_comp_print)
539 verbose("%s: INFO: Event count after '%u': %u->%u (%d%%)", __local_name,
543 (c_comp_size * 100)/c_orig_size);
550 /* If the ip is dynamic (not single host, append agent id
553 if(!isSingleHost(keys->keyentries[id]->ip) && isAgent)
555 snprintf(msg_encrypted, 16, "!%s!:", keys->keyentries[id]->id);
556 msg_size = strlen(msg_encrypted);
560 /* Setting beginning of the message */
561 msg_encrypted[0] = ':';
566 /* msg_size is the ammount of non-encrypted message
567 * appended to the buffer. On dynamic ips, it will
568 * include the agent id.
571 /* Encrypting everything */
572 OS_BF_Str(_tmpmsg + (7 - bfsize), msg_encrypted + msg_size,
573 keys->keyentries[id]->key,
578 /* Storing before leaving */
579 StoreSenderCounter(keys, global_count, local_count);
581 return(cmp_size + msg_size);