1/* Copyright (C) 1997-2016 Free Software Foundation, Inc.
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
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.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
18
19#include <pwd.h>
20#include <ctype.h>
21#include <errno.h>
22#include <string.h>
23#include <rpcsvc/nis.h>
24
25#include "nisplus-parser.h"
26
27#define NISENTRYVAL(idx, col, res) \
28 (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
29
30#define NISENTRYLEN(idx, col, res) \
31 (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
32
33#define NISOBJVAL(col, obj) \
34 ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val)
35
36#define NISOBJLEN(col, obj) \
37 ((obj)->EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len)
38
39
40int
41_nss_nisplus_parse_pwent (nis_result *result, struct passwd *pw,
42 char *buffer, size_t buflen, int *errnop)
43{
44 if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
45 || NIS_RES_NUMOBJ (result) != 1
46 || __type_of (NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
47 || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "passwd_tbl") != 0
48 || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 7)
49 return 0;
50
51 nis_object *obj = NIS_RES_OBJECT (result);
52 char *first_unused = buffer;
53 size_t room_left = buflen;
54 size_t len;
55
56 if (NISOBJLEN (0, obj) >= room_left)
57 {
58 /* The line is too long for our buffer. */
59 no_more_room:
60 *errnop = ERANGE;
61 return -1;
62 }
63
64 strncpy (first_unused, NISOBJVAL (0, obj), NISOBJLEN (0, obj));
65 first_unused[NISOBJLEN (0, obj)] = '\0';
66 len = strlen (first_unused);
67 if (len == 0) /* No name ? Should never happen, database is corrupt */
68 return 0;
69 pw->pw_name = first_unused;
70 room_left -= len + 1;
71 first_unused += len + 1;
72
73 if (NISOBJLEN (1, obj) >= room_left)
74 goto no_more_room;
75
76 strncpy (first_unused, NISOBJVAL (1, obj), NISOBJLEN (1, obj));
77 first_unused[NISOBJLEN (1, obj)] = '\0';
78 pw->pw_passwd = first_unused;
79 len = strlen (first_unused);
80 room_left -= len + 1;
81 first_unused += len + 1;
82
83 char *numstr = NISOBJVAL (2, obj);
84 len = NISOBJLEN (2, obj);
85 if (len == 0 && numstr[len - 1] != '\0')
86 {
87 if (len >= room_left)
88 goto no_more_room;
89
90 strncpy (first_unused, numstr, len);
91 first_unused[len] = '\0';
92 numstr = first_unused;
93 }
94 if (numstr[0] == '\0')
95 /* If we don't have a uid, it's an invalid shadow entry. */
96 return 0;
97 pw->pw_uid = strtoul (numstr, NULL, 10);
98
99 numstr = NISOBJVAL (3, obj);
100 len = NISOBJLEN (3, obj);
101 if (len == 0 && numstr[len - 1] != '\0')
102 {
103 if (len >= room_left)
104 goto no_more_room;
105
106 strncpy (first_unused, numstr, len);
107 first_unused[len] = '\0';
108 numstr = first_unused;
109 }
110 if (numstr[0] == '\0')
111 /* If we don't have a gid, it's an invalid shadow entry. */
112 return 0;
113 pw->pw_gid = strtoul (numstr, NULL, 10);
114
115 if (NISOBJLEN(4, obj) >= room_left)
116 goto no_more_room;
117
118 strncpy (first_unused, NISOBJVAL (4, obj), NISOBJLEN (4, obj));
119 first_unused[NISOBJLEN (4, obj)] = '\0';
120 pw->pw_gecos = first_unused;
121 len = strlen (first_unused);
122 room_left -= len + 1;
123 first_unused += len + 1;
124
125 if (NISOBJLEN (5, obj) >= room_left)
126 goto no_more_room;
127
128 strncpy (first_unused, NISOBJVAL (5, obj), NISOBJLEN (5, obj));
129 first_unused[NISOBJLEN (5, obj)] = '\0';
130 pw->pw_dir = first_unused;
131 len = strlen (first_unused);
132 room_left -= len + 1;
133 first_unused += len + 1;
134
135 if (NISOBJLEN (6, obj) >= room_left)
136 goto no_more_room;
137
138 strncpy (first_unused, NISOBJVAL (6, obj), NISOBJLEN (6, obj));
139 first_unused[NISOBJLEN (6, obj)] = '\0';
140 pw->pw_shell = first_unused;
141 len = strlen (first_unused);
142 room_left -= len + 1;
143 first_unused += len + 1;
144
145 return 1;
146}
147
148
149int
150_nss_nisplus_parse_grent (nis_result *result, struct group *gr,
151 char *buffer, size_t buflen, int *errnop)
152{
153 if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
154 || __type_of(NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
155 || strcmp (NIS_RES_OBJECT (result)[0].EN_data.en_type, "group_tbl") != 0
156 || NIS_RES_OBJECT (result)[0].EN_data.en_cols.en_cols_len < 4)
157 return 0;
158
159 nis_object *obj = NIS_RES_OBJECT (result);
160 char *first_unused = buffer;
161 size_t room_left = buflen;
162 char *line;
163 int count;
164 size_t len;
165
166 if (NISOBJLEN (0, obj) >= room_left)
167 {
168 /* The line is too long for our buffer. */
169 no_more_room:
170 *errnop = ERANGE;
171 return -1;
172 }
173
174 strncpy (first_unused, NISOBJVAL (0, obj), NISOBJLEN (0, obj));
175 first_unused[NISOBJLEN (0, obj)] = '\0';
176 len = strlen (first_unused);
177 if (len == 0) /* group table is corrupt */
178 return 0;
179 gr->gr_name = first_unused;
180 room_left -= len + 1;
181 first_unused += len + 1;
182
183 if (NISOBJLEN (1, obj) >= room_left)
184 goto no_more_room;
185
186 strncpy (first_unused, NISOBJVAL (1, obj), NISOBJLEN (1, obj));
187 first_unused[NISOBJLEN (1, obj)] = '\0';
188 gr->gr_passwd = first_unused;
189 len = strlen (first_unused);
190 room_left -= len + 1;
191 first_unused += len + 1;
192
193 char *numstr = NISOBJVAL (2, obj);
194 len = NISOBJLEN (2, obj);
195 if (len == 0 || numstr[len - 1] != '\0')
196 {
197 if (len >= room_left)
198 goto no_more_room;
199
200 strncpy (first_unused, numstr, len);
201 first_unused[len] = '\0';
202 numstr = first_unused;
203 }
204 if (numstr[0] == '\0')
205 /* We should always have a gid. */
206 return 0;
207 gr->gr_gid = strtoul (numstr, NULL, 10);
208
209 if (NISOBJLEN (3, obj) >= room_left)
210 goto no_more_room;
211
212 strncpy (first_unused, NISOBJVAL (3, obj), NISOBJLEN (3, obj));
213 first_unused[NISOBJLEN (3, obj)] = '\0';
214 line = first_unused;
215 len = strlen (line);
216 room_left -= len + 1;
217 first_unused += len + 1;
218 /* Adjust the pointer so it is aligned for
219 storing pointers. */
220 size_t adjust = ((__alignof__ (char *)
221 - (first_unused - (char *) 0) % __alignof__ (char *))
222 % __alignof__ (char *));
223 if (room_left < adjust)
224 goto no_more_room;
225 first_unused += adjust;
226 room_left -= adjust;
227 gr->gr_mem = (char **) first_unused;
228
229 count = 0;
230 while (*line != '\0')
231 {
232 /* Skip leading blanks. */
233 while (isspace (*line))
234 ++line;
235
236 if (*line == '\0')
237 break;
238
239 if (room_left < sizeof (char *))
240 goto no_more_room;
241 room_left -= sizeof (char *);
242 gr->gr_mem[count++] = line;
243
244 while (*line != '\0' && *line != ',' && !isspace (*line))
245 ++line;
246
247 if (*line == ',' || isspace (*line))
248 {
249 int is = isspace (*line);
250
251 *line++ = '\0';
252 if (is)
253 while (*line != '\0' && (*line == ',' || isspace (*line)))
254 ++line;
255 }
256 }
257 if (room_left < sizeof (char *))
258 goto no_more_room;
259 room_left -= sizeof (char *);
260 gr->gr_mem[count] = NULL;
261
262 return 1;
263}
264
265
266int
267_nss_nisplus_parse_spent (nis_result *result, struct spwd *sp,
268 char *buffer, size_t buflen, int *errnop)
269{
270 char *first_unused = buffer;
271 size_t room_left = buflen;
272 size_t len;
273
274 if (result == NULL)
275 return 0;
276
277 if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
278 || NIS_RES_NUMOBJ (result) != 1
279 || __type_of(NIS_RES_OBJECT (result)) != NIS_ENTRY_OBJ
280 || strcmp (NIS_RES_OBJECT (result)->EN_data.en_type, "passwd_tbl") != 0
281 || NIS_RES_OBJECT (result)->EN_data.en_cols.en_cols_len < 8)
282 return 0;
283
284 if (NISENTRYLEN (0, 0, result) >= room_left)
285 {
286 /* The line is too long for our buffer. */
287 no_more_room:
288 *errnop = ERANGE;
289 return -1;
290 }
291
292 strncpy (first_unused, NISENTRYVAL (0, 0, result),
293 NISENTRYLEN (0, 0, result));
294 first_unused[NISENTRYLEN (0, 0, result)] = '\0';
295 len = strlen (first_unused);
296 if (len == 0)
297 return 0;
298 sp->sp_namp = first_unused;
299 room_left -= len + 1;
300 first_unused += len + 1;
301
302 if (NISENTRYLEN (0, 1, result) >= room_left)
303 goto no_more_room;
304
305 strncpy (first_unused, NISENTRYVAL (0, 1, result),
306 NISENTRYLEN (0, 1, result));
307 first_unused[NISENTRYLEN (0, 1, result)] = '\0';
308 sp->sp_pwdp = first_unused;
309 len = strlen (first_unused);
310 room_left -= len + 1;
311 first_unused += len + 1;
312
313 sp->sp_lstchg = sp->sp_min = sp->sp_max = sp->sp_warn = sp->sp_inact =
314 sp->sp_expire = -1;
315 sp->sp_flag = ~0ul;
316
317 if (NISENTRYLEN (0, 7, result) > 0)
318 {
319 char *line = NISENTRYVAL (0, 7, result);
320 char *cp = strchr (line, ':');
321 if (cp == NULL)
322 return 1;
323 *cp++ = '\0';
324 if (*line)
325 sp->sp_lstchg = atol (line);
326
327 line = cp;
328 cp = strchr (line, ':');
329 if (cp == NULL)
330 return 1;
331 *cp++ = '\0';
332 if (*line)
333 sp->sp_min = atol (line);
334
335 line = cp;
336 cp = strchr (line, ':');
337 if (cp == NULL)
338 return 1;
339 *cp++ = '\0';
340 if (*line)
341 sp->sp_max = atol (line);
342
343 line = cp;
344 cp = strchr (line, ':');
345 if (cp == NULL)
346 return 1;
347 *cp++ = '\0';
348 if (*line)
349 sp->sp_warn = atol (line);
350
351 line = cp;
352 cp = strchr (line, ':');
353 if (cp == NULL)
354 return 1;
355 *cp++ = '\0';
356 if (*line)
357 sp->sp_inact = atol (line);
358
359 line = cp;
360 cp = strchr (line, ':');
361 if (cp == NULL)
362 return 1;
363 *cp++ = '\0';
364 if (*line)
365 sp->sp_expire = atol (line);
366
367 line = cp;
368 if (line == NULL)
369 return 1;
370 if (*line)
371 sp->sp_flag = atol (line);
372 }
373
374 return 1;
375}
376