Added support for optional DELAY_ON_ERROR
authorMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 12 Dec 2002 20:54:22 +0000 (20:54 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Thu, 12 Dec 2002 20:54:22 +0000 (20:54 +0000)
15 files changed:
mmsoftware/TODO
mmsoftware/mmftpd/ChangeLog
mmsoftware/mmftpd/etc/mmftpd.conf
mmsoftware/mmftpd/src/mmftpd.c
mmsoftware/mmftpd/src/mmftpd.conf.5
mmsoftware/mmftpd/src/mmftpd.h
mmsoftware/mmmail/ChangeLog
mmsoftware/mmmail/etc/mmpop3d.conf
mmsoftware/mmmail/etc/mmsmtpd.conf
mmsoftware/mmmail/src/mmpop3d/mmpop3d.c
mmsoftware/mmmail/src/mmpop3d/mmpop3d.conf.5
mmsoftware/mmmail/src/mmpop3d/mmpop3d.h
mmsoftware/mmmail/src/mmsmtpd/mmsmtpd.c
mmsoftware/mmmail/src/mmsmtpd/mmsmtpd.conf.5
mmsoftware/mmmail/src/mmsmtpd/mmsmtpd.h

index 29d337e..9501778 100644 (file)
@@ -65,6 +65,4 @@ easy to implement so why not ?
 SITE:
 ====
 
-- Fix cvsweb CGI
 - Fix anoncvs pserver
-- Complete donators.html and contributors.html
index 1638995..6028f8e 100644 (file)
@@ -1,4 +1,4 @@
-$Id: ChangeLog,v 1.1 2002/12/11 10:11:16 mmondor Exp $
+$Id: ChangeLog,v 1.2 2002/12/12 20:54:21 mmondor Exp $
 
 
 
@@ -68,6 +68,8 @@ By     : Matthew Mondor
     non-privileged users.
     The default is to only accept to be started by the superuser and then
     drop privileges.
+  - Configuration file option DELAY_ON_ERROR was added to allow to pause
+    at every user command error. Thanks to Jeroen Oostendorp for the idea.
 * Other
   - Optimized the command matching loop by using fast packed hashes
   - Other optimizations were performed by moving some variables in
index 5e54a8b..a7ee932 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: mmftpd.conf,v 1.1 2002/12/11 10:11:26 mmondor Exp $
+; $Id: mmftpd.conf,v 1.2 2002/12/12 20:54:21 mmondor Exp $
 ;
 ; mmftpd configuration file (/etc/mmftpd.conf)
 ; and # are considered comments, and can happen at start or end of line.
@@ -62,6 +62,11 @@ RESOLVE_HOSTS        FALSE
 ; Maximum number of bad commands user may issue per session
 MAX_ERRORS     16
 ;
+; If TRUE, the server will cause the clients to wait before sending a command
+; after an error was issued. After each error an additional second delay is
+; added.
+DELAY_ON_ERROR FALSE
+;
 ; Total maximum number of simultanious different IP addresses we allow
 MAX_IPS                64
 ; Maximum simultanious connections per single IP address we accept
index 00c9d22..4339781 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmftpd.c,v 1.1 2002/12/11 10:12:25 mmondor Exp $ */
+/* $Id: mmftpd.c,v 1.2 2002/12/12 20:54:21 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2002, Matthew Mondor
@@ -76,7 +76,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmftpd.c,v 1.1 2002/12/11 10:12:25 mmondor Exp $");
+MMRCSID("$Id: mmftpd.c,v 1.2 2002/12/12 20:54:21 mmondor Exp $");
 
 
 
@@ -297,8 +297,6 @@ all_help(clientenv *clenv)
     fdbuf *fdb = clenv->fdb;
     register char *tmp2;
 
-    clenv->errors++;
-
     if ((mm_straspl(args, clenv->buffer, 2)) == 2) {
        register int i = 0;
        register int32_t chash;
@@ -318,7 +316,7 @@ all_help(clientenv *clenv)
        if (valid) {
            tmp = commands[i].name;
            if (!(tmp2 = commands[i].args)) {
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
                if (!reply(fdb, 214, FALSE,
                            "No help information for this command"))
                    return (STATE_ERROR);
@@ -335,7 +333,7 @@ all_help(clientenv *clenv)
                }
            }
        } else {
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
            if (!reply(fdb, 502, FALSE, "Unknown command"))
                return (STATE_ERROR);
        }
@@ -403,7 +401,7 @@ all_beer(clientenv *clenv)
 static int
 all_user(clientenv *clenv)
 {
-    clenv->errors++;
+    REGISTER_ERROR(clenv);
     if (!reply(clenv->fdb, 530, FALSE, "Can't change user"))
        return (STATE_ERROR);
 
@@ -414,7 +412,7 @@ all_user(clientenv *clenv)
 static int
 all_pass(clientenv *clenv)
 {
-    clenv->errors++;
+    REGISTER_ERROR(clenv);
     if (!reply(clenv->fdb, 503, FALSE, "Login with USER first"))
        return (STATE_ERROR);
 
@@ -436,7 +434,7 @@ all_syst(clientenv *clenv)
     } else {
        if (!reply(fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -457,7 +455,7 @@ auth_user(clientenv *clenv)
     if (clenv->user || clenv->tuser) {
        if (clenv->user) clenv->user = mmstrfree(clenv->user);
        if (clenv->tuser) clenv->tuser = mmstrfree(clenv->tuser);
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     if ((mm_straspl(args, clenv->buffer, 2)) == 2) {
@@ -479,7 +477,7 @@ auth_user(clientenv *clenv)
                if (!reply(fdb, 530, FALSE,
                            "No anonymous access on this server"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
 
        } else {
@@ -499,7 +497,7 @@ auth_user(clientenv *clenv)
     } else {
        if (!reply(fdb, 500, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -518,7 +516,7 @@ auth_pass(clientenv *clenv)
 
        if (!reply(fdb, 503, FALSE, "Specify username first"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
 
     } else {
 
@@ -589,12 +587,11 @@ auth_pass(clientenv *clenv)
        }
 
        if (!clenv->login) {
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
            if (clenv->user) clenv->user = mmstrfree(clenv->user);
            if (clenv->tuser) clenv->tuser = mmstrfree(clenv->tuser);
            if (!reply(fdb, 530, FALSE, "Invalid login"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
        }
 
     }
@@ -731,7 +728,8 @@ main_cwd(clientenv *clenv)
            return (STATE_ERROR);
     }
 
-    clenv->errors++;
+    REGISTER_ERROR(clenv);
+
     return (STATE_CURRENT);
 }
 
@@ -750,7 +748,7 @@ main_cdup(clientenv *clenv)
     } else {
        if (!reply(clenv->fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -793,7 +791,7 @@ main_port(clientenv *clenv)
                        } else {
                            if (!reply(fdb, 500, FALSE, "Error"))
                                nextstate = STATE_ERROR;
-                           clenv->errors++;
+                           REGISTER_ERROR(clenv);
                            mmsyslog(0, LOGLEVEL,
                                    "* main_port() - transfer_request(\
 REQ_NEWPORT)");
@@ -801,12 +799,12 @@ REQ_NEWPORT)");
                    } else {
                        if (!reply(fdb, 500, FALSE, "Transfer ongoing"))
                            nextstate = STATE_ERROR;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                    }
                } else {
                    if (!reply(fdb, 500, FALSE, "Error"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                    mmsyslog(0, LOGLEVEL,
                            "* main_port() - transfer_request(REQ_STATUS)");
                }
@@ -815,17 +813,17 @@ REQ_NEWPORT)");
                        clenv->id, ipaddr, port);
                if (!reply(fdb, 500, FALSE, "Illegal port or address"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "Command syntax error"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -871,7 +869,7 @@ main_lprt(clientenv *clenv)
                            } else {
                                if (!reply(fdb, 500, FALSE, "Error"))
                                    nextstate = STATE_ERROR;
-                               clenv->errors++;
+                               REGISTER_ERROR(clenv);
                                mmsyslog(0, LOGLEVEL,
                                        "* main_lprt() - transfer_request(\
 REQ_NEWPORT)");
@@ -879,12 +877,12 @@ REQ_NEWPORT)");
                        } else {
                            if (!reply(fdb, 500, FALSE, "Transfer ongoing"))
                                nextstate = STATE_ERROR;
-                           clenv->errors++;
+                           REGISTER_ERROR(clenv);
                        }
                    } else {
                        if (!reply(fdb, 500, FALSE, "Error"))
                            nextstate = STATE_ERROR;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                        mmsyslog(0, LOGLEVEL,
                                "* main_lprt() - transfer_request(\
 REQ_STATUS)");
@@ -894,22 +892,22 @@ REQ_STATUS)");
                            clenv->id, ipaddr, port);
                    if (!reply(fdb, 500, FALSE, "Illegal port or address"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                }
            } else {
                if (!reply(fdb, 522, FALSE, "Unimplemented protocol"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "Command syntax error"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -952,7 +950,7 @@ main_eprt(clientenv *clenv)
                            } else {
                                if (!reply(fdb, 500, FALSE, "Error"))
                                    nextstate = STATE_ERROR;
-                               clenv->errors++;
+                               REGISTER_ERROR(clenv);
                                mmsyslog(0, LOGLEVEL,
                                        "* main_eprt() - transfer_request(\
 REQ_NEWPORT)");
@@ -960,12 +958,12 @@ REQ_NEWPORT)");
                        } else {
                            if (!reply(fdb, 500, FALSE, "Transfer ongoing"))
                                nextstate = STATE_ERROR;
-                           clenv->errors++;
+                           REGISTER_ERROR(clenv);
                        }
                    } else {
                        if (!reply(fdb, 500, FALSE, "Error"))
                            nextstate = STATE_ERROR;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                        mmsyslog(0, LOGLEVEL,
                                "* main_eprt() - transfer_request(\
 REQ_STATUS)");
@@ -975,22 +973,22 @@ REQ_STATUS)");
                            clenv->id, ipaddr, port);
                    if (!reply(fdb, 500, FALSE, "Illegal port or address"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                }
            } else {
                if (!reply(fdb, 522, FALSE, "Unimplemented protocol"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "Command syntax error"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1021,26 +1019,26 @@ main_pasv(clientenv *clenv)
                } else {
                    if (!reply(fdb, 500, FALSE, "Error"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                    mmsyslog(0, LOGLEVEL,
                            "* main_pasv() - transfer_request(REQ_NEWPORT)");
                }
            } else {
                if (!reply(fdb, 500, FALSE, "Transfer ongoing"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 500, FALSE, "Error"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
            mmsyslog(0, LOGLEVEL,
                    "* main_pasv() - transfer_request(REQ_STATUS)");
        }
     } else {
        if (!reply(fdb, 501, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1071,26 +1069,26 @@ main_lpsv(clientenv *clenv)
                } else {
                    if (!reply(fdb, 500, FALSE, "Error"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                    mmsyslog(0, LOGLEVEL,
                            "* main_lpsv() - transfer_request(REQ_NEWPORT)");
                }
            } else {
                if (!reply(fdb, 500, FALSE, "Transfer ongoing"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 500, FALSE, "Error"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
            mmsyslog(0, LOGLEVEL,
                    "* main_lpsv() - transfer_request(REQ_STATUS)");
        }
     } else {
        if (!reply(fdb, 501, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1118,26 +1116,26 @@ main_epsv(clientenv *clenv)
                } else {
                    if (!reply(fdb, 500, FALSE, "Error"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                    mmsyslog(0, LOGLEVEL,
                            "* main_epsv() - transfer_request(REQ_NEWPORT)");
                }
            } else {
                if (!reply(fdb, 500, FALSE, "Transfer ongoing"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 500, FALSE, "Error"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
            mmsyslog(0, LOGLEVEL,
                    "* main_epsv() - transfer_request(REQ_STATUS)");
        }
     } else {
        if (!reply(fdb, 501, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1167,7 +1165,7 @@ main_type(clientenv *clenv)
        } else {
            if (!reply(fdb, 504, FALSE, "Unimplemented type"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else if (a == 3) {
        if (!(mm_stricmp(args[1], "L"))) {
@@ -1179,17 +1177,17 @@ main_type(clientenv *clenv)
            } else {
                if (!reply(fdb, 504, FALSE, "Only 8-bit bytes allowed"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "Command syntax error"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1210,12 +1208,12 @@ main_stru(clientenv *clenv)
        } else {
            if (!reply(fdb, 504, FALSE, "Unimplemented structure"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1236,12 +1234,12 @@ main_mode(clientenv *clenv)
        } else {
            if (!reply(fdb, 502, FALSE, "Unimplemented mode"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1283,7 +1281,7 @@ REQ_TRANSFER)");
                        } else {
                            if (!reply(fdb, 425, FALSE, "Error"))
                                nextstate = STATE_ERROR;
-                           clenv->errors++;
+                           REGISTER_ERROR(clenv);
                            mmsyslog(0, LOGLEVEL,
                                    "* main_retr() - open(%s)", path);
                        }
@@ -1291,30 +1289,30 @@ REQ_TRANSFER)");
                        if (!reply(fdb, 425, FALSE,
                                    "Transfer already ongoing"))
                            nextstate = STATE_ERROR;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                    }
                } else {
                    if (!reply(fdb, 425, FALSE,
                                "Can't establish data connection"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                }
            } else {
                if (!reply(fdb, 425, FALSE, "Error"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
                mmsyslog(0, LOGLEVEL,
                        "* main_retr() - transfer_request(REQ_STATUS)");
            }
        } else {
            if (!reply(fdb, 550, FALSE, "Not a plain file"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "No such file or directory"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1389,7 +1387,7 @@ main_stor(clientenv *clenv)
                                    } else {
                                        if (!reply(fdb, 425, FALSE, "Error"))
                                            nextstate = STATE_ERROR;
-                                       clenv->errors++;
+                                       REGISTER_ERROR(clenv);
                                        mmsyslog(0, LOGLEVEL,
                                                "* main_stor() - open(%s)",
                                                path);
@@ -1398,7 +1396,7 @@ main_stor(clientenv *clenv)
                                    if (!reply(fdb, 502, FALSE,
                                                "Quota exceeded"))
                                        nextstate = STATE_ERROR;
-                                   clenv->errors++;
+                                   REGISTER_ERROR(clenv);
                                    mmsyslog(0, LOGLEVEL,
                                            "%08X Quota exceeded",
                                            clenv->id);
@@ -1407,18 +1405,18 @@ main_stor(clientenv *clenv)
                                if (!reply(fdb, 425, FALSE,
                                            "Transfer already ongoing"))
                                    nextstate = STATE_ERROR;
-                               clenv->errors++;
+                               REGISTER_ERROR(clenv);
                            }
                        } else {
                            if (!reply(fdb, 425, FALSE,
                                        "Can't establish data connection"))
                                nextstate = STATE_ERROR;
-                           clenv->errors++;
+                           REGISTER_ERROR(clenv);
                        }
                    } else {
                        if (!reply(fdb, 425, FALSE, "Error"))
                            nextstate = STATE_ERROR;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                        mmsyslog(0, LOGLEVEL,
                                "* main_stor() - transfer_request(\
 REQ_STATUS)");
@@ -1426,22 +1424,22 @@ REQ_STATUS)");
                } else {
                    if (!reply(fdb, 502, FALSE, "Permission denied"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                }
            } else {
                if (!reply(fdb, 550, FALSE, "Not a plain file"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "Invalid filename"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 502, FALSE, "Permission denied"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1532,7 +1530,7 @@ main_stou(clientenv *clenv)
                                } else {
                                    if (!reply(fdb, 425, FALSE, "Error"))
                                        nextstate = STATE_ERROR;
-                                   clenv->errors++;
+                                   REGISTER_ERROR(clenv);
                                    mmsyslog(0, LOGLEVEL,
                                            "* main_stou() - open(%s)",
                                            uniquepath);
@@ -1540,7 +1538,7 @@ main_stou(clientenv *clenv)
                            } else {
                                if (!reply(fdb, 502, FALSE, "Quota exceeded"))
                                    nextstate = STATE_ERROR;
-                               clenv->errors++;
+                               REGISTER_ERROR(clenv);
                                mmsyslog(0, LOGLEVEL,
                                        "%08X Quota exceeded", clenv->id);
                            }
@@ -1548,18 +1546,18 @@ main_stou(clientenv *clenv)
                            if (!reply(fdb, 425, FALSE,
                                        "Transfer already ongoing"))
                                nextstate = STATE_ERROR;
-                           clenv->errors++;
+                           REGISTER_ERROR(clenv);
                        }
                    } else {
                        if (!reply(fdb, 425, FALSE,
                                    "Can't establish data connection"))
                            nextstate = STATE_ERROR;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                    }
                } else {
                    if (!reply(fdb, 425, FALSE, "Error"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                    mmsyslog(0, LOGLEVEL,
                            "* main_stou() - transfer_request(REQ_STATUS)");
                }
@@ -1567,19 +1565,19 @@ main_stou(clientenv *clenv)
                if (!reply(fdb, 425, FALSE,
                            "Coundn't generate unique filename"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
                mmsyslog(0, LOGLEVEL,
                        "* main_stou() - Couldn't generate unique filename");
            }
        } else {
            if (!reply(fdb, 550, FALSE, "Invalid filename"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 502, FALSE, "Permission denied"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1621,7 +1619,7 @@ main_appe(clientenv *clenv)
                                        if (!reply(fdb, 502, FALSE,
                                                    "Quota exceeded"))
                                            nextstate = STATE_ERROR;
-                                       clenv->errors++;
+                                       REGISTER_ERROR(clenv);
                                        mmsyslog(0, LOGLEVEL,
                                                "%08X Quota exceeded",
                                                clenv->id);
@@ -1652,7 +1650,7 @@ main_appe(clientenv *clenv)
                                } else {
                                    if (!reply(fdb, 425, FALSE, "Error"))
                                        nextstate = STATE_ERROR;
-                                   clenv->errors++;
+                                   REGISTER_ERROR(clenv);
                                    mmsyslog(0, LOGLEVEL,
                                            "* main_appe() - open(%s)",
                                            path);
@@ -1661,18 +1659,18 @@ main_appe(clientenv *clenv)
                                if (!reply(fdb, 425, FALSE,
                                            "Transfer already ongoing"))
                                    nextstate = STATE_ERROR;
-                               clenv->errors++;
+                               REGISTER_ERROR(clenv);
                            }
                        } else {
                            if (!reply(fdb, 425, FALSE,
                                        "Can't establish data connection"))
                                nextstate = STATE_ERROR;
-                           clenv->errors++;
+                           REGISTER_ERROR(clenv);
                        }
                    } else {
                        if (!reply(fdb, 425, FALSE, "Error"))
                            nextstate = STATE_ERROR;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                        mmsyslog(0, LOGLEVEL,
                                "* main_appe() - transfer_request(\
 REQ_STATUS)");
@@ -1680,22 +1678,22 @@ REQ_STATUS)");
                } else {
                    if (!reply(fdb, 502, FALSE, "Permission denied"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                }
            } else {
                if (!reply(fdb, 550, FALSE, "Not a plain file"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "Invalid filename"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 502, FALSE, "Permission denied"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1714,7 +1712,7 @@ main_allo(clientenv *clenv)
     } else {
        if (!reply(clenv->fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1736,7 +1734,7 @@ main_rest(clientenv *clenv)
     } else {
        if (!reply(clenv->fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1771,13 +1769,13 @@ main_rnfr(clientenv *clenv)
        } else {
            if (!reply(fdb, 550, FALSE, "No such file or directory"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
 
     } else {
        if (!reply(fdb, 502, FALSE, "Permission denied"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1806,7 +1804,7 @@ main_rnto(clientenv *clenv)
                    } else {
                        if (!reply(fdb, 521, FALSE, "Error renaming file"))
                            nextstate = STATE_ERROR;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                        mmsyslog(0, LOGLEVEL,
                                "* main_rnto() - rename(%s,%s)",
                                clenv->rnfr, path);
@@ -1814,23 +1812,23 @@ main_rnto(clientenv *clenv)
                } else {
                    if (!reply(fdb, 521, FALSE, "File exists"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                }
            } else {
                if (!reply(fdb, 550, FALSE, "Command syntax error"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
            clenv->rnfr = mmstrfree(clenv->rnfr);
        } else {
            if (!reply(fdb, 503, FALSE, "RNFR expected first"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 502, FALSE, "Permission denied"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1861,7 +1859,7 @@ main_abor(clientenv *clenv)
     } else {
        if (!reply(clenv->fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1894,24 +1892,24 @@ main_dele(clientenv *clenv)
                } else {
                    if (!reply(fdb, 521, FALSE, "Error deleting file"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                    mmsyslog(0, LOGLEVEL, "* main_dele() - unlink(%s)",
                            path);
                }
            } else {
                if (!reply(fdb, 550, FALSE, "No such file or directory"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "Command syntax error"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 502, FALSE, "Permission denied"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1937,23 +1935,23 @@ main_rmd(clientenv *clenv)
                    if (!reply(fdb, 521, FALSE,
                                "Error deleting directory (not empty?)"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                    mmsyslog(0, LOGLEVEL, "* main_rmd() - rmdir(%s)", path);
                }
            } else {
                if (!reply(fdb, 550, FALSE, "No such file or directory"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "No such file or directory"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 502, FALSE, "Permission denied"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1978,17 +1976,17 @@ main_mdtm(clientenv *clenv)
            } else {
                if (!reply(fdb, 550, FALSE, "Not a regular file"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "No such file or directory"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "No such file or directory"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -2007,7 +2005,7 @@ main_pwd(clientenv *clenv)
     } else {
        if (!reply(clenv->fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -2040,30 +2038,30 @@ main_mkd(clientenv *clenv)
                        if (!reply(fdb, 521, FALSE,
                                    "Error creating directory"))
                            nextstate = STATE_ERROR;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                        mmsyslog(0, LOGLEVEL, "* main_mkd() - mkdir(%s)",
                                path);
                    }
                } else {
                    if (!reply(fdb, 502, FALSE, "Quota exceeded"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                    mmsyslog(0, LOGLEVEL, "%08X Quota exceeded", clenv->id);
                }
            } else {
                if (!reply(fdb, 550, FALSE, "File exists"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "Command syntax error"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 502, FALSE, "Permission denied"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -2107,17 +2105,17 @@ main_list(clientenv *clenv)
            } else {
                if (!reply(fdb, 425, FALSE, "Transfer already ongoing"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 425, FALSE, "Can't establish data connection"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 425, FALSE, "Error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
        mmsyslog(0, LOGLEVEL,
                "* main_list() - transfer_request(REQ_STATUS)");
     }
@@ -2163,17 +2161,17 @@ main_nlst(clientenv *clenv)
            } else {
                if (!reply(fdb, 425, FALSE, "Transfer already ongoing"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 425, FALSE, "Can't establish data connection"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 425, FALSE, "Error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
        mmsyslog(0, LOGLEVEL,
                "* main_list() - transfer_request(REQ_STATUS)");
     }
@@ -2208,12 +2206,12 @@ main_site(clientenv *clenv)
                } else {
                    if (!reply(fdb, 550, FALSE, "Command syntax error"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                }
            } else {
                if (!reply(fdb, 502, FALSE, "Permission denied"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else if (!(mm_stricmp(args[1], "CHMOD"))) {
            if (clenv->modify && clenv->mumask) {
@@ -2255,33 +2253,33 @@ main_site(clientenv *clenv)
                            if (!reply(fdb, 550, FALSE,
                                        "No such file or directory"))
                                nextstate = STATE_ERROR;
-                           clenv->errors++;
+                           REGISTER_ERROR(clenv);
                        }
                    } else {
                        if (!reply(fdb, 550, FALSE,
                                    "No such file or directory"))
                            nextstate = STATE_ERROR;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                    }
                } else {
                    if (!reply(fdb, 550, FALSE, "Command syntax error"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                }
            } else {
                if (!reply(fdb, 502, FALSE, "Permission denied"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 500, FALSE, "Unknown command"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 500, FALSE, "Unknown command"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -2307,17 +2305,17 @@ main_size(clientenv *clenv)
            } else {
                if (!reply(fdb, 550, FALSE, "Not a regular file"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 550, FALSE, "No such file or directory"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "No such file or directory"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -2346,7 +2344,7 @@ main_stat(clientenv *clenv)
        } else {
            if (!reply(fdb, 214, FALSE, "Invalid path"))
                return (STATE_ERROR);
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        /* Normal ftpd status report */
@@ -2563,6 +2561,8 @@ main(int argc, char **argv)
            &CONF.REMEMBER_CWDS},
        {CAT_BOOL, 0, 0, CAS_UNTOUCHED, "RESOLVE_HOSTS",
            &CONF.RESOLVE_HOSTS},
+       {CAT_BOOL, 0, 0, CAS_UNTOUCHED, "DELAY_ON_ERROR",
+           &CONF.DELAY_ON_ERROR},
        {CAT_END, 0, 0, 0, NULL, NULL}
     };
     CMAP cmap[] = {
@@ -2617,6 +2617,7 @@ main(int argc, char **argv)
     CONF.GBANDWIDTH_OUT = 0;
     CONF.REMEMBER_CWDS = 16;
     CONF.RESOLVE_HOSTS = FALSE;
+    CONF.DELAY_ON_ERROR = FALSE;
 
     /* Read config file */
     if (argc == 2)
@@ -3432,7 +3433,7 @@ handleclient(unsigned long cid, int fd, clientlistnode *clientlnode,
 
                                } else {
                                    /* Unimplemented command for this state */
-                                   clenv->errors++;
+                                   REGISTER_ERROR(clenv);
                                    if (!reply(fdb, states[state].errcode,
                                                FALSE, states[state].errtext))
                                        break;
@@ -3440,7 +3441,7 @@ handleclient(unsigned long cid, int fd, clientlistnode *clientlnode,
 
                            } else {
                                mmsyslog(3, LOGLEVEL, "%08X %s", cid, buffer);
-                               clenv->errors++;
+                               REGISTER_ERROR(clenv);
                                if (!reply(fdb, 500, FALSE, "Unknown command"))
                                    break;
                            }
@@ -3881,7 +3882,7 @@ socket()");
                                reply(clenv->fdb, 425, FALSE,
                                        "Can't establish data connection");
                                fdbflushw(clenv->fdb);
-                               clenv->errors++;
+                               REGISTER_ERROR(clenv);
                                state = 1;
                                break;
                            }
@@ -3897,7 +3898,7 @@ socket()");
                        reply(clenv->fdb, 425, FALSE,
                                "Can't establish data connection");
                        fdbflushw(clenv->fdb);
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                        state = 1;
                        break;
                    }
@@ -3909,7 +3910,7 @@ socket()");
                    reply(clenv->fdb, 425, FALSE,
                            "Can't establish data connection");
                    fdbflushw(clenv->fdb);
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                    state = 1;
                    break;
                }
@@ -3960,7 +3961,7 @@ socket()");
                                reply(clenv->fdb, 425, FALSE,
                                        "Can't establish data connection");
                                fdbflushw(clenv->fdb);
-                               clenv->errors++;
+                               REGISTER_ERROR(clenv);
                                state = 1;
                            }
                        } else state = 3;
index 5cc9563..09a8d61 100644 (file)
@@ -1,4 +1,4 @@
-.\" $Id: mmftpd.conf.5,v 1.1 2002/12/11 10:12:29 mmondor Exp $
+.\" $Id: mmftpd.conf.5,v 1.2 2002/12/12 20:54:21 mmondor Exp $
 .\"
 .\" Copyright (C) 2002, Matthew Mondor
 .\" All rights reserved.
@@ -182,6 +182,12 @@ respectively.
 .It Nm MAX_ERRORS Ar "number"
 Maximum number of bad commands user may issue per session before being dropped.
 .Pp
+.It Nm DELAY_ON_ERROR Ar "boolean"
+If set to TRUE, at each bad command or error (see
+.Ar MAX_ERRORS )
+a delay will be forced before accepting another command from that client.
+At each error the delay will increase by one second.
+.Pp
 .It Nm MAX_IPS Ar "number"
 Total maximum number of simultanious different IP addresses we allow
 connections from.
@@ -277,6 +283,7 @@ LISTEN_IPS              "127.0.0.1"
 LISTEN_PORT             21
 RESOLVE_HOSTS           FALSE
 MAX_ERRORS              16
+DELAY_ON_ERROR          FALSE
 MAX_IPS                 64
 MAX_PER_IP              1
 CONNECTION_RATE         10
index 01775fe..8de6ac0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmftpd.h,v 1.1 2002/12/11 10:12:32 mmondor Exp $ */
+/* $Id: mmftpd.h,v 1.2 2002/12/12 20:54:21 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2002, Matthew Mondor
 #define ASYNC_HASHPW           1
 #define ASYNC_TREESIZE         2
 
+/* Error registration macro */
+#define REGISTER_ERROR(x) do { \
+    (x)->errors++; \
+    if (CONF.DELAY_ON_ERROR) \
+       pth_sleep((x)->errors); \
+} while(0)
+
 
 
 
@@ -127,7 +134,7 @@ typedef struct config {
        MAX_PER_IP, CONNECTION_RATE, CONNECTION_PERIOD, CONTROL_TIMEOUT,
        DATA_TIMEOUT, BANDWIDTH_IN, BANDWIDTH_OUT, GBANDWIDTH_IN,
        GBANDWIDTH_OUT, REMEMBER_CWDS, ASYNC_PROCESSES;
-    bool RESOLVE_HOSTS;
+    bool RESOLVE_HOSTS, DELAY_ON_ERROR;
 } CONFIG;
 
 /* We communicate with our transfer thread using this message structure */
index 0ecce1e..edda901 100644 (file)
@@ -1,4 +1,4 @@
-$Id: ChangeLog,v 1.1 2002/12/11 10:14:49 mmondor Exp $
+$Id: ChangeLog,v 1.2 2002/12/12 20:54:21 mmondor Exp $
 
 
 
@@ -65,6 +65,8 @@ By     : Matthew Mondor
     to run mmstatd.
     The default is to only accept to be started by the superuser and then
     drop privileges.
+  - Configuration file option DELAY_ON_ERROR was added to allow to pause
+    at every user command error. Thanks to Jeroen Oostendorp for the idea.
 * Other
   - Optimized the command matching loop by using fast packed hashes
   - Other optimizations were performed by moving some variables in
index a243d26..a8f0ae7 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: mmpop3d.conf,v 1.1 2002/12/11 10:14:56 mmondor Exp $
+; $Id: mmpop3d.conf,v 1.2 2002/12/12 20:54:21 mmondor Exp $
 ;
 ; mmpop3d mmmail component configuration file (/etc/mmpop3d.conf)
 ; and # are considered comments, and can occur at start or end of line.
@@ -54,6 +54,9 @@ LISTEN_PORT   110
 ; DNS server reliability and service load
 RESOLVE_HOSTS  FALSE
 ;
+; If TRUE, will force a delay when the client performs an error.
+DELAY_ON_ERROR FALSE
+;
 ; Maximum number of bad commands user may issue per session
 MAX_ERRORS     16
 ;
index 185539d..9e630d3 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: mmsmtpd.conf,v 1.1 2002/12/11 10:14:58 mmondor Exp $
+; $Id: mmsmtpd.conf,v 1.2 2002/12/12 20:54:21 mmondor Exp $
 ;
 ; mmsmtpd configuration file (/etc/mmsmtpd.conf)
 ; and # are considered comments, and can happen at start or end of line.
@@ -54,6 +54,9 @@ LISTEN_PORT   25
 ; DNS server reliability and service load
 RESOLVE_HOSTS  FALSE
 ;
+; If TRUE, will force a delay when the client performs an error.
+DELAY_ON_ERROR FALSE
+;
 ; Maximum number of bad commands user may issue per session
 MAX_ERRORS     16
 ;
index ac48b7f..060facb 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmpop3d.c,v 1.1 2002/12/11 10:15:31 mmondor Exp $ */
+/* $Id: mmpop3d.c,v 1.2 2002/12/12 20:54:22 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2002, Matthew Mondor
@@ -73,7 +73,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmpop3d.c,v 1.1 2002/12/11 10:15:31 mmondor Exp $");
+MMRCSID("$Id: mmpop3d.c,v 1.2 2002/12/12 20:54:22 mmondor Exp $");
 
 
 
@@ -205,6 +205,8 @@ main(int argc, char **argv)
            &CONF.GBANDWIDTH_OUT},
        {CAT_BOOL, 0, 0, CAS_UNTOUCHED, "RESOLVE_HOSTS",
            &CONF.RESOLVE_HOSTS},
+       {CAT_BOOL, 0, 0, CAS_UNTOUCHED, "DELAY_ON_ERROR",
+           &CONF.DELAY_ON_ERROR},
        {CAT_END, 0, 0, 0, NULL, NULL}
     };
     CMAP cmap[] = {
@@ -253,6 +255,7 @@ main(int argc, char **argv)
     CONF.GBANDWIDTH_IN = 0;
     CONF.GBANDWIDTH_OUT = 0;
     CONF.RESOLVE_HOSTS = FALSE;
+    CONF.DELAY_ON_ERROR = FALSE;
 
     /* Advertize */
     printf("\r\n+++ %s (%s)\r\n\r\n", DAEMON_NAME, DAEMON_VERSION);
@@ -576,7 +579,7 @@ main_list(clientenv *clenv)
                || clenv->index[i].deleted) {
            if (!reply(fdb, FALSE, "Out of range"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        } else {
            if (!reply(fdb, TRUE, "%d %d", i + 1, clenv->index[i].size))
                nextstate = STATE_ERROR;
@@ -622,13 +625,13 @@ main_retr(clientenv *clenv)
                || clenv->index[i].deleted) {
            if (!reply(fdb, FALSE, "Out of range"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        } else {
            /* Valid message number to retreive */
            if (clenv->index[i].retreived) {
                if (!reply(fdb, FALSE, "Already retreived"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            } else {
                clenv->last = i + 1;
                clenv->retreived++;
@@ -639,7 +642,7 @@ main_retr(clientenv *clenv)
     } else {
        if (!reply(fdb, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -660,7 +663,7 @@ main_dele(clientenv *clenv)
            if (i < 0 || !(i < clenv->messages)) {
                if (!reply(fdb, FALSE, "Out of range"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            } else {
                if (!clenv->index[i].deleted) {
                    clenv->index[i].deleted = TRUE;
@@ -672,18 +675,18 @@ main_dele(clientenv *clenv)
                } else {
                    if (!reply(fdb, FALSE, "Already marked to delete"))
                        nextstate = STATE_ERROR;
-                   clenv->errors++;
+                   REGISTER_ERROR(clenv);
                }
            }
        } else {
            if (!reply(fdb, FALSE, "No messages"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -717,13 +720,13 @@ main_top(clientenv *clenv)
                || clenv->index[i1].deleted) {
            if (!reply(fdb, FALSE, "Out of range"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        } else {
            /* Valid message number to retreive */
            if (clenv->index[i1].retreived) {
                if (!reply(fdb, FALSE, "Already retreived"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            } else {
                clenv->last = i1 + 1;
                if (!do_top(fdb, &clenv->index[i1], i2))
@@ -733,7 +736,7 @@ main_top(clientenv *clenv)
     } else {
        if (!reply(fdb, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -757,13 +760,13 @@ main_page(clientenv *clenv)
                || !clenv->index || clenv->index[i1].deleted) {
            if (!reply(fdb, FALSE, "Out of range"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        } else {
            /* Valid message number to retreive */
            if (clenv->index[i1].retreived) {
                if (!reply(fdb, FALSE, "Already retreived"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            } else {
                clenv->last = i1 + 1;
                if (!do_page(fdb, &clenv->index[i1], i2, i3))
@@ -773,7 +776,7 @@ main_page(clientenv *clenv)
     } else {
        if (!reply(fdb, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1468,7 +1471,7 @@ handleclient(unsigned long id, int fd, clientlistnode *clientlnode,
 
                        } else {
                            /* Unimplemented command for this state */
-                           clenv->errors++;
+                           REGISTER_ERROR(clenv);
                            if (!reply(fdb, states[state].errcode,
                                        states[state].errtext))
                                break;
@@ -1479,7 +1482,7 @@ handleclient(unsigned long id, int fd, clientlistnode *clientlnode,
                        if (!reply(fdb, FALSE,
                                    "Syntax error or unknown command"))
                            break;
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                    }
 
                } else {
index c0f1792..608fd64 100644 (file)
@@ -1,4 +1,4 @@
-.\" $Id: mmpop3d.conf.5,v 1.1 2002/12/11 10:15:35 mmondor Exp $
+.\" $Id: mmpop3d.conf.5,v 1.2 2002/12/12 20:54:22 mmondor Exp $
 .\"
 .\" Copyright (C) 2002, Matthew Mondor
 .\" All rights reserved.
@@ -193,6 +193,12 @@ respectively.
 .It Nm MAX_ERRORS Ar "number"
 Maximum number of bad commands user may issue per session before being dropped.
 .Pp
+.It Nm DELAY_ON_ERROR Ar "boolean"
+If set to TRUE, at each bad command or error (see
+.Ar MAX_ERRORS )
+a delay will be forced before accepting another command from that client.
+At each error the delay will increase by one second.
+.Pp
 .It Nm MAX_IPS Ar "number"
 Total maximum number of simultanious different IP addresses we allow
 connections from.
@@ -272,6 +278,7 @@ ALLOC_BUFFERS           1
 LOG_LEVEL               3
 LISTEN_PORT             110
 MAX_ERRORS              16
+DELAY_ON_ERROR          FALSE
 MAX_IPS                 64
 MAX_PER_IP              1
 CONNECTION_RATE         10
index c5e1b8d..a2e029f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmpop3d.h,v 1.1 2002/12/11 10:15:38 mmondor Exp $ */
+/* $Id: mmpop3d.h,v 1.2 2002/12/12 20:54:22 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2002, Matthew Mondor
 /* Asynchroneous functions we attach */
 #define ASYNC_HASHPW   1
 
+/* Error registration macro */
+#define REGISTER_ERROR(x) do { \
+    (x)->errors++; \
+       if (CONF.DELAY_ON_ERROR) \
+           pth_sleep((x)->errors); \
+} while(0)
+
 
 
 
@@ -82,7 +89,7 @@ typedef struct config {
        MAX_PER_IP, CONNECTION_RATE, CONNECTION_PERIOD, INPUT_TIMEOUT,
        BANDWIDTH_IN, BANDWIDTH_OUT, GBANDWIDTH_IN, GBANDWIDTH_OUT,
        ASYNC_PROCESSES;
-    bool RESOLVE_HOSTS;
+    bool RESOLVE_HOSTS, DELAY_ON_ERROR;
 } CONFIG;
 
 /* For the messages list during the session */
index 924def9..d7d1a06 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmsmtpd.c,v 1.1 2002/12/11 10:15:55 mmondor Exp $ */
+/* $Id: mmsmtpd.c,v 1.2 2002/12/12 20:54:22 mmondor Exp $ */
 
 /*
  * Copyright (C) 2001-2002, Matthew Mondor
@@ -74,7 +74,7 @@
 
 MMCOPYRIGHT("@(#) Copyright (c) 2002\n\
 \tMatthew Mondor. All rights reserved.\n");
-MMRCSID("$Id: mmsmtpd.c,v 1.1 2002/12/11 10:15:55 mmondor Exp $");
+MMRCSID("$Id: mmsmtpd.c,v 1.2 2002/12/12 20:54:22 mmondor Exp $");
 
 
 
@@ -241,6 +241,8 @@ main(int argc, char **argv)
            &CONF.STATFAIL_FULL},
        {CAT_BOOL, 0, 0, CAS_UNTOUCHED, "STATFAIL_TIMEOUT",
            &CONF.STATFAIL_TIMEOUT},
+       {CAT_BOOL, 0, 0, CAS_UNTOUCHED, "DELAY_ON_ERROR",
+           &CONF.DELAY_ON_ERROR},
        {CAT_END, 0, 0, 0, NULL, NULL}
     };
     CMAP cmap[] = {
@@ -304,6 +306,7 @@ main(int argc, char **argv)
     CONF.STATFAIL_FLOOD = TRUE;
     CONF.STATFAIL_FULL = TRUE;
     CONF.STATFAIL_TIMEOUT = TRUE;
+    CONF.DELAY_ON_ERROR = FALSE;
 
     /* Advertize */
     printf("\r\n+++ %s (%s)\r\n\r\n", DAEMON_NAME, DAEMON_VERSION);
@@ -447,7 +450,7 @@ all_rset(clientenv *clenv)
     } else {
        if (!reply(fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -507,7 +510,7 @@ all_help(clientenv *clenv)
        } else {
            if (!reply(fdb, 504, FALSE, "Unknown HELP topic"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
 
     } else {
@@ -557,17 +560,17 @@ all_helo(clientenv *clenv)
            } else {
                if (!reply(fdb, 501, FALSE, "Invalid hostname"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 503, FALSE, "Duplicate HELO, use RSET or proceed"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -607,19 +610,19 @@ all_mail(clientenv *clenv)
            } else {
                if (!reply(fdb, 501, FALSE, "Invalid address"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
 
        } else {
            if (!reply(fdb, 503, FALSE, "Sender already specified"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
 
     } else {
        if (!reply(fdb, 503, FALSE, "Use HELO first"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -817,7 +820,7 @@ within last %ld minute(s))", clenv->id, mnod->posts,
 
     /* Reply with appropriate message */
     if (reason != RCPT_OK)
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     if (!reply(fdb, rcpt_msg[reason].code, FALSE, rcpt_msg[reason].msg))
        nextstate = STATE_ERROR;
 
@@ -841,17 +844,17 @@ all_data(clientenv *clenv)
            } else {
                if (!reply(fdb, 502, FALSE, "Use RCPT first"))
                    nextstate = STATE_ERROR;
-               clenv->errors++;
+               REGISTER_ERROR(clenv);
            }
        } else {
            if (!reply(fdb, 503, FALSE, "Use MAIL and RCPT first"))
                nextstate = STATE_ERROR;
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
        }
     } else {
        if (!reply(fdb, 550, FALSE, "Command syntax error"))
            nextstate = STATE_ERROR;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
     }
 
     return (nextstate);
@@ -1337,12 +1340,12 @@ do_data(clientenv *clenv)
     case FDBRB_MEM:
        mmsyslog(0, LOGLEVEL, "%08X * Out of memory", clenv->id);
        err = DATA_INTERNAL;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
        break;
     case FDBRB_OVERFLOW:
        mmsyslog(0, LOGLEVEL, "%08X * Message size too large", clenv->id);
        err = DATA_OVERFLOW;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
        break;
     case FDBRB_TIMEOUT:
        mmsyslog(0, LOGLEVEL, "%08X * Input timeout", clenv->id);
@@ -1356,7 +1359,7 @@ do_data(clientenv *clenv)
     case CFDBRB_HOPS:
        mmsyslog(0, LOGLEVEL, "%08X * Too many hops", clenv->id);
        err = DATA_HOPS;
-       clenv->errors++;
+       REGISTER_ERROR(clenv);
        break;
     case FDBRB_OK:
        ok = TRUE;
@@ -1445,7 +1448,7 @@ box_msgs=box_msgs+1,box_in=NOW() WHERE box_address='%s'",
            free(query);
        } else {
            mmsyslog(0, LOGLEVEL, "%08X * Out of memory", clenv->id);
-           clenv->errors++;
+           REGISTER_ERROR(clenv);
            ok = FALSE;
        }
     }
@@ -1584,7 +1587,7 @@ handleclient(unsigned long id, int fd, clientlistnode *clientlnode,
 
                        } else {
                            /* Unimplemented command for this state */
-                           clenv->errors++;
+                           REGISTER_ERROR(clenv);
                            if (!reply(fdb, states[state].errcode, FALSE,
                                        states[state].errtext))
                                break;
@@ -1594,7 +1597,7 @@ handleclient(unsigned long id, int fd, clientlistnode *clientlnode,
                        mmsyslog(3, LOGLEVEL, "%08X %s", id, buffer);
                        reply(fdb, 500, FALSE,
                                "Syntax error or unknown command, type HELP");
-                       clenv->errors++;
+                       REGISTER_ERROR(clenv);
                    }
 
                } else {
index 73b3d2c..3499638 100644 (file)
@@ -1,4 +1,4 @@
-.\" $Id: mmsmtpd.conf.5,v 1.1 2002/12/11 10:16:06 mmondor Exp $
+.\" $Id: mmsmtpd.conf.5,v 1.2 2002/12/12 20:54:22 mmondor Exp $
 .\"
 .\" Copyright (C) 2002, Matthew Mondor
 .\" All rights reserved.
@@ -190,6 +190,12 @@ Resolving clients hostnames for logging can make the system slow depending on
 DNS server reliability and service load. boolean should be TRUE or FALSE,
 respectively.
 .Pp
+.It Nm DELAY_ON_ERROR Ar "boolean"
+If set to TRUE, at each bad command or error (see
+.Ar MAX_ERRORS )
+a delay will be forced before accepting another command from that client.
+At each error the delay will increase by one second.
+.Pp
 .It Nm MAX_ERRORS Ar "number"
 Maximum number of bad commands user may issue per session before being dropped.
 .Pp
@@ -392,6 +398,7 @@ ALLOC_BUFFERS           1
 LOG_LEVEL               3
 LISTEN_PORT             25
 MAX_ERRORS              16
+DELAY_ON_ERROR          FALSE
 MAX_IPS                 64
 MAX_PER_IP              1
 CONNECTION_RATE         10
index 9fe0f01..44452fd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: mmsmtpd.h,v 1.1 2002/12/11 10:16:17 mmondor Exp $ */
+/* $Id: mmsmtpd.h,v 1.2 2002/12/12 20:54:22 mmondor Exp $ */
 
 /*
  * Copyright (C) 2000-2002, Matthew Mondor
 /* Asynchroneous functions we attach */
 #define ASYNC_RESQUERY 1
 
+/* Error registration macro */
+#define REGISTER_ERROR(x) do { \
+    (x)->errors++; \
+       if (CONF.DELAY_ON_ERROR) \
+           pth_sleep((x)->errors); \
+} while(0)
+
 
 
 
@@ -102,7 +109,7 @@ typedef struct config {
        FLOOD_EXPIRES, FLOOD_CACHE, ASYNC_PROCESSES;
     bool RESOLVE_HOSTS, RESOLVE_MX_HELO, RESOLVE_MX_MAIL, REQUIRE_HELO,
        FLOOD_PROTECTION, STATFAIL_ADDRESS, STATFAIL_FLOOD, STATFAIL_FULL,
-       STATFAIL_TIMEOUT;
+       STATFAIL_TIMEOUT, DELAY_ON_ERROR;
 } CONFIG;