Line data Source code
1 : /*
2 : SSSD
3 :
4 : nss_netgroup.c
5 :
6 : Authors:
7 : Stephen Gallagher <sgallagh@redhat.com>
8 :
9 : Copyright (C) 2010 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include <nss.h>
26 : #include <errno.h>
27 : #include <sys/types.h>
28 : #include <unistd.h>
29 : #include <stdlib.h>
30 : #include <stdint.h>
31 : #include <stdio.h>
32 : #include <string.h>
33 : #include "sss_cli.h"
34 : #include "nss_compat.h"
35 :
36 : #define CLEAR_NETGRENT_DATA(netgrent) do { \
37 : free(netgrent->data); \
38 : netgrent->data = NULL; \
39 : netgrent->idx.position = 0; \
40 : netgrent->data_size = 0; \
41 : } while (0);
42 :
43 : /*
44 : * Replies:
45 : *
46 : * 0-3: 32bit unsigned number of results N
47 : * 4-7: 32bit unsigned (reserved/padding)
48 : * For each result:
49 : * 8-11: 32bit unsigned type of result
50 : * 12-X: \0 terminated string representing a tuple
51 : * (host, user, domain)
52 : * or a netgroup, depending on the type indicator
53 : * ... repeated N times
54 : */
55 : #define NETGR_METADATA_COUNT 2 * sizeof(uint32_t)
56 : struct sss_nss_netgr_rep {
57 : struct __netgrent *result;
58 : char *buffer;
59 : size_t buflen;
60 : };
61 :
62 0 : static int sss_nss_getnetgr_readrep(struct sss_nss_netgr_rep *pr,
63 : uint8_t *buf, size_t *len)
64 : {
65 : errno_t ret;
66 : char *sbuf;
67 : char *temp;
68 : size_t i, slen, dlen, size;
69 : uint32_t type;
70 :
71 0 : if (*len < 6) {
72 : /* Not enough space for data, bad packet */
73 0 : return EBADMSG;
74 : }
75 :
76 0 : sbuf = (char *)(buf + sizeof(uint32_t));
77 0 : slen = *len - sizeof(uint32_t);
78 0 : dlen = pr->buflen;
79 :
80 0 : i = 0;
81 :
82 0 : SAFEALIGN_COPY_UINT32(&type, buf, NULL);
83 0 : switch (type) {
84 : case SSS_NETGR_REP_TRIPLE:
85 0 : pr->result->type = triple_val;
86 :
87 : /* Host value */
88 0 : temp = &(pr->buffer[i]);
89 0 : ret = sss_readrep_copy_string(sbuf, &i,
90 : &slen, &dlen,
91 : &temp,
92 : &size);
93 0 : if (ret != EOK) return ret;
94 :
95 : /* libc expects NULL instead of empty string */
96 0 : if (size == 0) {
97 0 : pr->result->val.triple.host = NULL;
98 : } else {
99 0 : pr->result->val.triple.host = temp;
100 : }
101 :
102 : /* User value */
103 0 : temp = &(pr->buffer[i]);
104 0 : ret = sss_readrep_copy_string(sbuf, &i,
105 : &slen, &dlen,
106 : &temp,
107 : &size);
108 0 : if (ret != EOK) return ret;
109 :
110 : /* libc expects NULL instead of empty string */
111 0 : if (size == 0) {
112 0 : pr->result->val.triple.user = NULL;
113 : } else {
114 0 : pr->result->val.triple.user = temp;
115 : }
116 :
117 : /* Domain value */
118 0 : temp = &(pr->buffer[i]);
119 0 : ret = sss_readrep_copy_string(sbuf, &i,
120 : &slen, &dlen,
121 : &temp,
122 : &size);
123 0 : if (ret != EOK) return ret;
124 :
125 : /* libc expects NULL instead of empty string */
126 0 : if (size == 0) {
127 0 : pr->result->val.triple.domain = NULL;
128 : } else {
129 0 : pr->result->val.triple.domain = temp;
130 : }
131 :
132 0 : break;
133 :
134 : case SSS_NETGR_REP_GROUP:
135 0 : pr->result->type = group_val;
136 :
137 0 : temp = &(pr->buffer[i]);
138 0 : ret = sss_readrep_copy_string(sbuf, &i,
139 : &slen, &dlen,
140 : &temp,
141 : NULL);
142 0 : if (ret != EOK) return ret;
143 :
144 0 : pr->result->val.group = temp;
145 :
146 0 : break;
147 :
148 : default:
149 0 : return EBADMSG;
150 : }
151 :
152 :
153 0 : *len = slen -i;
154 :
155 0 : return 0;
156 : }
157 :
158 0 : enum nss_status _nss_sss_setnetgrent(const char *netgroup,
159 : struct __netgrent *result)
160 : {
161 0 : uint8_t *repbuf = NULL;
162 : size_t replen;
163 : uint32_t num_results;
164 : enum nss_status nret;
165 : struct sss_cli_req_data rd;
166 : int errnop;
167 : char *name;
168 : size_t name_len;
169 : errno_t ret;
170 :
171 0 : if (!netgroup) return NSS_STATUS_NOTFOUND;
172 :
173 0 : sss_nss_lock();
174 :
175 : /* make sure we do not have leftovers, and release memory */
176 0 : CLEAR_NETGRENT_DATA(result);
177 :
178 0 : ret = sss_strnlen(netgroup, SSS_NAME_MAX, &name_len);
179 0 : if (ret != 0) {
180 0 : nret = NSS_STATUS_NOTFOUND;
181 0 : goto out;
182 : }
183 :
184 0 : name = malloc(sizeof(char)*name_len + 1);
185 0 : if (name == NULL) {
186 0 : nret = NSS_STATUS_TRYAGAIN;
187 0 : goto out;
188 : }
189 0 : strncpy(name, netgroup, name_len + 1);
190 :
191 0 : rd.data = name;
192 0 : rd.len = name_len + 1;
193 :
194 0 : nret = sss_nss_make_request(SSS_NSS_SETNETGRENT, &rd,
195 : &repbuf, &replen, &errnop);
196 0 : free(name);
197 0 : if (nret != NSS_STATUS_SUCCESS) {
198 0 : errno = errnop;
199 0 : goto out;
200 : }
201 :
202 : /* Get number of results from repbuf */
203 0 : SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);
204 :
205 : /* no results if not found */
206 0 : if ((num_results == 0) || (replen < NETGR_METADATA_COUNT)) {
207 0 : free(repbuf);
208 0 : nret = NSS_STATUS_NOTFOUND;
209 0 : goto out;
210 : }
211 :
212 0 : free(repbuf);
213 0 : nret = NSS_STATUS_SUCCESS;
214 :
215 : out:
216 0 : sss_nss_unlock();
217 0 : return nret;
218 : }
219 :
220 0 : static enum nss_status internal_getnetgrent_r(struct __netgrent *result,
221 : char *buffer, size_t buflen,
222 : int *errnop)
223 : {
224 : struct sss_cli_req_data rd;
225 : struct sss_nss_netgr_rep netgrrep;
226 : uint8_t *repbuf;
227 : size_t replen;
228 : uint32_t num_results;
229 : enum nss_status nret;
230 : uint32_t num_entries;
231 : int ret;
232 :
233 : /* Caught once glibc passing in buffer == 0x0 */
234 0 : if (!buffer || !buflen) return ERANGE;
235 :
236 : /* If we're already processing result data, continue to
237 : * return it.
238 : */
239 0 : if (result->data != NULL &&
240 0 : result->idx.position < result->data_size) {
241 :
242 0 : repbuf = (uint8_t *) result->data + result->idx.position;
243 0 : replen = result->data_size - result->idx.position;
244 :
245 0 : netgrrep.result = result;
246 0 : netgrrep.buffer = buffer;
247 0 : netgrrep.buflen = buflen;
248 :
249 0 : ret = sss_nss_getnetgr_readrep(&netgrrep, repbuf, &replen);
250 0 : if (ret != 0) {
251 0 : *errnop = ret;
252 0 : return NSS_STATUS_TRYAGAIN;
253 : }
254 :
255 0 : result->idx.position = result->data_size - replen;
256 :
257 0 : return NSS_STATUS_SUCCESS;
258 : }
259 :
260 : /* Release memory, if any */
261 0 : CLEAR_NETGRENT_DATA(result);
262 :
263 : /* retrieve no more than SSS_NSS_MAX_ENTRIES at a time */
264 0 : num_entries = SSS_NSS_MAX_ENTRIES;
265 0 : rd.len = sizeof(uint32_t);
266 0 : rd.data = &num_entries;
267 :
268 0 : nret = sss_nss_make_request(SSS_NSS_GETNETGRENT, &rd,
269 : &repbuf, &replen, errnop);
270 0 : if (nret != NSS_STATUS_SUCCESS) {
271 0 : return nret;
272 : }
273 :
274 : /* Get number of results from repbuf. */
275 0 : SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);
276 :
277 : /* no results if not found */
278 0 : if ((num_results == 0) || (replen <= NETGR_METADATA_COUNT)) {
279 0 : free(repbuf);
280 0 : return NSS_STATUS_RETURN;
281 : }
282 :
283 0 : result->data = (char *) repbuf;
284 0 : result->data_size = replen;
285 : /* skip metadata fields */
286 0 : result->idx.position = NETGR_METADATA_COUNT;
287 :
288 : /* call again ourselves, this will return the first result */
289 0 : return internal_getnetgrent_r(result, buffer, buflen, errnop);
290 : }
291 :
292 0 : enum nss_status _nss_sss_getnetgrent_r(struct __netgrent *result,
293 : char *buffer, size_t buflen,
294 : int *errnop)
295 : {
296 : enum nss_status nret;
297 :
298 0 : sss_nss_lock();
299 0 : nret = internal_getnetgrent_r(result, buffer, buflen, errnop);
300 0 : sss_nss_unlock();
301 :
302 0 : return nret;
303 : }
304 :
305 0 : enum nss_status _nss_sss_endnetgrent(struct __netgrent *result)
306 : {
307 : enum nss_status nret;
308 : int errnop;
309 :
310 0 : sss_nss_lock();
311 :
312 : /* make sure we do not have leftovers, and release memory */
313 0 : CLEAR_NETGRENT_DATA(result);
314 :
315 0 : nret = sss_nss_make_request(SSS_NSS_ENDNETGRENT,
316 : NULL, NULL, NULL, &errnop);
317 0 : if (nret != NSS_STATUS_SUCCESS) {
318 0 : errno = errnop;
319 : }
320 :
321 0 : sss_nss_unlock();
322 0 : return nret;
323 : }
|