]>
Commit | Line | Data |
---|---|---|
48b29391 | 1 | /* Copyright (C) 1997,1999,2001,2002,2003,2005 Free Software Foundation, Inc. |
e61abf83 UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. | |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
e61abf83 UD |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 13 | Lesser General Public License for more details. |
e61abf83 | 14 | |
41bdb6e2 AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
e61abf83 | 19 | |
48b29391 | 20 | #include <atomic.h> |
e61abf83 UD |
21 | #include <nss.h> |
22 | #include <errno.h> | |
23 | #include <pwd.h> | |
24 | #include <string.h> | |
5107cf1d | 25 | #include <bits/libc-lock.h> |
e61abf83 | 26 | #include <rpcsvc/nis.h> |
e61abf83 UD |
27 | |
28 | #include "nss-nisplus.h" | |
7d1de115 | 29 | #include "nisplus-parser.h" |
e61abf83 UD |
30 | |
31 | __libc_lock_define_initialized (static, lock) | |
32 | ||
a334319f | 33 | static nis_result *result; |
48b29391 UD |
34 | nis_name pwd_tablename_val attribute_hidden; |
35 | size_t pwd_tablename_len attribute_hidden; | |
0ecb606c | 36 | |
48b29391 UD |
37 | enum nss_status |
38 | _nss_pwd_create_tablename (int *errnop) | |
e61abf83 | 39 | { |
48b29391 | 40 | if (pwd_tablename_val == NULL) |
e61abf83 | 41 | { |
48b29391 UD |
42 | const char *local_dir = nis_local_directory (); |
43 | size_t local_dir_len = strlen (local_dir); | |
44 | static const char prefix[] = "passwd.org_dir."; | |
2d7da676 | 45 | |
48b29391 UD |
46 | char *p = malloc (sizeof (prefix) + local_dir_len); |
47 | if (pwd_tablename_val == NULL) | |
d71b808a UD |
48 | { |
49 | *errnop = errno; | |
50 | return NSS_STATUS_TRYAGAIN; | |
51 | } | |
48b29391 UD |
52 | |
53 | memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1); | |
54 | ||
55 | pwd_tablename_len = sizeof (prefix) - 1 + local_dir_len; | |
56 | ||
57 | atomic_write_barrier (); | |
58 | ||
8e64faef UD |
59 | if (atomic_compare_and_exchange_bool_acq (&pwd_tablename_val, p, NULL)) |
60 | { | |
61 | /* Another thread already installed the value. */ | |
62 | free (p); | |
63 | pwd_tablename_len = strlen (pwd_tablename_val); | |
64 | } | |
e61abf83 | 65 | } |
48b29391 | 66 | |
2d7da676 | 67 | return NSS_STATUS_SUCCESS; |
e61abf83 UD |
68 | } |
69 | ||
2d7da676 | 70 | |
e61abf83 | 71 | enum nss_status |
51eecc4a | 72 | _nss_nisplus_setpwent (int stayopen) |
e61abf83 | 73 | { |
a334319f | 74 | enum nss_status status = NSS_STATUS_SUCCESS; |
2d7da676 | 75 | |
e61abf83 UD |
76 | __libc_lock_lock (lock); |
77 | ||
48b29391 UD |
78 | if (result != NULL) |
79 | { | |
80 | nis_freeresult (result); | |
81 | result = NULL; | |
82 | } | |
2d7da676 | 83 | |
48b29391 UD |
84 | if (pwd_tablename_val == NULL) |
85 | { | |
86 | int err; | |
87 | status = _nss_pwd_create_tablename (&err); | |
88 | } | |
e61abf83 UD |
89 | |
90 | __libc_lock_unlock (lock); | |
91 | ||
2d7da676 | 92 | return status; |
e61abf83 UD |
93 | } |
94 | ||
95 | enum nss_status | |
96 | _nss_nisplus_endpwent (void) | |
97 | { | |
98 | __libc_lock_lock (lock); | |
99 | ||
48b29391 UD |
100 | if (result != NULL) |
101 | { | |
102 | nis_freeresult (result); | |
103 | result = NULL; | |
104 | } | |
e61abf83 UD |
105 | |
106 | __libc_lock_unlock (lock); | |
107 | ||
108 | return NSS_STATUS_SUCCESS; | |
109 | } | |
110 | ||
111 | static enum nss_status | |
d71b808a UD |
112 | internal_nisplus_getpwent_r (struct passwd *pw, char *buffer, size_t buflen, |
113 | int *errnop) | |
e61abf83 | 114 | { |
a334319f | 115 | int parse_res; |
e61abf83 UD |
116 | |
117 | /* Get the next entry until we found a correct one. */ | |
118 | do | |
119 | { | |
a334319f | 120 | nis_result *saved_res; |
8f2ece69 | 121 | |
a334319f | 122 | if (result == NULL) |
e61abf83 | 123 | { |
a334319f | 124 | saved_res = NULL; |
48b29391 | 125 | if (pwd_tablename_val == NULL) |
d71b808a | 126 | { |
48b29391 | 127 | enum nss_status status = _nss_pwd_create_tablename (errnop); |
a334319f UD |
128 | |
129 | if (status != NSS_STATUS_SUCCESS) | |
130 | return status; | |
d71b808a | 131 | } |
e61abf83 | 132 | |
48b29391 | 133 | result = nis_first_entry (pwd_tablename_val); |
a334319f UD |
134 | if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) |
135 | return niserr2nss (result->status); | |
e61abf83 UD |
136 | } |
137 | else | |
138 | { | |
a334319f | 139 | saved_res = result; |
48b29391 | 140 | result = nis_next_entry (pwd_tablename_val, &result->cookie); |
a334319f UD |
141 | if (niserr2nss (result->status) != NSS_STATUS_SUCCESS) |
142 | { | |
143 | nis_freeresult (saved_res); | |
144 | return niserr2nss (result->status); | |
145 | } | |
e61abf83 UD |
146 | } |
147 | ||
a334319f | 148 | parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, |
d71b808a | 149 | buflen, errnop); |
48b29391 | 150 | if (__builtin_expect (parse_res == -1, 0)) |
60c96635 | 151 | { |
a334319f UD |
152 | nis_freeresult (result); |
153 | result = saved_res; | |
d71b808a | 154 | *errnop = ERANGE; |
a334319f | 155 | return NSS_STATUS_TRYAGAIN; |
60c96635 | 156 | } |
48b29391 UD |
157 | |
158 | if (saved_res) | |
159 | nis_freeresult (saved_res); | |
160 | } | |
161 | while (!parse_res); | |
e61abf83 | 162 | |
a334319f | 163 | return NSS_STATUS_SUCCESS; |
e61abf83 UD |
164 | } |
165 | ||
166 | enum nss_status | |
d71b808a UD |
167 | _nss_nisplus_getpwent_r (struct passwd *result, char *buffer, size_t buflen, |
168 | int *errnop) | |
e61abf83 UD |
169 | { |
170 | int status; | |
171 | ||
172 | __libc_lock_lock (lock); | |
173 | ||
d71b808a | 174 | status = internal_nisplus_getpwent_r (result, buffer, buflen, errnop); |
e61abf83 UD |
175 | |
176 | __libc_lock_unlock (lock); | |
177 | ||
178 | return status; | |
179 | } | |
180 | ||
181 | enum nss_status | |
182 | _nss_nisplus_getpwnam_r (const char *name, struct passwd *pw, | |
d71b808a | 183 | char *buffer, size_t buflen, int *errnop) |
e61abf83 UD |
184 | { |
185 | int parse_res; | |
186 | ||
48b29391 | 187 | if (pwd_tablename_val == NULL) |
d71b808a | 188 | { |
48b29391 UD |
189 | enum nss_status status = _nss_pwd_create_tablename (errnop); |
190 | ||
d71b808a UD |
191 | if (status != NSS_STATUS_SUCCESS) |
192 | return status; | |
193 | } | |
2d7da676 | 194 | |
ac9f45cf UD |
195 | if (name == NULL) |
196 | { | |
197 | *errnop = EINVAL; | |
198 | return NSS_STATUS_UNAVAIL; | |
199 | } | |
e61abf83 | 200 | |
48b29391 UD |
201 | nis_result *result; |
202 | char buf[strlen (name) + 9 + pwd_tablename_len]; | |
203 | int olderr = errno; | |
e61abf83 | 204 | |
48b29391 | 205 | snprintf (buf, sizeof (buf), "[name=%s],%s", name, pwd_tablename_val); |
e61abf83 | 206 | |
48b29391 | 207 | result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); |
e61abf83 | 208 | |
48b29391 UD |
209 | if (result == NULL) |
210 | { | |
211 | *errnop = ENOMEM; | |
212 | return NSS_STATUS_TRYAGAIN; | |
213 | } | |
34816665 | 214 | |
48b29391 UD |
215 | if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0)) |
216 | { | |
217 | enum nss_status status = niserr2nss (result->status); | |
e61abf83 | 218 | |
48b29391 | 219 | __set_errno (olderr); |
e61abf83 UD |
220 | |
221 | nis_freeresult (result); | |
48b29391 UD |
222 | return status; |
223 | } | |
224 | ||
225 | parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop); | |
e61abf83 | 226 | |
48b29391 UD |
227 | nis_freeresult (result); |
228 | ||
229 | if (__builtin_expect (parse_res < 1, 0)) | |
230 | { | |
231 | if (parse_res == -1) | |
0ecb606c | 232 | { |
48b29391 UD |
233 | *errnop = ERANGE; |
234 | return NSS_STATUS_TRYAGAIN; | |
235 | } | |
236 | else | |
237 | { | |
238 | __set_errno (olderr); | |
239 | return NSS_STATUS_NOTFOUND; | |
d71b808a | 240 | } |
e61abf83 | 241 | } |
48b29391 UD |
242 | |
243 | return NSS_STATUS_SUCCESS; | |
e61abf83 UD |
244 | } |
245 | ||
246 | enum nss_status | |
247 | _nss_nisplus_getpwuid_r (const uid_t uid, struct passwd *pw, | |
d71b808a | 248 | char *buffer, size_t buflen, int *errnop) |
e61abf83 | 249 | { |
48b29391 | 250 | if (pwd_tablename_val == NULL) |
d71b808a | 251 | { |
48b29391 UD |
252 | enum nss_status status = _nss_pwd_create_tablename (errnop); |
253 | ||
d71b808a UD |
254 | if (status != NSS_STATUS_SUCCESS) |
255 | return status; | |
256 | } | |
257 | ||
48b29391 UD |
258 | int parse_res; |
259 | nis_result *result; | |
260 | char buf[8 + 3 * sizeof (unsigned long int) + pwd_tablename_len]; | |
261 | int olderr = errno; | |
e61abf83 | 262 | |
48b29391 UD |
263 | snprintf (buf, sizeof (buf), "[uid=%lu],%s", |
264 | (unsigned long int) uid, pwd_tablename_val); | |
e61abf83 | 265 | |
48b29391 | 266 | result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); |
e61abf83 | 267 | |
48b29391 UD |
268 | if (result == NULL) |
269 | { | |
270 | *errnop = ENOMEM; | |
271 | return NSS_STATUS_TRYAGAIN; | |
272 | } | |
e61abf83 | 273 | |
48b29391 UD |
274 | if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0)) |
275 | { | |
276 | enum nss_status status = niserr2nss (result->status); | |
34816665 | 277 | |
48b29391 UD |
278 | __set_errno (olderr); |
279 | ||
280 | nis_freeresult (result); | |
281 | return status; | |
282 | } | |
283 | ||
284 | parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop); | |
285 | ||
286 | nis_freeresult (result); | |
287 | ||
288 | if (__builtin_expect (parse_res < 1, 0)) | |
289 | { | |
290 | if (parse_res == -1) | |
291 | { | |
292 | *errnop = ERANGE; | |
293 | return NSS_STATUS_TRYAGAIN; | |
294 | } | |
295 | else | |
296 | { | |
297 | __set_errno (olderr); | |
298 | return NSS_STATUS_NOTFOUND; | |
299 | } | |
300 | } | |
301 | ||
302 | return NSS_STATUS_SUCCESS; | |
e61abf83 | 303 | } |