]> arthur.barton.de Git - ngircd.git/commitdiff
Merge branch 'MorePrivacy'
authorAlexander Barton <alex@barton.de>
Sun, 26 Jun 2011 13:41:27 +0000 (15:41 +0200)
committerAlexander Barton <alex@barton.de>
Sun, 26 Jun 2011 13:41:27 +0000 (15:41 +0200)
* MorePrivacy:
  New configuration opion "MorePrivacy" to "censor" some user information

INSTALL
doc/Contributing.txt [new file with mode: 0644]
doc/sample-ngircd.conf.tmpl
man/ngircd.conf.5.tmpl
src/ngircd/conf.c
src/ngircd/conf.h
src/ngircd/parse.c

diff --git a/INSTALL b/INSTALL
index ea77bd927a157dad3fe191f66790cd9ed815b457..1e96e16e24517cb654db7f52b59b137e4a59efeb 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -17,8 +17,8 @@ Differences to version 17
 - Support for ZeroConf/Bonjour/Rendezvous service registration has been
   removed. The configuration option "NoZeroconf" is no longer available.
 
-- The structure of ngircd.conf has been cleaned up and two new configuration
-  sections have been introduced: [Limits] and [Options].
+- The structure of ngircd.conf has been cleaned up and three new configuration
+  sections have been introduced: [Limits], [Options], and [SSL].
   Lots of configuration variables stored in the [Global] section are now
   deprecated there and should be stored in one of these new sections (but
   still work in [Global]):
@@ -39,11 +39,11 @@ Differences to version 17
     "PingTimeout"        -> [Limits]
     "PongTimeout"        -> [Limits]
     "PredefChannelsOnly" -> [Options]
-    "SSLCertFile"        -> [Options]
-    "SSLDHFile"          -> [Options]
-    "SSLKeyFile"         -> [Options]
-    "SSLKeyFilePassword" -> [Options]
-    "SSLPorts"           -> [Options]
+    "SSLCertFile"        -> [SSL], and renamed to "CertFile"
+    "SSLDHFile"          -> [SSL], and renamed to "DHFile"
+    "SSLKeyFile"         -> [SSL], and renamed to "KeyFile"
+    "SSLKeyFilePassword" -> [SSL], and renamed to "KeyFilePassword"
+    "SSLPorts"           -> [SSL], and renamed to "Ports"
     "SyslogFacility"     -> [Options]
     "WebircPassword"     -> [Options]
   You should adjust your ngircd.conf and run "ngircd --configtest" to make
diff --git a/doc/Contributing.txt b/doc/Contributing.txt
new file mode 100644 (file)
index 0000000..089afd4
--- /dev/null
@@ -0,0 +1,54 @@
+
+                     ngIRCd - Next Generation IRC Server
+                           http://ngircd.barton.de/
+
+               (c)2001-2011 Alexander Barton and Contributors.
+               ngIRCd is free software and published under the
+                   terms of the GNU General Public License.
+
+                            -- Contributing.txt --
+
+
+If you want to contribute to ngIRCd, please read the following paragraphs to
+get an idea of how to do it the best :-)
+
+ - Use GIT
+
+   The source code of ngIRCd is maintained using GIT, see doc/GIT.txt. So if
+   remotely possible, use GIT for your work, too. It makes your and our lifes
+   much easier ;-)
+
+ - Don't forget to include documentation
+
+   When adding features and new configuration options, don't forget to not
+   only code the features but to describe them in doc/sample-ngircd.conf,
+   man/ngircd.8.tmp and/or man/ngircd.conf.5.tmpl as well!
+
+ - Be present on IRC
+
+   If you intend to code some new features or do some code cleanups or better
+   documentation, please be present on <irc://irc.barton.de/#ngircd> and
+   discuss your plans early! So other developers have an idea on what others
+   are working on, can offer help, and can synchronize their own work.
+
+ - Check and validate your work!
+
+   Use "make check" to validate your work, and use "make distcheck" to
+   validate the resulting archives, especially when adding/removing files!
+
+ - Send patches in "unified diff" format
+
+   Please send patches in "unified" format, that is, use "diff -u".
+   Or even better: use GIT ("git diff"), see above.
+
+ - Send patches to the mailing list
+
+   If you have some code to present, send the patch(es) and/or pointers to
+   your GIT repository to the official ngIRCd mailing list for review, not
+   only to #ngircd: so it becomes archived and more people have a chance to
+   review your patch.
+
+   Sure it is a good idea to post some notes to #ngircd, too! :-)
+
+   And this is open source, your work must not be 100% finished and perfect,
+   work in progress is interesting, too: "release early, release often"!
index f5d7c8a6f7a7c5c0ca61fa63bdaa5c3ad0461876..7cd8afe0b38801d8425cf8838e68ab07afa52712 100644 (file)
@@ -12,7 +12,8 @@
 # Use "ngircd --configtest" (see manual page ngircd(8)) to validate that the
 # server interprets the configuration file as expected!
 #
-# Please see ngircd.conf(5) for a complete list of configuration options.
+# Please see ngircd.conf(5) for a complete list of configuration options
+# and their descriptions.
 #
 
 [Global]
        # "PONG" reply.
        ;RequireAuthPing = no
 
-       # SSL Server Key Certificate
-       ;SSLCertFile = :ETCDIR:/ssl/server-cert.pem
-
-       # Diffie-Hellman parameters
-       ;SSLDHFile = :ETCDIR:/ssl/dhparams.pem
-
-       # SSL Server Key
-       ;SSLKeyFile = :ETCDIR:/ssl/server-key.pem
-
-       # password to decrypt SSLKeyFile (OpenSSL only)
-       ;SSLKeyFilePassword = secret
-
-       # Additional Listen Ports that expect SSL/TLS encrypted connections
-       ;SSLPorts = 6697, 9999
+       # Silently drop all incomming CTCP requests.
+       ;ScrubCTCP = no
 
        # Syslog "facility" to which ngIRCd should send log messages.
        # Possible values are system dependent, but most probably auth, daemon,
        # user and local1 through local7 are possible values; see syslog(3).
        # Default is "local5" for historical reasons, you probably want to
        # change this to "daemon", for example.
-       SyslogFacility = local1
+       ;SyslogFacility = local1
 
        # Password required for using the WEBIRC command used by some
        # Web-to-IRC gateways. If not set/empty, the WEBIRC command can't
        # be used. (Default: not set)
        ;WebircPassword = xyz
 
+;[SSL]
+       # SSL-related configuration options. Please note that this section
+       # is only available when ngIRCd is compiled with support for SSL!
+       # So don't forget to remove the ";" above if this is the case ...
+
+       # SSL Server Key Certificate
+       ;CertFile = :ETCDIR:/ssl/server-cert.pem
+
+       # Diffie-Hellman parameters
+       ;DHFile = :ETCDIR:/ssl/dhparams.pem
+
+       # SSL Server Key
+       ;KeyFile = :ETCDIR:/ssl/server-key.pem
+
+       # password to decrypt SSLKeyFile (OpenSSL only)
+       ;KeyFilePassword = secret
+
+       # Additional Listen Ports that expect SSL/TLS encrypted connections
+       ;Ports = 6697, 9999
+
 [Operator]
        # [Operator] sections are used to define IRC Operators. There may be
        # more than one [Operator] block, one for each local operator.
index 8198c92b12af5f00fd22a53de29d405deb285d02..d25f1ebcb73e146f7c80f723f72a12827cc48690 100644 (file)
@@ -52,8 +52,8 @@ for numbers all decimal integer values are valid.
 In addition, some string or numerical variables accept lists of values,
 separated by commas (",").
 .SH "SECTION OVERVIEW"
-The file can contain blocks of four types: [Global], [Limits], [Options],
-[Operator], [Server], and [Channel].
+The file can contain blocks of seven types: [Global], [Limits], [Options],
+[SSL], [Operator], [Server], and [Channel].
 .PP
 The main configuration of the server is stored in the
 .I [Global]
@@ -68,8 +68,10 @@ block are used to tweak different limits and timeouts of the daemon, like the
 maximum number of clients allowed to connect to this server. Variables in the
 .I [Options]
 section can be used to enable or disable specific features of ngIRCd, like
-support for IDENT, PAM, IPv6, SSL, and protocol and cloaking features. These
-two sections are both optional.
+support for IDENT, PAM, IPv6, and protocol and cloaking features. The
+.I [SSL]
+block contains all SSL-related configuration variables. These three sections
+are all optional.
 .PP
 IRC operators of this server are defined in
 .I [Operator]
@@ -81,7 +83,7 @@ blocks are used to configure pre-defined ("persistent") IRC channels.
 .PP
 There can be more than one [Operator], [Server] and [Channel] section per
 configuration file (one for each operator, server, and channel), but only
-exactly one [Global], one [Limits], and one [Options] section.
+exactly one [Global], one [Limits], one [Options], and one [SSL] section.
 .SH [GLOBAL]
 The
 .I [Global]
@@ -285,6 +287,33 @@ Let ngIRCd send an "authentication PING" when a new client connects, and
 register this client only after receiving the corresponding "PONG" reply.
 Default: no.
 .TP
+\fBScrubCTCP\fR (boolean)
+If set to true, ngIRCd will silently drop all CTCP requests sent to it from
+both clients and servers. It will also not forward CTCP requests to any
+other servers. CTCP requests can be used to query user clients about which
+software they are using and which versions said softare is. CTCP can also be
+used to reveal clients IP numbers. ACTION CTCP requests are not blocked,
+this means that /me commands will not be dropped, but please note that
+blocking CTCP will disable file sharing between users!
+Default: no.
+.TP
+\fBSyslogFacility\fR (string)
+Syslog "facility" to which ngIRCd should send log messages. Possible
+values are system dependent, but most probably "auth", "daemon", "user"
+and "local1" through "local7" are possible values; see syslog(3).
+Default is "local5" for historical reasons, you probably want to
+change this to "daemon", for example.
+.TP
+\fBWebircPassword\fR (string)
+Password required for using the WEBIRC command used by some Web-to-IRC
+gateways. If not set or empty, the WEBIRC command can't be used.
+Default: not set.
+.SH [SSL]
+All SSL-related configuration variables are located in the
+.I [SSL]
+section. Please note that this whole section is only recognized by ngIRCd
+when it is compiled with support for SSL using OpenSSL or GnuTLS!
+.TP
 \fBSSLCertFile\fR (string)
 SSL Certificate file of the private server key.
 .TP
@@ -307,18 +336,6 @@ OpenSSL only: Password to decrypt the private key file.
 Same as \fBPorts\fR , except that ngIRCd will expect incoming connections
 to be SSL/TLS encrypted. Common port numbers for SSL-encrypted IRC are 6669
 and 6697. Default: none.
-.TP
-\fBSyslogFacility\fR (string)
-Syslog "facility" to which ngIRCd should send log messages. Possible
-values are system dependent, but most probably "auth", "daemon", "user"
-and "local1" through "local7" are possible values; see syslog(3).
-Default is "local5" for historical reasons, you probably want to
-change this to "daemon", for example.
-.TP
-\fBWebircPassword\fR (string)
-Password required for using the WEBIRC command used by some Web-to-IRC
-gateways. If not set or empty, the WEBIRC command can't be used.
-Default: not set.
 .SH [OPERATOR]
 .I [Operator]
 sections are used to define IRC Operators. There may be more than one
@@ -334,10 +351,6 @@ Password of the IRC operator.
 \fBMask\fR (string)
 Mask that is to be checked before an /OPER for this account is accepted.
 Example: nick!ident@*.example.com
-.SH [FEATURES]
-An optional section that can be used to disable features at
-run-time. A feature is enabled by default if if ngircd was built with
-support for it.
 .SH [SERVER]
 Other servers are configured in
 .I [Server]
index c947997215773e7e486ba586648ee32349b1aa24..4991918d54ade6d843e249bc61205e867d2ab497 100644 (file)
@@ -89,6 +89,8 @@ static void Init_Server_Struct PARAMS(( CONF_SERVER *Server ));
 
 #ifdef SSL_SUPPORT
 
+static void Handle_SSL PARAMS(( int Line, char *Var, char *Ark ));
+
 struct SSLOptions Conf_SSLOptions;
 
 /**
@@ -121,6 +123,9 @@ CheckFileReadable(const char *Var, const char *Filename)
 {
        FILE *fp;
 
+       if (!Filename)
+               return;
+
        fp = fopen(Filename, "r");
        if (fp)
                fclose(fp);
@@ -375,18 +380,7 @@ Conf_Test( void )
 #ifndef STRICT_RFC
        printf("  RequireAuthPing = %s\n", yesno_to_str(Conf_AuthPing));
 #endif
-#ifdef SSL_SUPPORT
-       printf("  SSLCertFile = %s\n", Conf_SSLOptions.CertFile);
-       printf("  SSLDHFile = %s\n", Conf_SSLOptions.DHFile);
-       printf("  SSLKeyFile = %s\n", Conf_SSLOptions.KeyFile);
-       if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
-               puts("  SSLKeyFilePassword = <secret>");
-       else
-               puts("  SSLKeyFilePassword = ");
-       array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
-       printf("  SSLPorts = ");
-       ports_puts(&Conf_SSLOptions.ListenPorts);
-#endif
+       printf("  ScrubCTCP = %s\n", yesno_to_str(Conf_ScrubCTCP));
 #ifdef SYSLOG
        printf("  SyslogFacility = %s\n",
               ngt_SyslogFacilityName(Conf_SyslogFacility));
@@ -394,6 +388,24 @@ Conf_Test( void )
        printf("  WebircPassword = %s\n", Conf_WebircPwd);
        puts("");
 
+#ifdef SSL_SUPPORT
+       puts("[SSL]");
+       printf("  CertFile = %s\n", Conf_SSLOptions.CertFile
+                                       ? Conf_SSLOptions.CertFile : "");
+       printf("  DHFile = %s\n", Conf_SSLOptions.DHFile
+                                       ? Conf_SSLOptions.DHFile : "");
+       printf("  KeyFile = %s\n", Conf_SSLOptions.KeyFile
+                                       ? Conf_SSLOptions.KeyFile : "");
+       if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
+               puts("  KeyFilePassword = <secret>");
+       else
+               puts("  KeyFilePassword = ");
+       array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
+       printf("  Ports = ");
+       ports_puts(&Conf_SSLOptions.ListenPorts);
+       puts("");
+#endif
+
        opers_puts();
 
        for( i = 0; i < MAX_SERVERS; i++ ) {
@@ -689,6 +701,7 @@ Set_Defaults(bool InitServers)
 #endif
        Conf_PredefChannelsOnly = false;
 #ifdef SYSLOG
+       Conf_ScrubCTCP = false;
 #ifdef LOG_LOCAL5
        Conf_SyslogFacility = LOG_LOCAL5;
 #else
@@ -846,7 +859,8 @@ Read_Config( bool ngircd_starting )
                        strlcpy( section, str, sizeof( section ));
                        if (strcasecmp(section, "[GLOBAL]") == 0 ||
                            strcasecmp(section, "[LIMITS]") == 0 ||
-                           strcasecmp(section, "[OPTIONS]") == 0)
+                           strcasecmp(section, "[OPTIONS]") == 0 ||
+                           strcasecmp(section, "[SSL]") == 0)
                                continue;
 
                        if( strcasecmp( section, "[SERVER]" ) == 0 ) {
@@ -905,6 +919,10 @@ Read_Config( bool ngircd_starting )
                        Handle_LIMITS(line, var, arg);
                else if(strcasecmp(section, "[OPTIONS]") == 0)
                        Handle_OPTIONS(line, var, arg);
+#ifdef SSL_SUPPORT
+               else if(strcasecmp(section, "[SSL]") == 0)
+                       Handle_SSL(line, var, arg);
+#endif
                else if(strcasecmp(section, "[OPERATOR]") == 0)
                        Handle_OPERATOR(line, var, arg);
                else if(strcasecmp(section, "[SERVER]") == 0)
@@ -951,9 +969,9 @@ Read_Config( bool ngircd_starting )
 
 #ifdef SSL_SUPPORT
        /* Make sure that all SSL-related files are readable */
-       CheckFileReadable("SSLCertFile", Conf_SSLOptions.CertFile);
-       CheckFileReadable("SSLDHFile", Conf_SSLOptions.DHFile);
-       CheckFileReadable("SSLKeyFile", Conf_SSLOptions.KeyFile);
+       CheckFileReadable("CertFile", Conf_SSLOptions.CertFile);
+       CheckFileReadable("DHFile", Conf_SSLOptions.DHFile);
+       CheckFileReadable("KeyFile", Conf_SSLOptions.KeyFile);
 #endif
 
        return true;
@@ -1099,13 +1117,6 @@ CheckLegacyGlobalOption(int Line, char *Var, char *Arg)
            || strcasecmp(Var, "OperCanUseMode") == 0
            || strcasecmp(Var, "OperServerMode") == 0
            || strcasecmp(Var, "PredefChannelsOnly") == 0
-#ifdef SSL_SUPPORT
-           || strcasecmp(Var, "SSLCertFile") == 0
-           || strcasecmp(Var, "SSLDHFile") == 0
-           || strcasecmp(Var, "SSLKeyFile") == 0
-           || strcasecmp(Var, "SSLKeyFilePassword") == 0
-           || strcasecmp(Var, "SSLPorts") == 0
-#endif
            || strcasecmp(Var, "SyslogFacility") == 0
            || strcasecmp(Var, "WebircPassword") == 0) {
                Handle_OPTIONS(Line, Var, Arg);
@@ -1121,6 +1132,16 @@ CheckLegacyGlobalOption(int Line, char *Var, char *Arg)
                Handle_LIMITS(Line, Var, Arg);
                return "[Limits]";
        }
+#ifdef SSL_SUPPORT
+       if (strcasecmp(Var, "SSLCertFile") == 0
+           || strcasecmp(Var, "SSLDHFile") == 0
+           || strcasecmp(Var, "SSLKeyFile") == 0
+           || strcasecmp(Var, "SSLKeyFilePassword") == 0
+           || strcasecmp(Var, "SSLPorts") == 0) {
+               Handle_SSL(Line, Var + 3, Arg);
+               return "[SSL]";
+       }
+#endif
 
        return NULL;
 }
@@ -1301,9 +1322,16 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
                /** TODO: This function and support for these options in the
                 * [Global] section could be removed starting with ngIRCd
                 * release 19 (one release after marking it "deprecated"). */
-               Config_Error(LOG_WARNING,
-                            "%s, line %d (section \"Global\"): \"%s\" is deprecated here, move it to %s!",
-                            NGIRCd_ConfFile, Line, Var, section);
+               if (strncasecmp(Var, "SSL", 3) == 0) {
+                       Config_Error(LOG_WARNING,
+                                    "%s, line %d (section \"Global\"): \"%s\" is deprecated here, move it to %s and rename to \"%s\"!",
+                                    NGIRCd_ConfFile, Line, Var, section,
+                                    Var + 3);
+               } else {
+                       Config_Error(LOG_WARNING,
+                                    "%s, line %d (section \"Global\"): \"%s\" is deprecated here, move it to %s!",
+                                    NGIRCd_ConfFile, Line, Var, section);
+               }
                return;
        }
 
@@ -1465,53 +1493,77 @@ Handle_OPTIONS(int Line, char *Var, char *Arg)
                return;
        }
 #endif
+       if (strcasecmp(Var, "ScrubCTCP") == 0) {
+               Conf_ScrubCTCP = Check_ArgIsTrue(Arg);
+               return;
+       }
+#ifdef SYSLOG
+       if (strcasecmp(Var, "SyslogFacility") == 0) {
+               Conf_SyslogFacility = ngt_SyslogFacilityID(Arg,
+                                                          Conf_SyslogFacility);
+               return;
+       }
+#endif
+       if (strcasecmp(Var, "WebircPassword") == 0) {
+               len = strlcpy(Conf_WebircPwd, Arg, sizeof(Conf_WebircPwd));
+               if (len >= sizeof(Conf_WebircPwd))
+                       Config_Error_TooLong(Line, Var);
+               return;
+       }
+
+       Config_Error_Section(Line, Var, "Options");
+}
+
 #ifdef SSL_SUPPORT
-       if (strcasecmp(Var, "SSLCertFile") == 0) {
+
+/**
+ * Handle variable in [SSL] configuration section.
+ *
+ * @param Line Line numer in configuration file.
+ * @param Var  Variable name.
+ * @param Arg  Variable argument.
+ */
+static void
+Handle_SSL(int Line, char *Var, char *Arg)
+{
+       assert(Line > 0);
+       assert(Var != NULL);
+       assert(Arg != NULL);
+
+       if (strcasecmp(Var, "CertFile") == 0) {
                assert(Conf_SSLOptions.CertFile == NULL);
                Conf_SSLOptions.CertFile = strdup_warn(Arg);
                return;
        }
-       if (strcasecmp(Var, "SSLDHFile") == 0) {
+       if (strcasecmp(Var, "DHFile") == 0) {
                assert(Conf_SSLOptions.DHFile == NULL);
                Conf_SSLOptions.DHFile = strdup_warn(Arg);
                return;
        }
-       if (strcasecmp(Var, "SSLKeyFile") == 0) {
+       if (strcasecmp(Var, "KeyFile") == 0) {
                assert(Conf_SSLOptions.KeyFile == NULL);
                Conf_SSLOptions.KeyFile = strdup_warn(Arg);
                return;
        }
-       if (strcasecmp(Var, "SSLKeyFilePassword") == 0) {
+       if (strcasecmp(Var, "KeyFilePassword") == 0) {
                assert(array_bytes(&Conf_SSLOptions.KeyFilePassword) == 0);
                if (!array_copys(&Conf_SSLOptions.KeyFilePassword, Arg))
                        Config_Error(LOG_ERR,
-                                    "%s, line %d (section \"Global\"): Could not copy %s: %s!",
+                                    "%s, line %d (section \"SSL\"): Could not copy %s: %s!",
                                     NGIRCd_ConfFile, Line, Var,
                                     strerror(errno));
                return;
        }
-       if (strcasecmp(Var, "SSLPorts") == 0) {
+       if (strcasecmp(Var, "Ports") == 0) {
                ports_parse(&Conf_SSLOptions.ListenPorts, Line, Arg);
                return;
        }
-#endif
-#ifdef SYSLOG
-       if (strcasecmp(Var, "SyslogFacility") == 0) {
-               Conf_SyslogFacility = ngt_SyslogFacilityID(Arg,
-                                                          Conf_SyslogFacility);
-               return;
-       }
-#endif
-       if (strcasecmp(Var, "WebircPassword") == 0) {
-               len = strlcpy(Conf_WebircPwd, Arg, sizeof(Conf_WebircPwd));
-               if (len >= sizeof(Conf_WebircPwd))
-                       Config_Error_TooLong(Line, Var);
-               return;
-       }
 
-       Config_Error_Section(Line, Var, "Options");
+       Config_Error_Section(Line, Var, "SSL");
 }
 
+#endif
+
 /**
  * Handle variable in [Operator] configuration section.
  *
@@ -1848,7 +1900,7 @@ Validate_Config(bool Configtest, bool Rehash)
 #ifdef PAM
        if (Conf_ServerPwd[0])
                Config_Error(LOG_ERR,
-                            "This server uses PAM, \"Password\" will be ignored!");
+                            "This server uses PAM, \"Password\" in [Global] section will be ignored!");
 #endif
 
 #ifdef DEBUG
index c2af692a63834b5a0153eec3ef0b64910dc8797e..afc0afaa96c712f1c78626160a26d3dab2750aaa 100644 (file)
@@ -175,15 +175,18 @@ GLOBAL bool Conf_DNS;
 /** Enable IDENT lookups, even when compiled with support for it */
 GLOBAL bool Conf_Ident;
 
-/** Enable all usage of PAM, even when compiled with support for it */
-GLOBAL bool Conf_PAM;
-
 /** Enable "more privacy" mode and "censor" some user-related information */
 GLOBAL bool Conf_MorePrivacy;
 
 /** Enable NOTICE AUTH messages on connect */
 GLOBAL bool Conf_NoticeAuth;
 
+/** Enable all usage of PAM, even when compiled with support for it */
+GLOBAL bool Conf_PAM;
+
+/** Disable all CTCP commands except for /me ? */
+GLOBAL bool Conf_ScrubCTCP;
+
 /*
  * try to connect to remote systems using the ipv6 protocol,
  * if they have an ipv6 address? (default yes)
index c2603918ff430643d045d8e5d95bdfcca43eec8f..72e3430998b301d4011b9b55175e1a91d41875a6 100644 (file)
@@ -47,6 +47,7 @@
 #include "numeric.h"
 
 #include "exp.h"
+#include "conf.h"
 
 struct _NUMERIC {
        int numeric;
@@ -124,6 +125,8 @@ static bool Validate_Args PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
 
 static bool Handle_Request PARAMS(( CONN_ID Idx, REQUEST *Req ));
 
+static bool ScrubCTCP PARAMS((char *Request));
+
 /**
  * Return the pointer to the global "IRC command structure".
  * This structure, an array of type "COMMAND" describes all the IRC commands
@@ -174,8 +177,10 @@ Parse_Request( CONN_ID Idx, char *Request )
        /* remove leading & trailing whitespace */
        ngt_TrimStr( Request );
 
-       if( Request[0] == ':' )
-       {
+       if (Conf_ScrubCTCP && ScrubCTCP(Request))
+               return true;
+
+       if (Request[0] == ':') {
                /* Prefix */
                req.prefix = Request + 1;
                ptr = strchr( Request, ' ' );
@@ -459,7 +464,6 @@ Handle_Numeric(CLIENT *client, REQUEST *Req)
        return IRC_WriteStrClientPrefix(target, prefix, "%s", str);
 }
 
-
 static bool
 Handle_Request( CONN_ID Idx, REQUEST *Req )
 {
@@ -525,4 +529,39 @@ Handle_Request( CONN_ID Idx, REQUEST *Req )
 } /* Handle_Request */
 
 
+/**
+ * Check if incoming messages contains CTCP commands and should be dropped.
+ *
+ * @param Request NULL terminated incoming command.
+ * @returns true, when the message should be dropped.
+ */
+static bool
+ScrubCTCP(char *Request)
+{
+       static const char me_cmd[] = "ACTION ";
+       static const char ctcp_char = 0x1;
+       bool dropCommand = false;
+       char *ptr = Request;
+       char *ptrEnd = strchr(Request, '\0');
+
+       if (Request[0] == ':' && ptrEnd > ptr)
+               ptr++;
+
+       while (ptr != ptrEnd && *ptr != ':')
+               ptr++;
+
+       if ((ptrEnd - ptr) > 1) {
+               ptr++;
+               if (*ptr == ctcp_char) {
+                       dropCommand = true;
+                       ptr++;
+                       /* allow /me commands */
+                       if ((size_t)(ptrEnd - ptr) >= strlen(me_cmd)
+                           && !strncmp(ptr, me_cmd, strlen(me_cmd)))
+                               dropCommand = false;
+               }
+       }
+       return dropCommand;
+}
+
 /* -eof- */