r11867: attempt at fixing the compile issue with nss_winbind.so on HP-UX caused by...
[Samba.git] / source / nsswitch / winbind_nss_solaris.c
blob8076c043e044fb996f0dc1e52c3c8340217b7498
1 /*
2 Solaris NSS wrapper for winbind
3 - Shirish Kalele 2000
5 Based on Luke Howard's ldap_nss module for Solaris
6 */
8 /*
9 Copyright (C) 1997-2003 Luke Howard.
10 This file is part of the nss_ldap library.
12 The nss_ldap library is free software; you can redistribute it and/or
13 modify it under the terms of the GNU Library General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
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.
22 You should have received a copy of the GNU Library General Public
23 License along with the nss_ldap library; see the file COPYING.LIB. If not,
24 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25 Boston, MA 02111-1307, USA.
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <sys/param.h>
31 #include <string.h>
32 #include <pwd.h>
33 #include "includes.h"
34 #include <syslog.h>
35 #if !defined(HPUX)
36 #include <sys/syslog.h>
37 #endif /*hpux*/
38 #include "winbind_nss_config.h"
40 #if defined(HAVE_NSS_COMMON_H) || defined(HPUX)
42 #undef NSS_DEBUG
44 #ifdef NSS_DEBUG
45 #define NSS_DEBUG(str) syslog(LOG_DEBUG, "nss_winbind: %s", str);
46 #else
47 #define NSS_DEBUG(str) ;
48 #endif
50 #define NSS_ARGS(args) ((nss_XbyY_args_t *)args)
52 #ifdef HPUX
55 * HP-UX 11 has no definiton of the nss_groupsbymem structure. This
56 * definition is taken from the nss_ldap project at:
57 * http://www.padl.com/OSS/nss_ldap.html
60 struct nss_groupsbymem {
61 const char *username;
62 gid_t *gid_array;
63 int maxgids;
64 int force_slow_way;
65 int (*str2ent)(const char *instr, int instr_len, void *ent,
66 char *buffer, int buflen);
67 nss_status_t (*process_cstr)(const char *instr, int instr_len,
68 struct nss_groupsbymem *);
69 int numgids;
72 #endif /* HPUX */
74 #define make_pwent_str(dest, src) \
75 { \
76 if((dest = get_static(buffer, buflen, strlen(src)+1)) == NULL) \
77 { \
78 *errnop = ERANGE; \
79 NSS_DEBUG("ERANGE error"); \
80 return NSS_STATUS_TRYAGAIN; \
81 } \
82 strcpy(dest, src); \
85 static NSS_STATUS _nss_winbind_setpwent_solwrap (nss_backend_t* be, void* args)
87 NSS_DEBUG("_nss_winbind_setpwent_solwrap");
88 return _nss_winbind_setpwent();
91 static NSS_STATUS
92 _nss_winbind_endpwent_solwrap (nss_backend_t * be, void *args)
94 NSS_DEBUG("_nss_winbind_endpwent_solwrap");
95 return _nss_winbind_endpwent();
98 static NSS_STATUS
99 _nss_winbind_getpwent_solwrap (nss_backend_t* be, void *args)
101 NSS_STATUS ret;
102 char* buffer = NSS_ARGS(args)->buf.buffer;
103 int buflen = NSS_ARGS(args)->buf.buflen;
104 struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
105 int* errnop = &NSS_ARGS(args)->erange;
106 char logmsg[80];
108 ret = _nss_winbind_getpwent_r(result, buffer,
109 buflen, errnop);
111 if(ret == NSS_STATUS_SUCCESS)
113 snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning user: %s\n",
114 result->pw_name);
115 NSS_DEBUG(logmsg);
116 NSS_ARGS(args)->returnval = (void*) result;
117 } else {
118 snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning error: %d.\n",ret);
119 NSS_DEBUG(logmsg);
122 return ret;
125 static NSS_STATUS
126 _nss_winbind_getpwnam_solwrap (nss_backend_t* be, void* args)
128 NSS_STATUS ret;
129 struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
131 NSS_DEBUG("_nss_winbind_getpwnam_solwrap");
133 ret = _nss_winbind_getpwnam_r (NSS_ARGS(args)->key.name,
134 result,
135 NSS_ARGS(args)->buf.buffer,
136 NSS_ARGS(args)->buf.buflen,
137 &NSS_ARGS(args)->erange);
138 if(ret == NSS_STATUS_SUCCESS)
139 NSS_ARGS(args)->returnval = (void*) result;
141 return ret;
144 static NSS_STATUS
145 _nss_winbind_getpwuid_solwrap(nss_backend_t* be, void* args)
147 NSS_STATUS ret;
148 struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
150 NSS_DEBUG("_nss_winbind_getpwuid_solwrap");
151 ret = _nss_winbind_getpwuid_r (NSS_ARGS(args)->key.uid,
152 result,
153 NSS_ARGS(args)->buf.buffer,
154 NSS_ARGS(args)->buf.buflen,
155 &NSS_ARGS(args)->erange);
156 if(ret == NSS_STATUS_SUCCESS)
157 NSS_ARGS(args)->returnval = (void*) result;
159 return ret;
162 static NSS_STATUS _nss_winbind_passwd_destr (nss_backend_t * be, void *args)
164 SAFE_FREE(be);
165 NSS_DEBUG("_nss_winbind_passwd_destr");
166 return NSS_STATUS_SUCCESS;
169 static nss_backend_op_t passwd_ops[] =
171 _nss_winbind_passwd_destr,
172 _nss_winbind_endpwent_solwrap, /* NSS_DBOP_ENDENT */
173 _nss_winbind_setpwent_solwrap, /* NSS_DBOP_SETENT */
174 _nss_winbind_getpwent_solwrap, /* NSS_DBOP_GETENT */
175 _nss_winbind_getpwnam_solwrap, /* NSS_DBOP_PASSWD_BYNAME */
176 _nss_winbind_getpwuid_solwrap /* NSS_DBOP_PASSWD_BYUID */
179 nss_backend_t*
180 _nss_winbind_passwd_constr (const char* db_name,
181 const char* src_name,
182 const char* cfg_args)
184 nss_backend_t *be;
186 if(!(be = (nss_backend_t*) malloc(sizeof(nss_backend_t))) )
187 return NULL;
189 be->ops = passwd_ops;
190 be->n_ops = sizeof(passwd_ops) / sizeof(nss_backend_op_t);
192 NSS_DEBUG("Initialized nss_winbind passwd backend");
193 return be;
196 /*****************************************************************
197 GROUP database backend
198 *****************************************************************/
200 static NSS_STATUS _nss_winbind_setgrent_solwrap (nss_backend_t* be, void* args)
202 NSS_DEBUG("_nss_winbind_setgrent_solwrap");
203 return _nss_winbind_setgrent();
206 static NSS_STATUS
207 _nss_winbind_endgrent_solwrap (nss_backend_t * be, void *args)
209 NSS_DEBUG("_nss_winbind_endgrent_solwrap");
210 return _nss_winbind_endgrent();
213 static NSS_STATUS
214 _nss_winbind_getgrent_solwrap(nss_backend_t* be, void* args)
216 NSS_STATUS ret;
217 char* buffer = NSS_ARGS(args)->buf.buffer;
218 int buflen = NSS_ARGS(args)->buf.buflen;
219 struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
220 int* errnop = &NSS_ARGS(args)->erange;
221 char logmsg[80];
223 ret = _nss_winbind_getgrent_r(result, buffer,
224 buflen, errnop);
226 if(ret == NSS_STATUS_SUCCESS)
228 snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning group: %s\n", result->gr_name);
229 NSS_DEBUG(logmsg);
230 NSS_ARGS(args)->returnval = (void*) result;
231 } else {
232 snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning error: %d.\n", ret);
233 NSS_DEBUG(logmsg);
236 return ret;
240 static NSS_STATUS
241 _nss_winbind_getgrnam_solwrap(nss_backend_t* be, void* args)
243 NSS_STATUS ret;
244 struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
246 NSS_DEBUG("_nss_winbind_getgrnam_solwrap");
247 ret = _nss_winbind_getgrnam_r(NSS_ARGS(args)->key.name,
248 result,
249 NSS_ARGS(args)->buf.buffer,
250 NSS_ARGS(args)->buf.buflen,
251 &NSS_ARGS(args)->erange);
253 if(ret == NSS_STATUS_SUCCESS)
254 NSS_ARGS(args)->returnval = (void*) result;
256 return ret;
259 static NSS_STATUS
260 _nss_winbind_getgrgid_solwrap(nss_backend_t* be, void* args)
262 NSS_STATUS ret;
263 struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
265 NSS_DEBUG("_nss_winbind_getgrgid_solwrap");
266 ret = _nss_winbind_getgrgid_r (NSS_ARGS(args)->key.gid,
267 result,
268 NSS_ARGS(args)->buf.buffer,
269 NSS_ARGS(args)->buf.buflen,
270 &NSS_ARGS(args)->erange);
272 if(ret == NSS_STATUS_SUCCESS)
273 NSS_ARGS(args)->returnval = (void*) result;
275 return ret;
278 static NSS_STATUS
279 _nss_winbind_getgroupsbymember_solwrap(nss_backend_t* be, void* args)
281 int errnop;
282 struct nss_groupsbymem *gmem = (struct nss_groupsbymem *)args;
284 NSS_DEBUG("_nss_winbind_getgroupsbymember");
286 _nss_winbind_initgroups_dyn(gmem->username,
287 gmem->gid_array[0], /* Primary Group */
288 &gmem->numgids,
289 &gmem->maxgids,
290 &gmem->gid_array,
291 gmem->maxgids,
292 &errnop);
295 * If the maximum number of gids have been found, return
296 * SUCCESS so the switch engine will stop searching. Otherwise
297 * return NOTFOUND so nsswitch will continue to get groups
298 * from the remaining database backends specified in the
299 * nsswitch.conf file.
301 return (gmem->numgids == gmem->maxgids ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND);
304 static NSS_STATUS
305 _nss_winbind_group_destr (nss_backend_t* be, void* args)
307 SAFE_FREE(be);
308 NSS_DEBUG("_nss_winbind_group_destr");
309 return NSS_STATUS_SUCCESS;
312 static nss_backend_op_t group_ops[] =
314 _nss_winbind_group_destr,
315 _nss_winbind_endgrent_solwrap,
316 _nss_winbind_setgrent_solwrap,
317 _nss_winbind_getgrent_solwrap,
318 _nss_winbind_getgrnam_solwrap,
319 _nss_winbind_getgrgid_solwrap,
320 _nss_winbind_getgroupsbymember_solwrap
323 nss_backend_t*
324 _nss_winbind_group_constr (const char* db_name,
325 const char* src_name,
326 const char* cfg_args)
328 nss_backend_t* be;
330 if(!(be = (nss_backend_t*) malloc(sizeof(nss_backend_t))) )
331 return NULL;
333 be->ops = group_ops;
334 be->n_ops = sizeof(group_ops) / sizeof(nss_backend_op_t);
336 NSS_DEBUG("Initialized nss_winbind group backend");
337 return be;
340 /*****************************************************************
341 hosts and ipnodes backend
342 *****************************************************************/
343 #if defined(SUNOS5) /* not compatible with HP-UX */
345 /* this parser is shared between get*byname and get*byaddr, as key type
346 in request is stored in different locations, I had to provide the
347 address family as an argument, caller must free the winbind response. */
349 static NSS_STATUS
350 parse_response(int af, nss_XbyY_args_t* argp, struct winbindd_response *response)
352 struct hostent *he = (struct hostent *)argp->buf.result;
353 char *buffer = argp->buf.buffer;
354 int buflen = argp->buf.buflen;
355 NSS_STATUS ret;
357 char *p, *data;
358 int addrcount = 0;
359 int len = 0;
360 struct in_addr *addrp;
361 struct in6_addr *addrp6;
362 int i;
364 /* response is tab separated list of ip addresses with hostname
365 and newline at the end. so at first we will strip newline
366 then construct list of addresses for hostent.
368 p = strchr(response->data.winsresp, '\n');
369 if(p) *p = '\0';
370 else {/* it must be broken */
371 argp->h_errno = NO_DATA;
372 return NSS_STATUS_UNAVAIL;
375 for(; p != response->data.winsresp; p--) {
376 if(*p == '\t') addrcount++;
379 if(addrcount == 0) {/* it must be broken */
380 argp->h_errno = NO_DATA;
381 return NSS_STATUS_UNAVAIL;
384 /* allocate space for addresses and h_addr_list */
385 he->h_addrtype = af;
386 if( he->h_addrtype == AF_INET) {
387 he->h_length = sizeof(struct in_addr);
388 addrp = (struct in_addr *)ROUND_DOWN(buffer + buflen,
389 sizeof(struct in_addr));
390 addrp -= addrcount;
391 he->h_addr_list = (char **)ROUND_DOWN(addrp, sizeof (char*));
392 he->h_addr_list -= addrcount+1;
393 } else {
394 he->h_length = sizeof(struct in6_addr);
395 addrp6 = (struct in6_addr *)ROUND_DOWN(buffer + buflen,
396 sizeof(struct in6_addr));
397 addrp6 -= addrcount;
398 he->h_addr_list = (char **)ROUND_DOWN(addrp6, sizeof (char*));
399 he->h_addr_list -= addrcount+1;
402 /* buffer too small?! */
403 if((char *)he->h_addr_list < buffer ) {
404 argp->erange = 1;
405 return NSS_STR_PARSE_ERANGE;
408 data = response->data.winsresp;
409 for( i = 0; i < addrcount; i++) {
410 p = strchr(data, '\t');
411 if(p == NULL) break; /* just in case... */
413 *p = '\0'; /* terminate the string */
414 if(he->h_addrtype == AF_INET) {
415 he->h_addr_list[i] = (char *)&addrp[i];
416 if ((addrp[i].s_addr = inet_addr(data)) == -1) {
417 argp->erange = 1;
418 return NSS_STR_PARSE_ERANGE;
420 } else {
421 he->h_addr_list[i] = (char *)&addrp6[i];
422 if (strchr(data, ':') != 0) {
423 if (inet_pton(AF_INET6, data, &addrp6[i]) != 1) {
424 argp->erange = 1;
425 return NSS_STR_PARSE_ERANGE;
427 } else {
428 struct in_addr in4;
429 if ((in4.s_addr = inet_addr(data)) == -1) {
430 argp->erange = 1;
431 return NSS_STR_PARSE_ERANGE;
433 IN6_INADDR_TO_V4MAPPED(&in4, &addrp6[i]);
436 data = p+1;
439 he->h_addr_list[i] = (char *)NULL;
441 len = strlen(data);
442 if(len > he->h_addr_list - (char**)argp->buf.buffer) {
443 argp->erange = 1;
444 return NSS_STR_PARSE_ERANGE;
447 /* this is a bit overkill to use _nss_netdb_aliases here since
448 there seems to be no aliases but it will create all data for us */
449 he->h_aliases = _nss_netdb_aliases(data, len, buffer,
450 ((char*) he->h_addr_list) - buffer);
451 if(he->h_aliases == NULL) {
452 argp->erange = 1;
453 ret = NSS_STR_PARSE_ERANGE;
454 } else {
455 he->h_name = he->h_aliases[0];
456 he->h_aliases++;
457 ret = NSS_STR_PARSE_SUCCESS;
460 argp->returnval = (void*)he;
461 return ret;
464 static NSS_STATUS
465 _nss_winbind_ipnodes_getbyname(nss_backend_t* be, void *args)
467 nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args;
468 struct winbindd_response response;
469 struct winbindd_request request;
470 NSS_STATUS ret;
471 int af;
473 ZERO_STRUCT(response);
474 ZERO_STRUCT(request);
476 /* I assume there that AI_ADDRCONFIG cases are handled in nss
477 frontend code, at least it seems done so in solaris...
479 we will give NO_DATA for pure IPv6; IPv4 will be returned for
480 AF_INET or for AF_INET6 and AI_ALL|AI_V4MAPPED we have to map
481 IPv4 to IPv6.
483 #ifdef HAVE_NSS_XBYY_KEY_IPNODE
484 af = argp->key.ipnode.af_family;
485 if(af == AF_INET6 && argp->key.ipnode.flags == 0) {
486 argp->h_errno = NO_DATA;
487 return NSS_STATUS_UNAVAIL;
489 #else
490 /* I'm not that sure if this is correct, but... */
491 af = AF_INET6;
492 #endif
494 strncpy(request.data.winsreq, argp->key.name, strlen(argp->key.name)) ;
496 if( (ret = winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response))
497 == NSS_STATUS_SUCCESS ) {
498 ret = parse_response(af, argp, &response);
501 free_response(&response);
502 return ret;
505 static NSS_STATUS
506 _nss_winbind_hosts_getbyname(nss_backend_t* be, void *args)
508 nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args;
509 struct winbindd_response response;
510 struct winbindd_request request;
511 NSS_STATUS ret;
513 ZERO_STRUCT(response);
514 ZERO_STRUCT(request);
516 strncpy(request.data.winsreq, argp->key.name, strlen(argp->key.name));
518 if( (ret = winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response))
519 == NSS_STATUS_SUCCESS ) {
520 ret = parse_response(AF_INET, argp, &response);
523 free_response(&response);
524 return ret;
527 static NSS_STATUS
528 _nss_winbind_hosts_getbyaddr(nss_backend_t* be, void *args)
530 NSS_STATUS ret;
531 struct winbindd_response response;
532 struct winbindd_request request;
533 nss_XbyY_args_t *argp = (nss_XbyY_args_t *)args;
534 const char *p;
536 ZERO_STRUCT(response);
537 ZERO_STRUCT(request);
539 /* winbindd currently does not resolve IPv6 */
540 if(argp->key.hostaddr.type == AF_INET6) {
541 argp->h_errno = NO_DATA;
542 return NSS_STATUS_UNAVAIL;
545 p = inet_ntop(argp->key.hostaddr.type, argp->key.hostaddr.addr,
546 request.data.winsreq, INET6_ADDRSTRLEN);
548 ret = winbindd_request_response(WINBINDD_WINS_BYIP, &request, &response);
550 if( ret == NSS_STATUS_SUCCESS) {
551 parse_response(argp->key.hostaddr.type, argp, &response);
553 free_response(&response);
554 return ret;
557 /* winbind does not provide setent, getent, endent for wins */
558 static NSS_STATUS
559 _nss_winbind_common_endent(nss_backend_t* be, void *args)
561 return (NSS_STATUS_UNAVAIL);
564 static NSS_STATUS
565 _nss_winbind_common_setent(nss_backend_t* be, void *args)
567 return (NSS_STATUS_UNAVAIL);
570 static NSS_STATUS
571 _nss_winbind_common_getent(nss_backend_t* be, void *args)
573 return (NSS_STATUS_UNAVAIL);
576 static nss_backend_t*
577 _nss_winbind_common_constr (nss_backend_op_t ops[], int n_ops)
579 nss_backend_t* be;
581 if(!(be = (nss_backend_t*) malloc(sizeof(nss_backend_t))) )
582 return NULL;
584 be->ops = ops;
585 be->n_ops = n_ops;
587 return be;
590 static NSS_STATUS
591 _nss_winbind_common_destr (nss_backend_t* be, void* args)
593 SAFE_FREE(be);
594 return NSS_STATUS_SUCCESS;
597 static nss_backend_op_t ipnodes_ops[] = {
598 _nss_winbind_common_destr,
599 _nss_winbind_common_endent,
600 _nss_winbind_common_setent,
601 _nss_winbind_common_getent,
602 _nss_winbind_ipnodes_getbyname,
603 _nss_winbind_hosts_getbyaddr,
606 nss_backend_t *
607 _nss_winbind_ipnodes_constr(dummy1, dummy2, dummy3)
608 const char *dummy1, *dummy2, *dummy3;
610 return (_nss_winbind_common_constr(ipnodes_ops,
611 sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0])));
614 static nss_backend_op_t host_ops[] = {
615 _nss_winbind_common_destr,
616 _nss_winbind_common_endent,
617 _nss_winbind_common_setent,
618 _nss_winbind_common_getent,
619 _nss_winbind_hosts_getbyname,
620 _nss_winbind_hosts_getbyaddr,
623 nss_backend_t *
624 _nss_winbind_hosts_constr(dummy1, dummy2, dummy3)
625 const char *dummy1, *dummy2, *dummy3;
627 return (_nss_winbind_common_constr(host_ops,
628 sizeof (host_ops) / sizeof (host_ops[0])));
631 #endif /* defined(SUNOS5) */
632 #endif /* defined(HAVE_NSS_COMMON_H) || defined(HPUX) */