1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20: #include <assert.h>
21: #include <errno.h>
22: #include <grp.h>
23: #include <stdlib.h>
24: #include <string.h>
25: #include <unistd.h>
26: #include <not-cancel.h>
27:
28: #include "nscd-client.h"
29: #include "nscd_proto.h"
30:
31:
32:
33: libc_locked_map_ptr (extern, __gr_map_handle) attribute_hidden;
34:
35:
36: int
37: __nscd_getgrouplist (const char *user, gid_t group, long int *size,
38: gid_t **groupsp, long int limit)
39: {
40: size_t userlen = strlen (user) + 1;
41: int gc_cycle;
42: int nretries = 0;
43:
44:
45:
46: struct mapped_database *mapped;
47: mapped = __nscd_get_map_ref (GETFDGR, "group", &__gr_map_handle, &gc_cycle);
48:
49: retry:;
50: char *respdata = NULL;
51: int retval = -1;
52: int sock = -1;
53: initgr_response_header initgr_resp;
54:
55: if (mapped != NO_MAPPING)
56: {
57: struct datahead *found = __nscd_cache_search (INITGROUPS, user,
58: userlen, mapped);
59: if (found != NULL)
60: {
61: respdata = (char *) (&found->data[0].initgrdata + 1);
62: initgr_resp = found->data[0].initgrdata;
63: char *recend = (char *) found->data + found->recsize;
64:
65:
66:
67: if (mapped->head->gc_cycle != gc_cycle)
68: {
69: retval = -2;
70: goto out;
71: }
72:
73: if (respdata + initgr_resp.ngrps * sizeof (int32_t) > recend)
74: goto out;
75: }
76: }
77:
78:
79:
80: if (respdata == NULL)
81: {
82: sock = __nscd_open_socket (user, userlen, INITGROUPS, &initgr_resp,
83: sizeof (initgr_resp));
84: if (sock == -1)
85: {
86:
87: __nss_not_use_nscd_group = 1;
88: goto out;
89: }
90: }
91:
92: if (initgr_resp.found == 1)
93: {
94:
95:
96:
97:
98:
99: assert (sizeof (int32_t) == sizeof (gid_t));
100: assert (initgr_resp.ngrps >= 0);
101:
102:
103:
104: if (*size < initgr_resp.ngrps + 1)
105: {
106: gid_t *newp = realloc (*groupsp,
107: (initgr_resp.ngrps + 1) * sizeof (gid_t));
108: if (newp == NULL)
109:
110: goto out_close;
111:
112: *groupsp = newp;
113: *size = initgr_resp.ngrps + 1;
114: }
115:
116: if (respdata == NULL)
117: {
118:
119: if ((size_t) __readall (sock, *groupsp, initgr_resp.ngrps
120: * sizeof (gid_t))
121: == initgr_resp.ngrps * sizeof (gid_t))
122: retval = initgr_resp.ngrps;
123: }
124: else
125: {
126:
127: retval = initgr_resp.ngrps;
128: memcpy (*groupsp, respdata, retval * sizeof (gid_t));
129: }
130: }
131: else
132: {
133: if (__builtin_expect (initgr_resp.found == -1, 0))
134: {
135:
136: __nss_not_use_nscd_group = 1;
137: goto out_close;
138: }
139:
140:
141: retval = 0;
142:
143: assert (*size >= 1);
144: }
145:
146:
147: if (retval >= 0)
148: {
149: int cnt;
150: for (cnt = 0; cnt < retval; ++cnt)
151: if ((*groupsp)[cnt] == group)
152: break;
153:
154: if (cnt == retval)
155: (*groupsp)[retval++] = group;
156: }
157:
158: out_close:
159: if (sock != -1)
160: close_not_cancel_no_status (sock);
161: out:
162: if (__nscd_drop_map_ref (mapped, &gc_cycle) != 0)
163: {
164:
165:
166:
167: if ((gc_cycle & 1) != 0 || ++nretries == 5 || retval == -1)
168: {
169:
170: if (atomic_decrement_val (&mapped->counter) == 0)
171: __nscd_unmap (mapped);
172: mapped = NO_MAPPING;
173: }
174:
175: if (retval != -1)
176: goto retry;
177: }
178:
179: return retval;
180: }