]>
Commit | Line | Data |
---|---|---|
9f2da732 | 1 | /* Initgroups handling in nss_db module. |
bfff8b1b | 2 | Copyright (C) 2011-2017 Free Software Foundation, Inc. |
9f2da732 UD |
3 | This file is part of the GNU C Library. |
4 | Contributed by Ulrich Drepper <drepper@gmail.com>. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Library General Public License as | |
8 | published by the Free Software Foundation; either version 2 of the | |
9 | License, or (at your option) any later version. | |
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 | |
14 | Library General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Library General Public | |
59ba27a6 PE |
17 | License along with the GNU C Library; see the file COPYING.LIB. If |
18 | not, see <http://www.gnu.org/licenses/>. */ | |
9f2da732 UD |
19 | |
20 | #include <ctype.h> | |
21 | #include <errno.h> | |
22 | #include <grp.h> | |
e468f8a3 | 23 | #include <limits.h> |
9f2da732 | 24 | #include <paths.h> |
bea9b193 | 25 | #include <stdlib.h> |
2c040eff | 26 | #include <string.h> |
e054f494 | 27 | #include <stdint.h> |
e468f8a3 | 28 | #include <sys/param.h> |
9f2da732 UD |
29 | |
30 | #include "nss_db.h" | |
31 | ||
32 | /* The hashing function we use. */ | |
33 | #include "../intl/hash-string.h" | |
34 | ||
35 | ||
36 | enum nss_status | |
37 | _nss_db_initgroups_dyn (const char *user, gid_t group, long int *start, | |
38 | long int *size, gid_t **groupsp, long int limit, | |
39 | int *errnop) | |
40 | { | |
41 | struct nss_db_map state = { NULL, 0 }; | |
42 | enum nss_status status = internal_setent (_PATH_VARDB "group.db", &state); | |
43 | if (status != NSS_STATUS_SUCCESS) | |
44 | { | |
45 | *errnop = errno; | |
46 | return status; | |
47 | } | |
48 | ||
49 | const struct nss_db_header *header = state.header; | |
50 | int i; | |
51 | for (i = 0; i < header->ndbs; ++i) | |
52 | if (header->dbs[i].id == ':') | |
53 | break; | |
54 | if (i == header->ndbs) | |
55 | { | |
56 | status = NSS_STATUS_UNAVAIL; | |
57 | goto out; | |
58 | } | |
59 | ||
60 | const stridx_t *hashtable | |
61 | = (const stridx_t *) ((const char *) header | |
62 | + header->dbs[i].hashoffset); | |
63 | const char *valstrtab = (const char *) header + header->valstroffset; | |
64 | size_t userlen = strlen (user); | |
65 | uint32_t hashval = __hash_string (user); | |
66 | size_t hidx = hashval % header->dbs[i].hashsize; | |
67 | size_t hval2 = 1 + hashval % (header->dbs[i].hashsize - 2); | |
68 | ||
69 | gid_t *groups = *groupsp; | |
70 | ||
71 | status = NSS_STATUS_NOTFOUND; | |
72 | while (hashtable[hidx] != ~((stridx_t) 0)) | |
73 | { | |
74 | const char *valstr = valstrtab + hashtable[hidx]; | |
75 | while (isblank (*valstr)) | |
76 | ++valstr; | |
77 | ||
78 | if (strncmp (valstr, user, userlen) == 0 && isblank (valstr[userlen])) | |
79 | { | |
80 | valstr += userlen + 1; | |
81 | while (isblank (*valstr)) | |
82 | ++valstr; | |
83 | ||
84 | while (*valstr != '\0') | |
85 | { | |
86 | errno = 0; | |
87 | char *endp; | |
88 | unsigned long int n = strtoul (valstr, &endp, 10); | |
89 | if (*endp != ',' && *endp != '\0') | |
90 | break; | |
91 | valstr = *endp == '\0' ? endp : endp + 1; | |
92 | ||
93 | if (n != ULONG_MAX || errno != ERANGE) | |
94 | { | |
95 | /* Insert the group. */ | |
96 | if (*start == *size) | |
97 | { | |
98 | /* Need a bigger buffer. */ | |
99 | if (limit > 0 && *size == limit) | |
100 | { | |
101 | /* We reached the maximum. */ | |
102 | status = NSS_STATUS_SUCCESS; | |
103 | goto out; | |
104 | } | |
105 | ||
106 | long int newsize; | |
107 | if (limit <= 0) | |
108 | newsize = 2 * *size; | |
109 | else | |
110 | newsize = MIN (limit, 2 * *size); | |
111 | ||
112 | gid_t *newgroups = realloc (groups, | |
113 | newsize * sizeof (*groups)); | |
114 | if (newgroups == NULL) | |
115 | { | |
116 | *errnop = ENOMEM; | |
117 | status = NSS_STATUS_TRYAGAIN; | |
118 | goto out; | |
119 | } | |
120 | ||
121 | *groupsp = groups = newgroups; | |
122 | *size = newsize; | |
123 | } | |
124 | ||
125 | groups[*start] = n; | |
126 | *start += 1; | |
127 | } | |
128 | } | |
129 | ||
130 | status = NSS_STATUS_SUCCESS; | |
131 | break; | |
132 | } | |
133 | ||
134 | if ((hidx += hval2) >= header->dbs[i].hashsize) | |
135 | hidx -= header->dbs[i].hashsize; | |
136 | } | |
137 | ||
138 | out: | |
139 | internal_endent (&state); | |
140 | ||
141 | return status; | |
142 | } |