4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
29 #include <sys/types.h>
36 #include <security/pam_appl.h>
37 #include <security/pam_modules.h>
38 #include <security/pam_impl.h>
40 #define ILLEGAL_COMBINATION "pam_list: illegal combination of options"
48 string_mode_type(pam_list_mode_t op_mode
, boolean_t allow
)
50 return (allow
? "allow" : "deny");
54 log_illegal_combination(const char *s1
, const char *s2
)
56 __pam_log(LOG_AUTH
| LOG_ERR
, ILLEGAL_COMBINATION
57 " %s and %s", s1
, s2
);
62 pam_sm_acct_mgmt(pam_handle_t
*pamh
, int flags
, int argc
, const char **argv
)
65 const char *allowdeny_filename
= NULL
;
67 char hostname
[MAXHOSTNAMELEN
];
68 char *username
= NULL
;
75 int allow_deny_test
= 0;
76 boolean_t debug
= B_FALSE
;
77 boolean_t allow
= B_FALSE
;
78 boolean_t matched
= B_FALSE
;
79 boolean_t check_user
= B_TRUE
;
80 boolean_t check_host
= B_FALSE
;
81 boolean_t check_exact
= B_FALSE
;
82 pam_list_mode_t op_mode
= LIST_PLUS_CHECK
;
84 for (i
= 0; i
< argc
; ++i
) {
85 if (strncasecmp(argv
[i
], "debug", sizeof ("debug")) == 0) {
87 } else if (strncasecmp(argv
[i
], "user", sizeof ("user")) == 0) {
89 } else if (strncasecmp(argv
[i
], "nouser",
90 sizeof ("nouser")) == 0) {
92 } else if (strncasecmp(argv
[i
], "host", sizeof ("host")) == 0) {
94 } else if (strncasecmp(argv
[i
], "nohost",
95 sizeof ("nohost")) == 0) {
97 } else if (strncasecmp(argv
[i
], "user_host_exact",
98 sizeof ("user_host_exact")) == 0) {
100 } else if (strncasecmp(argv
[i
], "allow=",
101 sizeof ("allow=") - 1) == 0) {
102 if (op_mode
== LIST_PLUS_CHECK
) {
103 allowdeny_filename
= argv
[i
] +
104 sizeof ("allow=") - 1;
106 op_mode
= LIST_EXTERNAL_FILE
;
109 log_illegal_combination("allow",
110 string_mode_type(op_mode
, allow
));
111 return (PAM_SERVICE_ERR
);
113 } else if (strncasecmp(argv
[i
], "deny=",
114 sizeof ("deny=") - 1) == 0) {
115 if (op_mode
== LIST_PLUS_CHECK
) {
116 allowdeny_filename
= argv
[i
] +
117 sizeof ("deny=") - 1;
119 op_mode
= LIST_EXTERNAL_FILE
;
122 log_illegal_combination("deny",
123 string_mode_type(op_mode
, allow
));
124 return (PAM_SERVICE_ERR
);
127 __pam_log(LOG_AUTH
| LOG_ERR
,
128 "pam_list: illegal option %s", argv
[i
]);
129 return (PAM_SERVICE_ERR
);
133 if (((check_user
|| check_host
|| check_exact
) == B_FALSE
) ||
134 (allow_deny_test
> 1)) {
135 __pam_log(LOG_AUTH
| LOG_ERR
, ILLEGAL_COMBINATION
);
136 return (PAM_SERVICE_ERR
);
139 if (!allowdeny_filename
|| strlen(allowdeny_filename
) == 0) {
140 __pam_log(LOG_AUTH
| LOG_ERR
,
141 "pam_list: file name not specified");
142 return (PAM_SERVICE_ERR
);
146 __pam_log(LOG_AUTH
| LOG_DEBUG
,
147 "pam_list: check_user = %d, check_host = %d,"
148 "check_exact = %d\n",
149 check_user
, check_host
, check_exact
);
151 __pam_log(LOG_AUTH
| LOG_DEBUG
,
152 "pam_list: auth_file: %s, %s\n", allowdeny_filename
,
153 (allow
? "allow file" : "deny file"));
156 (void) pam_get_item(pamh
, PAM_USER
, (void**)&username
);
158 if ((check_user
|| check_exact
) && ((username
== NULL
) ||
159 (*username
== '\0'))) {
160 __pam_log(LOG_AUTH
| LOG_ERR
,
161 "pam_list: username not supplied, critical error");
162 return (PAM_USER_UNKNOWN
);
165 (void) pam_get_item(pamh
, PAM_RHOST
, (void**)&rhost
);
167 if ((check_host
|| check_exact
) && ((rhost
== NULL
) ||
169 if (gethostname(hostname
, MAXHOSTNAMELEN
) == 0) {
172 __pam_log(LOG_AUTH
| LOG_ERR
,
173 "pam_list: error by gethostname - %m");
174 return (PAM_SERVICE_ERR
);
179 __pam_log(LOG_AUTH
| LOG_DEBUG
,
180 "pam_list: pam_sm_acct_mgmt for (%s,%s,)",
181 (rhost
!= NULL
) ? rhost
: "", username
);
184 if ((fd
= fopen(allowdeny_filename
, "rF")) == NULL
) {
185 __pam_log(LOG_AUTH
| LOG_ERR
, "pam_list: fopen of %s: %s",
186 allowdeny_filename
, strerror(errno
));
187 return (PAM_SERVICE_ERR
);
190 while (fgets(buf
, BUFSIZ
, fd
) != NULL
) {
191 /* lines longer than BUFSIZ-1 */
192 if ((strlen(buf
) == (BUFSIZ
- 1)) &&
193 (buf
[BUFSIZ
- 2] != '\n')) {
194 while ((fgetc(fd
) != '\n') && (!feof(fd
))) {
197 __pam_log(LOG_AUTH
| LOG_DEBUG
,
198 "pam_list: long line in file,"
199 "more than %d chars, the rest ignored", BUFSIZ
- 1);
202 /* remove unneeded colons if necessary */
203 if ((limit
= strpbrk(buf
, ":\n")) != NULL
) {
207 /* ignore free values */
208 if (buf
[0] == '\0') {
215 * if -> netgroup line
218 if ((bufp
[0] == '@') && (bufp
[1] != '\0')) {
222 if (innetgr(bufp
, rhost
, username
,
229 userok
= innetgr(bufp
, NULL
, username
,
235 hostok
= innetgr(bufp
, rhost
, NULL
,
240 if (userok
&& hostok
) {
247 if (strcmp(bufp
, username
) == 0) {
257 __pam_log(LOG_AUTH
| LOG_DEBUG
,
258 "pam_list: %s for %s", matched
? "matched" : "no match",
259 allow
? "allow" : "deny");
263 return (allow
? PAM_SUCCESS
: PAM_PERM_DENIED
);
265 return (allow
? PAM_PERM_DENIED
: PAM_SUCCESS
);