Code review request

Markus Moeller huaraz at moeller.plus.com
Tue Aug 8 14:55:45 EDT 2006


You could use also proftpd which all its modules, including mod_gss, 
mod_delay,etc ..

Markus


"Philip Prindeville" <philipp at redfish-solutions.com> wrote in message 
news:44D800E8.5060703 at redfish-solutions.com...
> Ok, here it is again.
>
>
> Jeffrey Hutzelman wrote:
>
>>It is, but there was no attached patch.
>>-----Original Message-----
>>From: Philip Prindeville <philipp at redfish-solutions.com>
>>Date: Monday, Aug 7, 2006 9:11 pm
>>Subject: Re: Code review request
>>
>>
>>
>>> [snip]
>>>
>>>Yes, the attached message contained diffs of a patch I wished to have 
>>>integrated into the KRB5 source release.
>>>
>>>The group web page says that krbdev is the appropriate place for such 
>>>postings.  Is that not the case?
>>>
>>>-Philip
>>>
>>>
>>>
>


--------------------------------------------------------------------------------


> --- src/appl/gssftp/ftpd/ftpd.c.graylist 2006-06-07 
> 20:13:07.000000000 -0600
> +++ src/appl/gssftp/ftpd/ftpd.c 2006-06-07 20:13:08.000000000 -0600
> @@ -101,6 +101,10 @@
> #endif
> #include "pathnames.h"
> #include <libpty.h>
> +#ifdef GRAYLIST
> +#include <db.h>
> +#include <limits.h>
> +#endif
>
> #ifdef NEED_SETENV
> extern int setenv(char *, char *, int);
> @@ -222,6 +226,32 @@
> char rhost_addra[16];
> char *rhost_sane;
>
> +#ifdef GRAYLIST
> +const char *gl_path= "/etc/ftpgraylist.db";
> +int gl_initial = 0;
> +int gl_scale = 0;
> +int gl_max = 0;
> +
> +typedef struct {
> + time_t start;
> + unsigned shutout;
> +} graylist_t;
> +
> +#define RET_NOTFOUND RET_SPECIAL
> +
> +#define GL_INIT_MIN 5
> +#define GL_INIT_MAX 7200
> +
> +#define GL_SCALE_MIN 2
> +#define GL_SCALE_MAX 100
> +#define GL_SCALE_DFLT 2
> +
> +#define GL_CAP_MIN 300
> +#define GL_CAP_MAX (365 * 24 * 3600)
> +
> +static unsigned gl_connect(struct in_addr, int);
> +#endif
> +
> /* Defines for authlevel */
> #define AUTHLEVEL_NONE 0
> #define AUTHLEVEL_AUTHENTICATE 1
> @@ -277,6 +307,18 @@
> }
> #endif
>
> +#ifdef KRB5_KRB4_COMPAT
> +#define KRB5_OPTIONS "s:"
> +#else
> +#define KRB5_OPTIONS ""
> +#endif
> +
> +#ifdef GRAYLIST
> +#define GL_OPTIONS "G:g:S:"
> +#else
> +#define GL_OPTIONS
> +#endif
> +
> int stripdomain = 1;
> int maxhostlen = 0;
> int always_ip = 0;
> @@ -290,11 +332,11 @@
>  int addrlen, c, on = 1, tos, port = -1;
>  extern char *optarg;
>  extern int optopt;
> -#ifdef KRB5_KRB4_COMPAT
> - char *option_string = "AaCcdlp:r:s:T:t:U:u:vw:";
> -#else /* !KRB5_KRB4_COMPAT */
> - char *option_string = "AaCcdlp:r:T:t:U:u:vw:";
> -#endif /* KRB5_KRB4_COMPAT */
> + char *option_string = "AaCcdlp:r:T:t:U:u:vw:" KRB5_OPTIONS
> + GL_OPTIONS;
> +#ifdef GRAYLIST
> + unsigned expire;
> +#endif
>  ftpusers = _PATH_FTPUSERS_DEFAULT;
>
> #ifdef KRB5_KRB4_COMPAT
> @@ -420,6 +462,29 @@
>  }
>  break;
>  }
> +#ifdef GRAYLIST
> + case 'G':
> + gl_max = atoi(optarg);
> + if (gl_max < GL_CAP_MIN || gl_max > GL_CAP_MAX) {
> + fprintf(stderr, "ftpd: bad arg to -G\n");
> + exit(1);
> + }
> + break;
> + case 'g':
> + gl_initial = atoi(optarg);
> + if (gl_initial < GL_INIT_MIN || gl_initial > GL_INIT_MAX) {
> + fprintf(stderr, "ftpd: bad arg to -g\n");
> + exit(1);
> + }
> + break;
> + case 'S':
> + gl_scale = atoi(optarg);
> + if (gl_scale < GL_SCALE_MIN || gl_scale > GL_SCALE_MAX) {
> + fprintf(stderr, "ftpd: bad arg to -S\n");
> + exit(1);
> + }
> + break;
> +#endif
>  default:
>  fprintf(stderr, "ftpd: Unknown flag -%c ignored.\n",
>       (char)optopt);
> @@ -427,6 +492,21 @@
>  }
>  }
>
> +#ifdef GRAYLIST
> + if (!gl_scale && gl_initial)
> + gl_scale = GL_SCALE_DFLT;
> + if (gl_max && !gl_initial) {
> + fprintf(stderr, "ftpd: -G must be used with -g\n");
> + exit(1);
> + } else if (gl_initial && !gl_max) {
> + gl_max = gl_initial * (gl_scale * gl_scale * gl_scale *
> + gl_scale * gl_scale);
> + } else if (gl_initial > gl_max) {
> + fprintf(stderr, "ftpd: -g arg must be less than -G arg\n");
> + exit(1);
> + }
> +#endif
> +
>  if (port != -1) {
>  struct sockaddr_in sin4;
>  int s, ns, sz;
> @@ -538,6 +618,15 @@
>  stru = STRU_F;
>  mode = MODE_S;
>  tmpline[0] = '\0';
> +
> +#ifdef GRAYLIST
> + expire = gl_connect(his_addr.sin_addr, 1);
> + if (expire != 0) {
> + reply(530, "Client graylisted for %u seconds.", expire);
> + dologout(0);
> + }
> +#endif
> +
>  (void) gethostname(hostname, sizeof (hostname));
>  reply(220, "%s FTP server (%s) ready.", hostname, version);
>  (void) setjmp(errcatch);
> @@ -909,6 +998,212 @@
>  guest = 0;
> }
>
> +#ifdef GRAYLIST
> +static void
> +gl_badlogin(addr)
> +struct in_addr addr;
> +{
> + DB *db;
> + DBT key, content;
> + graylist_t rec;
> + time_t now;
> + int status;
> +
> + /* feature is disabled */
> + if (!gl_initial)
> + return;
> +
> + syslog(LOG_DEBUG, "graylist: badlogin %s", inet_ntoa(addr));
> +
> + db = dbopen(gl_path, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
> + if (!db) {
> + syslog(LOG_ERR, "graylist: can't open database (errno %d)",
> +        errno);
> + return;
> + }
> +
> + key.data = &addr;
> + key.size = sizeof(addr);
> + status = db->get(db, &key, &content, 0);
> +
> + time(&now);
> +
> + switch (status) {
> + case RET_SUCCESS:
> + memcpy(&rec, content.data, content.size);
> + /* if the graylist hasn't expired, then increment it. */
> + if (now < rec.start + gl_max) {
> + rec.shutout *= gl_scale;
> + if (rec.shutout > gl_max)
> + rec.shutout = gl_max;
> + break;
> + }
> + /* FALLTHRU */
> + case RET_NOTFOUND:
> + rec.shutout = gl_initial;
> + break;
> + case RET_ERROR:
> + /* for now, failure isn't bad because we're exiting
> + * anyway... but we might want to fail more dramatically
> + * so that the system administrator takes notice.
> + */
> + syslog(LOG_ERR, "graylist: get (%s) failed (errno %d)",
> +        inet_ntoa(addr), errno);
> + (void)db->close(db);
> + return;
> + }
> +
> + /* reset the timer... */
> + rec.start = now;
> +
> + syslog(LOG_INFO, "graylisting %s for %u seconds", inet_ntoa(addr),
> +        rec.shutout);
> +
> + content.data = &rec;
> + content.size = sizeof(rec);
> + status = db->put(db, &key, &content, 0);
> +
> + switch (status) {
> + case RET_SUCCESS:
> + break;
> + case RET_ERROR:
> + syslog(LOG_ERR, "graylist: put (%s) failed (errno %d)",
> +        inet_ntoa(addr), errno);
> + break;
> + }
> +
> + (void)db->close(db);
> +}
> +
> +static unsigned
> +gl_connect(addr, punish)
> +struct in_addr addr;
> +int punish;
> +{
> + DB *db;
> + DBT key, content;
> + graylist_t rec;
> + time_t now, expire;
> + unsigned interval;
> + int status;
> +
> + /* feature is disabled */
> + if (!gl_initial)
> + return 0;
> +
> + syslog(LOG_DEBUG, "graylist: connect %s, %d", inet_ntoa(addr), punish);
> +
> + db = dbopen(gl_path, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
> + if (!db) {
> + syslog(LOG_ERR, "graylist: can't open database (errno %d)",
> +        errno);
> + return UINT_MAX;
> + }
> +
> + key.data = &addr;
> + key.size = sizeof(addr);
> + status = db->get(db, &key, &content, 0);
> +
> + time(&now);
> +
> + switch (status) {
> + case RET_SUCCESS:
> + /* handled outside switch */
> + break;
> + case RET_NOTFOUND:
> +ok: db->close(db);
> + return 0;
> + case RET_ERROR:
> + syslog(LOG_ERR, "graylist: get (%s) failed (errno %d)",
> +        inet_ntoa(addr), errno);
> + (void)db->close(db);
> + return UINT_MAX;
> + }
> +
> + memcpy(&rec, content.data, content.size);
> +
> + expire = rec.start + rec.shutout;
> +
> + /* we're past the expiry... but we don't delete the record; it
> + * can only get expunged by a successful login
> + */
> + if (expire <= now)
> + goto ok;
> +
> + /* do we spank them for connecting before the graylist expires? */
> + if (punish) {
> + rec.start = now;
> + rec.shutout *= gl_scale;
> + if (rec.shutout > gl_max)
> + rec.shutout = gl_max;
> +
> + content.data = &rec;
> + content.size = sizeof(rec);
> + status = db->put(db, &key, &content, 0);
> +
> + switch (status) {
> + case RET_SUCCESS:
> + break;
> + case RET_ERROR:
> + syslog(LOG_ERR, "graylist: put (%s) failed (errno %d)",
> +        inet_ntoa(addr), errno);
> + db->close(db);
> + return UINT_MAX;
> + }
> + /* update expiry to reflect spanking */
> + expire = rec.start + rec.shutout;
> + }
> +
> + syslog(LOG_INFO, "graylisted host %s %shas %u seconds remaining",
> +        inet_ntoa(addr), (punish ? "now " : ""), expire - now);
> +
> + (void)db->close(db);
> +
> + /* how long before they can retry */
> + return (expire - now);
> +}
> +
> +static void
> +gl_unblock(addr)
> +struct in_addr addr;
> +{
> + DB *db;
> + DBT key;
> + time_t now, expire;
> + int status;
> +
> + /* feature is disabled */
> + if (!gl_initial)
> + return;
> +
> + syslog(LOG_DEBUG, "graylist: authenticated %s", inet_ntoa(addr));
> +
> + db = dbopen(gl_path, O_CREAT | O_RDWR, 0600, DB_HASH, NULL);
> + if (!db) {
> + syslog(LOG_ERR, "graylist: can't open database (errno %d)",
> +        errno);
> + return;
> + }
> +
> + key.data = &addr;
> + key.size = sizeof(addr);
> + status = db->del(db, &key, 0);
> +
> + switch (status) {
> + case RET_SUCCESS:
> + case RET_NOTFOUND:
> + break;
> + case RET_ERROR:
> + syslog(LOG_ERR, "graylist: del (%s) failed (errno %d)",
> +        inet_ntoa(addr), errno);
> + (void)db->close(db);
> + return;
> + }
> +
> + (void)db->close(db);
> +}
> +#endif
> +
> static int
> kpass(name, passwd)
> char *name, *passwd;
> @@ -1076,6 +1371,9 @@
>  syslog(LOG_NOTICE,
>         "repeated login failures from %s (%s)",
>         rhost_addra, remotehost);
> +#ifdef GRAYLIST
> + gl_badlogin(his_addr.sin_addr);
> +#endif
>  dologout(0);
>  }
>  reply(530, "Login incorrect.");
> @@ -1084,6 +1382,10 @@
>  }
>  login_attempts = 0; /* this time successful */
>
> +#ifdef GRAYLIST
> + gl_unblock(his_addr.sin_addr);
> +#endif
> +
>  login(passwd, 0);
>  return;
> }
> --- src/appl/gssftp/ftpd/ftpd.M.graylist 2006-06-01 
> 15:58:00.000000000 -0600
> +++ src/appl/gssftp/ftpd/ftpd.M 2006-06-01 16:25:33.000000000 -0600
> @@ -38,6 +38,7 @@
> .B ftpd
> [\fB\-A \fP|\fB -a\fP] [\fB\-C\fP] [\fB\-c\fP] [\fB\-d\fP] [\fB\-l\fP]
> [\fB\-v\fP] [\fB\-T\fP \fImaxtimeout\fP] [\fB\-t\fP \fItimeout\fP]
> +[\fB\-g\fP \fIinitialgraylist \fP [\fB-G\fP \fImaxgraylist\fP] [\fB-S\fP 
> \fIscalefactor\fP]
> [\fB\-p\fP \fIport\fP] [\fB\-U\fP \fIftpusers-file\fP] [\fB\-u\fP 
> \fIumask\fP]
> [\fB\-r\fP \fIrealm-file\fP] [\fB\-s\fP \fIsrvtab\fP]
> [\fB\-w\fP{\fBip\fP|\fImaxhostlen\fP[\fB,\fP{\fBstriplocal\fP|\fBnostriplocal\fP}]}]
> @@ -116,6 +117,25 @@
> file to use.  The default value is normally
> .IR /etc/ftpusers .
> .TP
> +\fB\-g\fP \fIinitialgraylist\fP
> +Sets the initial time to graylist a user following 3 successive failed
> +logins on the same connection.  Should be in the range of 5..300.
> +.TP
> +\fB-G\fP \fImaxgraylist\fP
> +Sets the maximum time to graylist a user should he attempt to reconnect
> +before the graylist expires, or fail to login correctly 3 times on the 
> same
> +connection before the maximum time has expired (but after the current
> +graylist interval expired).  Should be in the range of 300..31536000.
> +If unspecified, it defaults to the \fIinitialgraylist\fP multipled by the
> +scalefactor to the fifth power.
> +.TP
> +\fB-S\fP \fIscalefactor\fP
> +Sets the scaling factor to increase the graylist period by should the
> +user attempt to connect before the graylist expires.  That is, if the
> +user connects before the current graylist expires, then the
> +current graylist will be increased by \fIscalefactor\fP times.  Should
> +be in the range of 2..100.  If unspecified, defaults to 2.
> +.TP
> \fB\-u\fP \fIumask\fP
> Sets the umask for the ftpd process.  The default value is normally 027.
> .TP
>


--------------------------------------------------------------------------------


> _______________________________________________
> krbdev mailing list             krbdev at mit.edu
> https://mailman.mit.edu/mailman/listinfo/krbdev
> 






More information about the krbdev mailing list