diff options
author | mharo <mharo@FreeBSD.org> | 2001-02-12 05:26:53 +0800 |
---|---|---|
committer | mharo <mharo@FreeBSD.org> | 2001-02-12 05:26:53 +0800 |
commit | ac9244809d9e40538e249613b80ab5af150ed979 (patch) | |
tree | f58ff2dcedfdfc3e24418738b76b2c1a22e01d47 /ftp | |
parent | 9b877bef5913cd5d71277a11410e293a11b14bbd (diff) | |
download | freebsd-ports-gnome-ac9244809d9e40538e249613b80ab5af150ed979.tar.gz freebsd-ports-gnome-ac9244809d9e40538e249613b80ab5af150ed979.tar.zst freebsd-ports-gnome-ac9244809d9e40538e249613b80ab5af150ed979.zip |
update to 1.2.0rc3
Submitted by: Anders Nordby <anders@fix.no>
Diffstat (limited to 'ftp')
-rw-r--r-- | ftp/proftpd-devel/Makefile | 16 | ||||
-rw-r--r-- | ftp/proftpd-devel/distinfo | 4 | ||||
-rw-r--r-- | ftp/proftpd-devel/files/patch-ae | 115 | ||||
-rw-r--r-- | ftp/proftpd-devel/files/patch-ak | 12 | ||||
-rw-r--r-- | ftp/proftpd-devel/files/patch-ba | 253 | ||||
-rw-r--r-- | ftp/proftpd-devel/files/patch-bb | 1023 | ||||
-rw-r--r-- | ftp/proftpd-devel/files/patch-bc | 19 | ||||
-rw-r--r-- | ftp/proftpd-devel/files/patch-bd | 21 | ||||
-rw-r--r-- | ftp/proftpd-devel/files/patch-be | 21 | ||||
-rw-r--r-- | ftp/proftpd/Makefile | 16 | ||||
-rw-r--r-- | ftp/proftpd/distinfo | 4 | ||||
-rw-r--r-- | ftp/proftpd/files/patch-ae | 115 | ||||
-rw-r--r-- | ftp/proftpd/files/patch-ak | 12 | ||||
-rw-r--r-- | ftp/proftpd/files/patch-ba | 253 | ||||
-rw-r--r-- | ftp/proftpd/files/patch-bb | 1023 | ||||
-rw-r--r-- | ftp/proftpd/files/patch-bc | 19 | ||||
-rw-r--r-- | ftp/proftpd/files/patch-bd | 21 | ||||
-rw-r--r-- | ftp/proftpd/files/patch-be | 21 |
18 files changed, 2822 insertions, 146 deletions
diff --git a/ftp/proftpd-devel/Makefile b/ftp/proftpd-devel/Makefile index a2ce7f485de1..b9c44d2db57d 100644 --- a/ftp/proftpd-devel/Makefile +++ b/ftp/proftpd-devel/Makefile @@ -6,21 +6,20 @@ # PORTNAME= proftpd -PORTVERSION= 1.2.0rc2 -PORTREVISION= 1 +PORTVERSION= 1.2.0rc3 CATEGORIES= ftp MASTER_SITES= ftp://ftp.tos.net/pub/proftpd/ \ ftp://ftp.stikman.com/pub/proftpd/ \ ftp://ftp.linux.co.uk/pub/packages/proftpd/ \ ftp://ftp.drenik.net/linux/ftp/proftpd/ -DISTNAME= ${PORTNAME}-1.2.0rc2 +DISTNAME= ${PORTNAME}-1.2.0rc3 MAINTAINER= mharo@FreeBSD.org .if defined(WITH_LDAP) MASTER_SITES+= http://www.horde.net/~jwm/software/proftpd-ldap/ -MOD_LDAP= mod_ldap-2.6.1.tar.gz -DISTFILES= ${DISTNAME}.${EXTRACT_SUFX} ${MOD_LDAP} +MOD_LDAP= mod_ldap-2.7.4.tar.gz +DISTFILES= ${DISTNAME}${EXTRACT_SUFX} ${MOD_LDAP} .endif MAN1= ftpcount.1 ftpwho.1 @@ -34,7 +33,7 @@ CONFIGURE_ARGS= --localstatedir=/var/run \ --disable-sendfile #allow user to override -MODULES?= mod_ratio:mod_readme:mod_tar +MODULES?= mod_ratio:mod_readme .if defined(WITH_LDAP) MODULES:=$(MODULES):mod_ldap @@ -42,6 +41,11 @@ BUILD_DEPENDS+= ${LOCALBASE}/lib/libldap.a:${PORTSDIR}/net/openldap CONFIGURE_ENV+= CFLAGS="-I/usr/local/include -g" LDFLAGS=-L/usr/local/lib .endif +# Currently not supported by the ProFTPd project, but it's patched in with +# bugfixes as well. For myself (anders@fix.no): +# patch-bc: bugid 330 (cached passwords not cleared properly) +# patch-bd: bugid 405 (sqlauthorative broken) +# patch-be: bugid 457 (speed improvement) .if defined(WITH_MYSQL) MODULES:=$(MODULES):mod_sqlpw:mod_mysql LIB_DEPENDS+= mysqlclient.10:${PORTSDIR}/databases/mysql323-client diff --git a/ftp/proftpd-devel/distinfo b/ftp/proftpd-devel/distinfo index a8e3849d8fdb..3a77685f3ed8 100644 --- a/ftp/proftpd-devel/distinfo +++ b/ftp/proftpd-devel/distinfo @@ -1,2 +1,2 @@ -MD5 (proftpd-1.2.0rc2.tar.gz) = 13e48f0f4006738ffb9aa7c28ab0ae63 -MD5 (mod_ldap-2.6.1.tar.gz) = 0e866a3137641e20e546543ed1c91760 +MD5 (proftpd-1.2.0rc3.tar.gz) = 0b2b32cec7138cdc1ba4b2a99148bb93 +MD5 (mod_ldap-2.7.4.tar.gz) = 7b3e948d89d2089b5c0b03fb9d22c050 diff --git a/ftp/proftpd-devel/files/patch-ae b/ftp/proftpd-devel/files/patch-ae index eb59e14d9b3f..50db35749dd1 100644 --- a/ftp/proftpd-devel/files/patch-ae +++ b/ftp/proftpd-devel/files/patch-ae @@ -1,6 +1,6 @@ ---- modules/mod_auth.c.orig Fri Jul 28 10:51:59 2000 -+++ modules/mod_auth.c Fri Jul 28 10:52:17 2000 -@@ -72,7 +72,7 @@ +--- modules/mod_auth.c.old Sun Feb 11 19:42:37 2001 ++++ modules/mod_auth.c Sun Feb 11 19:43:18 2001 +@@ -94,7 +94,7 @@ "closing control connection.", TimeoutLogin); @@ -9,7 +9,7 @@ (void*) 0, NULL); /* should never be reached */ -@@ -608,7 +608,7 @@ +@@ -630,7 +630,7 @@ c = _auth_resolve_user(p,&user,&ourname,&anonname); if(!user) { @@ -18,7 +18,7 @@ origuser); goto auth_failure; } -@@ -617,7 +617,7 @@ +@@ -639,7 +639,7 @@ aclp = login_check_limits(main_server->conf,FALSE,TRUE,&i); if((pw = auth_getpwnam(p,user)) == NULL) { @@ -27,7 +27,7 @@ goto auth_failure; } -@@ -678,14 +678,14 @@ +@@ -700,14 +700,14 @@ } if(!login_check_limits(c->subset,FALSE,TRUE,&i) || (!aclp && !i) ){ @@ -44,7 +44,7 @@ origuser); goto auth_failure; } -@@ -702,7 +702,7 @@ +@@ -724,7 +724,7 @@ if(c && origuser && strcasecmp(user,origuser) && get_param_int(c->subset,"AuthUsingAlias",FALSE) == 1) { user_name = origuser; @@ -53,7 +53,7 @@ user, user_name); } -@@ -730,22 +730,22 @@ +@@ -752,22 +752,22 @@ switch(authcode) { case AUTH_NOPWD: @@ -80,7 +80,7 @@ user); goto auth_failure; -@@ -768,12 +768,12 @@ +@@ -790,12 +790,12 @@ auth_setgrent(p); if(!_auth_check_shell((c ? c->subset : main_server->conf),pw->pw_shell)) { @@ -95,7 +95,7 @@ user, FTPUSERS_PATH); goto auth_failure; } -@@ -845,7 +845,7 @@ +@@ -870,7 +870,7 @@ if(!login_check_limits((c ? c->subset : main_server->conf),FALSE,TRUE,&i)) { @@ -104,7 +104,7 @@ origuser); goto auth_failure; } -@@ -860,7 +860,7 @@ +@@ -885,7 +885,7 @@ if(c && c->subset) resolve_anonymous_dirs(c->subset); @@ -113,61 +113,70 @@ (c != NULL) ? "ANON" : "USER", origuser); -@@ -1172,7 +1172,7 @@ - - if(failnopwprompt) { - if(!user) { -- log_pri(LOG_NOTICE, "USER %s (Login failed): Not a UserAlias.", -+ log_pri(LOG_INFO, "USER %s (Login failed): Not a UserAlias.", - origuser); - send_response(R_530,"Login incorrect."); - end_login(0); -@@ -1189,7 +1189,7 @@ - - if(c) { - if(!login_check_limits(c->subset,FALSE,TRUE,&i) || (!aclp && !i) ) { -- log_auth(LOG_NOTICE, "ANON %s: Limit access denies login.", -+ log_auth(LOG_INFO, "ANON %s: Limit access denies login.", - origuser); - send_response(R_530,"Login incorrect."); - end_login(0); -@@ -1197,7 +1197,7 @@ - } - - if(!c && !aclp) { -- log_auth(LOG_NOTICE, "USER %s: Limit access denies login.", origuser); -+ log_auth(LOG_INFO, "USER %s: Limit access denies login.", origuser); - send_response(R_530,"Login incorrect."); +@@ -1267,7 +1267,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); + +- log_auth(LOG_NOTICE, "Connection refused (max clients for class %s).", ++ log_auth(LOG_INFO, "Connection refused (max clients for class %s).", + session.class->name); + end_login(0); - } -@@ -1269,7 +1269,7 @@ - "Too many users in your class, " - "please try again later."); - -- log_auth(LOG_NOTICE, "Connection refused (max clients for class %s).", -+ log_auth(LOG_INFO, "Connection refused (max clients for class %s).", - session.class->name); - - end_login(0); -@@ -1304,7 +1304,7 @@ - send_response(R_530,"%s", - sreplace(cmd->tmp_pool,maxstr,"%m",maxn,NULL)); +@@ -1299,7 +1299,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); - log_auth(LOG_NOTICE, "Connection refused (max clients per host %d).", + log_auth(LOG_INFO, "Connection refused (max clients per host %d).", max); end_login(0); -@@ -1330,7 +1330,7 @@ - if(cur >= max) { +@@ -1324,7 +1324,7 @@ send_response(R_530, "%s", sreplace(cmd->tmp_pool, maxstr, "%m", maxn, NULL)); + - log_auth(LOG_NOTICE, "Connection refused (max clients %d).", max); + log_auth(LOG_INFO, "Connection refused (max clients %d).", max); + + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); +@@ -1354,7 +1354,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); + +- log_auth(LOG_NOTICE, "Connection refused (max clients per host %d).", ++ log_auth(LOG_INFO, "Connection refused (max clients per host %d).", + max); + end_login(0); - } +@@ -1401,7 +1401,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); + +- log_pri(LOG_NOTICE, "USER %s (Login failed): Not a UserAlias.", ++ log_pri(LOG_INFO, "USER %s (Login failed): Not a UserAlias.", + origuser); + send_response(R_530,"Login incorrect."); -@@ -1411,7 +1411,7 @@ +@@ -1422,7 +1422,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); + +- log_auth(LOG_NOTICE, "ANON %s: Limit access denies login.", ++ log_auth(LOG_INFO, "ANON %s: Limit access denies login.", + origuser); + send_response(R_530, "Login incorrect."); + +@@ -1434,7 +1434,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); + +- log_auth(LOG_NOTICE, "USER %s: Limit access denies login.", origuser); ++ log_auth(LOG_INFO, "USER %s: Limit access denies login.", origuser); + send_response(R_530, "Login incorrect."); + + end_login(0); +@@ -1528,7 +1528,7 @@ if(++auth_tries >= max) { send_response(R_530,"Login incorrect"); diff --git a/ftp/proftpd-devel/files/patch-ak b/ftp/proftpd-devel/files/patch-ak deleted file mode 100644 index 0d8bb08fee5b..000000000000 --- a/ftp/proftpd-devel/files/patch-ak +++ /dev/null @@ -1,12 +0,0 @@ ---- modules/mod_xfer.c.orig Mon Jul 31 16:49:19 2000 -+++ modules/mod_xfer.c Mon Jul 31 16:50:02 2000 -@@ -268,7 +268,8 @@ - - /* No PORT command has been issued. - */ -- if(session.d != NULL || !(session.flags & SF_PORT)) { -+ if(!(session.flags & SF_PASSIVE) && -+ (session.d != NULL || !(session.flags & SF_PORT))) { - add_response_err(R_503, "No PORT command issued first."); - return ERROR(cmd); - } diff --git a/ftp/proftpd-devel/files/patch-ba b/ftp/proftpd-devel/files/patch-ba new file mode 100644 index 000000000000..b1d054b52edc --- /dev/null +++ b/ftp/proftpd-devel/files/patch-ba @@ -0,0 +1,253 @@ +--- contrib/mod_mysql.c.old Sun Feb 11 19:47:54 2001 ++++ contrib/mod_mysql.c Sun Feb 11 19:45:37 2001 +@@ -0,0 +1,250 @@ ++/* ++ * ProFTPD: mod_mysql -- Support for connecting to MySQL databases. ++ * Time-stamp: <1999-10-04 03:21:21 root> ++ * Copyright (c) 1998-1999 Johnie Ingram. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#define MOD_MYSQL_VERSION "mod_mysql/2.0" ++ ++/* -- DO NOT MODIFY THE LINE BELOW UNLESS YOU FEEL LIKE IT -- ++ * $Libraries: -lm -lmysqlclient $ ++ */ ++ ++/* This is mod_mysql, contrib software for proftpd 1.2.0pre3 and above. ++ For more information contact Johnie Ingram <johnie@netgod.net>. ++ ++ History Log: ++ ++ * 1999-09-19: v2.0: Most directives split into mod_sql; invented API. ++ ++*/ ++ ++#include "conf.h" ++#include <mysql.h> ++ ++/* *INDENT-OFF* */ ++ ++static MYSQL mod_mysql_server; ++static MYSQL *mysqldb = 0; ++ ++/* Maximum username field to expect, etc. */ ++#define ARBITRARY_MAX 128 ++ ++static struct ++{ ++ char *sql_host; /* Data for connecting, set by MySQLInfo. */ ++ char *sql_user; ++ char *sql_pass; ++ char *sql_dbname; ++ ++ int ok; ++ int opens; ++} g; ++ ++/* *INDENT-ON* */ ++ ++/* **************************************************************** */ ++ ++MODRET ++sql_cmd_close (cmd_rec * cmd) ++{ ++ log_debug (DEBUG5, "mysql: close [%i] for %s", g.opens, cmd->argv[0]); ++ ++ if (!g.ok || g.opens--) ++ return DECLINED (cmd); ++ ++ if (mysqldb) ++ { ++ log_debug (DEBUG4, "mysql: disconnecting: %s", mysql_stat (mysqldb)); ++ mysql_close (mysqldb); ++ } ++ mysqldb = NULL; ++ return DECLINED (cmd); ++} ++ ++MODRET ++sql_cmd_open (cmd_rec * cmd) ++{ ++ if (!g.ok) ++ return DECLINED (cmd); ++ ++ g.opens++; ++ log_debug (DEBUG5, "mysql: open [%i] for %s", g.opens, cmd->argv[0]); ++ if (g.opens > 1) ++ return HANDLED (cmd); ++ ++ if (!(mysqldb = mysql_connect (&mod_mysql_server, g.sql_host, ++ g.sql_user, g.sql_pass))) ++ { ++ log_pri (LOG_ERR, "mysql: client %s connect FAILED to %s@%s", ++ mysql_get_client_info (), g.sql_user, g.sql_host); ++ g.ok = FALSE; ++ g.opens = 0; ++ return DECLINED (cmd); ++ } ++ log_debug (DEBUG5, "mysql: connect OK %s -> %s (%s@%s)", ++ mysql_get_client_info (), mysql_get_server_info (mysqldb), ++ g.sql_user, g.sql_host); ++ ++ return HANDLED (cmd); ++} ++ ++MODRET ++_do_query (cmd_rec * cmd, const char *query, int update) ++{ ++ int error = 1; ++ ++ if (!g.ok) ++ return DECLINED (cmd); ++ ++ block_signals (); ++ ++ /* This forces a quick ping of the remote server, so we know if its there. */ ++ if (mysqldb) ++ mysql_select_db (mysqldb, g.sql_dbname); ++ ++ if (!mysqldb ++ || ((error = mysql_query (mysqldb, query)) ++ && !strcasecmp (mysql_error (mysqldb), "mysql server has gone"))) ++ { ++ /* We need to restart the server link. */ ++ if (mysqldb) ++ log_pri (LOG_ERR, "mysql: server has wandered off (%s/%s)", ++ g.sql_host, g.sql_dbname); ++ sql_cmd_open (cmd); ++ if (!mysqldb) ++ return DECLINED (cmd); ++ error = mysql_select_db (mysqldb, g.sql_dbname) ++ || mysql_query (mysqldb, query); ++ } ++ ++ unblock_signals (); ++ ++ if (error) ++ { ++ log_debug (DEBUG4, "mysql: %s failed: \"%s\": %s", ++ (update) ? "update" : "select", ++ query, mysql_error (mysqldb)); ++ return DECLINED (cmd); ++ } ++ ++ log_debug (DEBUG5, "mysql: %s OK: [%s] \"%s\"", ++ (update) ? "update" : "select", g.sql_dbname, query); ++ return HANDLED (cmd); ++} ++ ++MODRET ++sql_cmd_update (cmd_rec * cmd) ++{ ++ return _do_query (cmd, cmd->argv[1], TRUE); ++} ++ ++MODRET ++sql_cmd_select (cmd_rec * cmd) ++{ ++ MODRET mr; ++ MYSQL_RES *result; ++ MYSQL_ROW sql_row; ++ int i, j; ++ ++ mr = _do_query (cmd, cmd->argv[1], FALSE); ++ if (!MODRET_ISHANDLED (mr)) ++ return DECLINED (mr); ++ ++ if ((result = mysql_store_result (mysqldb))) ++ { ++ int rcount = mysql_num_rows (result); ++ int fcount = mysql_num_fields (result); ++ int count = rcount * fcount; ++ ++ char **data = pcalloc (cmd->tmp_pool, sizeof (char *) * (count + 1)); ++ for (i = 0, count = 0; i < rcount; i++) ++ { ++ sql_row = mysql_fetch_row (result); ++ for (j = 0; j < fcount; j++) ++ data[count++] = pstrdup (cmd->tmp_pool, sql_row[j]); ++ } ++ mysql_free_result (result); ++ data[count] = NULL; ++ mr->data = data; ++ } ++ return mr; ++} ++ ++static authtable mysql_authtab[] = { ++ {0, "dbd_open", sql_cmd_open}, ++ {0, "dbd_close", sql_cmd_close}, ++ {0, "dbd_update", sql_cmd_update}, ++ {0, "dbd_select", sql_cmd_select}, ++ ++ {0, NULL, NULL} ++}; ++ ++/* **************************************************************** */ ++ ++MODRET set_sqlinfo (cmd_rec * cmd) ++{ ++ CHECK_ARGS (cmd, 4); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL | CONF_VIRTUAL); ++ add_config_param_str ("MySQLInfo", 4, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3], (void *) cmd->argv[4]); ++ return HANDLED (cmd); ++} ++ ++static conftable mysql_conftab[] = { ++/* *INDENT-OFF* */ ++ ++ { "MySQLInfo", set_sqlinfo, NULL }, ++ ++ { 0, NULL } ++ ++/* *INDENT-ON* */ ++}; ++ ++/* **************************************************************** */ ++ ++static int ++mysql_modinit () ++{ ++ config_rec *c; ++ ++ memset (&g, 0, sizeof (g)); ++ if (!(c = find_config (CURRENT_CONF, CONF_PARAM, "MySQLInfo", FALSE))) ++ return 0; ++ ++ g.sql_host = pstrdup (session.pool, c->argv[0]); ++ g.sql_user = pstrdup (session.pool, c->argv[1]); ++ g.sql_pass = pstrdup (session.pool, c->argv[2]); ++ g.sql_dbname = pstrdup (session.pool, c->argv[3]); ++ g.ok = TRUE; ++ ++ log_debug (DEBUG5, "%s: configured: db %s at %s@%s", ++ MOD_MYSQL_VERSION, g.sql_dbname, g.sql_user, g.sql_host); ++ return 0; ++} ++ ++module mysql_module = { ++ NULL, NULL, /* Always NULL */ ++ 0x20, /* API Version 2.0 */ ++ "mysql", ++ mysql_conftab, /* SQL configuration handler table */ ++ NULL, /* SQL command handler table */ ++ mysql_authtab, /* SQL authentication handler table */ ++ mysql_modinit, /* Pre-fork "parent-mode" init */ ++ mysql_modinit /* Post-fork "child mode" init */ ++}; diff --git a/ftp/proftpd-devel/files/patch-bb b/ftp/proftpd-devel/files/patch-bb new file mode 100644 index 000000000000..7d17d667f7dc --- /dev/null +++ b/ftp/proftpd-devel/files/patch-bb @@ -0,0 +1,1023 @@ +--- contrib/mod_sqlpw.c.old Sun Feb 11 19:47:34 2001 ++++ contrib/mod_sqlpw.c Sun Feb 11 19:45:37 2001 +@@ -0,0 +1,1020 @@ ++/* ++ * ProFTPD: mod_sql -- SQL frontend and user interface. ++ * Time-stamp: <1999-10-04 03:58:01 root> ++ * Copyright (c) 1998-1999 Johnie Ingram. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#define MOD_SQL_VERSION "mod_sqlpw/2.0" ++ ++/* This is mod_sqlpw, contrib software for proftpd 1.2.0pre3 and above. ++ For more information contact Johnie Ingram <johnie@netgod.net>. ++ ++ History Log: ++ ++ * 2000-03-16: Added SQLKeyField and SQLKey directive, which ++ should allow authentication of different logins for different ++ VirtualHosts to be in the same database table. ++ Jake Buchholz <jake@execpc.com> ++ ++ * 1999-09-19: v2.0: Backend directives split into mod_mysql. ++ Runtime API added. Username/passwords now escaped for SQL. ++ ++ * 1999-09-16: v1.0: Added documentation, made directives more ++ generic ("MySQL" -> "SQL" except for MySQLInfo). Dir part of ++ SQLLogDirs finally made optional. ++ ++ * 1999-06-01: v0.3: fixed segfault, changed 'strncmp' typo which ++ should have been copy. Made uid/gid support optional. ++ ++ * 1999-05-03: v0.2: Removed dead code, fix bug with interaction ++ with anon-user support. Added MySQLLogHits and MySQLHomedir ++ directives. Fixed atoi() invocation that could segfault. ++ Copious debugging code added. ++ ++ * 1999-04-09: v0.1: Initial attempt (mod_mysql). ++ ++*/ ++ ++#include "conf.h" ++#ifdef HAVE_CRYPT_H ++#include <crypt.h> ++#endif ++ ++#include <mysql.h> ++ ++/* *INDENT-OFF* */ ++ ++/* The Debian defintion of nobody/nogroup, minus 1 (used in getgwnam). */ ++#define MOD_SQL_MAGIC_USER 65533 ++#define MOD_SQL_MAGIC_GROUP 65533 ++ ++/* A uid or gid less than this is mapped to the magic numbers above ++ instead of simply rejected (which is arguably better, hmm.) */ ++#define MOD_SQL_MIN_ID 999 ++ ++#define MOD_SQL_MAGIC_SHELL "/bin/sh" ++ ++/* Maximum username field to expect, etc. */ ++#define ARBITRARY_MAX 128 ++ ++static struct { ++ char user [ARBITRARY_MAX]; ++ struct passwd pw; /* Scratch space for the getpwnam call. */ ++ char *pass; /* The password from db. */ ++ ++ char *homedir; /* Set when getpwnam is called. */ ++ int pwnamed; /* Set when getpwnam is called. */ ++ int sqled; /* Set if sql auth was used. */ ++ ++ char *sql_usertable; /* CREATE TABLE users ( */ ++ char *sql_userid; /* userid varchar(50) NOT NULL, */ ++ char *sql_passwd; /* passwd varchar(15), */ ++ ++ char *sql_uid; /* uid int(5), */ ++ char *sql_gid; /* gid int(5), */ ++ ++ char *sql_fstor; /* fstor int(11) NOT NULL DEFAULT '0', */ ++ char *sql_fretr; /* fretr int(11) NOT NULL DEFAULT '0', */ ++ char *sql_bstor; /* bstor int(11) NOT NULL DEFAULT '0', */ ++ char *sql_bretr; /* bretr int(11) NOT NULL DEFAULT '0', */ ++ ++ char *sql_fhdir; /* fhdir varchar(255), */ ++ ++ char *sql_fhost; /* fhost varchar(50), */ ++ char *sql_faddr; /* faddr char(15), */ ++ char *sql_ftime; /* ftime timestamp, */ ++ ++ char *sql_fcdir; /* fcdir varchar(255), */ ++ ++ char *sql_frate; /* frate int(11) NOT NULL DEFAULT '5', */ ++ char *sql_fcred; /* fcred int(2) NOT NULL DEFAULT '15', */ ++ char *sql_brate; /* brate int(11) NOT NULL DEFAULT '5', */ ++ char *sql_bcred; /* bcred int(2) NOT NULL DEFAULT '150000', */ ++ ++ char *sql_flogs; /* flogs int(11) NOT NULL DEFAULT '0', */ ++ ++ char *sql_hittable; ++ char *sql_dir; ++ char *sql_filename; ++ char *sql_hits; ++ ++ char *sql_keyfld; /* table column name that stores the key */ ++ char *sql_key; /* the key to match db table entries against */ ++ ++ char *loginmsg; ++ int ok; ++ ++} g; ++ ++/* *INDENT-ON* */ ++ ++/* **************************************************************** */ ++ ++/* Functions make_cmd and dispatch liberally stolen from auth.c. */ ++ ++static cmd_rec * ++_make_cmd (pool * cp, int argc, ...) ++{ ++ va_list args; ++ cmd_rec *c; ++ int i; ++ ++ c = pcalloc (cp, sizeof (cmd_rec)); ++ c->argc = argc; ++ c->symtable_index = -1; ++ ++ c->argv = pcalloc (cp, sizeof (void *) * (argc + 1)); ++ c->argv[0] = MOD_SQL_VERSION; ++ va_start (args, argc); ++ for (i = 0; i < argc; i++) ++ c->argv[i + 1] = (void *) va_arg (args, char *); ++ va_end (args); ++ ++ return c; ++} ++ ++static modret_t * ++_dispatch_sql (cmd_rec * cmd, char *match) ++{ ++ authtable *m; ++ modret_t *mr = NULL; ++ ++ m = mod_find_auth_symbol (match, &cmd->symtable_index, NULL); ++ while (m) ++ { ++ mr = call_module_auth (m->m, m->handler, cmd); ++ if (MODRET_ISHANDLED (mr) || MODRET_ISERROR (mr)) ++ break; ++ m = mod_find_auth_symbol (match, &cmd->symtable_index, m); ++ } ++ if (MODRET_ISERROR (mr)) ++ log_debug (DEBUG0, "Aiee! sql internal! %s", MODRET_ERRMSG (mr)); ++ return mr; ++} ++ ++MODRET ++modsql_open (cmd_rec * cmd) ++{ ++ cmd_rec *c; ++ modret_t *mr; ++ ++ c = _make_cmd (cmd ? cmd->tmp_pool : permanent_pool, 0); ++ mr = _dispatch_sql (c, "dbd_open"); ++ if (c->tmp_pool) ++ destroy_pool (c->tmp_pool); ++ return mr; ++} ++ ++MODRET ++modsql_close (cmd_rec * cmd) ++{ ++ cmd_rec *c; ++ modret_t *mr; ++ ++ c = _make_cmd (cmd ? cmd->tmp_pool : permanent_pool, 0); ++ mr = _dispatch_sql (c, "dbd_close"); ++ if (c->tmp_pool) ++ destroy_pool (c->tmp_pool); ++ return mr; ++} ++ ++MODRET ++modsql_update (cmd_rec * cmd, const char *query) ++{ ++ cmd_rec *c; ++ modret_t *mr; ++ ++ c = _make_cmd (cmd->tmp_pool, 1, query); ++ mr = _dispatch_sql (c, "dbd_update"); ++ if (c->tmp_pool) ++ destroy_pool (c->tmp_pool); ++ return mr; ++} ++ ++MODRET ++modsql_select (cmd_rec * cmd, const char *query) ++{ ++ cmd_rec *c; ++ modret_t *mr; ++ ++ c = _make_cmd (cmd->tmp_pool, 1, query); ++ mr = _dispatch_sql (c, "dbd_select"); ++ if (c->tmp_pool) ++ destroy_pool (c->tmp_pool); ++ return mr; ++} ++ ++MODRET ++modsql_queryuser (cmd_rec * cmd, const char *user, const char *query, ++ int update) ++{ ++ char *realquery; ++ ++ if ((update) && (!g.sql_keyfld)) ++ realquery = pstrcat (cmd->tmp_pool, "update ", g.sql_usertable, ++ " set ", query, " where ", g.sql_userid, " = '", ++ user, "'", NULL); ++ else if ((update) && (g.sql_keyfld)) ++ realquery = pstrcat (cmd->tmp_pool, "update ", g.sql_usertable, ++ " set ", query, " where ", g.sql_userid, " = '", ++ user, "' and ", g.sql_keyfld, " = '", ++ g.sql_key, "'", NULL); ++ else if ((!update) && (!g.sql_keyfld)) ++ realquery = pstrcat (cmd->tmp_pool, "select ", query, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "'", NULL); ++ else ++ realquery = pstrcat (cmd->tmp_pool, "select ", query, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "' and ", g.sql_keyfld, " = '", ++ g.sql_key, "'", NULL); ++ return (update) ? modsql_update (cmd, realquery) ++ : modsql_select (cmd, realquery); ++} ++ ++/* **************************************************************** */ ++ ++static char * ++_uservar (cmd_rec * cmd, const char *user, const char *var) ++{ ++ cmd_rec *c; ++ modret_t *mr; ++ char *query; ++ char **data; ++ ++ if (!g.sql_keyfld) ++ query = pstrcat (cmd->tmp_pool, "select ", var, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "'", NULL); ++ else ++ query = pstrcat (cmd->tmp_pool, "select ", var, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "' and ", g.sql_keyfld, " = '", ++ g.sql_key, "'", NULL); ++ c = _make_cmd (cmd->tmp_pool, 1, query); ++ ++ mr = _dispatch_sql (c, "dbd_select"); ++ ++ if (c->tmp_pool) ++ destroy_pool (c->tmp_pool); ++ if (MODRET_ISHANDLED (mr)) ++ { ++ data = mr->data; ++ return (data) ? data[0] : NULL; ++ } ++ ++ return NULL; ++} ++ ++/* Note: This function is called once by the master proftpd process ++ before it forks, so thankfully the homedir field is only set in the ++ child_init(). */ ++ ++MODRET ++auth_cmd_getpwnam (cmd_rec * cmd) ++{ ++ const char *homedir; ++ ++ if (!g.sql_fhdir && !g.homedir) ++ return DECLINED (cmd); ++ ++ /* Only try this for the USER command (is also called twice after ++ PASS for some reason. [update: 1 is dir_realpath/defroot related.] */ ++ if (!g.homedir && !g.pwnamed++) ++ { ++ if ((homedir = _uservar (cmd, cmd->argv[0], g.sql_fhdir))) ++ g.homedir = pstrdup (session.pool, homedir); ++ } ++ if (!g.homedir) ++ return DECLINED (cmd); ++ ++ if (!g.pw.pw_name) ++ { ++ g.pw.pw_name = pstrdup(session.pool, cmd->argv[0]); ++ if (g.sql_uid) ++ g.pw.pw_uid = atoi (_uservar (cmd, cmd->argv[0], g.sql_uid) ? : "0"); ++ if (g.pw.pw_uid < MOD_SQL_MIN_ID) ++ g.pw.pw_uid = MOD_SQL_MAGIC_USER; ++ if (g.sql_gid) ++ g.pw.pw_gid = atoi (_uservar (cmd, cmd->argv[0], g.sql_gid) ? : "0"); ++ if (g.pw.pw_gid < MOD_SQL_MIN_ID) ++ g.pw.pw_gid = MOD_SQL_MAGIC_GROUP; ++ g.pw.pw_shell = MOD_SQL_MAGIC_SHELL; ++ g.pw.pw_dir = (char *) g.homedir; ++ log_debug (DEBUG3, "sqlpw: user \"%s\" (%i/%i) for %s", ++ cmd->argv[0], g.pw.pw_uid, g.pw.pw_gid, g.pw.pw_dir); ++ ++ /* Copy username so proftpd anon handling won't confuse the issue. */ ++ ++ /* FIXME: unnecessary mysqlism */ ++ mysql_escape_string (g.user, g.pw.pw_name, strlen (g.pw.pw_name)); ++ g.user[ARBITRARY_MAX - 1] = 0; ++ } ++ ++ return mod_create_data (cmd, &g.pw); ++} ++ ++/* Returns 1 on successful match, 0 unsuccessful match, -1 on error. */ ++ ++static int ++_checkpass (cmd_rec * cmd, const char *user, const char *pass) ++{ ++ int success = 0; ++ char *query; ++ int emptyok, cplain, ccrypt; ++ char **row; ++ MODRET mr; ++ ++ emptyok = get_param_int (CURRENT_CONF, "SQLEmptyPasswords", FALSE); ++ cplain = get_param_int (CURRENT_CONF, "SQLPlaintextPasswords", FALSE); ++ ccrypt = get_param_int (CURRENT_CONF, "SQLEncryptedPasswords", FALSE); ++ ++ if (!g.sql_keyfld) ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_passwd, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "'", " limit 2", NULL); ++ else ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_passwd, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "' and ", g.sql_keyfld, " = '", ++ g.sql_key, "' limit 2", NULL); ++ mr = modsql_select (cmd, query); ++ if (!(MODRET_HASDATA (mr))) ++ return -1; ++ ++ row = mr->data; ++ if (row[0] == 0) ++ return 0; ++ ++ if (!row[0]) ++ { ++ log_debug (DEBUG4, "sqlpw: %s auth declined for NULL pass", user); ++ return 0; ++ } ++ ++ if (row[1]) ++ { ++ log_debug (DEBUG3, "sqlpw: %s pass result was not unique", user); ++ return -1; ++ } ++ ++ if (emptyok == TRUE && !strlen (row[0])) ++ { ++ log_debug (DEBUG4, "sqlpw: warning: %s has empty password", user); ++ success = 1; ++ } ++ ++ if (!success && cplain == TRUE && !strncasecmp (row[0], pass, 10)) ++ { ++ success = 1; ++ } ++ ++ /* Deliberate: ccrypt same if TRUE or -1 (unspecified). */ ++ if (!success && ccrypt) ++ { ++ if (!strcmp (query = (char *) crypt (pass, row[0]), row[0])) ++ success = 1; ++ } ++ ++ if (!success) ++ log_debug (DEBUG5, "sqlpw: %s auth failed: '%s' != '%s'", ++ user, pass, row ? row[0] : ""); ++ return success; ++} ++ ++MODRET ++auth_cmd_auth (cmd_rec * cmd) ++{ ++ char *user, *pass; ++ int return_type; ++ int retval = AUTH_NOPWD; ++ ++ if (!g.sql_passwd || !g.homedir) ++ return DECLINED (cmd); ++ ++ /* Figure out our default return style: Whether or not SQL should ++ * allow other auth modules a shot at this user or not is controlled ++ * by the parameter "SQLAuthoritative". Like mod_pam this ++ * defaults to no. */ ++ if((return_type = get_param_int (CURRENT_CONF, ++ "SQLAuthoritative", FALSE)) == -1) { ++ return_type = 0; ++ } ++ ++ /* Just in case... */ ++ if (cmd->argc != 2) ++ return return_type ? ERROR (cmd) : DECLINED (cmd); ++ if ((user = cmd->argv[0]) == NULL) ++ return return_type ? ERROR (cmd) : DECLINED (cmd); ++ if ((pass = cmd->argv[1]) == NULL) ++ return return_type ? ERROR (cmd) : DECLINED (cmd); ++ ++ if (!g.pass ++ && get_param_int (CURRENT_CONF, "SQLEmptyPasswords", FALSE) == 2) ++ { ++ char *query; ++ char passbuf[ARBITRARY_MAX] = {'\0'}; ++ ++ /* FIXME: unnecessary mysqlism */ ++ mysql_escape_string (passbuf, cmd->argv[1], strlen (cmd->argv[1])); ++ g.user[ARBITRARY_MAX - 1] = 0; ++ ++ if (!g.sql_keyfld) ++ query = pstrcat (cmd->tmp_pool, "update ", g.sql_usertable, ++ " set ", g.sql_passwd, " = '", passbuf, ++ "' where ", g.sql_userid, " = '", g.user, "'", 0); ++ else ++ query = pstrcat (cmd->tmp_pool, "update ", g.sql_usertable, ++ " set ", g.sql_passwd, " = '", passbuf, ++ "' where ", g.sql_userid, " = '", g.user, "' and ", ++ g.sql_keyfld, " = '", g.sql_key, "'", 0); ++ log_debug (DEBUG3, "sqlpw: %s NULL pass set to '%s'", user, ++ cmd->argv[1], query); ++ modsql_update (cmd, query); ++ } ++ ++ if (_checkpass (cmd, g.user, pass) != 1) ++ return return_type ? ERROR_INT (cmd, retval) : DECLINED (cmd); ++ ++ g.sqled++; ++ return HANDLED (cmd); ++} ++ ++MODRET ++auth_cmd_getstats (cmd_rec * cmd) ++{ ++ MODRET mr; ++ char *query; ++ ++ if (g.sql_fstor) ++ { ++ if (!g.sql_keyfld) ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_fstor, ", ", ++ g.sql_fretr, ", ", g.sql_bstor, ", ", ++ g.sql_bretr, " from ", g.sql_usertable, " where ", ++ g.sql_userid, " = '", g.user, "'", NULL); ++ else ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_fstor, ", ", ++ g.sql_fretr, ", ", g.sql_bstor, ", ", ++ g.sql_bretr, " from ", g.sql_usertable, " where ", ++ g.sql_userid, " = '", g.user, "' and ", g.sql_keyfld, ++ " = '", g.sql_key, "'", NULL); ++ mr = modsql_select (cmd, query); ++ if (MODRET_HASDATA (mr)) ++ return mr; ++ } ++ return DECLINED (cmd); ++} ++ ++MODRET ++auth_cmd_getratio (cmd_rec * cmd) ++{ ++ MODRET mr; ++ char *query; ++ ++ if (g.sql_frate) ++ { ++ if (!g.sql_keyfld) ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_frate, ", ", ++ g.sql_fcred, ", ", g.sql_brate, ", ", ++ g.sql_bcred, " from ", g.sql_usertable, " where ", ++ g.sql_userid, " = '", g.user, "'", NULL); ++ else ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_frate, ", ", ++ g.sql_fcred, ", ", g.sql_brate, ", ", ++ g.sql_bcred, " from ", g.sql_usertable, " where ", ++ g.sql_userid, " = '", g.user, "' and ", g.sql_keyfld, ++ " = '", g.sql_key, "'", NULL); ++ mr = modsql_select (cmd, query); ++ if (MODRET_HASDATA (mr)) ++ return mr; ++ } ++ return DECLINED (cmd); ++} ++ ++static authtable sqlpw_authtab[] = { ++ ++ {0, "auth", auth_cmd_auth}, ++ {0, "getpwnam", auth_cmd_getpwnam}, ++ {0, "getstats", auth_cmd_getstats}, ++ {0, "getratio", auth_cmd_getratio}, ++ {0, NULL, NULL} ++}; ++ ++/* **************************************************************** */ ++ ++static void ++_setstats (cmd_rec * cmd, int fstor, int fretr, int bstor, int bretr) ++{ ++ char query[ARBITRARY_MAX] = {'\0'}; ++ snprintf (query, sizeof (query), ++ "%s = %s + %i, %s = %s + %i, %s = %s + %i, %s = %s + %i", ++ g.sql_fstor, g.sql_fstor, fstor, ++ g.sql_fretr, g.sql_fretr, fretr, ++ g.sql_bstor, g.sql_bstor, bstor, g.sql_bretr, g.sql_bretr, bretr); ++ modsql_queryuser (cmd, g.user, query, TRUE); ++} ++ ++MODRET ++pre_cmd_quit (cmd_rec * cmd) ++{ ++ if (g.ok) ++ modsql_close (cmd); ++ return DECLINED (cmd); ++} ++ ++MODRET ++cmd_user (cmd_rec * cmd) ++{ ++ if (!g.user[0]) ++ sstrncpy (g.user, cmd->argv[1], ARBITRARY_MAX); ++ ++ if (g.sql_passwd) ++ { ++ g.pass = (char *) _uservar (cmd, cmd->argv[1], g.sql_passwd); ++ if (!g.pass ++ && get_param_int (CURRENT_CONF, "SQLEmptyPasswords", FALSE) == 2) ++ if (_uservar (cmd, cmd->argv[1], "1")) ++ add_response (R_331, "Changing password for %s -- " ++ "this password will be saved.", cmd->argv[1]); ++ } ++ return DECLINED (cmd); ++} ++ ++MODRET ++cmd_pass (cmd_rec * cmd) ++{ ++ if (g.sql_passwd && !g.pass ++ && get_param_int (CURRENT_CONF, "SQLEmptyPasswords", FALSE) == 2) ++ add_response (R_230, "\"%s\" is the new user \"%s\" password.", ++ cmd->argv[1], g.user); ++ ++ /* This is called before the disconnect() in log_cmd_pass. */ ++ if (g.sql_fcdir) ++ { ++ const char *d = _uservar (cmd, g.user, g.sql_fcdir); ++ if (d) ++ add_response (R_230, "\"%s\" was last directory.", d); ++ } ++ ++ return DECLINED (cmd); ++} ++ ++MODRET ++post_cmd_pass (cmd_rec * cmd) ++{ ++ if (g.sql_passwd && g.sqled) ++ session.anon_user = session.user = (char *) g.user; ++ return DECLINED (cmd); ++} ++ ++MODRET ++post_cmd_stor (cmd_rec * cmd) ++{ ++ if (g.sql_fstor) ++ _setstats (cmd, 1, 0, session.xfer.total_bytes, 0); ++ return DECLINED (cmd); ++} ++ ++MODRET ++cmd_retr (cmd_rec * cmd) ++{ ++ int i; ++ char *path, *filename, *query; ++ if (g.sql_hittable) ++ { ++ path = dir_realpath (cmd->tmp_pool, cmd->argv[1]); ++ if (g.sql_dir && g.sql_dir[0]) ++ { ++ for (i = strlen (path), filename = path + i; ++ *filename != '/' && i > 1; i--) ++ filename--; ++ *filename++ = 0; ++ query = pstrcat (cmd->tmp_pool, "update ", g.sql_hittable, ++ " set ", g.sql_hits, " = ", g.sql_hits, ++ " + 1 where ", g.sql_dir, " = '", ++path, ++ "' and ", g.sql_filename, " = '", filename, ++ "'", 0); ++ } ++ else ++ query = pstrcat (cmd->tmp_pool, "update ", g.sql_hittable, ++ " set ", g.sql_hits, " = ", g.sql_hits, ++ " + 1 where ", g.sql_filename, " = '", path, "'", 0); ++ modsql_update (cmd, query); ++ } ++ return DECLINED (cmd); ++} ++ ++MODRET ++post_cmd_retr (cmd_rec * cmd) ++{ ++ if (g.sql_fretr) ++ _setstats (cmd, 0, 1, 0, session.xfer.total_bytes); ++ return DECLINED (cmd); ++} ++ ++MODRET ++log_cmd_pass (cmd_rec * cmd) ++{ ++ char *query; ++ ++ if (g.sql_fhost) ++ { ++ query = pstrcat (cmd->tmp_pool, g.sql_fhost, " = '", ++ session.c->remote_name, "', ", g.sql_faddr, ++ " = '", inet_ntoa (*session.c->remote_ipaddr), ++ "', ", g.sql_ftime, " = now()", NULL); ++ modsql_queryuser (cmd, g.user, query, TRUE); ++ } ++ if (g.sql_flogs) ++ { ++ query = pstrcat (cmd->tmp_pool, g.sql_flogs, " = ", g.sql_flogs, ++ " + 1", NULL); ++ modsql_queryuser (cmd, g.user, query, TRUE); ++ } ++ ++ /* Autononpersistence: disconnect now if no other feature is being used. */ ++ if (!g.sql_fstor && !g.sql_fcdir && !g.sql_hittable) ++ modsql_close (cmd); ++ return DECLINED (cmd); ++} ++ ++MODRET ++log_cmd_cwd (cmd_rec * cmd) ++{ ++ if (g.sql_fcdir) ++ { ++ char *query = pstrcat (cmd->tmp_pool, g.sql_fcdir, " = '", ++ session.cwd, "'", NULL); ++ modsql_queryuser (cmd, g.user, query, TRUE); ++ } ++ return DECLINED (cmd); ++} ++ ++static cmdtable sqlpw_cmdtab[] = { ++/* *INDENT-OFF* */ ++ ++ { PRE_CMD, C_QUIT, G_NONE, pre_cmd_quit, FALSE, FALSE }, ++ { CMD, C_USER, G_NONE, cmd_user, FALSE, FALSE }, ++ { CMD, C_PASS, G_NONE, cmd_pass, FALSE, FALSE }, ++ { POST_CMD, C_PASS, G_NONE, post_cmd_pass, FALSE, FALSE }, ++ { POST_CMD, C_STOR, G_NONE, post_cmd_stor, FALSE, FALSE }, ++ { POST_CMD, C_RETR, G_NONE, post_cmd_retr, FALSE, FALSE }, ++ { CMD, C_RETR, G_NONE, cmd_retr, FALSE, FALSE }, ++ { LOG_CMD, C_PASS, G_NONE, log_cmd_pass, FALSE, FALSE }, ++ { LOG_CMD, C_CWD, G_NONE, log_cmd_cwd, FALSE, FALSE }, ++ { LOG_CMD, C_CDUP, G_NONE, log_cmd_cwd, FALSE, FALSE }, ++ ++ { 0, NULL } ++ ++/* *INDENT-ON* */ ++}; ++ ++/* **************************************************************** */ ++ ++MODRET ++set_sqlloghosts (cmd_rec * cmd) ++{ ++ int b; ++ ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ switch (cmd->argc - 1) ++ { ++ default: ++ CONF_ERROR (cmd, "requires a boolean or 3 field names: " ++ "fhost faddr ftime"); ++ case 1: ++ if ((b = get_boolean (cmd, 1)) == -1) ++ CONF_ERROR (cmd, "requires a boolean or 3 field names: " ++ "fhost faddr ftime"); ++ if (b) ++ add_config_param_str ("SQLLogHosts", 3, "fhost", "faddr", "ftime"); ++ break; ++ ++ case 3: ++ add_config_param_str ("SQLLogHosts", 3, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3]); ++ } ++ return HANDLED (cmd); ++} ++ ++MODRET ++set_sqllogstats (cmd_rec * cmd) ++{ ++ int b; ++ ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ switch (cmd->argc - 1) ++ { ++ default: ++ CONF_ERROR (cmd, "requires a boolean or 4 field names: " ++ "fstor fretr bstor bretr"); ++ case 1: ++ if ((b = get_boolean (cmd, 1)) == -1) ++ CONF_ERROR (cmd, "requires a boolean or 4 field names: " ++ "fstor fretr bstor bretr"); ++ if (b) ++ add_config_param_str ("SQLLogStats", 4, ++ "fstor", "fretr", "bstor", "bretr"); ++ break; ++ ++ case 4: ++ add_config_param_str ("SQLLogStats", 4, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3], (void *) cmd->argv[4]); ++ } ++ return HANDLED (cmd); ++} ++ ++MODRET ++set_sqlloghits (cmd_rec * cmd) ++{ ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ switch (cmd->argc - 1) ++ { ++ default: ++ CONF_ERROR (cmd, "requires a table or table plus 3 fields: " ++ "[table] filename count dir"); ++ case 1: ++ add_config_param_str ("SQLLogHits", 4, (void *) cmd->argv[1], ++ "filename", "count", ""); ++ break; ++ case 3: ++ add_config_param_str ("SQLLogHits", 4, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3], ""); ++ ++ case 4: ++ add_config_param_str ("SQLLogHits", 4, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3], (void *) cmd->argv[4]); ++ } ++ return HANDLED (cmd); ++} ++ ++MODRET ++set_sqllogdirs (cmd_rec * cmd) ++{ ++ int b; ++ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ if ((b = get_boolean (cmd, 1)) == -1) ++ add_config_param_str ("SQLLogDirs", 1, (void *) cmd->argv[1]); ++ else if (b) ++ add_config_param_str ("SQLLogDirs", 1, "fcdir"); ++ return HANDLED (cmd); ++} ++ ++MODRET ++set_sqlratios (cmd_rec * cmd) ++{ ++ int b; ++ ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ switch (cmd->argc - 1) ++ { ++ default: ++ CONF_ERROR (cmd, "requires a boolean or 4 field names: " ++ "frate fcred brate bcred"); ++ case 1: ++ if ((b = get_boolean (cmd, 1)) == -1) ++ CONF_ERROR (cmd, "requires a boolean or 4 field names: " ++ "frate fcred brate bcred"); ++ if (b) ++ add_config_param_str ("SQLRatios", 4, ++ "frate", "fcred", "brate", "bcred"); ++ break; ++ ++ case 4: ++ add_config_param_str ("SQLRatios", 4, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3], (void *) cmd->argv[4]); ++ } ++ return HANDLED (cmd); ++} ++ ++MODRET ++set_sqlempty (cmd_rec * cmd) ++{ ++ int b; ++ config_rec *c; ++ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ ++ if ((b = get_boolean (cmd, 1)) == -1) ++ { ++ if (!strcasecmp (cmd->argv[1], "set")) ++ b = 2; ++ else ++ CONF_ERROR (cmd, "requires 'set' or a boolean value"); ++ } ++ c = add_config_param (cmd->argv[0], 1, (void *) b); ++ c->flags |= CF_MERGEDOWN; ++ return HANDLED (cmd); ++} ++ ++MODRET ++add_globalstr (cmd_rec * cmd) ++{ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ add_config_param_str (cmd->argv[0], 1, (void *) cmd->argv[1]); ++ return HANDLED (cmd); ++} ++ ++MODRET ++add_virtualstr (cmd_rec * cmd) ++{ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL | CONF_VIRTUAL); ++ add_config_param_str (cmd->argv[0], 1, (void *) cmd->argv[1]); ++ return HANDLED (cmd); ++} ++ ++MODRET ++add_globalbool (cmd_rec * cmd) ++{ ++ int b; ++ config_rec *c; ++ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ ++ b = get_boolean (cmd, 1); ++ if (b == -1) ++ CONF_ERROR (cmd, "requires a boolean value"); ++ c = add_config_param (cmd->argv[0], 1, (void *) b); ++ c->flags |= CF_MERGEDOWN; ++ return HANDLED (cmd); ++} ++ ++MODRET ++add_virtualbool (cmd_rec * cmd) ++{ ++ int b; ++ config_rec *c; ++ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL | CONF_VIRTUAL); ++ ++ b = get_boolean (cmd, 1); ++ if (b == -1) ++ CONF_ERROR (cmd, "requires a boolean value"); ++ c = add_config_param (cmd->argv[0], 1, (void *) b); ++ c->flags |= CF_MERGEDOWN; ++ return HANDLED (cmd); ++} ++ ++static conftable sqlpw_conftab[] = { ++/* *INDENT-OFF* */ ++ ++ { "SQLLogHosts", set_sqlloghosts, NULL }, ++ { "SQLLogStats", set_sqllogstats, NULL }, ++ { "SQLLogHits", set_sqlloghits, NULL }, ++ { "SQLLogDirs", set_sqllogdirs, NULL }, ++ { "SQLRatios", set_sqlratios, NULL }, ++ { "SQLEmptyPasswords", set_sqlempty, NULL }, ++ ++ { "SQLUserTable", add_globalstr, NULL }, ++ { "SQLUsernameField", add_globalstr, NULL }, ++ { "SQLUidField", add_globalstr, NULL }, ++ { "SQLGidField", add_globalstr, NULL }, ++ { "SQLPasswordField", add_globalstr, NULL }, ++ { "SQLHomedirField", add_globalstr, NULL }, ++ { "SQLLoginCountField", add_globalstr, NULL }, ++ { "SQLHomedir", add_globalstr, NULL }, ++ ++ { "SQLKeyField", add_globalstr, NULL }, ++ { "SQLKey", add_virtualstr, NULL }, ++ ++ { "SQLAuthoritative", add_virtualbool, NULL }, ++ { "SQLEncryptedPasswords", add_globalbool, NULL }, ++ { "SQLPlaintextPasswords", add_globalbool, NULL }, ++ ++ { NULL, NULL, NULL } ++ ++/* *INDENT-ON* */ ++}; ++ ++/* **************************************************************** */ ++ ++static int ++sqlpw_child_init () ++{ ++ config_rec *c; ++ MODRET mr; ++ ++ memset (&g, 0, sizeof (g)); ++ g.ok = TRUE; ++ ++ g.sql_passwd = get_param_ptr (CURRENT_CONF, "SQLPasswordField", FALSE); ++ g.sql_flogs = get_param_ptr (CURRENT_CONF, "SQLLoginCountField", FALSE); ++ g.sql_uid = get_param_ptr (CURRENT_CONF, "SQLUidField", FALSE); ++ g.sql_gid = get_param_ptr (CURRENT_CONF, "SQLGidField", FALSE); ++ ++ if (!(g.homedir = get_param_ptr (CURRENT_CONF, "SQLHomedir", FALSE))) ++ { ++ g.sql_fhdir = get_param_ptr (CURRENT_CONF, "SQLHomedirField", FALSE); ++ } ++ if ((c = find_config (CURRENT_CONF, CONF_PARAM, "SQLLogHosts", FALSE))) ++ { ++ g.sql_fhost = c->argv[0]; ++ g.sql_faddr = c->argv[1]; ++ g.sql_ftime = c->argv[2]; ++ } ++ if ((c = find_config (CURRENT_CONF, CONF_PARAM, "SQLLogStats", FALSE))) ++ { ++ g.sql_fstor = c->argv[0]; ++ g.sql_fretr = c->argv[1]; ++ g.sql_bstor = c->argv[2]; ++ g.sql_bretr = c->argv[3]; ++ } ++ if ((c = find_config (CURRENT_CONF, CONF_PARAM, "SQLRatios", FALSE))) ++ { ++ if (!g.sql_fstor) ++ log_pri (LOG_WARNING, "sqlpw: warning: SQLRatios directive " ++ "ineffective without SQLLogStats on"); ++ g.sql_frate = c->argv[0]; ++ g.sql_fcred = c->argv[1]; ++ g.sql_brate = c->argv[2]; ++ g.sql_bcred = c->argv[3]; ++ } ++ if ((c = find_config (CURRENT_CONF, CONF_PARAM, "SQLLogHits", FALSE))) ++ { ++ g.sql_hittable = c->argv[0]; ++ g.sql_filename = c->argv[1]; ++ g.sql_hits = c->argv[2]; ++ g.sql_dir = c->argv[3]; ++ } ++ g.sql_fcdir = get_param_ptr (CURRENT_CONF, "SQLLogDirs", FALSE); ++ ++ g.sql_usertable = get_param_ptr (CURRENT_CONF, "SQLUserTable", ++ FALSE) ? : "users"; ++ g.sql_userid = get_param_ptr (CURRENT_CONF, "SQLUsernameField", ++ FALSE) ? : "userid"; ++ ++ g.sql_keyfld = get_param_ptr (CURRENT_CONF, "SQLKeyField", FALSE); ++ g.sql_key = get_param_ptr (CURRENT_CONF, "SQLKey", FALSE); ++ ++ if (!(g.homedir || g.sql_fhdir) && !g.sql_fhost ++ && !g.sql_fstor && !g.sql_fcdir) ++ return 0; ++ ++ mr = modsql_open (NULL); ++ if (MODRET_ISHANDLED (mr)) ++ { ++ log_debug (DEBUG3, "%s: configured: %s%s%s%s%s%s%s%s", ++ MOD_SQL_VERSION, ++ (g.sql_passwd && (g.homedir || g.sql_fhdir)) ++ ? "auth " : "", ++ g.homedir ? "homedir " : "", ++ g.sql_fhdir ? "homedirfield " : "", ++ g.sql_fhost ? "loghosts " : "", ++ g.sql_fstor ? "logstats " : "", ++ g.sql_frate ? "ratios " : "", ++ g.sql_hittable ? "loghits " : "", ++ g.sql_fcdir ? "logdirs " : ""); ++ } ++ else ++ { ++ memset (&g, 0, sizeof (g)); ++ log_debug (DEBUG3, "%s: unconfigured: no backend could connect", ++ MOD_SQL_VERSION); ++ } ++ return 0; ++} ++ ++static int ++sqlpw_parent_init (void) ++{ ++ /* FIXME: add db init stuff once parent_init() actually works. */ ++ return 0; ++} ++ ++module sqlpw_module = { ++ NULL, NULL, /* Always NULL */ ++ 0x20, /* API Version 2.0 */ ++ "sql", ++ sqlpw_conftab, /* SQL configuration handler table */ ++ sqlpw_cmdtab, /* SQL command handler table */ ++ sqlpw_authtab, /* SQL authentication handler table */ ++ sqlpw_parent_init, /* Pre-fork "parent mode" init */ ++ sqlpw_child_init /* Post-fork "child mode" init */ ++}; diff --git a/ftp/proftpd-devel/files/patch-bc b/ftp/proftpd-devel/files/patch-bc new file mode 100644 index 000000000000..bd908a4fa9fa --- /dev/null +++ b/ftp/proftpd-devel/files/patch-bc @@ -0,0 +1,19 @@ +--- contrib/mod_sqlpw.c.old Sun Feb 11 19:52:06 2001 ++++ contrib/mod_sqlpw.c Sun Feb 11 19:53:42 2001 +@@ -302,8 +302,6 @@ + if (!g.homedir) + return DECLINED (cmd); + +- if (!g.pw.pw_name) +- { + g.pw.pw_name = pstrdup(session.pool, cmd->argv[0]); + if (g.sql_uid) + g.pw.pw_uid = atoi (_uservar (cmd, cmd->argv[0], g.sql_uid) ? : "0"); +@@ -323,7 +321,6 @@ + /* FIXME: unnecessary mysqlism */ + mysql_escape_string (g.user, g.pw.pw_name, strlen (g.pw.pw_name)); + g.user[ARBITRARY_MAX - 1] = 0; +- } + + return mod_create_data (cmd, &g.pw); + } diff --git a/ftp/proftpd-devel/files/patch-bd b/ftp/proftpd-devel/files/patch-bd new file mode 100644 index 000000000000..7eb41bc857e8 --- /dev/null +++ b/ftp/proftpd-devel/files/patch-bd @@ -0,0 +1,21 @@ +--- contrib/mod_sqlpw.c.old Sun Feb 11 20:14:40 2001 ++++ contrib/mod_sqlpw.c Sun Feb 11 20:16:00 2001 +@@ -400,9 +400,6 @@ + int return_type; + int retval = AUTH_NOPWD; + +- if (!g.sql_passwd || !g.homedir) +- return DECLINED (cmd); +- + /* Figure out our default return style: Whether or not SQL should + * allow other auth modules a shot at this user or not is controlled + * by the parameter "SQLAuthoritative". Like mod_pam this +@@ -418,6 +415,8 @@ + if ((user = cmd->argv[0]) == NULL) + return return_type ? ERROR (cmd) : DECLINED (cmd); + if ((pass = cmd->argv[1]) == NULL) ++ return return_type ? ERROR (cmd) : DECLINED (cmd); ++ if (!g.sql_passwd || !g.homedir) + return return_type ? ERROR (cmd) : DECLINED (cmd); + + if (!g.pass diff --git a/ftp/proftpd-devel/files/patch-be b/ftp/proftpd-devel/files/patch-be new file mode 100644 index 000000000000..7a6578032734 --- /dev/null +++ b/ftp/proftpd-devel/files/patch-be @@ -0,0 +1,21 @@ +--- contrib/mod_mysql.c.old Sun Feb 11 20:19:00 2001 ++++ contrib/mod_mysql.c Sun Feb 11 20:21:29 2001 +@@ -100,6 +100,9 @@ + mysql_get_client_info (), mysql_get_server_info (mysqldb), + g.sql_user, g.sql_host); + ++ if (mysqldb) ++ mysql_select_db (mysqldb, g.sql_dbname); ++ + return HANDLED (cmd); + } + +@@ -115,7 +118,7 @@ + + /* This forces a quick ping of the remote server, so we know if its there. */ + if (mysqldb) +- mysql_select_db (mysqldb, g.sql_dbname); ++ mysql_ping( mysqldb ); + + if (!mysqldb + || ((error = mysql_query (mysqldb, query)) diff --git a/ftp/proftpd/Makefile b/ftp/proftpd/Makefile index a2ce7f485de1..b9c44d2db57d 100644 --- a/ftp/proftpd/Makefile +++ b/ftp/proftpd/Makefile @@ -6,21 +6,20 @@ # PORTNAME= proftpd -PORTVERSION= 1.2.0rc2 -PORTREVISION= 1 +PORTVERSION= 1.2.0rc3 CATEGORIES= ftp MASTER_SITES= ftp://ftp.tos.net/pub/proftpd/ \ ftp://ftp.stikman.com/pub/proftpd/ \ ftp://ftp.linux.co.uk/pub/packages/proftpd/ \ ftp://ftp.drenik.net/linux/ftp/proftpd/ -DISTNAME= ${PORTNAME}-1.2.0rc2 +DISTNAME= ${PORTNAME}-1.2.0rc3 MAINTAINER= mharo@FreeBSD.org .if defined(WITH_LDAP) MASTER_SITES+= http://www.horde.net/~jwm/software/proftpd-ldap/ -MOD_LDAP= mod_ldap-2.6.1.tar.gz -DISTFILES= ${DISTNAME}.${EXTRACT_SUFX} ${MOD_LDAP} +MOD_LDAP= mod_ldap-2.7.4.tar.gz +DISTFILES= ${DISTNAME}${EXTRACT_SUFX} ${MOD_LDAP} .endif MAN1= ftpcount.1 ftpwho.1 @@ -34,7 +33,7 @@ CONFIGURE_ARGS= --localstatedir=/var/run \ --disable-sendfile #allow user to override -MODULES?= mod_ratio:mod_readme:mod_tar +MODULES?= mod_ratio:mod_readme .if defined(WITH_LDAP) MODULES:=$(MODULES):mod_ldap @@ -42,6 +41,11 @@ BUILD_DEPENDS+= ${LOCALBASE}/lib/libldap.a:${PORTSDIR}/net/openldap CONFIGURE_ENV+= CFLAGS="-I/usr/local/include -g" LDFLAGS=-L/usr/local/lib .endif +# Currently not supported by the ProFTPd project, but it's patched in with +# bugfixes as well. For myself (anders@fix.no): +# patch-bc: bugid 330 (cached passwords not cleared properly) +# patch-bd: bugid 405 (sqlauthorative broken) +# patch-be: bugid 457 (speed improvement) .if defined(WITH_MYSQL) MODULES:=$(MODULES):mod_sqlpw:mod_mysql LIB_DEPENDS+= mysqlclient.10:${PORTSDIR}/databases/mysql323-client diff --git a/ftp/proftpd/distinfo b/ftp/proftpd/distinfo index a8e3849d8fdb..3a77685f3ed8 100644 --- a/ftp/proftpd/distinfo +++ b/ftp/proftpd/distinfo @@ -1,2 +1,2 @@ -MD5 (proftpd-1.2.0rc2.tar.gz) = 13e48f0f4006738ffb9aa7c28ab0ae63 -MD5 (mod_ldap-2.6.1.tar.gz) = 0e866a3137641e20e546543ed1c91760 +MD5 (proftpd-1.2.0rc3.tar.gz) = 0b2b32cec7138cdc1ba4b2a99148bb93 +MD5 (mod_ldap-2.7.4.tar.gz) = 7b3e948d89d2089b5c0b03fb9d22c050 diff --git a/ftp/proftpd/files/patch-ae b/ftp/proftpd/files/patch-ae index eb59e14d9b3f..50db35749dd1 100644 --- a/ftp/proftpd/files/patch-ae +++ b/ftp/proftpd/files/patch-ae @@ -1,6 +1,6 @@ ---- modules/mod_auth.c.orig Fri Jul 28 10:51:59 2000 -+++ modules/mod_auth.c Fri Jul 28 10:52:17 2000 -@@ -72,7 +72,7 @@ +--- modules/mod_auth.c.old Sun Feb 11 19:42:37 2001 ++++ modules/mod_auth.c Sun Feb 11 19:43:18 2001 +@@ -94,7 +94,7 @@ "closing control connection.", TimeoutLogin); @@ -9,7 +9,7 @@ (void*) 0, NULL); /* should never be reached */ -@@ -608,7 +608,7 @@ +@@ -630,7 +630,7 @@ c = _auth_resolve_user(p,&user,&ourname,&anonname); if(!user) { @@ -18,7 +18,7 @@ origuser); goto auth_failure; } -@@ -617,7 +617,7 @@ +@@ -639,7 +639,7 @@ aclp = login_check_limits(main_server->conf,FALSE,TRUE,&i); if((pw = auth_getpwnam(p,user)) == NULL) { @@ -27,7 +27,7 @@ goto auth_failure; } -@@ -678,14 +678,14 @@ +@@ -700,14 +700,14 @@ } if(!login_check_limits(c->subset,FALSE,TRUE,&i) || (!aclp && !i) ){ @@ -44,7 +44,7 @@ origuser); goto auth_failure; } -@@ -702,7 +702,7 @@ +@@ -724,7 +724,7 @@ if(c && origuser && strcasecmp(user,origuser) && get_param_int(c->subset,"AuthUsingAlias",FALSE) == 1) { user_name = origuser; @@ -53,7 +53,7 @@ user, user_name); } -@@ -730,22 +730,22 @@ +@@ -752,22 +752,22 @@ switch(authcode) { case AUTH_NOPWD: @@ -80,7 +80,7 @@ user); goto auth_failure; -@@ -768,12 +768,12 @@ +@@ -790,12 +790,12 @@ auth_setgrent(p); if(!_auth_check_shell((c ? c->subset : main_server->conf),pw->pw_shell)) { @@ -95,7 +95,7 @@ user, FTPUSERS_PATH); goto auth_failure; } -@@ -845,7 +845,7 @@ +@@ -870,7 +870,7 @@ if(!login_check_limits((c ? c->subset : main_server->conf),FALSE,TRUE,&i)) { @@ -104,7 +104,7 @@ origuser); goto auth_failure; } -@@ -860,7 +860,7 @@ +@@ -885,7 +885,7 @@ if(c && c->subset) resolve_anonymous_dirs(c->subset); @@ -113,61 +113,70 @@ (c != NULL) ? "ANON" : "USER", origuser); -@@ -1172,7 +1172,7 @@ - - if(failnopwprompt) { - if(!user) { -- log_pri(LOG_NOTICE, "USER %s (Login failed): Not a UserAlias.", -+ log_pri(LOG_INFO, "USER %s (Login failed): Not a UserAlias.", - origuser); - send_response(R_530,"Login incorrect."); - end_login(0); -@@ -1189,7 +1189,7 @@ - - if(c) { - if(!login_check_limits(c->subset,FALSE,TRUE,&i) || (!aclp && !i) ) { -- log_auth(LOG_NOTICE, "ANON %s: Limit access denies login.", -+ log_auth(LOG_INFO, "ANON %s: Limit access denies login.", - origuser); - send_response(R_530,"Login incorrect."); - end_login(0); -@@ -1197,7 +1197,7 @@ - } - - if(!c && !aclp) { -- log_auth(LOG_NOTICE, "USER %s: Limit access denies login.", origuser); -+ log_auth(LOG_INFO, "USER %s: Limit access denies login.", origuser); - send_response(R_530,"Login incorrect."); +@@ -1267,7 +1267,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); + +- log_auth(LOG_NOTICE, "Connection refused (max clients for class %s).", ++ log_auth(LOG_INFO, "Connection refused (max clients for class %s).", + session.class->name); + end_login(0); - } -@@ -1269,7 +1269,7 @@ - "Too many users in your class, " - "please try again later."); - -- log_auth(LOG_NOTICE, "Connection refused (max clients for class %s).", -+ log_auth(LOG_INFO, "Connection refused (max clients for class %s).", - session.class->name); - - end_login(0); -@@ -1304,7 +1304,7 @@ - send_response(R_530,"%s", - sreplace(cmd->tmp_pool,maxstr,"%m",maxn,NULL)); +@@ -1299,7 +1299,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); - log_auth(LOG_NOTICE, "Connection refused (max clients per host %d).", + log_auth(LOG_INFO, "Connection refused (max clients per host %d).", max); end_login(0); -@@ -1330,7 +1330,7 @@ - if(cur >= max) { +@@ -1324,7 +1324,7 @@ send_response(R_530, "%s", sreplace(cmd->tmp_pool, maxstr, "%m", maxn, NULL)); + - log_auth(LOG_NOTICE, "Connection refused (max clients %d).", max); + log_auth(LOG_INFO, "Connection refused (max clients %d).", max); + + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); +@@ -1354,7 +1354,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); + +- log_auth(LOG_NOTICE, "Connection refused (max clients per host %d).", ++ log_auth(LOG_INFO, "Connection refused (max clients per host %d).", + max); + end_login(0); - } +@@ -1401,7 +1401,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); + +- log_pri(LOG_NOTICE, "USER %s (Login failed): Not a UserAlias.", ++ log_pri(LOG_INFO, "USER %s (Login failed): Not a UserAlias.", + origuser); + send_response(R_530,"Login incorrect."); -@@ -1411,7 +1411,7 @@ +@@ -1422,7 +1422,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); + +- log_auth(LOG_NOTICE, "ANON %s: Limit access denies login.", ++ log_auth(LOG_INFO, "ANON %s: Limit access denies login.", + origuser); + send_response(R_530, "Login incorrect."); + +@@ -1434,7 +1434,7 @@ + remove_config(cmd->server->conf, C_USER, FALSE); + remove_config(cmd->server->conf, C_PASS, FALSE); + +- log_auth(LOG_NOTICE, "USER %s: Limit access denies login.", origuser); ++ log_auth(LOG_INFO, "USER %s: Limit access denies login.", origuser); + send_response(R_530, "Login incorrect."); + + end_login(0); +@@ -1528,7 +1528,7 @@ if(++auth_tries >= max) { send_response(R_530,"Login incorrect"); diff --git a/ftp/proftpd/files/patch-ak b/ftp/proftpd/files/patch-ak deleted file mode 100644 index 0d8bb08fee5b..000000000000 --- a/ftp/proftpd/files/patch-ak +++ /dev/null @@ -1,12 +0,0 @@ ---- modules/mod_xfer.c.orig Mon Jul 31 16:49:19 2000 -+++ modules/mod_xfer.c Mon Jul 31 16:50:02 2000 -@@ -268,7 +268,8 @@ - - /* No PORT command has been issued. - */ -- if(session.d != NULL || !(session.flags & SF_PORT)) { -+ if(!(session.flags & SF_PASSIVE) && -+ (session.d != NULL || !(session.flags & SF_PORT))) { - add_response_err(R_503, "No PORT command issued first."); - return ERROR(cmd); - } diff --git a/ftp/proftpd/files/patch-ba b/ftp/proftpd/files/patch-ba new file mode 100644 index 000000000000..b1d054b52edc --- /dev/null +++ b/ftp/proftpd/files/patch-ba @@ -0,0 +1,253 @@ +--- contrib/mod_mysql.c.old Sun Feb 11 19:47:54 2001 ++++ contrib/mod_mysql.c Sun Feb 11 19:45:37 2001 +@@ -0,0 +1,250 @@ ++/* ++ * ProFTPD: mod_mysql -- Support for connecting to MySQL databases. ++ * Time-stamp: <1999-10-04 03:21:21 root> ++ * Copyright (c) 1998-1999 Johnie Ingram. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#define MOD_MYSQL_VERSION "mod_mysql/2.0" ++ ++/* -- DO NOT MODIFY THE LINE BELOW UNLESS YOU FEEL LIKE IT -- ++ * $Libraries: -lm -lmysqlclient $ ++ */ ++ ++/* This is mod_mysql, contrib software for proftpd 1.2.0pre3 and above. ++ For more information contact Johnie Ingram <johnie@netgod.net>. ++ ++ History Log: ++ ++ * 1999-09-19: v2.0: Most directives split into mod_sql; invented API. ++ ++*/ ++ ++#include "conf.h" ++#include <mysql.h> ++ ++/* *INDENT-OFF* */ ++ ++static MYSQL mod_mysql_server; ++static MYSQL *mysqldb = 0; ++ ++/* Maximum username field to expect, etc. */ ++#define ARBITRARY_MAX 128 ++ ++static struct ++{ ++ char *sql_host; /* Data for connecting, set by MySQLInfo. */ ++ char *sql_user; ++ char *sql_pass; ++ char *sql_dbname; ++ ++ int ok; ++ int opens; ++} g; ++ ++/* *INDENT-ON* */ ++ ++/* **************************************************************** */ ++ ++MODRET ++sql_cmd_close (cmd_rec * cmd) ++{ ++ log_debug (DEBUG5, "mysql: close [%i] for %s", g.opens, cmd->argv[0]); ++ ++ if (!g.ok || g.opens--) ++ return DECLINED (cmd); ++ ++ if (mysqldb) ++ { ++ log_debug (DEBUG4, "mysql: disconnecting: %s", mysql_stat (mysqldb)); ++ mysql_close (mysqldb); ++ } ++ mysqldb = NULL; ++ return DECLINED (cmd); ++} ++ ++MODRET ++sql_cmd_open (cmd_rec * cmd) ++{ ++ if (!g.ok) ++ return DECLINED (cmd); ++ ++ g.opens++; ++ log_debug (DEBUG5, "mysql: open [%i] for %s", g.opens, cmd->argv[0]); ++ if (g.opens > 1) ++ return HANDLED (cmd); ++ ++ if (!(mysqldb = mysql_connect (&mod_mysql_server, g.sql_host, ++ g.sql_user, g.sql_pass))) ++ { ++ log_pri (LOG_ERR, "mysql: client %s connect FAILED to %s@%s", ++ mysql_get_client_info (), g.sql_user, g.sql_host); ++ g.ok = FALSE; ++ g.opens = 0; ++ return DECLINED (cmd); ++ } ++ log_debug (DEBUG5, "mysql: connect OK %s -> %s (%s@%s)", ++ mysql_get_client_info (), mysql_get_server_info (mysqldb), ++ g.sql_user, g.sql_host); ++ ++ return HANDLED (cmd); ++} ++ ++MODRET ++_do_query (cmd_rec * cmd, const char *query, int update) ++{ ++ int error = 1; ++ ++ if (!g.ok) ++ return DECLINED (cmd); ++ ++ block_signals (); ++ ++ /* This forces a quick ping of the remote server, so we know if its there. */ ++ if (mysqldb) ++ mysql_select_db (mysqldb, g.sql_dbname); ++ ++ if (!mysqldb ++ || ((error = mysql_query (mysqldb, query)) ++ && !strcasecmp (mysql_error (mysqldb), "mysql server has gone"))) ++ { ++ /* We need to restart the server link. */ ++ if (mysqldb) ++ log_pri (LOG_ERR, "mysql: server has wandered off (%s/%s)", ++ g.sql_host, g.sql_dbname); ++ sql_cmd_open (cmd); ++ if (!mysqldb) ++ return DECLINED (cmd); ++ error = mysql_select_db (mysqldb, g.sql_dbname) ++ || mysql_query (mysqldb, query); ++ } ++ ++ unblock_signals (); ++ ++ if (error) ++ { ++ log_debug (DEBUG4, "mysql: %s failed: \"%s\": %s", ++ (update) ? "update" : "select", ++ query, mysql_error (mysqldb)); ++ return DECLINED (cmd); ++ } ++ ++ log_debug (DEBUG5, "mysql: %s OK: [%s] \"%s\"", ++ (update) ? "update" : "select", g.sql_dbname, query); ++ return HANDLED (cmd); ++} ++ ++MODRET ++sql_cmd_update (cmd_rec * cmd) ++{ ++ return _do_query (cmd, cmd->argv[1], TRUE); ++} ++ ++MODRET ++sql_cmd_select (cmd_rec * cmd) ++{ ++ MODRET mr; ++ MYSQL_RES *result; ++ MYSQL_ROW sql_row; ++ int i, j; ++ ++ mr = _do_query (cmd, cmd->argv[1], FALSE); ++ if (!MODRET_ISHANDLED (mr)) ++ return DECLINED (mr); ++ ++ if ((result = mysql_store_result (mysqldb))) ++ { ++ int rcount = mysql_num_rows (result); ++ int fcount = mysql_num_fields (result); ++ int count = rcount * fcount; ++ ++ char **data = pcalloc (cmd->tmp_pool, sizeof (char *) * (count + 1)); ++ for (i = 0, count = 0; i < rcount; i++) ++ { ++ sql_row = mysql_fetch_row (result); ++ for (j = 0; j < fcount; j++) ++ data[count++] = pstrdup (cmd->tmp_pool, sql_row[j]); ++ } ++ mysql_free_result (result); ++ data[count] = NULL; ++ mr->data = data; ++ } ++ return mr; ++} ++ ++static authtable mysql_authtab[] = { ++ {0, "dbd_open", sql_cmd_open}, ++ {0, "dbd_close", sql_cmd_close}, ++ {0, "dbd_update", sql_cmd_update}, ++ {0, "dbd_select", sql_cmd_select}, ++ ++ {0, NULL, NULL} ++}; ++ ++/* **************************************************************** */ ++ ++MODRET set_sqlinfo (cmd_rec * cmd) ++{ ++ CHECK_ARGS (cmd, 4); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL | CONF_VIRTUAL); ++ add_config_param_str ("MySQLInfo", 4, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3], (void *) cmd->argv[4]); ++ return HANDLED (cmd); ++} ++ ++static conftable mysql_conftab[] = { ++/* *INDENT-OFF* */ ++ ++ { "MySQLInfo", set_sqlinfo, NULL }, ++ ++ { 0, NULL } ++ ++/* *INDENT-ON* */ ++}; ++ ++/* **************************************************************** */ ++ ++static int ++mysql_modinit () ++{ ++ config_rec *c; ++ ++ memset (&g, 0, sizeof (g)); ++ if (!(c = find_config (CURRENT_CONF, CONF_PARAM, "MySQLInfo", FALSE))) ++ return 0; ++ ++ g.sql_host = pstrdup (session.pool, c->argv[0]); ++ g.sql_user = pstrdup (session.pool, c->argv[1]); ++ g.sql_pass = pstrdup (session.pool, c->argv[2]); ++ g.sql_dbname = pstrdup (session.pool, c->argv[3]); ++ g.ok = TRUE; ++ ++ log_debug (DEBUG5, "%s: configured: db %s at %s@%s", ++ MOD_MYSQL_VERSION, g.sql_dbname, g.sql_user, g.sql_host); ++ return 0; ++} ++ ++module mysql_module = { ++ NULL, NULL, /* Always NULL */ ++ 0x20, /* API Version 2.0 */ ++ "mysql", ++ mysql_conftab, /* SQL configuration handler table */ ++ NULL, /* SQL command handler table */ ++ mysql_authtab, /* SQL authentication handler table */ ++ mysql_modinit, /* Pre-fork "parent-mode" init */ ++ mysql_modinit /* Post-fork "child mode" init */ ++}; diff --git a/ftp/proftpd/files/patch-bb b/ftp/proftpd/files/patch-bb new file mode 100644 index 000000000000..7d17d667f7dc --- /dev/null +++ b/ftp/proftpd/files/patch-bb @@ -0,0 +1,1023 @@ +--- contrib/mod_sqlpw.c.old Sun Feb 11 19:47:34 2001 ++++ contrib/mod_sqlpw.c Sun Feb 11 19:45:37 2001 +@@ -0,0 +1,1020 @@ ++/* ++ * ProFTPD: mod_sql -- SQL frontend and user interface. ++ * Time-stamp: <1999-10-04 03:58:01 root> ++ * Copyright (c) 1998-1999 Johnie Ingram. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#define MOD_SQL_VERSION "mod_sqlpw/2.0" ++ ++/* This is mod_sqlpw, contrib software for proftpd 1.2.0pre3 and above. ++ For more information contact Johnie Ingram <johnie@netgod.net>. ++ ++ History Log: ++ ++ * 2000-03-16: Added SQLKeyField and SQLKey directive, which ++ should allow authentication of different logins for different ++ VirtualHosts to be in the same database table. ++ Jake Buchholz <jake@execpc.com> ++ ++ * 1999-09-19: v2.0: Backend directives split into mod_mysql. ++ Runtime API added. Username/passwords now escaped for SQL. ++ ++ * 1999-09-16: v1.0: Added documentation, made directives more ++ generic ("MySQL" -> "SQL" except for MySQLInfo). Dir part of ++ SQLLogDirs finally made optional. ++ ++ * 1999-06-01: v0.3: fixed segfault, changed 'strncmp' typo which ++ should have been copy. Made uid/gid support optional. ++ ++ * 1999-05-03: v0.2: Removed dead code, fix bug with interaction ++ with anon-user support. Added MySQLLogHits and MySQLHomedir ++ directives. Fixed atoi() invocation that could segfault. ++ Copious debugging code added. ++ ++ * 1999-04-09: v0.1: Initial attempt (mod_mysql). ++ ++*/ ++ ++#include "conf.h" ++#ifdef HAVE_CRYPT_H ++#include <crypt.h> ++#endif ++ ++#include <mysql.h> ++ ++/* *INDENT-OFF* */ ++ ++/* The Debian defintion of nobody/nogroup, minus 1 (used in getgwnam). */ ++#define MOD_SQL_MAGIC_USER 65533 ++#define MOD_SQL_MAGIC_GROUP 65533 ++ ++/* A uid or gid less than this is mapped to the magic numbers above ++ instead of simply rejected (which is arguably better, hmm.) */ ++#define MOD_SQL_MIN_ID 999 ++ ++#define MOD_SQL_MAGIC_SHELL "/bin/sh" ++ ++/* Maximum username field to expect, etc. */ ++#define ARBITRARY_MAX 128 ++ ++static struct { ++ char user [ARBITRARY_MAX]; ++ struct passwd pw; /* Scratch space for the getpwnam call. */ ++ char *pass; /* The password from db. */ ++ ++ char *homedir; /* Set when getpwnam is called. */ ++ int pwnamed; /* Set when getpwnam is called. */ ++ int sqled; /* Set if sql auth was used. */ ++ ++ char *sql_usertable; /* CREATE TABLE users ( */ ++ char *sql_userid; /* userid varchar(50) NOT NULL, */ ++ char *sql_passwd; /* passwd varchar(15), */ ++ ++ char *sql_uid; /* uid int(5), */ ++ char *sql_gid; /* gid int(5), */ ++ ++ char *sql_fstor; /* fstor int(11) NOT NULL DEFAULT '0', */ ++ char *sql_fretr; /* fretr int(11) NOT NULL DEFAULT '0', */ ++ char *sql_bstor; /* bstor int(11) NOT NULL DEFAULT '0', */ ++ char *sql_bretr; /* bretr int(11) NOT NULL DEFAULT '0', */ ++ ++ char *sql_fhdir; /* fhdir varchar(255), */ ++ ++ char *sql_fhost; /* fhost varchar(50), */ ++ char *sql_faddr; /* faddr char(15), */ ++ char *sql_ftime; /* ftime timestamp, */ ++ ++ char *sql_fcdir; /* fcdir varchar(255), */ ++ ++ char *sql_frate; /* frate int(11) NOT NULL DEFAULT '5', */ ++ char *sql_fcred; /* fcred int(2) NOT NULL DEFAULT '15', */ ++ char *sql_brate; /* brate int(11) NOT NULL DEFAULT '5', */ ++ char *sql_bcred; /* bcred int(2) NOT NULL DEFAULT '150000', */ ++ ++ char *sql_flogs; /* flogs int(11) NOT NULL DEFAULT '0', */ ++ ++ char *sql_hittable; ++ char *sql_dir; ++ char *sql_filename; ++ char *sql_hits; ++ ++ char *sql_keyfld; /* table column name that stores the key */ ++ char *sql_key; /* the key to match db table entries against */ ++ ++ char *loginmsg; ++ int ok; ++ ++} g; ++ ++/* *INDENT-ON* */ ++ ++/* **************************************************************** */ ++ ++/* Functions make_cmd and dispatch liberally stolen from auth.c. */ ++ ++static cmd_rec * ++_make_cmd (pool * cp, int argc, ...) ++{ ++ va_list args; ++ cmd_rec *c; ++ int i; ++ ++ c = pcalloc (cp, sizeof (cmd_rec)); ++ c->argc = argc; ++ c->symtable_index = -1; ++ ++ c->argv = pcalloc (cp, sizeof (void *) * (argc + 1)); ++ c->argv[0] = MOD_SQL_VERSION; ++ va_start (args, argc); ++ for (i = 0; i < argc; i++) ++ c->argv[i + 1] = (void *) va_arg (args, char *); ++ va_end (args); ++ ++ return c; ++} ++ ++static modret_t * ++_dispatch_sql (cmd_rec * cmd, char *match) ++{ ++ authtable *m; ++ modret_t *mr = NULL; ++ ++ m = mod_find_auth_symbol (match, &cmd->symtable_index, NULL); ++ while (m) ++ { ++ mr = call_module_auth (m->m, m->handler, cmd); ++ if (MODRET_ISHANDLED (mr) || MODRET_ISERROR (mr)) ++ break; ++ m = mod_find_auth_symbol (match, &cmd->symtable_index, m); ++ } ++ if (MODRET_ISERROR (mr)) ++ log_debug (DEBUG0, "Aiee! sql internal! %s", MODRET_ERRMSG (mr)); ++ return mr; ++} ++ ++MODRET ++modsql_open (cmd_rec * cmd) ++{ ++ cmd_rec *c; ++ modret_t *mr; ++ ++ c = _make_cmd (cmd ? cmd->tmp_pool : permanent_pool, 0); ++ mr = _dispatch_sql (c, "dbd_open"); ++ if (c->tmp_pool) ++ destroy_pool (c->tmp_pool); ++ return mr; ++} ++ ++MODRET ++modsql_close (cmd_rec * cmd) ++{ ++ cmd_rec *c; ++ modret_t *mr; ++ ++ c = _make_cmd (cmd ? cmd->tmp_pool : permanent_pool, 0); ++ mr = _dispatch_sql (c, "dbd_close"); ++ if (c->tmp_pool) ++ destroy_pool (c->tmp_pool); ++ return mr; ++} ++ ++MODRET ++modsql_update (cmd_rec * cmd, const char *query) ++{ ++ cmd_rec *c; ++ modret_t *mr; ++ ++ c = _make_cmd (cmd->tmp_pool, 1, query); ++ mr = _dispatch_sql (c, "dbd_update"); ++ if (c->tmp_pool) ++ destroy_pool (c->tmp_pool); ++ return mr; ++} ++ ++MODRET ++modsql_select (cmd_rec * cmd, const char *query) ++{ ++ cmd_rec *c; ++ modret_t *mr; ++ ++ c = _make_cmd (cmd->tmp_pool, 1, query); ++ mr = _dispatch_sql (c, "dbd_select"); ++ if (c->tmp_pool) ++ destroy_pool (c->tmp_pool); ++ return mr; ++} ++ ++MODRET ++modsql_queryuser (cmd_rec * cmd, const char *user, const char *query, ++ int update) ++{ ++ char *realquery; ++ ++ if ((update) && (!g.sql_keyfld)) ++ realquery = pstrcat (cmd->tmp_pool, "update ", g.sql_usertable, ++ " set ", query, " where ", g.sql_userid, " = '", ++ user, "'", NULL); ++ else if ((update) && (g.sql_keyfld)) ++ realquery = pstrcat (cmd->tmp_pool, "update ", g.sql_usertable, ++ " set ", query, " where ", g.sql_userid, " = '", ++ user, "' and ", g.sql_keyfld, " = '", ++ g.sql_key, "'", NULL); ++ else if ((!update) && (!g.sql_keyfld)) ++ realquery = pstrcat (cmd->tmp_pool, "select ", query, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "'", NULL); ++ else ++ realquery = pstrcat (cmd->tmp_pool, "select ", query, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "' and ", g.sql_keyfld, " = '", ++ g.sql_key, "'", NULL); ++ return (update) ? modsql_update (cmd, realquery) ++ : modsql_select (cmd, realquery); ++} ++ ++/* **************************************************************** */ ++ ++static char * ++_uservar (cmd_rec * cmd, const char *user, const char *var) ++{ ++ cmd_rec *c; ++ modret_t *mr; ++ char *query; ++ char **data; ++ ++ if (!g.sql_keyfld) ++ query = pstrcat (cmd->tmp_pool, "select ", var, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "'", NULL); ++ else ++ query = pstrcat (cmd->tmp_pool, "select ", var, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "' and ", g.sql_keyfld, " = '", ++ g.sql_key, "'", NULL); ++ c = _make_cmd (cmd->tmp_pool, 1, query); ++ ++ mr = _dispatch_sql (c, "dbd_select"); ++ ++ if (c->tmp_pool) ++ destroy_pool (c->tmp_pool); ++ if (MODRET_ISHANDLED (mr)) ++ { ++ data = mr->data; ++ return (data) ? data[0] : NULL; ++ } ++ ++ return NULL; ++} ++ ++/* Note: This function is called once by the master proftpd process ++ before it forks, so thankfully the homedir field is only set in the ++ child_init(). */ ++ ++MODRET ++auth_cmd_getpwnam (cmd_rec * cmd) ++{ ++ const char *homedir; ++ ++ if (!g.sql_fhdir && !g.homedir) ++ return DECLINED (cmd); ++ ++ /* Only try this for the USER command (is also called twice after ++ PASS for some reason. [update: 1 is dir_realpath/defroot related.] */ ++ if (!g.homedir && !g.pwnamed++) ++ { ++ if ((homedir = _uservar (cmd, cmd->argv[0], g.sql_fhdir))) ++ g.homedir = pstrdup (session.pool, homedir); ++ } ++ if (!g.homedir) ++ return DECLINED (cmd); ++ ++ if (!g.pw.pw_name) ++ { ++ g.pw.pw_name = pstrdup(session.pool, cmd->argv[0]); ++ if (g.sql_uid) ++ g.pw.pw_uid = atoi (_uservar (cmd, cmd->argv[0], g.sql_uid) ? : "0"); ++ if (g.pw.pw_uid < MOD_SQL_MIN_ID) ++ g.pw.pw_uid = MOD_SQL_MAGIC_USER; ++ if (g.sql_gid) ++ g.pw.pw_gid = atoi (_uservar (cmd, cmd->argv[0], g.sql_gid) ? : "0"); ++ if (g.pw.pw_gid < MOD_SQL_MIN_ID) ++ g.pw.pw_gid = MOD_SQL_MAGIC_GROUP; ++ g.pw.pw_shell = MOD_SQL_MAGIC_SHELL; ++ g.pw.pw_dir = (char *) g.homedir; ++ log_debug (DEBUG3, "sqlpw: user \"%s\" (%i/%i) for %s", ++ cmd->argv[0], g.pw.pw_uid, g.pw.pw_gid, g.pw.pw_dir); ++ ++ /* Copy username so proftpd anon handling won't confuse the issue. */ ++ ++ /* FIXME: unnecessary mysqlism */ ++ mysql_escape_string (g.user, g.pw.pw_name, strlen (g.pw.pw_name)); ++ g.user[ARBITRARY_MAX - 1] = 0; ++ } ++ ++ return mod_create_data (cmd, &g.pw); ++} ++ ++/* Returns 1 on successful match, 0 unsuccessful match, -1 on error. */ ++ ++static int ++_checkpass (cmd_rec * cmd, const char *user, const char *pass) ++{ ++ int success = 0; ++ char *query; ++ int emptyok, cplain, ccrypt; ++ char **row; ++ MODRET mr; ++ ++ emptyok = get_param_int (CURRENT_CONF, "SQLEmptyPasswords", FALSE); ++ cplain = get_param_int (CURRENT_CONF, "SQLPlaintextPasswords", FALSE); ++ ccrypt = get_param_int (CURRENT_CONF, "SQLEncryptedPasswords", FALSE); ++ ++ if (!g.sql_keyfld) ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_passwd, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "'", " limit 2", NULL); ++ else ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_passwd, " from ", ++ g.sql_usertable, " where ", g.sql_userid, ++ " = '", user, "' and ", g.sql_keyfld, " = '", ++ g.sql_key, "' limit 2", NULL); ++ mr = modsql_select (cmd, query); ++ if (!(MODRET_HASDATA (mr))) ++ return -1; ++ ++ row = mr->data; ++ if (row[0] == 0) ++ return 0; ++ ++ if (!row[0]) ++ { ++ log_debug (DEBUG4, "sqlpw: %s auth declined for NULL pass", user); ++ return 0; ++ } ++ ++ if (row[1]) ++ { ++ log_debug (DEBUG3, "sqlpw: %s pass result was not unique", user); ++ return -1; ++ } ++ ++ if (emptyok == TRUE && !strlen (row[0])) ++ { ++ log_debug (DEBUG4, "sqlpw: warning: %s has empty password", user); ++ success = 1; ++ } ++ ++ if (!success && cplain == TRUE && !strncasecmp (row[0], pass, 10)) ++ { ++ success = 1; ++ } ++ ++ /* Deliberate: ccrypt same if TRUE or -1 (unspecified). */ ++ if (!success && ccrypt) ++ { ++ if (!strcmp (query = (char *) crypt (pass, row[0]), row[0])) ++ success = 1; ++ } ++ ++ if (!success) ++ log_debug (DEBUG5, "sqlpw: %s auth failed: '%s' != '%s'", ++ user, pass, row ? row[0] : ""); ++ return success; ++} ++ ++MODRET ++auth_cmd_auth (cmd_rec * cmd) ++{ ++ char *user, *pass; ++ int return_type; ++ int retval = AUTH_NOPWD; ++ ++ if (!g.sql_passwd || !g.homedir) ++ return DECLINED (cmd); ++ ++ /* Figure out our default return style: Whether or not SQL should ++ * allow other auth modules a shot at this user or not is controlled ++ * by the parameter "SQLAuthoritative". Like mod_pam this ++ * defaults to no. */ ++ if((return_type = get_param_int (CURRENT_CONF, ++ "SQLAuthoritative", FALSE)) == -1) { ++ return_type = 0; ++ } ++ ++ /* Just in case... */ ++ if (cmd->argc != 2) ++ return return_type ? ERROR (cmd) : DECLINED (cmd); ++ if ((user = cmd->argv[0]) == NULL) ++ return return_type ? ERROR (cmd) : DECLINED (cmd); ++ if ((pass = cmd->argv[1]) == NULL) ++ return return_type ? ERROR (cmd) : DECLINED (cmd); ++ ++ if (!g.pass ++ && get_param_int (CURRENT_CONF, "SQLEmptyPasswords", FALSE) == 2) ++ { ++ char *query; ++ char passbuf[ARBITRARY_MAX] = {'\0'}; ++ ++ /* FIXME: unnecessary mysqlism */ ++ mysql_escape_string (passbuf, cmd->argv[1], strlen (cmd->argv[1])); ++ g.user[ARBITRARY_MAX - 1] = 0; ++ ++ if (!g.sql_keyfld) ++ query = pstrcat (cmd->tmp_pool, "update ", g.sql_usertable, ++ " set ", g.sql_passwd, " = '", passbuf, ++ "' where ", g.sql_userid, " = '", g.user, "'", 0); ++ else ++ query = pstrcat (cmd->tmp_pool, "update ", g.sql_usertable, ++ " set ", g.sql_passwd, " = '", passbuf, ++ "' where ", g.sql_userid, " = '", g.user, "' and ", ++ g.sql_keyfld, " = '", g.sql_key, "'", 0); ++ log_debug (DEBUG3, "sqlpw: %s NULL pass set to '%s'", user, ++ cmd->argv[1], query); ++ modsql_update (cmd, query); ++ } ++ ++ if (_checkpass (cmd, g.user, pass) != 1) ++ return return_type ? ERROR_INT (cmd, retval) : DECLINED (cmd); ++ ++ g.sqled++; ++ return HANDLED (cmd); ++} ++ ++MODRET ++auth_cmd_getstats (cmd_rec * cmd) ++{ ++ MODRET mr; ++ char *query; ++ ++ if (g.sql_fstor) ++ { ++ if (!g.sql_keyfld) ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_fstor, ", ", ++ g.sql_fretr, ", ", g.sql_bstor, ", ", ++ g.sql_bretr, " from ", g.sql_usertable, " where ", ++ g.sql_userid, " = '", g.user, "'", NULL); ++ else ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_fstor, ", ", ++ g.sql_fretr, ", ", g.sql_bstor, ", ", ++ g.sql_bretr, " from ", g.sql_usertable, " where ", ++ g.sql_userid, " = '", g.user, "' and ", g.sql_keyfld, ++ " = '", g.sql_key, "'", NULL); ++ mr = modsql_select (cmd, query); ++ if (MODRET_HASDATA (mr)) ++ return mr; ++ } ++ return DECLINED (cmd); ++} ++ ++MODRET ++auth_cmd_getratio (cmd_rec * cmd) ++{ ++ MODRET mr; ++ char *query; ++ ++ if (g.sql_frate) ++ { ++ if (!g.sql_keyfld) ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_frate, ", ", ++ g.sql_fcred, ", ", g.sql_brate, ", ", ++ g.sql_bcred, " from ", g.sql_usertable, " where ", ++ g.sql_userid, " = '", g.user, "'", NULL); ++ else ++ query = pstrcat (cmd->tmp_pool, "select ", g.sql_frate, ", ", ++ g.sql_fcred, ", ", g.sql_brate, ", ", ++ g.sql_bcred, " from ", g.sql_usertable, " where ", ++ g.sql_userid, " = '", g.user, "' and ", g.sql_keyfld, ++ " = '", g.sql_key, "'", NULL); ++ mr = modsql_select (cmd, query); ++ if (MODRET_HASDATA (mr)) ++ return mr; ++ } ++ return DECLINED (cmd); ++} ++ ++static authtable sqlpw_authtab[] = { ++ ++ {0, "auth", auth_cmd_auth}, ++ {0, "getpwnam", auth_cmd_getpwnam}, ++ {0, "getstats", auth_cmd_getstats}, ++ {0, "getratio", auth_cmd_getratio}, ++ {0, NULL, NULL} ++}; ++ ++/* **************************************************************** */ ++ ++static void ++_setstats (cmd_rec * cmd, int fstor, int fretr, int bstor, int bretr) ++{ ++ char query[ARBITRARY_MAX] = {'\0'}; ++ snprintf (query, sizeof (query), ++ "%s = %s + %i, %s = %s + %i, %s = %s + %i, %s = %s + %i", ++ g.sql_fstor, g.sql_fstor, fstor, ++ g.sql_fretr, g.sql_fretr, fretr, ++ g.sql_bstor, g.sql_bstor, bstor, g.sql_bretr, g.sql_bretr, bretr); ++ modsql_queryuser (cmd, g.user, query, TRUE); ++} ++ ++MODRET ++pre_cmd_quit (cmd_rec * cmd) ++{ ++ if (g.ok) ++ modsql_close (cmd); ++ return DECLINED (cmd); ++} ++ ++MODRET ++cmd_user (cmd_rec * cmd) ++{ ++ if (!g.user[0]) ++ sstrncpy (g.user, cmd->argv[1], ARBITRARY_MAX); ++ ++ if (g.sql_passwd) ++ { ++ g.pass = (char *) _uservar (cmd, cmd->argv[1], g.sql_passwd); ++ if (!g.pass ++ && get_param_int (CURRENT_CONF, "SQLEmptyPasswords", FALSE) == 2) ++ if (_uservar (cmd, cmd->argv[1], "1")) ++ add_response (R_331, "Changing password for %s -- " ++ "this password will be saved.", cmd->argv[1]); ++ } ++ return DECLINED (cmd); ++} ++ ++MODRET ++cmd_pass (cmd_rec * cmd) ++{ ++ if (g.sql_passwd && !g.pass ++ && get_param_int (CURRENT_CONF, "SQLEmptyPasswords", FALSE) == 2) ++ add_response (R_230, "\"%s\" is the new user \"%s\" password.", ++ cmd->argv[1], g.user); ++ ++ /* This is called before the disconnect() in log_cmd_pass. */ ++ if (g.sql_fcdir) ++ { ++ const char *d = _uservar (cmd, g.user, g.sql_fcdir); ++ if (d) ++ add_response (R_230, "\"%s\" was last directory.", d); ++ } ++ ++ return DECLINED (cmd); ++} ++ ++MODRET ++post_cmd_pass (cmd_rec * cmd) ++{ ++ if (g.sql_passwd && g.sqled) ++ session.anon_user = session.user = (char *) g.user; ++ return DECLINED (cmd); ++} ++ ++MODRET ++post_cmd_stor (cmd_rec * cmd) ++{ ++ if (g.sql_fstor) ++ _setstats (cmd, 1, 0, session.xfer.total_bytes, 0); ++ return DECLINED (cmd); ++} ++ ++MODRET ++cmd_retr (cmd_rec * cmd) ++{ ++ int i; ++ char *path, *filename, *query; ++ if (g.sql_hittable) ++ { ++ path = dir_realpath (cmd->tmp_pool, cmd->argv[1]); ++ if (g.sql_dir && g.sql_dir[0]) ++ { ++ for (i = strlen (path), filename = path + i; ++ *filename != '/' && i > 1; i--) ++ filename--; ++ *filename++ = 0; ++ query = pstrcat (cmd->tmp_pool, "update ", g.sql_hittable, ++ " set ", g.sql_hits, " = ", g.sql_hits, ++ " + 1 where ", g.sql_dir, " = '", ++path, ++ "' and ", g.sql_filename, " = '", filename, ++ "'", 0); ++ } ++ else ++ query = pstrcat (cmd->tmp_pool, "update ", g.sql_hittable, ++ " set ", g.sql_hits, " = ", g.sql_hits, ++ " + 1 where ", g.sql_filename, " = '", path, "'", 0); ++ modsql_update (cmd, query); ++ } ++ return DECLINED (cmd); ++} ++ ++MODRET ++post_cmd_retr (cmd_rec * cmd) ++{ ++ if (g.sql_fretr) ++ _setstats (cmd, 0, 1, 0, session.xfer.total_bytes); ++ return DECLINED (cmd); ++} ++ ++MODRET ++log_cmd_pass (cmd_rec * cmd) ++{ ++ char *query; ++ ++ if (g.sql_fhost) ++ { ++ query = pstrcat (cmd->tmp_pool, g.sql_fhost, " = '", ++ session.c->remote_name, "', ", g.sql_faddr, ++ " = '", inet_ntoa (*session.c->remote_ipaddr), ++ "', ", g.sql_ftime, " = now()", NULL); ++ modsql_queryuser (cmd, g.user, query, TRUE); ++ } ++ if (g.sql_flogs) ++ { ++ query = pstrcat (cmd->tmp_pool, g.sql_flogs, " = ", g.sql_flogs, ++ " + 1", NULL); ++ modsql_queryuser (cmd, g.user, query, TRUE); ++ } ++ ++ /* Autononpersistence: disconnect now if no other feature is being used. */ ++ if (!g.sql_fstor && !g.sql_fcdir && !g.sql_hittable) ++ modsql_close (cmd); ++ return DECLINED (cmd); ++} ++ ++MODRET ++log_cmd_cwd (cmd_rec * cmd) ++{ ++ if (g.sql_fcdir) ++ { ++ char *query = pstrcat (cmd->tmp_pool, g.sql_fcdir, " = '", ++ session.cwd, "'", NULL); ++ modsql_queryuser (cmd, g.user, query, TRUE); ++ } ++ return DECLINED (cmd); ++} ++ ++static cmdtable sqlpw_cmdtab[] = { ++/* *INDENT-OFF* */ ++ ++ { PRE_CMD, C_QUIT, G_NONE, pre_cmd_quit, FALSE, FALSE }, ++ { CMD, C_USER, G_NONE, cmd_user, FALSE, FALSE }, ++ { CMD, C_PASS, G_NONE, cmd_pass, FALSE, FALSE }, ++ { POST_CMD, C_PASS, G_NONE, post_cmd_pass, FALSE, FALSE }, ++ { POST_CMD, C_STOR, G_NONE, post_cmd_stor, FALSE, FALSE }, ++ { POST_CMD, C_RETR, G_NONE, post_cmd_retr, FALSE, FALSE }, ++ { CMD, C_RETR, G_NONE, cmd_retr, FALSE, FALSE }, ++ { LOG_CMD, C_PASS, G_NONE, log_cmd_pass, FALSE, FALSE }, ++ { LOG_CMD, C_CWD, G_NONE, log_cmd_cwd, FALSE, FALSE }, ++ { LOG_CMD, C_CDUP, G_NONE, log_cmd_cwd, FALSE, FALSE }, ++ ++ { 0, NULL } ++ ++/* *INDENT-ON* */ ++}; ++ ++/* **************************************************************** */ ++ ++MODRET ++set_sqlloghosts (cmd_rec * cmd) ++{ ++ int b; ++ ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ switch (cmd->argc - 1) ++ { ++ default: ++ CONF_ERROR (cmd, "requires a boolean or 3 field names: " ++ "fhost faddr ftime"); ++ case 1: ++ if ((b = get_boolean (cmd, 1)) == -1) ++ CONF_ERROR (cmd, "requires a boolean or 3 field names: " ++ "fhost faddr ftime"); ++ if (b) ++ add_config_param_str ("SQLLogHosts", 3, "fhost", "faddr", "ftime"); ++ break; ++ ++ case 3: ++ add_config_param_str ("SQLLogHosts", 3, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3]); ++ } ++ return HANDLED (cmd); ++} ++ ++MODRET ++set_sqllogstats (cmd_rec * cmd) ++{ ++ int b; ++ ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ switch (cmd->argc - 1) ++ { ++ default: ++ CONF_ERROR (cmd, "requires a boolean or 4 field names: " ++ "fstor fretr bstor bretr"); ++ case 1: ++ if ((b = get_boolean (cmd, 1)) == -1) ++ CONF_ERROR (cmd, "requires a boolean or 4 field names: " ++ "fstor fretr bstor bretr"); ++ if (b) ++ add_config_param_str ("SQLLogStats", 4, ++ "fstor", "fretr", "bstor", "bretr"); ++ break; ++ ++ case 4: ++ add_config_param_str ("SQLLogStats", 4, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3], (void *) cmd->argv[4]); ++ } ++ return HANDLED (cmd); ++} ++ ++MODRET ++set_sqlloghits (cmd_rec * cmd) ++{ ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ switch (cmd->argc - 1) ++ { ++ default: ++ CONF_ERROR (cmd, "requires a table or table plus 3 fields: " ++ "[table] filename count dir"); ++ case 1: ++ add_config_param_str ("SQLLogHits", 4, (void *) cmd->argv[1], ++ "filename", "count", ""); ++ break; ++ case 3: ++ add_config_param_str ("SQLLogHits", 4, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3], ""); ++ ++ case 4: ++ add_config_param_str ("SQLLogHits", 4, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3], (void *) cmd->argv[4]); ++ } ++ return HANDLED (cmd); ++} ++ ++MODRET ++set_sqllogdirs (cmd_rec * cmd) ++{ ++ int b; ++ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ if ((b = get_boolean (cmd, 1)) == -1) ++ add_config_param_str ("SQLLogDirs", 1, (void *) cmd->argv[1]); ++ else if (b) ++ add_config_param_str ("SQLLogDirs", 1, "fcdir"); ++ return HANDLED (cmd); ++} ++ ++MODRET ++set_sqlratios (cmd_rec * cmd) ++{ ++ int b; ++ ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ switch (cmd->argc - 1) ++ { ++ default: ++ CONF_ERROR (cmd, "requires a boolean or 4 field names: " ++ "frate fcred brate bcred"); ++ case 1: ++ if ((b = get_boolean (cmd, 1)) == -1) ++ CONF_ERROR (cmd, "requires a boolean or 4 field names: " ++ "frate fcred brate bcred"); ++ if (b) ++ add_config_param_str ("SQLRatios", 4, ++ "frate", "fcred", "brate", "bcred"); ++ break; ++ ++ case 4: ++ add_config_param_str ("SQLRatios", 4, ++ (void *) cmd->argv[1], (void *) cmd->argv[2], ++ (void *) cmd->argv[3], (void *) cmd->argv[4]); ++ } ++ return HANDLED (cmd); ++} ++ ++MODRET ++set_sqlempty (cmd_rec * cmd) ++{ ++ int b; ++ config_rec *c; ++ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ ++ if ((b = get_boolean (cmd, 1)) == -1) ++ { ++ if (!strcasecmp (cmd->argv[1], "set")) ++ b = 2; ++ else ++ CONF_ERROR (cmd, "requires 'set' or a boolean value"); ++ } ++ c = add_config_param (cmd->argv[0], 1, (void *) b); ++ c->flags |= CF_MERGEDOWN; ++ return HANDLED (cmd); ++} ++ ++MODRET ++add_globalstr (cmd_rec * cmd) ++{ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ add_config_param_str (cmd->argv[0], 1, (void *) cmd->argv[1]); ++ return HANDLED (cmd); ++} ++ ++MODRET ++add_virtualstr (cmd_rec * cmd) ++{ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL | CONF_VIRTUAL); ++ add_config_param_str (cmd->argv[0], 1, (void *) cmd->argv[1]); ++ return HANDLED (cmd); ++} ++ ++MODRET ++add_globalbool (cmd_rec * cmd) ++{ ++ int b; ++ config_rec *c; ++ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL); ++ ++ b = get_boolean (cmd, 1); ++ if (b == -1) ++ CONF_ERROR (cmd, "requires a boolean value"); ++ c = add_config_param (cmd->argv[0], 1, (void *) b); ++ c->flags |= CF_MERGEDOWN; ++ return HANDLED (cmd); ++} ++ ++MODRET ++add_virtualbool (cmd_rec * cmd) ++{ ++ int b; ++ config_rec *c; ++ ++ CHECK_ARGS (cmd, 1); ++ CHECK_CONF (cmd, CONF_ROOT | CONF_GLOBAL | CONF_VIRTUAL); ++ ++ b = get_boolean (cmd, 1); ++ if (b == -1) ++ CONF_ERROR (cmd, "requires a boolean value"); ++ c = add_config_param (cmd->argv[0], 1, (void *) b); ++ c->flags |= CF_MERGEDOWN; ++ return HANDLED (cmd); ++} ++ ++static conftable sqlpw_conftab[] = { ++/* *INDENT-OFF* */ ++ ++ { "SQLLogHosts", set_sqlloghosts, NULL }, ++ { "SQLLogStats", set_sqllogstats, NULL }, ++ { "SQLLogHits", set_sqlloghits, NULL }, ++ { "SQLLogDirs", set_sqllogdirs, NULL }, ++ { "SQLRatios", set_sqlratios, NULL }, ++ { "SQLEmptyPasswords", set_sqlempty, NULL }, ++ ++ { "SQLUserTable", add_globalstr, NULL }, ++ { "SQLUsernameField", add_globalstr, NULL }, ++ { "SQLUidField", add_globalstr, NULL }, ++ { "SQLGidField", add_globalstr, NULL }, ++ { "SQLPasswordField", add_globalstr, NULL }, ++ { "SQLHomedirField", add_globalstr, NULL }, ++ { "SQLLoginCountField", add_globalstr, NULL }, ++ { "SQLHomedir", add_globalstr, NULL }, ++ ++ { "SQLKeyField", add_globalstr, NULL }, ++ { "SQLKey", add_virtualstr, NULL }, ++ ++ { "SQLAuthoritative", add_virtualbool, NULL }, ++ { "SQLEncryptedPasswords", add_globalbool, NULL }, ++ { "SQLPlaintextPasswords", add_globalbool, NULL }, ++ ++ { NULL, NULL, NULL } ++ ++/* *INDENT-ON* */ ++}; ++ ++/* **************************************************************** */ ++ ++static int ++sqlpw_child_init () ++{ ++ config_rec *c; ++ MODRET mr; ++ ++ memset (&g, 0, sizeof (g)); ++ g.ok = TRUE; ++ ++ g.sql_passwd = get_param_ptr (CURRENT_CONF, "SQLPasswordField", FALSE); ++ g.sql_flogs = get_param_ptr (CURRENT_CONF, "SQLLoginCountField", FALSE); ++ g.sql_uid = get_param_ptr (CURRENT_CONF, "SQLUidField", FALSE); ++ g.sql_gid = get_param_ptr (CURRENT_CONF, "SQLGidField", FALSE); ++ ++ if (!(g.homedir = get_param_ptr (CURRENT_CONF, "SQLHomedir", FALSE))) ++ { ++ g.sql_fhdir = get_param_ptr (CURRENT_CONF, "SQLHomedirField", FALSE); ++ } ++ if ((c = find_config (CURRENT_CONF, CONF_PARAM, "SQLLogHosts", FALSE))) ++ { ++ g.sql_fhost = c->argv[0]; ++ g.sql_faddr = c->argv[1]; ++ g.sql_ftime = c->argv[2]; ++ } ++ if ((c = find_config (CURRENT_CONF, CONF_PARAM, "SQLLogStats", FALSE))) ++ { ++ g.sql_fstor = c->argv[0]; ++ g.sql_fretr = c->argv[1]; ++ g.sql_bstor = c->argv[2]; ++ g.sql_bretr = c->argv[3]; ++ } ++ if ((c = find_config (CURRENT_CONF, CONF_PARAM, "SQLRatios", FALSE))) ++ { ++ if (!g.sql_fstor) ++ log_pri (LOG_WARNING, "sqlpw: warning: SQLRatios directive " ++ "ineffective without SQLLogStats on"); ++ g.sql_frate = c->argv[0]; ++ g.sql_fcred = c->argv[1]; ++ g.sql_brate = c->argv[2]; ++ g.sql_bcred = c->argv[3]; ++ } ++ if ((c = find_config (CURRENT_CONF, CONF_PARAM, "SQLLogHits", FALSE))) ++ { ++ g.sql_hittable = c->argv[0]; ++ g.sql_filename = c->argv[1]; ++ g.sql_hits = c->argv[2]; ++ g.sql_dir = c->argv[3]; ++ } ++ g.sql_fcdir = get_param_ptr (CURRENT_CONF, "SQLLogDirs", FALSE); ++ ++ g.sql_usertable = get_param_ptr (CURRENT_CONF, "SQLUserTable", ++ FALSE) ? : "users"; ++ g.sql_userid = get_param_ptr (CURRENT_CONF, "SQLUsernameField", ++ FALSE) ? : "userid"; ++ ++ g.sql_keyfld = get_param_ptr (CURRENT_CONF, "SQLKeyField", FALSE); ++ g.sql_key = get_param_ptr (CURRENT_CONF, "SQLKey", FALSE); ++ ++ if (!(g.homedir || g.sql_fhdir) && !g.sql_fhost ++ && !g.sql_fstor && !g.sql_fcdir) ++ return 0; ++ ++ mr = modsql_open (NULL); ++ if (MODRET_ISHANDLED (mr)) ++ { ++ log_debug (DEBUG3, "%s: configured: %s%s%s%s%s%s%s%s", ++ MOD_SQL_VERSION, ++ (g.sql_passwd && (g.homedir || g.sql_fhdir)) ++ ? "auth " : "", ++ g.homedir ? "homedir " : "", ++ g.sql_fhdir ? "homedirfield " : "", ++ g.sql_fhost ? "loghosts " : "", ++ g.sql_fstor ? "logstats " : "", ++ g.sql_frate ? "ratios " : "", ++ g.sql_hittable ? "loghits " : "", ++ g.sql_fcdir ? "logdirs " : ""); ++ } ++ else ++ { ++ memset (&g, 0, sizeof (g)); ++ log_debug (DEBUG3, "%s: unconfigured: no backend could connect", ++ MOD_SQL_VERSION); ++ } ++ return 0; ++} ++ ++static int ++sqlpw_parent_init (void) ++{ ++ /* FIXME: add db init stuff once parent_init() actually works. */ ++ return 0; ++} ++ ++module sqlpw_module = { ++ NULL, NULL, /* Always NULL */ ++ 0x20, /* API Version 2.0 */ ++ "sql", ++ sqlpw_conftab, /* SQL configuration handler table */ ++ sqlpw_cmdtab, /* SQL command handler table */ ++ sqlpw_authtab, /* SQL authentication handler table */ ++ sqlpw_parent_init, /* Pre-fork "parent mode" init */ ++ sqlpw_child_init /* Post-fork "child mode" init */ ++}; diff --git a/ftp/proftpd/files/patch-bc b/ftp/proftpd/files/patch-bc new file mode 100644 index 000000000000..bd908a4fa9fa --- /dev/null +++ b/ftp/proftpd/files/patch-bc @@ -0,0 +1,19 @@ +--- contrib/mod_sqlpw.c.old Sun Feb 11 19:52:06 2001 ++++ contrib/mod_sqlpw.c Sun Feb 11 19:53:42 2001 +@@ -302,8 +302,6 @@ + if (!g.homedir) + return DECLINED (cmd); + +- if (!g.pw.pw_name) +- { + g.pw.pw_name = pstrdup(session.pool, cmd->argv[0]); + if (g.sql_uid) + g.pw.pw_uid = atoi (_uservar (cmd, cmd->argv[0], g.sql_uid) ? : "0"); +@@ -323,7 +321,6 @@ + /* FIXME: unnecessary mysqlism */ + mysql_escape_string (g.user, g.pw.pw_name, strlen (g.pw.pw_name)); + g.user[ARBITRARY_MAX - 1] = 0; +- } + + return mod_create_data (cmd, &g.pw); + } diff --git a/ftp/proftpd/files/patch-bd b/ftp/proftpd/files/patch-bd new file mode 100644 index 000000000000..7eb41bc857e8 --- /dev/null +++ b/ftp/proftpd/files/patch-bd @@ -0,0 +1,21 @@ +--- contrib/mod_sqlpw.c.old Sun Feb 11 20:14:40 2001 ++++ contrib/mod_sqlpw.c Sun Feb 11 20:16:00 2001 +@@ -400,9 +400,6 @@ + int return_type; + int retval = AUTH_NOPWD; + +- if (!g.sql_passwd || !g.homedir) +- return DECLINED (cmd); +- + /* Figure out our default return style: Whether or not SQL should + * allow other auth modules a shot at this user or not is controlled + * by the parameter "SQLAuthoritative". Like mod_pam this +@@ -418,6 +415,8 @@ + if ((user = cmd->argv[0]) == NULL) + return return_type ? ERROR (cmd) : DECLINED (cmd); + if ((pass = cmd->argv[1]) == NULL) ++ return return_type ? ERROR (cmd) : DECLINED (cmd); ++ if (!g.sql_passwd || !g.homedir) + return return_type ? ERROR (cmd) : DECLINED (cmd); + + if (!g.pass diff --git a/ftp/proftpd/files/patch-be b/ftp/proftpd/files/patch-be new file mode 100644 index 000000000000..7a6578032734 --- /dev/null +++ b/ftp/proftpd/files/patch-be @@ -0,0 +1,21 @@ +--- contrib/mod_mysql.c.old Sun Feb 11 20:19:00 2001 ++++ contrib/mod_mysql.c Sun Feb 11 20:21:29 2001 +@@ -100,6 +100,9 @@ + mysql_get_client_info (), mysql_get_server_info (mysqldb), + g.sql_user, g.sql_host); + ++ if (mysqldb) ++ mysql_select_db (mysqldb, g.sql_dbname); ++ + return HANDLED (cmd); + } + +@@ -115,7 +118,7 @@ + + /* This forces a quick ping of the remote server, so we know if its there. */ + if (mysqldb) +- mysql_select_db (mysqldb, g.sql_dbname); ++ mysql_ping( mysqldb ); + + if (!mysqldb + || ((error = mysql_query (mysqldb, query)) |