]> git.ipfire.org Git - thirdparty/glibc.git/blame - hesiod/nss_hesiod/hesiod-grp.c
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / hesiod / nss_hesiod / hesiod-grp.c
CommitLineData
2b778ceb 1/* Copyright (C) 1997-2021 Free Software Foundation, Inc.
61eb22d3
UD
2 This file is part of the GNU C Library.
3 Contributed by Mark Kettenis <kettenis@phys.uva.nl>, 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.
61eb22d3
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.
61eb22d3 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
61eb22d3 18
bee1e289 19#include <ctype.h>
61eb22d3 20#include <errno.h>
61eb22d3 21#include <grp.h>
bee1e289 22#include <hesiod.h>
2f54c82d 23#include <nss.h>
61eb22d3
UD
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
7603ea28 27#include <sys/param.h>
2f54c82d 28
69787006
FW
29NSS_DECLARE_MODULE_FUNCTIONS (hesiod)
30
61eb22d3
UD
31/* Get the declaration of the parser function. */
32#define ENTNAME grent
33#define STRUCTURE group
34#define EXTERN_PARSER
35#include <nss/nss_files/files-parse.c>
36
61eb22d3 37enum nss_status
51eecc4a 38_nss_hesiod_setgrent (int stayopen)
61eb22d3 39{
2f54c82d 40 return NSS_STATUS_SUCCESS;
61eb22d3
UD
41}
42
43enum nss_status
44_nss_hesiod_endgrent (void)
45{
61eb22d3
UD
46 return NSS_STATUS_SUCCESS;
47}
48
49static enum nss_status
50lookup (const char *name, const char *type, struct group *grp,
d71b808a 51 char *buffer, size_t buflen, int *errnop)
61eb22d3 52{
61eb22d3
UD
53 struct parser_data *data = (void *) buffer;
54 size_t linebuflen;
2f54c82d 55 void *context;
61eb22d3
UD
56 char **list;
57 int parse_res;
d71b808a 58 size_t len;
34816665 59 int olderr = errno;
61eb22d3 60
5018f16c 61 if (hesiod_init (&context) < 0)
2f54c82d 62 return NSS_STATUS_UNAVAIL;
61eb22d3
UD
63
64 list = hesiod_resolve (context, name, type);
65 if (list == NULL)
2f54c82d 66 {
34816665 67 int err = errno;
2f54c82d 68 hesiod_end (context);
34816665
UD
69 __set_errno (olderr);
70 return err == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
2f54c82d 71 }
61eb22d3
UD
72
73 linebuflen = buffer + buflen - data->linebuffer;
d71b808a
UD
74 len = strlen (*list) + 1;
75 if (linebuflen < len)
61eb22d3
UD
76 {
77 hesiod_free_list (context, list);
2f54c82d 78 hesiod_end (context);
d71b808a 79 *errnop = ERANGE;
61eb22d3
UD
80 return NSS_STATUS_TRYAGAIN;
81 }
82
d71b808a 83 memcpy (data->linebuffer, *list, len);
61eb22d3 84 hesiod_free_list (context, list);
2f54c82d 85 hesiod_end (context);
61eb22d3 86
d71b808a 87 parse_res = _nss_files_parse_grent (buffer, grp, data, buflen, errnop);
61eb22d3 88 if (parse_res < 1)
34816665
UD
89 {
90 __set_errno (olderr);
91 return parse_res == -1 ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
92 }
61eb22d3
UD
93
94 return NSS_STATUS_SUCCESS;
95}
96
97enum nss_status
98_nss_hesiod_getgrnam_r (const char *name, struct group *grp,
d71b808a 99 char *buffer, size_t buflen, int *errnop)
61eb22d3 100{
2f54c82d 101 return lookup (name, "group", grp, buffer, buflen, errnop);
61eb22d3
UD
102}
103
104enum nss_status
105_nss_hesiod_getgrgid_r (gid_t gid, struct group *grp,
d71b808a 106 char *buffer, size_t buflen, int *errnop)
61eb22d3 107{
61eb22d3
UD
108 char gidstr[21]; /* We will probably never have a gid_t with more
109 than 64 bits. */
110
111 snprintf (gidstr, sizeof gidstr, "%d", gid);
112
2f54c82d 113 return lookup (gidstr, "gid", grp, buffer, buflen, errnop);
61eb22d3 114}
bee1e289
UD
115
116static int
117internal_gid_in_list (const gid_t *list, const gid_t g, long int len)
118{
119 while (len > 0)
120 {
121 if (*list == g)
122 return 1;
123 --len;
124 ++list;
125 }
126 return 0;
127}
128
129static enum nss_status
130internal_gid_from_group (void *context, const char *groupname, gid_t *group)
131{
132 char **grp_res;
133 enum nss_status status = NSS_STATUS_NOTFOUND;
134
135 grp_res = hesiod_resolve (context, groupname, "group");
136 if (grp_res != NULL && *grp_res != NULL)
137 {
138 char *p = *grp_res;
139
2eeb9a5d 140 /* Skip to third field. */
bee1e289
UD
141 while (*p != '\0' && *p != ':')
142 ++p;
2eeb9a5d 143 if (*p != '\0')
bee1e289
UD
144 ++p;
145 while (*p != '\0' && *p != ':')
146 ++p;
2eeb9a5d 147 if (*p != '\0')
bee1e289
UD
148 {
149 char *endp;
150 char *q = ++p;
0a55a284 151 long int val;
bee1e289 152
bee1e289
UD
153 while (*q != '\0' && *q != ':')
154 ++q;
155
0a55a284
UD
156 val = strtol (p, &endp, 10);
157 if (sizeof (gid_t) == sizeof (long int) || (gid_t) val == val)
158 {
159 *group = val;
160 if (endp == q && endp != p)
161 status = NSS_STATUS_SUCCESS;
162 }
bee1e289
UD
163 }
164 hesiod_free_list (context, grp_res);
165 }
166 return status;
167}
168
169enum nss_status
cf9e9ad9 170_nss_hesiod_initgroups_dyn (const char *user, gid_t group, long int *start,
7603ea28
UD
171 long int *size, gid_t **groupsp, long int limit,
172 int *errnop)
bee1e289
UD
173{
174 enum nss_status status = NSS_STATUS_SUCCESS;
175 char **list = NULL;
176 char *p;
177 void *context;
cf9e9ad9 178 gid_t *groups = *groupsp;
521a2f65 179 int save_errno;
bee1e289 180
5018f16c 181 if (hesiod_init (&context) < 0)
bee1e289
UD
182 return NSS_STATUS_UNAVAIL;
183
184 list = hesiod_resolve (context, user, "grplist");
185
186 if (list == NULL)
187 {
0a55a284 188 hesiod_end (context);
bee1e289
UD
189 return errno == ENOENT ? NSS_STATUS_NOTFOUND : NSS_STATUS_UNAVAIL;
190 }
191
521a2f65
UD
192 save_errno = errno;
193
bee1e289 194 p = *list;
cf9e9ad9 195 while (*p != '\0')
bee1e289
UD
196 {
197 char *endp;
198 char *q;
0a55a284 199 long int val;
bee1e289
UD
200
201 status = NSS_STATUS_NOTFOUND;
202
203 q = p;
521a2f65 204 while (*q != '\0' && *q != ':' && *q != ',')
bee1e289
UD
205 ++q;
206
207 if (*q != '\0')
208 *q++ = '\0';
209
521a2f65 210 __set_errno (0);
0a55a284 211 val = strtol (p, &endp, 10);
521a2f65
UD
212 /* Test whether the number is representable in a variable of
213 type `gid_t'. If not ignore the number. */
214 if ((sizeof (gid_t) == sizeof (long int) || (gid_t) val == val)
215 && errno == 0)
0a55a284
UD
216 {
217 if (*endp == '\0' && endp != p)
521a2f65
UD
218 {
219 group = val;
220 status = NSS_STATUS_SUCCESS;
221 }
0a55a284
UD
222 else
223 status = internal_gid_from_group (context, p, &group);
bee1e289 224
0a55a284
UD
225 if (status == NSS_STATUS_SUCCESS
226 && !internal_gid_in_list (groups, group, *start))
cf9e9ad9 227 {
a1ffb40e 228 if (__glibc_unlikely (*start == *size))
cf9e9ad9
UD
229 {
230 /* Need a bigger buffer. */
231 gid_t *newgroups;
7603ea28
UD
232 long int newsize;
233
234 if (limit > 0 && *size == limit)
235 /* We reached the maximum. */
236 goto done;
237
238 if (limit <= 0)
239 newsize = 2 * *size;
240 else
241 newsize = MIN (limit, 2 * *size);
242
243 newgroups = realloc (groups, newsize * sizeof (*groups));
cf9e9ad9
UD
244 if (newgroups == NULL)
245 goto done;
246 *groupsp = groups = newgroups;
7603ea28 247 *size = newsize;
cf9e9ad9
UD
248 }
249
250 groups[(*start)++] = group;
251 }
0a55a284 252 }
bee1e289
UD
253
254 p = q;
255 }
256
521a2f65
UD
257 __set_errno (save_errno);
258
cf9e9ad9 259 done:
bee1e289 260 hesiod_free_list (context, list);
0a55a284 261 hesiod_end (context);
bee1e289
UD
262
263 return NSS_STATUS_SUCCESS;
264}