• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

contrib/sentinel-logs/H26-Jul-2002-584445

INSTALLH A D26-Oct-20031.2 KiB3124

Makefile.FreeBSDH A D20-Oct-2003260 147

Makefile.LinuxH A D20-Oct-2003255 137

Makefile.SolarisH A D20-Oct-2003287 158

READMEH A D26-Oct-200333.5 KiB825714

README.FreeBSDH A D02-Nov-2002219 54

README.SolarisH A D09-Jul-200214.9 KiB435332

README.Solaris8H A D24-Nov-2002150 32

init.sentinelH A D23-Jul-20021.8 KiB8373

sentinel.cH A D03-May-2022114.7 KiB3,8133,585

sentinel.cf.SAMPLEH A D25-Jul-20026.5 KiB129117

sentinel.cf.SAMPLE2H A D02-Nov-20028.4 KiB153141

README

1Sentinel 1.7b
2-------------
3
4    This milter I wrote mostly for myself as it relieves my sysadmin's
5live considerably. If somebody else wants to use it, go ahead. But just
6keep in mind this program is WITHOUT ANY WARRANTY, use this at your own
7risk. Though this milter is stable enough on sparc Solaris7/8. I've never
8had a chance to try it somewhere else under more or less solid loading.
9It can be compiled in FreeBSD and Linux as well. So if somebody wants to
10try it on any platforms different from Solaris7/8 just let me know about
11results. Although "rbl" feature in this release doesn't work for FreeBSD.
12I'm still looking for reentrant gethostbyname() implementation for FreeBSD.
13If somebody has some ideas, just let me know. Also I didn't have enough
14time to shape it as a package. Probably I'll do it in the future.
15
16
17    I think whoever is going to use it knows how to integrate Milter with
18sendmail. It is documented very well on http://www.sendmail.org
19So this README just explains how to operate Sentinel.
20
21Usage: sentinel -p port [-c config] [-v[1-3]] -d
22  or
23       sentinel -p port [-c config] [-v[1-3]]
24  or
25       sentinel -t [-c config] [-f message] [-v[1-3]]
26
27where
28    -p port - a port description according to libmilter specification
29	      unix:/var/run/smmsp/sentinel.socket for example
30
31    -c config - a configuration file location (/etc/mail/sentinel.cf by default)
32
33    -d - run as a daemon
34
35    -t - test a configuration file and return
36
37    -f message - a message file location for testing your configuration on
38       a real message. This option will simulate all SMFI calls like for a real
39       message with complete debug/log output on STDOUT. Three additional headers
40       are supported for a message in order to simulate mlfi_connect/mlfi_envfrom/mlfi_rcpt
41       calls. Just place Connection/EnvelopeFrom/EnvelopeRcpt headers at the begining
42       of a message in order to simulate "connection" and  "mail from"/"rcpt to" smtp
43       commands like below:
44         ---
45         Connection: 211.239.127.9
46         EnvelopeFrom: foo@bar-list.com
47         EnvelopeRcpt: person1@company.com
48         EnvelopeRcpt: person2@company.com
49         ...
50         EnvelopeRcpt: personn@company.com
51         Received: from relay.bar-list.com (relay.bar-list.com [192.112.214.7])
52	           by mx1.mycompany.com (....)
53         ....
54         ---
55       This option might help you to debug your regular expressions and understand
56       your configuration better ;) Also it'll help you to understand how Sentinel
57       is working.
58
59    -v - verbose or debug level. Global parameter "debug" need to be specified
60         to have appropriate destination for debug records. Syslog is by default.
61
62Use signal USR1 to reload a configuration in fly.
63
64The simple configuration file might look as described below:
65
66sentinel.cf
67############################################################################
68## global chapter ##
69[global]
70tmp:/var/tmp
71log:/var/log/sentinel.log
72debug:/var/log/sentinel.debug
73user:smmsp
74group:smmsp
75max_nofiles:512
76max_soconn:64
77
78## hosts chapter ##
79[hosts]
80smtp1:smtp1:reject:/^64\.32\.18\.3[4-9]/
81smtp2:smtp2:reject:/somewhere\.net/i
82
83## headers chapter ##
84[headers]
85From:	from1:from1:spam:/Vladimir\.Lenin@gorki.com/i
86	from2:from2:spam:/Alexandr\.Trotsky@zimney.com/i
87
88EnvelopeRcpt:	rcpt1:rcpt1:accept:/autoparser@mycompany\.com/i
89
90EnvelopeFrom:	efrom1:efrom1:discard:/somebody@tryToSpamUs\.com/i
91
92To:	to1:to1,rcvd1:spam:/undisclosed\.recipients@mycompany\.com/i
93	to2:to2,rcvd1:spam:/user@mycompany\.com/i
94
95Received:	rcvd1:rcvd1:null:/by[ ]+mx0[1-9]+\.mycompany\.com/i
96		rcvd2:rcvd2:spam:/\.nas[0-9]+\.dialup.somewhere1\.in\.the\.inet\.net/i
97		rcvd3:rcvd3:spam:/\.nas[0-9]+\.dialup.somewhere2\.in\.the\.inet\.net/i
98
99Subject:	subj1:subj1:spam:/^adv:|save money|lose weight|save up to/i
100		subj2:subj2:spam:/adult|pussy|pussies|sex/i
101
102## attachments chapter ##
103[attachments]
104## reject all unsafe attachments from outside, some of them from inside as well
105## all attachments below are according to microsoft
106## http://support.microsoft.com/support/kb/articles/Q262/6/17.ASP
107att01:att01,rcvd1:virus:/\.ade$/i
108att02:att02,rcvd1:virus:/\.adp$/i
109att03:att03,rcvd1:virus:/\.bas$/i
110att04:att04,rcvd1:virus:/\.bat$/i
111att05:att05,rcvd1:virus:/\.chm$/i
112att06:att06,rcvd1:virus:/\.cmd$/i
113att07:att07,rcvd1:virus:/\.com$/i
114att08:att08,rcvd1:virus:/\.cpl$/i
115att09:att09,rcvd1:virus:/\.crt$/i
116att10:att10,rcvd1:virus:/\.exe$/i
117att11:att11,rcvd1:virus:/\.hlp$/i
118att12:att12,rcvd1:virus:/\.hta$/i
119att13:att13,rcvd1:virus:/\.inf$/i
120att14:att14,rcvd1:virus:/\.ins$/i
121att15:att15,rcvd1:virus:/\.isp$/i
122att16:att16,rcvd1:virus:/\.js$/i
123att17:att17,rcvd1:virus:/\.jse$/i
124att18:att18,rcvd1:virus:/\.lnk$/i
125att19:att19,rcvd1:virus:/\.mdb$/i
126att20:att20,rcvd1:virus:/\.mde$/i
127att21:att21,rcvd1:virus:/\.msc$/i
128att22:att22,rcvd1:virus:/\.msi$/i
129att23:att23,rcvd1:virus:/\.msp$/i
130att24:att24,rcvd1:virus:/\.mst$/i
131att25:att25,rcvd1:virus:/\.pcd$/i
132att26:att26:virus:/\.pif$/i
133att27:att27,rcvd1:virus:/\.reg$/i
134att28:att28:virus:/\.scr$/i
135att29:att29,rcvd1:virus:/\.sct$/i
136att30:att30,rcvd1:virus:/\.shs$/i
137att31:att31,rcvd1:virus:/\.shb$/i
138att32:att32,rcvd1:virus:/\.url$/i
139att33:att33:virus:/\.vb$/i
140att34:att34:virus:/\.vbe$/i
141att35:att35:virus:/\.vbs$/i
142att36:att36,rcvd1:virus:/\.wsc$/i
143att37:att37,rcvd1:virus:/\.wsf$/i
144att38:att38,rcvd1:virus:/\.wsh$/i
145
146## mime types chapter ##
147[mime types]
148mime1:mime1:virus:/^application/x-javascript$/i
149
150## body chapter ##
151[body]
152body1:body2:offense:/fuck|shit/i
153
154## action chapter ##
155[actions]
156## all actions are here ##
157spam:reject:The message was classified as SPAM.
158reject:reject:This host is blacklisted in our company
159virus:reject:The attachment of the message was classified as unsafe.
160offense:reject:The content of the message consists an offensive words.
161discard:discard
162accept:accept
163null:null
164
165####################################################################
166
167The format of a configuration file is next:
168
169[chapter 1]
170statement 1
171statement 2
172.
173.
174.
175statement n
176
177[chapter 2]
178statement 1
179statement 2
180.
181.
182.
183statement n
184.
185.
186.
187[chapter n]
188statement 1
189statement 2
190.
191.
192.
193statement n
194
195"statement n" might be either parameter/event/action statement for a particular chapter
196or directive "INCLUDE". Directive "INCLUDE" has next syntax:
197
198INCLUDE full_path_to_included_file
199
200For example:
201
202INCLUDE /etc/mail/sentinel/attachments.cf
203
204All "INCLUDE" files just continue a configuration right from "INCLUDE" point.
205Nested "INCLUDE"'s, when included has also "INCLUDE" directive, are allowed.
206
207Below are next chapter names that available in current version:
208
209[global]
210[hosts]
211[headers]
212[attachments]
213[mime types]
214[body]
215[actions]
216
217All chapters but "global" and "actions" have next format:
218
219event:events:actions:regex
220
221where:
222  - event - an event name that will be registered for a message in case
223            a regular expression is matched (context dependable).
224  - events - comma separated list of all events that must be registered
225             (or must not in case "negative" event) for a message in order
226	     to process "actions". Symbol "!" is a sign of "negative event".
227
228          Sample:
229	     --
230             addr2:addr2,!addr1:ordb(rejectordb):/^(\d+)\.(\d+)\.(\d+)\.(\d+)/
231	     --
232	     that means "run an action ordb(rejectordb) only if event addr2
233	     is matched and event addr1 isn't matched". In other words:
234             --
235             if (addr2 == true && addr1 == false)
236             then
237                 run ordb(rejectordb)
238             endif
239             --
240             Multiple negative events are allowed in a list.
241
242        Sample:
243             --
244             addr2:addr2,!addr1,!addr3:ordb(rejectordb):/^(\d+)\.(\d+)\.(\d+)\.(\d+)/
245             --
246	     that means:
247             if (addr2 == true && addr1 == false && addr3 == false)
248             then
249                 run ordb(rejectordb)
250             endif
251             --
252  - actions - comma separated list of all action that will be processed
253              in case all "events" are registered and all "negative events"
254	      are not registered.
255  - regex - regular expression for current event. This version supports
256            extended regular expressions. Two options are available for regex:
257	      i - case insensitive
258	      n - negative, that means NOMATCH must return MATCH result
259	      s - check against html content, which has stripped html tags.
260	      d - decode html numeric entities, like "&#nnn;"
261	    An option "s" may be helpful against such tricks in html contens as
262	    "via<!--he-he-->gra". If you defined your regex like "/viagra|valium|xanax/is",
263	    then it'll be running against stripped html content (html content without
264	    html tags). It means all html tags will be taken out from html content
265	    before to run appropriate regular expression. Of course, it's working for
266	    "text/html" only. This optiion will be ignored in case of "text/plain" content".
267	    An option "d" is also helpful in case spammers try to hide real content in sequences
268	    "&#nnn;". For example, if you defined your regex like "/viagra|valium|xanax/d",
269	    then it'll be running against decoded html content (html content without numeric entities).
270	    Therefore, the sequences "&#nnn;" will be decoded before to run either regex or body ACL's.
271	    You can combine this option with option "s". Of course, it's working for "text/html" only.
272	    This option will be ignored in case of "text/plain" content. Below is an example how to run
273	    ACL against HTML content with stripped tags and decoded numeric entities:
274            --
275            [body]
276            body1:body1:tabooBody:/.*/ds
277            ...
278            [actions]
279            tabooBody:acl:/etc/mail/milter/tabooBody.lst
280            --
281            where tabooBody.lst is something like below:
282            --
283            viagra
284            Online Pharmacy
285            xanox
286            phentermine
287            prozac
288            valium
289            Vicodin
290            ...
291            --
292	    An expression must be delimited by // if you want to use these
293	    options. There are some perl-like extentions that are actualy
294	    "Alpha Regex Metasymbols":
295		\w - match any "word" character (alphanumerics plus "_");
296		\d - match any digit character;
297		\s - match any whitespace character;
298		\n - match the newline character;
299		\r - match the return character;
300		\t - match the tab character.
301	    I don't see any necessity to implement "\W", "\D" and "\S"
302	    metasymbols as well. They might be easy defined in your regular
303	    expressions as "[^\w]", "[^\d]" and "[^\s]" accordingly.
304
305	Sample:
306	    subj1:rblpfx,rcvd1,ordb:/^RBL:/in
307
308	    "[global]" chapter.
309
310The syntax for a chapter "[global]" is next:
311<parameter name>:<parameter value>
312Currently next parameters can be defined here:
313
314tmp - where is a temporary files location. Very important if you are going
315      to use "program" action. In this case there should be enough space
316      for temporary files in order to accommodate decoded attachments.
317
318log - where is a logfile location in order to log all actions by sentinel.
319      Must have write permissions for an user "user" (see below). You can either
320      specify "syslog" there or just omit this parameter if you want all log
321      info was recorded by syslog. Syslog is by default. Look for "mail.info"
322      destination in your syslog.conf
323
324debug - where is a debugfile location in order to record all debug info there.
325      Must have write permissions for an user "user" (see below). You can either
326      specify "syslog" there or just omit this parameter if you want all debug
327      info was recorded by syslog. Syslog is by default. Look for "mail.debug"
328      destination in your syslog.conf
329
330user - milter will be running under this account perm.
331
332group - milter will be running under this group perm.
333
334max_nofiles - max number of file descriptors. Important for heavy loaded systems.
335              Can be used as the fix for next possible problems:
336	         - "libthread panic: cannot create new lwp";
337		 - "too many open files".
338
339max_soconn - backlog value for smfi_sebacklog(). It's using as backlog parameter
340             for listen(). Don't use it if you don't understand what you are
341	     doing. The default value in libmilter is 20 for most of systems.
342	     Could be useful for heavy loaded systems.
343
344max_parse_txt - this parameter tells sentinel not to process "body" rules for
345                "text/plain" or "text/html" message part if content length for
346		this part is greater than "max_parse_txt". This parameter must
347		be specified in bytes. The deafult value is 1M.
348
349
350	    "[actions]" chapter.
351
352Actually all actions that are described here can be available for events in
353chapters "[hosts]", "[headers]", "[attachments]", "[mime types]", "[body]".
354The syntax for chapter "[actions]" is next:
355
356<action name>:<function>:<an argument for a finction>
357
358where
359  <action name> - any name you want
360
361  <function> - one of the next functions that available in the current release:
362
363    null - null operator, that means do nothing but just register an event.
364          Sample: null:null
365
366    accept - accept a message without any further checking. Don't need any arguments.
367             This type is a highest priority type. If you defined some rules with
368	     "accept" type, a message will be accepted, no matter what kind of events
369	     were triggered before.
370          Sample: accept:accept
371
372    reject - reject a message. An argument will be passed to 554 4.7.1 DSN diagnostic.
373             An argument will be processed as a pattern relatively to a context from
374	     where this action was called (headers, hosts, body reg. expressions).
375	     You can use next subexpressions:
376	         ${0} - whole string that was submitted for an expression
377		        (for example "subject" header)
378		 ${1} .. ${nn} - subexpressions according to parenthesized
379				 subexpressions (delimited by () regular expressions)
380		                 in appropriate regular expression.
381		 $file - attached file name in context of "[attachments]" chapter.
382          Samples:
383	        spam:reject:The message was classified as SPAM.
384                rejectordb:reject:Rejected according to ORDB Realtime Blackhole List for IP address ${1}.${2}.${3}.${4} (see http://ordb.org/lookup/?host=${1}.${2}.${3}.${4}). Please contact postmaster@netapp.com in case any business related issues.
385		virus:reject:The attachment "$file" of the message was classified as unsafe.
386
387    discard - just discard a message without any notifications.
388              Don't need any arguments.
389	  Sample:
390	        discard:discard
391
392    addrcpt - add an recipient for a message. A recipient must be specified
393              as an argument.
394	  Sample:
395	        addrobot:addrcpt:robot@mycompany.com
396
397    delrcpt - remove an recipient. Don't need any argument. Make sense only
398              in "headers" chapter and only for "EnvelopeRcpt" header. Will
399	      remove current recipient for an event in "EnvelopeRcpt".
400	  Sample:
401	        delrcpt:delrcpt
402
403    chgrcpt - change an recipient. A new recipient must be specified as argument.
404              Make sense only in "headers" chapter and only for "EnvelopeRcpt"
405	      header. Will change a current recipient for an event in "EnvelopeRcpt".
406	  Sample:
407	        chg_domain:chgrcpt:${1}@newdomain.com
408
409    addhdr - add a header for a message. A header name and value must be specified
410             as arguments
411	  Sample:
412	        xfilter:addhdr:X-Filter: this message was checked by Sentinel
413
414    delhdr - remove a header for a message. Don't need any arguments. Will remove
415             a current header for a first matched regular expression in an event
416	     list for a header that defined in "headers" chapter.
417	  Sample:
418	        delhdr:delhdr
419
420    chghdr - change a header. A new value for a header must be specified as an argument.
421             Make sense only in "headers" chapter. Will change a current header for a
422	     first matched regular expression in an event list for a header that defined
423	     in "headers" chapter.
424	     Sample:
425	        rblpfx:chghdr:RBL: ${0}
426
427    quarantine - save message in quarantine directory. Quarantine directory must be specified
428                 as an argument. A message will be saved as a file with name event_name.queue_id,
429		 where event_name is an event from where this action was called, and queue_id
430		 is sendmail queue ID for a message. Default action after a message will be
431		 saved is just to discard if an argument is not specified (see arguments for
432		 actions program/rbl/quarantine below). You can use formatted string as a
433		 directory specification. Only last subdirectory in the path will be created
434		 according to your formatted string. Next date/time formatted symbols can be
435		 used for last subdirectory in your directory path specification:
436                     %a - locale's abbreviated weekday name;
437                     %A - lLocale's full weekday name;
438                     %b - Locale's abbreviated month name;
439                     %B - Locale's full month name;
440                     %c - Locale's appropriate date and time representation;
441                     %d - day of month [1,31]; single digits are preceded by 0;
442                     %D - date as %m/%d/%y;
443                     %e - day of month [1,31]; single digits are preceded by a space;
444                     %g - week-based year within century [00,99];
445                     %G - week-based year, including the century [0000,9999];
446                     %h - locale's abbreviated month name;
447                     %H - hour (24-hour clock) [0,23]; single  digits  are  preceded by 0;
448                     %I - hour (12-hour clock) [1,12]; single  digits  are  preceded by 0;
449                     %j - day number of year [1,366]; single digits are preceded by 0;
450                     %k - hour (24-hour clock) [0,23]; single  digits  are  preceded by a blank;
451                     %l - hour (12-hour clock) [1,12]; single  digits  are  preceded by a blank;
452                     %m - month number [1,12]; single digits are preceded by 0;
453                     %M - minute  [00,59]; leading 0 is permitted but not required;
454                     %p - locale's equivalent of either a.m. or p.m.;
455                     %r - appropriate time representation in 12-hour clock format with %p;
456                     %R - time as %H:%M;
457                     %S - seconds [00,61];
458                     %T - time as %H:%M:%S;
459                     %u - weekday as a decimal number [1,7], with 1 representing Monday;
460                     %U - week number of year as a decimal number [00,53], with Sunday as the first day of week 1;
461                     %w - weekday as a decimal number [0,6], with 0 representing Sunday;
462                     %W - week number of year as a decimal number [00,53], with Monday as the first day of week 1;
463                     %x - locale's appropriate date representation;
464                     %X - locale's appropriate time representation;
465                     %y - year within century [00,99];
466                     %Y - year, including the century (for example 1993);
467	  Samples:
468	         qrtDiscard:quarantine:/var/spool/quarantine
469		     or
470	         qrtDiscard:quarantine:/var/spool/quarantine/%Y%m%d
471
472		 qrtReject:quarantine(spam):/var/log/quarantine
473		     or
474		 qrtReject:quarantine(spam):/var/log/quarantine/%Y%m%d
475
476    program - call an external program. This action make sense only in "attachments"
477              chapter. An argument is a program name with all required parameters.
478	      An argument must be specified as a pattern with "$file" subexpression.
479	      This action will call an "argument" if it's specified or just reject
480	      action if it isn't. An argument or reject action will be called only
481	      in case non zero return code.
482	Samples:
483	         vscan:program:/usr/local/sbin/vscan -b -f $file
484	         vscan:program(virus):/usr/local/sbin/vscan -b -f $file
485
486		    where "virus" action was defined as:
487
488		 virus:reject:The attachment "$file" of the message was classified as unsafe.
489
490    strip - strip an attached file. An argument is a diagnostic text message that
491            will be instead of attached file. A subexpression "$file" can be specified
492	    in argument string.
493	Sample:
494	    stripatt:strip:The attached file "$file" was stripped.
495
496    rbl - Remote Blackhole List. DNS lookup in RBL database will be done according
497          to an argument. Actually this is an argument for gethostbyname call.
498	  Next subexpressions may be specified: ${0}, ${1} .. ${nn}. A message
499	  will be just rejected in case defined name will be found in RBL.
500	  Of course this is just default behavior when no arguments is specified
501	  for "rbl" action (see arguments for actions "progarm,rbl,resolv,quarantine" below).
502	Samples:
503	     ordb:rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
504	     ordb(rejectordb):rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
505
506		where "rejectordb" might be defined as:
507
508	     rejectordb:reject:Rejected according to ORDB Realtime Blackhole List for IP address ${1}.${2}.${3}.${4} (see http://ordb.org/lookup/?host=${1}.${2}.${3}.${4}). Please contact postmaster@mycompany.com in case any business related issues.
509
510    resolv - try to resolve name and compare results with second parameter (if defined).
511             This action can accept 1 or 2 arguments. If only one argument defined, "resolv"
512	     will return "reject" by default or run an action in parentheses in case specified
513	     name is not resolved. If second argument is defined, which expects to be an IP
514	     address, "resolv" will try to compare it with each with each address of resolved
515	     name. It will return "reject" by default or run an action in parentheses if there
516	     is no specified IP in results of resolving. First and second arguments must be
517	     separated by comma in an action definition (see an example below).
518	Samples:
519             [headers]
520	       Received:
521                  rcvd2:rcvd2:helo(quarantine):/^from\s+([^ \t]+)\s+\((unknown\s+)?\[(\d+\.\d+\.\d+\.\d+)\]\)\s+by\s+mx[1-3]\.mycompany\.com/i
522
523             [actions]
524               helo(quarantine):resolv:${1}, ${3}
525    acl - Access Control List allows to define external (outside of sentinel.cf) lists,
526	  which can be utilized as whitelists, blacklists, banned URL's lists, and etc.
527	  These external lists are regular text files, which consist one entry per string.
528	  Entries may be domains, addresses, url's, and etc. It depends of context from which
529	  particular "acl" will be called. For example, if you defined an "acl" to be called
530	  from header's context, then such "acl" must refer to a list of domains/addresses.
531	  In case you want to define an external list as banned URL's list, you must call
532	  appropriate "acl" from "body" context ("body" chapter). Just keep in mind, you
533	  can't use regular expression inside such lists. Sentinel will check all entries
534	  in such lists as case insensitive string occurrences in appropriate context (headers,
535	  text or html message body). It means incomplete domain name like "dailypromo.com"
536	  will trigger an event for "From" header like "<offers@mail.dailypromo.com>".
537	Samples:
538	  Lets say you defined blacklist in /etc/mail/milter/blacklist.lst, which consists:
539	  --
540	  apslist526.com
541	  backpackgirl
542	  cupidsclock
543	  cdsteals.com
544	  DailyDealDepot.com
545	  ebanat.com
546	  hotbot.com
547	  vmadmin.com
548	  VIRTUAL0.NET
549	  SMTP0.NET
550	  IREAYE.NET
551	  sepis4556@yahoo.com
552	  --
553	  Then you need to define "acl" action for this list like below:
554	  --
555          [actions]
556	  accept:accept
557	  quarantine:quarantine:/var/spool/quarantine/sentinel/%Y%m%d
558          blacklist(quarantine):acl:/etc/mail/milter/blacklist.lst
559          whitelist(accept):acl:/etc/mail/milter/whitelist.lst
560	  --
561	  which can be utilized in "headers" chapter, like below:
562	  --
563	  [headers]
564	  From: from1:from1:blacklist(quarantine):/.*/
565	  ...
566	  ...
567	  EnvelopeFrom: efrom1:efrom1:blacklist(quarantine):/.*/
568	                efrom2:efrom2:whitelist(accept):/.*/
569	  --
570	  In case of "whitelist" an example above shows "whitelist(accept)"
571	  action for /etc/mail/milter/whitelist.lst whitelist.
572          Or lets say you defined /etc/mail/milter/bannedurl.lst as below:
573	  --
574	  beefupyourpenis
575	  cool-host
576	  quickhost.bz
577	  verycoolcars
578	  secretsexads
579	  freelivewebcamteens
580	  --
581	  In this case you can utilize this list like in example below:
582	  --
583	  [body]
584	  body1:body1:bannedurl(quarantine):/.*/
585	  ...
586	  ...
587          [actions]
588	  quarantine:quarantine:/var/spool/quarantine/sentinel/%Y%m%d
589          bannedurl(quarantine):acl:/etc/mail/milter/bannedurl.lst
590	  --
591	  Just keep in mind, if you want to utilize regular expressions, then you have to use
592	  them in sentinel.cf file. "Acl"'s won't be much helpful in this case.
593          Access control (ACL) can accept one extra parameter in action definition.
594          Typically it could back reference to subexpression in regular expression of
595          event calling this ACL. Like an example below:
596          --
597          [headers]
598          Received: rcvd1:rcvd1:blackRelays:/^from.*\((.+)\s+\[.*\]( \(may be forged\))?\)\s+by\s+mx[1-9]\.mycompany\.com/i
599          ...
600          [actions]
601          blackRelays:acl:${1}:/etc/mail/milter/blackRelays.lst
602          --
603          If you omit first parameter ("${1}" for example above), ACL will apply to entire header.
604          Like below:
605          --
606          [actions]
607          blackRelays:acl:/etc/mail/milter/blackRelays.lst
608          --
609          Please note, it does not work for body rules. Will implement it in next release.
610          However, "url" parameter can be specified in "body" rules and will be ignored in
611	  a header context. This parameter tells sentinel to run ACL rules against URL strings
612	  only in a message body. All URL strings will be decoded before to run ACL's.
613	  For example:
614          --
615          [body]
616          body1:body1:bannedURLS:/.*/
617          ...
618          [actions]
619          bannedURLs:acl:url:/etc/mail/milter/bannedURLS.lst
620          --
621
622Five next actions "program", "rbl", "acl", "resolv", and "quarantine" can be specified with
623arguments that delimited in parenthesis. For "program" action an argument action will be called
624every time when a program return non zero code. For "rbl" in case a name will be found in
625a Remote Blackhole List. ACL's have "null" action by default. It means if you need something else
626for your "acl", you have to specify it ias parameter, like "whitelist(accept)". For "resolv"
627if a name cannot be resolved or results of resolving are different from a second specified argument
628(IP address). For "quarantine" this is just an action that must be called instead of default "discard"
629after a message will be saved in quarantine directory. Only one argument is allowed. But an argument
630action can be called with an argument as well.
631Samples:
632
633      rcvd1:rcvd1,rblpfx:ordb(quarantine(spam)):/^from .*\(.*\[([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)\]\).*by mx[1-3]+\.mycompany\.com/i
634      rcvd2:rcvd2:helo(quarantine):/^from\s+([^ \t]+)\s+\((unknown\s+)?\[(\d+\.\d+\.\d+\.\d+)\]\)\s+by\s+mx[1-3]+\.mycompany\.com/i
635      att10:att10,rcvd1:vscan(quarantine(virus)):/\.exe$/i
636
637  where actions:
638
639      ordb(quarantine(spam)),quarantine(spam),helo(quarantine),spam,vscan(quarantine(virus)),quarantine(virus),virus
640
641  are define below as:
642
643      spam:reject:The message was classified as SPAM.
644      virus:reject:The attachment "$file" of the message was classified as unsafe.
645      quarantine(virus):quarantine:/var/spool/quarantine
646      quarantine(spam):quarantine:/var/spool/quarantine
647      ordb(quarantine(spam)):rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
648      helo(quarantine):resolv:${1}, ${3}
649      vscan(quarantine(virus)):program:/usr/local/sbin/vscan -b -f $file
650
651Four actions rbl, acl, resolv, and program will trigger events with the same names in case
652of non zero return code for "program", positive results for "rbl" and "acl", and negative
653result for "resolv". For the sample above the event names will be "ordb" and "vscan" - action
654name without arguments. You can use these triggered events in any another event lists.
655Sample:
656
657      subj3:subj3,ordb:rblpfx:/^RBL:/in
658
659   that means if current subject is not prefixed and ordb action has positive
660   result, then add "RBL:" prefix to a subject header by action "rblpfx". For
661   this sample "rblpfx" action might looks as:
662
663      rblpfx:chghdr:RBL: ${0}
664
665Very simple configuration below is a real sample how "negative events"
666could be used to distinguish internal "outbound" and external "inbound"
667smtp connections. It's useless resource consumption to do rbl lookup for
668"private network" hosts.
669##############################################################################
670[global]
671tmp:/var/tmp
672log:/var/log/sentinel.log
673user:smmsp
674group:smmsp
675max_nofiles:512
676max_soconn:30
677max_parse_txt:524288
678
679[hosts]
680haddr1:haddr1:null:/^(192\.168\.|172\.16\.|10\.)/
681# It does not make any sense to do ordb lookup for internal hosts
682haddr2:haddr2,!haddr1:ordb(rejectordb):/^(\d+)\.(\d+)\.(\d+)\.(\d+)/
683
684[actions]
685ordb(rejectordb):rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
686rejectordb:reject:Rejected according to ORDB Realtime Blackhole List for IP address ${1}.${2}.${3}.${4} (see http://ordb.org/lookup/?host=${1}.${2}.${3}.${4}).
687null:null
688
689Below is more complex sample.
690##############################################################################
691[global]
692tmp:/var/tmp
693log:/var/log/sentinel.log
694user:smmsp
695group:smmsp
696max_nofiles:512
697max_soconn:30
698max_parse_txt:524288
699
700[headers]
701X-Mailer:	xmlr1:xmlr1,rcvd1:spam:/WorldMerge|Extractor Pro|Floodgate Pro|Emailer Platinum.*Internet Marketing|BritecastMailer/i
702
703#
704# "subj3" event is defined with "negative" option in regex in order to
705# eliminate duplicate prefixing.
706# The rule for "subj3" is about "Do a subject prefixing by rblpfx action in
707# case 'ordb' action returned positive result and a subject wasn't prefixed
708# before".
709#
710Subject:        subj1:subj1,rcvd1:spam:/^adv:|save money|lose weight|save up to/i
711		subj2:subj2,rcvd1:spam:/adult|pussy|girl| ass | fuck | sex |fucking/i
712		subj3:subj3,ordb:rblpfx:/^RBL:/in
713
714#
715# The rules in aol.com, msn.com, and juno.com don't allow to use
716# names that have first numeric symbols
717#
718From:	from1:from1:spam:/^[0-9]+@(aol|msn|juno)\.com/i
719	from2:from2:spam:/girls\.net|jobseekernews\.com|jobseekernews\.net|jobfly\.com|supportgate\.com/i
720
721To:	to1:to1,rcvd1:spam:/undisclosed\.recipients|friend@|@public\.com/i
722
723#
724# Do RBL checking and add an extra "X-RBL" header for all blackholed sources only
725# if a subject header was not prefixed. This case is for Milter that's behind of
726# firewall. Otherwise we could use "hosts" chapter in order to catch an IP.
727#
728Received:	rcvd1:rcvd1,subj3:ordb(addhdrordb):/^from .*\(.*\[([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)\]\).*by mx[1-3]+\.mycompany\.com/i
729		rcvd2:rcvd2:spam:/\.nas[0-9]+\.dialup\..*\.someISP\.net/i
730
731#
732# Next recipient's addresses are "pass through" addresses, no matter from where
733# they are and which message content
734#
735EnvelopeRcpt:	rcpt1:rcpt1:accept:/autoparser@mycompany\.com|postmaster@mycompany\.com/i
736
737[attachments]
738#
739# reject all unsafe attachments from outside, some of them from inside as well.
740# All attachments below are according to the next article for microsoft:
741# http://support.microsoft.com/support/kb/articles/Q262/6/17.ASP
742# "rcvd1" event in this case allow to distinguish inbound external traffic
743# (see "rcvd1" event above)
744#
745att01:att01,rcvd1:virus:/\.ade$/i
746att02:att02,rcvd1:virus:/\.adp$/i
747att03:att03,rcvd1:virus:/\.bas$/i
748att04:att04,rcvd1:virus:/\.bat$/i
749att05:att05,rcvd1:virus:/\.chm$/i
750att06:att06,rcvd1:virus:/\.cmd$/i
751att07:att07,rcvd1:virus:/\.com$/i
752att08:att08,rcvd1:virus:/\.cpl$/i
753att09:att09,rcvd1:virus:/\.crt$/i
754att10:att10,rcvd1:virus:/\.exe$/i
755att11:att11,rcvd1:virus:/\.hlp$/i
756att12:att12,rcvd1:virus:/\.hta$/i
757att13:att13,rcvd1:virus:/\.inf$/i
758att14:att14,rcvd1:virus:/\.ins$/i
759att15:att15,rcvd1:virus:/\.isp$/i
760att16:att16,rcvd1:virus:/\.js$/i
761att17:att17,rcvd1:virus:/\.jse$/i
762att18:att18,rcvd1:virus:/\.lnk$/i
763att19:att19,rcvd1:virus:/\.mdb$/i
764att20:att20,rcvd1:virus:/\.mde$/i
765att21:att21,rcvd1:virus:/\.msc$/i
766att22:att22,rcvd1:virus:/\.msi$/i
767att23:att23,rcvd1:virus:/\.msp$/i
768att24:att24,rcvd1:virus:/\.mst$/i
769att25:att25,rcvd1:virus:/\.pcd$/i
770att26:att26:virus:/\.pif$/i
771att27:att27,rcvd1:virus:/\.reg$/i
772att28:att28:virus:/\.scr$/i
773att29:att29,rcvd1:virus:/\.sct$/i
774att30:att30,rcvd1:virus:/\.shs$/i
775att31:att31,rcvd1:virus:/\.shb$/i
776att32:att32,rcvd1:virus:/\.url$/i
777att33:att33:virus:/\.vb$/i
778att34:att34:virus:/\.vbe$/i
779att35:att35:virus:/\.vbs$/i
780att36:att36,rcvd1:virus:/\.wsc$/i
781att37:att37,rcvd1:virus:/\.wsf$/i
782att38:att38,rcvd1:virus:/\.wsh$/i
783att39:att39:confd:/SunPricing2002\.xls/i
784
785[mime types]
786#
787# Strip all javascript attachments for a message
788#
789mime1:mime1:stripatt:/^application/x-javascript$/i
790
791[actions]
792#
793# All actions are defined here
794#
795spam:reject:The message was classified as SPAM.
796virus:reject:The attachment "$file" of the message was classified as unsafe.
797stripatt:strip:Unsafe attachment was stripped.
798ordb(rejectordb):rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
799ordb(addhdrordb):rbl:${4}.${3}.${2}.${1}.relays.ordb.org.
800rejectordb:reject:Rejected according to ORDB Realtime Blackhole List for IP address ${1}.${2}.${3}.${4} (see http://ordb.org/lookup/?host=${1}.${2}.${3}.${4}). Please contact postmaster@netapp.com in case any business related issues.
801addhdrordb:addhdr:X-RBL: dubious source ${1}.${2}.${3}.${4} according to ORDB Realtime Blackhole List (see http://ordb.org/lookup/?host=${1}.${2}.${3}.${4})
802rblpfx:chghdr:RBL: ${0}
803discard:discard
804accept:accept
805null:null
806
807###############################################################################
808
809What's in my TODO:
810
811   1. more flexible event's list with or/and logic like below:
812
813          event1 | (event2 & event3)
814
815   2. ms-tnef support (don't know if I realy need it)
816
817   3. different character set support for headers/body mime decoding / compare
818
819   4. bugs fixing (if somebody will report)
820
821If you have any questions or comments, just send them to smfilter2002@yahoo.com.
822
823----
824Igor
825

README.FreeBSD

1Unfortunately you cannot use "rbl" feature on FreeBSD platform.
2I didn't find reentrant gethostbyname() implementation for FreeBSD.
3If somebody find out right solution, please let me know and I implement
4it right away.
5

README.Solaris

1Jean-Michel kindly provided this README. Thanks Jean-Michel!
2--------------------------------------------------------------------------
3Because I have had lots of work to master Sentinel in my environment
4(Solaris 2.6: no problem, Solaris 2.5.1: many problems, CPU overload),
5I send you what I have done. Perhaps it will help other people.
6
7Jean-Michel.
8--------------------------------------------------------------------------
9
10I. INTRODUCTION TO SENTINEL:
11   ========================
12
13    Sentinel is a sendmail milter API implementation with very interesting
14    features:
15    . written in C / Sendmail Milter API (fast and multithreaded)
16    . regular expressions (regexp) support
17    . host (IP address/block) and domain filtering
18    . enveloppe check
19    . headers check: "From:", "To:", "Received:", "Subject:", ...
20    . body / attachments / mime types check
21    . anti-virus / quarantine support
22    . logs support
23
24    More information can be found at:
25
26        http://smfilter.sourceforge.net/
27        http://smfilter.sourceforge.net/README.html
28
29II. INSTALLATION OF SENTINEL:
30    ========================
31
32  II.1. Pre-requisite:
33        -------------
34
35        Sentinel requires Sendmail 8.12.x versions compiled with Milter
36        support. Milter includes and libraries files must also been installed
37        (in `/usr/local' for example):
38        . include/libmilter/mfapi.h
39        . lib/libsm.a
40        . lib/libsmutil.a
41        . libmilter.a
42
43  II.2. Downloading the Sentinel software:
44        ---------------------------------
45
46        It can be doanloaded from: http://sourceforge.net/projects/smfilter/
47        The downloaded file is:    sentinel-1.2.4b.tar.gz
48
49  II.3. Compilation of Sentinel:
50        -----------------------
51
52        # tar zxf sentinel-1.2.4b.tar.gz
53        # cd sentinel-1.2.4b
54        # more README
55        # more INSTALL
56
57        # vi Makefile.Solaris
58
59            CC = gcc
60            CFLAGS = -O -I../sendmail-8.12.4/include
61            LDFLAGS = -s -L../sendmail-8.12.4/obj.SunOS.5.6.sun4/libmilter \
62		    -L../sendmail-8.12.4/obj.SunOS.5.6.sun4/libsmutil \
63                    -L../sendmail-8.12.4/obj.SunOS.5.6.sun4/libsm
64	    LIBS = -lmilter -lsmutil -lsm -lresolv -lnsl -lsocket -lpthread
65
66        # make -f Makefile.Solaris
67
68  II.4. Installation of Sentinel:
69        ------------------------
70
71        # mkdir                 /etc/mail/filter
72        # cp sentinel           /etc/mail/filter
73        # chown bin:bin         /etc/mail/filter/sentinel
74        # chmod 555             /etc/mail/filter/sentinel
75
76        # cp init.sentinel      /etc/init.d/sentinel
77        # chown root:sys        /etc/init.d/sentinel
78        # chmod 744             /etc/init.d/sentinel
79
80        # ln -s ../init.d/sentinel /etc/rc2.d/S87sentinel
81        # ln -s ../init.d/sentinel /etc/rc0.d/K87sentinel
82        # ln -s ../init.d/sentinel /etc/rc1.d/K87sentinel
83        # chgrp -h sys /etc/rc?.d/?87sentinel
84
85        # vi /etc/init.d/sentinel
86
87            SMFILTER=/etc/mail/filter/sentinel
88            CONFIG=/etc/mail/tables/sentinel.cf
89            SOCKET=/var/run/sentinel/sock
90
91            Replace:    [ ... -f $SOCKET ];
92            With   :    [ ... -r $SOCKET ];
93
94        # mkdir                 /var/run/sentinel \
95        # chown nobody:nobody   /var/run/sentinel | ...for socket creation
96        # chmod 750             /var/run/sentinel /
97
98        # cp sentinel.cf.SAMPLE /etc/mail/tables/sentinel.cf
99
100III. CONFIGURATION OF SENTINEL:
101     =========================
102
103 III.1. Configuration of Sendmail 8.12.x:
104        --------------------------------
105
106        The `.mc' configuration file must include the two following lines in
107        the "include" part:
108
109            INPUT_MAIL_FILTER(`sentinel',`S=local:/var/run/sentinel/sock,T=S:2m;R:4m;E:6m')
110            define(`confINPUT_MAIL_FILTERS',`sentinel')
111
112        Where the filter parameters are:
113
114            T=S:1m;R:1m;E:60m
115            ^ ^    ^    ^
116            | |    |    |____ overall timeout
117            | |    |_________ timeout reading reply from the filter
118            | |______________ timeout sending information from MTA to filter
119            |________________ timeouts when talking to the filter
120
121        Note: do not use the 'F=[R|]' option to avoid rejecting connections!!!
122
123 III.2. Configuration of Sentinel:
124        -------------------------
125
126        # vi /etc/mail/tables/sentinel.cf
127
128            [global]
129            tmp:/var/tmp
130            log:/var/log/sentinel/log
131            user:nobody
132            group:nobody
133            max_nofiles:512
134            max_soconn:30
135            ...
136
137------------------------------------------------------------------------------
138            max_nofiles - max number of file descriptors. Important for heavy
139            loaded systems. Can be used as the fix for next possible problems:
140            - "libthread panic: cannot create new lwp";
141            - "too many open files".
142
143            max_soconn - backlog value for smfi_sebacklog(). It's using as
144            backlog parameter for listen(). Don't use it if you don't
145            understand what you are doing. The default value in libmilter is 20
146            for most of systems. Could be useful for heavy loaded systems.
147
148------------------------------------------------------------------------------
149
150        # mkdir                  /var/log/sentinel      \
151        # touch                  /var/log/sentinel/log  |
152        # chown -R nobody:nobody /var/log/sentinel      |...for logs!
153        # chmod 750              /var/log/sentinel      |
154        # chmod 640              /var/log/sentinel/log  /
155
156IV. PLAYING WITH SENTINEL:
157    =====================
158
159  IV.1. Starting Sentinel in debug mode:
160        -------------------------------
161
162        # /etc/mail/filter/sentinel             \
163                -c /etc/mail/tables/sentinel.cf \
164                -p /var/run/sentinel/sock       \
165                -v 9
166
167            mlfi_connection: entered
168            mlfi_envfrom: entered
169            mlfi_envrcpt: entered
170            mlfi_connection: entered
171            mlfi_header: entered
172            ...
173
174  IV.2. Checking logs:
175        -------------
176
177        # tail -f /var/log/sentinel/log
178        05/29/2002 10:44:41 sentinel[g4TAhtWg008488]:
179                rejected: Event subj2, From <root@aol.com>
180
181        # grep subj2 /etc/mail/tables/sentinel.cf
182        subj2:subj2:spam:/adult|pussy|pussies| sex|viagra|discount/i
183
184        # grep g4TAhtWg008488 /var/log/syslog
185        May 29 10:44:41 mx3 sendmail[8488]: g4TAhtWg008488:
186            from=<root@aol.com>, size=84, class=0, nrcpts=1,
187	    msgid=<200205291044.g4TAhtWg008488@mx3.sita.int>,
188	    proto=ESMTP, daemon=MTA,relay=ANice-101-1-4-14.abo.wanadoo.fr [193.253.186.14]
189        May 29 10:44:41 mx3 sendmail[8488]: g4TAhtWg008488:
190            Milter: data, reject=554 5.7.1 The message was categorized as SPAM.
191        May 29 10:44:41 mx3 sendmail[8488]: g4TAhtWg008488:
192    	    to=<jean-michel.suzanne@sita.int>, delay=00:00:26,
193	    pri=30073, stat=The message was categorized as SPAM.
194
195  IV.3. Starting Sentinel in deamon mode:
196        --------------------------------
197
198        # /etc/mail/filter/sentinel             \
199                -c /etc/mail/tables/sentinel.cf \
200                -p /var/run/sentinel/sock       \
201                -d
202
203        --or--
204
205        # /etc/init.d/sentinel start
206
207  IV.4. Forcing Sentinel to relaod its configuration file:
208        -------------------------------------------------
209
210        Sentinel does not need to be restarted is its configuration file has
211        changed. Use signal USR1 to reload a configuration in fly:
212
213            # kill -USR1
214
215V. MISC: COMPILATION UNDER SOLARIS 2.5.1:
216   =====================================
217
218   V.1. Solaris 2.5.1 doesn't support SNPRINTF(3S):
219        ------------------------------------------
220
221        With Solaris 2.5.1, the `sentinel.c' source code must be modified to
222        use the Sendmail SM_SNPRINTF function in `/obj*/libsm/libsm.a':
223
224        # cd sentinel-1.2.4b
225        # vi sentinel.c
226
227            Replace:    #include <arpa/inet.h>
228                        #include <netinet/in.h>
229
230            With:       #include <sys/types.h>
231                        #include <sys/socket.h>
232                        #include <netinet/in.h>
233                        #include <arpa/inet.h>
234
235            Replace:    snprintf        vsnprintf
236
237            With   :    sm_snprintf     sm_vsnprintf
238
239        # make -f Makefile.Solaris
240
241        Then, install it !!!
242
243   V.2. The REGEX(5) library has changed between Solaris<=2.5 and Solaris>=2.6:
244
245----------------------------------------------------------------------
246
247        The REGEX(5) library under Solaris <= 2.5.1 has low capabilities in
248        comparison with REGEX(5) under Solaris >= 2.6. For example, the
249        following RE:
250
251            /^\<{0,1}\$.*@/i    ...match '<$...@' and '$...@'
252
253        ...works fine under Solaris >= 2.6
254        ...doesn't works under Solaris <= 2.5.1
255
256        Then, to have full REGEX supported under Solaris 2.5.1, I used the
257        "Henry Spencer's regular expression library" (http://arglist.com/regex/)
258
259            # wget http://arglist.com/regex/rxspencer-alpha3.8.g2.tar.gz
260            # tar zxf rxspencer-alpha3.8.g2.tar.gz
261            # CC=gcc CFLAGS=-O2 ./configure
262            # make
263            # make check
264            # make install
265                |___ /usr/local/lib/
266                |       |___ librxspencer.a
267                |       |___ librxspencer.la
268                |       |___ librxspencer.so*
269                |___ /usr/local/include/
270                |       |___ rxspencer/regex.h
271                |___ /usr/local/man/
272                        |___ man3/rxspencer.3
273                        |___ man7/rxspencer.7
274
275        Once the librarie compiles, the Sentinel source code and Makefile must
276        be updated:
277
278            # vi sentinel.c
279
280                Replace:        #include
281                With   :        #include
282
283            # vi Makefile.Solaris
284
285                CFLAGS = -O -I../sendmail-8.12.4/include -I/usr/local/include
286
287                LDFLAGS = -s \
288		    -L../sendmail-8.12.4/obj.SunOS.5.5.1.sun4/libmilter \
289		    -L../sendmail-8.12.4/obj.SunOS.5.5.1.sun4/libsmutil \
290                    -L../sendmail-8.12.4/obj.SunOS.5.5.1.sun4/libsm \
291                LIBS =  -lmilter -lsmutil -lsm /usr/local/lib/librxspencer.a \
292                        -lresolv -lnsl -lsocket -lpthread
293
294            # make -f Makefile.Solaris
295
296VI. MY OWN SENTINEL STARTUP SCRIPT:
297    ==============================
298
299    # vi /etc/init.d/sentinel
300
301        #!/bin/sh
302        #
303        # sentinel start/stop/restart script
304        #
305
306        SMFILTER=/etc/mail/filter/sentinel
307        CONFIG=/etc/mail/tables/sentinel.cf
308        SOCKET=/var/run/sentinel/sock
309
310        getprocs() {
311            /usr/bin/ps -ef | /usr/bin/grep $1 | /usr/bin/grep -v grep | awk '{print $2}'
312        }
313
314        case $1 in
315
316            start)
317                echo 'Starting Sentinel... \c'
318                if [ -r $SOCKET ]; then
319                    pids=`getprocs $SMFILTER`
320                    if [ -z "$pids" ]; then
321                        rm -f $SOCKET
322                    else
323                        echo 'Sentinel is already running. Aborting.'
324                        exit 0
325                    fi
326                fi
327                $SMFILTER -c $CONFIG -p unix:$SOCKET -d
328                sleep 3; /usr/bin/chmod 777 $SOCKET     # Needed under Solaris 2.5.1
329                echo DONE
330                ;;
331
332            stop)
333                pids=`getprocs $SMFILTER`
334                if [ "$pids" ]; then
335                    echo 'Stopping Sentinel... \c'
336                    kill $pids
337                    while [ "`getprocs $SMFILTER`" ]; do sleep 3; done
338                    if [ -r $SOCKET ]; then rm -f $SOCKET; fi
339                    echo DONE
340                fi
341                ;;
342
343            restart)
344                if [ ! -r $SOCKET ]; then
345                    echo "'$SOCKET' does not exists. Starting... \c"
346                    $SMFILTER -c $CONFIG -p unix:$SOCKET -d
347                    sleep 3; /usr/bin/chmod 777 $SOCKET # Needed under Solaris 2.5.1
348                    echo DONE
349                    exit 0
350                fi
351                pids=`getprocs $SMFILTER`
352                if [ "$pids" ]; then
353                    echo 'Restarting Sentinel... \c'
354                    kill $pids
355                    while [ "`getprocs $SMFILTER`" ]; do sleep 3; done
356                    if [ -r $SOCKET  ]; then rm -f $SOCKET; fi
357                else
358                    echo "'$SOCKET' exists but Sentinel isn't running. Starting... \c"
359                    rm -f $SOCKET
360                fi
361                $SMFILTER -c $CONFIG -p unix:$SOCKET -d
362                sleep 3; /usr/bin/chmod 777 $SOCKET     # Needed under Solaris 2.5.1
363                echo DONE
364                ;;
365
366            reload)
367                echo 'Reloading Sentinel... \c'
368                if [ ! -r $SOCKET ]; then
369                    echo "'$SOCKET' does not exists. Aborting."
370                    exit 1
371                fi
372                pids=`getprocs $SMFILTER`
373                if [ "$pids" ]; then
374                    kill -USR1 $pids
375                else
376                    echo "Sentinel isn't running. Aborting."
377                fi
378                ;;
379
380            *)
381                echo "usage: $0 {start|stop|restart|reload}"
382                ;;
383
384        esac
385        exit 0
386
387    # chown root:sys /etc/init.d/sentinel
388    # chmod 744      /etc/init.d/sentinel
389
390VII. Sentinel "WATCHDOG":
391     ===================
392
393    Under Solaris 2.5.1 (or an overloaded relay ?), after an undefined time of
394    use, Sentinel becomes "nuts":
395
396        mx# /usr/bin/ps -e -o "pcpu args" | grep 'sentinel -c'
397        62.5 /etc/mail/filter/sentinel -c /etc/mail/tables/sentinel.cf
398         ^
399         |___ CPU used at 62.5%
400
401    So, a "watchdog", started via CRON(1M), will check this and restart it if
402    needed:
403
404        mx# crontab -e
405
406#------------------------------------------------------------------
407            # Check that our Milter filter (Sentinel) didn't become "nuts"...
408#------------------------------------------------------------------
409            10,20,30,40,50 * * * * /etc/mail/cron/sentinel.watchdog
410
411        mx# cat /etc/mail/cron/sentinel.watchdog
412
413            #!/bin/sh
414            process=`/usr/bin/ps -e -o "pcpu pid args" | grep 'sentinel -c'`
415            cpusage=`echo $process | cut -d ' ' -f1`
416            if [ $cpusage -gt 50 ]; then
417
418                SMFILTER=/etc/mail/filter/sentinel
419                CONFIG=/etc/mail/tables/sentinel.cf
420                SOCKET=/var/run/sentinel/sock
421
422                # Stop the current process...
423                pid=`echo $process | cut -d ' ' -f2`
424                kill $pid
425                sleep 3
426                while [ "`/usr/bin/ps -e -o 'pid args' | grep 'sentinel -c'`" ]; do sleep 3; done
427
428                # Start a new Sentinel filter...
429                if [ -r $SOCKET  ]; then rm -f $SOCKET; fi
430                $SMFILTER -c $CONFIG -p unix:$SOCKET -d
431                sleep 3; /usr/bin/chmod 777 $SOCKET
432            fi
433
434#--------------------------------------------------------------------
435

README.Solaris8

1For better stability and performance please consider to have kernel patch
2level 108528-17 September 2002. Or at least patch 108827-34 for libpthread.
3