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