1 /************************************************************************/
2 /*                                                                      */
3 /* PortSentry								*/
4 /*                                                                      */
5 /* Created: 10-12-1997                                                  */
6 /* Modified: 05-23-2003                                                 */
7 /*                                                                      */
8 /* Send all changes/modifications/bugfixes to:				*/
9 /* craigrowland at users dot sourceforge dot net    			*/
10 /*                                                                      */
11 /*                                                                      */
12 /* This software is Copyright(c) 1997-2003 Craig Rowland	        */
13 /*                                                                      */
14 /* This software is covered under the Common Public License v1.0	*/
15 /* See the enclosed LICENSE file for more information.			*/
16 /* $Id: portsentry_io.c,v 1.36 2003/05/23 17:41:40 crowland Exp crowland $ */
17 /************************************************************************/
18 
19 
20 #include "portsentry.h"
21 #include "portsentry_io.h"
22 #include "portsentry_util.h"
23 
24 /* Main logging function to surrogate syslog */
25 void
Log(char * logentry,...)26 Log (char *logentry, ...)
27 {
28   char logbuffer[MAXBUF];
29 
30   va_list argsPtr;
31   va_start (argsPtr, logentry);
32 
33   vsnprintf (logbuffer, MAXBUF, logentry, argsPtr);
34 
35   va_end(argsPtr);
36 
37   openlog ("portsentry", LOG_PID, SYSLOG_FACILITY);
38   syslog (SYSLOG_LEVEL, "%s", logbuffer);
39   closelog ();
40 }
41 
42 
43 void
Exit(int status)44 Exit (int status)
45 {
46   Log ("securityalert: PortSentry is shutting down\n");
47   Log ("adminalert: PortSentry is shutting down\n");
48   exit (status);
49 }
50 
51 
52 void
Start(void)53 Start (void)
54 {
55   Log ("adminalert: PortSentry %s is starting.\n", VERSION);
56 #ifdef DEBUG
57   printf("Compiled: " __DATE__ " at " __TIME__ "\n");
58 #endif
59 }
60 
61 
62 
63 /* The daemonizing code copied from Advanced Programming */
64 /* in the UNIX Environment by W. Richard Stevens with minor changes */
65 int
DaemonSeed(void)66 DaemonSeed (void)
67 {
68   int childpid;
69 
70   signal (SIGALRM, SIG_IGN);
71   signal (SIGHUP, SIG_IGN);
72   signal (SIGPIPE, SIG_IGN);
73   signal (SIGTERM, Exit);
74   signal (SIGABRT, Exit);
75   signal (SIGURG, Exit);
76   signal (SIGKILL, Exit);
77 
78   if ((childpid = fork ()) < 0)
79     return (ERROR);
80   else if (childpid > 0)
81     exit (0);
82 
83   setsid ();
84   chdir ("/");
85   umask (077);
86 
87   /* close stdout, stdin, stderr */
88   close(0);
89   close(1);
90   close(2);
91 
92   return (TRUE);
93 }
94 
95 
96 /* Compares an IP address against a listed address and its netmask*/
97 int
CompareIPs(char * target,char * ignoreAddr,int ignoreNetmaskBits)98 CompareIPs(char *target, char *ignoreAddr, int ignoreNetmaskBits)
99 {
100   unsigned long int netmaskAddr, ipAddr, targetAddr;
101 
102   ipAddr = inet_addr(ignoreAddr);
103   targetAddr = inet_addr(target);
104   netmaskAddr = htonl (0xFFFFFFFF << (32 - ignoreNetmaskBits));
105 
106 
107 #ifdef DEBUG
108 	Log ("debug: target %s\n", target);
109 	Log ("debug: ignoreAddr %s\n", ignoreAddr);
110 	Log ("debug: ignoreNetmaskBits %d\n", ignoreNetmaskBits);
111 	Log ("debug: ipAddr %lu\n", ipAddr);
112 	Log ("debug: targetAddr %lu\n", targetAddr);
113 	Log ("debug: netmask %x\n", netmaskAddr);
114 	Log ("debug: mix ipAddr %lu\n", (ipAddr & netmaskAddr));
115 	Log ("debug: mix target %lu\n", (targetAddr & netmaskAddr));
116 #endif
117 
118   /* Network portion mask & op and return */
119   if ((ipAddr & netmaskAddr) == (targetAddr & netmaskAddr))
120 	return(TRUE);
121   else
122 	return(FALSE);
123 }
124 
125 
126 
127 /* check hosts that should never be blocked */
128 int
NeverBlock(char * target,char * filename)129 NeverBlock (char *target, char *filename)
130 {
131   FILE *input;
132   char buffer[MAXBUF], tempBuffer[MAXBUF], netmaskBuffer[MAXBUF];
133   char *slashPos;
134   int count = 0, dest = 0, netmaskBits = 0;
135 
136 #ifdef DEBUG
137   Log ("debug: NeverBlock: Opening ignore file: %s \n", filename);
138 #endif
139   if ((input = fopen (filename, "r")) == NULL)
140 	return (ERROR);
141 
142 #ifdef DEBUG
143   Log ("debug: NeverBlock: Doing lookup for host: %s \n", target);
144 #endif
145 
146   while (fgets (buffer, MAXBUF, input) != NULL)
147   {
148 	/* Reset destination counter */
149 	dest = 0;
150 
151 	if ((buffer[0] == '#') || (buffer[0] == '\n'))
152 		continue;
153 
154 	for(count = 0; count < strlen(buffer); count++)
155 	{
156 		/* Parse out digits, colons, and slashes. Everything else rejected */
157         	if((isdigit(buffer[count])) ||
158            	   (buffer[count] == '.') || (buffer[count] == ':') || (buffer[count] == '/'))
159         	{
160           		tempBuffer[dest++] = buffer[count];
161         	}
162         	else
163         	{
164           		tempBuffer[dest] = '\0';
165           		break;
166         	}
167 	}
168 
169 	/* Return pointer to slash if it exists and copy data to buffer */
170 	slashPos = strchr(tempBuffer, '/');
171 	if (slashPos)
172 	{
173 		SafeStrncpy(netmaskBuffer, slashPos + 1, MAXBUF);
174 		/* Terminate tempBuffer string at delimeter for later use */
175 		*slashPos = '\0';
176 	}
177 	else
178 		/* Copy in a 32 bit netmask if none given */
179 		SafeStrncpy(netmaskBuffer, "32", MAXBUF);
180 
181 
182 	/* Convert netmaskBuffer to bits in netmask */
183 	netmaskBits = atoi(netmaskBuffer);
184 	if ((netmaskBits < 0) || (netmaskBits > 32))
185 	{
186 		Log ("adminalert: Invalid netmask in config file: %s  Ignoring entry.\n", buffer);
187 		continue;
188 	}
189 
190 	if (CompareIPs(target, tempBuffer, netmaskBits))
191 	{
192 #ifdef DEBUG
193 	  		Log ("debug: NeverBlock: Host: %s found in ignore file with netmask %s\n", target, netmaskBuffer);
194 #endif
195 
196 	  		fclose (input);
197 	  		return (TRUE);
198 	}
199 
200    } /* end while() */
201 
202 #ifdef DEBUG
203   Log ("debug: NeverBlock: Host: %s NOT found in ignore file\n", target);
204 #endif
205 
206   fclose (input);
207   return (FALSE);
208 }
209 
210 
211 /* Make sure the config file is available */
212 int
CheckConfig(void)213 CheckConfig (void)
214 {
215   FILE *input;
216 
217   if ((input = fopen (CONFIG_FILE, "r")) == NULL)
218     {
219       Log ("adminalert: Cannot open config file: %s. Exiting\n", CONFIG_FILE);
220       return(FALSE);
221     }
222   else
223     fclose (input);
224 
225 return(TRUE);
226 }
227 
228 
229 /* This writes out blocked hosts to the blocked file. It adds the hostname */
230 /* time stamp, and port connection that was acted on */
231 int
WriteBlocked(char * target,char * resolvedHost,int port,char * blockedFilename,char * historyFilename,char * portType)232 WriteBlocked (char *target, char *resolvedHost, int port, char *blockedFilename,
233 char *historyFilename, char *portType)
234 {
235   FILE *output;
236   int blockedStatus = TRUE, historyStatus = TRUE;
237 
238   struct tm *tmptr;
239 
240   time_t current_time;
241   current_time = time (0);
242   tmptr = localtime (&current_time);
243 
244 
245 #ifdef DEBUG
246       Log ("debug: WriteBlocked: Opening block file: %s \n", blockedFilename);
247 #endif
248 
249 
250       if ((output = fopen (blockedFilename, "a")) == NULL)
251 	{
252 	  Log ("adminalert: ERROR: Cannot open blocked file: %s.\n", blockedFilename);
253 	  blockedStatus = FALSE;
254 	}
255       else
256 	{
257 	  fprintf (output, "%ld - %02d/%02d/%04d %02d:%02d:%02d Host: %s/%s Port: %d %s Blocked\n",
258 	    current_time, tmptr->tm_mon + 1, tmptr->tm_mday, tmptr->tm_year + 1900,
259 		   tmptr->tm_hour, tmptr->tm_min, tmptr->tm_sec, resolvedHost, target, port,
260 		   portType);
261 	  fclose (output);
262 	  blockedStatus = TRUE;
263 	}
264 
265 #ifdef DEBUG
266       Log ("debug: WriteBlocked: Opening history file: %s \n", historyFilename);
267 #endif
268       if ((output = fopen (historyFilename, "a")) == NULL)
269 	{
270 	  Log ("adminalert: ERROR: Cannot open history file: %s.\n", historyFilename);
271 	  historyStatus = FALSE;
272 	}
273       else
274 	{
275 	  fprintf (output, "%ld - %02d/%02d/%04d %02d:%02d:%02d Host: %s/%s Port: %d %s Blocked\n",
276 	    current_time, tmptr->tm_mon + 1, tmptr->tm_mday, tmptr->tm_year + 1900,
277 		   tmptr->tm_hour, tmptr->tm_min, tmptr->tm_sec, resolvedHost, target, port,
278 	  	   portType);
279 	  fclose (output);
280 	  historyStatus = TRUE;
281 	}
282 
283   if (historyStatus || blockedStatus == FALSE)
284     return (FALSE);
285   else
286     return (TRUE);
287 }
288 
289 
290 
291 
292 /* This reads a token from the config file up to the "=" and returns the string */
293 /* up to the first space or NULL */
294 int
ConfigTokenRetrieve(char * token,char * configToken)295 ConfigTokenRetrieve (char *token, char *configToken)
296 {
297   FILE *config;
298   char buffer[MAXBUF], tokenBuffer[MAXBUF];
299   int count = 0;
300 
301   if ((config = fopen (CONFIG_FILE, "r")) == NULL)
302     {
303       Log ("adminalert: ERROR: Cannot open config file: %s.\n", CONFIG_FILE);
304       return (ERROR);
305     }
306   else
307     {
308 #ifdef DEBUG
309       Log ("debug: ConfigTokenRetrieve: checking for token %s", token);
310 #endif
311       while ((fgets (buffer, MAXBUF, config)) != NULL)
312 	{
313 	  /* this skips comments */
314 	  if (buffer[0] != '#')
315 	    {
316 #ifdef DEBUG
317 	      Log ("debug: ConfigTokenRetrieve: data: %s", buffer);
318 #endif
319 	      /* search for the token and make sure the trailing character */
320 	      /* is a " " or "=" to make sure the entire token was found */
321 	      if ((strstr (buffer, token) != (char) NULL) &&
322 		   ((buffer[strlen(token)] == '=') || (buffer[strlen(token)] == ' ')))
323 		{		/* cut off the '=' and send it back */
324 		  if (strstr (buffer, "\"") == (char) NULL)
325 		    {
326 		      Log ("adminalert: Quotes missing from %s token. Option skipped\n", token);
327 		      fclose (config);
328 		      return (FALSE);
329 		    }
330 
331 		  SafeStrncpy (tokenBuffer, strstr (buffer, "\"") + 1, MAXBUF);
332 
333 		  /* strip off unprintables/linefeeds (if any) */
334 		  count = 0;
335 		  while (count < MAXBUF - 1)
336 		    {
337 		      if ((isprint (tokenBuffer[count])) && tokenBuffer[count] != '"')
338 			configToken[count] = tokenBuffer[count];
339 		      else
340 			{
341 			  configToken[count] = '\0';
342 			  break;
343 			}
344 		      count++;
345 		    }
346 
347 #ifdef DEBUG
348 		  Log ("debug: ConfigTokenRetrieved token: %s\n", configToken);
349 #endif
350 		  configToken[MAXBUF - 1] = '\0';
351 		  fclose (config);
352 		  return (TRUE);
353 		}
354 	    }
355 	}
356       fclose (config);
357       return (FALSE);
358     }
359 
360 }
361 
362 
363 
364 
365 /* This will bind a socket to a port. It works for UDP/TCP */
366 int
BindSocket(int sockfd,struct sockaddr_in client,struct sockaddr_in server,int port)367 BindSocket (int sockfd, struct sockaddr_in client,
368 		  struct sockaddr_in server, int port)
369 {
370 #ifdef DEBUG
371   Log ("debug: BindSocket: Binding to port: %d\n", port);
372 #endif
373 
374   bzero ((char *) &server, sizeof (server));
375   server.sin_family = AF_INET;
376   server.sin_addr.s_addr = htonl (INADDR_ANY);
377   server.sin_port = htons (port);
378 
379   if (bind (sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
380     {
381 #ifdef DEBUG
382       Log ("debug: BindSocket: Binding failed\n");
383 #endif
384       return (ERROR);
385     }
386   else
387     {
388 #ifdef DEBUG
389       Log ("debug: BindSocket: Binding successful. Doing listen\n");
390 #endif
391       listen (sockfd, 5);
392       return (TRUE);
393     }
394 }
395 
396 
397 /* Open a TCP Socket */
398 int
OpenTCPSocket(void)399 OpenTCPSocket (void)
400 {
401   int sockfd;
402 
403 #ifdef DEBUG
404   Log ("debug: OpenTCPSocket: opening TCP socket\n");
405 #endif
406 
407   if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
408     return (ERROR);
409   else
410     return (sockfd);
411 }
412 
413 
414 /* Open a UDP Socket */
415 int
OpenUDPSocket(void)416 OpenUDPSocket (void)
417 {
418   int sockfd;
419 
420 #ifdef DEBUG
421   Log ("debug: openUDPSocket opening UDP socket\n");
422 #endif
423 
424   if ((sockfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
425     return (ERROR);
426   else
427     return (sockfd);
428 }
429 
430 #ifdef SUPPORT_STEALTH
431 /* Open a RAW TCPSocket */
432 int
OpenRAWTCPSocket(void)433 OpenRAWTCPSocket (void)
434 {
435   int sockfd;
436 
437 #ifdef DEBUG
438   Log ("debug: OpenRAWTCPSocket: opening RAW TCP socket\n");
439 #endif
440 
441   if ((sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0)
442     return (ERROR);
443   else
444     return (sockfd);
445 }
446 
447 /* Open a RAW UDP Socket */
448 int
OpenRAWUDPSocket(void)449 OpenRAWUDPSocket (void)
450 {
451   int sockfd;
452 
453 #ifdef DEBUG
454   Log ("debug: OpenRAWUDPSocket: opening RAW UDP socket\n");
455 #endif
456 
457   if ((sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_UDP)) < 0)
458     return (ERROR);
459   else
460     return (sockfd);
461 }
462 #endif
463 
464 /* This will use a system() call to change the route of the target host to */
465 /* a dead IP address on your LOCAL SUBNET. */
466 int
KillRoute(char * target,int port,char * killString,char * detectionType)467 KillRoute (char *target, int port, char *killString, char *detectionType)
468 {
469   char cleanAddr[MAXBUF], commandStringTemp[MAXBUF];
470   char commandStringTemp2[MAXBUF],commandStringFinal[MAXBUF];
471   char portString[MAXBUF];
472   int killStatus = ERROR, substStatus = ERROR;
473 
474   CleanIpAddr (cleanAddr, target);
475   snprintf(portString, MAXBUF, "%d", port);
476 
477   substStatus = SubstString (cleanAddr, "$TARGET$", killString, commandStringTemp);
478   if (substStatus == 0)
479     {
480       Log ("adminalert: No target variable specified in KILL_ROUTE option. Skipping.\n");
481       return (ERROR);
482     }
483   else if (substStatus == ERROR)
484     {
485       Log ("adminalert: Error trying to parse $TARGET$ Token for KILL_ROUTE. Skipping.\n");
486       return (ERROR);
487     }
488 
489   if(SubstString (portString, "$PORT$", commandStringTemp, commandStringTemp2) == ERROR)
490     {
491       Log ("adminalert: Error trying to parse $PORT$ Token for KILL_ROUTE. Skipping.\n");
492       return (ERROR);
493     }
494 
495   if(SubstString (detectionType, "$MODE$", commandStringTemp2, commandStringFinal) == ERROR)
496     {
497       Log ("adminalert: Error trying to parse $MODE$ Token for KILL_ROUTE. Skipping.\n");
498       return (ERROR);
499     }
500 
501 
502 #ifdef DEBUG
503   Log ("debug: KillRoute: running route command: %s\n", commandStringFinal);
504 #endif
505 
506   /* Kill the bastard and report a status */
507   killStatus = system (commandStringFinal);
508 
509   if (killStatus == 127)
510     {
511       Log ("adminalert: ERROR: There was an error trying to block host (exec fail) %s", target);
512       return (ERROR);
513     }
514   else if (killStatus < 0)
515     {
516       Log ("adminalert: ERROR: There was an error trying to block host (system fail) %s", target);
517       return (ERROR);
518     }
519   else
520     {
521       Log ("attackalert: Host %s has been blocked via dropped route using command: \"%s\"", target,
522 		commandStringFinal);
523       return (TRUE);
524     }
525 }
526 
527 
528 
529 /* This will run a specified command with TARGET as the option if one is given. */
530 int
KillRunCmd(char * target,int port,char * killString,char * detectionType)531 KillRunCmd (char *target, int port, char *killString, char *detectionType)
532 {
533   char cleanAddr[MAXBUF], commandStringTemp[MAXBUF];
534   char commandStringTemp2[MAXBUF], commandStringFinal[MAXBUF];
535   char portString[MAXBUF];
536   int killStatus = ERROR;
537 
538   CleanIpAddr (cleanAddr, target);
539   snprintf(portString, MAXBUF, "%d", port);
540 
541   /* Tokens are not required, but we check for an error anyway */
542   if(SubstString (cleanAddr, "$TARGET$", killString, commandStringTemp) == ERROR)
543     {
544       Log ("adminalert: Error trying to parse $TARGET$ Token for KILL_RUN_CMD. Skipping.\n");
545       return (ERROR);
546     }
547 
548   if(SubstString (portString, "$PORT$", commandStringTemp, commandStringTemp2) == ERROR)
549     {
550       Log ("adminalert: Error trying to parse $PORT$ Token for KILL_RUN_CMD. Skipping.\n");
551       return (ERROR);
552     }
553 
554   if(SubstString (detectionType, "$MODE$", commandStringTemp2, commandStringFinal) == ERROR)
555     {
556       Log ("adminalert: Error trying to parse $MODE$ Token for KILL_RUN_CMD. Skipping.\n");
557       return (ERROR);
558     }
559 
560 
561   /* Kill the bastard and report a status */
562   killStatus = system (commandStringFinal);
563 
564   if (killStatus == 127)
565     {
566       Log ("adminalert: ERROR: There was an error trying to run command (exec fail) %s", target);
567       return (ERROR);
568     }
569   else if (killStatus < 0)
570     {
571       Log ("adminalert: ERROR: There was an error trying to run command (system fail) %s", target);
572       return (ERROR);
573     }
574   else
575     {
576       /* report success */
577       Log ("attackalert: External command run for host: %s using command: \"%s\"", target,
578 		commandStringFinal);
579       return (TRUE);
580     }
581 }
582 
583 
584 /* this function will drop the host into the TCP wrappers hosts.deny file to deny */
585 /* all access. The drop route metod is preferred as this stops UDP attacks as well */
586 /* as TCP. You may find though that host.deny will be a more permanent home.. */
587 int
KillHostsDeny(char * target,int port,char * killString,char * detectionType)588 KillHostsDeny (char *target, int port, char *killString, char *detectionType)
589 {
590 
591   FILE *output;
592   char cleanAddr[MAXBUF], commandStringTemp[MAXBUF];
593   char commandStringTemp2[MAXBUF], commandStringFinal[MAXBUF];
594   char portString[MAXBUF];
595   int substStatus = ERROR;
596 
597   CleanIpAddr (cleanAddr, target);
598 
599   snprintf(portString, MAXBUF, "%d", port);
600 
601 #ifdef DEBUG
602   Log ("debug: KillHostsDeny: parsing string for block: %s\n", killString);
603 #endif
604 
605   substStatus = SubstString (cleanAddr, "$TARGET$", killString, commandStringTemp);
606   if (substStatus == 0)
607     {
608       Log ("adminalert: No target variable specified in KILL_HOSTS_DENY option. Skipping.\n");
609       return (ERROR);
610     }
611   else if (substStatus == ERROR)
612     {
613       Log ("adminalert: Error trying to parse $TARGET$ Token for KILL_HOSTS_DENY. Skipping.\n");
614       return (ERROR);
615     }
616 
617   if(SubstString (portString, "$PORT$", commandStringTemp, commandStringTemp2) == ERROR)
618     {
619       Log ("adminalert: Error trying to parse $PORT$ Token for KILL_HOSTS_DENY. Skipping.\n");
620       return (ERROR);
621     }
622 
623   if(SubstString (detectionType, "$MODE$", commandStringTemp2, commandStringFinal) == ERROR)
624     {
625       Log ("adminalert: Error trying to parse $MODE$ Token for KILL_HOSTS_DENY. Skipping.\n");
626       return (ERROR);
627     }
628 
629 #ifdef DEBUG
630   Log ("debug: KillHostsDeny: result string for block: %s\n", commandStringFinal);
631 #endif
632 
633   if ((output = fopen (WRAPPER_HOSTS_DENY, "a")) == NULL)
634     {
635       Log ("adminalert: cannot open hosts.deny file: %s for blocking.", WRAPPER_HOSTS_DENY);
636       Log ("securityalert: ERROR: There was an error trying to block host %s", target);
637       return (FALSE);
638     }
639   else
640     {
641       fprintf (output, "%s\n", commandStringFinal);
642       fclose (output);
643       Log ("attackalert: Host %s has been blocked via wrappers with string: \"%s\"", target, commandStringFinal);
644       return (TRUE);
645     }
646 }
647 
648 
649 /* check if the host is already blocked */
650 int
IsBlocked(char * target,char * filename)651 IsBlocked (char *target, char *filename)
652 {
653   FILE *input;
654   char buffer[MAXBUF], tempBuffer[MAXBUF];
655   char *ipOffset;
656   int count;
657 
658 
659 #ifdef DEBUG
660   Log ("debug: IsBlocked: Opening block file: %s \n", filename);
661 #endif
662   if ((input = fopen (filename, "r")) == NULL)
663   {
664 	Log ("adminalert: ERROR: Cannot open blocked file: %s for reading. Will create.\n", filename);
665 	return (FALSE);
666   }
667 
668   while (fgets (buffer, MAXBUF, input) != NULL)
669   {
670 	if((ipOffset = strstr(buffer, target)) != (char) NULL)
671 	{
672 		for(count = 0; count < strlen(ipOffset); count++)
673 		{
674 			if((isdigit(ipOffset[count])) ||
675 				(ipOffset[count] == '.'))
676 			{
677 				tempBuffer[count] = ipOffset[count];
678 			}
679 			else
680 			{
681 				tempBuffer[count] = '\0';
682 				break;
683 			}
684 		}
685 		if(strcmp(target, tempBuffer) == 0)
686 		{
687 #ifdef DEBUG
688 	  		Log ("debug: isBlocked: Host: %s found in blocked  file\n", target);
689 #endif
690 	  		fclose (input);
691 	  		return (TRUE);
692 		}
693 	}
694 
695     }
696 #ifdef DEBUG
697       Log ("debug: IsBlocked: Host: %s NOT found in blocked file\n", target);
698 #endif
699   fclose(input);
700   return (FALSE);
701 }
702 
703 /*********************************************************************************
704 * String substitute function
705 *
706 * This function takes:
707 *
708 * 1) A token to use for replacement.
709 * 2) A token to find.
710 * 3) A string with the tokens in it.
711 * 4) A string to write the replaced result.
712 *
713 * It returns the number of substitutions made during the operation.
714 **********************************************************************************/
SubstString(const char * replace,const char * find,const char * target,char * result)715 int SubstString (const char *replace, const char *find, const char *target, char *result)
716 {
717 int replaceCount = 0, count = 0, findCount = 0, findLen=0, numberOfSubst=0;
718 char tempString[MAXBUF], *tempStringPtr;
719 
720 #ifdef DEBUG
721   Log ("debug: SubstString: Processing string: %s %d", target, strlen(target));
722   Log ("debug: SubstString: Processing search text: %s %d", replace, strlen(replace));
723   Log ("debug: SubstString: Processing replace text: %s %d", find, strlen(find));
724 #endif
725 
726 	/* string not found in target */
727   	if (strstr (target, find) == (char) NULL)
728 	{
729 		strncpy(result, target, MAXBUF);
730 		#ifdef DEBUG
731   			Log ("debug: SubstString: Result string: %s", result);
732 		#endif
733     		return (numberOfSubst);
734 	}
735 	/* String/victim/target too long */
736   	else if ((strlen (target)) + (strlen(replace)) + (strlen(find)) > MAXBUF)
737     		return (ERROR);
738 
739 	memset(tempString, '\0', MAXBUF);
740 	memset(result, '\0', MAXBUF);
741 	findLen = strlen(find);
742 	tempStringPtr = tempString;
743 
744 	for(count = 0; count < MAXBUF; count++)
745 	{
746 		if(*target == '\0')
747 			break;
748 		else if((strncmp(target, find, findLen)) != 0)
749 			*tempStringPtr++ = *target++;
750 		else
751 		{
752 			numberOfSubst++;
753 			for(replaceCount = 0; replaceCount < strlen(replace); replaceCount++)
754 				*tempStringPtr++ = replace[replaceCount];
755 			for(findCount = 0; findCount < findLen; findCount++)
756 				target++;
757 		}
758 	}
759 
760 strncpy(result, tempString, MAXBUF);
761 #ifdef DEBUG
762   Log ("debug: SubstString: Result string: %s", result);
763 #endif
764 return(numberOfSubst);
765 }
766 
767 
768 
769 /* This function checks a config variable for a numerical flag and returns it */
770 int
CheckFlag(char * flagName)771 CheckFlag (char *flagName)
772 {
773   char configToken[MAXBUF];
774 
775   if ((ConfigTokenRetrieve (flagName, configToken)) == TRUE)
776     {
777 #ifdef DEBUG
778       Log ("debug: CheckFlag: found %s string.\n", flagName);
779 #endif
780       return (atoi(configToken));
781     }
782   else
783     {
784 #ifdef DEBUG
785       Log ("debug: CheckFlag: %s option not found. Assuming FALSE.\n", flagName);
786 #endif
787       return (FALSE);
788     }
789 }
790 
791 
792 /* snprintf for NEXTSTEP (others??) */
793 /* I don't know where this code came from and I don't */
794 /* warrant its effectiveness. CHR */
795 
796 #ifdef HAS_NO_SNPRINTF
797 int
snprintf(char * str,size_t n,char const * fmt,...)798 snprintf (char *str, size_t n, char const *fmt,...)
799 {
800   va_list ap;
801   FILE f;
802 
803   if (n > MAXBUF)
804     {
805       n = MAXBUF;
806     }
807   va_start (ap, fmt);
808   f._file = EOF;
809   f._flag = _IOWRT | _IOSTRG;
810   f._base = f._ptr = str;
811   f._bufsiz = f._cnt = n ? n - 1 : 0;
812   (void) vfprintf (&f, fmt, ap);
813   va_end (ap);
814   if (n)
815     {
816       *f._ptr = '\0';
817     }
818   return (f._ptr - str);
819 }
820 #endif
821 
822