~ubuntu-branches/ubuntu/trusty/libnss-ldap/trusty-proposed

« back to all changes in this revision

Viewing changes to doc/lookup_nssldap.c

  • Committer: Bazaar Package Importer
  • Author(s): Richard A Nelson (Rick)
  • Date: 2007-05-14 19:40:00 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20070514194000-40u9ndh540lgliqe
Tags: 255-1
Survived i386 and amd64, let it loose

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ident "$Id: lookup_nssldap.c,v 1.3 2005/08/08 23:28:37 lukeh Exp $"
2
 
/* ----------------------------------------------------------------------- *
3
 
 *
4
 
 *  lookup_nss.c - module for Linux automountd to access a NSS
5
 
 *               automount map
6
 
 *
7
 
 *   Copyright 1997 Transmeta Corporation - All Rights Reserved
8
 
 *   Copyright 2001-2003 Ian Kent <raven@themaw.net>
9
 
 *   Copyright 2005 PADL Software Pty Ltd - All Rights Reserved
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, Inc., 675 Mass Ave, Cambridge MA 02139,
14
 
 *   USA; either version 2 of the License, or (at your option) any later
15
 
 *   version; incorporated herein by reference.
16
 
 *
17
 
 * ----------------------------------------------------------------------- */
18
 
 
19
 
#define _GNU_SOURCE
20
 
#include <stdio.h>
21
 
#include <sys/types.h>
22
 
#include <ctype.h>
23
 
#include <string.h>
24
 
#include <syslog.h>
25
 
#include <unistd.h>
26
 
#include <stdlib.h>
27
 
#include <time.h>
28
 
#include <netinet/in.h>
29
 
#include <arpa/nameser.h>
30
 
#include <resolv.h>
31
 
#include <dlfcn.h>
32
 
#include <nss.h>
33
 
 
34
 
#define MODULE_LOOKUP
35
 
#include "automount.h"
36
 
 
37
 
#define MAPFMT_DEFAULT "sun"
38
 
 
39
 
#define NAMESERVICE "ldap"
40
 
 
41
 
#define MODPREFIX "lookup(nss" NAMESERVICE "): "
42
 
 
43
 
struct lookup_context {
44
 
        char *nsname;
45
 
        char *mapname;
46
 
        struct parse_mod *parse;
47
 
        void *dlhandle;
48
 
        enum nss_status (*setautomntent)(const char *, void **);
49
 
        enum nss_status (*getautomntent_r)(void *, const char **, const char **,
50
 
                                           char *, size_t, int *);
51
 
        enum nss_status (*endautomntent)(void **);
52
 
        enum nss_status (*getautomntbyname_r)(void *, const char *,
53
 
                                              const char **, const char **,
54
 
                                              char *, size_t, int *);
55
 
};
56
 
 
57
 
int lookup_version = AUTOFS_LOOKUP_VERSION;
58
 
 
59
 
int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context_p)
60
 
{
61
 
        struct lookup_context *context;
62
 
        char buf[1024];
63
 
 
64
 
        context = (struct lookup_context *)malloc(sizeof(*context));
65
 
        if (context == NULL) {
66
 
                crit(MODPREFIX "malloc: %m");
67
 
                return 1;
68
 
        }
69
 
        memset(context, 0, sizeof(*context));
70
 
 
71
 
        context->nsname = NULL;
72
 
        context->parse = NULL;
73
 
        context->dlhandle = NULL;
74
 
        context->setautomntent = NULL;
75
 
        context->getautomntent_r = NULL;
76
 
        context->endautomntent = NULL;
77
 
 
78
 
        if (mapfmt == NULL) {
79
 
                mapfmt = MAPFMT_DEFAULT;
80
 
        }
81
 
 
82
 
        if (argc < 1) {
83
 
                crit(MODPREFIX "invalid number of arguments");
84
 
                return 1;
85
 
        }
86
 
 
87
 
        asprintf(&context->nsname, "nss%s", NAMESERVICE);
88
 
        if (context->nsname == NULL) {
89
 
                crit(MODPREFIX "strdup: %m");
90
 
                return 1;
91
 
        }
92
 
 
93
 
        snprintf(buf, sizeof(buf), "libnss_%s.so.2", NAMESERVICE);
94
 
 
95
 
        context->dlhandle = dlopen(buf, RTLD_NOW | RTLD_LOCAL);
96
 
        if (context->dlhandle == NULL) {
97
 
                crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
98
 
                return 1;
99
 
        }
100
 
 
101
 
        snprintf(buf, sizeof(buf), "_nss_%s_setautomntent", NAMESERVICE);
102
 
        context->setautomntent = dlsym(context->dlhandle, buf);
103
 
        if (context->setautomntent == NULL) {
104
 
                crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
105
 
                return 1;
106
 
        }
107
 
 
108
 
        snprintf(buf, sizeof(buf), "_nss_%s_getautomntent_r", NAMESERVICE);
109
 
        context->getautomntent_r = dlsym(context->dlhandle, buf);
110
 
        if (context->getautomntent_r == NULL) {
111
 
                crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
112
 
                return 1;
113
 
        }
114
 
 
115
 
        snprintf(buf, sizeof(buf), "_nss_%s_endautomntent", NAMESERVICE);
116
 
        context->endautomntent = dlsym(context->dlhandle, buf);
117
 
        if (context->endautomntent == NULL) {
118
 
                crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
119
 
                return 1;
120
 
        }
121
 
 
122
 
        snprintf(buf, sizeof(buf), "_nss_%s_getautomntbyname_r", NAMESERVICE);
123
 
        context->getautomntbyname_r = dlsym(context->dlhandle, buf);
124
 
        if (context->getautomntbyname_r == NULL) {
125
 
                crit(MODPREFIX "failed to load %s nameservice provider: %s", NAMESERVICE, dlerror());
126
 
                return 1;
127
 
        }
128
 
 
129
 
        context->mapname = strdup(argv[0]);
130
 
        if (context->mapname == NULL) {
131
 
                crit(MODPREFIX "strdup: %m");
132
 
                return 1;
133
 
        }
134
 
 
135
 
        context->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
136
 
        if (context->parse == NULL) {
137
 
                free(context);
138
 
                return 1;
139
 
        }
140
 
 
141
 
        *context_p = context;
142
 
        return 0;
143
 
}
144
 
 
145
 
static const char *nsserr_string(enum nss_status status)
146
 
{
147
 
        switch (status) {
148
 
        case NSS_STATUS_TRYAGAIN:
149
 
                return "Insufficient buffer space";
150
 
                break;
151
 
        case NSS_STATUS_UNAVAIL:
152
 
                return "Name service unavailable";
153
 
                break;
154
 
        case NSS_STATUS_NOTFOUND:
155
 
                return "Not found";
156
 
                break;
157
 
        case NSS_STATUS_SUCCESS:
158
 
                return "Success";
159
 
                break;
160
 
        default:
161
 
                break;
162
 
        }
163
 
 
164
 
        return "Unknown error";
165
 
}
166
 
 
167
 
static int read_map(const char *root, struct lookup_context *context)
168
 
{
169
 
        enum nss_status status;
170
 
        void *private = NULL;
171
 
        time_t age = time(NULL);
172
 
        const char *key, *mapent;
173
 
        int nss_errno;
174
 
        char buffer[KEY_MAX_LEN + 1 + MAPENT_MAX_LEN + 1];
175
 
 
176
 
        status = (*context->setautomntent)(context->mapname, &private);
177
 
        if (status != NSS_STATUS_SUCCESS) {
178
 
                warn(MODPREFIX "failed to read map %s: %s",
179
 
                        context->mapname, nsserr_string(status));
180
 
                return 0;
181
 
        }
182
 
 
183
 
        for (;;) {
184
 
                status = (*context->getautomntent_r)(private, &key, &mapent,
185
 
                                                     buffer, sizeof(buffer),
186
 
                                                     &nss_errno);
187
 
                if (status != NSS_STATUS_SUCCESS)
188
 
                        break;
189
 
#ifdef CHE_FAIL
190
 
                cache_update(root, key, mapent, age);
191
 
#else
192
 
                cache_update(key, mapent, age);
193
 
#endif
194
 
        }
195
 
 
196
 
        (*context->endautomntent)(&private);
197
 
        
198
 
        cache_clean(root, age);
199
 
        return 1;
200
 
}
201
 
 
202
 
int lookup_ghost(const char *root, int ghost, time_t now, void *context)
203
 
{
204
 
        struct lookup_context *ctxt = (struct lookup_context *)context;
205
 
        struct mapent_cache *me;
206
 
        int status = 1;
207
 
 
208
 
        if (!read_map(root, ctxt))
209
 
                return LKP_FAIL;
210
 
 
211
 
        status = cache_ghost(root, ghost, ctxt->mapname, ctxt->nsname, ctxt->parse);
212
 
 
213
 
        me = cache_lookup_first();
214
 
        if (me == NULL)
215
 
                return LKP_FAIL;
216
 
 
217
 
        if (*me->key == '/' && *(root + 1) != '-') {
218
 
                me = cache_partial_match(root);
219
 
                /* me NULL => no entries for this direct mount root or indirect map */
220
 
                if (me == NULL)
221
 
                        return LKP_FAIL | LKP_INDIRECT;
222
 
        }
223
 
 
224
 
        return status;
225
 
}
226
 
 
227
 
int lookup_mount(const char *root, const char *name, int name_len, void *context)
228
 
{
229
 
        struct lookup_context *ctxt = (struct lookup_context *)context;
230
 
        char key[KEY_MAX_LEN + 1];
231
 
        char buffer[KEY_MAX_LEN + 1 + MAPENT_MAX_LEN + 1];
232
 
        const char *canon_key, *mapent;
233
 
        struct mapent_cache *me = NULL;
234
 
        time_t age = time(NULL);
235
 
        enum nss_status status;
236
 
 
237
 
        debug(MODPREFIX "looking up %s", name);
238
 
 
239
 
        snprintf(key, sizeof(key), "%s/%s", root, name);
240
 
 
241
 
        me = cache_lookup(name);
242
 
        if (me == NULL) {
243
 
                me = cache_lookup(key);
244
 
        }
245
 
 
246
 
        if (me == NULL) {
247
 
                /* path component, do submount */
248
 
                me = cache_partial_match(key);
249
 
 
250
 
                if (me) {
251
 
                        snprintf(buffer, sizeof(buffer), "-fstype=autofs %s:%s",
252
 
                                 ctxt->nsname, ctxt->mapname);
253
 
                        mapent = buffer;
254
 
                }
255
 
        } else {
256
 
                snprintf(buffer, sizeof(buffer), "%s", me->mapent);
257
 
                mapent = buffer;
258
 
        }
259
 
 
260
 
        if (me == NULL) {
261
 
                const char *keys[3];
262
 
                int i;
263
 
                int nss_errno;
264
 
                void *private = NULL;
265
 
 
266
 
                status = (*ctxt->setautomntent)(ctxt->mapname, &private);
267
 
                if (status != NSS_STATUS_SUCCESS) {
268
 
                        warn(MODPREFIX "failed to read map %s: %s", ctxt->mapname, nsserr_string(status));
269
 
                        goto out_err;
270
 
                }
271
 
 
272
 
                keys[0] = name,
273
 
                keys[1] = key;
274
 
                keys[2] = "*";
275
 
 
276
 
                for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
277
 
                        status = (*ctxt->getautomntbyname_r)(private, name,
278
 
                                                             &canon_key, &mapent,
279
 
                                                             buffer, sizeof(buffer),
280
 
                                                             &nss_errno);
281
 
                        if (status != NSS_STATUS_NOTFOUND)
282
 
                                break;
283
 
                }
284
 
 
285
 
                (*ctxt->endautomntent)(&private);
286
 
 
287
 
                if (status != NSS_STATUS_SUCCESS) {
288
 
                        warn(MODPREFIX "failed to read map %s: %s", ctxt->mapname, nsserr_string(status));
289
 
                        goto out_err;
290
 
                }
291
 
 
292
 
#ifdef CHE_FAIL
293
 
                cache_update(root, keys[i], mapent, age);
294
 
#else
295
 
                cache_update(keys[i], mapent, age);
296
 
#endif
297
 
        }
298
 
 
299
 
        debug(MODPREFIX "%s -> %s", name, mapent);
300
 
 
301
 
        return ctxt->parse->parse_mount(root, name, name_len, mapent, ctxt->parse->context);
302
 
 
303
 
out_err:
304
 
        warn(MODPREFIX "lookup for %s failed: %d", name, status);
305
 
        return 1;
306
 
}
307
 
 
308
 
int lookup_done(void *context)
309
 
{
310
 
        struct lookup_context *ctxt = (struct lookup_context *)context;
311
 
        int ret;
312
 
 
313
 
        if (ctxt->nsname != NULL) {
314
 
                free(ctxt->nsname);
315
 
                ctxt->nsname = NULL;
316
 
        }
317
 
 
318
 
        if (ctxt->mapname != NULL) {
319
 
                free(ctxt->mapname);
320
 
                ctxt->mapname = NULL;
321
 
        }
322
 
 
323
 
        ret = close_parse(ctxt->parse);
324
 
 
325
 
        if (ctxt->dlhandle != NULL) {
326
 
                dlclose(ctxt->dlhandle);
327
 
                ctxt->dlhandle = NULL;
328
 
        }
329
 
 
330
 
        memset(ctxt, 0, sizeof(*ctxt));
331
 
        free(ctxt);
332
 
 
333
 
        return ret;
334
 
}
335