Index: lukemftpd/src/ftpd.c =================================================================== RCS file: /home/ncvs/src/contrib/lukemftpd/src/ftpd.c,v retrieving revision 1.3 diff -u -r1.3 ftpd.c --- lukemftpd/src/ftpd.c 2 Feb 2003 21:03:28 -0000 1.3 +++ lukemftpd/src/ftpd.c 30 Nov 2003 20:59:48 -0000 @@ -169,6 +169,9 @@ #include #include #endif +#ifdef LOGIN_CAP +#include +#endif #define GLOBAL #include "extern.h" @@ -628,6 +631,9 @@ void user(const char *name) { +#ifdef LOGIN_CAP + login_cap_t *lc = NULL; +#endif char *class; class = NULL; @@ -691,8 +697,16 @@ /* check user in /etc/ftpusers, and setup class */ permitted = checkuser(_PATH_FTPUSERS, curname, 1, 0, &class); +#ifdef LOGIN_CAP /* allow login.conf configuration as well */ + if ((lc = login_getpwclass(pw)) != NULL) + goto cleanup_user; +#endif /* check user in /etc/ftpchroot */ - if (checkuser(_PATH_FTPCHROOT, curname, 0, 0, NULL)) { + if (checkuser(_PATH_FTPCHROOT, curname, 0, 0, NULL) +#ifdef LOGIN_CAP /* allow login.conf configuration as well */ + || login_getcapbool(lc, "ftp-chroot", 0) +#endif + ) { if (curclass.type == CLASS_GUEST) { syslog(LOG_NOTICE, "Can't change guest user to chroot class; remove entry in %s", @@ -776,6 +790,9 @@ } cleanup_user: +#ifdef LOGIN_CAP + login_close(lc); +#endif /* * Delay before reading passwd after first failed * attempt to slow down passwd-guessing programs. @@ -1029,6 +1046,10 @@ gidcount = 0; curclass.type = CLASS_REAL; (void) seteuid((uid_t)0); +#ifdef LOGIN_CAP + setusercontext(NULL, getpwuid(0), (uid_t)0, + LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK|LOGIN_SETMAC); +#endif #ifdef USE_PAM if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS) syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e)); @@ -1043,6 +1064,9 @@ void pass(const char *passwd) { +#ifdef LOGIN_CAP + login_cap_t *lc = NULL; +#endif #ifdef USE_PAM int e; #endif @@ -1154,6 +1178,33 @@ reply(550, "Can't set gid."); goto bad; } + +#ifdef LOGIN_CAP + if ((lc = login_getpwclass(pw)) != NULL) { + char remote_ip[MAXHOSTNAMELEN]; + + getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len, + remote_ip, sizeof(remote_ip) - 1, NULL, 0, NI_NUMERICHOST); + remote_ip[sizeof(remote_ip) - 1] = 0; + if (!auth_hostok(lc, remotehost, remote_ip)) { + syslog(LOG_INFO|LOG_AUTH, + "FTP LOGIN FAILED (HOST) as %s: permission denied.", + pw->pw_name); + reply(530, "Permission denied.\n"); + pw = NULL; + return; + } + if (!auth_timeok(lc, time(NULL))) { + reply(530, "Login not available right now.\n"); + pw = NULL; + return; + } + } + setusercontext(lc, pw, (uid_t)0, + LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY|LOGIN_SETRESOURCES + |LOGIN_SETUMASK|LOGIN_SETMAC); +#endif /*LOGIN_CAP*/ + (void) initgroups(pw->pw_name, pw->pw_gid); /* cache groups for cmds.c::matchgroup() */ gidcount = getgroups(sizeof(gidlist), gidlist); @@ -1346,11 +1397,17 @@ remotehost, pw->pw_name, curclass.classname, CURCLASSTYPE); } +#ifdef LOGIN_CAP + login_close(lc); +#endif (void) umask(curclass.umask); return; bad: /* Forget all about it... */ +#ifdef LOGIN_CAP + login_close(lc); +#endif end_login(); }