source: server/common/oursrc/nss_nonlocal/nonlocal-shadow.c @ 782

Last change on this file since 782 was 750, checked in by andersk, 14 years ago
Add nss_nonlocal.
File size: 5.0 KB
Line 
1/*
2 * nonlocal-shadow.c
3 * shadow database for nss_nonlocal proxy.
4 *
5 * Copyright © 2007 Anders Kaseorg <andersk@mit.edu>
6 *
7 * Permission is hereby granted, free of charge, to any person
8 * obtaining a copy of this software and associated documentation
9 * files (the "Software"), to deal in the Software without
10 * restriction, including without limitation the rights to use, copy,
11 * modify, merge, publish, distribute, sublicense, and/or sell copies
12 * of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28#define _GNU_SOURCE
29#include <sys/types.h>
30#include <unistd.h>
31#include <stdlib.h>
32#include <stdint.h>
33#include <string.h>
34#include <dlfcn.h>
35#include <stdio.h>
36#include <errno.h>
37#include <shadow.h>
38#include <nss.h>
39
40#include "nsswitch-internal.h"
41#include "nonlocal.h"
42
43
44static service_user *
45nss_shadow_nonlocal_database(void)
46{
47    static service_user *nip = NULL;
48    if (nip == NULL)
49        __nss_database_lookup("shadow_nonlocal", NULL, "", &nip);
50
51    return nip;
52}
53
54
55static service_user *spent_nip = NULL;
56static void *spent_fct_start;
57static union {
58    enum nss_status (*l)(struct spwd *pwd, char *buffer, size_t buflen,
59                         int *errnop);
60    void *ptr;
61} spent_fct;
62static const char *spent_fct_name = "getspent_r";
63
64enum nss_status
65_nss_nonlocal_setspent(int stayopen)
66{
67    static const char *fct_name = "setspent";
68    static void *fct_start = NULL;
69    enum nss_status status;
70    service_user *nip;
71    union {
72        enum nss_status (*l)(int stayopen);
73        void *ptr;
74    } fct;
75
76    nip = nss_shadow_nonlocal_database();
77    if (nip == NULL)
78        return NSS_STATUS_UNAVAIL;
79    if (fct_start == NULL)
80        fct_start = __nss_lookup_function(nip, fct_name);
81    fct.ptr = fct_start;
82    do {
83        if (fct.ptr == NULL)
84            status = NSS_STATUS_UNAVAIL;
85        else
86            status = DL_CALL_FCT(fct.l, (stayopen));
87    } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
88    if (status != NSS_STATUS_SUCCESS)
89        return status;
90
91    spent_nip = nip;
92    if (spent_fct_start == NULL)
93        spent_fct_start = __nss_lookup_function(nip, spent_fct_name);
94    spent_fct.ptr = spent_fct_start;
95    return NSS_STATUS_SUCCESS;
96}
97
98enum nss_status
99_nss_nonlocal_endspent(void)
100{
101    static const char *fct_name = "endspent";
102    static void *fct_start = NULL;
103    enum nss_status status;
104    service_user *nip;
105    union {
106        enum nss_status (*l)(void);
107        void *ptr;
108    } fct;
109
110    spent_nip = NULL;
111
112    nip = nss_shadow_nonlocal_database();
113    if (nip == NULL)
114        return NSS_STATUS_UNAVAIL;
115    if (fct_start == NULL)
116        fct_start = __nss_lookup_function(nip, fct_name);
117    fct.ptr = fct_start;
118    do {
119        if (fct.ptr == NULL)
120            status = NSS_STATUS_UNAVAIL;
121        else
122            status = DL_CALL_FCT(fct.l, ());
123    } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
124    return status;
125}
126
127enum nss_status
128_nss_nonlocal_getspent_r(struct spwd *pwd, char *buffer, size_t buflen,
129                         int *errnop)
130{
131    enum nss_status status;
132    if (spent_nip == NULL) {
133        status = _nss_nonlocal_setspent(0);
134        if (status != NSS_STATUS_SUCCESS)
135            return status;
136    }
137    do {
138        if (spent_fct.ptr == NULL)
139            status = NSS_STATUS_UNAVAIL;
140        else
141            status = DL_CALL_FCT(spent_fct.l, (pwd, buffer, buflen, errnop));   
142        if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
143            return status;
144
145        if (status == NSS_STATUS_SUCCESS)
146            return NSS_STATUS_SUCCESS;
147    } while (__nss_next(&spent_nip, spent_fct_name, &spent_fct.ptr, status, 0) == 0);
148
149    spent_nip = NULL;
150    return NSS_STATUS_NOTFOUND;
151}
152
153
154enum nss_status
155_nss_nonlocal_getspnam_r(const char *name, struct spwd *pwd,
156                         char *buffer, size_t buflen, int *errnop)
157{
158    static const char *fct_name = "getspnam_r";
159    static void *fct_start = NULL;
160    enum nss_status status;
161    service_user *nip;
162    union {
163        enum nss_status (*l)(const char *name, struct spwd *pwd,
164                             char *buffer, size_t buflen, int *errnop);
165        void *ptr;
166    } fct;
167
168    nip = nss_shadow_nonlocal_database();
169    if (nip == NULL)
170        return NSS_STATUS_UNAVAIL;
171    if (fct_start == NULL)
172        fct_start = __nss_lookup_function(nip, fct_name);
173    fct.ptr = fct_start;
174    do {
175        if (fct.ptr == NULL)
176            status = NSS_STATUS_UNAVAIL;
177        else
178            status = DL_CALL_FCT(fct.l, (name, pwd, buffer, buflen, errnop));
179        if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
180            break;
181    } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
182    return status;
183}
Note: See TracBrowser for help on using the repository browser.