Line data Source code
1 : /*
2 : Authors:
3 : Jakub Hrozek <jhrozek@redhat.com>
4 :
5 : Copyright (C) 2012 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <errno.h>
22 : #include <stdlib.h>
23 :
24 : #include "sss_client/autofs/sss_autofs_private.h"
25 : #include "sss_client/sss_cli.h"
26 :
27 : /* Historically, autofs map names were just file names. Direct key names
28 : * may be full directory paths
29 : */
30 : #define MAX_AUTOMNTMAPNAME_LEN NAME_MAX
31 : #define MAX_AUTOMNTKEYNAME_LEN PATH_MAX
32 :
33 : /* How many entries shall _sss_getautomntent_r retreive at once */
34 : #define GETAUTOMNTENT_MAX_ENTRIES 512
35 :
36 : struct automtent {
37 : char *mapname;
38 : size_t cursor;
39 : };
40 :
41 : static struct sss_getautomntent_data {
42 : char *mapname;
43 : size_t len;
44 : size_t ptr;
45 : uint8_t *data;
46 : } sss_getautomntent_data;
47 :
48 : static void
49 0 : sss_getautomntent_data_clean(void)
50 : {
51 0 : free(sss_getautomntent_data.data);
52 0 : free(sss_getautomntent_data.mapname);
53 0 : memset(&sss_getautomntent_data, 0, sizeof(struct sss_getautomntent_data));
54 0 : }
55 :
56 : errno_t
57 0 : _sss_setautomntent(const char *mapname, void **context)
58 : {
59 : errno_t ret;
60 : int errnop;
61 : struct automtent *ctx;
62 : char *name;
63 : size_t name_len;
64 : struct sss_cli_req_data rd;
65 0 : uint8_t *repbuf = NULL;
66 : size_t replen;
67 0 : uint32_t num_results = 0;
68 :
69 0 : if (!mapname) return EINVAL;
70 :
71 0 : sss_nss_lock();
72 :
73 : /* Make sure there are no leftovers from previous runs */
74 0 : sss_getautomntent_data_clean();
75 :
76 0 : ret = sss_strnlen(mapname, MAX_AUTOMNTMAPNAME_LEN, &name_len);
77 0 : if (ret != 0) {
78 0 : ret = EINVAL;
79 0 : goto out;
80 : }
81 :
82 0 : name = malloc(sizeof(char)*name_len + 1);
83 0 : if (name == NULL) {
84 0 : ret = ENOMEM;
85 0 : goto out;
86 : }
87 0 : strncpy(name, mapname, name_len + 1);
88 :
89 0 : rd.data = name;
90 0 : rd.len = name_len + 1;
91 :
92 0 : ret = sss_autofs_make_request(SSS_AUTOFS_SETAUTOMNTENT, &rd,
93 : &repbuf, &replen, &errnop);
94 0 : if (ret != SSS_STATUS_SUCCESS) {
95 0 : free(name);
96 0 : ret = errnop;
97 0 : goto out;
98 : }
99 :
100 : /* Get number of results from repbuf. */
101 0 : SAFEALIGN_COPY_UINT32(&num_results, repbuf, NULL);
102 :
103 : /* no results if not found */
104 0 : if (num_results == 0) {
105 0 : free(name);
106 0 : free(repbuf);
107 0 : ret = ENOENT;
108 0 : goto out;
109 : }
110 0 : free(repbuf);
111 :
112 0 : ctx = malloc(sizeof(struct automtent));
113 0 : if (!ctx) {
114 0 : free(name);
115 0 : ret = ENOMEM;
116 0 : goto out;
117 : }
118 :
119 0 : ctx->mapname = strdup(name);
120 0 : if (!ctx->mapname) {
121 0 : free(name);
122 0 : free(ctx);
123 0 : ret = ENOMEM;
124 0 : goto out;
125 : }
126 0 : ctx->cursor = 0;
127 0 : free(name);
128 :
129 0 : *context = ctx;
130 0 : ret = 0;
131 : out:
132 0 : sss_nss_unlock();
133 0 : return ret;
134 : }
135 :
136 : static errno_t
137 0 : sss_getautomntent_data_return(const char *mapname, char **_key, char **_value)
138 : {
139 : size_t dp;
140 0 : uint32_t len = 0;
141 0 : char *key = NULL;
142 : uint32_t keylen;
143 0 : char *value = NULL;
144 : uint32_t vallen;
145 : errno_t ret;
146 :
147 0 : if (sss_getautomntent_data.mapname == NULL ||
148 0 : sss_getautomntent_data.data == NULL ||
149 0 : sss_getautomntent_data.ptr >= sss_getautomntent_data.len) {
150 : /* We're done with this buffer */
151 0 : ret = ENOENT;
152 0 : goto done;
153 : }
154 :
155 0 : ret = strcmp(mapname, sss_getautomntent_data.mapname);
156 0 : if (ret != EOK) {
157 : /* The map we're looking for is not cached. Let responder
158 : * do an implicit setautomntent */
159 0 : ret = ENOENT;
160 0 : goto done;
161 : }
162 :
163 0 : dp = sss_getautomntent_data.ptr;
164 :
165 0 : SAFEALIGN_COPY_UINT32(&len, sss_getautomntent_data.data+dp, &dp);
166 0 : if (len + sss_getautomntent_data.ptr > sss_getautomntent_data.len) {
167 : /* len is bigger than the buffer */
168 0 : ret = EIO;
169 0 : goto done;
170 : }
171 :
172 0 : if (len == 0) {
173 : /* There are no more records. */
174 0 : *_key = NULL;
175 0 : *_value = NULL;
176 0 : ret = ENOENT;
177 0 : goto done;
178 : }
179 :
180 0 : SAFEALIGN_COPY_UINT32(&keylen, sss_getautomntent_data.data+dp, &dp);
181 0 : if (keylen + dp > sss_getautomntent_data.len) {
182 0 : ret = EIO;
183 0 : goto done;
184 : }
185 :
186 0 : key = malloc(keylen);
187 0 : if (!key) {
188 0 : ret = ENOMEM;
189 0 : goto done;
190 : }
191 :
192 0 : safealign_memcpy(key, sss_getautomntent_data.data+dp, keylen, &dp);
193 :
194 0 : SAFEALIGN_COPY_UINT32(&vallen, sss_getautomntent_data.data+dp, &dp);
195 0 : if (vallen + dp > sss_getautomntent_data.len) {
196 0 : ret = EIO;
197 0 : goto done;
198 : }
199 :
200 0 : value = malloc(vallen);
201 0 : if (!value) {
202 0 : ret = ENOMEM;
203 0 : goto done;
204 : }
205 :
206 0 : safealign_memcpy(value, sss_getautomntent_data.data+dp, vallen, &dp);
207 :
208 0 : sss_getautomntent_data.ptr = dp;
209 0 : *_key = key;
210 0 : *_value = value;
211 0 : return EOK;
212 :
213 : done:
214 0 : free(key);
215 0 : free(value);
216 0 : sss_getautomntent_data_clean();
217 0 : return ret;
218 : }
219 :
220 : /* The repbuf is owned by the sss_getautomntent_data once this
221 : * function is called */
222 : static errno_t
223 0 : sss_getautomntent_data_save(const char *mapname, uint8_t **repbuf, size_t replen)
224 : {
225 : size_t rp;
226 : uint32_t num;
227 :
228 0 : rp = 0;
229 0 : SAFEALIGN_COPY_UINT32(&num, *repbuf+rp, &rp);
230 0 : if (num == 0) {
231 0 : free(*repbuf);
232 0 : return ENOENT;
233 : }
234 :
235 0 : sss_getautomntent_data.mapname = strdup(mapname);
236 0 : if (sss_getautomntent_data.mapname == NULL) {
237 0 : free(*repbuf);
238 0 : return ENOENT;
239 : }
240 :
241 0 : sss_getautomntent_data.data = *repbuf;
242 0 : sss_getautomntent_data.len = replen;
243 0 : sss_getautomntent_data.ptr = rp;
244 0 : *repbuf = NULL;
245 0 : return EOK;
246 : }
247 :
248 : errno_t
249 0 : _sss_getautomntent_r(char **key, char **value, void *context)
250 : {
251 : int errnop;
252 : errno_t ret;
253 : size_t name_len;
254 : struct sss_cli_req_data rd;
255 0 : uint8_t *repbuf = NULL;
256 : size_t replen;
257 : struct automtent *ctx;
258 0 : size_t ctr = 0;
259 0 : size_t data_len = 0;
260 : uint8_t *data;
261 :
262 0 : sss_nss_lock();
263 :
264 0 : ctx = (struct automtent *) context;
265 0 : if (!ctx) {
266 0 : ret = EINVAL;
267 0 : goto out;
268 : }
269 :
270 : /* Be paranoid in case someone tries to smuggle in a huge map name */
271 0 : ret = sss_strnlen(ctx->mapname, MAX_AUTOMNTMAPNAME_LEN, &name_len);
272 0 : if (ret != 0) {
273 0 : ret = EINVAL;
274 0 : goto out;
275 : }
276 :
277 0 : ret = sss_getautomntent_data_return(ctx->mapname, key, value);
278 0 : if (ret == EOK) {
279 : /* The results are available from cache. Just advance the
280 : * cursor and return. */
281 0 : ctx->cursor++;
282 0 : ret = 0;
283 0 : goto out;
284 : }
285 : /* Don't try to handle any error codes, just go to the responder again */
286 :
287 0 : data_len = sizeof(uint32_t) + /* mapname len */
288 : name_len + 1 + /* mapname\0 */
289 0 : sizeof(uint32_t) + /* index into the map */
290 : sizeof(uint32_t); /* num entries to retreive */
291 :
292 0 : data = malloc(data_len);
293 0 : if (!data) {
294 0 : ret = ENOMEM;
295 0 : goto out;
296 : }
297 :
298 0 : SAFEALIGN_SET_UINT32(data, name_len, &ctr);
299 :
300 0 : safealign_memcpy(data+ctr, ctx->mapname, name_len + 1, &ctr);
301 :
302 0 : SAFEALIGN_SET_UINT32(data+ctr, ctx->cursor, &ctr);
303 :
304 0 : SAFEALIGN_SET_UINT32(data+ctr, GETAUTOMNTENT_MAX_ENTRIES, &ctr);
305 :
306 0 : rd.data = data;
307 0 : rd.len = data_len;
308 :
309 0 : ret = sss_autofs_make_request(SSS_AUTOFS_GETAUTOMNTENT, &rd,
310 : &repbuf, &replen, &errnop);
311 0 : free(data);
312 0 : if (ret != SSS_STATUS_SUCCESS) {
313 0 : ret = errnop;
314 0 : goto out;
315 : }
316 :
317 : /* Got reply, let's save it and return from "cache" */
318 0 : ret = sss_getautomntent_data_save(ctx->mapname, &repbuf, replen);
319 0 : if (ret == ENOENT) {
320 : /* No results */
321 0 : *key = NULL;
322 0 : *value = NULL;
323 0 : goto out;
324 0 : } else if (ret != EOK) {
325 : /* Unexpected error */
326 0 : goto out;
327 : }
328 :
329 0 : ret = sss_getautomntent_data_return(ctx->mapname, key, value);
330 0 : if (ret != EOK) {
331 0 : goto out;
332 : }
333 :
334 : /* Advance the cursor so that we'll fetch the next map
335 : * next time getautomntent is called */
336 0 : ctx->cursor++;
337 0 : ret = 0;
338 : out:
339 0 : sss_nss_unlock();
340 0 : return ret;
341 : }
342 :
343 : errno_t
344 0 : _sss_getautomntbyname_r(const char *key, char **value, void *context)
345 : {
346 : int errnop;
347 : errno_t ret;
348 : struct automtent *ctx;
349 : size_t key_len;
350 : size_t name_len;
351 0 : size_t data_len = 0;
352 : uint8_t *data;
353 0 : size_t ctr = 0;
354 : struct sss_cli_req_data rd;
355 0 : uint8_t *repbuf = NULL;
356 : size_t replen;
357 :
358 : char *buf;
359 : uint32_t len;
360 : uint32_t vallen;
361 : size_t rp;
362 :
363 0 : sss_nss_lock();
364 :
365 0 : ctx = (struct automtent *) context;
366 0 : if (!ctx || !key) {
367 0 : ret = EINVAL;
368 0 : goto out;
369 : }
370 :
371 : /* Be paranoid in case someone tries to smuggle in a huge map name */
372 0 : ret = sss_strnlen(ctx->mapname, MAX_AUTOMNTMAPNAME_LEN, &name_len);
373 0 : if (ret != 0) {
374 0 : ret = EINVAL;
375 0 : goto out;
376 : }
377 :
378 0 : ret = sss_strnlen(key, MAX_AUTOMNTKEYNAME_LEN, &key_len);
379 0 : if (ret != 0) {
380 0 : ret = EINVAL;
381 0 : goto out;
382 : }
383 :
384 :
385 0 : data_len = sizeof(uint32_t) + /* mapname len */
386 : name_len + 1 + /* mapname\0 */
387 0 : sizeof(uint32_t) + /* keyname len */
388 : key_len + 1; /* keyname\0 */
389 :
390 0 : data = malloc(data_len);
391 0 : if (!data) {
392 0 : ret = ENOMEM;
393 0 : goto out;
394 : }
395 :
396 0 : SAFEALIGN_SET_UINT32(data, name_len, &ctr);
397 :
398 0 : safealign_memcpy(data+ctr, ctx->mapname, name_len + 1, &ctr);
399 :
400 0 : SAFEALIGN_SET_UINT32(data+ctr, key_len, &ctr);
401 :
402 0 : safealign_memcpy(data+ctr, key, key_len + 1, &ctr);
403 :
404 0 : rd.data = data;
405 0 : rd.len = data_len;
406 :
407 0 : ret = sss_autofs_make_request(SSS_AUTOFS_GETAUTOMNTBYNAME, &rd,
408 : &repbuf, &replen, &errnop);
409 0 : free(data);
410 0 : if (ret != SSS_STATUS_SUCCESS) {
411 0 : ret = errnop;
412 0 : goto out;
413 : }
414 :
415 : /* Got reply, let's parse it */
416 0 : rp = 0;
417 0 : SAFEALIGN_COPY_UINT32(&len, repbuf+rp, &rp);
418 0 : if (len == 0) {
419 : /* No data */
420 0 : *value = NULL;
421 0 : ret = ENOENT;
422 0 : goto out;
423 : }
424 :
425 0 : SAFEALIGN_COPY_UINT32(&vallen, repbuf+rp, &rp);
426 0 : if (vallen > len-rp) {
427 0 : ret = EIO;
428 0 : goto out;
429 : }
430 :
431 0 : buf = malloc(vallen);
432 0 : if (!buf) {
433 0 : ret = ENOMEM;
434 0 : goto out;
435 : }
436 :
437 0 : safealign_memcpy(buf, repbuf+rp, vallen, &rp);
438 0 : *value = buf;
439 :
440 0 : ret = 0;
441 : out:
442 0 : free(repbuf);
443 0 : sss_nss_unlock();
444 0 : return ret;
445 : }
446 :
447 : errno_t
448 0 : _sss_endautomntent(void **context)
449 : {
450 : struct automtent *fctx;
451 : errno_t ret;
452 : int errnop;
453 :
454 0 : if (!context) return 0;
455 :
456 0 : sss_nss_lock();
457 :
458 0 : sss_getautomntent_data_clean();
459 :
460 0 : fctx = (struct automtent *) *context;
461 :
462 0 : if (fctx != NULL) {
463 0 : free(fctx->mapname);
464 0 : free(fctx);
465 : }
466 :
467 0 : ret = sss_autofs_make_request(SSS_AUTOFS_ENDAUTOMNTENT,
468 : NULL, NULL, NULL, &errnop);
469 0 : if (ret != SSS_STATUS_SUCCESS) {
470 0 : ret = errnop;
471 0 : goto out;
472 : }
473 :
474 0 : ret = 0;
475 : out:
476 0 : sss_nss_unlock();
477 0 : return ret;
478 : }
|