]> git.ipfire.org Git - thirdparty/glibc.git/blame - nis/nss_nisplus/nisplus-grp.c
* version.h (VERSION): Bump to 2.5.90 for new development tree.
[thirdparty/glibc.git] / nis / nss_nisplus / nisplus-grp.c
CommitLineData
c8e82b4a
UD
1/* Copyright (C) 1997, 2001, 2002, 2003, 2005, 2006
2 Free Software Foundation, Inc.
e61abf83
UD
3 This file is part of the GNU C Library.
4 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
5
6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
e61abf83
UD
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 14 Lesser General Public License for more details.
e61abf83 15
41bdb6e2
AJ
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
e61abf83 20
48b29391 21#include <atomic.h>
e61abf83
UD
22#include <nss.h>
23#include <grp.h>
24#include <ctype.h>
25#include <errno.h>
26#include <string.h>
5107cf1d 27#include <bits/libc-lock.h>
e61abf83 28#include <rpcsvc/nis.h>
e61abf83
UD
29
30#include "nss-nisplus.h"
2d7da676 31#include "nisplus-parser.h"
a17fa610
UD
32#include <libnsl.h>
33#include <nis_intern.h>
34#include <nis_xdr.h>
e61abf83 35
48b29391 36
e61abf83
UD
37__libc_lock_define_initialized (static, lock);
38
a17fa610
UD
39/* Connection information. */
40static ib_request *ibreq;
41static directory_obj *dir;
42static dir_binding bptr;
43static char *tablepath;
44static char *tableptr;
45/* Cursor. */
46static netobj cursor;
47
48
a334319f 49static nis_name tablename_val;
48b29391 50static size_t tablename_len;
0ecb606c 51
a334319f
UD
52static enum nss_status
53_nss_create_tablename (int *errnop)
e61abf83 54{
a334319f 55 if (tablename_val == NULL)
e61abf83 56 {
48b29391
UD
57 const char *local_dir = nis_local_directory ();
58 size_t local_dir_len = strlen (local_dir);
59 static const char prefix[] = "group.org_dir.";
2d7da676 60
48b29391 61 char *p = malloc (sizeof (prefix) + local_dir_len);
c8e82b4a 62 if (p == NULL)
d71b808a
UD
63 {
64 *errnop = errno;
65 return NSS_STATUS_TRYAGAIN;
66 }
48b29391
UD
67
68 memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
69
70 tablename_len = sizeof (prefix) - 1 + local_dir_len;
71
72 atomic_write_barrier ();
73
74 tablename_val = p;
e61abf83 75 }
48b29391 76
2d7da676
UD
77 return NSS_STATUS_SUCCESS;
78}
5107cf1d 79
a17fa610
UD
80
81static void
82internal_endgrent (void)
0ecb606c 83{
a17fa610
UD
84 __nisbind_destroy (&bptr);
85 memset (&bptr, '\0', sizeof (bptr));
0ecb606c 86
a17fa610
UD
87 nis_free_directory (dir);
88 dir = NULL;
89
90 nis_free_request (ibreq);
91 ibreq = NULL;
92
93 xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
94 memset (&cursor, '\0', sizeof (cursor));
95
96 free (tablepath);
97 tableptr = tablepath = NULL;
98}
99
100
101static enum nss_status
102internal_setgrent (int *errnop)
103{
104 enum nss_status status = NSS_STATUS_SUCCESS;
0ecb606c 105
a334319f 106 if (tablename_val == NULL)
a17fa610 107 status = _nss_create_tablename (errnop);
0ecb606c 108
a17fa610 109 if (status == NSS_STATUS_SUCCESS)
a334319f 110 {
a17fa610
UD
111 ibreq = __create_ib_request (tablename_val, 0);
112 if (ibreq == NULL)
0ecb606c 113 {
a17fa610
UD
114 *errnop = errno;
115 return NSS_STATUS_TRYAGAIN;
116 }
117
118 nis_error retcode = __prepare_niscall (tablename_val, &dir, &bptr, 0);
119 if (retcode != NIS_SUCCESS)
120 {
121 nis_free_request (ibreq);
122 ibreq = NULL;
123 status = niserr2nss (retcode);
901956a5 124 }
e61abf83 125 }
a17fa610 126
8f2ece69 127 return status;
e61abf83
UD
128}
129
a17fa610 130
e61abf83 131enum nss_status
51eecc4a 132_nss_nisplus_setgrent (int stayopen)
e61abf83 133{
2d7da676
UD
134 enum nss_status status;
135
e61abf83
UD
136 __libc_lock_lock (lock);
137
a17fa610
UD
138 internal_endgrent ();
139
140 // XXX We need to be able to set errno. Pass in new parameter.
141 int err;
142 status = internal_setgrent (&err);
e61abf83
UD
143
144 __libc_lock_unlock (lock);
145
2d7da676 146 return status;
e61abf83
UD
147}
148
a17fa610 149
e61abf83
UD
150enum nss_status
151_nss_nisplus_endgrent (void)
152{
153 __libc_lock_lock (lock);
154
a17fa610 155 internal_endgrent ();
e61abf83
UD
156
157 __libc_lock_unlock (lock);
158
159 return NSS_STATUS_SUCCESS;
160}
161
a17fa610 162
e61abf83 163static enum nss_status
d71b808a
UD
164internal_nisplus_getgrent_r (struct group *gr, char *buffer, size_t buflen,
165 int *errnop)
e61abf83 166{
a17fa610
UD
167 int parse_res = -1;
168 enum nss_status retval = NSS_STATUS_SUCCESS;
e61abf83 169
a334319f
UD
170 /* Get the next entry until we found a correct one. */
171 do
172 {
a17fa610
UD
173 nis_error status;
174 nis_result result;
175 memset (&result, '\0', sizeof (result));
0ecb606c 176
a17fa610
UD
177 if (cursor.n_bytes == NULL)
178 {
179 if (ibreq == NULL)
180 {
181 retval = internal_setgrent (errnop);
182 if (retval != NSS_STATUS_SUCCESS)
183 return retval;
184 }
185
186 status = __do_niscall3 (&bptr, NIS_IBFIRST,
187 (xdrproc_t) _xdr_ib_request,
188 (caddr_t) ibreq,
189 (xdrproc_t) _xdr_nis_result,
190 (caddr_t) &result,
191 0, NULL);
192 }
193 else
194 {
195 ibreq->ibr_cookie.n_bytes = cursor.n_bytes;
196 ibreq->ibr_cookie.n_len = cursor.n_len;
197
198 status = __do_niscall3 (&bptr, NIS_IBNEXT,
199 (xdrproc_t) _xdr_ib_request,
200 (caddr_t) ibreq,
201 (xdrproc_t) _xdr_nis_result,
202 (caddr_t) &result,
203 0, NULL);
204
205 ibreq->ibr_cookie.n_bytes = NULL;
206 ibreq->ibr_cookie.n_len = 0;
207 }
208
209 if (status != NIS_SUCCESS)
210 return niserr2nss (status);
211
212 if (NIS_RES_STATUS (&result) == NIS_NOTFOUND)
213 {
214 /* No more entries on this server. This means we have to go
215 to the next server on the path. */
216 status = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
217 if (status != NIS_SUCCESS)
218 return niserr2nss (status);
219
220 directory_obj *newdir = NULL;
221 dir_binding newbptr;
222 status = __prepare_niscall (ibreq->ibr_name, &newdir, &newbptr, 0);
223 if (status != NIS_SUCCESS)
224 return niserr2nss (status);
225
226 nis_free_directory (dir);
227 dir = newdir;
228 __nisbind_destroy (&bptr);
229 bptr = newbptr;
230
231 xdr_free ((xdrproc_t) xdr_netobj, (char *) &result.cookie);
232 result.cookie.n_bytes = NULL;
233 result.cookie.n_len = 0;
234 parse_res = 0;
235 goto next;
236 }
237 else if (NIS_RES_STATUS (&result) != NIS_SUCCESS)
238 return niserr2nss (NIS_RES_STATUS (&result));
239
240 parse_res = _nss_nisplus_parse_grent (&result, gr,
d71b808a 241 buffer, buflen, errnop);
a17fa610
UD
242 if (__builtin_expect (parse_res == -1, 0))
243 {
244 *errnop = ERANGE;
245 retval = NSS_STATUS_TRYAGAIN;
246 goto freeres;
247 }
60c96635 248
a17fa610
UD
249 next:
250 /* Free the old cursor. */
251 xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
252 /* Remember the new one. */
253 cursor.n_bytes = result.cookie.n_bytes;
254 cursor.n_len = result.cookie.n_len;
255 /* Free the result structure. NB: we do not remove the cookie. */
256 result.cookie.n_bytes = NULL;
257 result.cookie.n_len = 0;
258 freeres:
259 xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &result);
260 memset (&result, '\0', sizeof (result));
e61abf83
UD
261 }
262 while (!parse_res);
263
a17fa610 264 return retval;
e61abf83
UD
265}
266
267enum nss_status
d71b808a
UD
268_nss_nisplus_getgrent_r (struct group *result, char *buffer, size_t buflen,
269 int *errnop)
e61abf83
UD
270{
271 int status;
272
273 __libc_lock_lock (lock);
274
d71b808a 275 status = internal_nisplus_getgrent_r (result, buffer, buflen, errnop);
e61abf83
UD
276
277 __libc_lock_unlock (lock);
278
279 return status;
280}
281
282enum nss_status
283_nss_nisplus_getgrnam_r (const char *name, struct group *gr,
d71b808a 284 char *buffer, size_t buflen, int *errnop)
e61abf83
UD
285{
286 int parse_res;
287
a334319f 288 if (tablename_val == NULL)
d71b808a 289 {
48b29391
UD
290 __libc_lock_lock (lock);
291
a334319f 292 enum nss_status status = _nss_create_tablename (errnop);
d71b808a 293
48b29391
UD
294 __libc_lock_unlock (lock);
295
d71b808a
UD
296 if (status != NSS_STATUS_SUCCESS)
297 return status;
298 }
2d7da676 299
ac9f45cf
UD
300 if (name == NULL)
301 {
302 *errnop = EINVAL;
303 return NSS_STATUS_NOTFOUND;
304 }
48b29391
UD
305
306 nis_result *result;
307 char buf[strlen (name) + 9 + tablename_len];
308 int olderr = errno;
309
310 snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val);
311
312 result = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
313
314 if (result == NULL)
e61abf83 315 {
48b29391
UD
316 *errnop = ENOMEM;
317 return NSS_STATUS_TRYAGAIN;
318 }
e61abf83 319
48b29391
UD
320 if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
321 {
322 enum nss_status status = niserr2nss (result->status);
e61abf83 323
48b29391
UD
324 nis_freeresult (result);
325 return status;
326 }
e61abf83 327
a17fa610 328 parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen, errnop);
48b29391
UD
329 nis_freeresult (result);
330 if (__builtin_expect (parse_res < 1, 0))
331 {
332 if (parse_res == -1)
901956a5 333 {
48b29391 334 *errnop = ERANGE;
901956a5
UD
335 return NSS_STATUS_TRYAGAIN;
336 }
48b29391 337 else
a334319f 338 {
48b29391
UD
339 __set_errno (olderr);
340 return NSS_STATUS_NOTFOUND;
a334319f 341 }
a334319f 342 }
48b29391
UD
343
344 return NSS_STATUS_SUCCESS;
e61abf83
UD
345}
346
347enum nss_status
348_nss_nisplus_getgrgid_r (const gid_t gid, struct group *gr,
d71b808a 349 char *buffer, size_t buflen, int *errnop)
e61abf83 350{
a334319f 351 if (tablename_val == NULL)
d71b808a 352 {
48b29391
UD
353 __libc_lock_lock (lock);
354
a334319f 355 enum nss_status status = _nss_create_tablename (errnop);
d71b808a 356
48b29391
UD
357 __libc_lock_unlock (lock);
358
d71b808a
UD
359 if (status != NSS_STATUS_SUCCESS)
360 return status;
361 }
e61abf83 362
48b29391
UD
363 int parse_res;
364 nis_result *result;
365 char buf[8 + 3 * sizeof (unsigned long int) + tablename_len];
366 int olderr = errno;
e61abf83 367
48b29391
UD
368 snprintf (buf, sizeof (buf), "[gid=%lu],%s",
369 (unsigned long int) gid, tablename_val);
e61abf83 370
48b29391 371 result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
e61abf83 372
48b29391
UD
373 if (result == NULL)
374 {
375 *errnop = ENOMEM;
376 return NSS_STATUS_TRYAGAIN;
377 }
2d7da676 378
48b29391
UD
379 if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
380 {
381 enum nss_status status = niserr2nss (result->status);
0ecb606c 382
48b29391
UD
383 __set_errno (olderr);
384
385 nis_freeresult (result);
386 return status;
387 }
388
a17fa610 389 parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen, errnop);
48b29391
UD
390
391 nis_freeresult (result);
392 if (__builtin_expect (parse_res < 1, 0))
393 {
394 __set_errno (olderr);
395
396 if (parse_res == -1)
397 {
398 *errnop = ERANGE;
399 return NSS_STATUS_TRYAGAIN;
400 }
401 else
402 return NSS_STATUS_NOTFOUND;
403 }
404
405 return NSS_STATUS_SUCCESS;
e61abf83 406}