2
Solaris NSS wrapper for winbind
5
Based on Luke Howard's ldap_nss module for Solaris
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.
31
#include <sys/types.h>
32
#include <sys/param.h>
38
#include <sys/syslog.h>
40
#include "winbind_nss_config.h"
42
#if defined(HAVE_NSS_COMMON_H) || defined(HPUX)
47
#define NSS_DEBUG(str) syslog(LOG_DEBUG, "nss_winbind: %s", str);
49
#define NSS_DEBUG(str) ;
52
#define NSS_ARGS(args) ((nss_XbyY_args_t *)args)
57
* HP-UX 11 has no definiton of the nss_groupsbymem structure. This
58
* definition is taken from the nss_ldap project at:
59
* http://www.padl.com/OSS/nss_ldap.html
62
struct nss_groupsbymem {
67
int (*str2ent)(const char *instr, int instr_len, void *ent,
68
char *buffer, int buflen);
69
nss_status_t (*process_cstr)(const char *instr, int instr_len,
70
struct nss_groupsbymem *);
76
#define make_pwent_str(dest, src) \
78
if((dest = get_static(buffer, buflen, strlen(src)+1)) == NULL) \
81
NSS_DEBUG("ERANGE error"); \
82
return NSS_STATUS_TRYAGAIN; \
87
static NSS_STATUS _nss_winbind_setpwent_solwrap (nss_backend_t* be, void* args)
89
NSS_DEBUG("_nss_winbind_setpwent_solwrap");
90
return _nss_winbind_setpwent();
94
_nss_winbind_endpwent_solwrap (nss_backend_t * be, void *args)
96
NSS_DEBUG("_nss_winbind_endpwent_solwrap");
97
return _nss_winbind_endpwent();
101
_nss_winbind_getpwent_solwrap (nss_backend_t* be, void *args)
104
char* buffer = NSS_ARGS(args)->buf.buffer;
105
int buflen = NSS_ARGS(args)->buf.buflen;
106
struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
107
int* errnop = &NSS_ARGS(args)->erange;
110
ret = _nss_winbind_getpwent_r(result, buffer,
113
if(ret == NSS_STATUS_SUCCESS)
115
snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning user: %s\n",
118
NSS_ARGS(args)->returnval = (void*) result;
120
snprintf(logmsg, 79, "_nss_winbind_getpwent_solwrap: Returning error: %d.\n",ret);
128
_nss_winbind_getpwnam_solwrap (nss_backend_t* be, void* args)
131
struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
133
NSS_DEBUG("_nss_winbind_getpwnam_solwrap");
135
ret = _nss_winbind_getpwnam_r (NSS_ARGS(args)->key.name,
137
NSS_ARGS(args)->buf.buffer,
138
NSS_ARGS(args)->buf.buflen,
139
&NSS_ARGS(args)->erange);
140
if(ret == NSS_STATUS_SUCCESS)
141
NSS_ARGS(args)->returnval = (void*) result;
147
_nss_winbind_getpwuid_solwrap(nss_backend_t* be, void* args)
150
struct passwd* result = (struct passwd*) NSS_ARGS(args)->buf.result;
152
NSS_DEBUG("_nss_winbind_getpwuid_solwrap");
153
ret = _nss_winbind_getpwuid_r (NSS_ARGS(args)->key.uid,
155
NSS_ARGS(args)->buf.buffer,
156
NSS_ARGS(args)->buf.buflen,
157
&NSS_ARGS(args)->erange);
158
if(ret == NSS_STATUS_SUCCESS)
159
NSS_ARGS(args)->returnval = (void*) result;
164
static NSS_STATUS _nss_winbind_passwd_destr (nss_backend_t * be, void *args)
167
NSS_DEBUG("_nss_winbind_passwd_destr");
168
return NSS_STATUS_SUCCESS;
171
static nss_backend_op_t passwd_ops[] =
173
_nss_winbind_passwd_destr,
174
_nss_winbind_endpwent_solwrap, /* NSS_DBOP_ENDENT */
175
_nss_winbind_setpwent_solwrap, /* NSS_DBOP_SETENT */
176
_nss_winbind_getpwent_solwrap, /* NSS_DBOP_GETENT */
177
_nss_winbind_getpwnam_solwrap, /* NSS_DBOP_PASSWD_BYNAME */
178
_nss_winbind_getpwuid_solwrap /* NSS_DBOP_PASSWD_BYUID */
182
_nss_winbind_passwd_constr (const char* db_name,
183
const char* src_name,
184
const char* cfg_args)
188
if(!(be = SMB_MALLOC_P(nss_backend_t)) )
191
be->ops = passwd_ops;
192
be->n_ops = sizeof(passwd_ops) / sizeof(nss_backend_op_t);
194
NSS_DEBUG("Initialized nss_winbind passwd backend");
198
/*****************************************************************
199
GROUP database backend
200
*****************************************************************/
202
static NSS_STATUS _nss_winbind_setgrent_solwrap (nss_backend_t* be, void* args)
204
NSS_DEBUG("_nss_winbind_setgrent_solwrap");
205
return _nss_winbind_setgrent();
209
_nss_winbind_endgrent_solwrap (nss_backend_t * be, void *args)
211
NSS_DEBUG("_nss_winbind_endgrent_solwrap");
212
return _nss_winbind_endgrent();
216
_nss_winbind_getgrent_solwrap(nss_backend_t* be, void* args)
219
char* buffer = NSS_ARGS(args)->buf.buffer;
220
int buflen = NSS_ARGS(args)->buf.buflen;
221
struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
222
int* errnop = &NSS_ARGS(args)->erange;
225
ret = _nss_winbind_getgrent_r(result, buffer,
228
if(ret == NSS_STATUS_SUCCESS)
230
snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning group: %s\n", result->gr_name);
232
NSS_ARGS(args)->returnval = (void*) result;
234
snprintf(logmsg, 79, "_nss_winbind_getgrent_solwrap: Returning error: %d.\n", ret);
243
_nss_winbind_getgrnam_solwrap(nss_backend_t* be, void* args)
246
struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
248
NSS_DEBUG("_nss_winbind_getgrnam_solwrap");
249
ret = _nss_winbind_getgrnam_r(NSS_ARGS(args)->key.name,
251
NSS_ARGS(args)->buf.buffer,
252
NSS_ARGS(args)->buf.buflen,
253
&NSS_ARGS(args)->erange);
255
if(ret == NSS_STATUS_SUCCESS)
256
NSS_ARGS(args)->returnval = (void*) result;
262
_nss_winbind_getgrgid_solwrap(nss_backend_t* be, void* args)
265
struct group* result = (struct group*) NSS_ARGS(args)->buf.result;
267
NSS_DEBUG("_nss_winbind_getgrgid_solwrap");
268
ret = _nss_winbind_getgrgid_r (NSS_ARGS(args)->key.gid,
270
NSS_ARGS(args)->buf.buffer,
271
NSS_ARGS(args)->buf.buflen,
272
&NSS_ARGS(args)->erange);
274
if(ret == NSS_STATUS_SUCCESS)
275
NSS_ARGS(args)->returnval = (void*) result;
281
_nss_winbind_getgroupsbymember_solwrap(nss_backend_t* be, void* args)
284
struct nss_groupsbymem *gmem = (struct nss_groupsbymem *)args;
286
NSS_DEBUG("_nss_winbind_getgroupsbymember");
288
_nss_winbind_initgroups_dyn(gmem->username,
289
gmem->gid_array[0], /* Primary Group */
297
* If the maximum number of gids have been found, return
298
* SUCCESS so the switch engine will stop searching. Otherwise
299
* return NOTFOUND so nsswitch will continue to get groups
300
* from the remaining database backends specified in the
301
* nsswitch.conf file.
303
return (gmem->numgids == gmem->maxgids ? NSS_STATUS_SUCCESS : NSS_STATUS_NOTFOUND);
307
_nss_winbind_group_destr (nss_backend_t* be, void* args)
310
NSS_DEBUG("_nss_winbind_group_destr");
311
return NSS_STATUS_SUCCESS;
314
static nss_backend_op_t group_ops[] =
316
_nss_winbind_group_destr,
317
_nss_winbind_endgrent_solwrap,
318
_nss_winbind_setgrent_solwrap,
319
_nss_winbind_getgrent_solwrap,
320
_nss_winbind_getgrnam_solwrap,
321
_nss_winbind_getgrgid_solwrap,
322
_nss_winbind_getgroupsbymember_solwrap
326
_nss_winbind_group_constr (const char* db_name,
327
const char* src_name,
328
const char* cfg_args)
332
if(!(be = SMB_MALLOC_P(nss_backend_t)) )
336
be->n_ops = sizeof(group_ops) / sizeof(nss_backend_op_t);
338
NSS_DEBUG("Initialized nss_winbind group backend");
342
/*****************************************************************
343
hosts and ipnodes backend
344
*****************************************************************/
345
#if defined(SUNOS5) /* not compatible with HP-UX */
347
/* this parser is shared between get*byname and get*byaddr, as key type
348
in request is stored in different locations, I had to provide the
349
address family as an argument, caller must free the winbind response. */
352
parse_response(int af, nss_XbyY_args_t* argp, struct winbindd_response *response)
354
struct hostent *he = (struct hostent *)argp->buf.result;
355
char *buffer = argp->buf.buffer;
356
int buflen = argp->buf.buflen;
362
struct in_addr *addrp;
363
struct in6_addr *addrp6;
366
/* response is tab separated list of ip addresses with hostname
367
and newline at the end. so at first we will strip newline
368
then construct list of addresses for hostent.
370
p = strchr(response->data.winsresp, '\n');
372
else {/* it must be broken */
373
argp->h_errno = NO_DATA;
374
return NSS_STATUS_UNAVAIL;
377
for(; p != response->data.winsresp; p--) {
378
if(*p == '\t') addrcount++;
381
if(addrcount == 0) {/* it must be broken */
382
argp->h_errno = NO_DATA;
383
return NSS_STATUS_UNAVAIL;
386
/* allocate space for addresses and h_addr_list */
388
if( he->h_addrtype == AF_INET) {
389
he->h_length = sizeof(struct in_addr);
390
addrp = (struct in_addr *)ROUND_DOWN(buffer + buflen,
391
sizeof(struct in_addr));
393
he->h_addr_list = (char **)ROUND_DOWN(addrp, sizeof (char*));
394
he->h_addr_list -= addrcount+1;
396
he->h_length = sizeof(struct in6_addr);
397
addrp6 = (struct in6_addr *)ROUND_DOWN(buffer + buflen,
398
sizeof(struct in6_addr));
400
he->h_addr_list = (char **)ROUND_DOWN(addrp6, sizeof (char*));
401
he->h_addr_list -= addrcount+1;
404
/* buffer too small?! */
405
if((char *)he->h_addr_list < buffer ) {
407
return NSS_STR_PARSE_ERANGE;
410
data = response->data.winsresp;
411
for( i = 0; i < addrcount; i++) {
412
p = strchr(data, '\t');
413
if(p == NULL) break; /* just in case... */
415
*p = '\0'; /* terminate the string */
416
if(he->h_addrtype == AF_INET) {
417
he->h_addr_list[i] = (char *)&addrp[i];
418
if ((addrp[i].s_addr = inet_addr(data)) == -1) {
420
return NSS_STR_PARSE_ERANGE;
423
he->h_addr_list[i] = (char *)&addrp6[i];
424
if (strchr(data, ':') != 0) {
425
if (inet_pton(AF_INET6, data, &addrp6[i]) != 1) {
427
return NSS_STR_PARSE_ERANGE;
431
if ((in4.s_addr = inet_addr(data)) == -1) {
433
return NSS_STR_PARSE_ERANGE;
435
IN6_INADDR_TO_V4MAPPED(&in4, &addrp6[i]);
441
he->h_addr_list[i] = (char *)NULL;
444
if(len > he->h_addr_list - (char**)argp->buf.buffer) {
446
return NSS_STR_PARSE_ERANGE;
449
/* this is a bit overkill to use _nss_netdb_aliases here since
450
there seems to be no aliases but it will create all data for us */
451
he->h_aliases = _nss_netdb_aliases(data, len, buffer,
452
((char*) he->h_addr_list) - buffer);
453
if(he->h_aliases == NULL) {
455
ret = NSS_STR_PARSE_ERANGE;
457
he->h_name = he->h_aliases[0];
459
ret = NSS_STR_PARSE_SUCCESS;
462
argp->returnval = (void*)he;
467
_nss_winbind_ipnodes_getbyname(nss_backend_t* be, void *args)
469
nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args;
470
struct winbindd_response response;
471
struct winbindd_request request;
475
ZERO_STRUCT(response);
476
ZERO_STRUCT(request);
478
/* I assume there that AI_ADDRCONFIG cases are handled in nss
479
frontend code, at least it seems done so in solaris...
481
we will give NO_DATA for pure IPv6; IPv4 will be returned for
482
AF_INET or for AF_INET6 and AI_ALL|AI_V4MAPPED we have to map
485
#ifdef HAVE_NSS_XBYY_KEY_IPNODE
486
af = argp->key.ipnode.af_family;
487
if(af == AF_INET6 && argp->key.ipnode.flags == 0) {
488
argp->h_errno = NO_DATA;
489
return NSS_STATUS_UNAVAIL;
492
/* I'm not that sure if this is correct, but... */
496
strncpy(request.data.winsreq, argp->key.name, strlen(argp->key.name)) ;
498
if( (ret = winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response))
499
== NSS_STATUS_SUCCESS ) {
500
ret = parse_response(af, argp, &response);
503
free_response(&response);
508
_nss_winbind_hosts_getbyname(nss_backend_t* be, void *args)
510
nss_XbyY_args_t *argp = (nss_XbyY_args_t*) args;
511
struct winbindd_response response;
512
struct winbindd_request request;
515
ZERO_STRUCT(response);
516
ZERO_STRUCT(request);
518
strncpy(request.data.winsreq, argp->key.name, strlen(argp->key.name));
520
if( (ret = winbindd_request_response(WINBINDD_WINS_BYNAME, &request, &response))
521
== NSS_STATUS_SUCCESS ) {
522
ret = parse_response(AF_INET, argp, &response);
525
free_response(&response);
530
_nss_winbind_hosts_getbyaddr(nss_backend_t* be, void *args)
533
struct winbindd_response response;
534
struct winbindd_request request;
535
nss_XbyY_args_t *argp = (nss_XbyY_args_t *)args;
538
ZERO_STRUCT(response);
539
ZERO_STRUCT(request);
541
/* winbindd currently does not resolve IPv6 */
542
if(argp->key.hostaddr.type == AF_INET6) {
543
argp->h_errno = NO_DATA;
544
return NSS_STATUS_UNAVAIL;
547
p = inet_ntop(argp->key.hostaddr.type, argp->key.hostaddr.addr,
548
request.data.winsreq, INET6_ADDRSTRLEN);
550
ret = winbindd_request_response(WINBINDD_WINS_BYIP, &request, &response);
552
if( ret == NSS_STATUS_SUCCESS) {
553
parse_response(argp->key.hostaddr.type, argp, &response);
555
free_response(&response);
559
/* winbind does not provide setent, getent, endent for wins */
561
_nss_winbind_common_endent(nss_backend_t* be, void *args)
563
return (NSS_STATUS_UNAVAIL);
567
_nss_winbind_common_setent(nss_backend_t* be, void *args)
569
return (NSS_STATUS_UNAVAIL);
573
_nss_winbind_common_getent(nss_backend_t* be, void *args)
575
return (NSS_STATUS_UNAVAIL);
578
static nss_backend_t*
579
_nss_winbind_common_constr (nss_backend_op_t ops[], int n_ops)
583
if(!(be = SMB_MALLOC_P(nss_backend_t)) )
593
_nss_winbind_common_destr (nss_backend_t* be, void* args)
596
return NSS_STATUS_SUCCESS;
599
static nss_backend_op_t ipnodes_ops[] = {
600
_nss_winbind_common_destr,
601
_nss_winbind_common_endent,
602
_nss_winbind_common_setent,
603
_nss_winbind_common_getent,
604
_nss_winbind_ipnodes_getbyname,
605
_nss_winbind_hosts_getbyaddr,
609
_nss_winbind_ipnodes_constr(dummy1, dummy2, dummy3)
610
const char *dummy1, *dummy2, *dummy3;
612
return (_nss_winbind_common_constr(ipnodes_ops,
613
sizeof (ipnodes_ops) / sizeof (ipnodes_ops[0])));
616
static nss_backend_op_t host_ops[] = {
617
_nss_winbind_common_destr,
618
_nss_winbind_common_endent,
619
_nss_winbind_common_setent,
620
_nss_winbind_common_getent,
621
_nss_winbind_hosts_getbyname,
622
_nss_winbind_hosts_getbyaddr,
626
_nss_winbind_hosts_constr(dummy1, dummy2, dummy3)
627
const char *dummy1, *dummy2, *dummy3;
629
return (_nss_winbind_common_constr(host_ops,
630
sizeof (host_ops) / sizeof (host_ops[0])));
633
#endif /* defined(SUNOS5) */
634
#endif /* defined(HAVE_NSS_COMMON_H) || defined(HPUX) */