Antirelay Sample Plugin Information ------------------------------------ o the Sample Plugin 1. Building the sample There is a sample Makefile included with the plugin that should be usable or easily adaptable to most UNIX platforms. The default is set to use GCC (the Gnu Compiler) since it's assumed that's the easiest compiler package for people to get. You may need to modify values in the Makefile to be able to build on your particular platform. In general, just make sure you build a shared object with position independent code. Once you have the Makefile configured for your platform, just type "gmake -f Makefile.antirelay". When you're done, copy the shared object (antirelay.so for example) into wherever you want to reside in your server installation. 2. Configuring the server To configure the server to recognize your plugin you need to set a config option specifying which plugins the smtpd should load when it starts up. The option 'service.smtp.protplugmodules' must be set locally and can contain multiple plugins to load. The value for the option is a $ separated list of shared objects. If the objects do not reside in a directory the server is already looking in (such as bin/msg/lib), then the value must be a full path. So for example, to configure the server to load both the antirelay plugin and some other plugin (called foo.so) you would use the following command: configutil -l -o service.smtp.protplugmodules -v 'antirelay.so$foo.so' Remember to run configutil you'll need to set the environment variable CONFIGROOT to the config directory for that server instance. This is usually something like /usr/netscape/suitespot/msg-hostname/config. You may also need to set a variable like LD_LIBRARY_PATH (or whatever your platforms shared library path variable is) so that configutil can find the shared libraries it needs. Setting it to [server-root]/bin/msg/lib should be sufficient. Also, if you're going to use hostname based rules (like *.netscape.com) make sure you turn on hostname resolution in the smtp server (see the explanation of resolvehostnames below). If you don't turn this on and use hostname based rules, every host will be treated as an untrusted host since the server cannot match the IP-addresses to the hostname patterns. 3. Configuring the plugin Antirelay configuration will be done via a plain text config file (antirelay.conf) that will be stored in the server-instance config directory. It will look something like: # comments here resolvehostnames:0 useauthinfo:0 advertiseauthinfo:1 delivery:*@netscape.com submission:*.com submission:*.netscape.com submission:*.foo.com submission:hamilton.mcom.com submission:127.0.0.1 The antirelay.conf should be placed in the server instance config directory. Each line is colon delimited. The first field contains the key and the second the data. Any blank link or line beginning with a pound sign (#) is ignored. The keys are defined below. submission: This parameter indicates a domain from which peers are trusted to relay. It can be listed multiple times. These parameters may contain specific hostnames or ip-addresses. They may also contain patterns using asterisk characters to indicate a wildcard. They are processed in reverse order (last rule is evaluated first). If any pattern matches, the peer is allowed unconditional relay. Listing no submission patterns indicates that all hosts may relay. delivery: This parameter indicates a domain to any host is allowed to delivery. It can be listed multiple times. These parameters may contain specific hostnames or ip-addresses. They may also contain patterns using asterisk characters to indicate a wildcard. They are processed in reverse order (last rule is evaluated first). If any pattern matches, the peer is allowed unconditional relay. Listing no delivery patterns indicates that any address will be delivered to. resolvehostnames: By default the plugin will attempt to use hostnames if the messaging server is configured to resolve peer addresses into hostnames. If your server is not setup to resolve hostnames (config parameter service.smtp.doclientdnslookup) you delivery and submission domains should contain only ip-addresses and ip-address patterns. However, if your server is configured to resolve hostnames but you do not want the plugin to use them, you may set the data value for this to a zero (0) indicating it should only use ip-addresses to match patterns. The default is one (1). useauthinfo: By default the plugin will trust any authenticated user as if they were connecting from a valid submission domain. If you want to change this, set this data value to zero (0). The default is one (1). advertiseauthinfo: By default the server will not provide an SMTP client any way for it to know if authentication will make any difference. If this option is enabled, clients being rejected relay privileges will receive a different return code (530) indicating that authenticating may allow them to perform the operation. If you want to enable this, set the data value to one (1). The default is zero (0). 4. Debugging problems If you're having problems with the plugin (it's not working how you expect, the smtpd is crashing, etc), try building antirelay with debugging enabled. This will generate more verbose logging. To make a debug build, just uncomment the line in the Makefile where "FLAGS" is defined to be "-D_DEBUG". Rebuild the plugin and copy the new shared object into place. Now stop and start the server. Once the server is started, run your test and then go look at [instance-dir]/log/smtp/smtp. It should contain log messages about the plugin (generated by smtpd) and from the plugin itself. General Plugin Information -------------------------- o the Plugin API 1. Take a look at ../include/protplug.h. If you can read C code, most of the detail you need is there. Then look at antirelay.c. That should give you a pretty good example. 2. GETPROPERTY keys These are the keys you can pass to the GETPROPERTY() macro to get session specific properties from the server. "TLS" /* yes/no, in TLS */ "ESMTP" /* yes/no, got good EHLO */ "BadCert" /* yes/no, SSLclientcert bad */ "ReceivedLines" /* int, "Recieved" lines */ "SizeOfHeader" /* int */ "SizeOfBody" /* int */ "PeerName" /* peer name (if available) */ "PeerIP" /* peer ip (dot-quad) */ "HostName" /* server hostname */ "HeloDomain" /* domain given in ehlo */ "SenderAuthed" /* yes/no */ "AuthSender" /* authenticated sender */ "Sender" /* from */ "Recipients" /* rcpt list, comma separated */ "BadCommands" /* int, num so far */ 3. GetINI keys The keys you can pass to GetIni() are just config value names. Run configutil if you want to see a list of them. o Plugin Programming Tips 1. Use PPRealloc(p,0) instead of free(p). 2. Be careful about passing valid pointers to realloc and expecting it to work like malloc. It doesn't. If you have any other pointers pointing to the same data, they will be invalid after the call. The safest way to allocate new memory is make sure your pointer is set to NULL before calling realloc. 3. Be very careful about freeing all memory you use... especially on a per plugin bases. Smtpd is a very long lived process and leaking a few bytes per connection (per plugin) can end up leaking a lot of memory. 4. Watch out for system routines that allocate their own memory (like strdup). You cannot use those. You must write your own (like ARStrdup) that use the plugin memory allocation routines. 5. Be careful about external dependencies. If you're DLL or shared library has unresolved symbols which are not fulfilled at load time, the smtpd will not be able to load the plugin. A typical indicator of this is seeing an error of "-5977" in the smtp log complaining about not being able to load the plugin. On UNIX, you can use tools like "ldd -r" or "nm " to examine such dependencies. On NT, MS-DevStudio includes a tool called "dumpbin.exe" that will work in a similar fashion. 6. If you're processing DATA lines, make sure you use DEFER if you are doing something passive (like counting bytes). 7. If you're processing DATA lines and want to return a failure (e.g. they submitted a msg that was too large) you need to set the response line and return PP_CLOSE. You cannot return PP_DONE (the session will be in a weird state).