libc: make stdio_impl.h an internal libc header
[unleashed/tickless.git] / usr / src / lib / pam_modules / list / list.c
blob05017fed5e764cff3429ff2f8ef52a967504be91
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <stdio.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <syslog.h>
32 #include <netdb.h>
33 #include <malloc.h>
34 #include <unistd.h>
35 #include <errno.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"
42 typedef enum {
43 LIST_EXTERNAL_FILE,
44 LIST_PLUS_CHECK,
45 } pam_list_mode_t;
47 static const char *
48 string_mode_type(pam_list_mode_t op_mode, boolean_t allow)
50 return (allow ? "allow" : "deny");
53 static void
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);
60 /*ARGSUSED*/
61 int
62 pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
64 FILE *fd;
65 const char *allowdeny_filename = NULL;
66 char buf[BUFSIZ];
67 char hostname[MAXHOSTNAMELEN];
68 char *username = NULL;
69 char *bufp;
70 char *rhost;
71 char *limit;
72 int userok = 0;
73 int hostok = 0;
74 int i;
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) {
86 debug = B_TRUE;
87 } else if (strncasecmp(argv[i], "user", sizeof ("user")) == 0) {
88 check_user = B_TRUE;
89 } else if (strncasecmp(argv[i], "nouser",
90 sizeof ("nouser")) == 0) {
91 check_user = B_FALSE;
92 } else if (strncasecmp(argv[i], "host", sizeof ("host")) == 0) {
93 check_host = B_TRUE;
94 } else if (strncasecmp(argv[i], "nohost",
95 sizeof ("nohost")) == 0) {
96 check_host = B_FALSE;
97 } else if (strncasecmp(argv[i], "user_host_exact",
98 sizeof ("user_host_exact")) == 0) {
99 check_exact = B_TRUE;
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;
105 allow = B_TRUE;
106 op_mode = LIST_EXTERNAL_FILE;
107 allow_deny_test++;
108 } else {
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;
118 allow = B_FALSE;
119 op_mode = LIST_EXTERNAL_FILE;
120 allow_deny_test++;
121 } else {
122 log_illegal_combination("deny",
123 string_mode_type(op_mode, allow));
124 return (PAM_SERVICE_ERR);
126 } else {
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);
145 if (debug) {
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) ||
168 (*rhost == '\0'))) {
169 if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
170 rhost = hostname;
171 } else {
172 __pam_log(LOG_AUTH | LOG_ERR,
173 "pam_list: error by gethostname - %m");
174 return (PAM_SERVICE_ERR);
178 if (debug) {
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))) {
195 continue;
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) {
204 *limit = '\0';
207 /* ignore free values */
208 if (buf[0] == '\0') {
209 continue;
212 bufp = buf;
215 * if -> netgroup line
216 * else -> user line
218 if ((bufp[0] == '@') && (bufp[1] != '\0')) {
219 bufp++;
221 if (check_exact) {
222 if (innetgr(bufp, rhost, username,
223 NULL) == 1) {
224 matched = B_TRUE;
225 break;
227 } else {
228 if (check_user) {
229 userok = innetgr(bufp, NULL, username,
230 NULL);
231 } else {
232 userok = 1;
234 if (check_host) {
235 hostok = innetgr(bufp, rhost, NULL,
236 NULL);
237 } else {
238 hostok = 1;
240 if (userok && hostok) {
241 matched = B_TRUE;
242 break;
245 } else {
246 if (check_user) {
247 if (strcmp(bufp, username) == 0) {
248 matched = B_TRUE;
249 break;
254 (void) fclose(fd);
256 if (debug) {
257 __pam_log(LOG_AUTH | LOG_DEBUG,
258 "pam_list: %s for %s", matched ? "matched" : "no match",
259 allow ? "allow" : "deny");
262 if (matched) {
263 return (allow ? PAM_SUCCESS : PAM_PERM_DENIED);
265 return (allow ? PAM_PERM_DENIED : PAM_SUCCESS);