head 1.29; access; symbols OPENPKG_E1_MP_HEAD:1.19 OPENPKG_E1_MP:1.19 OPENPKG_E1_MP_2_STABLE:1.12.2.1 OPENPKG_E1_FP:1.12.2.1 OPENPKG_2_STABLE_MP:1.21 OPENPKG_2_STABLE_20061018:1.12.2.1 OPENPKG_2_STABLE_20060622:1.12 OPENPKG_2_STABLE:1.12.0.2 OPENPKG_2_STABLE_BP:1.12 OPENPKG_2_5_RELEASE:1.10 OPENPKG_2_5_SOLID:1.10.0.2 OPENPKG_2_5_SOLID_BP:1.10 OPENPKG_2_4_RELEASE:1.8 OPENPKG_2_4_SOLID:1.8.0.2 OPENPKG_2_4_SOLID_BP:1.8 OPENPKG_CW_FP:1.7 OPENPKG_2_3_RELEASE:1.7 OPENPKG_2_3_SOLID:1.7.0.2 OPENPKG_2_3_SOLID_BP:1.7 OPENPKG_2_2_RELEASE:1.6 OPENPKG_2_2_SOLID:1.6.0.6 OPENPKG_2_2_SOLID_BP:1.6 OPENPKG_2_1_RELEASE:1.6 OPENPKG_2_1_SOLID:1.6.0.4 OPENPKG_2_1_SOLID_BP:1.6 OPENPKG_2_0_RELEASE:1.6 OPENPKG_2_0_SOLID:1.6.0.2 OPENPKG_2_0_SOLID_BP:1.6 OPENPKG_1_3_RELEASE:1.2.2.2 OPENPKG_1_3_SOLID:1.2.2.2.0.2 OPENPKG_1_3_SOLID_BP:1.2.2.2 OPENPKG_1_STABLE_MP:1.5 OPENPKG_1_2_RELEASE:1.2.4.1 OPENPKG_1_2_SOLID:1.2.0.4 OPENPKG_1_2_SOLID_BP:1.2 OPENPKG_1_STABLE:1.2.0.2 OPENPKG_1_STABLE_BP:1.2; locks; strict; comment @# @; expand @o@; 1.29 date 2009.07.01.10.43.06; author rse; state Exp; branches; next 1.28; commitid VPh92qk9JY13RZTt; 1.28 date 2009.01.27.18.41.00; author rse; state Exp; branches; next 1.27; commitid f9NKKQZCDiBTt7At; 1.27 date 2008.09.06.16.02.51; author rse; state Exp; branches; next 1.26; commitid voYabCYURYXBcJht; 1.26 date 2007.10.11.15.58.07; author tho; state Exp; branches; next 1.25; commitid emoh7igwTbvEObBs; 1.25 date 2007.10.06.07.55.06; author rse; state Exp; branches; next 1.24; commitid WczjgF3I2DIUivAs; 1.24 date 2007.07.25.08.30.54; author rse; state Exp; branches; next 1.23; commitid kmY4WhrNLAYFQ7rs; 1.23 date 2007.05.22.09.49.57; author rse; state Exp; branches; next 1.22; commitid kXbBn83sXHrklUis; 1.22 date 2007.04.13.19.24.06; author rse; state Exp; branches; next 1.21; commitid fdCh2mQDVAr2MWds; 1.21 date 2007.01.19.12.49.16; author rse; state Exp; branches; next 1.20; commitid mBLrGBZeIO1Zh73s; 1.20 date 2007.01.19.11.56.27; author rse; state Exp; branches; next 1.19; commitid 8uNrrb4xuUuRZ63s; 1.19 date 2006.12.06.17.51.08; author rse; state Exp; branches; next 1.18; commitid 7cA1pB0Ud52enuXr; 1.18 date 2006.12.06.08.07.43; author rse; state Exp; branches; next 1.17; commitid XCOMXvCSVK359rXr; 1.17 date 2006.12.06.07.03.13; author rse; state Exp; branches; next 1.16; commitid 50xL5SCUw3eXMqXr; 1.16 date 2006.11.28.07.48.54; author rse; state Exp; branches; next 1.15; commitid cvZMOiLn1QLzipWr; 1.15 date 2006.11.16.21.53.55; author rse; state Exp; branches; next 1.14; commitid ufxYQdv2cOpnmWUr; 1.14 date 2006.11.16.21.26.52; author rse; state Exp; branches; next 1.13; commitid vjZz1A2XvqC5dWUr; 1.13 date 2006.06.27.14.12.21; author rse; state Exp; branches; next 1.12; commitid NExaeL9hFU01nECr; 1.12 date 2005.11.07.20.37.58; author rse; state Exp; branches 1.12.2.1; next 1.11; commitid ssS5aqWsU5nFXR8r; 1.11 date 2005.11.01.07.33.46; author rse; state dead; branches; next 1.10; commitid SbfTH1ebZKJAO18r; 1.10 date 2005.09.27.17.43.40; author rse; state Exp; branches; next 1.9; 1.9 date 2005.09.11.11.17.46; author rse; state Exp; branches; next 1.8; 1.8 date 2005.04.11.08.50.44; author rse; state dead; branches 1.8.2.1; next 1.7; 1.7 date 2004.12.07.12.03.07; author rse; state Exp; branches 1.7.2.1; next 1.6; 1.6 date 2003.07.29.09.58.52; author cs; state dead; branches 1.6.2.1; next 1.5; 1.5 date 2003.07.02.15.25.55; author thl; state Exp; branches; next 1.4; 1.4 date 2003.03.04.19.07.08; author mlelstv; state dead; branches; next 1.3; 1.3 date 2003.01.20.11.31.23; author rse; state Exp; branches; next 1.2; 1.2 date 2002.06.10.08.58.47; author rse; state dead; branches 1.2.2.1 1.2.4.1; next 1.1; 1.1 date 2002.05.29.19.56.15; author rse; state Exp; branches; next ; 1.12.2.1 date 2006.06.27.14.13.16; author rse; state Exp; branches; next 1.12.2.2; commitid 3BCX1jo3swZknECr; 1.12.2.2 date 2006.11.16.21.27.49; author rse; state Exp; branches; next 1.12.2.3; commitid 6jSnPF7DIhlqdWUr; 1.12.2.3 date 2006.11.16.21.54.44; author rse; state Exp; branches; next 1.12.2.4; commitid roKQ7VRScwaFmWUr; 1.12.2.4 date 2006.11.28.07.49.57; author rse; state Exp; branches; next 1.12.2.5; commitid y3IzNKAWpGCVipWr; 1.12.2.5 date 2006.12.22.19.13.34; author thl; state Exp; branches; next 1.12.2.6; commitid 2LefOfqsS8nsjyZr; 1.12.2.6 date 2007.02.07.20.36.41; author thl; state Exp; branches; next ; commitid buiDpkvFRFCkgB5s; 1.8.2.1 date 2005.09.06.13.59.54; author rse; state Exp; branches; next ; 1.7.2.1 date 2005.09.06.14.04.53; author rse; state Exp; branches; next ; 1.6.2.1 date 2004.04.30.07.58.36; author rse; state Exp; branches; next ; 1.2.2.1 date 2003.01.20.11.32.58; author rse; state Exp; branches; next 1.2.2.2; 1.2.2.2 date 2003.07.24.20.45.09; author rse; state Exp; branches 1.2.2.2.2.1; next ; 1.2.2.2.2.1 date 2003.09.24.07.16.02; author rse; state Exp; branches; next 1.2.2.2.2.2; 1.2.2.2.2.2 date 2003.10.17.09.33.52; author thl; state Exp; branches; next ; 1.2.4.1 date 2003.01.20.11.34.34; author rse; state Exp; branches; next 1.2.4.2; 1.2.4.2 date 2003.09.24.07.08.59; author rse; state Exp; branches; next 1.2.4.3; 1.2.4.3 date 2003.10.17.09.35.00; author thl; state Exp; branches; next ; desc @@ 1.29 log @upgrading package: proftpd 1.3.2 -> 1.3.3rc1 @ text @Index: mod_exec/mod_exec.c --- mod_exec/mod_exec.c.orig 2008-11-14 16:32:42 +0100 +++ mod_exec/mod_exec.c 2009-07-01 12:37:29 +0200 @@@@ -212,7 +212,7 @@@@ pr_signals_block(); PRIVS_ROOT - res = log_openfile(exec_logname, &exec_logfd, 0640); + res = pr_log_openfile(exec_logname, &exec_logfd, 0640); PRIVS_RELINQUISH pr_signals_unblock(); Index: mod_otp/mod_otp.c --- mod_otp/mod_otp.c.orig 2006-12-06 17:13:06 +0100 +++ mod_otp/mod_otp.c 2009-07-01 12:37:18 +0200 @@@@ -79,7 +79,7 @@@@ CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL); bool = get_boolean(cmd, 1); - if ((bool == -1) + if (bool == -1) CONF_ERROR(cmd, "expecting Boolean parameter"); c = add_config_param(cmd->argv[0], 1, NULL); @@@@ -128,7 +128,7 @@@@ ": error generating challenge for user '%s': %s", cmd->argv[1], str); } else - pr_add_response_dup(R_DUP, "Challenge: [ %s ]", challenge); + pr_response_add(R_DUP, "Challenge: [ %s ]", challenge); return DECLINED(cmd); } Index: mod_sql_odbc/mod_sql_odbc.c --- mod_sql_odbc/mod_sql_odbc.c.orig 2007-04-17 17:05:18 +0200 +++ mod_sql_odbc/mod_sql_odbc.c 2009-07-01 12:37:18 +0200 @@@@ -890,8 +890,8 @@@@ /* Set up our timer, if necessary. */ if (entry->ttl > 0) { - entry->timer = add_timer(entry->ttl, -1, &sql_odbc_module, - sqlodbc_timer_cb); + entry->timer = pr_timer_add(entry->ttl, -1, &sql_odbc_module, + sqlodbc_timer_cb, "mod_sql_odbc TTL"); sql_log(DEBUG_INFO, "'%s' connection: %d second timer started", entry->name, entry->ttl); Index: mod_sql_sqlite/mod_sql_sqlite.c --- mod_sql_sqlite/mod_sql_sqlite.c.orig 2007-05-21 17:37:11 +0200 +++ mod_sql_sqlite/mod_sql_sqlite.c 2009-07-01 12:37:18 +0200 @@@@ -236,8 +236,8 @@@@ /* Set up our timer, if necessary. */ if (entry->ttl > 0) { - entry->timer = add_timer(entry->ttl, -1, &sql_sqlite_module, - sql_sqlite_timer_cb); + entry->timer = pr_timer_add(entry->ttl, -1, &sql_sqlite_module, + sql_sqlite_timer_cb, "mod_sql_sqlite TTL"); sql_log(DEBUG_INFO, "'%s' connection: %d second timer started", entry->name, entry->ttl); Index: mod_time/mod_time.c --- mod_time/mod_time.c.orig 2004-05-12 20:57:06 +0200 +++ mod_time/mod_time.c 2009-07-01 12:37:38 +0200 @@@@ -146,7 +146,7 @@@@ /* If we don't have a password file, we create an empty array and punt. */ if (!pw) { - if (!name || !(pw = (struct passwd *) auth_getpwnam(p, name))) { + if (!name || !(pw = (struct passwd *) pr_auth_getpwnam(p, name))) { *gids = make_array(p, 2, sizeof(gid_t)); *groups = make_array(p, 2, sizeof(char *)); return; @@@@ -172,7 +172,7 @@@@ /* Now populate the names of the groups. */ for (i = 0; i < total; i++) { - if ((gr = (struct group *) auth_getgrgid(p, ((gid_t *) xgids->elts)[i]))) + if ((gr = (struct group *) pr_auth_getgrgid(p, ((gid_t *) xgids->elts)[i]))) *((char **) push_array(xgroups)) = pstrdup(p, gr->gr_name); } @@@@ -188,7 +188,7 @@@@ /* Nothing there...punt. */ if (!pw) { - if (!name || !(pw = (struct passwd *) auth_getpwnam(p, name))) { + if (!name || !(pw = (struct passwd *) pr_auth_getpwnam(p, name))) { *gids = xgids; *groups = xgroups; return; @@@@ -197,16 +197,16 @@@@ /* Populate the first group name. */ - if ((gr = auth_getgrgid(p, pw->pw_gid)) != NULL) + if ((gr = pr_auth_getgrgid(p, pw->pw_gid)) != NULL) *((char **) push_array(xgroups)) = pstrdup(p, gr->gr_name); - auth_setgrent(p); + pr_auth_setgrent(p); /* This is where things get slow, expensive, and ugly. * Loop through everything, checking to make sure we haven't already added * it. This is why we have getgroups() and company. */ - while ((gr = auth_getgrent(p)) != NULL && gr->gr_mem) + while ((gr = pr_auth_getgrent(p)) != NULL && gr->gr_mem) for (gr_mem = gr->gr_mem; *gr_mem; gr_mem++) { if (strcmp(*gr_mem, pw->pw_name) == 0) { *((int *) push_array(xgids)) = (int) gr->gr_gid; @@@@ -362,7 +362,7 @@@@ /* find the matching NamedTime */ if ((named_time = get_named_time((time_map->namev)[i])) == NULL) { - log_debug(DEBUG0, MOD_TIME_VERSION + pr_log_debug(DEBUG0, MOD_TIME_VERSION ": error: no matching NamedTime found for '%s'", (time_map->namev)[i]); continue; @@@@ -374,7 +374,7 @@@@ if (is_allowed_time(named_time)) { /* Success! Return NULL, and allow the requested action to occur */ - log_debug(DEBUG3, MOD_TIME_VERSION + pr_log_debug(DEBUG3, MOD_TIME_VERSION ": command '%s' allowed by NamedTime '%s'", cmd->argv[0], (time_map->namev)[i]); return NULL; @@@@ -385,7 +385,7 @@@@ * command. It doesn't -- yet -- because there may be other * NamedTimes in the list that do allow the command. */ - log_debug(DEBUG3, MOD_TIME_VERSION + pr_log_debug(DEBUG3, MOD_TIME_VERSION ": command '%s' denied by NamedTime '%s'", cmd->argv[0], (time_map->namev)[i]); } @@@@ -415,7 +415,7 @@@@ return after_hours_mesg; } else { - log_debug(DEBUG2, MOD_TIME_VERSION + pr_log_debug(DEBUG2, MOD_TIME_VERSION ": error finding DisplayAfterHours '%s': %s", after_hours_mesg, strerror(errno)); return ""; @@@@ -566,7 +566,7 @@@@ * is the case, default to using localtime(), and report the * problem. */ - log_pri(LOG_INFO, "gmtime() returned NULL -- using localtime()"); + pr_log_pri(LOG_INFO, "gmtime() returned NULL -- using localtime()"); timep = localtime(&system_time); } @@@@ -634,7 +634,7 @@@@ if (!session.user) { /* Populate the pw struct, check for a NULL return value. */ - if ((pw = auth_getpwnam(cmd->tmp_pool, user)) == NULL) + if ((pw = pr_auth_getpwnam(cmd->tmp_pool, user)) == NULL) return NULL; time_user = pstrdup(session.pool, pw->pw_name); @@@@ -1603,7 +1603,7 @@@@ "%R", (session.c && session.c->remote_name ? session.c->remote_name : "(unknown)"), "%L", main_server->ServerFQDN, "%U", user, - "%u", session.ident_user, + "%u", session.user, "%M", mesg_max, "%N", mesg_cur, "%E", main_server->ServerAdmin, @@@@ -1929,12 +1929,12 @@@@ * the command pass now. */ if ((deny_mesg_file = get_deny_mesg(cmd)) == NULL) { - log_debug(DEBUG3, MOD_TIME_VERSION ": %s allowed by configuration", + pr_log_debug(DEBUG3, MOD_TIME_VERSION ": %s allowed by configuration", cmd->argv[0]); return DECLINED(cmd); } - log_debug(DEBUG3, MOD_TIME_VERSION ": %s denied by configuration", + pr_log_debug(DEBUG3, MOD_TIME_VERSION ": %s denied by configuration", cmd->argv[0]); /* Check for an empty deny_mesg_file string, signalling no message. @@@@ -1961,7 +1961,7 @@@@ */ if (strlen(deny_mesg_file) > 0) { - log_debug(DEBUG4, MOD_TIME_VERSION ": displaying '%s'", deny_mesg_file); + pr_log_debug(DEBUG4, MOD_TIME_VERSION ": displaying '%s'", deny_mesg_file); if (strcmp(cmd->argv[0], C_PASV) == 0 || strcmp(cmd->argv[0], C_PORT) == 0) @@@@ -1982,11 +1982,11 @@@@ if ((denymesg = (char *) get_param_ptr((session.anon_config ? session.anon_config->subset : cmd->server->conf), "AccessDenyMsg", FALSE)) != NULL) { - log_debug(DEBUG5, MOD_TIME_VERSION ": displaying AccessDenyMsg"); + pr_log_debug(DEBUG5, MOD_TIME_VERSION ": displaying AccessDenyMsg"); denymesg = sreplace(cmd->tmp_pool, denymesg, "%u", user, NULL); } else { - log_debug(DEBUG5, MOD_TIME_VERSION ": displaying default message"); + pr_log_debug(DEBUG5, MOD_TIME_VERSION ": displaying default message"); denymesg = pstrcat(cmd->tmp_pool, cmd->argv[0], " not allowed at this time.", NULL); } @@@@ -2025,11 +2025,11 @@@@ * If none are found, let the command pass now. */ if ((deny_mesg_file = get_deny_mesg(cmd)) == NULL) { - log_debug(DEBUG5, MOD_TIME_VERSION ": login allowed by configuration"); + pr_log_debug(DEBUG5, MOD_TIME_VERSION ": login allowed by configuration"); return DECLINED(cmd); } - log_debug(DEBUG3, MOD_TIME_VERSION ": login denied by configuration"); + pr_log_debug(DEBUG3, MOD_TIME_VERSION ": login denied by configuration"); /* Check for an empty deny_mesg_file string, signalling no message. * Deny connection with a 421 error. @ 1.28 log @add optional MD5 module, add optional SFTP module(s), fix building of SQLite and ODBC modules @ text @d1 12 d15 1 a15 1 +++ mod_otp/mod_otp.c 2009-01-27 08:33:56 +0100 d36 1 a36 1 +++ mod_sql_odbc/mod_sql_odbc.c 2009-01-27 19:16:56 +0100 d50 1 a50 1 +++ mod_sql_sqlite/mod_sql_sqlite.c 2009-01-27 19:15:57 +0100 d64 1 a64 1 +++ mod_time/mod_time.c 2009-01-27 08:33:56 +0100 d112 45 d175 52 @ 1.27 log @upgrading package: proftpd 1.3.1 -> 1.3.2rc1 @ text @d3 1 a3 1 +++ mod_otp/mod_otp.c 2008-09-06 09:58:58 +0200 d22 28 d52 1 a52 1 +++ mod_time/mod_time.c 2008-09-06 09:59:29 +0200 @ 1.26 log @fixed configure not checking for system getopt* if compilled with --without-getopt @ text @d3 1 a3 1 +++ mod_otp/mod_otp.c 2007-10-06 09:52:27 +0200 d24 1 a24 1 +++ mod_time/mod_time.c 2007-10-06 09:52:27 +0200 d81 9 a89 42 Index: modules/mod_auth_unix.c --- modules/mod_auth_unix.c.orig 2006-06-29 19:16:23 +0200 +++ modules/mod_auth_unix.c 2007-10-06 09:52:27 +0200 @@@@ -243,7 +243,7 @@@@ return gr; } -inline static int _compare_uid(idmap_t *m1, idmap_t *m2) { +static int _compare_uid(idmap_t *m1, idmap_t *m2) { if (m1->id.uid < m2->id.uid) return -1; @@@@ -253,7 +253,7 @@@@ return 0; } -inline static int _compare_gid(idmap_t *m1, idmap_t *m2) { +static int _compare_gid(idmap_t *m1, idmap_t *m2) { if (m1->id.gid < m2->id.gid) return -1; @@@@ -263,7 +263,7 @@@@ return 0; } -inline static int _compare_id(xaset_t **table, idauth_t id, idauth_t idcomp) { +static int _compare_id(xaset_t **table, idauth_t id, idauth_t idcomp) { if (table == uid_table) return id.uid == idcomp.uid; else Index: configure --- configure.orig 2007-10-11 12:22:28.000000000 +0000 +++ configure 2007-10-11 13:01:52.000000000 +0000 @@@@ -19236,7 +19236,7 @@@@ if test "${with_getopt+set}" = set; then withval="$with_getopt" - if test "$withval" != "no" ; then + if test "$withval" = "no" ; then for ac_func in getopt do @ 1.25 log @upgrading package: proftpd 1.3.1rc3 -> 1.3.1 @ text @d111 12 @ 1.24 log @upgrading package: proftpd 1.3.0a -> 1.3.1rc3 @ text @d3 1 a3 1 +++ mod_otp/mod_otp.c 2007-07-25 10:24:36 +0200 d24 1 a24 1 +++ mod_time/mod_time.c 2007-07-25 10:24:36 +0200 d83 1 a83 1 +++ modules/mod_auth_unix.c 2007-07-25 10:24:36 +0200 a110 19 Index: src/dirtree.c --- src/dirtree.c.orig 2007-03-22 04:54:20 +0100 +++ src/dirtree.c 2007-07-25 10:24:36 +0200 @@@@ -2911,12 +2911,13 @@@@ * this address. */ snprintf(ipbuf, sizeof(ipbuf), "::ffff:%s", ipstr); - ipstr = ipbuf; + ipstr = pstrdup(s->pool, ipbuf); } } #endif /* PR_USE_IPV6 */ - pr_conf_add_server_config_param_str(s, "_bind", 1, ipstr); + if (ipstr) + pr_conf_add_server_config_param_str(s, "_bind", 1, ipstr); } } @ 1.23 log @modifying package: proftpd-1.3.0a 20070518 -> 20070522 @ text @d1 18 a18 6 Index: mod_sql_sqlite/mod_sql_sqlite.c --- mod_sql_sqlite/mod_sql_sqlite.c.orig 2007-05-21 17:37:11 +0200 +++ mod_sql_sqlite/mod_sql_sqlite.c 2007-05-22 11:38:32 +0200 @@@@ -343,7 +343,7 @@@@ "lists mod_sql *before* mod_sql_sqlite, and recompile."); sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_defineconnection"); d20 21 a40 2 - return PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "uninitialized module"); + return ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "uninitialized module"); d43 10 a52 2 conn = (db_conn_t *) palloc(conn_pool, sizeof(db_conn_t)); @@@@ -706,7 +706,7 @@@@ d54 21 a74 5 MODRET sql_sqlite_prepare(cmd_rec *cmd) { if (cmd->argc != 1) { - return PR_ERROR(cmd); + return ERROR(cmd); } d76 3 a78 11 conn_pool = (pool *) cmd->argv[0]; Index: mod_vroot/mod_vroot.c --- mod_vroot/mod_vroot.c.orig 2006-12-06 03:58:51 +0100 +++ mod_vroot/mod_vroot.c 2006-12-06 08:00:45 +0100 @@@@ -582,7 +582,7 @@@@ CONF_ERROR(cmd, "must be an absolute path"); add_config_param_str(cmd->argv[0], 1, cmd->argv[1]); - return PR_HANDLED(cmd); + return HANDLED(cmd); } d80 1 a80 1 /* usage: VRootOptions opt1 opt2 ... optN */ d82 3 a84 3 --- modules/mod_auth_unix.c.orig 2005-07-03 20:52:02 +0200 +++ modules/mod_auth_unix.c 2006-06-27 16:10:20 +0200 @@@@ -248,7 +248,7 @@@@ d93 1 a93 1 @@@@ -258,7 +258,7 @@@@ d102 1 a102 1 @@@@ -268,7 +268,7 @@@@ d111 17 a127 49 ----------------------------------------------------------------------------- Security Fix (CVE-2006-5815, according to CVE, but vendor thinks differently) Security Fix (CVE-2006-6171, according to OpenPKG GmbH information) Index: src/main.c --- src/main.c.orig 2006-03-15 20:41:01 +0100 +++ src/main.c 2006-11-15 16:47:29 +0100 @@@@ -116,6 +116,8 @@@@ static char sbuf[PR_TUNABLE_BUFFER_SIZE] = {'\0'}; +#define PR_DEFAULT_CMD_BUFSZ 512 + static char **Argv = NULL; static char *LastArgv = NULL; static const char *PidPath = PR_PID_FILE_PATH; @@@@ -820,16 +822,25 @@@@ pr_timer_reset(TIMER_IDLE, NULL); if (cmd_buf_size == -1) { - long *buf_size = get_param_ptr(main_server->conf, - "CommandBufferSize", FALSE); + int *bufsz = get_param_ptr(main_server->conf, "CommandBufferSize", + FALSE); - if (buf_size == NULL || *buf_size <= 0) - cmd_buf_size = 512; + if (bufsz == NULL || + *bufsz <= 0) { + pr_log_pri(PR_LOG_WARNING, "invalid CommandBufferSize size (%d) " + "given, resetting to default buffer size (%u)", + bufsz != NULL ? *bufsz : 0, (unsigned int) PR_DEFAULT_CMD_BUFSZ); + cmd_buf_size = PR_DEFAULT_CMD_BUFSZ; + + } else if (*bufsz + 1 > sizeof(buf)) { + pr_log_pri(PR_LOG_WARNING, "invalid CommandBufferSize size (%d) " + "given, resetting to default buffer size (%u)", + *bufsz, (unsigned int) PR_DEFAULT_CMD_BUFSZ); + cmd_buf_size = PR_DEFAULT_CMD_BUFSZ; - else if (*buf_size + 1 > sizeof(buf)) { - pr_log_pri(PR_LOG_WARNING, "Invalid CommandBufferSize size given. " - "Resetting to 512."); - cmd_buf_size = 512; + } else { + pr_log_debug(DEBUG1, "setting CommandBufferSize to %d", *bufsz); + cmd_buf_size = (long) *bufsz; d129 1 a129 1071 } ----------------------------------------------------------------------------- Security Fix Index: contrib/mod_tls.c --- contrib/mod_tls.c.orig 2005-11-08 18:59:49 +0100 +++ contrib/mod_tls.c 2006-11-15 17:54:43 +0100 @@@@ -2421,6 +2421,8 @@@@ datalen = BIO_get_mem_data(mem, &data); if (data) { + if (datalen > sizeof(buf)-1) + datalen = sizeof(buf)-1; memset(&buf, '\0', sizeof(buf)); memcpy(buf, data, datalen); buf[datalen] = '\0'; ----------------------------------------------------------------------------- Fix Endless Looping. (backported from http://proftp.cvs.sourceforge.net/proftp/proftpd/src/auth.c?r1=1.46&r2=1.47) "Make sure that dispatch_auth() does not loop endlessly, if there are never any ERROR or HANDLED returns from the auth module handlers. Simply keep track of the starting table, and watch the iterator table; when the two match, we have looped through the auth handlers, and will assume that the entire auth command has been DECLINED." Index: src/auth.c --- src/auth.c.orig 2005-06-14 20:11:12 +0200 +++ src/auth.c 2007-01-19 10:38:19 +0100 @@@@ -64,28 +64,35 @@@@ } static modret_t *dispatch_auth(cmd_rec *cmd, char *match) { - authtable *authtab = NULL; + authtable *start_tab = NULL, *iter_tab = NULL; modret_t *mr = NULL; - authtab = pr_stash_get_symbol(PR_SYM_AUTH, match, NULL, + start_tab = pr_stash_get_symbol(PR_SYM_AUTH, match, NULL, &cmd->stash_index); + iter_tab = start_tab; - while (authtab) { + pr_log_debug(DEBUG6, "dispatching auth request \"%s\": START", match); + while (iter_tab) { pr_log_debug(DEBUG6, "dispatching auth request \"%s\" to module mod_%s", - match, authtab->m->name); + match, iter_tab->m->name); - mr = call_module(authtab->m, authtab->handler, cmd); + mr = call_module(iter_tab->m, iter_tab->handler, cmd); - if (authtab->auth_flags & PR_AUTH_FL_REQUIRED) + if (iter_tab->auth_flags & PR_AUTH_FL_REQUIRED) break; if (MODRET_ISHANDLED(mr) || MODRET_ISERROR(mr)) break; - authtab = pr_stash_get_symbol(PR_SYM_AUTH, match, authtab, + iter_tab = pr_stash_get_symbol(PR_SYM_AUTH, match, iter_tab, &cmd->stash_index); + if (iter_tab == start_tab) { + mr = DECLINED(cmd); + break; + } } + pr_log_debug(DEBUG6, "dispatching auth request \"%s\": END", match); return mr; } ----------------------------------------------------------------------------- Fix Incorrect AuthUserFile iteration. (backported from http://proftp.cvs.sourceforge.net/proftp/proftpd/modules/mod_auth_file.?r1=1.27&r2=1.28) "Bug#2803 - mod_auth_file does not properly iterate through AuthUserFile entries. The issue was one of rewinding an already open AuthUserFile, every time pr_auth_getpwent() was called. The mod_auth_file module has been restructured to avoid this. The code was also substantially changed, removing a lot of dead code for a never-used feature (that of supporting multiple AuthUserFiles within the same server context)." Index: modules/mod_auth_file.c --- modules/mod_auth_file.c.orig 2005-07-03 20:52:02 +0200 +++ modules/mod_auth_file.c 2007-01-19 13:10:40 +0100 @@@@ -52,15 +52,7 @@@@ } authfile_id_t; -typedef struct entry_rec { - struct entry_rec *next, *prev; - char *name; - -} authfile_entry_t; - typedef struct file_rec { - struct file_rec *af_next; - char *af_path; FILE *af_file; @@@@ -84,15 +76,14 @@@@ } authfile_file_t; -static unsigned char af_handle_pw = FALSE, af_handle_gr = FALSE; +/* List of server-specific Authiles */ +static authfile_file_t *af_user_file = NULL; +static authfile_file_t *af_group_file = NULL; + +extern unsigned char persistent_passwd; -/* List of server-specific AuthUserFiles */ -static authfile_file_t *af_user_file_list = NULL; -static authfile_file_t *af_current_user_file = NULL; - -/* List of server-specific AuthGroupFiles */ -static authfile_file_t *af_group_file_list = NULL; -static authfile_file_t *af_current_group_file = NULL; +static int af_setpwent(void); +static int af_setgrent(void); /* Support routines. Move the passwd/group functions out of lib/ into here. */ @@@@ -179,7 +170,8 @@@@ { char *new_buf; - if ((new_buf = realloc(*buf, *buflen)) == NULL) + new_buf = realloc(*buf, *buflen); + if (new_buf == NULL) break; *buf = new_buf; @@@@ -228,13 +220,15 @@@@ sstrncpy(grpbuf, buf, i); - if ((cp = strrchr(grpbuf, '\n'))) + cp = strrchr(grpbuf, '\n'); + if (cp) *cp = '\0'; for (cp = grpbuf, i = 0; i < NGRPFIELDS && cp; i++) { grpfields[i] = cp; - if ((cp = strchr(cp, ':'))) + cp = strchr(cp, ':'); + if (cp) *cp++ = 0; } @@@@ -255,84 +249,76 @@@@ } #endif /* !HAVE_FGETGRENT */ -static unsigned char af_close_file(authfile_file_t *file) { - if (file && file->af_file) { - fclose(file->af_file); - file->af_file = NULL; +static int af_allow_grent(struct group *grp) { + if (!af_group_file) { + errno = EPERM; + return -1; } - return TRUE; -} - -static unsigned char af_open_file(authfile_file_t *file) { - if (file) { - - /* If already opened, rewind */ - if (file->af_file) - rewind(file->af_file); - - else if ((file->af_file = fopen(file->af_path, "r")) == NULL) - return FALSE; - - return TRUE; - } - - return FALSE; -} - -static unsigned char af_allow_grent(authfile_file_t *groupf, - struct group *grp) { - /* Check that the grent is within the ID restrictions (if present). */ - if (groupf->af_restricted_ids) { + if (af_group_file->af_restricted_ids) { - if (grp->gr_gid < groupf->af_min_id.gid) { + if (grp->gr_gid < af_group_file->af_min_id.gid) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping group '%s': " "GID (%u) below the minimum allowed (%u)", grp->gr_name, - (unsigned int) grp->gr_gid, (unsigned int) groupf->af_min_id.gid); - return FALSE; + (unsigned int) grp->gr_gid, + (unsigned int) af_group_file->af_min_id.gid); + errno = EINVAL; + return -1; } - if (grp->gr_gid > groupf->af_max_id.gid) { + if (grp->gr_gid > af_group_file->af_max_id.gid) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping group '%s': " "GID (%u) above the maximum allowed (%u)", grp->gr_name, - (unsigned int) grp->gr_gid, (unsigned int) groupf->af_max_id.gid); - return FALSE; + (unsigned int) grp->gr_gid, + (unsigned int) af_group_file->af_max_id.gid); + errno = EINVAL; + return -1; } } #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) /* Check if the grent has an acceptable name. */ - if (groupf->af_restricted_names) { - int res = regexec(groupf->af_name_regex, grp->gr_name, 0, NULL, 0); + if (af_group_file->af_restricted_names) { + int res = regexec(af_group_file->af_name_regex, grp->gr_name, 0, NULL, 0); - if ((res != 0 && !groupf->af_name_regex_inverted) || - (res == 0 && groupf->af_name_regex_inverted)) { + if ((res != 0 && !af_group_file->af_name_regex_inverted) || + (res == 0 && af_group_file->af_name_regex_inverted)) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping group '%s': " "name '%s' does not meet allowed filter '%s'", grp->gr_name, - grp->gr_name, groupf->af_name_filter); - return FALSE; + grp->gr_name, af_group_file->af_name_filter); + errno = EINVAL; + return -1; } } #endif /* !HAVE_REGEX_H and !HAVE_REGCOMP */ - return TRUE; + return 0; } static void af_endgrent(void) { - af_close_file(af_current_group_file); - af_current_group_file = NULL; + if (af_group_file && + af_group_file->af_file) { + fclose(af_group_file->af_file); + af_group_file->af_file = NULL; + } return; } -static struct group *af_getgrent(authfile_file_t *groupf) { +static struct group *af_getgrent(void) { struct group *grp = NULL; + if (!af_group_file || + !af_group_file->af_file) { + errno = EINVAL; + return NULL; + } + while (TRUE) { #ifdef HAVE_FGETGRENT pr_signals_handle(); - grp = fgetgrent(groupf->af_file); + grp = fgetgrent(af_group_file->af_file); #else char *cp = NULL, *buf = NULL; int buflen = BUFSIZ; @@@@ -343,13 +329,14 @@@@ if (!buf) return NULL; - while (af_getgrentline(&buf, &buflen, groupf->af_file) != NULL) { + while (af_getgrentline(&buf, &buflen, af_group_file->af_file) != NULL) { /* Ignore comment and empty lines */ if (buf[0] == '\0' || buf[0] == '#') continue; - if ((cp = strchr(buf, '\n')) != NULL) + cp = strchr(buf, '\n'); + if (cp != NULL) *cp = '\0'; grp = af_getgrp(buf); @@@@ -363,7 +350,7 @@@@ if (!grp) break; - if (!af_allow_grent(groupf, grp)) + if (af_allow_grent(grp) < 0) continue; break; @@@@ -372,129 +359,156 @@@@ return grp; } -static struct group *af_getgrnam(authfile_file_t *groupf, const char *name) { +static struct group *af_getgrnam(const char *name) { struct group *grp = NULL; - while ((grp = af_getgrent(groupf)) != NULL) - if (!strcmp(name, grp->gr_name)) + if (af_setgrent() < 0) + return NULL; + + while ((grp = af_getgrent()) != NULL) { + if (strcmp(name, grp->gr_name) == 0) { /* Found the requested group */ break; + } + } return grp; } -static struct group *af_getgrgid(authfile_file_t *groupf, gid_t gid) { +static struct group *af_getgrgid(gid_t gid) { struct group *grp = NULL; - while ((grp = af_getgrent(groupf)) != NULL) - if (grp->gr_gid == gid) + if (af_setgrent() < 0) + return NULL; + + while ((grp = af_getgrent()) != NULL) { + if (grp->gr_gid == gid) { /* Found the requested GID */ break; + } + } return grp; } -static unsigned char af_setgrent(void) { - - /* If not already present, start at the top of the list. */ - if (!af_current_group_file) - af_current_group_file = af_group_file_list; +static int af_setgrent(void) { - while (af_current_group_file) { + if (af_group_file) { + if (af_group_file->af_file) { + /* If already opened, rewind */ + rewind(af_group_file->af_file); + return 0; - if (!af_open_file(af_current_group_file)) { - /* Log the error */ - pr_log_pri(PR_LOG_ERR, "error: unable to open group file '%s': %s", - af_current_group_file->af_path, strerror(errno)); + } else { +pr_log_debug(DEBUG0, MOD_AUTH_FILE_VERSION ": af_setgrent: opening AuthGroupFile"); - /* Move to the next file in the list. */ - af_current_group_file = af_current_group_file->af_next; - continue; + af_group_file->af_file = fopen(af_group_file->af_path, "r"); + if (af_group_file->af_file == NULL) { + pr_log_pri(PR_LOG_ERR, "error: unable to open group file '%s': %s", + af_group_file->af_path, strerror(errno)); + return -1; + } - } else { pr_log_debug(DEBUG7, MOD_AUTH_FILE_VERSION ": using group file '%s'", - af_current_group_file->af_path); - return TRUE; + af_group_file->af_path); + return 0; } } - return FALSE; + errno = EPERM; + return -1; } -static unsigned char af_allow_pwent(authfile_file_t *passwdf, - struct passwd *pwd) { +static int af_allow_pwent(struct passwd *pwd) { + if (!af_user_file) { + errno = EPERM; + return -1; + } /* Check that the pwent is within the ID restrictions (if present). */ - if (passwdf->af_restricted_ids) { + if (af_user_file->af_restricted_ids) { - if (pwd->pw_uid < passwdf->af_min_id.uid) { + if (pwd->pw_uid < af_user_file->af_min_id.uid) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping user '%s': " "UID (%u) below the minimum allowed (%u)", pwd->pw_name, - (unsigned int) pwd->pw_uid, (unsigned int) passwdf->af_min_id.uid); - return FALSE; + (unsigned int) pwd->pw_uid, (unsigned int) af_user_file->af_min_id.uid); + errno = EINVAL; + return -1; } - if (pwd->pw_uid > passwdf->af_max_id.gid) { + if (pwd->pw_uid > af_user_file->af_max_id.gid) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping user '%s': " "UID (%u) above the maximum allowed (%u)", pwd->pw_name, - (unsigned int) pwd->pw_uid, (unsigned int) passwdf->af_max_id.uid); - return FALSE; + (unsigned int) pwd->pw_uid, (unsigned int) af_user_file->af_max_id.uid); + errno = EINVAL; + return -1; } } #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) /* Check if the pwent has an acceptable name. */ - if (passwdf->af_restricted_names) { - int res = regexec(passwdf->af_name_regex, pwd->pw_name, 0, NULL, 0); + if (af_user_file->af_restricted_names) { + int res = regexec(af_user_file->af_name_regex, pwd->pw_name, 0, NULL, 0); - if ((res != 0 && !passwdf->af_name_regex_inverted) || - (res == 0 && passwdf->af_name_regex_inverted)) { + if ((res != 0 && !af_user_file->af_name_regex_inverted) || + (res == 0 && af_user_file->af_name_regex_inverted)) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping user '%s': " "name '%s' does not meet allowed filter '%s'", pwd->pw_name, - pwd->pw_name, passwdf->af_name_filter); - return FALSE; + pwd->pw_name, af_user_file->af_name_filter); + errno = EINVAL; + return -1; } } /* Check if the pwent has an acceptable home directory. */ - if (passwdf->af_restricted_homes) { + if (af_user_file->af_restricted_homes) { - int res = regexec(passwdf->af_home_regex, pwd->pw_dir, 0, NULL, 0); + int res = regexec(af_user_file->af_home_regex, pwd->pw_dir, 0, NULL, 0); - if ((res != 0 && !passwdf->af_home_regex_inverted) || - (res == 0 && passwdf->af_home_regex_inverted)) { + if ((res != 0 && !af_user_file->af_home_regex_inverted) || + (res == 0 && af_user_file->af_home_regex_inverted)) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping user '%s': " "home '%s' does not meet allowed filter '%s'", pwd->pw_name, - pwd->pw_dir, passwdf->af_home_filter); - return FALSE; + pwd->pw_dir, af_user_file->af_home_filter); + errno = EINVAL; + return -1; } } #endif /* !HAVE_REGEX_H and !HAVE_REGCOMP */ - return TRUE; + return 0; } static void af_endpwent(void) { - af_close_file(af_current_user_file); - af_current_user_file = NULL; + if (af_user_file && + af_user_file->af_file) { + fclose(af_user_file->af_file); + af_user_file->af_file = NULL; + } return; } -static struct passwd *af_getpwent(authfile_file_t *passwdf) { +static struct passwd *af_getpwent(void) { struct passwd *pwd = NULL; + if (!af_user_file || + !af_user_file->af_file) { + errno = EINVAL; + return NULL; + } + while (TRUE) { #ifdef HAVE_FGETPWENT pr_signals_handle(); - pwd = fgetpwent(passwdf->af_file); + pwd = fgetpwent(af_user_file->af_file); #else char buf[BUFSIZ] = {'\0'}; pr_signals_handle(); - while (fgets(buf, sizeof(buf), passwdf->af_file) != (char*) 0) { + while (fgets(buf, sizeof(buf), af_user_file->af_file) != (char*) 0) { pr_signals_handle(); /* Ignore empty and comment lines */ @@@@ -511,7 +525,7 @@@@ if (!pwd) break; - if (!af_allow_pwent(passwdf, pwd)) + if (af_allow_pwent(pwd) < 0) continue; break; @@@@ -520,88 +534,84 @@@@ return pwd; } -static struct passwd *af_getpwnam(authfile_file_t *passwdf, const char *name) { +static struct passwd *af_getpwnam(const char *name) { struct passwd *pwd = NULL; - while ((pwd = af_getpwent(passwdf)) != NULL) - if (!strcmp(name, pwd->pw_name)) + if (af_setpwent() < 0) + return NULL; + + while ((pwd = af_getpwent()) != NULL) { + if (strcmp(name, pwd->pw_name) == 0) { /* Found the requested user */ break; + } + } return pwd; } -static char *af_getpwpass(authfile_file_t *passwdf, const char *name) { - struct passwd *pwd = af_getpwnam(passwdf, name); - +static char *af_getpwpass(const char *name) { + struct passwd *pwd = af_getpwnam(name); return pwd ? pwd->pw_passwd : NULL; } -static struct passwd *af_getpwuid(authfile_file_t *passwdf, uid_t uid) { +static struct passwd *af_getpwuid(uid_t uid) { struct passwd *pwd = NULL; - while ((pwd = af_getpwent(passwdf)) != NULL) - if (pwd->pw_uid == uid) + if (af_setpwent() < 0) + return NULL; + + while ((pwd = af_getpwent()) != NULL) { + if (pwd->pw_uid == uid) { /* Found the requested UID */ break; + } + } return pwd; } -static unsigned char af_setpwent(void) { +static int af_setpwent(void) { - /* If not already present, start at the top of the list. */ - if (!af_current_user_file) - af_current_user_file = af_user_file_list; - - while (af_current_user_file) { - - if (!af_open_file(af_current_user_file)) { - /* Log the error */ - pr_log_pri(PR_LOG_ERR, "error: unable to open passwd file '%s': %s", - af_current_user_file->af_path, strerror(errno)); - - /* Move to the next file in the list. */ - af_current_user_file = af_current_user_file->af_next; - continue; + if (af_user_file) { + if (af_user_file->af_file) { + /* If already opened, rewind */ + rewind(af_user_file->af_file); + return 0; } else { +pr_log_debug(DEBUG0, MOD_AUTH_FILE_VERSION ": af_setpwent: opening AuthUserFile '%s'", af_user_file->af_path); + af_user_file->af_file = fopen(af_user_file->af_path, "r"); + if (af_user_file->af_file == NULL) { + pr_log_pri(PR_LOG_ERR, "error: unable to open passwd file '%s': %s", + af_user_file->af_path, strerror(errno)); + return -1; + } + pr_log_debug(DEBUG7, MOD_AUTH_FILE_VERSION ": using passwd file '%s'", - af_current_user_file->af_path); - return TRUE; + af_user_file->af_path); + return 0; } } - return FALSE; + errno = EPERM; + return -1; } /* Authentication handlers. */ MODRET authfile_endpwent(cmd_rec *cmd) { - - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - af_endpwent(); - return DECLINED(cmd); } MODRET authfile_getpwent(cmd_rec *cmd) { struct passwd *pwd = NULL; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (!af_setpwent()) - return DECLINED(cmd); - - pwd = af_getpwent(af_current_user_file); + pwd = af_getpwent(); return pwd ? mod_create_data(cmd, pwd) : DECLINED(cmd); } @@@@ -610,15 +620,11 @@@@ struct passwd *pwd = NULL; const char *name = cmd->argv[0]; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (!af_setpwent()) + if (af_setpwent() < 0) return DECLINED(cmd); /* Ugly -- we iterate through the file. Time-consuming. */ - while ((pwd = af_getpwent(af_current_user_file)) != NULL) + while ((pwd = af_getpwent()) != NULL) if (!strcmp(name, pwd->pw_name)) /* Found the requested name */ @@@@ -631,14 +637,10 @@@@ struct passwd *pwd = NULL; uid_t uid = *((uid_t *) cmd->argv[0]); - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (!af_setpwent()) + if (af_setpwent() < 0) return DECLINED(cmd); - pwd = af_getpwuid(af_current_user_file, uid); + pwd = af_getpwuid(uid); return pwd ? mod_create_data(cmd, pwd) : DECLINED(cmd); } @@@@ -646,70 +648,41 @@@@ MODRET authfile_name2uid(cmd_rec *cmd) { struct passwd *pwd = NULL; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) + if (af_setpwent() < 0) return DECLINED(cmd); - if (!af_setpwent()) - return DECLINED(cmd); - - pwd = af_getpwnam(af_current_user_file, cmd->argv[0]); + pwd = af_getpwnam(cmd->argv[0]); return pwd ? mod_create_data(cmd, (void *) &pwd->pw_uid) : DECLINED(cmd); } MODRET authfile_setpwent(cmd_rec *cmd) { - - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (af_setpwent()) + if (af_setpwent() == 0) return DECLINED(cmd); - pr_log_debug(DEBUG2, - MOD_AUTH_FILE_VERSION ": unable to find useable AuthUserFile"); - return DECLINED(cmd); } MODRET authfile_uid2name(cmd_rec *cmd) { struct passwd *pwd = NULL; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (!af_setpwent()) + if (af_setpwent() < 0) return DECLINED(cmd); - pwd = af_getpwuid(af_current_user_file, *((uid_t *) cmd->argv[0])); + pwd = af_getpwuid(*((uid_t *) cmd->argv[0])); return pwd ? mod_create_data(cmd, pwd->pw_name) : DECLINED(cmd); } MODRET authfile_endgrent(cmd_rec *cmd) { - - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) - return DECLINED(cmd); - af_endgrent(); - return DECLINED(cmd); } MODRET authfile_getgrent(cmd_rec *cmd) { struct group *grp = NULL; - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) - return DECLINED(cmd); - - if (!af_setgrent()) - return DECLINED(cmd); - - grp = af_getgrent(af_current_group_file); + grp = af_getgrent(); return grp ? mod_create_data(cmd, grp) : DECLINED(cmd); } @@@@ -718,14 +691,10 @@@@ struct group *grp = NULL; gid_t gid = *((gid_t *) cmd->argv[0]); - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) + if (af_setgrent() < 0) return DECLINED(cmd); - if (!af_setgrent()) - return DECLINED(cmd); - - grp = af_getgrgid(af_current_group_file, gid); + grp = af_getgrgid(gid); return grp ? mod_create_data(cmd, grp) : DECLINED(cmd); } @@@@ -734,14 +703,10 @@@@ struct group *grp = NULL; const char *name = cmd->argv[0]; - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) - return DECLINED(cmd); - - if (!af_setgrent()) + if (af_setgrent() < 0) return DECLINED(cmd); - while ((grp = af_getgrent(af_current_group_file)) != NULL) + while ((grp = af_getgrent()) != NULL) if (!strcmp(name, grp->gr_name)) /* Found the name requested */ @@@@ -756,14 +721,10 @@@@ array_header *gids = NULL, *groups = NULL; char *name = cmd->argv[0]; - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) + if (af_setpwent() < 0) return DECLINED(cmd); - if (!af_setpwent()) - return DECLINED(cmd); - - if (!af_setgrent()) + if (af_setgrent() < 0) return DECLINED(cmd); /* Check for NULLs */ @@@@ -774,7 +735,7 @@@@ groups = (array_header *) cmd->argv[2]; /* Retrieve the necessary info. */ - if (!name || !(pwd = af_getpwnam(af_current_user_file, name))) + if (!name || !(pwd = af_getpwnam(name))) return mod_create_error(cmd, -1); /* Populate the first group ID and name. */ @@@@ -782,25 +743,15 @@@@ *((gid_t *) push_array(gids)) = pwd->pw_gid; if (groups && - (grp = af_getgrgid(af_current_group_file, pwd->pw_gid)) != NULL) + (grp = af_getgrgid(pwd->pw_gid)) != NULL) *((char **) push_array(groups)) = pstrdup(session.pool, grp->gr_name); - /* The above call to af_getgrgid() will position the file pointer in - * the AuthGroupFile just after the group with the primary GID. - * Subsequently, the below af_getgrent() starts from that position, and - * goes to the end of the file. The problem is that there may be groups - * before the primary GID for the current group. So, ideally, the - * getgrent() loop would continue until we're back to where we are now, - * rather than stopping at the end of the file. Conversely, we could - * just simply rewind to the start of the AuthGroupFile (which is easier). - * The core auth code will remove duplicate IDs as needed. - */ - af_open_file(af_current_group_file); + af_setgrent(); /* This is where things get slow, expensive, and ugly. Loop through * everything, checking to make sure we haven't already added it. */ - while ((grp = af_getgrent(af_current_group_file)) != NULL && + while ((grp = af_getgrent()) != NULL && grp->gr_mem) { char **gr_mems = NULL; @@@@ -832,14 +783,10 @@@@ MODRET authfile_gid2name(cmd_rec *cmd) { struct group *grp = NULL; - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) + if (af_setgrent() < 0) return DECLINED(cmd); - if (!af_setgrent()) - return DECLINED(cmd); - - grp = af_getgrgid(af_current_group_file, *((gid_t *) cmd->argv[0])); + grp = af_getgrgid(*((gid_t *) cmd->argv[0])); return grp ? mod_create_data(cmd, grp->gr_name) : DECLINED(cmd); } @@@@ -847,30 +794,18 @@@@ MODRET authfile_name2gid(cmd_rec *cmd) { struct group *grp = NULL; - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) - return DECLINED(cmd); - - if (!af_setgrent()) + if (af_setgrent() < 0) return DECLINED(cmd); - grp = af_getgrnam(af_current_group_file, cmd->argv[0]); + grp = af_getgrnam(cmd->argv[0]); return grp ? mod_create_data(cmd, (void *) &grp->gr_gid) : DECLINED(cmd); } MODRET authfile_setgrent(cmd_rec *cmd) { - - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) - return DECLINED(cmd); - - if (af_setgrent()) + if (af_setgrent() == 0) return DECLINED(cmd); - pr_log_debug(DEBUG2, - MOD_AUTH_FILE_VERSION ": unable to find useable AuthGroupFile"); - return DECLINED(cmd); } @@@@ -879,15 +814,11 @@@@ char *tmp = NULL, *cleartxt_pass = NULL; const char *name = cmd->argv[0]; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (!af_setpwent()) + if (af_setpwent() < 0) return DECLINED(cmd); /* Lookup the cleartxt password for this user. */ - if ((tmp = af_getpwpass(af_current_user_file, name)) == NULL) { + if ((tmp = af_getpwpass(name)) == NULL) { /* For now, return DECLINED. Ideally, we could stash an auth module * identifier in the session structure, so that all auth modules could @@@@ -923,8 +854,12 @@@@ const char *ciphertxt_pass = cmd->argv[0]; const char *cleartxt_pass = cmd->argv[2]; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) + /* Even though the AuthUserFile is not used here, there must be one + * configured before this function should attempt to check the password. + * Otherwise, it could be checking a password retrieved by some other + * auth module. + */ + if (!af_user_file) return DECLINED(cmd); if (strcmp(crypt(cleartxt_pass, ciphertxt_pass), ciphertxt_pass) == 0) { @@@@ -938,13 +873,6 @@@@ /* Configuration handlers */ -/* NOTE: support multiple AuthUserFiles, AuthGroupFiles. Have optional - * parameter to restrict ID range in files, min and max, where max >= min. - * - * Future rev: incorporate AuthShadowFile into this, and add --shadow - * capabilities to ftpasswd. - */ - /* usage: AuthGroupFile path [id ] [name ] */ MODRET set_authgroupfile(cmd_rec *cmd) { config_rec *c = NULL; @@@@ -1180,54 +1108,18 @@@@ static int authfile_sess_init(void) { config_rec *c = NULL; - af_user_file_list = af_group_file_list = NULL; - - /* Search for all relevant AuthUserFiles for this server. */ c = find_config(main_server->conf, CONF_PARAM, "AuthUserFile", FALSE); - - while (c) { - authfile_file_t *file = c->argv[0]; - -/* NOTE: This is a hack, to prevent these config_recs from being handled by - * mod_unixpw. Only necessary until mod_unixpw is transformed into - * mod_auth_unix. - */ -c->name = ""; - - if (!af_user_file_list) { - file->af_next = af_user_file_list; - af_user_file_list = file; - } - - c = find_config_next(c, c->next, CONF_PARAM, "AuthUserFile", FALSE); + if (c) { + af_user_file = c->argv[0]; + pr_log_debug(DEBUG0, MOD_AUTH_FILE_VERSION ": found AuthUserFile '%s'", af_user_file->af_path); } - /* Search for all relevant AuthGroupFiles for this server. */ - c = find_config(main_server->conf, CONF_PARAM, "AuthGroupFile", FALSE); - - while (c) { - authfile_file_t *file = c->argv[0]; - -/* NOTE: This is a hack, to prevent these config_recs from being handled by - * mod_unixpw. Only necessary until mod_unixpw is transformed into - * mod_auth_unix. - */ -c->name = ""; - - if (!af_group_file_list) { - file->af_next = af_group_file_list; - af_group_file_list = file; - } - - c = find_config_next(c, c->next, CONF_PARAM, "AuthGroupFile", FALSE); + c = find_config_next(c, c->next, CONF_PARAM, "AuthGroupFile", FALSE); + if (c) { + af_group_file = c->argv[0]; + pr_log_debug(DEBUG0, MOD_AUTH_FILE_VERSION ": found AuthGroupFile '%s'", af_group_file->af_path); } - if (af_user_file_list) - af_handle_pw = TRUE; - - if (af_group_file_list) - af_handle_gr = TRUE; - return 0; } @@@@ -1291,6 +1183,9 @@@@ NULL, /* Session initialization function */ - authfile_sess_init + authfile_sess_init, + + /* Module version */ + MOD_AUTH_FILE_VERSION }; ----------------------------------------------------------------------------- Security Fix (CVE-2006-6563) Index: src/ctrls.c --- src/ctrls.c.orig 2005-11-11 22:05:32 +0100 +++ src/ctrls.c 2006-12-15 23:30:05 +0100 @@@@ -526,11 +526,20 @@@@ return -1; } + if (reqarglen >= sizeof(reqaction)) { + pr_signals_unblock(); + errno = ENOMEM; + return -1; + } + + memset(reqaction, '\0', sizeof(reqaction)); + if (read(cl->cl_fd, reqaction, reqarglen) < 0) { pr_signals_unblock(); return -1; } + reqaction[sizeof(reqaction)-1] = '\0'; nreqargs--; /* Find a matching action object, and use it to populate a ctrl object, @@@@ -649,17 +658,16 @@@@ return -1; } - memset(response, '\0', sizeof(response)); - /* Make sure resparglen is not too big */ - if (resparglen > sizeof(response)) { + if (resparglen >= sizeof(response)) { pr_signals_unblock(); errno = ENOMEM; return -1; } - bread = read(ctrls_sockfd, response, resparglen); + memset(response, '\0', sizeof(response)); + bread = read(ctrls_sockfd, response, resparglen); while (bread != resparglen) { if (bread < 0) { pr_signals_unblock(); @ 1.22 log @MFE: Security Fix (CVE-2006-6171) Security Fix (CVE-2006-6563) @ text @d2 5 a6 49 --- mod_sql_sqlite/mod_sql_sqlite.c.orig 2006-12-06 08:49:36 +0100 +++ mod_sql_sqlite/mod_sql_sqlite.c 2006-12-06 09:01:01 +0100 @@@@ -22,15 +22,15 @@@@ * the source code for OpenSSL in the source distribution. * * $Id: mod_sql_sqlite.c,v 1.1 2004/10/17 19:59:48 tj Exp tj $ - * $Libraries: -lsqlite $ + * $Libraries: -lsqlite3 $ */ -#include +#include #include "conf.h" #include "mod_sql.h" -#define MOD_SQL_SQLITE_VERSION "mod_sql_sqlite/0.1" +#define MOD_SQL_SQLITE_VERSION "mod_sql_sqlite/0.1+" /* Make sure the version of proftpd is as necessary. */ #if PROFTPD_VERSION_NUMBER < 0x0001021101 @@@@ -44,7 +44,7 @@@@ char *user; char *pass; - sqlite *dbh; + sqlite3 *dbh; } db_conn_t; @@@@ -185,7 +185,6 @@@@ } MODRET sql_sqlite_open(cmd_rec *cmd) { - char *tmp = NULL; conn_entry_t *entry = NULL; db_conn_t *conn = NULL; @@@@ -220,21 +219,17 @@@@ return HANDLED(cmd); } - conn->dbh = sqlite_open(conn->dsn, 0, &tmp); - if (conn->dbh == NULL) { - char *errstr = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + if (sqlite3_open(conn->dsn, &conn->dbh) != SQLITE_OK) { + char *errstr = pstrdup(cmd->pool, sqlite3_errmsg(conn->dbh)); + sqlite3_close(conn->dbh); d8 2 a9 2 sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_open"); return ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr); d12 2 a13 18 - if (tmp) - sqlite_freemem(tmp); - /* Add some SQLite information to the logs. */ sql_log(DEBUG_INFO, MOD_SQL_SQLITE_VERSION ": SQLite version: %s", - sqlite_libversion()); + sqlite3_libversion()); entry->nconn++; @@@@ -295,7 +290,7 @@@@ (cmd->argc == 2 && cmd->argv[1])) { if (conn->dbh) { - sqlite_close(conn->dbh); + sqlite3_close(conn->dbh); conn->dbh = NULL; } d15 4 a18 13 @@@@ -447,9 +442,9 @@@@ /* Perform the query. If it doesn't work, log the error, close the * connection, then return the error from the query processing. */ - if (sqlite_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { + if (sqlite3_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { char *errstr = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + sqlite3_free(tmp); close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name); sql_sqlite_close(close_cmd); @@@@ -460,7 +455,7 @@@@ d21 1 a21 81 if (tmp) - sqlite_freemem(tmp); + sqlite3_free(tmp); mr = sql_sqlite_get_data(cmd); @@@@ -517,9 +512,9 @@@@ * connection (and log any errors there, too) then return the error * from the query processing. */ - if (sqlite_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { + if (sqlite3_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { char *errstr = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + sqlite3_free(tmp); close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name); sql_sqlite_close(close_cmd); @@@@ -530,7 +525,7 @@@@ } if (tmp) - sqlite_freemem(tmp); + sqlite3_free(tmp); /* Reset these variables. The memory in them is allocated from this * same cmd_rec, and will be recovered when the cmd_rec is destroyed. @@@@ -594,9 +589,9 @@@@ /* Perform the query. If it doesn't work close the connection, then * return the error from the query processing. */ - if (sqlite_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { + if (sqlite3_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { char *errstr = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + sqlite3_free(tmp); close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name); sql_sqlite_close(close_cmd); @@@@ -607,7 +602,7 @@@@ } if (tmp) - sqlite_freemem(tmp); + sqlite3_free(tmp); /* Reset these variables. The memory in them is allocated from this * same cmd_rec, and will be recovered when the cmd_rec is destroyed. @@@@ -674,9 +669,9 @@@@ /* Perform the query. If it doesn't work close the connection, then * return the error from the query processing. */ - if (sqlite_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { + if (sqlite3_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { char *errstr = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + sqlite3_free(tmp); close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name); sql_sqlite_close(close_cmd); @@@@ -687,7 +682,7 @@@@ } if (tmp) - sqlite_freemem(tmp); + sqlite3_free(tmp); mr = sql_sqlite_get_data(cmd); @@@@ -724,9 +719,9 @@@@ conn = (db_conn_t *) entry->data; unescaped = cmd->argv[1]; - tmp = sqlite_mprintf("%q", unescaped); + tmp = sqlite3_mprintf("%q", unescaped); escaped = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + sqlite3_free(tmp); sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_escapestring"); return mod_create_data(cmd, escaped); @ 1.21 log @do people a favor and backport the mod_auth_file fixes to 1.3.0a (although I'm wondering why I'm spending my time on this) @ text @d217 1 d1283 51 @ 1.20 log @add the CommandBufferSize to remove run-time warning and apply a back-ported patch to fix part of an endless loop in the 'auth' sub-system (unfortunately this doesn't solve the endless looping in mod_auth_file as this requires a lot more backporting of fixes as it is even more broken in 1.3.0a) @ text @d283 1 a283 1 Fix for Endless Loop d286 6 d338 944 @ 1.19 log @upstream has taken over my patches @ text @d281 51 @ 1.18 log @try to convert the mod_sql_sqlite modules from the ancient SQLite v2 API to the current v3 API so the module finally uses SQLite 3.x @ text @a0 21 Index: mod_otp/mod_otp.c --- mod_otp/mod_otp.c.orig 2002-10-31 02:16:23 +0100 +++ mod_otp/mod_otp.c 2005-11-07 21:15:19 +0100 @@@@ -127,7 +127,7 @@@@ ": error generating challenge for user '%s': %s", cmd->argv[1], str); } else - add_response(R_DUP, "Challenge: [ %s ]", challenge); + pr_response_add(R_DUP, "Challenge: [ %s ]", challenge); return DECLINED(cmd); } @@@@ -203,7 +203,7 @@@@ static cmdtable otp_cmdtab[] = { { POST_CMD, C_USER, G_NONE, otp_post_user, FALSE, FALSE }, - { NULL } + { 0, NULL } }; static authtable otp_authtab[] = { @ 1.17 log @modifying package: proftpd-1.3.0a 20061128 -> 20061206 @ text @d22 170 @ 1.16 log @upgrading package: proftpd 1.3.0 -> 1.3.0a @ text @d22 12 @ 1.15 log @ops, we have to fix the vendor fix @ text @d55 1 a55 1 Security Fix (CVE-2006-5815) @ 1.14 log @Security Fixes @ text @d84 1 a84 1 + *bufsz, (unsigned int) PR_DEFAULT_CMD_BUFSZ); @ 1.13 log @get rid of inline/static combination which GCC disliked at least under 64-bit platforms like FreeBSD/amd64 @ text @d52 68 @ 1.12 log @add a bunch of third-party ProFTPd add-on modules @ text @d22 30 @ 1.12.2.1 log @MFC: get rid of inline/static combination which GCC disliked at least under 64-bit platforms like FreeBSD/amd64 @ text @a21 30 Index: modules/mod_auth_unix.c --- modules/mod_auth_unix.c.orig 2005-07-03 20:52:02 +0200 +++ modules/mod_auth_unix.c 2006-06-27 16:10:20 +0200 @@@@ -248,7 +248,7 @@@@ return gr; } -inline static int _compare_uid(idmap_t *m1, idmap_t *m2) { +static int _compare_uid(idmap_t *m1, idmap_t *m2) { if (m1->id.uid < m2->id.uid) return -1; @@@@ -258,7 +258,7 @@@@ return 0; } -inline static int _compare_gid(idmap_t *m1, idmap_t *m2) { +static int _compare_gid(idmap_t *m1, idmap_t *m2) { if (m1->id.gid < m2->id.gid) return -1; @@@@ -268,7 +268,7 @@@@ return 0; } -inline static int _compare_id(xaset_t **table, idauth_t id, idauth_t idcomp) { +static int _compare_id(xaset_t **table, idauth_t id, idauth_t idcomp) { if (table == uid_table) return id.uid == idcomp.uid; else @ 1.12.2.2 log @MFC: Security Fixes @ text @a51 68 ----------------------------------------------------------------------------- Security Fix (CVE-2006-5815) Index: src/main.c --- src/main.c.orig 2006-03-15 20:41:01 +0100 +++ src/main.c 2006-11-15 16:47:29 +0100 @@@@ -116,6 +116,8 @@@@ static char sbuf[PR_TUNABLE_BUFFER_SIZE] = {'\0'}; +#define PR_DEFAULT_CMD_BUFSZ 512 + static char **Argv = NULL; static char *LastArgv = NULL; static const char *PidPath = PR_PID_FILE_PATH; @@@@ -820,16 +822,25 @@@@ pr_timer_reset(TIMER_IDLE, NULL); if (cmd_buf_size == -1) { - long *buf_size = get_param_ptr(main_server->conf, - "CommandBufferSize", FALSE); + int *bufsz = get_param_ptr(main_server->conf, "CommandBufferSize", + FALSE); - if (buf_size == NULL || *buf_size <= 0) - cmd_buf_size = 512; + if (bufsz == NULL || + *bufsz <= 0) { + pr_log_pri(PR_LOG_WARNING, "invalid CommandBufferSize size (%d) " + "given, resetting to default buffer size (%u)", + *bufsz, (unsigned int) PR_DEFAULT_CMD_BUFSZ); + cmd_buf_size = PR_DEFAULT_CMD_BUFSZ; + + } else if (*bufsz + 1 > sizeof(buf)) { + pr_log_pri(PR_LOG_WARNING, "invalid CommandBufferSize size (%d) " + "given, resetting to default buffer size (%u)", + *bufsz, (unsigned int) PR_DEFAULT_CMD_BUFSZ); + cmd_buf_size = PR_DEFAULT_CMD_BUFSZ; - else if (*buf_size + 1 > sizeof(buf)) { - pr_log_pri(PR_LOG_WARNING, "Invalid CommandBufferSize size given. " - "Resetting to 512."); - cmd_buf_size = 512; + } else { + pr_log_debug(DEBUG1, "setting CommandBufferSize to %d", *bufsz); + cmd_buf_size = (long) *bufsz; } } ----------------------------------------------------------------------------- Security Fix Index: contrib/mod_tls.c --- contrib/mod_tls.c.orig 2005-11-08 18:59:49 +0100 +++ contrib/mod_tls.c 2006-11-15 17:54:43 +0100 @@@@ -2421,6 +2421,8 @@@@ datalen = BIO_get_mem_data(mem, &data); if (data) { + if (datalen > sizeof(buf)-1) + datalen = sizeof(buf)-1; memset(&buf, '\0', sizeof(buf)); memcpy(buf, data, datalen); buf[datalen] = '\0'; @ 1.12.2.3 log @MFC: ops, we have to fix the vendor fix @ text @d84 1 a84 1 + bufsz != NULL ? *bufsz : 0, (unsigned int) PR_DEFAULT_CMD_BUFSZ); @ 1.12.2.4 log @MFC: update to security fixed version @ text @d55 1 a55 1 Security Fix (CVE-2006-5815, according to CVE, but vendor thinks differently) @ 1.12.2.5 log @MFC: make up leeway for 2_STABLE by virtue of build-time results @ text @d1 9 a9 25 Index: mod_sql_sqlite/mod_sql_sqlite.c --- mod_sql_sqlite/mod_sql_sqlite.c.orig 2006-12-06 08:49:36 +0100 +++ mod_sql_sqlite/mod_sql_sqlite.c 2006-12-06 09:01:01 +0100 @@@@ -22,15 +22,15 @@@@ * the source code for OpenSSL in the source distribution. * * $Id: mod_sql_sqlite.c,v 1.1 2004/10/17 19:59:48 tj Exp tj $ - * $Libraries: -lsqlite $ + * $Libraries: -lsqlite3 $ */ -#include +#include #include "conf.h" #include "mod_sql.h" -#define MOD_SQL_SQLITE_VERSION "mod_sql_sqlite/0.1" +#define MOD_SQL_SQLITE_VERSION "mod_sql_sqlite/0.1+" /* Make sure the version of proftpd is as necessary. */ #if PROFTPD_VERSION_NUMBER < 0x0001021101 @@@@ -44,7 +44,7 @@@@ char *user; char *pass; d11 1 a11 6 - sqlite *dbh; + sqlite3 *dbh; } db_conn_t; @@@@ -185,7 +185,6 @@@@ d13 1 d15 5 a19 146 MODRET sql_sqlite_open(cmd_rec *cmd) { - char *tmp = NULL; conn_entry_t *entry = NULL; db_conn_t *conn = NULL; @@@@ -220,21 +219,17 @@@@ return HANDLED(cmd); } - conn->dbh = sqlite_open(conn->dsn, 0, &tmp); - if (conn->dbh == NULL) { - char *errstr = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + if (sqlite3_open(conn->dsn, &conn->dbh) != SQLITE_OK) { + char *errstr = pstrdup(cmd->pool, sqlite3_errmsg(conn->dbh)); + sqlite3_close(conn->dbh); sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_open"); return ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, errstr); } - if (tmp) - sqlite_freemem(tmp); - /* Add some SQLite information to the logs. */ sql_log(DEBUG_INFO, MOD_SQL_SQLITE_VERSION ": SQLite version: %s", - sqlite_libversion()); + sqlite3_libversion()); entry->nconn++; @@@@ -295,7 +290,7 @@@@ (cmd->argc == 2 && cmd->argv[1])) { if (conn->dbh) { - sqlite_close(conn->dbh); + sqlite3_close(conn->dbh); conn->dbh = NULL; } @@@@ -447,9 +442,9 @@@@ /* Perform the query. If it doesn't work, log the error, close the * connection, then return the error from the query processing. */ - if (sqlite_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { + if (sqlite3_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { char *errstr = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + sqlite3_free(tmp); close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name); sql_sqlite_close(close_cmd); @@@@ -460,7 +455,7 @@@@ } if (tmp) - sqlite_freemem(tmp); + sqlite3_free(tmp); mr = sql_sqlite_get_data(cmd); @@@@ -517,9 +512,9 @@@@ * connection (and log any errors there, too) then return the error * from the query processing. */ - if (sqlite_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { + if (sqlite3_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { char *errstr = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + sqlite3_free(tmp); close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name); sql_sqlite_close(close_cmd); @@@@ -530,7 +525,7 @@@@ } if (tmp) - sqlite_freemem(tmp); + sqlite3_free(tmp); /* Reset these variables. The memory in them is allocated from this * same cmd_rec, and will be recovered when the cmd_rec is destroyed. @@@@ -594,9 +589,9 @@@@ /* Perform the query. If it doesn't work close the connection, then * return the error from the query processing. */ - if (sqlite_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { + if (sqlite3_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { char *errstr = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + sqlite3_free(tmp); close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name); sql_sqlite_close(close_cmd); @@@@ -607,7 +602,7 @@@@ } if (tmp) - sqlite_freemem(tmp); + sqlite3_free(tmp); /* Reset these variables. The memory in them is allocated from this * same cmd_rec, and will be recovered when the cmd_rec is destroyed. @@@@ -674,9 +669,9 @@@@ /* Perform the query. If it doesn't work close the connection, then * return the error from the query processing. */ - if (sqlite_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { + if (sqlite3_exec(conn->dbh, query, exec_cb, cmd, &tmp) != SQLITE_OK) { char *errstr = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + sqlite3_free(tmp); close_cmd = pr_cmd_alloc(cmd->tmp_pool, 1, entry->name); sql_sqlite_close(close_cmd); @@@@ -687,7 +682,7 @@@@ } if (tmp) - sqlite_freemem(tmp); + sqlite3_free(tmp); mr = sql_sqlite_get_data(cmd); @@@@ -724,9 +719,9 @@@@ conn = (db_conn_t *) entry->data; unescaped = cmd->argv[1]; - tmp = sqlite_mprintf("%q", unescaped); + tmp = sqlite3_mprintf("%q", unescaped); escaped = pstrdup(cmd->pool, tmp); - sqlite_freemem(tmp); + sqlite3_free(tmp); sql_log(DEBUG_FUNC, "%s", "exiting \tsqlite cmd_escapestring"); return mod_create_data(cmd, escaped); Index: mod_vroot/mod_vroot.c --- mod_vroot/mod_vroot.c.orig 2006-12-06 03:58:51 +0100 +++ mod_vroot/mod_vroot.c 2006-12-06 08:00:45 +0100 @@@@ -582,7 +582,7 @@@@ CONF_ERROR(cmd, "must be an absolute path"); add_config_param_str(cmd->argv[0], 1, cmd->argv[1]); - return PR_HANDLED(cmd); + return HANDLED(cmd); } d21 1 a21 1 /* usage: VRootOptions opt1 opt2 ... optN */ @ 1.12.2.6 log @MFC: make up leeway for 2_STABLE by virtue of build-time results @ text @a280 1001 ----------------------------------------------------------------------------- Fix Endless Looping. (backported from http://proftp.cvs.sourceforge.net/proftp/proftpd/src/auth.c?r1=1.46&r2=1.47) "Make sure that dispatch_auth() does not loop endlessly, if there are never any ERROR or HANDLED returns from the auth module handlers. Simply keep track of the starting table, and watch the iterator table; when the two match, we have looped through the auth handlers, and will assume that the entire auth command has been DECLINED." Index: src/auth.c --- src/auth.c.orig 2005-06-14 20:11:12 +0200 +++ src/auth.c 2007-01-19 10:38:19 +0100 @@@@ -64,28 +64,35 @@@@ } static modret_t *dispatch_auth(cmd_rec *cmd, char *match) { - authtable *authtab = NULL; + authtable *start_tab = NULL, *iter_tab = NULL; modret_t *mr = NULL; - authtab = pr_stash_get_symbol(PR_SYM_AUTH, match, NULL, + start_tab = pr_stash_get_symbol(PR_SYM_AUTH, match, NULL, &cmd->stash_index); + iter_tab = start_tab; - while (authtab) { + pr_log_debug(DEBUG6, "dispatching auth request \"%s\": START", match); + while (iter_tab) { pr_log_debug(DEBUG6, "dispatching auth request \"%s\" to module mod_%s", - match, authtab->m->name); + match, iter_tab->m->name); - mr = call_module(authtab->m, authtab->handler, cmd); + mr = call_module(iter_tab->m, iter_tab->handler, cmd); - if (authtab->auth_flags & PR_AUTH_FL_REQUIRED) + if (iter_tab->auth_flags & PR_AUTH_FL_REQUIRED) break; if (MODRET_ISHANDLED(mr) || MODRET_ISERROR(mr)) break; - authtab = pr_stash_get_symbol(PR_SYM_AUTH, match, authtab, + iter_tab = pr_stash_get_symbol(PR_SYM_AUTH, match, iter_tab, &cmd->stash_index); + if (iter_tab == start_tab) { + mr = DECLINED(cmd); + break; + } } + pr_log_debug(DEBUG6, "dispatching auth request \"%s\": END", match); return mr; } ----------------------------------------------------------------------------- Fix Incorrect AuthUserFile iteration. (backported from http://proftp.cvs.sourceforge.net/proftp/proftpd/modules/mod_auth_file.?r1=1.27&r2=1.28) "Bug#2803 - mod_auth_file does not properly iterate through AuthUserFile entries. The issue was one of rewinding an already open AuthUserFile, every time pr_auth_getpwent() was called. The mod_auth_file module has been restructured to avoid this. The code was also substantially changed, removing a lot of dead code for a never-used feature (that of supporting multiple AuthUserFiles within the same server context)." Index: modules/mod_auth_file.c --- modules/mod_auth_file.c.orig 2005-07-03 20:52:02 +0200 +++ modules/mod_auth_file.c 2007-01-19 13:10:40 +0100 @@@@ -52,15 +52,7 @@@@ } authfile_id_t; -typedef struct entry_rec { - struct entry_rec *next, *prev; - char *name; - -} authfile_entry_t; - typedef struct file_rec { - struct file_rec *af_next; - char *af_path; FILE *af_file; @@@@ -84,15 +76,14 @@@@ } authfile_file_t; -static unsigned char af_handle_pw = FALSE, af_handle_gr = FALSE; +/* List of server-specific Authiles */ +static authfile_file_t *af_user_file = NULL; +static authfile_file_t *af_group_file = NULL; + +extern unsigned char persistent_passwd; -/* List of server-specific AuthUserFiles */ -static authfile_file_t *af_user_file_list = NULL; -static authfile_file_t *af_current_user_file = NULL; - -/* List of server-specific AuthGroupFiles */ -static authfile_file_t *af_group_file_list = NULL; -static authfile_file_t *af_current_group_file = NULL; +static int af_setpwent(void); +static int af_setgrent(void); /* Support routines. Move the passwd/group functions out of lib/ into here. */ @@@@ -179,7 +170,8 @@@@ { char *new_buf; - if ((new_buf = realloc(*buf, *buflen)) == NULL) + new_buf = realloc(*buf, *buflen); + if (new_buf == NULL) break; *buf = new_buf; @@@@ -228,13 +220,15 @@@@ sstrncpy(grpbuf, buf, i); - if ((cp = strrchr(grpbuf, '\n'))) + cp = strrchr(grpbuf, '\n'); + if (cp) *cp = '\0'; for (cp = grpbuf, i = 0; i < NGRPFIELDS && cp; i++) { grpfields[i] = cp; - if ((cp = strchr(cp, ':'))) + cp = strchr(cp, ':'); + if (cp) *cp++ = 0; } @@@@ -255,84 +249,76 @@@@ } #endif /* !HAVE_FGETGRENT */ -static unsigned char af_close_file(authfile_file_t *file) { - if (file && file->af_file) { - fclose(file->af_file); - file->af_file = NULL; +static int af_allow_grent(struct group *grp) { + if (!af_group_file) { + errno = EPERM; + return -1; } - return TRUE; -} - -static unsigned char af_open_file(authfile_file_t *file) { - if (file) { - - /* If already opened, rewind */ - if (file->af_file) - rewind(file->af_file); - - else if ((file->af_file = fopen(file->af_path, "r")) == NULL) - return FALSE; - - return TRUE; - } - - return FALSE; -} - -static unsigned char af_allow_grent(authfile_file_t *groupf, - struct group *grp) { - /* Check that the grent is within the ID restrictions (if present). */ - if (groupf->af_restricted_ids) { + if (af_group_file->af_restricted_ids) { - if (grp->gr_gid < groupf->af_min_id.gid) { + if (grp->gr_gid < af_group_file->af_min_id.gid) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping group '%s': " "GID (%u) below the minimum allowed (%u)", grp->gr_name, - (unsigned int) grp->gr_gid, (unsigned int) groupf->af_min_id.gid); - return FALSE; + (unsigned int) grp->gr_gid, + (unsigned int) af_group_file->af_min_id.gid); + errno = EINVAL; + return -1; } - if (grp->gr_gid > groupf->af_max_id.gid) { + if (grp->gr_gid > af_group_file->af_max_id.gid) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping group '%s': " "GID (%u) above the maximum allowed (%u)", grp->gr_name, - (unsigned int) grp->gr_gid, (unsigned int) groupf->af_max_id.gid); - return FALSE; + (unsigned int) grp->gr_gid, + (unsigned int) af_group_file->af_max_id.gid); + errno = EINVAL; + return -1; } } #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) /* Check if the grent has an acceptable name. */ - if (groupf->af_restricted_names) { - int res = regexec(groupf->af_name_regex, grp->gr_name, 0, NULL, 0); + if (af_group_file->af_restricted_names) { + int res = regexec(af_group_file->af_name_regex, grp->gr_name, 0, NULL, 0); - if ((res != 0 && !groupf->af_name_regex_inverted) || - (res == 0 && groupf->af_name_regex_inverted)) { + if ((res != 0 && !af_group_file->af_name_regex_inverted) || + (res == 0 && af_group_file->af_name_regex_inverted)) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping group '%s': " "name '%s' does not meet allowed filter '%s'", grp->gr_name, - grp->gr_name, groupf->af_name_filter); - return FALSE; + grp->gr_name, af_group_file->af_name_filter); + errno = EINVAL; + return -1; } } #endif /* !HAVE_REGEX_H and !HAVE_REGCOMP */ - return TRUE; + return 0; } static void af_endgrent(void) { - af_close_file(af_current_group_file); - af_current_group_file = NULL; + if (af_group_file && + af_group_file->af_file) { + fclose(af_group_file->af_file); + af_group_file->af_file = NULL; + } return; } -static struct group *af_getgrent(authfile_file_t *groupf) { +static struct group *af_getgrent(void) { struct group *grp = NULL; + if (!af_group_file || + !af_group_file->af_file) { + errno = EINVAL; + return NULL; + } + while (TRUE) { #ifdef HAVE_FGETGRENT pr_signals_handle(); - grp = fgetgrent(groupf->af_file); + grp = fgetgrent(af_group_file->af_file); #else char *cp = NULL, *buf = NULL; int buflen = BUFSIZ; @@@@ -343,13 +329,14 @@@@ if (!buf) return NULL; - while (af_getgrentline(&buf, &buflen, groupf->af_file) != NULL) { + while (af_getgrentline(&buf, &buflen, af_group_file->af_file) != NULL) { /* Ignore comment and empty lines */ if (buf[0] == '\0' || buf[0] == '#') continue; - if ((cp = strchr(buf, '\n')) != NULL) + cp = strchr(buf, '\n'); + if (cp != NULL) *cp = '\0'; grp = af_getgrp(buf); @@@@ -363,7 +350,7 @@@@ if (!grp) break; - if (!af_allow_grent(groupf, grp)) + if (af_allow_grent(grp) < 0) continue; break; @@@@ -372,129 +359,156 @@@@ return grp; } -static struct group *af_getgrnam(authfile_file_t *groupf, const char *name) { +static struct group *af_getgrnam(const char *name) { struct group *grp = NULL; - while ((grp = af_getgrent(groupf)) != NULL) - if (!strcmp(name, grp->gr_name)) + if (af_setgrent() < 0) + return NULL; + + while ((grp = af_getgrent()) != NULL) { + if (strcmp(name, grp->gr_name) == 0) { /* Found the requested group */ break; + } + } return grp; } -static struct group *af_getgrgid(authfile_file_t *groupf, gid_t gid) { +static struct group *af_getgrgid(gid_t gid) { struct group *grp = NULL; - while ((grp = af_getgrent(groupf)) != NULL) - if (grp->gr_gid == gid) + if (af_setgrent() < 0) + return NULL; + + while ((grp = af_getgrent()) != NULL) { + if (grp->gr_gid == gid) { /* Found the requested GID */ break; + } + } return grp; } -static unsigned char af_setgrent(void) { - - /* If not already present, start at the top of the list. */ - if (!af_current_group_file) - af_current_group_file = af_group_file_list; +static int af_setgrent(void) { - while (af_current_group_file) { + if (af_group_file) { + if (af_group_file->af_file) { + /* If already opened, rewind */ + rewind(af_group_file->af_file); + return 0; - if (!af_open_file(af_current_group_file)) { - /* Log the error */ - pr_log_pri(PR_LOG_ERR, "error: unable to open group file '%s': %s", - af_current_group_file->af_path, strerror(errno)); + } else { +pr_log_debug(DEBUG0, MOD_AUTH_FILE_VERSION ": af_setgrent: opening AuthGroupFile"); - /* Move to the next file in the list. */ - af_current_group_file = af_current_group_file->af_next; - continue; + af_group_file->af_file = fopen(af_group_file->af_path, "r"); + if (af_group_file->af_file == NULL) { + pr_log_pri(PR_LOG_ERR, "error: unable to open group file '%s': %s", + af_group_file->af_path, strerror(errno)); + return -1; + } - } else { pr_log_debug(DEBUG7, MOD_AUTH_FILE_VERSION ": using group file '%s'", - af_current_group_file->af_path); - return TRUE; + af_group_file->af_path); + return 0; } } - return FALSE; + errno = EPERM; + return -1; } -static unsigned char af_allow_pwent(authfile_file_t *passwdf, - struct passwd *pwd) { +static int af_allow_pwent(struct passwd *pwd) { + if (!af_user_file) { + errno = EPERM; + return -1; + } /* Check that the pwent is within the ID restrictions (if present). */ - if (passwdf->af_restricted_ids) { + if (af_user_file->af_restricted_ids) { - if (pwd->pw_uid < passwdf->af_min_id.uid) { + if (pwd->pw_uid < af_user_file->af_min_id.uid) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping user '%s': " "UID (%u) below the minimum allowed (%u)", pwd->pw_name, - (unsigned int) pwd->pw_uid, (unsigned int) passwdf->af_min_id.uid); - return FALSE; + (unsigned int) pwd->pw_uid, (unsigned int) af_user_file->af_min_id.uid); + errno = EINVAL; + return -1; } - if (pwd->pw_uid > passwdf->af_max_id.gid) { + if (pwd->pw_uid > af_user_file->af_max_id.gid) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping user '%s': " "UID (%u) above the maximum allowed (%u)", pwd->pw_name, - (unsigned int) pwd->pw_uid, (unsigned int) passwdf->af_max_id.uid); - return FALSE; + (unsigned int) pwd->pw_uid, (unsigned int) af_user_file->af_max_id.uid); + errno = EINVAL; + return -1; } } #if defined(HAVE_REGEX_H) && defined(HAVE_REGCOMP) /* Check if the pwent has an acceptable name. */ - if (passwdf->af_restricted_names) { - int res = regexec(passwdf->af_name_regex, pwd->pw_name, 0, NULL, 0); + if (af_user_file->af_restricted_names) { + int res = regexec(af_user_file->af_name_regex, pwd->pw_name, 0, NULL, 0); - if ((res != 0 && !passwdf->af_name_regex_inverted) || - (res == 0 && passwdf->af_name_regex_inverted)) { + if ((res != 0 && !af_user_file->af_name_regex_inverted) || + (res == 0 && af_user_file->af_name_regex_inverted)) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping user '%s': " "name '%s' does not meet allowed filter '%s'", pwd->pw_name, - pwd->pw_name, passwdf->af_name_filter); - return FALSE; + pwd->pw_name, af_user_file->af_name_filter); + errno = EINVAL; + return -1; } } /* Check if the pwent has an acceptable home directory. */ - if (passwdf->af_restricted_homes) { + if (af_user_file->af_restricted_homes) { - int res = regexec(passwdf->af_home_regex, pwd->pw_dir, 0, NULL, 0); + int res = regexec(af_user_file->af_home_regex, pwd->pw_dir, 0, NULL, 0); - if ((res != 0 && !passwdf->af_home_regex_inverted) || - (res == 0 && passwdf->af_home_regex_inverted)) { + if ((res != 0 && !af_user_file->af_home_regex_inverted) || + (res == 0 && af_user_file->af_home_regex_inverted)) { pr_log_debug(DEBUG3, MOD_AUTH_FILE_VERSION ": skipping user '%s': " "home '%s' does not meet allowed filter '%s'", pwd->pw_name, - pwd->pw_dir, passwdf->af_home_filter); - return FALSE; + pwd->pw_dir, af_user_file->af_home_filter); + errno = EINVAL; + return -1; } } #endif /* !HAVE_REGEX_H and !HAVE_REGCOMP */ - return TRUE; + return 0; } static void af_endpwent(void) { - af_close_file(af_current_user_file); - af_current_user_file = NULL; + if (af_user_file && + af_user_file->af_file) { + fclose(af_user_file->af_file); + af_user_file->af_file = NULL; + } return; } -static struct passwd *af_getpwent(authfile_file_t *passwdf) { +static struct passwd *af_getpwent(void) { struct passwd *pwd = NULL; + if (!af_user_file || + !af_user_file->af_file) { + errno = EINVAL; + return NULL; + } + while (TRUE) { #ifdef HAVE_FGETPWENT pr_signals_handle(); - pwd = fgetpwent(passwdf->af_file); + pwd = fgetpwent(af_user_file->af_file); #else char buf[BUFSIZ] = {'\0'}; pr_signals_handle(); - while (fgets(buf, sizeof(buf), passwdf->af_file) != (char*) 0) { + while (fgets(buf, sizeof(buf), af_user_file->af_file) != (char*) 0) { pr_signals_handle(); /* Ignore empty and comment lines */ @@@@ -511,7 +525,7 @@@@ if (!pwd) break; - if (!af_allow_pwent(passwdf, pwd)) + if (af_allow_pwent(pwd) < 0) continue; break; @@@@ -520,88 +534,84 @@@@ return pwd; } -static struct passwd *af_getpwnam(authfile_file_t *passwdf, const char *name) { +static struct passwd *af_getpwnam(const char *name) { struct passwd *pwd = NULL; - while ((pwd = af_getpwent(passwdf)) != NULL) - if (!strcmp(name, pwd->pw_name)) + if (af_setpwent() < 0) + return NULL; + + while ((pwd = af_getpwent()) != NULL) { + if (strcmp(name, pwd->pw_name) == 0) { /* Found the requested user */ break; + } + } return pwd; } -static char *af_getpwpass(authfile_file_t *passwdf, const char *name) { - struct passwd *pwd = af_getpwnam(passwdf, name); - +static char *af_getpwpass(const char *name) { + struct passwd *pwd = af_getpwnam(name); return pwd ? pwd->pw_passwd : NULL; } -static struct passwd *af_getpwuid(authfile_file_t *passwdf, uid_t uid) { +static struct passwd *af_getpwuid(uid_t uid) { struct passwd *pwd = NULL; - while ((pwd = af_getpwent(passwdf)) != NULL) - if (pwd->pw_uid == uid) + if (af_setpwent() < 0) + return NULL; + + while ((pwd = af_getpwent()) != NULL) { + if (pwd->pw_uid == uid) { /* Found the requested UID */ break; + } + } return pwd; } -static unsigned char af_setpwent(void) { +static int af_setpwent(void) { - /* If not already present, start at the top of the list. */ - if (!af_current_user_file) - af_current_user_file = af_user_file_list; - - while (af_current_user_file) { - - if (!af_open_file(af_current_user_file)) { - /* Log the error */ - pr_log_pri(PR_LOG_ERR, "error: unable to open passwd file '%s': %s", - af_current_user_file->af_path, strerror(errno)); - - /* Move to the next file in the list. */ - af_current_user_file = af_current_user_file->af_next; - continue; + if (af_user_file) { + if (af_user_file->af_file) { + /* If already opened, rewind */ + rewind(af_user_file->af_file); + return 0; } else { +pr_log_debug(DEBUG0, MOD_AUTH_FILE_VERSION ": af_setpwent: opening AuthUserFile '%s'", af_user_file->af_path); + af_user_file->af_file = fopen(af_user_file->af_path, "r"); + if (af_user_file->af_file == NULL) { + pr_log_pri(PR_LOG_ERR, "error: unable to open passwd file '%s': %s", + af_user_file->af_path, strerror(errno)); + return -1; + } + pr_log_debug(DEBUG7, MOD_AUTH_FILE_VERSION ": using passwd file '%s'", - af_current_user_file->af_path); - return TRUE; + af_user_file->af_path); + return 0; } } - return FALSE; + errno = EPERM; + return -1; } /* Authentication handlers. */ MODRET authfile_endpwent(cmd_rec *cmd) { - - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - af_endpwent(); - return DECLINED(cmd); } MODRET authfile_getpwent(cmd_rec *cmd) { struct passwd *pwd = NULL; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (!af_setpwent()) - return DECLINED(cmd); - - pwd = af_getpwent(af_current_user_file); + pwd = af_getpwent(); return pwd ? mod_create_data(cmd, pwd) : DECLINED(cmd); } @@@@ -610,15 +620,11 @@@@ struct passwd *pwd = NULL; const char *name = cmd->argv[0]; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (!af_setpwent()) + if (af_setpwent() < 0) return DECLINED(cmd); /* Ugly -- we iterate through the file. Time-consuming. */ - while ((pwd = af_getpwent(af_current_user_file)) != NULL) + while ((pwd = af_getpwent()) != NULL) if (!strcmp(name, pwd->pw_name)) /* Found the requested name */ @@@@ -631,14 +637,10 @@@@ struct passwd *pwd = NULL; uid_t uid = *((uid_t *) cmd->argv[0]); - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (!af_setpwent()) + if (af_setpwent() < 0) return DECLINED(cmd); - pwd = af_getpwuid(af_current_user_file, uid); + pwd = af_getpwuid(uid); return pwd ? mod_create_data(cmd, pwd) : DECLINED(cmd); } @@@@ -646,70 +648,41 @@@@ MODRET authfile_name2uid(cmd_rec *cmd) { struct passwd *pwd = NULL; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) + if (af_setpwent() < 0) return DECLINED(cmd); - if (!af_setpwent()) - return DECLINED(cmd); - - pwd = af_getpwnam(af_current_user_file, cmd->argv[0]); + pwd = af_getpwnam(cmd->argv[0]); return pwd ? mod_create_data(cmd, (void *) &pwd->pw_uid) : DECLINED(cmd); } MODRET authfile_setpwent(cmd_rec *cmd) { - - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (af_setpwent()) + if (af_setpwent() == 0) return DECLINED(cmd); - pr_log_debug(DEBUG2, - MOD_AUTH_FILE_VERSION ": unable to find useable AuthUserFile"); - return DECLINED(cmd); } MODRET authfile_uid2name(cmd_rec *cmd) { struct passwd *pwd = NULL; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (!af_setpwent()) + if (af_setpwent() < 0) return DECLINED(cmd); - pwd = af_getpwuid(af_current_user_file, *((uid_t *) cmd->argv[0])); + pwd = af_getpwuid(*((uid_t *) cmd->argv[0])); return pwd ? mod_create_data(cmd, pwd->pw_name) : DECLINED(cmd); } MODRET authfile_endgrent(cmd_rec *cmd) { - - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) - return DECLINED(cmd); - af_endgrent(); - return DECLINED(cmd); } MODRET authfile_getgrent(cmd_rec *cmd) { struct group *grp = NULL; - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) - return DECLINED(cmd); - - if (!af_setgrent()) - return DECLINED(cmd); - - grp = af_getgrent(af_current_group_file); + grp = af_getgrent(); return grp ? mod_create_data(cmd, grp) : DECLINED(cmd); } @@@@ -718,14 +691,10 @@@@ struct group *grp = NULL; gid_t gid = *((gid_t *) cmd->argv[0]); - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) + if (af_setgrent() < 0) return DECLINED(cmd); - if (!af_setgrent()) - return DECLINED(cmd); - - grp = af_getgrgid(af_current_group_file, gid); + grp = af_getgrgid(gid); return grp ? mod_create_data(cmd, grp) : DECLINED(cmd); } @@@@ -734,14 +703,10 @@@@ struct group *grp = NULL; const char *name = cmd->argv[0]; - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) - return DECLINED(cmd); - - if (!af_setgrent()) + if (af_setgrent() < 0) return DECLINED(cmd); - while ((grp = af_getgrent(af_current_group_file)) != NULL) + while ((grp = af_getgrent()) != NULL) if (!strcmp(name, grp->gr_name)) /* Found the name requested */ @@@@ -756,14 +721,10 @@@@ array_header *gids = NULL, *groups = NULL; char *name = cmd->argv[0]; - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) + if (af_setpwent() < 0) return DECLINED(cmd); - if (!af_setpwent()) - return DECLINED(cmd); - - if (!af_setgrent()) + if (af_setgrent() < 0) return DECLINED(cmd); /* Check for NULLs */ @@@@ -774,7 +735,7 @@@@ groups = (array_header *) cmd->argv[2]; /* Retrieve the necessary info. */ - if (!name || !(pwd = af_getpwnam(af_current_user_file, name))) + if (!name || !(pwd = af_getpwnam(name))) return mod_create_error(cmd, -1); /* Populate the first group ID and name. */ @@@@ -782,25 +743,15 @@@@ *((gid_t *) push_array(gids)) = pwd->pw_gid; if (groups && - (grp = af_getgrgid(af_current_group_file, pwd->pw_gid)) != NULL) + (grp = af_getgrgid(pwd->pw_gid)) != NULL) *((char **) push_array(groups)) = pstrdup(session.pool, grp->gr_name); - /* The above call to af_getgrgid() will position the file pointer in - * the AuthGroupFile just after the group with the primary GID. - * Subsequently, the below af_getgrent() starts from that position, and - * goes to the end of the file. The problem is that there may be groups - * before the primary GID for the current group. So, ideally, the - * getgrent() loop would continue until we're back to where we are now, - * rather than stopping at the end of the file. Conversely, we could - * just simply rewind to the start of the AuthGroupFile (which is easier). - * The core auth code will remove duplicate IDs as needed. - */ - af_open_file(af_current_group_file); + af_setgrent(); /* This is where things get slow, expensive, and ugly. Loop through * everything, checking to make sure we haven't already added it. */ - while ((grp = af_getgrent(af_current_group_file)) != NULL && + while ((grp = af_getgrent()) != NULL && grp->gr_mem) { char **gr_mems = NULL; @@@@ -832,14 +783,10 @@@@ MODRET authfile_gid2name(cmd_rec *cmd) { struct group *grp = NULL; - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) + if (af_setgrent() < 0) return DECLINED(cmd); - if (!af_setgrent()) - return DECLINED(cmd); - - grp = af_getgrgid(af_current_group_file, *((gid_t *) cmd->argv[0])); + grp = af_getgrgid(*((gid_t *) cmd->argv[0])); return grp ? mod_create_data(cmd, grp->gr_name) : DECLINED(cmd); } @@@@ -847,30 +794,18 @@@@ MODRET authfile_name2gid(cmd_rec *cmd) { struct group *grp = NULL; - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) - return DECLINED(cmd); - - if (!af_setgrent()) + if (af_setgrent() < 0) return DECLINED(cmd); - grp = af_getgrnam(af_current_group_file, cmd->argv[0]); + grp = af_getgrnam(cmd->argv[0]); return grp ? mod_create_data(cmd, (void *) &grp->gr_gid) : DECLINED(cmd); } MODRET authfile_setgrent(cmd_rec *cmd) { - - /* Do not handle *gr* requests unless we can do so. */ - if (!af_handle_gr) - return DECLINED(cmd); - - if (af_setgrent()) + if (af_setgrent() == 0) return DECLINED(cmd); - pr_log_debug(DEBUG2, - MOD_AUTH_FILE_VERSION ": unable to find useable AuthGroupFile"); - return DECLINED(cmd); } @@@@ -879,15 +814,11 @@@@ char *tmp = NULL, *cleartxt_pass = NULL; const char *name = cmd->argv[0]; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) - return DECLINED(cmd); - - if (!af_setpwent()) + if (af_setpwent() < 0) return DECLINED(cmd); /* Lookup the cleartxt password for this user. */ - if ((tmp = af_getpwpass(af_current_user_file, name)) == NULL) { + if ((tmp = af_getpwpass(name)) == NULL) { /* For now, return DECLINED. Ideally, we could stash an auth module * identifier in the session structure, so that all auth modules could @@@@ -923,8 +854,12 @@@@ const char *ciphertxt_pass = cmd->argv[0]; const char *cleartxt_pass = cmd->argv[2]; - /* Do not handle *pw* requests unless we can do so. */ - if (!af_handle_pw) + /* Even though the AuthUserFile is not used here, there must be one + * configured before this function should attempt to check the password. + * Otherwise, it could be checking a password retrieved by some other + * auth module. + */ + if (!af_user_file) return DECLINED(cmd); if (strcmp(crypt(cleartxt_pass, ciphertxt_pass), ciphertxt_pass) == 0) { @@@@ -938,13 +873,6 @@@@ /* Configuration handlers */ -/* NOTE: support multiple AuthUserFiles, AuthGroupFiles. Have optional - * parameter to restrict ID range in files, min and max, where max >= min. - * - * Future rev: incorporate AuthShadowFile into this, and add --shadow - * capabilities to ftpasswd. - */ - /* usage: AuthGroupFile path [id ] [name ] */ MODRET set_authgroupfile(cmd_rec *cmd) { config_rec *c = NULL; @@@@ -1180,54 +1108,18 @@@@ static int authfile_sess_init(void) { config_rec *c = NULL; - af_user_file_list = af_group_file_list = NULL; - - /* Search for all relevant AuthUserFiles for this server. */ c = find_config(main_server->conf, CONF_PARAM, "AuthUserFile", FALSE); - - while (c) { - authfile_file_t *file = c->argv[0]; - -/* NOTE: This is a hack, to prevent these config_recs from being handled by - * mod_unixpw. Only necessary until mod_unixpw is transformed into - * mod_auth_unix. - */ -c->name = ""; - - if (!af_user_file_list) { - file->af_next = af_user_file_list; - af_user_file_list = file; - } - - c = find_config_next(c, c->next, CONF_PARAM, "AuthUserFile", FALSE); + if (c) { + af_user_file = c->argv[0]; + pr_log_debug(DEBUG0, MOD_AUTH_FILE_VERSION ": found AuthUserFile '%s'", af_user_file->af_path); } - /* Search for all relevant AuthGroupFiles for this server. */ - c = find_config(main_server->conf, CONF_PARAM, "AuthGroupFile", FALSE); - - while (c) { - authfile_file_t *file = c->argv[0]; - -/* NOTE: This is a hack, to prevent these config_recs from being handled by - * mod_unixpw. Only necessary until mod_unixpw is transformed into - * mod_auth_unix. - */ -c->name = ""; - - if (!af_group_file_list) { - file->af_next = af_group_file_list; - af_group_file_list = file; - } - - c = find_config_next(c, c->next, CONF_PARAM, "AuthGroupFile", FALSE); + c = find_config_next(c, c->next, CONF_PARAM, "AuthGroupFile", FALSE); + if (c) { + af_group_file = c->argv[0]; + pr_log_debug(DEBUG0, MOD_AUTH_FILE_VERSION ": found AuthGroupFile '%s'", af_group_file->af_path); } - if (af_user_file_list) - af_handle_pw = TRUE; - - if (af_group_file_list) - af_handle_gr = TRUE; - return 0; } @@@@ -1291,6 +1183,9 @@@@ NULL, /* Session initialization function */ - authfile_sess_init + authfile_sess_init, + + /* Module version */ + MOD_AUTH_FILE_VERSION }; @ 1.11 log @ok, my FTP protocol fixes are now part of the new 1.3.0rc3 version @ text @d1 5 a5 65 [reported to vendor under http://bugs.proftpd.org/show_bug.cgi?id=2692 and in the meantime already taken over into vendor CVS on 2005-09-27] If "DisplayReadme README*" (mod_readme) is configured and a top-level README file exists, mod_readme's "Please read the file README[...]" response lines breaks the FTP protocol already at login time just after the "PASS" request: ---> PASS anonymous@@ <--- (null)-Please read the file README <--- (null)- it was last modified on Sat Sep 10 20:45:37 2005 - 1 day ago <--- (null) Anonymous access granted, restrictions apply. The "(null)" comes from passing a NULL pointer to the format string "%s" on FreeBSD -- on other platforms it could even lead to a segmentation fault. The reason for the broken response codes is that the mod_readme response is added to the top of the the internal response list "resp_list" with the response code R_DUP (= NULL) in mod_readme's POST_CMD for "PASS", *before* mod_auth's POST_CMD for "PASS" later adds its "Anonymous access granted, restrictions apply" with a code of "230". But R_DUP only works if it is *following* a previous (non R_DUP/NULL) response. As a possible workaround we make sure that if a numeric (non R_DUP/NULL) response is added to "resp_list" and the first already existing response is R_DUP/NULL, insert the new response before and not after the existing R_DUP response. After this workaround the protocol handling is fixed, although the order of the response messages is slightly different: ---> PASS anonymous@@ <--- 230-Anonymous access granted, restrictions apply. <--- 230-Please read the file README <--- 230 it was last modified on Sat Sep 10 20:45:37 2005 - 1 day ago Alternative solutions we investigated in were: First, mod_readme's "POST_CMD" handler could have been dispatched *after* mod_auth's "POST_CMD" handler. This doesn't work because mod_auth finally HANDLES the command and does not DECLINE it. Second, mod_readme could use R_230 instead of R_DUP. But currently mod_readme uses a generic callback for all commands including "CWD", etc. And R_230 is intended after "PASS" and not "CWD". Finally, as inside ProFTPd the R_DUP is used also at other possibilities (where it also could break), we decided to fix the handling directly in the response list management routines. --rse 20050911 Index: src/response.c --- src/response.c.orig 2005-07-05 17:42:01 +0200 +++ src/response.c 2005-09-11 12:12:58 +0200 @@@@ -124,8 +124,11 @@@@ resp->num = (numeric ? pstrdup(resp_pool, numeric) : NULL); resp->msg = pstrdup(resp_pool, resp_buf); - for (head = &resp_err_list; *head && (!numeric || !(*head)->num || - strcmp((*head)->num, numeric) <= 0); head = &(*head)->next); + for (head = &resp_err_list; + *head + && (!numeric || !(*head)->num || strcmp((*head)->num, numeric) <= 0) + && !(numeric && !(*head)->num && head == &resp_list); + head = &(*head)->next); d7 3 a9 13 resp->next = *head; *head = resp; @@@@ -145,8 +148,11 @@@@ resp->num = (numeric ? pstrdup(resp_pool, numeric) : NULL); resp->msg = pstrdup(resp_pool, resp_buf); - for (head = &resp_list; *head && (!numeric || !(*head)->num || - strcmp((*head)->num, numeric) <= 0); head = &(*head)->next); + for (head = &resp_list; + *head + && (!numeric || !(*head)->num || strcmp((*head)->num, numeric) <= 0) + && !(numeric && !(*head)->num && head == &resp_list); + head = &(*head)->next); d11 11 a21 2 resp->next = *head; *head = resp; @ 1.10 log @the ProFTPD people in the meantime have already taken over my FTP response protocol fixes @ text @@ 1.9 log @After a few hours of debugging ProFTPd I was finally able to find the reason why ProFTPd in its latest version(s) has a broken FTP protocol handling of "DisplayReadme README*" is active and a top-evel README file exists (as it is usually the case on most of my FTP services). See the long description in the patch file for details. @ text @d1 3 @ 1.8 log @upgrade to 1.3.0rc1; flag more files as %config; fix substitutions; remove obsolete patch @ text @d1 41 a41 26 Index: modules/mod_auth.c --- modules/mod_auth.c.orig 2004-05-19 23:44:26 +0200 +++ modules/mod_auth.c 2004-12-07 12:53:10 +0100 @@@@ -612,7 +612,7 @@@@ buf[sizeof(buf)-1] = '\0'; CHOP(buf); - if (!strcmp(shell, buf)) { + if (shell && !strcmp(shell, buf)) { res = TRUE; break; } Index: modules/mod_log.c --- modules/mod_log.c.orig 2004-01-29 23:20:52 +0100 +++ modules/mod_log.c 2004-12-07 13:00:26 +0100 @@@@ -791,8 +791,8 @@@@ end_time.tv_sec--; } - snprintf(argp, sizeof(arg), "%ld.%03ld", (time_t) end_time.tv_sec, - (time_t) (end_time.tv_usec / 1000)); + snprintf(argp, sizeof(arg), "%ld.%03ld", (long) end_time.tv_sec, + (long) (end_time.tv_usec / 1000)); } else sstrncpy(argp, "-", sizeof(arg)); d43 3 a45 1 ----------------------------------------------------------------------------- d47 1 a47 2 Fix timeout problems. See http://bugs.proftpd.org/show_bug.cgi?id=2516 d49 28 a76 42 Index: include/timers.h --- include/timers.h.orig 2003-02-12 09:49:14 +0100 +++ include/timers.h 2004-12-07 12:53:10 +0100 @@@@ -49,5 +49,6 @@@@ int timer_sleep(int); void handle_alarm(void); void set_sig_alarm(void); +void timers_init(void); #endif /* __TIMERS_H */ Index: src/main.c --- src/main.c.orig 2004-08-08 00:22:42 +0200 +++ src/main.c 2004-12-07 12:53:10 +0100 @@@@ -1317,6 +1317,9 @@@@ else pr_log_debug(DEBUG2, "FTP session requested from unknown class"); + /* Prepare the Timers API. */ + timers_init(); + /* Inform all the modules that we are now a child */ pr_log_debug(DEBUG7, "performing module session initializations"); Index: src/timers.c --- src/timers.c.orig 2004-07-15 02:07:00 +0200 +++ src/timers.c 2004-12-07 12:53:10 +0100 @@@@ -41,13 +41,12 @@@@ static int alarms_blocked = 0,alarm_pending = 0; static xaset_t *timers = NULL; static xaset_t *recycled = NULL; +static xaset_t *free_timers = NULL; static int _indispatch = 0; static int dynamic_timerno = 1024; static unsigned int nalarms = 0; static time_t _alarmed_time = 0; -xaset_t *free_timers = NULL; - static int timer_cmp(timer_t *t1, timer_t *t2) { if (t1->count < t2->count) return -1; @@@@ -383,3 +382,19 @@@@ d78 2 a79 18 return 0; } + +void timers_init(void) { + + /* Reset some of the key static variables. */ + _current_timeout = 0; + _total_time = 0; + nalarms = 0; + _alarmed_time = 0; + + /* Don't inherit the parent's timer lists. */ + timers = NULL; + recycled = NULL; + free_timers = NULL; + + return; +} @ 1.8.2.1 log @apply two security fixes (CAN-2005-2390, buffer overflows) @ text @d1 28 a28 3 Security Bugfixes (CAN-2005-2390) http://bugs.proftpd.org/show_bug.cgi?id=2645 http://bugs.proftpd.org/show_bug.cgi?id=2646 d30 45 a74 20 Index: contrib/mod_sql.c --- contrib/mod_sql.c.orig 2004-12-23 20:55:32 +0100 +++ contrib/mod_sql.c 2005-09-06 15:54:53 +0200 @@@@ -2177,7 +2177,7 @@@@ *outsp++ = 0; /* add the response */ - pr_response_add( c->argv[0], outs); + pr_response_add(c->argv[0], "%s", outs); } while((c = find_config_next(c, c->next, CONF_PARAM, name, FALSE)) != NULL); @@@@ -2251,7 +2251,7 @@@@ *outsp++ = 0; /* add the response */ - pr_response_add( c->argv[0], outs); + pr_response_add(c->argv[0], "%s", outs); } while((c = find_config_next(c, c->next, CONF_PARAM, name, FALSE)) != NULL); d76 1 a76 27 @@@@ -2341,7 +2341,7 @@@@ *outsp++ = 0; /* add the response */ - pr_response_add_err( c->argv[0], outs); + pr_response_add_err(c->argv[0], "%s", outs); } while((c = find_config_next(c, c->next, CONF_PARAM, name, FALSE)) != NULL); @@@@ -2415,7 +2415,7 @@@@ *outsp++ = 0; /* add the response */ - pr_response_add( c->argv[0], outs); + pr_response_add(c->argv[0], "%s", outs); } while((c = find_config_next(c, c->next, CONF_PARAM, name, FALSE)) != NULL); Index: src/response.c --- src/response.c.orig 2003-06-03 18:25:23 +0200 +++ src/response.c 2005-09-06 15:53:44 +0200 @@@@ -169,7 +169,7 @@@@ buf[sizeof(buf) - 1] = '\0'; sstrcat(buf, "\r\n", sizeof(buf)); - RESPONSE_WRITE_STR_ASYNC(session.c->outstrm, buf, strlen(buf)) + RESPONSE_WRITE_STR_ASYNC(session.c->outstrm, "%s", buf) d78 16 a93 2 void pr_response_send(const char *resp_numeric, const char *fmt, ...) { @ 1.7 log @apply a bunch of patches; fix URLs; also specify umask for directories @ text @@ 1.7.2.1 log @apply two security fixes (CAN-2005-2390, format string bug) @ text @a93 58 ----------------------------------------------------------------------------- Security Bugfixes (CAN-2005-2390) http://bugs.proftpd.org/show_bug.cgi?id=2645 http://bugs.proftpd.org/show_bug.cgi?id=2646 Index: contrib/mod_sql.c --- contrib/mod_sql.c.orig 2004-08-03 02:44:31 +0200 +++ contrib/mod_sql.c 2005-09-06 16:02:48 +0200 @@@@ -2036,7 +2036,7 @@@@ *outsp++ = 0; /* add the response */ - pr_response_add( c->argv[0], outs); + pr_response_add(c->argv[0], "%s", outs); } while((c = find_config_next(c, c->next, CONF_PARAM, name, FALSE)) != NULL); @@@@ -2110,7 +2110,7 @@@@ *outsp++ = 0; /* add the response */ - pr_response_add( c->argv[0], outs); + pr_response_add(c->argv[0], "%s", outs); } while((c = find_config_next(c, c->next, CONF_PARAM, name, FALSE)) != NULL); @@@@ -2201,7 +2201,7 @@@@ *outsp++ = 0; /* add the response */ - pr_response_add_err( c->argv[0], outs); + pr_response_add_err(c->argv[0], "%s", outs); } while((c = find_config_next(c, c->next, CONF_PARAM, name, FALSE)) != NULL); @@@@ -2275,7 +2275,7 @@@@ *outsp++ = 0; /* add the response */ - pr_response_add( c->argv[0], outs); + pr_response_add(c->argv[0], "%s", outs); } while((c = find_config_next(c, c->next, CONF_PARAM, name, FALSE)) != NULL); Index: src/response.c --- src/response.c.orig 2003-06-03 18:25:23 +0200 +++ src/response.c 2005-09-06 16:01:37 +0200 @@@@ -169,7 +169,7 @@@@ buf[sizeof(buf) - 1] = '\0'; sstrcat(buf, "\r\n", sizeof(buf)); - RESPONSE_WRITE_STR_ASYNC(session.c->outstrm, buf, strlen(buf)) + RESPONSE_WRITE_STR_ASYNC(session.c->outstrm, "%s", buf) } void pr_response_send(const char *resp_numeric, const char *fmt, ...) { @ 1.6 log @bump to rc1 cause of ifsession module @ text @d1 26 a26 2 http://www.debian.org/security/2003/dsa-338 DSA-338-1 proftpd -- SQL injection, Date Reported: 29 Jun 2003 d28 1 a28 6 runlevel [runlevel@@raregazz.org] reported that ProFTPD's PostgreSQL authentication module is vulnerable to a SQL injection attack. This vulnerability could be exploited by a remote, unauthenticated attacker to execute arbitrary SQL statements, potentially exposing the passwords of other users, or to connect to ProFTPD as an arbitrary user without supplying the correct password. d30 2 a31 2 patch AE.mod_sql_postgres.c.diff extracted from http://security.debian.org/pool/updates/main/p/proftpd/proftpd_1.2.4+1.2.5rc1-5woody2.tar.gz d33 44 a76 26 --- contrib/mod_sql_postgres.c.orig Wed Jul 2 16:49:26 2003 +++ contrib/mod_sql_postgres.c Wed Jul 2 16:56:35 2003 @@@@ -1082,6 +1082,8 @@@@ { conn_entry_t *entry = NULL; db_conn_t *conn = NULL; + char *unescaped = NULL; + char *escaped = NULL; sql_log(DEBUG_FUNC, "%s", "entering \tpostgres cmd_escapestring"); @@@@ -1102,9 +1104,16 @@@@ conn = (db_conn_t *) entry->data; /* PostgreSQL has no way to escape strings internally */ + /* Note: the PQescapeString() function appeared in the C API as of + * Postgres-7.2. + */ + unescaped = cmd->argv[1]; + escaped = (char *) pcalloc(cmd->tmp_pool, sizeof(char) * + (strlen(unescaped) * 2) + 1); + PQescapeString(escaped, unescaped, strlen(unescaped)); sql_log(DEBUG_FUNC, "%s", "exiting \tpostgres cmd_escapestring"); - return mod_create_data(cmd, (void *) cmd->argv[1]); + return mod_create_data(cmd, (void *) escaped ); d78 16 a93 2 /* @ 1.6.2.1 log @apply ACL CIDR mode bugfix @ text @d1 2 a2 3 This patch fixes the broken ACL implementation. Without this patch the ACLs with CIDR entries will not work. See http://bugs.proftpd.org/show_bug.cgi?id=2267 for details. d4 31 a34 5 Index: src/dirtree.c --- src/dirtree.c.orig 2003-10-19 00:14:14.000000000 +0200 +++ src/dirtree.c 2004-04-30 09:50:58.000000000 +0200 @@@@ -1533,11 +1533,11 @@@@ } d36 5 a40 11 if (cidr_mode) { -/* NOTE: encapsulation breakage note/IPv6 change needed here. */ -#if 0 - if ((cli_addr->s_addr & htonl(cidr_mask)) == cidr_addr.s_addr) -#endif - return 1; + if (pr_netaddr_get_family(cli_addr) == AF_INET) { + struct in_addr *cli_in_addr = pr_netaddr_get_inaddr(cli_addr); + if ((cli_in_addr->s_addr & htonl(cidr_mask)) == cidr_addr.s_addr) + return 1; + } d42 1 a42 2 } else { pr_netaddr_t *acl_addr = NULL; @ 1.5 log @apply security fix @ text @@ 1.4 log @purge patch that was rolled into vendor source @ text @d1 21 a21 5 --- include/glibc-glob.h Mon Jan 20 11:59:41 2003 +++ include/glibc-glob.h Mon Jan 20 12:08:48 2003 @@@@ -49,24 +49,6 @@@@ # define __PMT(x) __P(x) #endif d23 1 a23 31 -/* We need `size_t' for the following definitions. */ -#ifndef __size_t -# if defined __GNUC__ && __GNUC__ >= 2 -typedef __SIZE_TYPE__ __size_t; -# ifdef _XOPEN_SOURCE -typedef __SIZE_TYPE__ size_t; -# endif -# else -/* This is a guess. */ -typedef unsigned long int __size_t; -# endif -#else -/* The GNU CC stddef.h version defines __size_t as empty. We need a real - definition. */ -# undef __size_t -# define __size_t size_t -#endif - /* Bits set in the FLAGS argument to `glob'. */ #define GLOB_ERR (1 << 0)/* Return on read errors. */ #define GLOB_MARK (1 << 1)/* Append a slash to each name. */ @@@@ -117,9 +99,9 @@@@ #endif typedef struct { - __size_t gl_pathc; /* Count of paths matched by the pattern. */ + size_t gl_pathc; /* Count of paths matched by the pattern. */ char **gl_pathv; /* List of matched pathnames. */ - __size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ + size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ d25 2 a26 11 /* If the GLOB_ALTDIRFUNC flag is set, the following functions @@@@ -147,9 +129,9 @@@@ # endif typedef struct { - __size_t gl_pathc; + size_t gl_pathc; char **gl_pathv; - __size_t gl_offs; + size_t gl_offs; int gl_flags; d28 15 a42 1 /* If the GLOB_ALTDIRFUNC flag is set, the following functions @ 1.3 log @align with general style of using %{name}.patch only except for special situation @ text @@ 1.2 log @upgrading package: proftpd 1.2.4 -> 1.2.5 @ text @d1 51 a51 30 Index: modules/mod_ls.c =================================================================== RCS file: /var/proftpd/proftpd-1.2/modules/mod_ls.c,v retrieving revision 1.45 diff -u -r1.45 mod_ls.c --- modules/mod_ls.c 2001/09/26 15:32:47 1.45 +++ modules/mod_ls.c 2001/12/05 18:59:50 @@@@ -1018,7 +1018,10 @@@@ glob_t g; int a; char pbuffer[MAXPATHLEN + 1] = ""; - + + /* make sure the glob_t is initialized */ + memset(&g, '\0', sizeof(glob_t)); + if(*arg == '~') { struct passwd *pw; int i; @@@@ -1491,6 +1494,10 @@@@ if(strpbrk(target,"{[*?") != NULL) { glob_t g; char **path,*p; + + /* make sure the glob_t is initialized */ + memset(&g, '\0', sizeof(glob_t)); + if(fs_glob(target,GLOB_PERIOD,NULL,&g) != 0) { add_response_err(R_550,"No files found."); @ 1.2.4.1 log @MFS: patch against glibc-poking @ text @d1 30 a30 51 --- include/glibc-glob.h Mon Jan 20 11:59:41 2003 +++ include/glibc-glob.h Mon Jan 20 12:08:48 2003 @@@@ -49,24 +49,6 @@@@ # define __PMT(x) __P(x) #endif -/* We need `size_t' for the following definitions. */ -#ifndef __size_t -# if defined __GNUC__ && __GNUC__ >= 2 -typedef __SIZE_TYPE__ __size_t; -# ifdef _XOPEN_SOURCE -typedef __SIZE_TYPE__ size_t; -# endif -# else -/* This is a guess. */ -typedef unsigned long int __size_t; -# endif -#else -/* The GNU CC stddef.h version defines __size_t as empty. We need a real - definition. */ -# undef __size_t -# define __size_t size_t -#endif - /* Bits set in the FLAGS argument to `glob'. */ #define GLOB_ERR (1 << 0)/* Return on read errors. */ #define GLOB_MARK (1 << 1)/* Append a slash to each name. */ @@@@ -117,9 +99,9 @@@@ #endif typedef struct { - __size_t gl_pathc; /* Count of paths matched by the pattern. */ + size_t gl_pathc; /* Count of paths matched by the pattern. */ char **gl_pathv; /* List of matched pathnames. */ - __size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ + size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ /* If the GLOB_ALTDIRFUNC flag is set, the following functions @@@@ -147,9 +129,9 @@@@ # endif typedef struct { - __size_t gl_pathc; + size_t gl_pathc; char **gl_pathv; - __size_t gl_offs; + size_t gl_offs; int gl_flags; /* If the GLOB_ALTDIRFUNC flag is set, the following functions @ 1.2.4.2 log @apply security fix @ text @a0 138 Apply security bugfix related to http://xforce.iss.net/xforce/alerts/id/154 --- src/data.c Tue Oct 29 16:51:54 2002 +++ src/data.c Thu Sep 18 05:59:15 2003 @@@@ -114,16 +114,14 @@@@ * value and its value when this function returns */ static void _xlate_ascii_write(char **buf, unsigned int *buflen, - unsigned int bufsize, unsigned int *expand) { + unsigned int bufsize) { char *tmpbuf = *buf; unsigned int tmplen = *buflen; unsigned int lfcount = 0; + unsigned int added = 0; int res = 0; register unsigned int i = 0; - /* Make sure this is zero (could be a holdover from a previous call). */ - *expand = 0; - /* First, determine how many bare LFs are present. */ if (tmpbuf[0] == '\n') lfcount++; @@@@ -132,6 +130,9 @@@@ if (tmpbuf[i] == '\n' && tmpbuf[i-1] != '\r') lfcount++; + if (lfcount == 0) + return; + /* Assume that for each LF (including a leading LF), space for another * char (a '\r') is needed. Determine whether there is enough space in * the buffer for the adjusted data. If not, allocate a new buffer that is @@@@ -146,7 +147,7 @@@@ * would be of the same type as the operands: an unsigned int (which will * never be less than zero). */ - if ((res = (bufsize - tmplen - lfcount)) < 0) { + if ((res = (bufsize - tmplen - lfcount)) <= 0) { pool *copy_pool = make_sub_pool(session.xfer.p); char *copy_buf = pcalloc(copy_pool, tmplen); @@@@ -180,7 +181,7 @@@@ /* Increment the number of "expanded" characters, and decrement the * number of bare LFs. */ - (*expand)++; + added++; lfcount--; } @@@@ -188,15 +189,15 @@@@ if (tmpbuf[i] == '\n' && tmpbuf[i-1] != '\r') { memmove(&(tmpbuf[i+1]), &(tmpbuf[i]), bufsize - i); tmpbuf[i] = '\r'; - (*expand)++; + added++; lfcount--; } } /* Always make sure the buffer is NUL-terminated. */ - tmpbuf[tmplen + (*expand)] = '\0'; + tmpbuf[tmplen + added] = '\0'; *buf = tmpbuf; - *buflen = tmplen + (*expand); + *buflen = tmplen + added; } static void _data_new_xfer(char *filename, int direction) { @@@@ -826,41 +827,29 @@@@ * xlate ascii as necessary */ while (cl_size) { - int o_size, size = cl_size; - - if (size > PR_TUNABLE_BUFFER_SIZE) - size = PR_TUNABLE_BUFFER_SIZE; - - o_size = size; - memcpy(buf, cl_buf, size); - - while (size) { - char *wb = buf; - unsigned int wsize = size, adjlen = 0; - - if (session.flags & (SF_ASCII|SF_ASCII_OVERRIDE)) - _xlate_ascii_write(&wb, &wsize, session.xfer.bufsize, &adjlen); - - if (pr_netio_write(session.d->outstrm, wb, wsize) == -1) - return -1; - - if (TimeoutStalled) - reset_timer(TIMER_STALLED, ANY_MODULE); - - /* Do not take any added CRs into account for the session sum. */ - total += (wsize - adjlen); - size -= (wsize - adjlen); - - if (size) { - /* Advance the output buffer pointer into unsent buffer space. */ - wb += wsize; - memcpy(buf, wb, size); - buf[size] = '\0'; - } - } + int buflen = cl_size; + unsigned int xferbuflen; - cl_size -= o_size; - cl_buf += o_size; + if (buflen > PR_TUNABLE_BUFFER_SIZE) + buflen = PR_TUNABLE_BUFFER_SIZE; + + xferbuflen = buflen; + memcpy(session.xfer.buf, cl_buf, buflen); + + if (session.flags & (SF_ASCII|SF_ASCII_OVERRIDE)) + _xlate_ascii_write(&session.xfer.buf, &xferbuflen, + session.xfer.bufsize); + + if (pr_netio_write(session.d->outstrm, session.xfer.buf, + xferbuflen) == -1) + return -1; + + if (TimeoutStalled) + reset_timer(TIMER_STALLED, ANY_MODULE); + + cl_size -= buflen; + cl_buf += buflen; + total += buflen; } len = total; ----------------------------------------------------------------------------- @ 1.2.4.3 log @Segfault could not be reproduced on FreeBSD 4.9, 5.1, RedHat 9, Debian 2.2, 3.0, Solaris 9 (iX86); Solaris 8, 9 (SPARC64) but update anyway as a safety precaution @ text @a189 37 It looks like Proftpd versions 1.2.7p and 1.2.8p at least (the versions patched for the ISS ASCII transfer buffer overflow vulnerability) are vulnerable to some kind of buffer overflow: http://bugs.proftpd.org/show_bug.cgi?id=2190 http://bugs.proftpd.org/show_bug.cgi?id=2194 --- src/data.c.orig 2003-10-16 17:55:28.000000000 +0200 +++ src/data.c 2003-10-16 17:56:22.000000000 +0200 @@@@ -154,15 +154,9 @@@@ memmove(copy_buf, tmpbuf, tmplen); /* Allocate a new session.xfer.buf of the needed size. */ - session.xfer.bufsize = tmplen + lfcount; + session.xfer.bufsize = tmplen + lfcount + 1; session.xfer.buf = pcalloc(session.xfer.p, session.xfer.bufsize); - /* Allow space for a CR to be inserted before an LF if an LF is the - * first character in the buffer. - */ - session.xfer.buf++; - session.xfer.bufstart = session.xfer.buf; - memmove(session.xfer.buf, copy_buf, tmplen); destroy_pool(copy_pool); @@@@ -194,8 +188,6 @@@@ } } - /* Always make sure the buffer is NUL-terminated. */ - tmpbuf[tmplen + added] = '\0'; *buf = tmpbuf; *buflen = tmplen + added; } @ 1.2.2.1 log @MFC: patch against glibc-poking @ text @d1 30 a30 51 --- include/glibc-glob.h Mon Jan 20 11:59:41 2003 +++ include/glibc-glob.h Mon Jan 20 12:08:48 2003 @@@@ -49,24 +49,6 @@@@ # define __PMT(x) __P(x) #endif -/* We need `size_t' for the following definitions. */ -#ifndef __size_t -# if defined __GNUC__ && __GNUC__ >= 2 -typedef __SIZE_TYPE__ __size_t; -# ifdef _XOPEN_SOURCE -typedef __SIZE_TYPE__ size_t; -# endif -# else -/* This is a guess. */ -typedef unsigned long int __size_t; -# endif -#else -/* The GNU CC stddef.h version defines __size_t as empty. We need a real - definition. */ -# undef __size_t -# define __size_t size_t -#endif - /* Bits set in the FLAGS argument to `glob'. */ #define GLOB_ERR (1 << 0)/* Return on read errors. */ #define GLOB_MARK (1 << 1)/* Append a slash to each name. */ @@@@ -117,9 +99,9 @@@@ #endif typedef struct { - __size_t gl_pathc; /* Count of paths matched by the pattern. */ + size_t gl_pathc; /* Count of paths matched by the pattern. */ char **gl_pathv; /* List of matched pathnames. */ - __size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ + size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ /* If the GLOB_ALTDIRFUNC flag is set, the following functions @@@@ -147,9 +129,9 @@@@ # endif typedef struct { - __size_t gl_pathc; + size_t gl_pathc; char **gl_pathv; - __size_t gl_offs; + size_t gl_offs; int gl_flags; /* If the GLOB_ALTDIRFUNC flag is set, the following functions @ 1.2.2.2 log @mass Merge-From-CURRENT (MFC) in preparation for OpenPKG 1.3 [class BASE only] @ text @d1 5 a5 21 http://www.debian.org/security/2003/dsa-338 DSA-338-1 proftpd -- SQL injection, Date Reported: 29 Jun 2003 runlevel [runlevel@@raregazz.org] reported that ProFTPD's PostgreSQL authentication module is vulnerable to a SQL injection attack. This vulnerability could be exploited by a remote, unauthenticated attacker to execute arbitrary SQL statements, potentially exposing the passwords of other users, or to connect to ProFTPD as an arbitrary user without supplying the correct password. patch AE.mod_sql_postgres.c.diff extracted from http://security.debian.org/pool/updates/main/p/proftpd/proftpd_1.2.4+1.2.5rc1-5woody2.tar.gz --- contrib/mod_sql_postgres.c.orig Wed Jul 2 16:49:26 2003 +++ contrib/mod_sql_postgres.c Wed Jul 2 16:56:35 2003 @@@@ -1082,6 +1082,8 @@@@ { conn_entry_t *entry = NULL; db_conn_t *conn = NULL; + char *unescaped = NULL; + char *escaped = NULL; d7 31 a37 1 sql_log(DEBUG_FUNC, "%s", "entering \tpostgres cmd_escapestring"); d39 11 a49 2 @@@@ -1102,9 +1104,16 @@@@ conn = (db_conn_t *) entry->data; d51 1 a51 15 /* PostgreSQL has no way to escape strings internally */ + /* Note: the PQescapeString() function appeared in the C API as of + * Postgres-7.2. + */ + unescaped = cmd->argv[1]; + escaped = (char *) pcalloc(cmd->tmp_pool, sizeof(char) * + (strlen(unescaped) * 2) + 1); + PQescapeString(escaped, unescaped, strlen(unescaped)); sql_log(DEBUG_FUNC, "%s", "exiting \tpostgres cmd_escapestring"); - return mod_create_data(cmd, (void *) cmd->argv[1]); + return mod_create_data(cmd, (void *) escaped ); } /* @ 1.2.2.2.2.1 log @apply security bugfix @ text @a0 131 Security bugfix related to http://xforce.iss.net/xforce/alerts/id/154 --- src/data.c Wed Feb 12 20:03:36 2003 +++ src/data.c Thu Sep 18 06:00:19 2003 @@@@ -114,16 +114,14 @@@@ * value and its value when this function returns */ static void _xlate_ascii_write(char **buf, unsigned int *buflen, - unsigned int bufsize, unsigned int *expand) { + unsigned int bufsize) { char *tmpbuf = *buf; unsigned int tmplen = *buflen; unsigned int lfcount = 0; + unsigned int added = 0; int res = 0; register unsigned int i = 0; - /* Make sure this is zero (could be a holdover from a previous call). */ - *expand = 0; - /* First, determine how many bare LFs are present. */ if (tmpbuf[0] == '\n') lfcount++; @@@@ -132,6 +130,9 @@@@ if (tmpbuf[i] == '\n' && tmpbuf[i-1] != '\r') lfcount++; + if (lfcount == 0) + return; + /* Assume that for each LF (including a leading LF), space for another * char (a '\r') is needed. Determine whether there is enough space in * the buffer for the adjusted data. If not, allocate a new buffer that is @@@@ -146,7 +147,7 @@@@ * would be of the same type as the operands: an unsigned int (which will * never be less than zero). */ - if ((res = (bufsize - tmplen - lfcount)) < 0) { + if ((res = (bufsize - tmplen - lfcount)) <= 0) { pool *copy_pool = make_sub_pool(session.xfer.p); char *copy_buf = pcalloc(copy_pool, tmplen); @@@@ -180,7 +181,7 @@@@ /* Increment the number of "expanded" characters, and decrement the * number of bare LFs. */ - (*expand)++; + added++; lfcount--; } @@@@ -188,15 +189,15 @@@@ if (tmpbuf[i] == '\n' && tmpbuf[i-1] != '\r') { memmove(&(tmpbuf[i+1]), &(tmpbuf[i]), bufsize - i); tmpbuf[i] = '\r'; - (*expand)++; + added++; lfcount--; } } /* Always make sure the buffer is NUL-terminated. */ - tmpbuf[tmplen + (*expand)] = '\0'; + tmpbuf[tmplen + added] = '\0'; *buf = tmpbuf; - *buflen = tmplen + (*expand); + *buflen = tmplen + added; } static void data_new_xfer(char *filename, int direction) { @@@@ -844,41 +845,29 @@@@ * xlate ascii as necessary */ while (cl_size) { - int o_size, size = cl_size; + int buflen = cl_size; + unsigned int xferbuflen; - if (size > PR_TUNABLE_BUFFER_SIZE) - size = PR_TUNABLE_BUFFER_SIZE; + if (buflen > PR_TUNABLE_BUFFER_SIZE) + buflen = PR_TUNABLE_BUFFER_SIZE; - o_size = size; - memcpy(buf, cl_buf, size); + xferbuflen = buflen; + memcpy(session.xfer.buf, cl_buf, buflen); - while (size) { - char *wb = buf; - unsigned int wsize = size, adjlen = 0; + if (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE)) + _xlate_ascii_write(&session.xfer.buf, &xferbuflen, + session.xfer.bufsize); - if (session.sf_flags & (SF_ASCII|SF_ASCII_OVERRIDE)) - _xlate_ascii_write(&wb, &wsize, session.xfer.bufsize, &adjlen); + if (pr_netio_write(session.d->outstrm, session.xfer.buf, + xferbuflen) == -1) + return -1; - if (pr_netio_write(session.d->outstrm, wb, wsize) == -1) - return -1; - - if (TimeoutStalled) - reset_timer(TIMER_STALLED, ANY_MODULE); - - /* Do not take any added CRs into account for the session sum. */ - total += (wsize - adjlen); - size -= (wsize - adjlen); - - if (size) { - /* Advance the output buffer pointer into unsent buffer space. */ - wb += wsize; - memcpy(buf, wb, size); - buf[size] = '\0'; - } - } + if (TimeoutStalled) + reset_timer(TIMER_STALLED, ANY_MODULE); - cl_size -= o_size; - cl_buf += o_size; + cl_size -= buflen; + cl_buf += buflen; + total += buflen; } len = total; @ 1.2.2.2.2.2 log @Segfault could not be reproduced on FreeBSD 4.9, 5.1, RedHat 9, Debian 2.2, 3.0, Solaris 9 (iX86); Solaris 8, 9 (SPARC64) but update anyway as a safety precaution @ text @a173 37 It looks like Proftpd versions 1.2.7p and 1.2.8p at least (the versions patched for the ISS ASCII transfer buffer overflow vulnerability) are vulnerable to some kind of buffer overflow: http://bugs.proftpd.org/show_bug.cgi?id=2190 http://bugs.proftpd.org/show_bug.cgi?id=2194 --- src/data.c.orig 2003-10-16 17:42:39.000000000 +0200 +++ src/data.c 2003-10-16 17:46:55.000000000 +0200 @@@@ -154,15 +154,9 @@@@ memmove(copy_buf, tmpbuf, tmplen); /* Allocate a new session.xfer.buf of the needed size. */ - session.xfer.bufsize = tmplen + lfcount; + session.xfer.bufsize = tmplen + lfcount + 1; session.xfer.buf = pcalloc(session.xfer.p, session.xfer.bufsize); - /* Allow space for a CR to be inserted before an LF if an LF is the - * first character in the buffer. - */ - session.xfer.buf++; - session.xfer.bufstart = session.xfer.buf; - memmove(session.xfer.buf, copy_buf, tmplen); destroy_pool(copy_pool); @@@@ -194,8 +188,6 @@@@ } } - /* Always make sure the buffer is NUL-terminated. */ - tmpbuf[tmplen + added] = '\0'; *buf = tmpbuf; *buflen = tmplen + added; } @ 1.1 log @Finally rename all foo-X.Y.patch files to foo.patch in order to allow us to preserve history in CVS for patch files. @ text @@