For about two years vsftpd has has partial support for PAM to log sessions. I submitted a patch to the author back then, which got not action. Here we are again but with a more serious problem. With PAM session support vsftpd goes to 100% utilization and will not exit (from inetd) when the session is closed. The fix listed below solves the cpu and exiting problem, and provides PAM session support. Fix: The patch material below solves this problem and provides full PAM session support (so that "last" work, etc). sysdeputil.c.orig is in the most recent vsftpd in the ports collection. # diff -u sysdeputil.c.orig sysdeputil.c > sysdeputil.diff # cat sysdeputil.diff #include "sysdeputil.h" #include "str.h" @@ -34,6 +38,9 @@ /* For FreeBSD */ #include <sys/param.h> #include <sys/uio.h> +#include <stdio.h> /* JRD */ +#include <syslog.h> /* JRD */ +#include <utmp.h> /* JRD */ /* Configuration.. here are the possibilities */ #undef VSF_SYSDEP_HAVE_CAPABILITIES @@ -302,15 +309,21 @@ s_pamh = 0; return 0; } -#ifdef PAM_RHOST - retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); + +/*was JRD #ifdef PAM_RHOST */ + { + char buf[UT_HOSTSIZE]; /* restrict to normal system buf size */ + snprintf(buf, sizeof(buf), "%s", str_getbuf(p_remote_host)); + retval = pam_set_item(s_pamh, PAM_RHOST, buf); + } +/*was JRD retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); */ if (retval != PAM_SUCCESS) { (void) pam_end(s_pamh, 0); s_pamh = 0; return 0; } -#endif +/*was JRD #endif */ retval = pam_authenticate(s_pamh, 0); if (retval != PAM_SUCCESS) { @@ -341,6 +354,14 @@ } /* Must do this BEFORE opening a session for pam_limits to count us */ vsf_insert_uwtmp(p_user_str, p_remote_host); +/* JRD Tell PAM our "PAM_TTY" */ + { + char ttyline[UT_LINESIZE]; + (void)snprintf(ttyline, sizeof(ttyline), "ftp%d", getpid()); + pam_set_item(s_pamh, PAM_TTY, ttyline); + } +/* JRD end */ + retval = pam_open_session(s_pamh, 0); if (retval != PAM_SUCCESS) { #--EGAvp1OwVk7REnhyhobzc3GOBDOPy9lwDY3XZx5l3XRudvwk Content-Type: text/plain; name="file.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="file.diff" --- sysdeputil.c.orig Mon May 23 16:34:23 2005 +++ sysdeputil.c Mon Jan 30 20:17:40 2006 @@ -6,6 +6,10 @@ * * Highly system dependent utilities - e.g. authentication, capabilities. */ +/* Modifications by Joe R. Doupnik, jrd@cc.usu.edu, marked as JRD, for +PAM support on recent FreeBSD systems. Does wtmp entries for last_log. +Most recently tested on FBSD v6.0 +*/ How-To-Repeat: Add these three items to vsftpd.conf, start an ftp session, watch with top, exit the session, see 100% cpu assigned to vsftpd which does not exit. session_support=YES syslog_enable=YES pam_service_name=ftp
Responsible Changed From-To: freebsd-ports-bugs->dinoex Over to maintainer
State Changed From-To: open->feedback Sorry your patch does not apply to the the version in the port. Please check and update your patch.
>Synopsis: VSFTPD goes to 100% cpu util when exiting, if PAM support enabled > >State-Changed-From-To: open->feedback >State-Changed-By: dinoex >State-Changed-When: Tue Jan 31 17:15:13 CET 2006 >State-Changed-Why: >Sorry your patch does not apply to the the version in the port. >Please check and update your patch. > > >http://www.freebsd.org/cgi/query-pr.cgi?pr=92579 ----------- Well, actually it does apply at my end (recently cvsup'd): Within /usr/ports/ftp/vsftpd on my machine I see -- # cd work # ls .PLIST.flattened .PLIST.mktmp .PLIST.objdump .PLIST.setuid .PLIST.writable .build_done.vsftpd-ssl-2.0.4._usr_local .configure_done.vsftpd-ssl-2.0.4._usr_local .extract_done.vsftpd-ssl-2.0.4._usr_local .install_done.vsftpd-ssl-2.0.4._usr_local .patch_done.vsftpd-ssl-2.0.4._usr_local vsftpd-2.0.4 vsftpd.sh # cat ../distinfo MD5 (vsftpd-2.0.4.tar.gz) = c0bf8c7b8e15ab15827172786fc56115 SHA256 (vsftpd-2.0.4.tar.gz) = 3bd3d8750460cf724b4589589eb37ab0d398f0c4d3d749246 8c66d3617052af6 SIZE (vsftpd-2.0.4.tar.gz) = 154857 # And here is the content of file distinfo from your CVS system: MD5 (vsftpd-2.0.4.tar.gz) = c0bf8c7b8e15ab15827172786fc56115 SHA256 (vsftpd-2.0.4.tar.gz) = 3bd3d8750460cf724b4589589eb37ab0d398f0c4d3d7492468c66d3617052af6 SIZE (vsftpd-2.0.4.tar.gz) = 154857 The same stuff, right? The source file involved is sysdeputils.c, and item which has changed little over at least two years. Let us progress regardless, as they say. The submitted patch has context into which my changes may be identified and sensibly reinserted in most versions of vsftpd (given the slow evolution of the source file). Contextural reference #1 is look for PAM_RHOST in the file. In passing we can notice that the PAM material in FBSD 6 does have PAM_RHOST within <security/pam_constants.h> but for obscure reasons it is not exposed in the work at hand. Thus I work around the #ifdef PAM_RHOST protection. Contextural reference #2 is look for "Must do this BEFORE". Here we may notice I submit phrase "ftp<PID>" to PAM so that the last log/wtmp can distinguish one session from another. The rest, #includes, is at the top of the file together with other FBSD items under /* For FreeBSD */. I don't wish to seen ponderous, but I do wish to have the problem resolved. Putting the good word to the vsftpd folks would be an excellent idea as well. Joe D.
State Changed From-To: feedback->suspended Sorry but your patch does not apply. Your mailclient may have altered the patch. ===> Vulnerability check disabled, database not found ===> Found saved configuration for vsftpd-2.0.4 ===> Extracting for vsftpd--2.0.4 ===> Vulnerability check disabled, database not found ===> Found saved configuration for vsftpd-2.0.4 => MD5 Checksum OK for vsftpd-2.0.4.tar.gz. => SHA256 Checksum OK for vsftpd-2.0.4.tar.gz. ===> Patching for vsftpd-2.0.4 ===> Applying FreeBSD patches for vsftpd-2.0.4 1 out of 3 hunks failed--saving rejects to sysdeputil.c.rej File to patch: No file found--skip this patch? [n] y 1 out of 1 hunks ignored--saving rejects to y.rej => Patch patch-sysdeputil.c failed to apply cleanly. *** Error code 1 Stop in /usr/ports/current/vsftpd. *** Error code 1 Stop in /usr/ports/current/vsftpd. *** Error code 1 Stop in /usr/ports/current/vsftpd. MD5 (files/patch-utility) = 947493b45bf46a26a148b1e08435c981 $ head -2 files/patch-utility --- utility.c.orig Fri Jul 2 18:26:30 2004 +++ utility.c Mon Oct 10 01:19:02 2005 vsftpd/work/vsftpd-2.0.4$ ls -l sysdeputil.* -rw-r--r-- 1 dm wheel 28932 25 Feb 13:52 sysdeputil.c -rw-r--r-- 1 dm wheel 28663 24 Mai 2005 sysdeputil.c.orig -rw-r--r-- 1 dm wheel 951 25 Feb 13:52 sysdeputil.c.rej -rw-r--r-- 1 dm wheel 1976 25 Jan 2003 sysdeputil.h cat sysdeputil.c.rej *************** *** 302,316 **** s_pamh = 0; return 0; } - #ifdef PAM_RHOST - retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); */ if (retval != PAM_SUCCESS) { (void) pam_end(s_pamh, 0); s_pamh = 0; return 0; } - #endif retval = pam_authenticate(s_pamh, 0); if (retval != PAM_SUCCESS) --- 309,329 ---- s_pamh = 0; return 0; } + + /*was JRD #ifdef PAM_RHOST */ + { + char buf[UT_HOSTSIZE]; /* restrict to normal system buf size */ + snprintf(buf, sizeof(buf), "%s", str_getbuf(p_remote_host)); + retval = pam_set_item(s_pamh, PAM_RHOST, buf); + } + /*was JRD retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); */ if (retval != PAM_SUCCESS) { (void) pam_end(s_pamh, 0); s_pamh = 0; return 0; } + /*was JRD #endif */ retval = pam_authenticate(s_pamh, 0); if (retval != PAM_SUCCESS)
State Changed From-To: suspended->patched Thanks, this patch now does apply. diff between the patches: (for your information) < --- sysdeputil.c.orig Mon May 23 16:34:23 2005 < +++ sysdeputil.c Mon Jan 30 20:17:40 2006 --- > --- sysdeputil.c.orig Mon May 23 16:34:23 2005 > +++ sysdeputil.c Mon Jan 30 20:17:40 2006 75c8 < +PAM support on recent FreeBSD systems. Does wtmp entries for last_log. --- > +PAM support on recent FreeBSD systems. Does wtmp entries for last_log. 78c11 < --- > 88c21 < --- > 100c33 < + char buf[UT_HOSTSIZE]; /* restrict to normal system buf size */ --- > + char buf[UT_HOSTSIZE]; /* restrict to normal system buf size */ 104,105c37 < +/*was JRD retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); < */ --- > +/*was JRD retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); */
State Changed From-To: patched->closed committed, thanks.