~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to lib/nss_wrapper/nss_wrapper.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org>
 
3
 *
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 *
 
10
 * 1. Redistributions of source code must retain the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer.
 
12
 *
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in the
 
15
 *    documentation and/or other materials provided with the distribution.
 
16
 *
 
17
 * 3. Neither the name of the author nor the names of its contributors
 
18
 *    may be used to endorse or promote products derived from this software
 
19
 *    without specific prior written permission.
 
20
 *
 
21
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
31
 * SUCH DAMAGE.
 
32
 */
 
33
 
 
34
#ifdef _SAMBA_BUILD_
 
35
 
 
36
#define NSS_WRAPPER_NOT_REPLACE
 
37
#include "../replace/replace.h"
 
38
#include "system/passwd.h"
 
39
#include "system/filesys.h"
 
40
 
 
41
#else /* _SAMBA_BUILD_ */
 
42
 
 
43
#error nss_wrapper_only_supported_in_samba_yet
 
44
 
 
45
#endif
 
46
 
 
47
#ifndef _PUBLIC_
 
48
#define _PUBLIC_
 
49
#endif
 
50
 
 
51
/* not all systems have _r functions... */
 
52
#ifndef HAVE_GETPWNAM_R
 
53
#define getpwnam_r(name, pwdst, buf, buflen, pwdstp)    ENOSYS
 
54
#endif
 
55
#ifndef HAVE_GETPWUID_R
 
56
#define getpwuid_r(uid, pwdst, buf, buflen, pwdstp)     ENOSYS
 
57
#endif
 
58
#ifndef HAVE_GETPWENT_R
 
59
#define getpwent_r(pwdst, buf, buflen, pwdstp)          ENOSYS
 
60
#endif
 
61
#ifndef HAVE_GETGRNAM_R
 
62
#define getgrnam_r(name, grdst, buf, buflen, grdstp)    ENOSYS
 
63
#endif
 
64
#ifndef HAVE_GETGRUID_R
 
65
#define getgrgid_r(uid, grdst, buf, buflen, grdstp)     ENOSYS
 
66
#endif
 
67
#ifndef HAVE_GETGRENT_R
 
68
#define getgrent_r(grdst, buf, buflen, grdstp)          ENOSYS
 
69
#endif
 
70
 
 
71
/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
 
72
 * for now */
 
73
#define REWRITE_CALLS
 
74
 
 
75
#ifdef REWRITE_CALLS
 
76
 
 
77
#define real_getpwnam           getpwnam
 
78
#define real_getpwnam_r         getpwnam_r
 
79
#define real_getpwuid           getpwuid
 
80
#define real_getpwuid_r         getpwuid_r
 
81
 
 
82
#define real_setpwent           setpwent
 
83
#define real_getpwent           getpwent
 
84
#define real_getpwent_r         getpwent_r
 
85
#define real_endpwent           endpwent
 
86
 
 
87
/*
 
88
#define real_getgrlst           getgrlst
 
89
#define real_getgrlst_r         getgrlst_r
 
90
#define real_initgroups_dyn     initgroups_dyn
 
91
*/
 
92
#define real_initgroups         initgroups
 
93
 
 
94
#define real_getgrnam           getgrnam
 
95
#define real_getgrnam_r         getgrnam_r
 
96
#define real_getgrgid           getgrgid
 
97
#define real_getgrgid_r         getgrgid_r
 
98
 
 
99
#define real_setgrent           setgrent
 
100
#define real_getgrent           getgrent
 
101
#define real_getgrent_r         getgrent_r
 
102
#define real_endgrent           endgrent
 
103
 
 
104
#endif
 
105
 
 
106
#if 0
 
107
# ifdef DEBUG
 
108
# define NWRAP_ERROR(args)      DEBUG(0, args)
 
109
# else
 
110
# define NWRAP_ERROR(args)      printf args
 
111
# endif
 
112
#else
 
113
#define NWRAP_ERROR(args)
 
114
#endif
 
115
 
 
116
#if 0
 
117
# ifdef DEBUG
 
118
# define NWRAP_DEBUG(args)      DEBUG(0, args)
 
119
# else
 
120
# define NWRAP_DEBUG(args)      printf args
 
121
# endif
 
122
#else
 
123
#define NWRAP_DEBUG(args)
 
124
#endif
 
125
 
 
126
#if 0
 
127
# ifdef DEBUG
 
128
# define NWRAP_VERBOSE(args)    DEBUG(0, args)
 
129
# else
 
130
# define NWRAP_VERBOSE(args)    printf args
 
131
# endif
 
132
#else
 
133
#define NWRAP_VERBOSE(args)
 
134
#endif
 
135
 
 
136
struct nwrap_cache {
 
137
        const char *path;
 
138
        int fd;
 
139
        struct stat st;
 
140
        uint8_t *buf;
 
141
        void *private_data;
 
142
        bool (*parse_line)(struct nwrap_cache *, char *line);
 
143
        void (*unload)(struct nwrap_cache *);
 
144
};
 
145
 
 
146
struct nwrap_pw {
 
147
        struct nwrap_cache *cache;
 
148
 
 
149
        struct passwd *list;
 
150
        int num;
 
151
        int idx;
 
152
};
 
153
 
 
154
struct nwrap_cache __nwrap_cache_pw;
 
155
struct nwrap_pw nwrap_pw_global;
 
156
 
 
157
static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
 
158
static void nwrap_pw_unload(struct nwrap_cache *nwrap);
 
159
 
 
160
struct nwrap_gr {
 
161
        struct nwrap_cache *cache;
 
162
 
 
163
        struct group *list;
 
164
        int num;
 
165
        int idx;
 
166
};
 
167
 
 
168
struct nwrap_cache __nwrap_cache_gr;
 
169
struct nwrap_gr nwrap_gr_global;
 
170
 
 
171
static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
 
172
static void nwrap_gr_unload(struct nwrap_cache *nwrap);
 
173
 
 
174
static void nwrap_init(void)
 
175
{
 
176
        static bool initialized;
 
177
 
 
178
        if (initialized) return;
 
179
        initialized = true;
 
180
 
 
181
        nwrap_pw_global.cache = &__nwrap_cache_pw;
 
182
 
 
183
        nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
 
184
        nwrap_pw_global.cache->fd = -1;
 
185
        nwrap_pw_global.cache->private_data = &nwrap_pw_global;
 
186
        nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
 
187
        nwrap_pw_global.cache->unload = nwrap_pw_unload;
 
188
 
 
189
        nwrap_gr_global.cache = &__nwrap_cache_gr;
 
190
 
 
191
        nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
 
192
        nwrap_gr_global.cache->fd = -1;
 
193
        nwrap_gr_global.cache->private_data = &nwrap_gr_global;
 
194
        nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
 
195
        nwrap_gr_global.cache->unload = nwrap_gr_unload;
 
196
}
 
197
 
 
198
static bool nwrap_enabled(void)
 
199
{
 
200
        nwrap_init();
 
201
 
 
202
        if (!nwrap_pw_global.cache->path) {
 
203
                return false;
 
204
        }
 
205
        if (nwrap_pw_global.cache->path[0] == '\0') {
 
206
                return false;
 
207
        }
 
208
        if (!nwrap_gr_global.cache->path) {
 
209
                return false;
 
210
        }
 
211
        if (nwrap_gr_global.cache->path[0] == '\0') {
 
212
                return false;
 
213
        }
 
214
 
 
215
        return true;
 
216
}
 
217
 
 
218
static bool nwrap_parse_file(struct nwrap_cache *nwrap)
 
219
{
 
220
        int ret;
 
221
        uint8_t *buf = NULL;
 
222
        char *nline;
 
223
 
 
224
        if (nwrap->st.st_size == 0) {
 
225
                NWRAP_DEBUG(("%s: size == 0\n",
 
226
                             __location__));
 
227
                goto done;
 
228
        }
 
229
 
 
230
        if (nwrap->st.st_size > INT32_MAX) {
 
231
                NWRAP_ERROR(("%s: size[%u] larger than INT32_MAX\n",
 
232
                             __location__, (unsigned)nwrap->st.st_size));
 
233
                goto failed;
 
234
        }
 
235
 
 
236
        ret = lseek(nwrap->fd, 0, SEEK_SET);
 
237
        if (ret != 0) {
 
238
                NWRAP_ERROR(("%s: lseek - %d\n",__location__,ret));
 
239
                goto failed;
 
240
        }
 
241
 
 
242
        buf = (uint8_t *)malloc(nwrap->st.st_size + 1);
 
243
        if (!buf) {
 
244
                NWRAP_ERROR(("%s: malloc failed\n",__location__));
 
245
                goto failed;
 
246
        }
 
247
 
 
248
        ret = read(nwrap->fd, buf, nwrap->st.st_size);
 
249
        if (ret != nwrap->st.st_size) {
 
250
                NWRAP_ERROR(("%s: read(%u) gave %d\n",
 
251
                             __location__, (unsigned)nwrap->st.st_size, ret));
 
252
                goto failed;
 
253
        }
 
254
 
 
255
        buf[nwrap->st.st_size] = '\0';
 
256
 
 
257
        nline = (char *)buf;
 
258
        while (nline && nline[0]) {
 
259
                char *line;
 
260
                char *e;
 
261
                bool ok;
 
262
 
 
263
                line = nline;
 
264
                nline = NULL;
 
265
 
 
266
                e = strchr(line, '\n');
 
267
                if (e) {
 
268
                        e[0] = '\0';
 
269
                        e++;
 
270
                        if (e[0] == '\r') {
 
271
                                e[0] = '\0';
 
272
                                e++;
 
273
                        }
 
274
                        nline = e;
 
275
                }
 
276
 
 
277
                NWRAP_VERBOSE(("%s:'%s'\n",__location__, line));
 
278
 
 
279
                if (strlen(line) == 0) {
 
280
                        continue;
 
281
                }
 
282
 
 
283
                ok = nwrap->parse_line(nwrap, line);
 
284
                if (!ok) {
 
285
                        goto failed;
 
286
                }
 
287
        }
 
288
 
 
289
done:
 
290
        nwrap->buf = buf;
 
291
        return true;
 
292
 
 
293
failed:
 
294
        if (buf) free(buf);
 
295
        return false;
 
296
}
 
297
 
 
298
static void nwrap_cache_unload(struct nwrap_cache *nwrap)
 
299
{
 
300
        nwrap->unload(nwrap);
 
301
 
 
302
        if (nwrap->buf) free(nwrap->buf);
 
303
 
 
304
        nwrap->buf = NULL;
 
305
}
 
306
 
 
307
static void nwrap_cache_reload(struct nwrap_cache *nwrap)
 
308
{
 
309
        struct stat st;
 
310
        int ret;
 
311
        bool ok;
 
312
        bool retried = false;
 
313
 
 
314
reopen:
 
315
        if (nwrap->fd < 0) {
 
316
                nwrap->fd = open(nwrap->path, O_RDONLY);
 
317
                if (nwrap->fd < 0) {
 
318
                        NWRAP_ERROR(("%s: unable to open '%s' readonly %d:%s\n",
 
319
                                     __location__,
 
320
                                     nwrap->path, nwrap->fd,
 
321
                                     strerror(errno)));
 
322
                        return;
 
323
                }
 
324
                NWRAP_VERBOSE(("%s: open '%s'\n", __location__, nwrap->path));
 
325
        }
 
326
 
 
327
        ret = fstat(nwrap->fd, &st);
 
328
        if (ret != 0) {
 
329
                NWRAP_ERROR(("%s: fstat(%s) - %d:%s\n",
 
330
                             __location__,
 
331
                             nwrap->path,
 
332
                             ret, strerror(errno)));
 
333
                return;
 
334
        }
 
335
 
 
336
        if (retried == false && st.st_nlink == 0) {
 
337
                /* maybe someone has replaced the file... */
 
338
                NWRAP_DEBUG(("%s: st_nlink == 0, reopen %s\n",
 
339
                             __location__, nwrap->path));
 
340
                retried = true;
 
341
                memset(&nwrap->st, 0, sizeof(nwrap->st));
 
342
                close(nwrap->fd);
 
343
                nwrap->fd = -1;
 
344
                goto reopen;
 
345
        }
 
346
 
 
347
        if (st.st_mtime == nwrap->st.st_mtime) {
 
348
                NWRAP_VERBOSE(("%s: st_mtime[%u] hasn't changed, skip reload\n",
 
349
                               __location__, (unsigned)st.st_mtime));
 
350
                return;
 
351
        }
 
352
        NWRAP_DEBUG(("%s: st_mtime has changed [%u] => [%u], start reload\n",
 
353
                     __location__, (unsigned)st.st_mtime,
 
354
                     (unsigned)nwrap->st.st_mtime));
 
355
 
 
356
        nwrap->st = st;
 
357
 
 
358
        nwrap_cache_unload(nwrap);
 
359
 
 
360
        ok = nwrap_parse_file(nwrap);
 
361
        if (!ok) {
 
362
                NWRAP_ERROR(("%s: failed to reload %s\n",
 
363
                             __location__, nwrap->path));
 
364
                nwrap_cache_unload(nwrap);
 
365
        }
 
366
        NWRAP_DEBUG(("%s: reloaded %s\n",
 
367
                     __location__, nwrap->path));
 
368
}
 
369
 
 
370
/*
 
371
 * the caller has to call nwrap_unload() on failure
 
372
 */
 
373
static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
 
374
{
 
375
        struct nwrap_pw *nwrap_pw;
 
376
        char *c;
 
377
        char *p;
 
378
        char *e;
 
379
        struct passwd *pw;
 
380
        size_t list_size;
 
381
 
 
382
        nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
 
383
 
 
384
        list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
 
385
        pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
 
386
        if (!pw) {
 
387
                NWRAP_ERROR(("%s:realloc(%u) failed\n",
 
388
                             __location__, list_size));
 
389
                return false;
 
390
        }
 
391
        nwrap_pw->list = pw;
 
392
 
 
393
        pw = &nwrap_pw->list[nwrap_pw->num];
 
394
 
 
395
        c = line;
 
396
 
 
397
        /* name */
 
398
        p = strchr(c, ':');
 
399
        if (!p) {
 
400
                NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 
401
                             __location__, line, c));
 
402
                return false;
 
403
        }
 
404
        *p = '\0';
 
405
        p++;
 
406
        pw->pw_name = c;
 
407
        c = p;
 
408
 
 
409
        NWRAP_VERBOSE(("name[%s]\n", pw->pw_name));
 
410
 
 
411
        /* password */
 
412
        p = strchr(c, ':');
 
413
        if (!p) {
 
414
                NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 
415
                             __location__, line, c));
 
416
                return false;
 
417
        }
 
418
        *p = '\0';
 
419
        p++;
 
420
        pw->pw_passwd = c;
 
421
        c = p;
 
422
 
 
423
        NWRAP_VERBOSE(("password[%s]\n", pw->pw_passwd));
 
424
 
 
425
        /* uid */
 
426
        p = strchr(c, ':');
 
427
        if (!p) {
 
428
                NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 
429
                             __location__, line, c));
 
430
                return false;
 
431
        }
 
432
        *p = '\0';
 
433
        p++;
 
434
        e = NULL;
 
435
        pw->pw_uid = (uid_t)strtoul(c, &e, 10);
 
436
        if (c == e) {
 
437
                NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 
438
                             __location__, line, c, strerror(errno)));
 
439
                return false;
 
440
        }
 
441
        if (e == NULL) {
 
442
                NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 
443
                             __location__, line, c, strerror(errno)));
 
444
                return false;
 
445
        }
 
446
        if (e[0] != '\0') {
 
447
                NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 
448
                             __location__, line, c, strerror(errno)));
 
449
                return false;
 
450
        }
 
451
        c = p;
 
452
 
 
453
        NWRAP_VERBOSE(("uid[%u]\n", pw->pw_uid));
 
454
 
 
455
        /* gid */
 
456
        p = strchr(c, ':');
 
457
        if (!p) {
 
458
                NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 
459
                             __location__, line, c));
 
460
                return false;
 
461
        }
 
462
        *p = '\0';
 
463
        p++;
 
464
        e = NULL;
 
465
        pw->pw_gid = (gid_t)strtoul(c, &e, 10);
 
466
        if (c == e) {
 
467
                NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 
468
                             __location__, line, c, strerror(errno)));
 
469
                return false;
 
470
        }
 
471
        if (e == NULL) {
 
472
                NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 
473
                             __location__, line, c, strerror(errno)));
 
474
                return false;
 
475
        }
 
476
        if (e[0] != '\0') {
 
477
                NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 
478
                             __location__, line, c, strerror(errno)));
 
479
                return false;
 
480
        }
 
481
        c = p;
 
482
 
 
483
        NWRAP_VERBOSE(("gid[%u]\n", pw->pw_gid));
 
484
 
 
485
        /* gecos */
 
486
        p = strchr(c, ':');
 
487
        if (!p) {
 
488
                NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 
489
                             __location__, line, c));
 
490
                return false;
 
491
        }
 
492
        *p = '\0';
 
493
        p++;
 
494
        pw->pw_gecos = c;
 
495
        c = p;
 
496
 
 
497
        NWRAP_VERBOSE(("gecos[%s]\n", pw->pw_gecos));
 
498
 
 
499
        /* dir */
 
500
        p = strchr(c, ':');
 
501
        if (!p) {
 
502
                NWRAP_ERROR(("%s:'%s'\n",__location__,c));
 
503
                return false;
 
504
        }
 
505
        *p = '\0';
 
506
        p++;
 
507
        pw->pw_dir = c;
 
508
        c = p;
 
509
 
 
510
        NWRAP_VERBOSE(("dir[%s]\n", pw->pw_dir));
 
511
 
 
512
        /* shell */
 
513
        pw->pw_shell = c;
 
514
        NWRAP_VERBOSE(("shell[%s]\n", pw->pw_shell));
 
515
 
 
516
        NWRAP_DEBUG(("add user[%s:%s:%u:%u:%s:%s:%s]\n",
 
517
                     pw->pw_name, pw->pw_passwd,
 
518
                     pw->pw_uid, pw->pw_gid,
 
519
                     pw->pw_gecos, pw->pw_dir, pw->pw_shell));
 
520
 
 
521
        nwrap_pw->num++;
 
522
        return true;
 
523
}
 
524
 
 
525
static void nwrap_pw_unload(struct nwrap_cache *nwrap)
 
526
{
 
527
        struct nwrap_pw *nwrap_pw;
 
528
        nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
 
529
 
 
530
        if (nwrap_pw->list) free(nwrap_pw->list);
 
531
 
 
532
        nwrap_pw->list = NULL;
 
533
        nwrap_pw->num = 0;
 
534
        nwrap_pw->idx = 0;
 
535
}
 
536
 
 
537
static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
 
538
                           char *buf, size_t buflen, struct passwd **dstp)
 
539
{
 
540
        char *first;
 
541
        char *last;
 
542
        off_t ofs;
 
543
 
 
544
        first = src->pw_name;
 
545
 
 
546
        last = src->pw_shell;
 
547
        while (*last) last++;
 
548
 
 
549
        ofs = PTR_DIFF(last + 1, first);
 
550
 
 
551
        if (ofs > buflen) {
 
552
                return ERANGE;
 
553
        }
 
554
 
 
555
        memcpy(buf, first, ofs);
 
556
 
 
557
        ofs = PTR_DIFF(src->pw_name, first);
 
558
        dst->pw_name = buf + ofs;
 
559
        ofs = PTR_DIFF(src->pw_passwd, first);
 
560
        dst->pw_passwd = buf + ofs;
 
561
        dst->pw_uid = src->pw_uid;
 
562
        dst->pw_gid = src->pw_gid;
 
563
        ofs = PTR_DIFF(src->pw_gecos, first);
 
564
        dst->pw_gecos = buf + ofs;
 
565
        ofs = PTR_DIFF(src->pw_dir, first);
 
566
        dst->pw_dir = buf + ofs;
 
567
        ofs = PTR_DIFF(src->pw_shell, first);
 
568
        dst->pw_shell = buf + ofs;
 
569
 
 
570
        if (dstp) {
 
571
                *dstp = dst;
 
572
        }
 
573
 
 
574
        return 0;
 
575
}
 
576
 
 
577
/*
 
578
 * the caller has to call nwrap_unload() on failure
 
579
 */
 
580
static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
 
581
{
 
582
        struct nwrap_gr *nwrap_gr;
 
583
        char *c;
 
584
        char *p;
 
585
        char *e;
 
586
        struct group *gr;
 
587
        size_t list_size;
 
588
        unsigned nummem;
 
589
 
 
590
        nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
 
591
 
 
592
        list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
 
593
        gr = (struct group *)realloc(nwrap_gr->list, list_size);
 
594
        if (!gr) {
 
595
                NWRAP_ERROR(("%s:realloc failed\n",__location__));
 
596
                return false;
 
597
        }
 
598
        nwrap_gr->list = gr;
 
599
 
 
600
        gr = &nwrap_gr->list[nwrap_gr->num];
 
601
 
 
602
        c = line;
 
603
 
 
604
        /* name */
 
605
        p = strchr(c, ':');
 
606
        if (!p) {
 
607
                NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 
608
                             __location__, line, c));
 
609
                return false;
 
610
        }
 
611
        *p = '\0';
 
612
        p++;
 
613
        gr->gr_name = c;
 
614
        c = p;
 
615
 
 
616
        NWRAP_VERBOSE(("name[%s]\n", gr->gr_name));
 
617
 
 
618
        /* password */
 
619
        p = strchr(c, ':');
 
620
        if (!p) {
 
621
                NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 
622
                             __location__, line, c));
 
623
                return false;
 
624
        }
 
625
        *p = '\0';
 
626
        p++;
 
627
        gr->gr_passwd = c;
 
628
        c = p;
 
629
 
 
630
        NWRAP_VERBOSE(("password[%s]\n", gr->gr_passwd));
 
631
 
 
632
        /* gid */
 
633
        p = strchr(c, ':');
 
634
        if (!p) {
 
635
                NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 
636
                             __location__, line, c));
 
637
                return false;
 
638
        }
 
639
        *p = '\0';
 
640
        p++;
 
641
        e = NULL;
 
642
        gr->gr_gid = (gid_t)strtoul(c, &e, 10);
 
643
        if (c == e) {
 
644
                NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 
645
                             __location__, line, c, strerror(errno)));
 
646
                return false;
 
647
        }
 
648
        if (e == NULL) {
 
649
                NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 
650
                             __location__, line, c, strerror(errno)));
 
651
                return false;
 
652
        }
 
653
        if (e[0] != '\0') {
 
654
                NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 
655
                             __location__, line, c, strerror(errno)));
 
656
                return false;
 
657
        }
 
658
        c = p;
 
659
 
 
660
        NWRAP_VERBOSE(("gid[%u]\n", gr->gr_gid));
 
661
 
 
662
        /* members */
 
663
        gr->gr_mem = (char **)malloc(sizeof(char *));
 
664
        if (!gr->gr_mem) {
 
665
                NWRAP_ERROR(("%s:calloc failed\n",__location__));
 
666
                return false;
 
667
        }
 
668
        gr->gr_mem[0] = NULL;
 
669
 
 
670
        for(nummem=0; p; nummem++) {
 
671
                char **m;
 
672
                size_t m_size;
 
673
                c = p;
 
674
                p = strchr(c, ',');
 
675
                if (p) {
 
676
                        *p = '\0';
 
677
                        p++;
 
678
                }
 
679
 
 
680
                if (strlen(c) == 0) {
 
681
                        break;
 
682
                }
 
683
 
 
684
                m_size = sizeof(char *) * (nummem+2);
 
685
                m = (char **)realloc(gr->gr_mem, m_size);
 
686
                if (!m) {
 
687
                        NWRAP_ERROR(("%s:realloc(%u) failed\n",
 
688
                                      __location__, m_size));
 
689
                        return false;
 
690
                }
 
691
                gr->gr_mem = m;
 
692
                gr->gr_mem[nummem] = c;
 
693
                gr->gr_mem[nummem+1] = NULL;
 
694
 
 
695
                NWRAP_VERBOSE(("member[%u]: '%s'\n", nummem, gr->gr_mem[nummem]));
 
696
        }
 
697
 
 
698
        NWRAP_DEBUG(("add group[%s:%s:%u:] with %u members\n",
 
699
                     gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem));
 
700
 
 
701
        nwrap_gr->num++;
 
702
        return true;
 
703
}
 
704
 
 
705
static void nwrap_gr_unload(struct nwrap_cache *nwrap)
 
706
{
 
707
        int i;
 
708
        struct nwrap_gr *nwrap_gr;
 
709
        nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
 
710
 
 
711
        if (nwrap_gr->list) {
 
712
                for (i=0; i < nwrap_gr->num; i++) {
 
713
                        if (nwrap_gr->list[i].gr_mem) {
 
714
                                free(nwrap_gr->list[i].gr_mem);
 
715
                        }
 
716
                }
 
717
                free(nwrap_gr->list);
 
718
        }
 
719
 
 
720
        nwrap_gr->list = NULL;
 
721
        nwrap_gr->num = 0;
 
722
        nwrap_gr->idx = 0;
 
723
}
 
724
 
 
725
static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
 
726
                           char *buf, size_t buflen, struct group **dstp)
 
727
{
 
728
        char *first;
 
729
        char **lastm;
 
730
        char *last;
 
731
        off_t ofsb;
 
732
        off_t ofsm;
 
733
        off_t ofs;
 
734
        unsigned i;
 
735
 
 
736
        first = src->gr_name;
 
737
 
 
738
        lastm = src->gr_mem;
 
739
        while (*lastm) lastm++;
 
740
 
 
741
        last = *lastm;
 
742
        while (*last) last++;
 
743
 
 
744
        ofsb = PTR_DIFF(last + 1, first);
 
745
        ofsm = PTR_DIFF(lastm + 1, src->gr_mem);
 
746
 
 
747
        if ((ofsb + ofsm) > buflen) {
 
748
                return ERANGE;
 
749
        }
 
750
 
 
751
        memcpy(buf, first, ofsb);
 
752
        memcpy(buf + ofsb, src->gr_mem, ofsm);
 
753
 
 
754
        ofs = PTR_DIFF(src->gr_name, first);
 
755
        dst->gr_name = buf + ofs;
 
756
        ofs = PTR_DIFF(src->gr_passwd, first);
 
757
        dst->gr_passwd = buf + ofs;
 
758
        dst->gr_gid = src->gr_gid;
 
759
 
 
760
        dst->gr_mem = (char **)(buf + ofsb);
 
761
        for (i=0; src->gr_mem[i]; i++) {
 
762
                ofs = PTR_DIFF(src->gr_mem[i], first);
 
763
                dst->gr_mem[i] = buf + ofs;
 
764
        }
 
765
 
 
766
        if (dstp) {
 
767
                *dstp = dst;
 
768
        }
 
769
 
 
770
        return 0;
 
771
}
 
772
 
 
773
/* user functions */
 
774
 
 
775
static struct passwd *nwrap_files_getpwnam(const char *name)
 
776
{
 
777
        int i;
 
778
 
 
779
        nwrap_cache_reload(nwrap_pw_global.cache);
 
780
 
 
781
        for (i=0; i<nwrap_pw_global.num; i++) {
 
782
                if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
 
783
                        NWRAP_DEBUG(("%s: user[%s] found\n",
 
784
                                     __location__, name));
 
785
                        return &nwrap_pw_global.list[i];
 
786
                }
 
787
                NWRAP_VERBOSE(("%s: user[%s] does not match [%s]\n",
 
788
                               __location__, name,
 
789
                               nwrap_pw_global.list[i].pw_name));
 
790
        }
 
791
 
 
792
        NWRAP_DEBUG(("%s: user[%s] not found\n", __location__, name));
 
793
 
 
794
        errno = ENOENT;
 
795
        return NULL;
 
796
}
 
797
 
 
798
_PUBLIC_ struct passwd *nwrap_getpwnam(const char *name)
 
799
{
 
800
        if (!nwrap_enabled()) {
 
801
                return real_getpwnam(name);
 
802
        }
 
803
 
 
804
        return nwrap_files_getpwnam(name);
 
805
}
 
806
 
 
807
static int nwrap_files_getpwnam_r(const char *name, struct passwd *pwdst,
 
808
                                  char *buf, size_t buflen, struct passwd **pwdstp)
 
809
{
 
810
        struct passwd *pw;
 
811
 
 
812
        pw = nwrap_getpwnam(name);
 
813
        if (!pw) {
 
814
                if (errno == 0) {
 
815
                        return ENOENT;
 
816
                }
 
817
                return errno;
 
818
        }
 
819
 
 
820
        return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
 
821
}
 
822
 
 
823
_PUBLIC_ int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
 
824
                              char *buf, size_t buflen, struct passwd **pwdstp)
 
825
{
 
826
        if (!nwrap_enabled()) {
 
827
                return real_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
 
828
        }
 
829
 
 
830
        return nwrap_files_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
 
831
}
 
832
 
 
833
static struct passwd *nwrap_files_getpwuid(uid_t uid)
 
834
{
 
835
        int i;
 
836
 
 
837
        nwrap_cache_reload(nwrap_pw_global.cache);
 
838
 
 
839
        for (i=0; i<nwrap_pw_global.num; i++) {
 
840
                if (nwrap_pw_global.list[i].pw_uid == uid) {
 
841
                        NWRAP_DEBUG(("%s: uid[%u] found\n",
 
842
                                     __location__, uid));
 
843
                        return &nwrap_pw_global.list[i];
 
844
                }
 
845
                NWRAP_VERBOSE(("%s: uid[%u] does not match [%u]\n",
 
846
                               __location__, uid,
 
847
                               nwrap_pw_global.list[i].pw_uid));
 
848
        }
 
849
 
 
850
        NWRAP_DEBUG(("%s: uid[%u] not found\n", __location__, uid));
 
851
 
 
852
        errno = ENOENT;
 
853
        return NULL;
 
854
}
 
855
 
 
856
_PUBLIC_ struct passwd *nwrap_getpwuid(uid_t uid)
 
857
{
 
858
        if (!nwrap_enabled()) {
 
859
                return real_getpwuid(uid);
 
860
        }
 
861
 
 
862
        return nwrap_files_getpwuid(uid);
 
863
}
 
864
 
 
865
static int nwrap_files_getpwuid_r(uid_t uid, struct passwd *pwdst,
 
866
                                  char *buf, size_t buflen, struct passwd **pwdstp)
 
867
{
 
868
        struct passwd *pw;
 
869
 
 
870
        pw = nwrap_getpwuid(uid);
 
871
        if (!pw) {
 
872
                if (errno == 0) {
 
873
                        return ENOENT;
 
874
                }
 
875
                return errno;
 
876
        }
 
877
 
 
878
        return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
 
879
}
 
880
 
 
881
_PUBLIC_ int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
 
882
                              char *buf, size_t buflen, struct passwd **pwdstp)
 
883
{
 
884
        if (!nwrap_enabled()) {
 
885
                return real_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
 
886
        }
 
887
 
 
888
        return nwrap_files_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
 
889
}
 
890
 
 
891
/* user enum functions */
 
892
static void nwrap_files_setpwent(void)
 
893
{
 
894
        nwrap_pw_global.idx = 0;
 
895
}
 
896
 
 
897
_PUBLIC_ void nwrap_setpwent(void)
 
898
{
 
899
        if (!nwrap_enabled()) {
 
900
                real_setpwent();
 
901
        }
 
902
 
 
903
        nwrap_files_setpwent();
 
904
}
 
905
 
 
906
static struct passwd *nwrap_files_getpwent(void)
 
907
{
 
908
        struct passwd *pw;
 
909
 
 
910
        if (nwrap_pw_global.idx == 0) {
 
911
                nwrap_cache_reload(nwrap_pw_global.cache);
 
912
        }
 
913
 
 
914
        if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
 
915
                errno = ENOENT;
 
916
                return NULL;
 
917
        }
 
918
 
 
919
        pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
 
920
 
 
921
        NWRAP_VERBOSE(("%s: return user[%s] uid[%u]\n",
 
922
                       __location__, pw->pw_name, pw->pw_uid));
 
923
 
 
924
        return pw;
 
925
}
 
926
 
 
927
_PUBLIC_ struct passwd *nwrap_getpwent(void)
 
928
{
 
929
        if (!nwrap_enabled()) {
 
930
                return real_getpwent();
 
931
        }
 
932
 
 
933
        return nwrap_files_getpwent();
 
934
}
 
935
 
 
936
static int nwrap_files_getpwent_r(struct passwd *pwdst, char *buf,
 
937
                                  size_t buflen, struct passwd **pwdstp)
 
938
{
 
939
        struct passwd *pw;
 
940
 
 
941
        pw = nwrap_getpwent();
 
942
        if (!pw) {
 
943
                if (errno == 0) {
 
944
                        return ENOENT;
 
945
                }
 
946
                return errno;
 
947
        }
 
948
 
 
949
        return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
 
950
}
 
951
 
 
952
_PUBLIC_ int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
 
953
                              size_t buflen, struct passwd **pwdstp)
 
954
{
 
955
        if (!nwrap_enabled()) {
 
956
#ifdef SOLARIS_GETPWENT_R
 
957
                struct passwd *pw;
 
958
                pw = real_getpwent_r(pwdst, buf, buflen);
 
959
                if (!pw) {
 
960
                        if (errno == 0) {
 
961
                                return ENOENT;
 
962
                        }
 
963
                        return errno;
 
964
                }
 
965
                if (pwdstp) {
 
966
                        *pwdstp = pw;
 
967
                }
 
968
                return 0;
 
969
#else
 
970
                return real_getpwent_r(pwdst, buf, buflen, pwdstp);
 
971
#endif
 
972
        }
 
973
 
 
974
        return nwrap_files_getpwent_r(pwdst, buf, buflen, pwdstp);
 
975
}
 
976
 
 
977
static void nwrap_files_endpwent(void)
 
978
{
 
979
        nwrap_pw_global.idx = 0;
 
980
}
 
981
 
 
982
_PUBLIC_ void nwrap_endpwent(void)
 
983
{
 
984
        if (!nwrap_enabled()) {
 
985
                real_endpwent();
 
986
        }
 
987
 
 
988
        nwrap_files_endpwent();
 
989
}
 
990
 
 
991
/* misc functions */
 
992
static int nwrap_files_initgroups(const char *user, gid_t group)
 
993
{
 
994
        /* TODO: maybe we should also fake this... */
 
995
        return EPERM;
 
996
}
 
997
 
 
998
_PUBLIC_ int nwrap_initgroups(const char *user, gid_t group)
 
999
{
 
1000
        if (!nwrap_enabled()) {
 
1001
                return real_initgroups(user, group);
 
1002
        }
 
1003
 
 
1004
        return nwrap_files_initgroups(user, group);
 
1005
}
 
1006
 
 
1007
/* group functions */
 
1008
static struct group *nwrap_files_getgrnam(const char *name)
 
1009
{
 
1010
        int i;
 
1011
 
 
1012
        nwrap_cache_reload(nwrap_gr_global.cache);
 
1013
 
 
1014
        for (i=0; i<nwrap_gr_global.num; i++) {
 
1015
                if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
 
1016
                        NWRAP_DEBUG(("%s: group[%s] found\n",
 
1017
                                     __location__, name));
 
1018
                        return &nwrap_gr_global.list[i];
 
1019
                }
 
1020
                NWRAP_VERBOSE(("%s: group[%s] does not match [%s]\n",
 
1021
                               __location__, name,
 
1022
                               nwrap_gr_global.list[i].gr_name));
 
1023
        }
 
1024
 
 
1025
        NWRAP_DEBUG(("%s: group[%s] not found\n", __location__, name));
 
1026
 
 
1027
        errno = ENOENT;
 
1028
        return NULL;
 
1029
}
 
1030
 
 
1031
_PUBLIC_ struct group *nwrap_getgrnam(const char *name)
 
1032
{
 
1033
        if (!nwrap_enabled()) {
 
1034
                return real_getgrnam(name);
 
1035
        }
 
1036
 
 
1037
        return nwrap_files_getgrnam(name);
 
1038
}
 
1039
 
 
1040
static int nwrap_files_getgrnam_r(const char *name, struct group *grdst,
 
1041
                                  char *buf, size_t buflen, struct group **grdstp)
 
1042
{
 
1043
        struct group *gr;
 
1044
 
 
1045
        gr = nwrap_getgrnam(name);
 
1046
        if (!gr) {
 
1047
                if (errno == 0) {
 
1048
                        return ENOENT;
 
1049
                }
 
1050
                return errno;
 
1051
        }
 
1052
 
 
1053
        return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
 
1054
}
 
1055
 
 
1056
_PUBLIC_ int nwrap_getgrnam_r(const char *name, struct group *grdst,
 
1057
                              char *buf, size_t buflen, struct group **grdstp)
 
1058
{
 
1059
        if (!nwrap_enabled()) {
 
1060
                return real_getgrnam_r(name, grdst, buf, buflen, grdstp);
 
1061
        }
 
1062
 
 
1063
        return nwrap_files_getgrnam_r(name, grdst, buf, buflen, grdstp);
 
1064
}
 
1065
 
 
1066
static struct group *nwrap_files_getgrgid(gid_t gid)
 
1067
{
 
1068
        int i;
 
1069
 
 
1070
        nwrap_cache_reload(nwrap_gr_global.cache);
 
1071
 
 
1072
        for (i=0; i<nwrap_gr_global.num; i++) {
 
1073
                if (nwrap_gr_global.list[i].gr_gid == gid) {
 
1074
                        NWRAP_DEBUG(("%s: gid[%u] found\n",
 
1075
                                     __location__, gid));
 
1076
                        return &nwrap_gr_global.list[i];
 
1077
                }
 
1078
                NWRAP_VERBOSE(("%s: gid[%u] does not match [%u]\n",
 
1079
                               __location__, gid,
 
1080
                               nwrap_gr_global.list[i].gr_gid));
 
1081
        }
 
1082
 
 
1083
        NWRAP_DEBUG(("%s: gid[%u] not found\n", __location__, gid));
 
1084
 
 
1085
        errno = ENOENT;
 
1086
        return NULL;
 
1087
}
 
1088
 
 
1089
_PUBLIC_ struct group *nwrap_getgrgid(gid_t gid)
 
1090
{
 
1091
        if (!nwrap_enabled()) {
 
1092
                return real_getgrgid(gid);
 
1093
        }
 
1094
 
 
1095
        return nwrap_files_getgrgid(gid);
 
1096
}
 
1097
 
 
1098
static int nwrap_files_getgrgid_r(gid_t gid, struct group *grdst,
 
1099
                                  char *buf, size_t buflen, struct group **grdstp)
 
1100
{
 
1101
        struct group *gr;
 
1102
 
 
1103
        gr = nwrap_getgrgid(gid);
 
1104
        if (!gr) {
 
1105
                if (errno == 0) {
 
1106
                        return ENOENT;
 
1107
                }
 
1108
                return errno;
 
1109
        }
 
1110
 
 
1111
        return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
 
1112
 
 
1113
        return ENOENT;
 
1114
}
 
1115
 
 
1116
_PUBLIC_ int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
 
1117
                              char *buf, size_t buflen, struct group **grdstp)
 
1118
{
 
1119
        if (!nwrap_enabled()) {
 
1120
                return real_getgrgid_r(gid, grdst, buf, buflen, grdstp);
 
1121
        }
 
1122
 
 
1123
        return nwrap_files_getgrgid_r(gid, grdst, buf, buflen, grdstp);
 
1124
}
 
1125
 
 
1126
/* group enum functions */
 
1127
static void nwrap_files_setgrent(void)
 
1128
{
 
1129
        nwrap_gr_global.idx = 0;
 
1130
}
 
1131
 
 
1132
_PUBLIC_ void nwrap_setgrent(void)
 
1133
{
 
1134
        if (!nwrap_enabled()) {
 
1135
                real_setgrent();
 
1136
        }
 
1137
 
 
1138
        nwrap_files_setgrent();
 
1139
}
 
1140
 
 
1141
static struct group *nwrap_files_getgrent(void)
 
1142
{
 
1143
        struct group *gr;
 
1144
 
 
1145
        if (nwrap_gr_global.idx == 0) {
 
1146
                nwrap_cache_reload(nwrap_gr_global.cache);
 
1147
        }
 
1148
 
 
1149
        if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
 
1150
                errno = ENOENT;
 
1151
                return NULL;
 
1152
        }
 
1153
 
 
1154
        gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
 
1155
 
 
1156
        NWRAP_VERBOSE(("%s: return group[%s] gid[%u]\n",
 
1157
                       __location__, gr->gr_name, gr->gr_gid));
 
1158
 
 
1159
        return gr;
 
1160
}
 
1161
 
 
1162
_PUBLIC_ struct group *nwrap_getgrent(void)
 
1163
{
 
1164
        if (!nwrap_enabled()) {
 
1165
                return real_getgrent();
 
1166
        }
 
1167
 
 
1168
        return nwrap_files_getgrent();
 
1169
}
 
1170
 
 
1171
static int nwrap_files_getgrent_r(struct group *grdst, char *buf,
 
1172
                                  size_t buflen, struct group **grdstp)
 
1173
{
 
1174
        struct group *gr;
 
1175
 
 
1176
        gr = nwrap_getgrent();
 
1177
        if (!gr) {
 
1178
                if (errno == 0) {
 
1179
                        return ENOENT;
 
1180
                }
 
1181
                return errno;
 
1182
        }
 
1183
 
 
1184
        return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
 
1185
}
 
1186
 
 
1187
_PUBLIC_ int nwrap_getgrent_r(struct group *grdst, char *buf,
 
1188
                              size_t buflen, struct group **grdstp)
 
1189
{
 
1190
        if (!nwrap_enabled()) {
 
1191
#ifdef SOLARIS_GETGRENT_R
 
1192
                struct group *gr;
 
1193
                gr = real_getgrent_r(grdst, buf, buflen);
 
1194
                if (!gr) {
 
1195
                        if (errno == 0) {
 
1196
                                return ENOENT;
 
1197
                        }
 
1198
                        return errno;
 
1199
                }
 
1200
                if (grdstp) {
 
1201
                        *grdstp = gr;
 
1202
                }
 
1203
                return 0;
 
1204
#else
 
1205
                return real_getgrent_r(grdst, buf, buflen, grdstp);
 
1206
#endif
 
1207
        }
 
1208
 
 
1209
        return nwrap_files_getgrent_r(grdst, buf, buflen, grdstp);
 
1210
}
 
1211
 
 
1212
static void nwrap_files_endgrent(void)
 
1213
{
 
1214
        nwrap_gr_global.idx = 0;
 
1215
}
 
1216
 
 
1217
_PUBLIC_ void nwrap_endgrent(void)
 
1218
{
 
1219
        if (!nwrap_enabled()) {
 
1220
                real_endgrent();
 
1221
        }
 
1222
 
 
1223
        nwrap_files_endgrent();
 
1224
}