1 /****************************************************************************
2  *
3  * UTILS.C - Utility functions for NSCA
4  *
5  * License: GPL
6  * Copyright (c) 2000-2008 Ethan Galstad (nagios@nagios.org)
7  *
8  * Last Modified: 01-15-2008
9  *
10  * Description:
11  *
12  * This file contains common unctions used in nsca and send_nsca
13  *
14  * License Information:
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29  *
30  ****************************************************************************/
31 
32 #include "../include/common.h"
33 #include "../include/utils.h"
34 
35 
36 /*#define DEBUG*/
37 
38 static unsigned long crc32_table[256];
39 #ifdef HAVE_LIBMCRYPT
40 static volatile sig_atomic_t mcrypt_initialized=FALSE;
41 #endif
42 
43 /* escapes newlines in a string, snagged from nagios-3.0.6/base/utils.c */
escape_newlines(char * rawbuf)44 char *escape_newlines(char *rawbuf){
45         char *newbuf=NULL;
46         register int x,y;
47 
48         if(rawbuf==NULL)
49                 return NULL;
50 
51         /* allocate enough memory to escape all chars if necessary */
52         if((newbuf=malloc((strlen(rawbuf)*2)+1))==NULL)
53                 return NULL;
54 
55         for(x=0,y=0;rawbuf[x]!=(char)'\x0';x++){
56 
57                 /* escape backslashes */
58                 if(rawbuf[x]=='\\'){
59                         newbuf[y++]='\\';
60                         newbuf[y++]='\\';
61                         }
62 
63                 /* escape newlines */
64                 else if(rawbuf[x]=='\n'){
65                         newbuf[y++]='\\';
66                         newbuf[y++]='n';
67                         }
68 
69                 else
70                         newbuf[y++]=rawbuf[x];
71                 }
72         newbuf[y]='\x0';
73 
74         return newbuf;
75         }
76 
77 /* build the crc table - must be called before calculating the crc value */
generate_crc32_table(void)78 void generate_crc32_table(void){
79 	unsigned long crc, poly;
80 	int i, j;
81 
82 	poly=0xEDB88320L;
83 	for(i=0;i<256;i++){
84 		crc=i;
85 		for(j=8;j>0;j--){
86 			if(crc & 1)
87 				crc=(crc>>1)^poly;
88 			else
89 				crc>>=1;
90 		        }
91 		crc32_table[i]=crc;
92                 }
93 
94 	return;
95         }
96 
97 
98 /* calculates the CRC 32 value for a buffer */
calculate_crc32(char * buffer,int buffer_size)99 unsigned long calculate_crc32(char *buffer, int buffer_size){
100 	register unsigned long crc;
101 	int this_char;
102 	int current_index;
103 
104 	crc=0xFFFFFFFF;
105 
106 	for(current_index=0;current_index<buffer_size;current_index++){
107 		this_char=(int)buffer[current_index];
108 		crc=((crc>>8) & 0x00FFFFFF) ^ crc32_table[(crc ^ this_char) & 0xFF];
109 	        }
110 
111 	return (crc ^ 0xFFFFFFFF);
112         }
113 
114 
115 
116 /* initializes encryption routines */
encrypt_init(char * password,int encryption_method,char * received_iv,struct crypt_instance ** CIptr)117 int encrypt_init(char *password,int encryption_method,char *received_iv,struct crypt_instance **CIptr){
118 #ifdef HAVE_LIBMCRYPT
119         int i;
120         int iv_size;
121 #endif
122         struct crypt_instance *CI;
123 
124         CI=malloc(sizeof(struct crypt_instance));
125         *CIptr=CI;
126 
127         if(CI==NULL){
128                 syslog(LOG_ERR, "Could not allocate memory for crypt instance");
129                 return ERROR;
130                 }
131 
132 	/* server generates IV used for encryption */
133         if(received_iv==NULL)
134                 generate_transmitted_iv(CI->transmitted_iv);
135 
136 	/* client recieves IV from server */
137         else
138                 memcpy(CI->transmitted_iv,received_iv,TRANSMITTED_IV_SIZE);
139 
140 #ifdef HAVE_LIBMCRYPT
141         CI->blocksize=1;                        /* block size = 1 byte w/ CFB mode */
142         CI->keysize=7;                          /* default to 56 bit key length */
143         CI->mcrypt_mode="cfb";                  /* CFB = 8-bit cipher-feedback mode */
144         CI->mcrypt_algorithm="unknown";
145 #endif
146 
147         /* XOR or no encryption */
148         if(encryption_method==ENCRYPT_NONE || encryption_method==ENCRYPT_XOR)
149                 return OK;
150 
151 #ifdef HAVE_LIBMCRYPT
152 
153         /* get the name of the mcrypt encryption algorithm to use */
154         switch(encryption_method){
155         case ENCRYPT_DES:
156                 CI->mcrypt_algorithm=MCRYPT_DES;
157                 break;
158         case ENCRYPT_3DES:
159                 CI->mcrypt_algorithm=MCRYPT_3DES;
160                 break;
161         case ENCRYPT_CAST128:
162                 CI->mcrypt_algorithm=MCRYPT_CAST_128;
163                 break;
164         case ENCRYPT_CAST256:
165                 CI->mcrypt_algorithm=MCRYPT_CAST_256;
166                 break;
167         case ENCRYPT_XTEA:
168                 CI->mcrypt_algorithm=MCRYPT_XTEA;
169                 break;
170         case ENCRYPT_3WAY:
171                 CI->mcrypt_algorithm=MCRYPT_3WAY;
172                 break;
173         case ENCRYPT_BLOWFISH:
174                 CI->mcrypt_algorithm=MCRYPT_BLOWFISH;
175                 break;
176         case ENCRYPT_TWOFISH:
177                 CI->mcrypt_algorithm=MCRYPT_TWOFISH;
178                 break;
179         case ENCRYPT_LOKI97:
180                 CI->mcrypt_algorithm=MCRYPT_LOKI97;
181                 break;
182         case ENCRYPT_RC2:
183                 CI->mcrypt_algorithm=MCRYPT_RC2;
184                 break;
185         case ENCRYPT_ARCFOUR:
186                 CI->mcrypt_algorithm=MCRYPT_ARCFOUR;
187                 break;
188         case ENCRYPT_RIJNDAEL128:
189                 CI->mcrypt_algorithm=MCRYPT_RIJNDAEL_128;
190                 break;
191         case ENCRYPT_RIJNDAEL192:
192                 CI->mcrypt_algorithm=MCRYPT_RIJNDAEL_192;
193                 break;
194         case ENCRYPT_RIJNDAEL256:
195                 CI->mcrypt_algorithm=MCRYPT_RIJNDAEL_256;
196                 break;
197         case ENCRYPT_WAKE:
198                 CI->mcrypt_algorithm=MCRYPT_WAKE;
199                 break;
200         case ENCRYPT_SERPENT:
201                 CI->mcrypt_algorithm=MCRYPT_SERPENT;
202                 break;
203         case ENCRYPT_ENIGMA:
204                 CI->mcrypt_algorithm=MCRYPT_ENIGMA;
205                 break;
206         case ENCRYPT_GOST:
207                 CI->mcrypt_algorithm=MCRYPT_GOST;
208                 break;
209         case ENCRYPT_SAFER64:
210                 CI->mcrypt_algorithm=MCRYPT_SAFER_SK64;
211                 break;
212         case ENCRYPT_SAFER128:
213                 CI->mcrypt_algorithm=MCRYPT_SAFER_SK128;
214                 break;
215         case ENCRYPT_SAFERPLUS:
216                 CI->mcrypt_algorithm=MCRYPT_SAFERPLUS;
217                 break;
218 
219         default:
220                 CI->mcrypt_algorithm="unknown";
221                 break;
222                 }
223 
224 #ifdef DEBUG
225         syslog(LOG_INFO,"Attempting to initialize '%s' crypto algorithm...",CI->mcrypt_algorithm);
226 #endif
227 
228         /* open encryption module */
229         if((CI->td=mcrypt_module_open(CI->mcrypt_algorithm,NULL,CI->mcrypt_mode,NULL))==MCRYPT_FAILED){
230                 syslog(LOG_ERR,"Could not open mcrypt algorithm '%s' with mode '%s'",CI->mcrypt_algorithm,CI->mcrypt_mode);
231                 return ERROR;
232                 }
233 
234 #ifdef DEBUG
235         syslog(LOG_INFO,"Using '%s' as crypto algorithm...",CI->mcrypt_algorithm);
236 #endif
237 
238         /* determine size of IV buffer for this algorithm */
239         iv_size=mcrypt_enc_get_iv_size(CI->td);
240         if(iv_size>TRANSMITTED_IV_SIZE){
241                 syslog(LOG_ERR,"IV size for crypto algorithm exceeds limits");
242                 return ERROR;
243                 }
244 
245         /* allocate memory for IV buffer */
246         if((CI->IV=(char *)malloc(iv_size))==NULL){
247                 syslog(LOG_ERR,"Could not allocate memory for IV buffer");
248                 return ERROR;
249                 }
250 
251         /* fill IV buffer with first bytes of IV that is going to be used to crypt (determined by server) */
252         for(i=0;i<iv_size;i++)
253                 CI->IV[i]=CI->transmitted_iv[i];
254 
255         /* get maximum key size for this algorithm */
256         CI->keysize=mcrypt_enc_get_key_size(CI->td);
257 
258         /* generate an encryption/decription key using the password */
259         if((CI->key=(char *)malloc(CI->keysize))==NULL){
260                 syslog(LOG_ERR,"Could not allocate memory for encryption/decryption key");
261                 return ERROR;
262                 }
263         bzero(CI->key,CI->keysize);
264 
265         if(CI->keysize<strlen(password))
266                 strncpy(CI->key,password,CI->keysize);
267         else
268                 strncpy(CI->key,password,strlen(password));
269 
270         /* initialize encryption buffers */
271         mcrypt_generic_init(CI->td,CI->key,CI->keysize,CI->IV);
272         mcrypt_initialized=TRUE;
273 #endif
274 
275         return OK;
276         }
277 
278 
279 
280 /* encryption routine cleanup */
encrypt_cleanup(int encryption_method,struct crypt_instance * CI)281 void encrypt_cleanup(int encryption_method, struct crypt_instance *CI){
282 
283 	/* no crypt instance */
284 	if(CI==NULL)
285 		return;
286 
287 #ifdef HAVE_LIBMCRYPT
288         /* mcrypt cleanup */
289         if(encryption_method!=ENCRYPT_NONE && encryption_method!=ENCRYPT_XOR){
290 		if(mcrypt_initialized==TRUE)
291 			mcrypt_generic_end(CI->td);
292 		free(CI->key);
293 		CI->key=NULL;
294 		free(CI->IV);
295 		CI->IV=NULL;
296 		}
297 #endif
298 
299         free(CI);
300 
301         return;
302         }
303 
304 
305 
306 /* generates IV to use for encrypted communications (function is called by server only, client uses IV it receives from server) */
generate_transmitted_iv(char * transmitted_iv)307 static void generate_transmitted_iv(char *transmitted_iv){
308         FILE *fp;
309         int x;
310         int seed=0;
311 
312         /*********************************************************/
313         /* fill IV buffer with data that's as random as possible */
314         /*********************************************************/
315 
316         /* try to get seed value from /dev/urandom, as its a better source of entropy */
317         fp=fopen("/dev/urandom","r");
318         if(fp!=NULL){
319                 seed=fgetc(fp);
320                 fclose(fp);
321                 }
322 
323         /* else fallback to using the current time as the seed */
324         else
325                 seed=(int)time(NULL);
326 
327         /* generate pseudo-random IV */
328         srand(seed);
329         for(x=0;x<TRANSMITTED_IV_SIZE;x++)
330                 transmitted_iv[x]=(int)((256.0*rand())/(RAND_MAX+1.0));
331 
332         return;
333         }
334 
335 
336 
337 /* encrypt a buffer */
encrypt_buffer(char * buffer,int buffer_size,char * password,int encryption_method,struct crypt_instance * CI)338 void encrypt_buffer(char *buffer,int buffer_size, char *password, int encryption_method, struct crypt_instance *CI){
339         int x;
340         int y;
341         int password_length;
342 
343 #ifdef DEBUG
344         syslog(LOG_INFO,"Encrypting with algorithm #%d",encryption_method);
345 #endif
346 
347 	/* no crypt instance */
348 	if(CI==NULL)
349 		return;
350 
351         /* no encryption */
352         if(encryption_method==ENCRYPT_NONE)
353                 return;
354 
355         /* simple XOR "encryption" - not meant for any real security, just obfuscates data, but its fast... */
356         else if(encryption_method==ENCRYPT_XOR){
357 
358                 /* rotate over IV we received from the server... */
359                 for(y=0,x=0;y<buffer_size;y++,x++){
360 
361                         /* keep rotating over IV */
362                         if(x>=TRANSMITTED_IV_SIZE)
363                                 x=0;
364 
365                         buffer[y]^=CI->transmitted_iv[x];
366                         }
367 
368                 /* rotate over password... */
369                 password_length=strlen(password);
370                 for(y=0,x=0;y<buffer_size;y++,x++){
371 
372                         /* keep rotating over password */
373                         if(x>=password_length)
374                                 x=0;
375 
376                         buffer[y]^=password[x];
377                         }
378 
379                 return;
380                 }
381 
382 #ifdef HAVE_LIBMCRYPT
383         /* use mcrypt routines */
384         else{
385 
386                 /* encrypt each byte of buffer, one byte at a time (CFB mode) */
387                 for(x=0;x<buffer_size;x++)
388                         mcrypt_generic(CI->td,&buffer[x],1);
389                 }
390 #endif
391 
392         return;
393         }
394 
395 
396 /* decrypt a buffer */
decrypt_buffer(char * buffer,int buffer_size,char * password,int encryption_method,struct crypt_instance * CI)397 void decrypt_buffer(char *buffer,int buffer_size, char *password, int encryption_method, struct crypt_instance *CI){
398         int x=0;
399 
400 #ifdef DEBUG
401         syslog(LOG_INFO,"Decrypting with algorithm #%d",encryption_method);
402 #endif
403 
404 	/* no crypt instance */
405 	if(CI==NULL)
406 		return;
407 
408         /* no encryption */
409         if(encryption_method==ENCRYPT_NONE)
410                 return;
411 
412         /* XOR "decryption" is the same as encryption */
413         else if(encryption_method==ENCRYPT_XOR)
414                 encrypt_buffer(buffer,buffer_size,password,encryption_method,CI);
415 
416 #ifdef HAVE_LIBMCRYPT
417         /* use mcrypt routines */
418         else{
419 
420                 /* encrypt each byte of buffer, one byte at a time (CFB mode) */
421                 for(x=0;x<buffer_size;x++)
422                         mdecrypt_generic(CI->td,&buffer[x],1);
423                 }
424 #endif
425 
426         return;
427         }
428 
429 
430 
431 /* fill a buffer with semi-random data */
randomize_buffer(char * buffer,int buffer_size)432 void randomize_buffer(char *buffer,int buffer_size){
433 	FILE *fp;
434 	int x;
435 	int seed;
436 
437 	/**** FILL BUFFER WITH RANDOM ALPHA-NUMERIC CHARACTERS ****/
438 
439 	/***************************************************************
440 	   Only use alpha-numeric characters becase plugins usually
441 	   only generate numbers and letters in their output.  We
442 	   want the buffer to contain the same set of characters as
443 	   plugins, so its harder to distinguish where the real output
444 	   ends and the rest of the buffer (padded randomly) starts.
445 	***************************************************************/
446 
447 	/* try to get seed value from /dev/urandom, as its a better source of entropy */
448 	fp=fopen("/dev/urandom","r");
449 	if(fp!=NULL){
450 		seed=fgetc(fp);
451 		fclose(fp);
452 	        }
453 
454 	/* else fallback to using the current time as the seed */
455 	else
456 		seed=(int)time(NULL);
457 
458 	srand(seed);
459 	for(x=0;x<buffer_size;x++)
460 		buffer[x]=(int)'0'+(int)(72.0*rand()/(RAND_MAX+1.0));
461 
462 	return;
463         }
464 
465 
466 
467 /* strips trailing newlines, carriage returns, spaces, and tabs from a string */
strip(char * buffer)468 void strip(char *buffer){
469 	int x;
470 	int index;
471 
472 	for(x=strlen(buffer);x>=1;x--){
473 		index=x-1;
474 		if(buffer[index]==' ' || buffer[index]=='\r' || buffer[index]=='\n' || buffer[index]=='\t')
475 			buffer[index]='\x0';
476 		else
477 			break;
478 	        }
479 
480 	return;
481         }
482 
483 
484 
485 /* wipes an area of memory clean */
clear_buffer(char * buffer,int buffer_length)486 void clear_buffer(char *buffer, int buffer_length){
487 
488 	/* NULL all bytes of buffer */
489 	memset(buffer,'\x0',buffer_length);
490 
491 	return;
492         }
493 
494 
495 
496 /* show license */
display_license(void)497 void display_license(void){
498 
499 	printf("This program is free software; you can redistribute it and/or modify\n");
500 	printf("it under the terms of the GNU General Public License as published by\n");
501 	printf("the Free Software Foundation; either version 2 of the License, or\n");
502 	printf("(at your option) any later version.\n\n");
503 	printf("This program is distributed in the hope that it will be useful,\n");
504 	printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
505 	printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n");
506 	printf("GNU General Public License for more details.\n\n");
507 	printf("You should have received a copy of the GNU General Public License\n");
508 	printf("along with this program; if not, write to the Free Software\n");
509 	printf("Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
510 
511 	return;
512         }
513