]> andersk Git - nss_nonlocal.git/blob - nonlocal-shadow.c
Check that a nonlocal lookup by name returns the right name.
[nss_nonlocal.git] / nonlocal-shadow.c
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 <syslog.h>
37 #include <errno.h>
38 #include <shadow.h>
39 #include <nss.h>
40
41 #include "nsswitch-internal.h"
42 #include "nonlocal.h"
43
44
45 static service_user *
46 nss_shadow_nonlocal_database(void)
47 {
48     static service_user *nip = NULL;
49     if (nip == NULL)
50         __nss_database_lookup("shadow_nonlocal", NULL, "", &nip);
51
52     return nip;
53 }
54
55
56 static service_user *spent_nip = NULL;
57 static void *spent_fct_start;
58 static union {
59     enum nss_status (*l)(struct spwd *pwd, char *buffer, size_t buflen,
60                          int *errnop);
61     void *ptr;
62 } spent_fct;
63 static const char *spent_fct_name = "getspent_r";
64
65 enum nss_status
66 _nss_nonlocal_setspent(int stayopen)
67 {
68     static const char *fct_name = "setspent";
69     static void *fct_start = NULL;
70     enum nss_status status;
71     service_user *nip;
72     union {
73         enum nss_status (*l)(int stayopen);
74         void *ptr;
75     } fct;
76
77     nip = nss_shadow_nonlocal_database();
78     if (nip == NULL)
79         return NSS_STATUS_UNAVAIL;
80     if (fct_start == NULL)
81         fct_start = __nss_lookup_function(nip, fct_name);
82     fct.ptr = fct_start;
83     do {
84         if (fct.ptr == NULL)
85             status = NSS_STATUS_UNAVAIL;
86         else
87             status = DL_CALL_FCT(fct.l, (stayopen));
88     } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
89     if (status != NSS_STATUS_SUCCESS)
90         return status;
91
92     spent_nip = nip;
93     if (spent_fct_start == NULL)
94         spent_fct_start = __nss_lookup_function(nip, spent_fct_name);
95     spent_fct.ptr = spent_fct_start;
96     return NSS_STATUS_SUCCESS;
97 }
98
99 enum nss_status
100 _nss_nonlocal_endspent(void)
101 {
102     static const char *fct_name = "endspent";
103     static void *fct_start = NULL;
104     enum nss_status status;
105     service_user *nip;
106     union {
107         enum nss_status (*l)(void);
108         void *ptr;
109     } fct;
110
111     spent_nip = NULL;
112
113     nip = nss_shadow_nonlocal_database();
114     if (nip == NULL)
115         return NSS_STATUS_UNAVAIL;
116     if (fct_start == NULL)
117         fct_start = __nss_lookup_function(nip, fct_name);
118     fct.ptr = fct_start;
119     do {
120         if (fct.ptr == NULL)
121             status = NSS_STATUS_UNAVAIL;
122         else
123             status = DL_CALL_FCT(fct.l, ());
124     } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
125     return status;
126 }
127
128 enum nss_status
129 _nss_nonlocal_getspent_r(struct spwd *pwd, char *buffer, size_t buflen,
130                          int *errnop)
131 {
132     enum nss_status status;
133     if (spent_nip == NULL) {
134         status = _nss_nonlocal_setspent(0);
135         if (status != NSS_STATUS_SUCCESS)
136             return status;
137     }
138     do {
139         if (spent_fct.ptr == NULL)
140             status = NSS_STATUS_UNAVAIL;
141         else
142             status = DL_CALL_FCT(spent_fct.l, (pwd, buffer, buflen, errnop));   
143         if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
144             return status;
145
146         if (status == NSS_STATUS_SUCCESS)
147             return NSS_STATUS_SUCCESS;
148     } while (__nss_next(&spent_nip, spent_fct_name, &spent_fct.ptr, status, 0) == 0);
149
150     spent_nip = NULL;
151     return NSS_STATUS_NOTFOUND;
152 }
153
154
155 enum nss_status
156 _nss_nonlocal_getspnam_r(const char *name, struct spwd *pwd,
157                          char *buffer, size_t buflen, int *errnop)
158 {
159     static const char *fct_name = "getspnam_r";
160     static void *fct_start = NULL;
161     enum nss_status status;
162     service_user *nip;
163     union {
164         enum nss_status (*l)(const char *name, struct spwd *pwd,
165                              char *buffer, size_t buflen, int *errnop);
166         void *ptr;
167     } fct;
168
169     nip = nss_shadow_nonlocal_database();
170     if (nip == NULL)
171         return NSS_STATUS_UNAVAIL;
172     if (fct_start == NULL)
173         fct_start = __nss_lookup_function(nip, fct_name);
174     fct.ptr = fct_start;
175     do {
176         if (fct.ptr == NULL)
177             status = NSS_STATUS_UNAVAIL;
178         else
179             status = DL_CALL_FCT(fct.l, (name, pwd, buffer, buflen, errnop));
180         if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
181             break;
182     } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
183     if (status != NSS_STATUS_SUCCESS)
184         return status;
185
186     if (strcmp(name, pwd->sp_namp) != 0) {
187         syslog(LOG_ERR, "nss_nonlocal: discarding shadow %s from lookup for shadow %s\n", pwd->sp_namp, name);
188         return NSS_STATUS_NOTFOUND;
189     }
190
191     return NSS_STATUS_SUCCESS;
192 }
This page took 0.267963 seconds and 5 git commands to generate.