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 (¤t_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