1 |
/* $MidnightBSD$ */ |
2 |
/*- |
3 |
* Copyright (c) 2003 Networks Associates Technology, Inc. |
4 |
* Copyright (c) 2004-2011 Dag-Erling Smørgrav |
5 |
* All rights reserved. |
6 |
* |
7 |
* Portions of this software were developed for the FreeBSD Project by |
8 |
* ThinkSec AS and NAI Labs, the Security Research Division of Network |
9 |
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 |
10 |
* ("CBOSS"), as part of the DARPA CHATS research program. |
11 |
* |
12 |
* Redistribution and use in source and binary forms, with or without |
13 |
* modification, are permitted provided that the following conditions |
14 |
* are met: |
15 |
* 1. Redistributions of source code must retain the above copyright |
16 |
* notice, this list of conditions and the following disclaimer. |
17 |
* 2. Redistributions in binary form must reproduce the above copyright |
18 |
* notice, this list of conditions and the following disclaimer in the |
19 |
* documentation and/or other materials provided with the distribution. |
20 |
* 3. The name of the author may not be used to endorse or promote |
21 |
* products derived from this software without specific prior written |
22 |
* permission. |
23 |
* |
24 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
25 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
28 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
29 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
30 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
31 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
32 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
33 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
34 |
* SUCH DAMAGE. |
35 |
*/ |
36 |
|
37 |
#include <sys/cdefs.h> |
38 |
__FBSDID("$FreeBSD: stable/10/lib/libpam/modules/pam_group/pam_group.c 270401 2014-08-23 11:40:40Z des $"); |
39 |
|
40 |
#include <sys/types.h> |
41 |
|
42 |
#include <grp.h> |
43 |
#include <pwd.h> |
44 |
#include <stdarg.h> |
45 |
#include <stdio.h> |
46 |
#include <string.h> |
47 |
#include <syslog.h> |
48 |
#include <unistd.h> |
49 |
|
50 |
#define PAM_SM_AUTH |
51 |
#define PAM_SM_ACCOUNT |
52 |
|
53 |
#include <security/pam_appl.h> |
54 |
#include <security/pam_modules.h> |
55 |
#include <security/openpam.h> |
56 |
|
57 |
static int |
58 |
pam_group(pam_handle_t *pamh) |
59 |
{ |
60 |
int local, remote; |
61 |
const char *group, *user; |
62 |
const void *ruser; |
63 |
char *const *list; |
64 |
struct passwd *pwd; |
65 |
struct group *grp; |
66 |
|
67 |
/* get target account */ |
68 |
if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS || |
69 |
user == NULL || (pwd = getpwnam(user)) == NULL) |
70 |
return (PAM_AUTH_ERR); |
71 |
if (pwd->pw_uid != 0 && openpam_get_option(pamh, "root_only")) |
72 |
return (PAM_IGNORE); |
73 |
|
74 |
/* check local / remote */ |
75 |
local = openpam_get_option(pamh, "luser") ? 1 : 0; |
76 |
remote = openpam_get_option(pamh, "ruser") ? 1 : 0; |
77 |
if (local && remote) { |
78 |
openpam_log(PAM_LOG_ERROR, "(pam_group) " |
79 |
"the luser and ruser options are mutually exclusive"); |
80 |
return (PAM_SERVICE_ERR); |
81 |
} else if (local) { |
82 |
/* we already have the correct struct passwd */ |
83 |
} else { |
84 |
if (!remote) |
85 |
openpam_log(PAM_LOG_NOTICE, "(pam_group) " |
86 |
"neither luser nor ruser specified, assuming ruser"); |
87 |
/* default / historical behavior */ |
88 |
if (pam_get_item(pamh, PAM_RUSER, &ruser) != PAM_SUCCESS || |
89 |
ruser == NULL || (pwd = getpwnam(ruser)) == NULL) |
90 |
return (PAM_AUTH_ERR); |
91 |
} |
92 |
|
93 |
/* get regulating group */ |
94 |
if ((group = openpam_get_option(pamh, "group")) == NULL) |
95 |
group = "wheel"; |
96 |
if ((grp = getgrnam(group)) == NULL || grp->gr_mem == NULL) |
97 |
goto failed; |
98 |
|
99 |
/* check if user's own primary group */ |
100 |
if (pwd->pw_gid == grp->gr_gid) |
101 |
goto found; |
102 |
|
103 |
/* iterate over members */ |
104 |
for (list = grp->gr_mem; list != NULL && *list != NULL; ++list) |
105 |
if (strcmp(*list, pwd->pw_name) == 0) |
106 |
goto found; |
107 |
|
108 |
not_found: |
109 |
if (openpam_get_option(pamh, "deny")) |
110 |
return (PAM_SUCCESS); |
111 |
return (PAM_AUTH_ERR); |
112 |
found: |
113 |
if (openpam_get_option(pamh, "deny")) |
114 |
return (PAM_AUTH_ERR); |
115 |
return (PAM_SUCCESS); |
116 |
failed: |
117 |
if (openpam_get_option(pamh, "fail_safe")) |
118 |
goto found; |
119 |
else |
120 |
goto not_found; |
121 |
} |
122 |
|
123 |
PAM_EXTERN int |
124 |
pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, |
125 |
int argc __unused, const char *argv[] __unused) |
126 |
{ |
127 |
|
128 |
return (pam_group(pamh)); |
129 |
} |
130 |
|
131 |
PAM_EXTERN int |
132 |
pam_sm_setcred(pam_handle_t * pamh __unused, int flags __unused, |
133 |
int argc __unused, const char *argv[] __unused) |
134 |
{ |
135 |
|
136 |
return (PAM_SUCCESS); |
137 |
} |
138 |
|
139 |
PAM_EXTERN int |
140 |
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags __unused, |
141 |
int argc __unused, const char *argv[] __unused) |
142 |
{ |
143 |
|
144 |
return (pam_group(pamh)); |
145 |
} |
146 |
|
147 |
PAM_MODULE_ENTRY("pam_group"); |