1 /*
2   Solaris NSS wrapper for winbind
3   - Shirish Kalele 2000
4 
5   Based on Luke Howard's ldap_nss module for Solaris
6   */
7 
8 /*
9   Copyright (C) 1997-2003 Luke Howard.
10   This file is part of the nss_ldap library.
11 
12   The nss_ldap library is free software; you can redistribute it and/or
13   modify it under the terms of the GNU Lesser General Public License as
14   published by the Free Software Foundation; either version 3 of the
15   License, or (at your option) any later version.
16 
17   The nss_ldap library is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20   Library General Public License for more details.
21 
22   You should have received a copy of the GNU Lesser General Public
23   License along with the nss_ldap library; see the file COPYING.LIB.  If not,
24   see <http://www.gnu.org/licenses/>.
25 */
26 
27 #undef DEVELOPER
28 
29 
30 #include "winbind_client.h"
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <string.h>
35 #include <pwd.h>
36 #include <syslog.h>
37 
38 #if !defined(HPUX)
39 #include <sys/syslog.h>
40 #endif /*hpux*/
41 
42 #if defined(HAVE_NSS_COMMON_H) || defined(HPUX)
43 
44 #undef NSS_DEBUG
45 
46 #ifdef NSS_DEBUG
47 #define NSS_DEBUG(str) syslog(LOG_DEBUG, "nss_winbind: %s", str);
48 #else
49 #define NSS_DEBUG(str) ;
50 #endif
51 
52 #if !defined(SMB_MALLOC_P)
53 #define SMB_MALLOC_P(type) (type *)malloc(sizeof(type))
54 #endif
55 
56 #define NSS_ARGS(args) ((nss_XbyY_args_t *)args)
57 
58 #ifdef HPUX
59 
60 /*
61  * HP-UX 11 has no definiton of the nss_groupsbymem structure.   This
62  * definition is taken from the nss_ldap project at:
63  *  http://www.padl.com/OSS/nss_ldap.html
64  */
65 
66 struct nss_groupsbymem {
67        const char *username;
68        gid_t *gid_array;
69        int maxgids;
70        int force_slow_way;
71        int (*str2ent)(const char *instr, int instr_len, void *ent,
72 		      char *buffer, int buflen);
73        nss_status_t (*process_cstr)(const char *instr, int instr_len,
74 				    struct nss_groupsbymem *);
75        int numgids;
76 };
77 
78 #endif /* HPUX */
79 
_nss_winbind_setpwent_solwrap(nss_backend_t * be,void * args)80 static NSS_STATUS _nss_winbind_setpwent_solwrap (nss_backend_t* be, void* args)
81 {
82 	NSS_DEBUG("_nss_winbind_setpwent_solwrap");
83 	return _nss_winbind_setpwent();
84 }
85 
86 static NSS_STATUS
_nss_winbind_endpwent_solwrap(nss_backend_t * be,void * args)87 _nss_winbind_endpwent_solwrap (nss_backend_t * be, void *args)
88 {
89 	NSS_DEBUG("_nss_winbind_endpwent_solwrap");
90 	return _nss_winbind_endpwent();
91 }
92 
93 static NSS_STATUS
_nss_winbind_getpwent_solwrap(nss_backend_t * be,void * args)94 _nss_winbind_getpwent_solwrap (nss_backend_t* be, void *args)
95 {
96 	NSS_STATUS ret;
97 	char* buffer = NSS_ARGS(args)->buf.buffer;
98 	int buflen = NSS_ARGS(args)->buf.buflen;
99 	struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
100 	int* errnop = &NSS_ARGS(args)->erange;
101 	char logmsg[80];
102 
103 	ret = _nss_winbind_getpwent_r(result, buffer,
104 				      buflen, errnop);
105 
106 	if(ret == NSS_STATUS_SUCCESS)
107 		{
108 			snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning user: %s\n",
109 				 result->pw_name);
110 			NSS_DEBUG(logmsg);
111 			NSS_ARGS(args)->returnval = (void*) result;
112 		} else {
113 			snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning error: %d.\n",ret);
114 			NSS_DEBUG(logmsg);
115 		}
116 
117 	return ret;
118 }
119 
120 static NSS_STATUS
_nss_winbind_getpwnam_solwrap(nss_backend_t * be,void * args)121 _nss_winbind_getpwnam_solwrap (nss_backend_t* be, void* args)
122 {
123 	NSS_STATUS ret;
124 	struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
125 
126 	NSS_DEBUG("_nss_winbind_getpwnam_solwrap");
127 
128 	ret = _nss_winbind_getpwnam_r (NSS_ARGS(args)->key.name,
129 						result,
130 						NSS_ARGS(args)->buf.buffer,
131 						NSS_ARGS(args)->buf.buflen,
132 						&NSS_ARGS(args)->erange);
133 	if(ret == NSS_STATUS_SUCCESS)
134 		NSS_ARGS(args)->returnval = (void*) result;
135 
136 	return ret;
137 }
138 
139 static NSS_STATUS
_nss_winbind_getpwuid_solwrap(nss_backend_t * be,void * args)140 _nss_winbind_getpwuid_solwrap(nss_backend_t* be, void* args)
141 {
142 	NSS_STATUS ret;
143 	struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
144 
145 	NSS_DEBUG("_nss_winbind_getpwuid_solwrap");
146 	ret = _nss_winbind_getpwuid_r (NSS_ARGS(args)->key.uid,
147 				       result,
148 				       NSS_ARGS(args)->buf.buffer,
149 				       NSS_ARGS(args)->buf.buflen,
150 				       &NSS_ARGS(args)->erange);
151 	if(ret == NSS_STATUS_SUCCESS)
152 		NSS_ARGS(args)->returnval = (void*) result;
153 
154 	return ret;
155 }
156 
_nss_winbind_passwd_destr(nss_backend_t * be,void * args)157 static NSS_STATUS _nss_winbind_passwd_destr (nss_backend_t * be, void *args)
158 {
159 	SAFE_FREE(be);
160 	NSS_DEBUG("_nss_winbind_passwd_destr");
161 	return NSS_STATUS_SUCCESS;
162 }
163 
164 static nss_backend_op_t passwd_ops[] =
165 {
166 	_nss_winbind_passwd_destr,
167 	_nss_winbind_endpwent_solwrap,		/* NSS_DBOP_ENDENT */
168 	_nss_winbind_setpwent_solwrap,		/* NSS_DBOP_SETENT */
169 	_nss_winbind_getpwent_solwrap,		/* NSS_DBOP_GETENT */
170 	_nss_winbind_getpwnam_solwrap,		/* NSS_DBOP_PASSWD_BYNAME */
171 	_nss_winbind_getpwuid_solwrap		/* NSS_DBOP_PASSWD_BYUID */
172 };
173 
174 nss_backend_t*
_nss_winbind_passwd_constr(const char * db_name,const char * src_name,const char * cfg_args)175 _nss_winbind_passwd_constr (const char* db_name,
176 			    const char* src_name,
177 			    const char* cfg_args)
178 {
179 	nss_backend_t *be;
180 
181 	if(!(be = SMB_MALLOC_P(nss_backend_t)) )
182 		return NULL;
183 
184 	be->ops = passwd_ops;
185 	be->n_ops = sizeof(passwd_ops) / sizeof(nss_backend_op_t);
186 
187 	NSS_DEBUG("Initialized nss_winbind passwd backend");
188 	return be;
189 }
190 
191 /*****************************************************************
192  GROUP database backend
193  *****************************************************************/
194 
_nss_winbind_setgrent_solwrap(nss_backend_t * be,void * args)195 static NSS_STATUS _nss_winbind_setgrent_solwrap (nss_backend_t* be, void* args)
196 {
197 	NSS_DEBUG("_nss_winbind_setgrent_solwrap");
198 	return _nss_winbind_setgrent();
199 }
200 
201 static NSS_STATUS
_nss_winbind_endgrent_solwrap(nss_backend_t * be,void * args)202 _nss_winbind_endgrent_solwrap (nss_backend_t * be, void *args)
203 {
204 	NSS_DEBUG("_nss_winbind_endgrent_solwrap");
205 	return _nss_winbind_endgrent();
206 }
207 
208 static NSS_STATUS
_nss_winbind_getgrent_solwrap(nss_backend_t * be,void * args)209 _nss_winbind_getgrent_solwrap(nss_backend_t* be, void* args)
210 {
211 	NSS_STATUS ret;
212 	char* buffer = NSS_ARGS(args)->buf.buffer;
213 	int buflen = NSS_ARGS(args)->buf.buflen;
214 	struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
215 	int* errnop = &NSS_ARGS(args)->erange;
216 	char logmsg[80];
217 
218 	ret = _nss_winbind_getgrent_r(result, buffer,
219 				      buflen, errnop);
220 
221 	if(ret == NSS_STATUS_SUCCESS)
222 		{
223 			snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning group: %s\n", result->gr_name);
224 			NSS_DEBUG(logmsg);
225 			NSS_ARGS(args)->returnval = (void*) result;
226 		} else {
227 			snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning error: %d.\n", ret);
228 			NSS_DEBUG(logmsg);
229 		}
230 
231 	return ret;
232 
233 }
234 
235 static NSS_STATUS
_nss_winbind_getgrnam_solwrap(nss_backend_t * be,void * args)236 _nss_winbind_getgrnam_solwrap(nss_backend_t* be, void* args)
237 {
238 	NSS_STATUS ret;
239 	struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
240 
241 	NSS_DEBUG("_nss_winbind_getgrnam_solwrap");
242 	ret = _nss_winbind_getgrnam_r(NSS_ARGS(args)->key.name,
243 				      result,
244 				      NSS_ARGS(args)->buf.buffer,
245 				      NSS_ARGS(args)->buf.buflen,
246 				      &NSS_ARGS(args)->erange);
247 
248 	if(ret == NSS_STATUS_SUCCESS)
249 		NSS_ARGS(args)->returnval = (void*) result;
250 
251 	if (NSS_ARGS(args)->erange == ERANGE && ret == NSS_STATUS_TRYAGAIN)
252 		return NSS_STATUS_UNAVAIL;
253 
254 	return ret;
255 }
256 
257 static NSS_STATUS
_nss_winbind_getgrgid_solwrap(nss_backend_t * be,void * args)258 _nss_winbind_getgrgid_solwrap(nss_backend_t* be, void* args)
259 {
260 	NSS_STATUS ret;
261 	struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
262 
263 	NSS_DEBUG("_nss_winbind_getgrgid_solwrap");
264 	ret = _nss_winbind_getgrgid_r (NSS_ARGS(args)->key.gid,
265 				       result,
266 				       NSS_ARGS(args)->buf.buffer,
267 				       NSS_ARGS(args)->buf.buflen,
268 				       &NSS_ARGS(args)->erange);
269 
270 	if(ret == NSS_STATUS_SUCCESS)
271 		NSS_ARGS(args)->returnval = (void*) result;
272 
273 	if (NSS_ARGS(args)->erange == ERANGE && ret == NSS_STATUS_TRYAGAIN)
274 		return NSS_STATUS_UNAVAIL;
275 
276 	return ret;
277 }
278 
279 static NSS_STATUS
_nss_winbind_getgroupsbymember_solwrap(nss_backend_t * be,void * args)280 _nss_winbind_getgroupsbymember_solwrap(nss_backend_t* be, void* args)
281 {
282 	int errnop;
283 	struct nss_groupsbymem *gmem = (struct nss_groupsbymem *)args;
284 	long int numgids = gmem->numgids;
285 	long int maxgids = gmem->maxgids;
286 
287 	NSS_DEBUG("_nss_winbind_getgroupsbymember");
288 
289 	_nss_winbind_initgroups_dyn(gmem->username,
290 		gmem->gid_array[0], /* Primary Group */
291 		&numgids,
292 		&maxgids,
293 		&gmem->gid_array,
294 		gmem->maxgids,
295 		&errnop);
296 
297 	gmem->numgids = numgids;
298 	gmem->maxgids = maxgids;
299 
300 	/*
301 	 * If the maximum number of gids have been found, return
302 	 * SUCCESS so the switch engine will stop searching. Otherwise
303 	 * return NOTFOUND so nsswitch will continue to get groups
304 	 * from the remaining database backends specified in the
305 	 * nsswitch.conf file.
306 	 */
307 	return (gmem->numgids == gmem->maxgids ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND);
308 }
309 
310 static NSS_STATUS
_nss_winbind_group_destr(nss_backend_t * be,void * args)311 _nss_winbind_group_destr (nss_backend_t* be, void* args)
312 {
313 	SAFE_FREE(be);
314 	NSS_DEBUG("_nss_winbind_group_destr");
315 	return NSS_STATUS_SUCCESS;
316 }
317 
318 static nss_backend_op_t group_ops[] =
319 {
320 	_nss_winbind_group_destr,
321 	_nss_winbind_endgrent_solwrap,
322 	_nss_winbind_setgrent_solwrap,
323 	_nss_winbind_getgrent_solwrap,
324 	_nss_winbind_getgrnam_solwrap,
325 	_nss_winbind_getgrgid_solwrap,
326 	_nss_winbind_getgroupsbymember_solwrap
327 };
328 
329 nss_backend_t*
_nss_winbind_group_constr(const char * db_name,const char * src_name,const char * cfg_args)330 _nss_winbind_group_constr (const char* db_name,
331 			   const char* src_name,
332 			   const char* cfg_args)
333 {
334 	nss_backend_t* be;
335 
336 	if(!(be = SMB_MALLOC_P(nss_backend_t)) )
337 		return NULL;
338 
339 	be->ops = group_ops;
340 	be->n_ops = sizeof(group_ops) / sizeof(nss_backend_op_t);
341 
342 	NSS_DEBUG("Initialized nss_winbind group backend");
343 	return be;
344 }
345 
346 /*****************************************************************
347  hosts and ipnodes backend
348  *****************************************************************/
349 #if defined(SUNOS5)	/* not compatible with HP-UX */
350 
351 /* this parser is shared between get*byname and get*byaddr, as key type
352    in request is stored in different locations, I had to provide the
353    address family as an argument, caller must free the winbind response. */
354 
355 static NSS_STATUS
parse_response(int af,nss_XbyY_args_t * argp,struct winbindd_response * response)356 parse_response(int af, nss_XbyY_args_t* argp, struct winbindd_response *response)
357 {
358 	struct hostent *he = (struct hostent *)argp->buf.result;
359 	char *buffer = argp->buf.buffer;
360 	int buflen =  argp->buf.buflen;
361 	NSS_STATUS ret;
362 
363 	char *p, *data;
364 	int addrcount = 0;
365 	int len = 0;
366 	struct in_addr *addrp;
367 #if defined(AF_INET6)
368 	struct in6_addr *addrp6;
369 #endif
370 	int i;
371 
372 	/* response is tab separated list of ip addresses with hostname
373 	   and newline at the end. so at first we will strip newline
374 	   then construct list of addresses for hostent.
375 	*/
376 	p = strchr(response->data.winsresp, '\n');
377 	if(p) *p = '\0';
378 	else {/* it must be broken */
379 		argp->h_errno = NO_DATA;
380 		return NSS_STATUS_UNAVAIL;
381 	}
382 
383 	for(; p != response->data.winsresp; p--) {
384 		if(*p == '\t') addrcount++;
385 	}
386 
387 	if(addrcount == 0) {/* it must be broken */
388 		argp->h_errno = NO_DATA;
389 		return NSS_STATUS_UNAVAIL;
390 	}
391 
392 	/* allocate space for addresses and h_addr_list */
393 	he->h_addrtype = af;
394 	if( he->h_addrtype == AF_INET) {
395 		he->h_length =  sizeof(struct in_addr);
396 		addrp = (struct in_addr *)ROUND_DOWN(buffer + buflen,
397 						sizeof(struct in_addr));
398 		addrp -= addrcount;
399 		he->h_addr_list = (char **)ROUND_DOWN(addrp, sizeof (char*));
400 		he->h_addr_list -= addrcount+1;
401 	}
402 #if defined(AF_INET6)
403         else {
404 		he->h_length = sizeof(struct in6_addr);
405 		addrp6 = (struct in6_addr *)ROUND_DOWN(buffer + buflen,
406 						sizeof(struct in6_addr));
407 		addrp6 -= addrcount;
408 		he->h_addr_list = (char **)ROUND_DOWN(addrp6, sizeof (char*));
409 		he->h_addr_list -= addrcount+1;
410 	}
411 #endif
412 
413 	/* buffer too small?! */
414 	if((char *)he->h_addr_list < buffer ) {
415 		argp->erange = 1;
416 		return NSS_STR_PARSE_ERANGE;
417 	}
418 
419 	data = response->data.winsresp;
420 	for( i = 0; i < addrcount; i++) {
421 		p = strchr(data, '\t');
422 		if(p == NULL) break; /* just in case... */
423 
424 		*p = '\0'; /* terminate the string */
425 		if(he->h_addrtype == AF_INET) {
426 		  he->h_addr_list[i] = (char *)&addrp[i];
427 		  if ((addrp[i].s_addr = inet_addr(data)) == -1) {
428 		    argp->erange = 1;
429 		    return NSS_STR_PARSE_ERANGE;
430 		  }
431 		}
432 #if defined(AF_INET6)
433                 else {
434 		  he->h_addr_list[i] = (char *)&addrp6[i];
435 		  if (strchr(data, ':') != 0) {
436 			if (inet_pton(AF_INET6, data, &addrp6[i]) != 1) {
437 			  argp->erange = 1;
438 			  return NSS_STR_PARSE_ERANGE;
439 			}
440 		  } else {
441 			struct in_addr in4;
442 			if ((in4.s_addr = inet_addr(data)) == -1) {
443 			  argp->erange = 1;
444 			  return NSS_STR_PARSE_ERANGE;
445 			}
446 			IN6_INADDR_TO_V4MAPPED(&in4, &addrp6[i]);
447 		  }
448 		}
449 #endif
450 		data = p+1;
451 	}
452 
453 	he->h_addr_list[i] = (char *)NULL;
454 
455 	len = strlen(data);
456 	if(len > he->h_addr_list - (char**)argp->buf.buffer) {
457 		argp->erange = 1;
458 		return NSS_STR_PARSE_ERANGE;
459 	}
460 
461 	/* this is a bit overkill to use _nss_netdb_aliases here since
462 	   there seems to be no aliases but it will create all data for us */
463 	he->h_aliases = _nss_netdb_aliases(data, len, buffer,
464 				((char*) he->h_addr_list) - buffer);
465 	if(he->h_aliases == NULL) {
466 	    argp->erange = 1;
467 	    ret = NSS_STR_PARSE_ERANGE;
468 	} else {
469 	    he->h_name = he->h_aliases[0];
470 	    he->h_aliases++;
471 	    ret = NSS_STR_PARSE_SUCCESS;
472 	}
473 
474 	argp->returnval = (void*)he;
475 	return ret;
476 }
477 
478 static NSS_STATUS
_nss_winbind_ipnodes_getbyname(nss_backend_t * be,void * args)479 _nss_winbind_ipnodes_getbyname(nss_backend_t* be, void *args)
480 {
481 	nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args;
482 	struct winbindd_request request = {
483 		.wb_flags = WBFLAG_FROM_NSS,
484 	};
485 	struct winbindd_response response = {
486 		.length = 0,
487 	};
488 	NSS_STATUS ret;
489 	int af;
490 
491 	/* I assume there that AI_ADDRCONFIG cases are handled in nss
492 	   frontend code, at least it seems done so in solaris...
493 
494 	   we will give NO_DATA for pure IPv6; IPv4 will be returned for
495 	   AF_INET or for AF_INET6 and AI_ALL|AI_V4MAPPED we have to map
496 	   IPv4 to IPv6.
497 	 */
498 #if defined(AF_INET6)
499 #ifdef HAVE_NSS_XBYY_KEY_IPNODE
500 	af = argp->key.ipnode.af_family;
501 	if(af == AF_INET6 && argp->key.ipnode.flags == 0) {
502 		argp->h_errno = NO_DATA;
503 		return NSS_STATUS_UNAVAIL;
504 	}
505 #else
506 	/* I'm not that sure if this is correct, but... */
507 	af = AF_INET6;
508 #endif
509 #endif
510 
511 	strncpy(request.data.winsreq, argp->key.name, sizeof(request.data.winsreq) - 1);
512 	request.data.winsreq[sizeof(request.data.winsreq) - 1] = '\0';
513 
514 	if( (ret = winbindd_request_response(NULL, WINBINDD_WINS_BYNAME,
515 					     &request, &response))
516 		== NSS_STATUS_SUCCESS ) {
517 	  ret = parse_response(af, argp, &response);
518 	}
519 
520 	winbindd_free_response(&response);
521 	return ret;
522 }
523 
524 static NSS_STATUS
_nss_winbind_hosts_getbyname(nss_backend_t * be,void * args)525 _nss_winbind_hosts_getbyname(nss_backend_t* be, void *args)
526 {
527 	nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args;
528 	struct winbindd_request request = {
529 		.wb_flags = WBFLAG_FROM_NSS,
530 	};
531 	struct winbindd_response response = {
532 		.length = 0,
533 	};
534 	NSS_STATUS ret;
535 
536 	strncpy(request.data.winsreq, argp->key.name, sizeof(request.data.winsreq) - 1);
537 	request.data.winsreq[sizeof(request.data.winsreq) - 1] = '\0';
538 
539 	if( (ret = winbindd_request_response(NULL, WINBINDD_WINS_BYNAME,
540 					     &request, &response))
541 		== NSS_STATUS_SUCCESS ) {
542 	  ret = parse_response(AF_INET, argp, &response);
543 	}
544 
545 	winbindd_free_response(&response);
546 	return ret;
547 }
548 
549 static NSS_STATUS
_nss_winbind_hosts_getbyaddr(nss_backend_t * be,void * args)550 _nss_winbind_hosts_getbyaddr(nss_backend_t* be, void *args)
551 {
552 	NSS_STATUS ret;
553 	struct winbindd_request request = {
554 		.wb_flags = WBFLAG_FROM_NSS,
555 	};
556 	struct winbindd_response response = {
557 		.length = 0,
558 	};
559 	nss_XbyY_args_t	*argp = (nss_XbyY_args_t *)args;
560 	const char *p;
561 
562 #if defined(AF_INET6)
563 	/* winbindd currently does not resolve IPv6 */
564 	if(argp->key.hostaddr.type == AF_INET6) {
565 		argp->h_errno = NO_DATA;
566 		return NSS_STATUS_UNAVAIL;
567 	}
568 
569 	p = inet_ntop(argp->key.hostaddr.type, argp->key.hostaddr.addr,
570 			request.data.winsreq, sizeof request.data.winsreq);
571 #else
572         snprintf(request.data.winsreq, sizeof request.data.winsreq,
573                 "%u.%u.%u.%u",
574                 ((unsigned char *)argp->key.hostaddr.addr)[0],
575                 ((unsigned char *)argp->key.hostaddr.addr)[1],
576                 ((unsigned char *)argp->key.hostaddr.addr)[2],
577                 ((unsigned char *)argp->key.hostaddr.addr)[3]);
578 #endif
579 
580 	ret = winbindd_request_response(NULL, WINBINDD_WINS_BYIP,
581 					&request, &response);
582 
583 	if( ret == NSS_STATUS_SUCCESS) {
584 	  parse_response(argp->key.hostaddr.type, argp, &response);
585 	}
586 	winbindd_free_response(&response);
587         return ret;
588 }
589 
590 /* winbind does not provide setent, getent, endent for wins */
591 static NSS_STATUS
_nss_winbind_common_endent(nss_backend_t * be,void * args)592 _nss_winbind_common_endent(nss_backend_t* be, void *args)
593 {
594         return (NSS_STATUS_UNAVAIL);
595 }
596 
597 static NSS_STATUS
_nss_winbind_common_setent(nss_backend_t * be,void * args)598 _nss_winbind_common_setent(nss_backend_t* be, void *args)
599 {
600         return (NSS_STATUS_UNAVAIL);
601 }
602 
603 static NSS_STATUS
_nss_winbind_common_getent(nss_backend_t * be,void * args)604 _nss_winbind_common_getent(nss_backend_t* be, void *args)
605 {
606         return (NSS_STATUS_UNAVAIL);
607 }
608 
609 static nss_backend_t*
_nss_winbind_common_constr(nss_backend_op_t ops[],int n_ops)610 _nss_winbind_common_constr (nss_backend_op_t ops[], int n_ops)
611 {
612 	nss_backend_t* be;
613 
614 	if(!(be = SMB_MALLOC_P(nss_backend_t)) )
615 	return NULL;
616 
617 	be->ops = ops;
618 	be->n_ops = n_ops;
619 
620 	return be;
621 }
622 
623 static NSS_STATUS
_nss_winbind_common_destr(nss_backend_t * be,void * args)624 _nss_winbind_common_destr (nss_backend_t* be, void* args)
625 {
626 	SAFE_FREE(be);
627 	return NSS_STATUS_SUCCESS;
628 }
629 
630 static nss_backend_op_t ipnodes_ops[] = {
631 	_nss_winbind_common_destr,
632 	_nss_winbind_common_endent,
633 	_nss_winbind_common_setent,
634 	_nss_winbind_common_getent,
635 	_nss_winbind_ipnodes_getbyname,
636 	_nss_winbind_hosts_getbyaddr,
637 };
638 
639 nss_backend_t *
_nss_winbind_ipnodes_constr(dummy1,dummy2,dummy3)640 _nss_winbind_ipnodes_constr(dummy1, dummy2, dummy3)
641         const char      *dummy1, *dummy2, *dummy3;
642 {
643 	return (_nss_winbind_common_constr(ipnodes_ops,
644 		sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0])));
645 }
646 
647 static nss_backend_op_t host_ops[] = {
648 	_nss_winbind_common_destr,
649 	_nss_winbind_common_endent,
650 	_nss_winbind_common_setent,
651 	_nss_winbind_common_getent,
652 	_nss_winbind_hosts_getbyname,
653 	_nss_winbind_hosts_getbyaddr,
654 };
655 
656 nss_backend_t *
_nss_winbind_hosts_constr(dummy1,dummy2,dummy3)657 _nss_winbind_hosts_constr(dummy1, dummy2, dummy3)
658         const char      *dummy1, *dummy2, *dummy3;
659 {
660 	return (_nss_winbind_common_constr(host_ops,
661 		sizeof (host_ops) / sizeof (host_ops[0])));
662 }
663 
664 #endif	/* defined(SUNOS5) */
665 #endif 	/* defined(HAVE_NSS_COMMON_H) || defined(HPUX) */
666