head 1.2; access; symbols pkgsrc-2013Q2:1.2.0.24 pkgsrc-2013Q2-base:1.2 pkgsrc-2012Q4:1.2.0.22 pkgsrc-2012Q4-base:1.2 pkgsrc-2011Q4:1.2.0.20 pkgsrc-2011Q4-base:1.2 pkgsrc-2011Q2:1.2.0.18 pkgsrc-2011Q2-base:1.2 pkgsrc-2009Q4:1.2.0.16 pkgsrc-2009Q4-base:1.2 pkgsrc-2008Q4:1.2.0.14 pkgsrc-2008Q4-base:1.2 pkgsrc-2008Q3:1.2.0.12 pkgsrc-2008Q3-base:1.2 cube-native-xorg:1.2.0.10 cube-native-xorg-base:1.2 pkgsrc-2008Q2:1.2.0.8 pkgsrc-2008Q2-base:1.2 pkgsrc-2008Q1:1.2.0.6 pkgsrc-2008Q1-base:1.2 pkgsrc-2007Q4:1.2.0.4 pkgsrc-2007Q4-base:1.2 pkgsrc-2007Q3:1.2.0.2 pkgsrc-2007Q3-base:1.2 pkgsrc-2007Q2:1.1.0.4 pkgsrc-2007Q2-base:1.1 pkgsrc-2007Q1:1.1.0.2; locks; strict; comment @# @; 1.2 date 2007.07.06.11.04.41; author martti; state dead; branches; next 1.1; 1.1 date 2007.06.26.23.25.56; author lkundrak; state Exp; branches 1.1.2.1 1.1.4.1; next ; 1.1.2.1 date 2007.06.26.23.25.56; author ghen; state dead; branches; next 1.1.2.2; 1.1.2.2 date 2007.06.28.10.49.46; author ghen; state Exp; branches; next ; 1.1.4.1 date 2007.07.10.12.16.06; author ghen; state dead; branches; next ; desc @@ 1.2 log @Updated net/proftpd to 1.3.1rc3 Hello, ProFTPD community. The ProFTPD Project team is pleased to announce that the third release candidate for ProFTPD 1.3.1 is now available for public consumption. The 1.3.1rc3 release includes a number of minor bugfixes, including segfaults when handling the NLST command, dealing assigning IPv6 addresses for the EPSV command, and better handling of Display files in chrooted sessions. Please read the included NEWS and ChangeLog files for the full details. @ text @$NetBSD: patch-af,v 1.1 2007/06/26 23:25:56 lkundrak Exp $ Part of fix for CVE-2007-2165 grabbed from upstream #2922. --- src/auth.c.orig 2007-06-27 01:13:58.000000000 +0200 +++ src/auth.c @@@@ -2,7 +2,7 @@@@ * ProFTPD - FTP server daemon * Copyright (c) 1997, 1998 Public Flood Software * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu - * Copyright (c) 2001-2006 The ProFTPD Project team + * Copyright (c) 2001-2007 The ProFTPD Project team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@@@ -30,6 +30,10 @@@@ #include "conf.h" +static pool *auth_pool = NULL; +static pr_table_t *auth_tab = NULL; +static const char *trace_channel = "auth"; + /* The difference between this function, and pr_cmd_alloc(), is that this * allocates the cmd_rec directly from the given pool, whereas pr_cmd_alloc() * will allocate a subpool from the given pool, and allocate its cmd_rec @@@@ -63,7 +67,7 @@@@ static cmd_rec *make_cmd(pool *cp, int a return c; } -static modret_t *dispatch_auth(cmd_rec *cmd, char *match) { +static modret_t *dispatch_auth(cmd_rec *cmd, char *match, module **m) { authtable *start_tab = NULL, *iter_tab = NULL; modret_t *mr = NULL; @@@@ -74,7 +78,12 @@@@ static modret_t *dispatch_auth(cmd_rec * while (iter_tab) { pr_signals_handle(); - pr_trace_msg("auth", 6, "dispatching auth request \"%s\" to module mod_%s", + if (m && *m && *m != iter_tab->m) { + goto next; + } + + pr_trace_msg(trace_channel, 6, + "dispatching auth request \"%s\" to module mod_%s", match, iter_tab->m->name); mr = call_module(iter_tab->m, iter_tab->handler, cmd); @@@@ -83,9 +92,19 @@@@ static modret_t *dispatch_auth(cmd_rec * break; if (MODRET_ISHANDLED(mr) || - MODRET_ISERROR(mr)) + MODRET_ISERROR(mr)) { + + /* Return a pointer, if requested, to the module which answered the + * auth request. This is used, for example, by auth_getpwnam() for + * associating the answering auth module with the data looked up. + */ + if (m) + *m = iter_tab->m; + break; + } + next: iter_tab = pr_stash_get_symbol(PR_SYM_AUTH, match, iter_tab, &cmd->stash_index); @@@@ -106,7 +125,7 @@@@ void pr_auth_setpwent(pool *p) { modret_t *mr = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "setpwent"); + mr = dispatch_auth(cmd, "setpwent", NULL); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); @@@@ -121,13 +140,20 @@@@ void pr_auth_endpwent(pool *p) { modret_t *mr = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "endpwent"); + mr = dispatch_auth(cmd, "endpwent", NULL); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } + if (auth_tab) { + pr_trace_msg(trace_channel, 5, "emptying authcache"); + (void) pr_table_empty(auth_tab); + (void) pr_table_free(auth_tab); + auth_tab = NULL; + } + return; } @@@@ -136,7 +162,7 @@@@ void pr_auth_setgrent(pool *p) { modret_t *mr = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "setgrent"); + mr = dispatch_auth(cmd, "setgrent", NULL); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); @@@@ -151,7 +177,7 @@@@ void pr_auth_endgrent(pool *p) { modret_t *mr = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "endgrent"); + mr = dispatch_auth(cmd, "endgrent", NULL); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); @@@@ -167,7 +193,7 @@@@ struct passwd *pr_auth_getpwent(pool *p) struct passwd *res = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "getpwent"); + mr = dispatch_auth(cmd, "getpwent", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; @@@@ -201,7 +227,7 @@@@ struct group *pr_auth_getgrent(pool *p) struct group *res = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "getgrent"); + mr = dispatch_auth(cmd, "getgrent", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; @@@@ -228,11 +254,13 @@@@ struct passwd *pr_auth_getpwnam(pool *p, cmd_rec *cmd = NULL; modret_t *mr = NULL; struct passwd *res = NULL; + module *m = NULL; cmd = make_cmd(p, 1, name); - mr = dispatch_auth(cmd, "getpwnam"); + mr = dispatch_auth(cmd, "getpwnam", &m); - if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) + if (MODRET_ISHANDLED(mr) && + MODRET_HASDATA(mr)) res = mr->data; if (cmd->tmp_pool) { @@@@ -257,6 +285,46 @@@@ struct passwd *pr_auth_getpwnam(pool *p, return NULL; } + if (!auth_tab && auth_pool) { + auth_tab = pr_table_alloc(auth_pool, 0); + } + + if (m && auth_tab) { + int count = 0; + void *value = NULL; + + value = palloc(auth_pool, sizeof(module *)); + *((module **) value) = m; + + count = pr_table_exists(auth_tab, name); + if (count <= 0) { + if (pr_table_add(auth_tab, pstrdup(auth_pool, name), value, + sizeof(module *)) < 0) { + pr_trace_msg(trace_channel, 3, + "error adding module 'mod_%s.c' for user '%s' to the authcache: %s", + m->name, name, strerror(errno)); + + } else { + pr_trace_msg(trace_channel, 5, + "stashed module 'mod_%s.c' for user '%s' in the authcache", + m->name, name); + } + + } else { + if (pr_table_set(auth_tab, pstrdup(auth_pool, name), value, + sizeof(module *)) < 0) { + pr_trace_msg(trace_channel, 3, + "error setting module 'mod_%s.c' for user '%s' in the authcache: %s", + m->name, name, strerror(errno)); + + } else { + pr_trace_msg(trace_channel, 5, + "stashed module 'mod_%s.c' for user '%s' in the authcache", + m->name, name); + } + } + } + pr_log_debug(DEBUG10, "retrieved UID %lu for user '%s'", (unsigned long) res->pw_uid, name); return res; @@@@ -268,7 +336,7 @@@@ struct passwd *pr_auth_getpwuid(pool *p, struct passwd *res = NULL; cmd = make_cmd(p, 1, (void *) &uid); - mr = dispatch_auth(cmd, "getpwuid"); + mr = dispatch_auth(cmd, "getpwuid", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; @@@@ -306,7 +374,7 @@@@ struct group *pr_auth_getgrnam(pool *p, struct group *res = NULL; cmd = make_cmd(p, 1, name); - mr = dispatch_auth(cmd, "getgrnam"); + mr = dispatch_auth(cmd, "getgrnam", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; @@@@ -339,7 +407,7 @@@@ struct group *pr_auth_getgrgid(pool *p, struct group *res = NULL; cmd = make_cmd(p, 1, (void *) &gid); - mr = dispatch_auth(cmd, "getgrgid"); + mr = dispatch_auth(cmd, "getgrgid", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; @@@@ -369,10 +437,51 @@@@ struct group *pr_auth_getgrgid(pool *p, int pr_auth_authenticate(pool *p, const char *name, const char *pw) { cmd_rec *cmd = NULL; modret_t *mr = NULL; + module *m = NULL; int res = PR_AUTH_NOPWD; cmd = make_cmd(p, 2, name, pw); - mr = dispatch_auth(cmd, "auth"); + + /* First, check for the mod_auth_pam.c module. + * + * PAM is a bit of hack in this Auth API, because PAM only provides + * yes/no checks, and is not a source of user information. + */ + m = pr_module_get("mod_auth_pam.c"); + if (m) { + mr = dispatch_auth(cmd, "auth", &m); + + if (MODRET_ISHANDLED(mr)) { + pr_trace_msg(trace_channel, 4, + "module 'mod_auth_pam.c' used for authenticating user '%s'", name); + + res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; + + if (cmd->tmp_pool) { + destroy_pool(cmd->tmp_pool); + cmd->tmp_pool = NULL; + } + + return res; + } + + m = NULL; + } + + if (auth_tab) { + + /* Fetch the specific module to be used for authenticating this user. */ + void *v = pr_table_get(auth_tab, name, NULL); + if (v) { + m = *((module **) v); + + pr_trace_msg(trace_channel, 4, + "using module 'mod_%s.c' from authcache to authenticate user '%s'", + m->name, name); + } + } + + mr = dispatch_auth(cmd, "auth", m ? &m : NULL); if (MODRET_ISHANDLED(mr)) res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; @@@@ -391,10 +500,51 @@@@ int pr_auth_authenticate(pool *p, const int pr_auth_check(pool *p, const char *cpw, const char *name, const char *pw) { cmd_rec *cmd = NULL; modret_t *mr = NULL; + module *m = NULL; int res = PR_AUTH_BADPWD; cmd = make_cmd(p, 3, cpw, name, pw); - mr = dispatch_auth(cmd, "check"); + + /* First, check for the mod_auth_pam.c module. + * + * PAM is a bit of hack in this Auth API, because PAM only provides + * yes/no checks, and is not a source of user information. + */ + m = pr_module_get("mod_auth_pam.c"); + if (m) { + mr = dispatch_auth(cmd, "check", &m); + + if (MODRET_ISHANDLED(mr)) { + pr_trace_msg(trace_channel, 4, + "module 'mod_auth_pam.c' used for authenticating user '%s'", name); + + res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; + + if (cmd->tmp_pool) { + destroy_pool(cmd->tmp_pool); + cmd->tmp_pool = NULL; + } + + return res; + } + + m = NULL; + } + + if (auth_tab) { + + /* Fetch the specific module to be used for authenticating this user. */ + void *v = pr_table_get(auth_tab, name, NULL); + if (v) { + m = *((module **) v); + + pr_trace_msg(trace_channel, 4, + "using module 'mod_%s.c' from authcache to authenticate user '%s'", + m->name, name); + } + } + + mr = dispatch_auth(cmd, "check", m ? &m : NULL); if (MODRET_ISHANDLED(mr)) res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; @@@@ -413,7 +563,7 @@@@ int pr_auth_requires_pass(pool *p, const int res = TRUE; cmd = make_cmd(p, 1, name); - mr = dispatch_auth(cmd, "requires_pass"); + mr = dispatch_auth(cmd, "requires_pass", NULL); if (MODRET_ISHANDLED(mr)) res = FALSE; @@@@ -438,7 +588,7 @@@@ const char *pr_auth_uid2name(pool *p, ui memset(namebuf, '\0', sizeof(namebuf)); cmd = make_cmd(p, 1, (void *) &uid); - mr = dispatch_auth(cmd, "uid2name"); + mr = dispatch_auth(cmd, "uid2name", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = mr->data; @@@@ -463,7 +613,7 @@@@ const char *pr_auth_gid2name(pool *p, gi memset(namebuf, '\0', sizeof(namebuf)); cmd = make_cmd(p, 1, (void *) &gid); - mr = dispatch_auth(cmd, "gid2name"); + mr = dispatch_auth(cmd, "gid2name", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = mr->data; @@@@ -485,7 +635,7 @@@@ uid_t pr_auth_name2uid(pool *p, const ch uid_t res = (uid_t) -1; cmd = make_cmd(p, 1, name); - mr = dispatch_auth(cmd, "name2uid"); + mr = dispatch_auth(cmd, "name2uid", NULL); if (MODRET_ISHANDLED(mr)) res = *((uid_t *) mr->data); @@@@ -506,7 +656,7 @@@@ gid_t pr_auth_name2gid(pool *p, const ch gid_t res = (gid_t) -1; cmd = make_cmd(p, 1, name); - mr = dispatch_auth(cmd, "name2gid"); + mr = dispatch_auth(cmd, "name2gid", NULL); if (MODRET_ISHANDLED(mr)) res = *((gid_t *) mr->data); @@@@ -538,7 +688,7 @@@@ int pr_auth_getgroups(pool *p, const cha cmd = make_cmd(p, 3, name, group_ids ? *group_ids : NULL, group_names ? *group_names : NULL); - mr = dispatch_auth(cmd, "getgroups"); + mr = dispatch_auth(cmd, "getgroups", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = *((int *) mr->data); @@@@ -832,3 +982,10 @@@@ int set_groups(pool *p, gid_t primary_gi return res; } +/* Internal use only. To be called in the session process. */ +int init_auth(void) { + auth_pool = make_sub_pool(permanent_pool); + pr_pool_tag(auth_pool, "Auth API"); + + return 0; +} @ 1.1 log @Fix for a CVE-2007-2165 security issue grabbed from upstream #2922. @ text @d1 1 a1 1 $NetBSD$ @ 1.1.4.1 log @Pullup ticket 2139 - requested by martti bugfix update for proftpd - pkgsrc/net/proftpd/Makefile 1.42 - pkgsrc/net/proftpd/PLIST 1.13 - pkgsrc/net/proftpd/distinfo 1.24 - pkgsrc/net/proftpd/patches/patch-ab 1.7 - pkgsrc/net/proftpd/patches/patch-ac 1.9 - pkgsrc/net/proftpd/patches/patch-ad removed - pkgsrc/net/proftpd/patches/patch-ae removed - pkgsrc/net/proftpd/patches/patch-af removed Module Name: pkgsrc Committed By: martti Date: Fri Jul 6 11:04:41 UTC 2007 Modified Files: pkgsrc/net/proftpd: Makefile PLIST distinfo pkgsrc/net/proftpd/patches: patch-ab patch-ac Removed Files: pkgsrc/net/proftpd/patches: patch-ad patch-ae patch-af Log Message: Updated net/proftpd to 1.3.1rc3 Hello, ProFTPD community. The ProFTPD Project team is pleased to announce that the third release candidate for ProFTPD 1.3.1 is now available for public consumption. The 1.3.1rc3 release includes a number of minor bugfixes, including segfaults when handling the NLST command, dealing assigning IPv6 addresses for the EPSV command, and better handling of Display files in chrooted sessions. Please read the included NEWS and ChangeLog files for the full details. @ text @d1 1 a1 1 $NetBSD: patch-af,v 1.1 2007/06/26 23:25:56 lkundrak Exp $ @ 1.1.2.1 log @file patch-af was added on branch pkgsrc-2007Q1 on 2007-06-28 10:49:46 +0000 @ text @d1 398 @ 1.1.2.2 log @Pullup ticket 2124 - requested by lkundrak security fix for proftpd - pkgsrc/net/proftpd/Makefile 1.41 - pkgsrc/net/proftpd/distinfo 1.23 - pkgsrc/net/proftpd/patches/patch-ad 1.3 - pkgsrc/net/proftpd/patches/patch-ae 1.3 - pkgsrc/net/proftpd/patches/patch-af 1.1 Module Name: pkgsrc Committed By: lkundrak Date: Tue Jun 26 23:25:57 UTC 2007 Modified Files: pkgsrc/net/proftpd: Makefile distinfo Added Files: pkgsrc/net/proftpd/patches: patch-ad patch-ae patch-af Log Message: Fix for a CVE-2007-2165 security issue grabbed from upstream #2922. @ text @a0 398 $NetBSD$ Part of fix for CVE-2007-2165 grabbed from upstream #2922. --- src/auth.c.orig 2007-06-27 01:13:58.000000000 +0200 +++ src/auth.c @@@@ -2,7 +2,7 @@@@ * ProFTPD - FTP server daemon * Copyright (c) 1997, 1998 Public Flood Software * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu - * Copyright (c) 2001-2006 The ProFTPD Project team + * Copyright (c) 2001-2007 The ProFTPD Project team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@@@ -30,6 +30,10 @@@@ #include "conf.h" +static pool *auth_pool = NULL; +static pr_table_t *auth_tab = NULL; +static const char *trace_channel = "auth"; + /* The difference between this function, and pr_cmd_alloc(), is that this * allocates the cmd_rec directly from the given pool, whereas pr_cmd_alloc() * will allocate a subpool from the given pool, and allocate its cmd_rec @@@@ -63,7 +67,7 @@@@ static cmd_rec *make_cmd(pool *cp, int a return c; } -static modret_t *dispatch_auth(cmd_rec *cmd, char *match) { +static modret_t *dispatch_auth(cmd_rec *cmd, char *match, module **m) { authtable *start_tab = NULL, *iter_tab = NULL; modret_t *mr = NULL; @@@@ -74,7 +78,12 @@@@ static modret_t *dispatch_auth(cmd_rec * while (iter_tab) { pr_signals_handle(); - pr_trace_msg("auth", 6, "dispatching auth request \"%s\" to module mod_%s", + if (m && *m && *m != iter_tab->m) { + goto next; + } + + pr_trace_msg(trace_channel, 6, + "dispatching auth request \"%s\" to module mod_%s", match, iter_tab->m->name); mr = call_module(iter_tab->m, iter_tab->handler, cmd); @@@@ -83,9 +92,19 @@@@ static modret_t *dispatch_auth(cmd_rec * break; if (MODRET_ISHANDLED(mr) || - MODRET_ISERROR(mr)) + MODRET_ISERROR(mr)) { + + /* Return a pointer, if requested, to the module which answered the + * auth request. This is used, for example, by auth_getpwnam() for + * associating the answering auth module with the data looked up. + */ + if (m) + *m = iter_tab->m; + break; + } + next: iter_tab = pr_stash_get_symbol(PR_SYM_AUTH, match, iter_tab, &cmd->stash_index); @@@@ -106,7 +125,7 @@@@ void pr_auth_setpwent(pool *p) { modret_t *mr = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "setpwent"); + mr = dispatch_auth(cmd, "setpwent", NULL); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); @@@@ -121,13 +140,20 @@@@ void pr_auth_endpwent(pool *p) { modret_t *mr = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "endpwent"); + mr = dispatch_auth(cmd, "endpwent", NULL); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); cmd->tmp_pool = NULL; } + if (auth_tab) { + pr_trace_msg(trace_channel, 5, "emptying authcache"); + (void) pr_table_empty(auth_tab); + (void) pr_table_free(auth_tab); + auth_tab = NULL; + } + return; } @@@@ -136,7 +162,7 @@@@ void pr_auth_setgrent(pool *p) { modret_t *mr = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "setgrent"); + mr = dispatch_auth(cmd, "setgrent", NULL); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); @@@@ -151,7 +177,7 @@@@ void pr_auth_endgrent(pool *p) { modret_t *mr = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "endgrent"); + mr = dispatch_auth(cmd, "endgrent", NULL); if (cmd->tmp_pool) { destroy_pool(cmd->tmp_pool); @@@@ -167,7 +193,7 @@@@ struct passwd *pr_auth_getpwent(pool *p) struct passwd *res = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "getpwent"); + mr = dispatch_auth(cmd, "getpwent", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; @@@@ -201,7 +227,7 @@@@ struct group *pr_auth_getgrent(pool *p) struct group *res = NULL; cmd = make_cmd(p, 0); - mr = dispatch_auth(cmd, "getgrent"); + mr = dispatch_auth(cmd, "getgrent", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; @@@@ -228,11 +254,13 @@@@ struct passwd *pr_auth_getpwnam(pool *p, cmd_rec *cmd = NULL; modret_t *mr = NULL; struct passwd *res = NULL; + module *m = NULL; cmd = make_cmd(p, 1, name); - mr = dispatch_auth(cmd, "getpwnam"); + mr = dispatch_auth(cmd, "getpwnam", &m); - if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) + if (MODRET_ISHANDLED(mr) && + MODRET_HASDATA(mr)) res = mr->data; if (cmd->tmp_pool) { @@@@ -257,6 +285,46 @@@@ struct passwd *pr_auth_getpwnam(pool *p, return NULL; } + if (!auth_tab && auth_pool) { + auth_tab = pr_table_alloc(auth_pool, 0); + } + + if (m && auth_tab) { + int count = 0; + void *value = NULL; + + value = palloc(auth_pool, sizeof(module *)); + *((module **) value) = m; + + count = pr_table_exists(auth_tab, name); + if (count <= 0) { + if (pr_table_add(auth_tab, pstrdup(auth_pool, name), value, + sizeof(module *)) < 0) { + pr_trace_msg(trace_channel, 3, + "error adding module 'mod_%s.c' for user '%s' to the authcache: %s", + m->name, name, strerror(errno)); + + } else { + pr_trace_msg(trace_channel, 5, + "stashed module 'mod_%s.c' for user '%s' in the authcache", + m->name, name); + } + + } else { + if (pr_table_set(auth_tab, pstrdup(auth_pool, name), value, + sizeof(module *)) < 0) { + pr_trace_msg(trace_channel, 3, + "error setting module 'mod_%s.c' for user '%s' in the authcache: %s", + m->name, name, strerror(errno)); + + } else { + pr_trace_msg(trace_channel, 5, + "stashed module 'mod_%s.c' for user '%s' in the authcache", + m->name, name); + } + } + } + pr_log_debug(DEBUG10, "retrieved UID %lu for user '%s'", (unsigned long) res->pw_uid, name); return res; @@@@ -268,7 +336,7 @@@@ struct passwd *pr_auth_getpwuid(pool *p, struct passwd *res = NULL; cmd = make_cmd(p, 1, (void *) &uid); - mr = dispatch_auth(cmd, "getpwuid"); + mr = dispatch_auth(cmd, "getpwuid", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; @@@@ -306,7 +374,7 @@@@ struct group *pr_auth_getgrnam(pool *p, struct group *res = NULL; cmd = make_cmd(p, 1, name); - mr = dispatch_auth(cmd, "getgrnam"); + mr = dispatch_auth(cmd, "getgrnam", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; @@@@ -339,7 +407,7 @@@@ struct group *pr_auth_getgrgid(pool *p, struct group *res = NULL; cmd = make_cmd(p, 1, (void *) &gid); - mr = dispatch_auth(cmd, "getgrgid"); + mr = dispatch_auth(cmd, "getgrgid", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) res = mr->data; @@@@ -369,10 +437,51 @@@@ struct group *pr_auth_getgrgid(pool *p, int pr_auth_authenticate(pool *p, const char *name, const char *pw) { cmd_rec *cmd = NULL; modret_t *mr = NULL; + module *m = NULL; int res = PR_AUTH_NOPWD; cmd = make_cmd(p, 2, name, pw); - mr = dispatch_auth(cmd, "auth"); + + /* First, check for the mod_auth_pam.c module. + * + * PAM is a bit of hack in this Auth API, because PAM only provides + * yes/no checks, and is not a source of user information. + */ + m = pr_module_get("mod_auth_pam.c"); + if (m) { + mr = dispatch_auth(cmd, "auth", &m); + + if (MODRET_ISHANDLED(mr)) { + pr_trace_msg(trace_channel, 4, + "module 'mod_auth_pam.c' used for authenticating user '%s'", name); + + res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; + + if (cmd->tmp_pool) { + destroy_pool(cmd->tmp_pool); + cmd->tmp_pool = NULL; + } + + return res; + } + + m = NULL; + } + + if (auth_tab) { + + /* Fetch the specific module to be used for authenticating this user. */ + void *v = pr_table_get(auth_tab, name, NULL); + if (v) { + m = *((module **) v); + + pr_trace_msg(trace_channel, 4, + "using module 'mod_%s.c' from authcache to authenticate user '%s'", + m->name, name); + } + } + + mr = dispatch_auth(cmd, "auth", m ? &m : NULL); if (MODRET_ISHANDLED(mr)) res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; @@@@ -391,10 +500,51 @@@@ int pr_auth_authenticate(pool *p, const int pr_auth_check(pool *p, const char *cpw, const char *name, const char *pw) { cmd_rec *cmd = NULL; modret_t *mr = NULL; + module *m = NULL; int res = PR_AUTH_BADPWD; cmd = make_cmd(p, 3, cpw, name, pw); - mr = dispatch_auth(cmd, "check"); + + /* First, check for the mod_auth_pam.c module. + * + * PAM is a bit of hack in this Auth API, because PAM only provides + * yes/no checks, and is not a source of user information. + */ + m = pr_module_get("mod_auth_pam.c"); + if (m) { + mr = dispatch_auth(cmd, "check", &m); + + if (MODRET_ISHANDLED(mr)) { + pr_trace_msg(trace_channel, 4, + "module 'mod_auth_pam.c' used for authenticating user '%s'", name); + + res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; + + if (cmd->tmp_pool) { + destroy_pool(cmd->tmp_pool); + cmd->tmp_pool = NULL; + } + + return res; + } + + m = NULL; + } + + if (auth_tab) { + + /* Fetch the specific module to be used for authenticating this user. */ + void *v = pr_table_get(auth_tab, name, NULL); + if (v) { + m = *((module **) v); + + pr_trace_msg(trace_channel, 4, + "using module 'mod_%s.c' from authcache to authenticate user '%s'", + m->name, name); + } + } + + mr = dispatch_auth(cmd, "check", m ? &m : NULL); if (MODRET_ISHANDLED(mr)) res = MODRET_HASDATA(mr) ? PR_AUTH_RFC2228_OK : PR_AUTH_OK; @@@@ -413,7 +563,7 @@@@ int pr_auth_requires_pass(pool *p, const int res = TRUE; cmd = make_cmd(p, 1, name); - mr = dispatch_auth(cmd, "requires_pass"); + mr = dispatch_auth(cmd, "requires_pass", NULL); if (MODRET_ISHANDLED(mr)) res = FALSE; @@@@ -438,7 +588,7 @@@@ const char *pr_auth_uid2name(pool *p, ui memset(namebuf, '\0', sizeof(namebuf)); cmd = make_cmd(p, 1, (void *) &uid); - mr = dispatch_auth(cmd, "uid2name"); + mr = dispatch_auth(cmd, "uid2name", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = mr->data; @@@@ -463,7 +613,7 @@@@ const char *pr_auth_gid2name(pool *p, gi memset(namebuf, '\0', sizeof(namebuf)); cmd = make_cmd(p, 1, (void *) &gid); - mr = dispatch_auth(cmd, "gid2name"); + mr = dispatch_auth(cmd, "gid2name", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = mr->data; @@@@ -485,7 +635,7 @@@@ uid_t pr_auth_name2uid(pool *p, const ch uid_t res = (uid_t) -1; cmd = make_cmd(p, 1, name); - mr = dispatch_auth(cmd, "name2uid"); + mr = dispatch_auth(cmd, "name2uid", NULL); if (MODRET_ISHANDLED(mr)) res = *((uid_t *) mr->data); @@@@ -506,7 +656,7 @@@@ gid_t pr_auth_name2gid(pool *p, const ch gid_t res = (gid_t) -1; cmd = make_cmd(p, 1, name); - mr = dispatch_auth(cmd, "name2gid"); + mr = dispatch_auth(cmd, "name2gid", NULL); if (MODRET_ISHANDLED(mr)) res = *((gid_t *) mr->data); @@@@ -538,7 +688,7 @@@@ int pr_auth_getgroups(pool *p, const cha cmd = make_cmd(p, 3, name, group_ids ? *group_ids : NULL, group_names ? *group_names : NULL); - mr = dispatch_auth(cmd, "getgroups"); + mr = dispatch_auth(cmd, "getgroups", NULL); if (MODRET_ISHANDLED(mr) && MODRET_HASDATA(mr)) { res = *((int *) mr->data); @@@@ -832,3 +982,10 @@@@ int set_groups(pool *p, gid_t primary_gi return res; } +/* Internal use only. To be called in the session process. */ +int init_auth(void) { + auth_pool = make_sub_pool(permanent_pool); + pr_pool_tag(auth_pool, "Auth API"); + + return 0; +} @