1110453Sdes/*- 2110453Sdes * Copyright (c) 2003 Networks Associates Technology, Inc. 3219563Sdes * Copyright (c) 2004-2011 Dag-Erling Sm��rgrav 4110453Sdes * All rights reserved. 5110453Sdes * 6110453Sdes * Portions of this software were developed for the FreeBSD Project by 7110453Sdes * ThinkSec AS and NAI Labs, the Security Research Division of Network 8110453Sdes * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 9110453Sdes * ("CBOSS"), as part of the DARPA CHATS research program. 10110453Sdes * 11110453Sdes * Redistribution and use in source and binary forms, with or without 12110453Sdes * modification, are permitted provided that the following conditions 13110453Sdes * are met: 14110453Sdes * 1. Redistributions of source code must retain the above copyright 15110453Sdes * notice, this list of conditions and the following disclaimer. 16110453Sdes * 2. Redistributions in binary form must reproduce the above copyright 17110453Sdes * notice, this list of conditions and the following disclaimer in the 18110453Sdes * documentation and/or other materials provided with the distribution. 19110453Sdes * 3. The name of the author may not be used to endorse or promote 20110453Sdes * products derived from this software without specific prior written 21110453Sdes * permission. 22110453Sdes * 23110453Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24110453Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25110453Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26110453Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27110453Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28110453Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29110453Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30110453Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31110453Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32110453Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33110453Sdes * SUCH DAMAGE. 34110453Sdes */ 35110453Sdes 36110453Sdes#include <sys/cdefs.h> 37110453Sdes__FBSDID("$FreeBSD: releng/11.0/lib/libpam/modules/pam_group/pam_group.c 268890 2014-07-19 21:04:21Z des $"); 38110453Sdes 39110453Sdes#include <sys/types.h> 40110453Sdes 41110453Sdes#include <grp.h> 42110453Sdes#include <pwd.h> 43110453Sdes#include <stdarg.h> 44110453Sdes#include <stdio.h> 45110453Sdes#include <string.h> 46110453Sdes#include <syslog.h> 47110453Sdes#include <unistd.h> 48110453Sdes 49110453Sdes#define PAM_SM_AUTH 50268890Sdes#define PAM_SM_ACCOUNT 51110453Sdes 52110453Sdes#include <security/pam_appl.h> 53110453Sdes#include <security/pam_modules.h> 54110453Sdes#include <security/openpam.h> 55110453Sdes 56268890Sdesstatic int 57268890Sdespam_group(pam_handle_t *pamh) 58110453Sdes{ 59219563Sdes int local, remote; 60123448Sdes const char *group, *user; 61123448Sdes const void *ruser; 62110453Sdes char *const *list; 63110453Sdes struct passwd *pwd; 64110453Sdes struct group *grp; 65110453Sdes 66110453Sdes /* get target account */ 67110653Sdes if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || 68110653Sdes user == NULL || (pwd = getpwnam(user)) == NULL) 69110453Sdes return (PAM_AUTH_ERR); 70110453Sdes if (pwd->pw_uid != 0 && openpam_get_option(pamh, "root_only")) 71110453Sdes return (PAM_IGNORE); 72110453Sdes 73219563Sdes /* check local / remote */ 74219563Sdes local = openpam_get_option(pamh, "luser") ? 1 : 0; 75219563Sdes remote = openpam_get_option(pamh, "ruser") ? 1 : 0; 76219563Sdes if (local && remote) { 77219564Sdes openpam_log(PAM_LOG_ERROR, "(pam_group) " 78219563Sdes "the luser and ruser options are mutually exclusive"); 79219563Sdes return (PAM_SERVICE_ERR); 80219563Sdes } else if (local) { 81219563Sdes /* we already have the correct struct passwd */ 82219563Sdes } else { 83219563Sdes if (!remote) 84219564Sdes openpam_log(PAM_LOG_NOTICE, "(pam_group) " 85219563Sdes "neither luser nor ruser specified, assuming ruser"); 86219563Sdes /* default / historical behavior */ 87219563Sdes if (pam_get_item(pamh, PAM_RUSER, &ruser) != PAM_SUCCESS || 88219563Sdes ruser == NULL || (pwd = getpwnam(ruser)) == NULL) 89219563Sdes return (PAM_AUTH_ERR); 90219563Sdes } 91110453Sdes 92110453Sdes /* get regulating group */ 93110453Sdes if ((group = openpam_get_option(pamh, "group")) == NULL) 94110453Sdes group = "wheel"; 95110453Sdes if ((grp = getgrnam(group)) == NULL || grp->gr_mem == NULL) 96110453Sdes goto failed; 97110453Sdes 98268888Sdes /* check if user's own primary group */ 99110453Sdes if (pwd->pw_gid == grp->gr_gid) 100110453Sdes goto found; 101268888Sdes 102268888Sdes /* iterate over members */ 103268888Sdes for (list = grp->gr_mem; list != NULL && *list != NULL; ++list) 104110453Sdes if (strcmp(*list, pwd->pw_name) == 0) 105110453Sdes goto found; 106110453Sdes 107110453Sdes not_found: 108110453Sdes if (openpam_get_option(pamh, "deny")) 109110453Sdes return (PAM_SUCCESS); 110110453Sdes return (PAM_AUTH_ERR); 111110453Sdes found: 112110453Sdes if (openpam_get_option(pamh, "deny")) 113110453Sdes return (PAM_AUTH_ERR); 114110453Sdes return (PAM_SUCCESS); 115110453Sdes failed: 116110453Sdes if (openpam_get_option(pamh, "fail_safe")) 117110453Sdes goto found; 118110453Sdes else 119110453Sdes goto not_found; 120110453Sdes} 121110453Sdes 122110453SdesPAM_EXTERN int 123268890Sdespam_sm_authenticate(pam_handle_t *pamh, int flags __unused, 124268890Sdes int argc __unused, const char *argv[] __unused) 125268890Sdes{ 126268890Sdes 127268890Sdes return (pam_group(pamh)); 128268890Sdes} 129268890Sdes 130268890SdesPAM_EXTERN int 131110453Sdespam_sm_setcred(pam_handle_t * pamh __unused, int flags __unused, 132110453Sdes int argc __unused, const char *argv[] __unused) 133110453Sdes{ 134110453Sdes 135110453Sdes return (PAM_SUCCESS); 136110453Sdes} 137110453Sdes 138268890SdesPAM_EXTERN int 139268890Sdespam_sm_acct_mgmt(pam_handle_t *pamh, int flags __unused, 140268890Sdes int argc __unused, const char *argv[] __unused) 141268890Sdes{ 142268890Sdes 143268890Sdes return (pam_group(pamh)); 144268890Sdes} 145268890Sdes 146110453SdesPAM_MODULE_ENTRY("pam_group"); 147