1 #include <sys/param.h>
2 #include <netinet/in.h>
3
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <pwd.h>
7 #include <grp.h>
8 #include <nss.h>
9 #include <nsswitch.h>
10 #include <netdb.h>
11
12 extern enum nss_status _nss_ldap_getgrent_r(struct group *, char *, size_t,
13 int *);
14 extern enum nss_status _nss_ldap_getgrnam_r(const char *, struct group *,
15 char *, size_t, int *);
16 extern enum nss_status _nss_ldap_getgrgid_r(gid_t gid, struct group *, char *,
17 size_t, int *);
18 extern enum nss_status _nss_ldap_setgrent(void);
19 extern enum nss_status _nss_ldap_endgrent(void);
20 extern enum nss_status _nss_ldap_initgroups_dyn(const char *, gid_t, long int *,
21 long int *, gid_t **, long int, int *);
22
23 extern enum nss_status _nss_ldap_getpwent_r(struct passwd *, char *, size_t,
24 int *);
25 extern enum nss_status _nss_ldap_getpwnam_r(const char *, struct passwd *,
26 char *, size_t, int *);
27 extern enum nss_status _nss_ldap_getpwuid_r(gid_t gid, struct passwd *, char *,
28 size_t, int *);
29 extern enum nss_status _nss_ldap_setpwent(void);
30 extern enum nss_status _nss_ldap_endpwent(void);
31
32 extern enum nss_status _nss_ldap_gethostbyname_r (const char *name, struct hostent * result,
33 char *buffer, size_t buflen, int *errnop,
34 int *h_errnop);
35
36 extern enum nss_status _nss_ldap_gethostbyname2_r (const char *name, int af, struct hostent * result,
37 char *buffer, size_t buflen, int *errnop,
38 int *h_errnop);
39 extern enum nss_status _nss_ldap_gethostbyaddr_r (struct in_addr * addr, int len, int type,
40 struct hostent * result, char *buffer,
41 size_t buflen, int *errnop, int *h_errnop);
42
43 struct __netgrent;
44 extern enum nss_status _nss_ldap_netgrp_load_result(struct __netgrent *result,
45 char **hostp, char **userp, char **domp);
46 extern enum nss_status _nss_ldap_getnetgrent_r(struct __netgrent *result, char *buffer,
47 size_t buflen, int *errnop);
48 extern enum nss_status _nss_ldap_setnetgrent(char *group, struct __netgrent *result);
49 extern enum nss_status _nss_ldap_endnetgrent(struct __netgrent *result);
50
51 NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r);
52 NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r);
53 NSS_METHOD_PROTOTYPE(__nss_compat_getgrent_r);
54 NSS_METHOD_PROTOTYPE(__nss_compat_setgrent);
55 NSS_METHOD_PROTOTYPE(__nss_compat_endgrent);
56 static NSS_METHOD_PROTOTYPE(__freebsd_getgroupmembership);
57
58 NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r);
59 NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r);
60 NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r);
61 NSS_METHOD_PROTOTYPE(__nss_compat_setpwent);
62 NSS_METHOD_PROTOTYPE(__nss_compat_endpwent);
63
64 NSS_METHOD_PROTOTYPE(__nss_compat_gethostbyname);
65 NSS_METHOD_PROTOTYPE(__nss_compat_gethostbyname2);
66 NSS_METHOD_PROTOTYPE(__nss_compat_gethostbyaddr);
67
68 static NSS_METHOD_PROTOTYPE(__nss_compat_getnetgrent_r);
69 static NSS_METHOD_PROTOTYPE(__nss_compat_setnetgrent);
70 static NSS_METHOD_PROTOTYPE(__nss_compat_endnetgrent);
71
72 static ns_mtab methods[] = {
73 { NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r, _nss_ldap_getgrnam_r },
74 { NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r, _nss_ldap_getgrgid_r },
75 { NSDB_GROUP, "getgrent_r", __nss_compat_getgrent_r, _nss_ldap_getgrent_r },
76 { NSDB_GROUP, "setgrent", __nss_compat_setgrent, _nss_ldap_setgrent },
77 { NSDB_GROUP, "endgrent", __nss_compat_endgrent, _nss_ldap_endgrent },
78 { NSDB_GROUP, "getgroupmembership", __freebsd_getgroupmembership, NULL },
79
80 { NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r, _nss_ldap_getpwnam_r },
81 { NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r, _nss_ldap_getpwuid_r },
82 { NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r, _nss_ldap_getpwent_r },
83 { NSDB_PASSWD, "setpwent", __nss_compat_setpwent, _nss_ldap_setpwent },
84 { NSDB_PASSWD, "endpwent", __nss_compat_endpwent, _nss_ldap_endpwent },
85
86 { NSDB_HOSTS, "gethostbyname", __nss_compat_gethostbyname, _nss_ldap_gethostbyname_r },
87 { NSDB_HOSTS, "gethostbyaddr", __nss_compat_gethostbyaddr, _nss_ldap_gethostbyaddr_r },
88 { NSDB_HOSTS, "gethostbyname2", __nss_compat_gethostbyname2, _nss_ldap_gethostbyname2_r },
89
90 { NSDB_NETGROUP, "getnetgrent_r", __nss_compat_getnetgrent_r, _nss_ldap_getnetgrent_r },
91 { NSDB_NETGROUP, "setnetgrent", __nss_compat_setnetgrent, _nss_ldap_setnetgrent },
92 { NSDB_NETGROUP, "endnetgrent", __nss_compat_endnetgrent, _nss_ldap_endnetgrent },
93
94 { NSDB_GROUP_COMPAT, "getgrnam_r", __nss_compat_getgrnam_r, _nss_ldap_getgrnam_r },
95 { NSDB_GROUP_COMPAT, "getgrgid_r", __nss_compat_getgrgid_r, _nss_ldap_getgrgid_r },
96 { NSDB_GROUP_COMPAT, "getgrent_r", __nss_compat_getgrent_r, _nss_ldap_getgrent_r },
97 { NSDB_GROUP_COMPAT, "setgrent", __nss_compat_setgrent, _nss_ldap_setgrent },
98 { NSDB_GROUP_COMPAT, "endgrent", __nss_compat_endgrent, _nss_ldap_endgrent },
99
100 { NSDB_PASSWD_COMPAT, "getpwnam_r", __nss_compat_getpwnam_r, _nss_ldap_getpwnam_r },
101 { NSDB_PASSWD_COMPAT, "getpwuid_r", __nss_compat_getpwuid_r, _nss_ldap_getpwuid_r },
102 { NSDB_PASSWD_COMPAT, "getpwent_r", __nss_compat_getpwent_r, _nss_ldap_getpwent_r },
103 { NSDB_PASSWD_COMPAT, "setpwent", __nss_compat_setpwent, _nss_ldap_setpwent },
104 { NSDB_PASSWD_COMPAT, "endpwent", __nss_compat_endpwent, _nss_ldap_endpwent },
105
106 };
107
108
109 ns_mtab *
nss_module_register(const char * source,unsigned int * mtabsize,nss_module_unregister_fn * unreg)110 nss_module_register(const char *source, unsigned int *mtabsize,
111 nss_module_unregister_fn *unreg)
112 {
113 *mtabsize = sizeof(methods)/sizeof(methods[0]);
114 *unreg = NULL;
115 return (methods);
116 }
117
__nss_compat_gethostbyname(void * retval,void * mdata,va_list ap)118 int __nss_compat_gethostbyname(void *retval, void *mdata, va_list ap)
119 {
120 enum nss_status (*fn)(const char *, struct hostent *, char *, size_t, int *, int *);
121 const char *name;
122 struct hostent *result;
123 char buffer[1024];
124 size_t buflen = 1024;
125 int errnop;
126 int h_errnop;
127 int af;
128 enum nss_status status;
129 fn = mdata;
130 name = va_arg(ap, const char*);
131 af = va_arg(ap,int);
132 result = va_arg(ap,struct hostent *);
133 status = fn(name, result, buffer, buflen, &errnop, &h_errnop);
134 status = __nss_compat_result(status,errnop);
135 h_errno = h_errnop;
136 return (status);
137 }
138
__nss_compat_gethostbyname2(void * retval,void * mdata,va_list ap)139 int __nss_compat_gethostbyname2(void *retval, void *mdata, va_list ap)
140 {
141 enum nss_status (*fn)(const char *, struct hostent *, char *, size_t, int *, int *);
142 const char *name;
143 struct hostent *result;
144 char buffer[1024];
145 size_t buflen = 1024;
146 int errnop;
147 int h_errnop;
148 int af;
149 enum nss_status status;
150 fn = mdata;
151 name = va_arg(ap, const char*);
152 af = va_arg(ap,int);
153 result = va_arg(ap,struct hostent *);
154 status = fn(name, result, buffer, buflen, &errnop, &h_errnop);
155 status = __nss_compat_result(status,errnop);
156 h_errno = h_errnop;
157 return (status);
158 }
159
__nss_compat_gethostbyaddr(void * retval,void * mdata,va_list ap)160 int __nss_compat_gethostbyaddr(void *retval, void *mdata, va_list ap)
161 {
162 struct in_addr *addr;
163 int len;
164 int type;
165 struct hostent *result;
166 char buffer[1024];
167 size_t buflen = 1024;
168 int errnop;
169 int h_errnop;
170 enum nss_status (*fn)(struct in_addr *, int, int, struct hostent *, char *, size_t, int *, int *);
171 enum nss_status status;
172 fn = mdata;
173 addr = va_arg(ap, struct in_addr*);
174 len = va_arg(ap,int);
175 type = va_arg(ap,int);
176 result = va_arg(ap, struct hostent*);
177 status = fn(addr, len, type, result, buffer, buflen, &errnop, &h_errnop);
178 status = __nss_compat_result(status,errnop);
179 h_errno = h_errnop;
180 return (status);
181 }
182
183 static int
__gr_addgid(gid_t gid,gid_t * groups,int maxgrp,int * groupc)184 __gr_addgid(gid_t gid, gid_t *groups, int maxgrp, int *groupc)
185 {
186 int ret, dupc;
187
188 /* skip duplicates */
189 for (dupc = 0; dupc < MIN(maxgrp, *groupc); dupc++) {
190 if (groups[dupc] == gid)
191 return 1;
192 }
193
194 ret = 1;
195 if (*groupc < maxgrp) /* add this gid */
196 groups[*groupc] = gid;
197 else
198 ret = 0;
199 (*groupc)++;
200 return ret;
201 }
202
__freebsd_getgroupmembership(void * retval,void * mdata,va_list ap)203 static int __freebsd_getgroupmembership(void *retval, void *mdata, va_list ap)
204 {
205 int err;
206 enum nss_status s;
207 const char *user = va_arg(ap, const char *);
208 gid_t group = va_arg(ap, gid_t);
209 gid_t *groups = va_arg(ap, gid_t *);
210 int limit = va_arg(ap, int);
211 int *size = va_arg(ap, int*);
212 gid_t *tmpgroups;
213 long int lstart, lsize;
214 int i;
215
216 tmpgroups = malloc(limit * sizeof(gid_t));
217 if (tmpgroups == NULL)
218 return NS_TRYAGAIN;
219
220 /* insert primary membership */
221 __gr_addgid(group, groups, limit, size);
222
223 lstart = 0;
224 lsize = limit;
225 s = _nss_ldap_initgroups_dyn(user, group, &lstart, &lsize,
226 &tmpgroups, 0, &err);
227 if (s == NSS_STATUS_SUCCESS) {
228 for (i = 0; i < lstart; i++)
229 __gr_addgid(tmpgroups[i], groups, limit, size);
230 s = NSS_STATUS_NOTFOUND;
231 }
232
233 free(tmpgroups);
234
235 return __nss_compat_result(s, err);
236 }
237
238 static void *_netgr_result;
239
240 static int
__nss_compat_getnetgrent_r(void * retval,void * mdata,va_list ap)241 __nss_compat_getnetgrent_r(void *retval, void *mdata, va_list ap)
242 {
243 char **hostp, **userp, **domp;
244 char *buffer;
245 size_t bufsize;
246 enum nss_status rv;
247 int *errorp;
248 int ret;
249
250 hostp = va_arg(ap, char **);
251 userp = va_arg(ap, char **);
252 domp = va_arg(ap, char **);
253 buffer = va_arg(ap, char *);
254 bufsize = va_arg(ap, size_t);
255 errorp = va_arg(ap, int *);
256
257 do {
258 *errorp = 0;
259 rv = _nss_ldap_getnetgrent_r(_netgr_result, buffer, bufsize,
260 errorp);
261 ret = __nss_compat_result(rv, *errorp);
262 if (ret != NS_SUCCESS)
263 return (ret);
264 rv = _nss_ldap_netgrp_load_result(_netgr_result, hostp, userp,
265 domp);
266 ret = __nss_compat_result(rv, 0);
267 } while (ret == NS_TRYAGAIN);
268
269 return (NS_SUCCESS);
270 }
271
272 extern size_t _nss_ldap_netgrent_sz;
273
274 static int
__nss_compat_setnetgrent(void * retval,void * mdata,va_list ap)275 __nss_compat_setnetgrent(void *retval, void *mdata, va_list ap)
276 {
277 const char *netgroup;
278 int ret;
279
280 netgroup = va_arg(ap, const char *);
281
282 if (_netgr_result != NULL)
283 free(_netgr_result);
284 _netgr_result = calloc(1, _nss_ldap_netgrent_sz);
285 if (_netgr_result == NULL)
286 return (NS_TRYAGAIN);
287
288 return (_nss_ldap_setnetgrent(netgroup, _netgr_result));
289 }
290
291 static int
__nss_compat_endnetgrent(void * retval,void * mdata,va_list ap)292 __nss_compat_endnetgrent(void *retval, void *mdata, va_list ap)
293 {
294 int ret;
295
296 ret = _nss_ldap_endnetgrent(_netgr_result);
297 free(_netgr_result);
298 _netgr_result = NULL;
299 return (ret);
300 }
301