OpenPKG CVS Repository
http://cvs.openpkg.org/
____________________________________________________________________________
Server: cvs.openpkg.org Name: Ralf S. Engelschall
Root: /v/openpkg/cvs Email: [EMAIL PROTECTED]
Module: openpkg-src Date: 25-Jul-2007 10:30:55
Branch: HEAD Handle: 2007072509305400
Modified files:
openpkg-src/proftpd proftpd.patch proftpd.spec
Log:
upgrading package: proftpd 1.3.0a -> 1.3.1rc3
Summary:
Revision Changes Path
1.24 +97 -1152 openpkg-src/proftpd/proftpd.patch
1.131 +3 -3 openpkg-src/proftpd/proftpd.spec
____________________________________________________________________________
patch -p0 <<'@@ .'
Index: openpkg-src/proftpd/proftpd.patch
============================================================================
$ cvs diff -u -r1.23 -r1.24 proftpd.patch
--- openpkg-src/proftpd/proftpd.patch 22 May 2007 09:49:57 -0000 1.23
+++ openpkg-src/proftpd/proftpd.patch 25 Jul 2007 08:30:54 -0000 1.24
@@ -1,40 +1,87 @@
-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");
+Index: mod_otp/mod_otp.c
+--- mod_otp/mod_otp.c.orig 2006-12-06 17:13:06 +0100
++++ mod_otp/mod_otp.c 2007-07-25 10:24:36 +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 PR_ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "uninitialized
module");
-+ return ERROR_MSG(cmd, MOD_SQL_SQLITE_VERSION, "uninitialized module");
+ return DECLINED(cmd);
+ }
+Index: mod_time/mod_time.c
+--- mod_time/mod_time.c.orig 2004-05-12 20:57:06 +0200
++++ mod_time/mod_time.c 2007-07-25 10:24:36 +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);
}
- conn = (db_conn_t *) palloc(conn_pool, sizeof(db_conn_t));
-@@ -706,7 +706,7 @@
-
- MODRET sql_sqlite_prepare(cmd_rec *cmd) {
- if (cmd->argc != 1) {
-- return PR_ERROR(cmd);
-+ return ERROR(cmd);
- }
+@@ -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 @@
- 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");
+ /* 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;
+@@ -634,7 +634,7 @@
+ if (!session.user) {
+ /* Populate the pw struct, check for a NULL return value. */
- add_config_param_str(cmd->argv[0], 1, cmd->argv[1]);
-- return PR_HANDLED(cmd);
-+ return HANDLED(cmd);
- }
+- if ((pw = auth_getpwnam(cmd->tmp_pool, user)) == NULL)
++ if ((pw = pr_auth_getpwnam(cmd->tmp_pool, user)) == NULL)
+ return NULL;
- /* usage: VRootOptions opt1 opt2 ... optN */
+ time_user = pstrdup(session.pool, pw->pw_name);
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 @@
+--- modules/mod_auth_unix.c.orig 2006-06-29 19:16:23 +0200
++++ modules/mod_auth_unix.c 2007-07-25 10:24:36 +0200
+@@ -243,7 +243,7 @@
return gr;
}
@@ -43,7 +90,7 @@
if (m1->id.uid < m2->id.uid)
return -1;
-@@ -258,7 +258,7 @@
+@@ -253,7 +253,7 @@
return 0;
}
@@ -52,7 +99,7 @@
if (m1->id.gid < m2->id.gid)
return -1;
-@@ -268,7 +268,7 @@
+@@ -263,7 +263,7 @@
return 0;
}
@@ -61,1124 +108,22 @@
if (table == uid_table)
return id.uid == idcomp.uid;
else
-
------------------------------------------------------------------------------
-
-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;
+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);
+ }
}
- }
-
------------------------------------------------------------------------------
-
-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 <min-max>] [name <regex>] */
- 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();
-
+
@@ .
patch -p0 <<'@@ .'
Index: openpkg-src/proftpd/proftpd.spec
============================================================================
$ cvs diff -u -r1.130 -r1.131 proftpd.spec
--- openpkg-src/proftpd/proftpd.spec 22 May 2007 09:49:58 -0000 1.130
+++ openpkg-src/proftpd/proftpd.spec 25 Jul 2007 08:30:54 -0000 1.131
@@ -23,7 +23,7 @@
##
# package version
-%define V_proftpd 1.3.0a
+%define V_proftpd 1.3.1rc3
%define V_mod_exec 0.9.2
%define V_mod_otp 0.9.1
%define V_mod_shaper 0.6.3
@@ -44,7 +44,7 @@
Group: FTP
License: GPL
Version: %{V_proftpd}
-Release: 20070522
+Release: 20070725
# package options
%option with_ifsession no
@@ -148,7 +148,7 @@
prog proftpd = {
version = %{V_proftpd}
url = ftp://ftp.proftpd.org/distrib/source/
- regex = proftpd-(\d+\.\d+\.\d+[a-z]?)\.tar\.bz2
+ regex = proftpd-(\d+\.\d+\.\d+(?:rc\d+|[a-z]?))\.tar\.bz2
}
prog proftpd:mod_exec = {
version = %{V_mod_exec}
@@ .
______________________________________________________________________
OpenPKG http://openpkg.org
CVS Repository Commit List [email protected]