196191Sdes/*- 296191Sdes * Copyright (c) 2001 Networks Associates Technology, Inc. 396191Sdes * All rights reserved. 496191Sdes * 596191Sdes * This software was developed for the FreeBSD Project by ThinkSec AS and 696191Sdes * NAI Labs, the Security Research Division of Network Associates, Inc. 796191Sdes * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 896191Sdes * DARPA CHATS research program. 996191Sdes * 1096191Sdes * Redistribution and use in source and binary forms, with or without 1196191Sdes * modification, are permitted provided that the following conditions 1296191Sdes * are met: 1396191Sdes * 1. Redistributions of source code must retain the above copyright 1496191Sdes * notice, this list of conditions and the following disclaimer. 1596191Sdes * 2. Redistributions in binary form must reproduce the above copyright 1696191Sdes * notice, this list of conditions and the following disclaimer in the 1796191Sdes * documentation and/or other materials provided with the distribution. 1896191Sdes * 3. The name of the author may not be used to endorse or promote 1996191Sdes * products derived from this software without specific prior written 2096191Sdes * permission. 2196191Sdes * 2296191Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2396191Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2496191Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2596191Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2696191Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2796191Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2896191Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2996191Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3096191Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3196191Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3296191Sdes * SUCH DAMAGE. 3396191Sdes */ 3496191Sdes 3596191Sdes#include <sys/cdefs.h> 3696191Sdes__FBSDID("$FreeBSD$"); 3796191Sdes 3896191Sdes#include <ctype.h> 3996191Sdes#include <grp.h> 4096191Sdes#include <paths.h> 4196191Sdes#include <pwd.h> 4296191Sdes#include <stdio.h> 4396191Sdes#include <stdlib.h> 4496191Sdes#include <string.h> 4596191Sdes 4696191Sdes#define PAM_SM_ACCOUNT 4796191Sdes 4896191Sdes#include <security/pam_appl.h> 4996191Sdes#include <security/pam_modules.h> 5096191Sdes#include <security/pam_mod_misc.h> 5196191Sdes#include <security/openpam.h> 5296191Sdes 5396191SdesPAM_EXTERN int 5496191Sdespam_sm_acct_mgmt(pam_handle_t *pamh, int flags __unused, 5596191Sdes int argc __unused, const char *argv[] __unused) 5696191Sdes{ 5796191Sdes struct passwd *pwd; 5896191Sdes struct group *grp; 5996191Sdes const char *user; 6096191Sdes int pam_err, found, allow; 6196191Sdes char *line, *name, **mem; 6296191Sdes size_t len, ulen; 6396191Sdes FILE *f; 6496191Sdes 6596191Sdes pam_err = pam_get_user(pamh, &user, NULL); 6696191Sdes if (pam_err != PAM_SUCCESS) 6796191Sdes return (pam_err); 6896191Sdes if (user == NULL || (pwd = getpwnam(user)) == NULL) 6996191Sdes return (PAM_SERVICE_ERR); 7096191Sdes 7196191Sdes found = 0; 7296191Sdes ulen = strlen(user); 7396191Sdes if ((f = fopen(_PATH_FTPUSERS, "r")) == NULL) { 7496191Sdes PAM_LOG("%s: %m", _PATH_FTPUSERS); 7596191Sdes goto done; 7696191Sdes } 7796191Sdes while (!found && (line = fgetln(f, &len)) != NULL) { 7896191Sdes if (*line == '#') 7996191Sdes continue; 8096191Sdes while (len > 0 && isspace(line[len - 1])) 8196191Sdes --len; 8296191Sdes if (len == 0) 8396191Sdes continue; 8496191Sdes /* simple case first */ 8596191Sdes if (*line != '@') { 8696191Sdes if (len == ulen && strncmp(user, line, len) == 0) 8796191Sdes found = 1; 8896191Sdes continue; 8996191Sdes } 9096191Sdes /* member of specified group? */ 9196191Sdes asprintf(&name, "%.*s", (int)len - 1, line + 1); 9296191Sdes if (name == NULL) { 9396191Sdes fclose(f); 9496191Sdes return (PAM_BUF_ERR); 9596191Sdes } 9696191Sdes grp = getgrnam(name); 9796191Sdes free(name); 9896191Sdes if (grp == NULL) 9996191Sdes continue; 10096191Sdes for (mem = grp->gr_mem; mem && *mem && !found; ++mem) 10196191Sdes if (strcmp(user, *mem) == 0) 10296191Sdes found = 1; 10396191Sdes } 10496191Sdes done: 10596191Sdes allow = (openpam_get_option(pamh, "disallow") == NULL); 10696191Sdes if (found) 10796191Sdes pam_err = allow ? PAM_SUCCESS : PAM_AUTH_ERR; 10896191Sdes else 10996191Sdes pam_err = allow ? PAM_AUTH_ERR : PAM_SUCCESS; 11096191Sdes if (f != NULL) 11196191Sdes fclose(f); 11296191Sdes return (pam_err); 11396191Sdes} 11496191Sdes 11596191SdesPAM_MODULE_ENTRY("pam_ftpusers"); 116