Index: configure.ac =================================================================== --- configure.ac (revision 1227) +++ configure.ac (working copy) @@ -207,6 +207,15 @@ AC_DEFINE_UNQUOTED(NSLCD_SOCKET,"$NSLCD_SOCKET",[The location of the socket used for communicating.]) AC_SUBST(NSLCD_SOCKET) +# the directory PAM librabries are expected to be placed into +AC_ARG_WITH(pam-seclib-dir, + AS_HELP_STRING([--with-pam-seclib-dir=PAM_SECLIB_DIR], + [path to PAM security library]), + [ PAM_SECLIB_DIR="$with_pam_seclib_dir" ], + [ PAM_SECLIB_DIR="/lib/security" ]) +AC_DEFINE_UNQUOTED(PAM_SECLIB_DIR,"$PAM_SECLIB_DIR",[path to PAM security library]) +AC_SUBST(PAM_SECLIB_DIR) + # the SONAME to use for the NSS module AC_ARG_WITH(nss-ldap-soname, AS_HELP_STRING([--with-nss-ldap-soname=SONAME], @@ -638,6 +647,44 @@ AC_SUBST(nslcd_LIBS) fi +# Always use native linker on Solaris +# but only invoke directly if compiling with gcc (?) +case "$target_os" in +solaris*) if test "$ac_cv_prog_gcc" = yes; then + nss_ldap_so_LD="/usr/ccs/bin/ld" + pam_ldap_so_LD="/usr/ccs/bin/ld" + fi + nss_ldap_so_LDFLAGS="-Bdirect -z nodelete -Bdynamic -M \$(srcdir)/exports.solaris -G" + pam_ldap_so_LDFLAGS="-Bdirect -z nodelete -Bdynamic -M \$(srcdir)/exports.solaris -G" + NSS_LDAP_SONAME="nss_ldap.so.1" + pam_ldap_so_VERSIONED="pam_ldap.so.1" + TARGET_OS="SUNOS" ;; +linux*) nss_ldap_so_LDFLAGS="-shared -Wl,-Bdynamic -Wl,--version-script,\$(srcdir)/exports.linux" + pam_ldap_so_LDFLAGS="-shared -Wl,-Bdynamic -Wl,--version-script,\$(srcdir)/exports.linux" + NSS_LDAP_SONAME="libnss_ldap.so.2" + pam_ldap_so_VERSIONED="pam_ldap.so" + TARGET_OS="LINUX" ;; +*) nss_ldap_so_LDFLAGS="-shared -Wl,-Bdynamic" + pam_ldap_so_LDFLAGS="-shared -Wl,-Bdynamic" + NSS_LDAP_SONAME="nss_ldap.so.1" + pam_ldap_so_VERSIONED="pam_ldap.so" ;; +esac + +AC_SUBST(nss_ldap_so_LD) +AC_SUBST(nss_ldap_so_LDFLAGS) +AC_SUBST(NSS_LDAP_SONAME) + +AC_SUBST(pam_ldap_so_LD) +AC_SUBST(pam_ldap_so_LDFLAGS) +AC_SUBST(pam_ldap_so_VERSIONED) + +AC_SUBST(AIX64SUFFIX) +AM_CONDITIONAL(GCC, test "$GCC" = "yes") +AM_CONDITIONAL(GLIBC, test "$target_os" = "linux" -o "$target_os" = "linux-gnu") +AM_CONDITIONAL(USE_NATIVE_LINKER, test -n "$nss_ldap_so_LD") +AM_CONDITIONAL(SUNOS, test "x${TARGET_OS}" = "xSUNOS") +AM_CONDITIONAL(LINUX, test "x${TARGET_OS}" = "xLINUX") + # generate files AC_CONFIG_FILES([Makefile compat/Makefile common/Makefile nss/Makefile pam/Makefile nslcd/Makefile man/Makefile tests/Makefile]) Index: pam/exports.solaris =================================================================== --- pam/exports.solaris (revision 0) +++ pam/exports.solaris (revision 0) @@ -0,0 +1,18 @@ +# $Id: exports.solaris,v 1.1 2010-08-07 00:28:30 tedcheng Exp $ + +pam_ldap.so { + # published PAM service functions + global: + # pam - pluggable auth + pam_sm_acct_mgmt; + pam_sm_authenticate; + pam_sm_chauthtok; + pam_sm_close_session; + pam_sm_open_session; + pam_sm_setcred; + + # everything else should not be exported + local: + *; + +}; Index: pam/Makefile.am =================================================================== --- pam/Makefile.am (revision 1227) +++ pam/Makefile.am (working copy) @@ -24,20 +24,24 @@ pam_ldap_so_SOURCES = ../nslcd.h ../common/nslcd-prot.h \ ../compat/attrs.h pam.c common.h -pam_ldap_so_LDFLAGS = -shared -if HAVE_VERSION_SCRIPT_FLAG -pam_ldap_so_LDFLAGS += $(VERSION_SCRIPT_FLAG)\$(srcdir)/pam_ldap.map -endif pam_ldap_so_LDADD = ../common/libtio.a ../common/libprot.a -lpam \ ../compat/libcompat.a -EXTRA_DIST = pam_ldap.map +EXTRA_DIST = pam_ldap.map exports.solaris +if USE_NATIVE_LINKER +pam_ldap_so_LINK = @pam_ldap_so_LD@ @pam_ldap_so_LDFLAGS@ -o $@ +else +pam_ldap_so_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAG) -o $@ +endif + install-exec-local: install-pam_ldap_so uninstall-local: uninstall-pam_ldap_so # install pam_ldap.so install-pam_ldap_so: pam_ldap.so - $(INSTALL_PROGRAM) -D pam_ldap.so $(DESTDIR)$(libdir)/security/pam_ldap.so + $(mkinstalldirs) $(DESTDIR)/$(PAM_SECLIB_DIR) + $(INSTALL_PROGRAM) pam_ldap.so $(DESTDIR)$(PAM_SECLIB_DIR)/$(pam_ldap_soVERSIONED) + uninstall-pam_ldap_so: - -rm -f $(DESTDIR)$(libdir)/security/pam_ldap.so + -rm -f $(DESTDIR)$(PAM_SECLIB_DIR)/$(pam_ldap_so_VERSIONED) Index: nss/exports.solaris =================================================================== --- nss/exports.solaris (revision 0) +++ nss/exports.solaris (revision 0) @@ -0,0 +1,23 @@ +# $Id: exports.solaris,v 1.1 2010-08-07 00:24:21 tedcheng Exp $ + +nss_ldap.so.1 { + # published NSS service functions + global: + # Published NSS service module interfaces + # _nss_ldap_bootparams_constr; + _nss_ldap_ethers_constr; + _nss_ldap_group_constr; + _nss_ldap_hosts_constr; + _nss_ldap_networks_constr; + _nss_ldap_protocols_constr; + _nss_ldap_passwd_constr; + _nss_ldap_rpc_constr; + _nss_ldap_services_constr; + _nss_ldap_shadow_constr; + _nss_ldap_netgroup_constr; + + # everything else should not be exported + local: + *; + +}; Index: nss/hosts.c =================================================================== --- nss/hosts.c (revision 1227) +++ nss/hosts.c (working copy) @@ -2,7 +2,8 @@ hosts.c - NSS lookup functions for hosts database Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008 Arthur de Jong + Copyright (C) 2006, 2007,2008,2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -179,12 +180,80 @@ /* this function just calls the gethostbyname2() variant with the address familiy set */ +#ifdef HAVE_NSSWITCH_H +static nss_status_t _nss_ldap_gethostbyname_r(nss_backend_t *be,void *args) +{ + struct hostent priv_host; + struct hostent *host=NSS_ARGS(args)->buf.result?NSS_ARGS(args)->buf.result:&priv_host; + char *data_ptr; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + int h_errno; + nss_status_t status; + status=_nss_ldap_gethostbyname2_r( + NSS_ARGS(args)->key.name, + AF_INET, + host, + NSS_ARGS(args)->buf.buffer, + NSS_ARGS(args)->buf.buflen, + &errno,&h_errno); + + if (status!=NSS_STATUS_SUCCESS) + { + NSS_ARGS(args)->h_errno=h_errno; + return status; + } + + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + if (host->h_addr_list) + { + int i; + struct in_addr in; + (void)memcpy(&in.s_addr,host->h_addr_list[0],sizeof(in.s_addr)); + sprintf(data_ptr,"%s %s",inet_ntoa(in),host->h_name); + if (host->h_aliases) + { + int j; + for (j=0; host->h_aliases[j]; j++) + { + strcat(data_ptr," "); + strcat(data_ptr,host->h_aliases[j]); + } + } + for (i=1; host->h_addr_list[i]; i++) + { + (void) memcpy(&in.s_addr,host->h_addr_list[i],sizeof(in.s_addr)); + strcat(data_ptr,"\n"); + strcat(data_ptr,inet_ntoa(in)); + strcat(data_ptr," "); + strcat(data_ptr,host->h_name); + /* TODO: aliases only supplied to the first address */ + /* need review */ + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { /* NSS_ARGS(args)->buf.result!=NULL */ + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + NSS_ARGS(args)->h_errno=h_errno; + return status; +} +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_gethostbyname_r( const char *name,struct hostent *result, char *buffer,size_t buflen,int *errnop,int *h_errnop) { return _nss_ldap_gethostbyname2_r(name,AF_INET,result,buffer,buflen,errnop,h_errnop); } +#endif /* HAVE_NSSWITCH_H */ /* write an address value */ #define WRITE_ADDRESS(fp,af,len,addr) \ @@ -200,7 +269,11 @@ result - OUT - entry found buffer,buflen - OUT - buffer to store allocated stuff on errnop,h_errnop - OUT - for reporting errors */ +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_gethostbyaddr_r( +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_gethostbyaddr_r( +#endif /* HAVE_NSSWITCH_H */ const void *addr,socklen_t len,int af,struct hostent *result, char *buffer,size_t buflen,int *errnop,int *h_errnop) { @@ -212,13 +285,21 @@ /* thread-local file pointer to an ongoing request */ static __thread TFILE *hostentfp; +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_sethostent(nss_backend_t *hosts_context,void *fakeargs) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_sethostent(int UNUSED(stayopen)) +#endif /* HAVE_NSSWITCH_H */ { NSS_SETENT(hostentfp); } /* this function only returns addresses of the AF_INET address family */ +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_gethostent_r( +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_gethostent_r( +#endif /* HAVE_NSSWITCH_H */ struct hostent *result, char *buffer,size_t buflen,int *errnop,int *h_errnop) { @@ -226,7 +307,166 @@ read_hostent_nextonempty(hostentfp,AF_INET,result,buffer,buflen,errnop,h_errnop)); } +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_endhostent(nss_backend_t *hosts_context,void *fakeargs ) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_endhostent(void) +#endif /* HAVE_NSSWITCH_H */ { NSS_ENDENT(hostentfp); } + +#ifdef HAVE_NSSWITCH_H + +static nss_status_t _nss_ldap_gethostbyaddr_r(nss_backend_t *be,void *args) +{ + struct in_addr iaddr; + int type; + struct hostent priv_host; + struct hostent *host=NSS_ARGS(args)->buf.result?NSS_ARGS(args)->buf.result:&priv_host; + char *data_ptr; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + int h_errno; + nss_status_t status; + status=_nss_nslcd_gethostbyaddr_r( + NSS_ARGS(args)->key.hostaddr.addr, + NSS_ARGS(args)->key.hostaddr.len, + NSS_ARGS(args)->key.hostaddr.type, + host, + NSS_ARGS(args)->buf.buffer, + NSS_ARGS(args)->buf.buflen, + &errno,&h_errno); + if (status!=NSS_STATUS_SUCCESS) + { + NSS_ARGS(args)->h_errno=h_errno; + return status; + } + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + if (host->h_addr_list) + { + int i; + struct in_addr in; + (void) memcpy(&in.s_addr,host->h_addr_list[0],sizeof(in.s_addr)); + sprintf(data_ptr,"%s %s",inet_ntoa(in),host->h_name); + if (host->h_aliases) + { + int j; + for (j=0; host->h_aliases[j]; j++) + { + strcat(data_ptr," "); + strcat(data_ptr,host->h_aliases[j]); + } + } + for (i=1; host->h_addr_list[i]; i++) + { + (void) memcpy(&in.s_addr,host->h_addr_list[i],sizeof(in.s_addr)); + strcat(data_ptr,"\n"); + strcat(data_ptr,inet_ntoa(in)); + strcat(data_ptr," "); + strcat(data_ptr,host->h_name); + /* TODO: aliases only supplied to the first address */ + /* need review */ + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { /* NSS_ARGS(args)->buf.result!=NULL */ + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + NSS_ARGS(args)->h_errno=h_errno; + return status; +} + +/* this function only returns addresses of the AF_INET address family */ +static nss_status_t _nss_ldap_gethostent_r(nss_backend_t *hosts_context,void *args) +{ + struct hostent priv_host; + struct hostent *host=NSS_ARGS(args)->buf.result ? + NSS_ARGS(args)->buf.result : &priv_host; + char *data_ptr; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + int h_errno; + nss_status_t status; + status=_nss_nslcd_gethostent_r(host,buffer,buflen,&errno,&h_errno); + if (status!=NSS_STATUS_SUCCESS) + { + NSS_ARGS(args)->h_errno=h_errno; + return status; + } + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + if (host->h_addr_list) + { + int i; + sprintf(data_ptr,"%s %s",host->h_addr_list[0],host->h_name); + if (host->h_aliases) + { + int j; + for (j=0; host->h_aliases[j]; j++) + { + strcat(data_ptr," "); + strcat(data_ptr,host->h_aliases[j]); + } + } + for (i=1; host->h_addr_list[i]; i++) + { + strcat(data_ptr,"\n"); + strcat(data_ptr,host->h_addr_list[i]); + strcat(data_ptr," "); + strcat(data_ptr,host->h_name); + /* TODO: aliases only supplied to the first address */ + /* need review */ + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { /* NSS_ARGS(args)->buf.result!=NULL */ + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + NSS_ARGS(args)->h_errno=h_errno; + return status; +} + +static nss_status_t _nss_ldap_hosts_destr(nss_backend_t *hosts_context,void *args) +{ + return _nss_ldap_default_destr(hosts_context,args); +} + +static nss_backend_op_t host_ops[]={ + _nss_ldap_hosts_destr, + _nss_ldap_endhostent, + _nss_ldap_sethostent, + _nss_ldap_gethostent_r, + _nss_ldap_gethostbyname_r, + _nss_ldap_gethostbyaddr_r +}; + +nss_backend_t *_nss_ldap_hosts_constr(const char *db_name, + const char *src_name,const char *cfg_args) +{ + nss_ldap_backend_t *be; + if (!(be=(nss_ldap_backend_t *)malloc(sizeof(*be)))) + return NULL; + be->ops=host_ops; + be->n_ops=sizeof(host_ops)/sizeof(nss_backend_op_t); + if (_nss_ldap_default_constr(be)!=NSS_STATUS_SUCCESS) + return NULL; + return (nss_backend_t *)be; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/passwd.c =================================================================== --- nss/passwd.c (revision 1227) +++ nss/passwd.c (working copy) @@ -2,7 +2,8 @@ passwd.c - NSS lookup functions for passwd database Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008 Arthur de Jong + Copyright (C) 2006, 2007,2008,2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -45,14 +46,26 @@ return NSS_STATUS_SUCCESS; } -nss_status_t _nss_ldap_getpwnam_r(const char *name,struct passwd *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getpwnam_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getpwnam_r( +#endif /* HAVE_NSSWITCH_H */ + const char *name,struct passwd *result,char *buffer,size_t buflen, + int *errnop) { NSS_BYNAME(NSLCD_ACTION_PASSWD_BYNAME, name, read_passwd(fp,result,buffer,buflen,errnop)); } -nss_status_t _nss_ldap_getpwuid_r(uid_t uid,struct passwd *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getpwuid_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getpwuid_r( +#endif /* HAVE_NSSWITCH_H */ + uid_t uid,struct passwd *result,char *buffer, + size_t buflen,int *errnop) { NSS_BYTYPE(NSLCD_ACTION_PASSWD_BYUID, uid,uid_t, @@ -63,20 +76,168 @@ static __thread TFILE *pwentfp; /* open a connection to the nslcd and write the request */ +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_setpwent(nss_backend_t *be,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_setpwent(int UNUSED(stayopen)) +#endif /* HAVE_NSSWITCH_H */ { NSS_SETENT(pwentfp); } /* read password data from an opened stream */ -nss_status_t _nss_ldap_getpwent_r(struct passwd *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getpwent_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getpwent_r( +#endif /* HAVE_NSSWITCH_H */ + struct passwd *result,char *buffer,size_t buflen,int *errnop) { NSS_GETENT(pwentfp,NSLCD_ACTION_PASSWD_ALL, read_passwd(pwentfp,result,buffer,buflen,errnop)); } /* close the stream opened with setpwent() above */ +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_endpwent(nss_backend_t *be,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_endpwent(void) +#endif /* HAVE_NSSWITCH_H */ { NSS_ENDENT(pwentfp); } + +#ifdef HAVE_NSSWITCH_H +static nss_status_t _nss_ldap_getpwnam_r(nss_backend_t *be,void *args) +{ + struct passwd priv_pw; + struct passwd *pw=NSS_ARGS(args)->buf.result?(struct passwd *)NSS_ARGS(args)->buf.result:&priv_pw; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *name=(char *)NSS_ARGS(args)->key.name; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + status=NSS_STATUS_TRYAGAIN; + return status; + } + status=_nss_nslcd_getpwnam_r(name,pw,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s:%s:%d:%d:%s:%s:%s", + pw->pw_name,"x",(int) pw->pw_uid,(int) pw->pw_gid,pw->pw_gecos, + pw->pw_dir,pw->pw_shell); + /* copy file-format data to buffer provided by front-end */ + strcpy(buffer,data_ptr); + if (data_ptr) + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getpwuid_r(nss_backend_t *be,void *args) +{ + struct passwd priv_pw; + struct passwd *pw=NSS_ARGS(args)->buf.result ? + NSS_ARGS(args)->buf.result : &priv_pw; + uid_t uid=NSS_ARGS(args)->key.uid; + char *data_ptr; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + nss_status_t status; + status=_nss_nslcd_getpwuid_r(uid,pw,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc((size_t) buflen); + sprintf(data_ptr,"%s:%s:%d:%d:%s:%s:%s", + pw->pw_name,"x",(int) pw->pw_uid,(int) pw->pw_gid,pw->pw_gecos, + pw->pw_dir,pw->pw_shell); + /* copy file-format data to buffer provided by front-end */ + strcpy(buffer,data_ptr); + if (data_ptr) + free((void *)data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getpwent_r(nss_backend_t *be,void *args) +{ + struct passwd priv_pw; + struct passwd *pw=NSS_ARGS(args)->buf.result?(struct passwd *)NSS_ARGS(args)->buf.result:&priv_pw; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + status=_nss_nslcd_getpwent_r(pw,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s:%s:%d:%d:%s:%s:%s", + pw->pw_name,"x",(int) pw->pw_uid,(int) pw->pw_gid,pw->pw_gecos, + pw->pw_dir,pw->pw_shell); + /* copy file-format data to buffer provided by front-end */ + strcpy(buffer,data_ptr); + if (data_ptr) + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_passwd_destr(nss_backend_t *pw_context,void *args) +{ + return _nss_ldap_default_destr(pw_context,args); +} + +static nss_backend_op_t passwd_ops[]={ + _nss_ldap_passwd_destr, + _nss_ldap_endpwent, /* NSS_DBOP_ENDENT */ + _nss_ldap_setpwent, /* NSS_DBOP_SETENT */ + _nss_ldap_getpwent_r, /* NSS_DBOP_GETENT */ + _nss_ldap_getpwnam_r, /* NSS_DBOP_PASSWD_BYNAME */ + _nss_ldap_getpwuid_r /* NSS_DBOP_PASSWD_BYUID */ +}; + +nss_backend_t *_nss_ldap_passwd_constr(const char *db_name, + const char *src_name,const char *cfg_args) +{ + nss_ldap_backend_t *be; + if (!(be=(nss_ldap_backend_t *)malloc(sizeof(*be)))) + return NULL; + be->ops=passwd_ops; + be->n_ops=sizeof(passwd_ops)/sizeof(nss_backend_op_t); + if (_nss_ldap_default_constr(be)!=NSS_STATUS_SUCCESS) + return NULL; + return (nss_backend_t *)be; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/netgroup.c =================================================================== --- nss/netgroup.c (revision 1227) +++ nss/netgroup.c (working copy) @@ -2,7 +2,8 @@ netgroup.c - NSS lookup functions for netgroup entries Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008 Arthur de Jong + Copyright (C) 2006, 2007,2008,2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -30,6 +31,51 @@ #include "common.h" #include "compat/attrs.h" +#ifdef HAVE_NSSWITCH_H +#include +#include +#include +#endif /* HAVE_NSSWITCH_H */ + + +#ifdef HAVE_NSSWITCH_H + +static nss_backend_op_t netgroup_ops[]; +static nss_status_t _nss_ldap_netgroup_destr(nss_backend_t *_ngbe,void *args); + +/* find a netgroup that has not been traversed */ +static char *_nss_ldap_chase_netgroup(nss_ldap_netgr_backend_t *ngbe) +{ + nss_status_t status; + char *group=NULL; + int found=0; + if (!ngbe->needed_groups) + { + /* exhausted all netgroups */ + return NULL; + } + while (ngbe->needed_groups&&!found) + { + if (_nss_ldap_namelist_find(ngbe->known_groups, + ngbe->needed_groups->name)) + { + /* netgroup seen before,ignore it */ + _nss_ldap_namelist_pop(&ngbe->needed_groups); + } + else + found=1; + } + if (found) + { + group=strdup(ngbe->needed_groups->name); + status=_nss_ldap_namelist_push(&ngbe->known_groups, + ngbe->needed_groups->name); + _nss_ldap_namelist_pop(&ngbe->needed_groups); + } + return group; +} +#endif /* HAVE_NSSWITCH_H */ + /* we redefine this here because we need to return NSS_STATUS_RETURN instead of NSS_STATUS_NOTFOUND */ #undef ERROR_OUT_NOSUCCESS @@ -89,8 +135,20 @@ /* thread-local file pointer to an ongoing request */ static __thread TFILE *netgrentfp; -nss_status_t _nss_ldap_setnetgrent(const char *group,struct __netgrent UNUSED(*result)) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_setnetgrent(nss_backend_t *be,void *_args) { + return NSS_STATUS_SUCCESS; +} +#endif /* HAVE_NSSWITCH_H */ + +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_setnetgrent( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_setnetgrent( +#endif /* HAVE_NSSWITCH_H */ + const char *group,struct __netgrent UNUSED(* result)) +{ /* we cannot use NSS_SETENT() here because we have a parameter that is only available in this function */ int32_t tmpint32; @@ -107,13 +165,180 @@ return NSS_STATUS_SUCCESS; } -nss_status_t _nss_ldap_getnetgrent_r(struct __netgrent *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getnetgrent_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getnetgrent_r( +#endif /* HAVE_NSSWITCH_H */ + struct __netgrent *result,char *buffer,size_t buflen,int *errnop) { NSS_GETENT(netgrentfp,NSLCD_ACTION_NETGROUP_BYNAME, read_netgrent(netgrentfp,result,buffer,buflen,errnop)); } +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_endnetgrent(nss_backend_t *be,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_endnetgrent(struct __netgrent UNUSED(* result)) +#endif /* HAVE_NSSWITCH_H */ { NSS_ENDENT(netgrentfp); } + +#ifdef HAVE_NSSWITCH_H + +nss_status_t _nss_ldap_getnetgrent_r(nss_backend_t *_be,void *_args) +{ + nss_ldap_netgr_backend_t *ngbe=(nss_ldap_netgr_backend_t *)_be; + struct nss_getnetgrent_args *args=(struct nss_getnetgrent_args *)_args; + struct __netgrent result; + char *group=NULL; + int done=0; + int err; + nss_status_t status,rc; + args->status=NSS_NETGR_NO; + while (!done) + { + status=_nss_nslcd_getnetgrent_r(&result,args->buffer,args->buflen, + &err); + if (status!=NSS_STATUS_SUCCESS) + { + if (err==ENOENT) + { + /* done with the current netgroup */ + /* explore nested netgroup,if any */ + int found=0; + while (!found) + { + /* find a nested netgroup to pursue further */ + group=_nss_ldap_chase_netgroup(ngbe); + if (!group) + { + /* no more netgroup */ + found=1; done = 1; + errno=ENOENT; + } + else + { + rc=_nss_nslcd_setnetgrent(group,&result); + if (rc==NSS_STATUS_SUCCESS) + found=1; + free(group); + group=NULL; + } + } /* while !found */ + } + else + { /* err!=ENOENT */ + done=1; + } + } + else + { /* status==NSS_STATUS_SUCCESS */ + if (result.type==group_val) + { + /* a netgroup nested within the current netgroup */ + rc=_nss_ldap_namelist_push(&ngbe->needed_groups,result.val.group); + if (rc!=NSS_STATUS_SUCCESS) + { + /* unable to push the group name for later netgroup */ + } + } + else if (result.type==triple_val) + { + args->retp[NSS_NETGR_MACHINE]=result.val.triple.host; + args->retp[NSS_NETGR_USER]=result.val.triple.user; + args->retp[NSS_NETGR_DOMAIN]=result.val.triple.domain; + args->status=NSS_NETGR_FOUND; + done=1; + } + else + { + /* NSS_STATUS_SUCCESS,but type is not group_val or triple_val */ + /* should not be here,log a message */ + status=NSS_STATUS_NOTFOUND; + done=1; + } + } + } /* while !done */ + return status; +} + +static nss_status_t _nss_ldap_netgr_set(nss_backend_t *be,void *_args) +{ + nss_status_t stat; + struct nss_setnetgrent_args *args; + nss_ldap_netgr_backend_t *ngbe; + struct __netgrent result; + char *group=NULL; + args=(struct nss_setnetgrent_args *)_args; + args->iterator=NULL; /* initialize */ + ngbe=(nss_ldap_netgr_backend_t *)malloc(sizeof(*ngbe)); + if (ngbe==NULL) + return NSS_STATUS_UNAVAIL; + ngbe->ops=netgroup_ops; + ngbe->n_ops=6; + ngbe->state=NULL; + ngbe->known_groups=NULL; + ngbe->needed_groups=NULL; + stat=_nss_ldap_default_constr((nss_ldap_backend_t *)ngbe); + if (stat!=NSS_STATUS_SUCCESS) + { + free(ngbe); + return stat; + } + group=(char *)args->netgroup; + stat=_nss_nslcd_setnetgrent(group,&result); + if (stat!=NSS_STATUS_SUCCESS) + { + _nss_ldap_default_destr((nss_backend_t *)ngbe,NULL); + return stat; + } + /* place the group name in known list */ + stat=_nss_ldap_namelist_push(&ngbe->known_groups,group); + if (stat!=NSS_STATUS_SUCCESS) + { + _nss_ldap_netgroup_destr((nss_backend_t *)ngbe,NULL); + return stat; + } + args->iterator=(nss_backend_t *)ngbe; + return stat; +} + +static nss_status_t _nss_ldap_netgroup_destr(nss_backend_t *_ngbe,void *args) +{ + nss_ldap_netgr_backend_t *ngbe=(nss_ldap_netgr_backend_t *)_ngbe; + /* free list of nested netgroups */ + _nss_ldap_namelist_destroy(&ngbe->known_groups); + _nss_ldap_namelist_destroy(&ngbe->needed_groups); + return _nss_ldap_default_destr(_ngbe,args); +} + +static nss_backend_op_t netgroup_ops[]={ + _nss_ldap_netgroup_destr, /* NSS_DBOP_DESTRUCTOR */ + _nss_ldap_endnetgrent, /* NSS_DBOP_ENDENT */ + _nss_ldap_setnetgrent, /* NSS_DBOP_SETNET */ + _nss_ldap_getnetgrent_r, /* NSS_DBOP_GETENT */ + NULL,/* TODO:_nss_ldap_netgr_in,*/ /* NSS_DBOP_NETGROUP_IN */ + _nss_ldap_netgr_set /* NSS_DBOP_NETGROUP_SET */ +}; + +nss_backend_t *_nss_ldap_netgroup_constr(const char *db_name, + const char *src_name,const char *cfg_args) +{ + nss_ldap_netgr_backend_t *be; + if (!(be=(nss_ldap_netgr_backend_t *)malloc(sizeof(*be)))) + return NULL; + be->ops=netgroup_ops; + be->n_ops=sizeof(netgroup_ops)/sizeof(nss_backend_op_t); + be->known_groups=NULL; + be->needed_groups=NULL; + if (_nss_ldap_default_constr((nss_ldap_backend_t *)be)!=NSS_STATUS_SUCCESS) + { + free(be); + return NULL; + } + return (nss_backend_t *)be; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/networks.c =================================================================== --- nss/networks.c (revision 1227) +++ nss/networks.c (working copy) @@ -2,7 +2,8 @@ networks.c - NSS lookup functions for networks database Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008 Arthur de Jong + Copyright (C) 2006, 2007,2008,2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -99,7 +100,13 @@ return retv; } -nss_status_t _nss_ldap_getnetbyname_r(const char *name,struct netent *result,char *buffer,size_t buflen,int *errnop,int *h_errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getnetbyname_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getnetbyname_r( +#endif /* HAVE_NSSWITCH_H */ + const char *name,struct netent *result,char *buffer, + size_t buflen,int *errnop,int *h_errnop) { NSS_BYNAME(NSLCD_ACTION_NETWORK_BYNAME, name, @@ -116,7 +123,13 @@ /* Note: the af parameter is ignored and is assumed to be AF_INET */ /* TODO: implement handling of af parameter */ -nss_status_t _nss_ldap_getnetbyaddr_r(uint32_t addr,int UNUSED(af),struct netent *result,char *buffer,size_t buflen,int *errnop,int *h_errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getnetbyaddr_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getnetbyaddr_r( +#endif /* HAVE_NSSWITCH_H */ + uint32_t addr,int UNUSED(af),struct netent *result, + char *buffer,size_t buflen,int *errnop,int *h_errnop) { NSS_BYGEN(NSLCD_ACTION_NETWORK_BYADDR, WRITE_ADDRESS(fp,addr), @@ -126,18 +139,213 @@ /* thread-local file pointer to an ongoing request */ static __thread TFILE *netentfp; +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_setnetent(nss_backend_t *net_context,void *fakeargs) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_setnetent(int UNUSED(stayopen)) +#endif /* HAVE_NSSWITCH_H */ { NSS_SETENT(netentfp); } -nss_status_t _nss_ldap_getnetent_r(struct netent *result,char *buffer,size_t buflen,int *errnop,int *h_errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getnetent_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getnetent_r( +#endif /* HAVE_NSSWITCH_H */ + struct netent *result,char *buffer,size_t buflen, + int *errnop,int *h_errnop) { NSS_GETENT(netentfp,NSLCD_ACTION_NETWORK_ALL, read_netent(netentfp,result,buffer,buflen,errnop,h_errnop)); } +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_endnetent(nss_backend_t *net_context,void *fakeargs) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_endnetent(void) +#endif /* HAVE_NSSWITCH_H */ { NSS_ENDENT(netentfp); } + +#ifdef HAVE_NSSWITCH_H +static nss_status_t _nss_ldap_getnetbyname_r(nss_backend_t *be,void *args) +{ + struct netent priv_network; + struct netent *network=NSS_ARGS(args)->buf.result?(struct netent *)NSS_ARGS(args)->buf.result:&priv_network; + char *name=(char *)NSS_ARGS(args)->key.name; + int af=NSS_ARGS(args)->key.netaddr.type; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + int h_errno; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getnetbyname_r(name,network,buffer, + buflen,&errno,&h_errno); + if (status!=NSS_STATUS_SUCCESS) + { + NSS_ARGS(args)->h_errno=h_errno; + return status; + } + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s %s",name,inet_ntoa(network->n_net)); /* ipNetworkNumber */ + if (network->n_aliases) + { + int i; + for (i=0; network->n_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,network->n_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + NSS_ARGS(args)->h_errno=h_errno; + return status; +} +#endif /* HAVE_NSSWITCH_H */ + +/* Note: the af parameter is ignored and is assumed to be AF_INET */ +/* TODO: implement handling of af parameter */ +#ifdef HAVE_NSSWITCH_H +static nss_status_t _nss_ldap_getnetbyaddr_r(nss_backend_t *be,void *args) +{ + struct netent priv_network; + struct netent *network=NSS_ARGS(args)->buf.result?(struct netent *)NSS_ARGS(args)->buf.result:&priv_network; + int addr=NSS_ARGS(args)->key.netaddr.net; + int af=NSS_ARGS(args)->key.netaddr.type; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + int h_errno; + char *data_ptr; + struct in_addr in_addr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getnetbyaddr_r(addr,af,network,buffer,buflen,&errno,&h_errno); + if (status!=NSS_STATUS_SUCCESS) + { + NSS_ARGS(args)->h_errno=h_errno; + return status; + } + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + (void)memcpy(&in_addr.s_addr,addr,sizeof(in_addr.s_addr)); + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s %s",network->n_name, + inet_ntoa(in_addr)); /* ipNetworkNumber */ + if (network->n_aliases) + { + int i; + for (i=0; network->n_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,network->n_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + NSS_ARGS(args)->h_errno=h_errno; + return status; +} + +static nss_status_t _nss_ldap_getnetent_r(nss_backend_t *net_context,void *args) +{ + struct netent priv_network; + struct netent *network=NSS_ARGS(args)->buf.result?(struct netent *)NSS_ARGS(args)->buf.result:&priv_network; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + int h_errno; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getnetent_r(network,buffer,buflen,&errno,&h_errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s %s",network->n_name, + inet_ntoa(network->n_net)); /* ipNetworkNumber */ + if (network->n_aliases) + { + int i; + for (i=0; network->n_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,network->n_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + NSS_ARGS(args)->h_errno=h_errno; + return status; +} + +static nss_status_t _nss_ldap_networks_destr(nss_backend_t *net_context,void *args) +{ + return _nss_ldap_default_destr(net_context,args); +} + +static nss_backend_op_t net_ops[]={ + _nss_ldap_networks_destr, + _nss_ldap_endnetent, + _nss_ldap_setnetent, + _nss_ldap_getnetent_r, + _nss_ldap_getnetbyname_r, + _nss_ldap_getnetbyaddr_r +}; + +nss_backend_t *_nss_ldap_networks_constr(const char *db_name, + const char *src_name,const char *cfg_args) +{ + nss_ldap_backend_t *be; + if (!(be=(nss_ldap_backend_t *)malloc(sizeof(*be)))) + return NULL; + be->ops=net_ops; + be->n_ops=sizeof(net_ops)/sizeof(nss_backend_op_t); + if (_nss_ldap_default_constr(be)!=NSS_STATUS_SUCCESS) + return NULL; + return (nss_backend_t *)be; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/services.c =================================================================== --- nss/services.c (revision 1227) +++ nss/services.c (working copy) @@ -2,7 +2,8 @@ service.c - NSS lookup functions for services database Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008 Arthur de Jong + Copyright (C) 2006, 2007,2008,2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -37,7 +38,6 @@ size_t bufptr=0; READ_BUF_STRING(fp,result->s_name); READ_BUF_STRINGLIST(fp,result->s_aliases); - /* store port number in network byte order */ READ_TYPE(fp,tmpint32,int32_t); result->s_port=htons((uint16_t)tmpint32); READ_BUF_STRING(fp,result->s_proto); @@ -45,7 +45,13 @@ return NSS_STATUS_SUCCESS; } -nss_status_t _nss_ldap_getservbyname_r(const char *name,const char *protocol,struct servent *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getservbyname_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getservbyname_r( +#endif /* HAVE_NSSWITCH_H */ + const char *name,const char *protocol,struct servent *result, + char *buffer,size_t buflen,int *errnop) { NSS_BYGEN(NSLCD_ACTION_SERVICE_BYNAME, WRITE_STRING(fp,name);WRITE_STRING(fp,protocol), @@ -53,7 +59,13 @@ } -nss_status_t _nss_ldap_getservbyport_r(int port,const char *protocol,struct servent *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getservbyport_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getservbyport_r( +#endif /* HAVE_NSSWITCH_H */ + int port,const char *protocol,struct servent *result, + char *buffer,size_t buflen,int *errnop) { NSS_BYGEN(NSLCD_ACTION_SERVICE_BYNUMBER, WRITE_INT32(fp,ntohs(port));WRITE_STRING(fp,protocol), @@ -63,18 +75,181 @@ /* thread-local file pointer to an ongoing request */ static __thread TFILE *protoentfp; +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_setservent(nss_backend_t *serv_context,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_setservent(int UNUSED(stayopen)) +#endif /* HAVE_NSSWITCH_H */ { NSS_SETENT(protoentfp); } -nss_status_t _nss_ldap_getservent_r(struct servent *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getservent_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getservent_r( +#endif /* HAVE_NSSWITCH_H */ + struct servent *result,char *buffer,size_t buflen,int *errnop) { NSS_GETENT(protoentfp,NSLCD_ACTION_SERVICE_ALL, read_servent(protoentfp,result,buffer,buflen,errnop)); } +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_endservent(nss_backend_t *serv_context,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_endservent(void) +#endif /* HAVE_NSSWITCH_H */ { NSS_ENDENT(protoentfp); } + +#ifdef HAVE_NSSWITCH_H + +static nss_status_t _nss_ldap_getservbyname_r(nss_backend_t *be,void *args) +{ + char *name=(char *)NSS_ARGS(args)->key.serv.serv.name; + char *protocol=NSS_ARGS(args)->key.serv.proto?(char *)NSS_ARGS(args)->key.serv.proto:""; + struct servent priv_service; + struct servent *service=NSS_ARGS(args)->buf.result?(struct servent *)NSS_ARGS(args)->buf.result:&priv_service; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + status=_nss_nslcd_getservbyname_r(name,protocol,service, + buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s %d/%s",name,service->s_port, + service->s_proto); + if (service->s_aliases) + { + int i; + for (i=0; service->s_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,service->s_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getservbyport_r(nss_backend_t *be,void *args) +{ + int port=NSS_ARGS(args)->key.serv.serv.port; + char *protocol=(char *)NSS_ARGS(args)->key.serv.proto; + struct servent priv_service; + struct servent *service=NSS_ARGS(args)->buf.result?(struct servent *)NSS_ARGS(args)->buf.result:&priv_service; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + status=_nss_nslcd_getservbyport_r(port,protocol,service,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s %d/%s",service->s_name,port, + service->s_proto); + if (service->s_aliases) + { + int i; + for (i=0; service->s_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,service->s_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getservent_r(nss_backend_t *serv_context,void *args) +{ + struct servent priv_service; + struct servent *service=NSS_ARGS(args)->buf.result?(struct servent *)NSS_ARGS(args)->buf.result:&priv_service; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + status=_nss_nslcd_getservent_r(service,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s %d/%s",service->s_name,service->s_port, + service->s_proto); + if (service->s_aliases) + { + int i; + for (i=0; service->s_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,service->s_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_services_destr(nss_backend_t *serv_context,void *args) +{ + return _nss_ldap_default_destr(serv_context,args); +} + +static nss_backend_op_t services_ops[]={ + _nss_ldap_services_destr, + _nss_ldap_endservent, + _nss_ldap_setservent, + _nss_ldap_getservent_r, + _nss_ldap_getservbyname_r, + _nss_ldap_getservbyport_r +}; + +nss_backend_t *_nss_ldap_services_constr(const char *db_name, + const char *src_name,const char *cfg_args) +{ + nss_ldap_backend_t *be; + if (!(be=(nss_ldap_backend_t *)malloc(sizeof(*be)))) + return NULL; + be->ops=services_ops; + be->n_ops=sizeof(services_ops)/sizeof(nss_backend_op_t); + if (_nss_ldap_default_constr(be)!=NSS_STATUS_SUCCESS) + return NULL; + return (nss_backend_t *)be; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/protocols.c =================================================================== --- nss/protocols.c (revision 1227) +++ nss/protocols.c (working copy) @@ -2,7 +2,8 @@ protocols.c - NSS lookup functions for protocol database Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008 Arthur de Jong + Copyright (C) 2006, 2007,2008,2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -41,14 +42,26 @@ return NSS_STATUS_SUCCESS; } -nss_status_t _nss_ldap_getprotobyname_r(const char *name,struct protoent *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getprotobyname_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getprotobyname_r( +#endif /* HAVE_NSSWITCH_H */ + const char *name,struct protoent *result,char *buffer, + size_t buflen,int *errnop) { NSS_BYNAME(NSLCD_ACTION_PROTOCOL_BYNAME, name, read_protoent(fp,result,buffer,buflen,errnop)); } -nss_status_t _nss_ldap_getprotobynumber_r(int number,struct protoent *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getprotobynumber_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getprotobynumber_r( +#endif /* HAVE_NSSWITCH_H */ + int number,struct protoent *result,char *buffer, + size_t buflen,int *errnop) { NSS_BYINT32(NSLCD_ACTION_PROTOCOL_BYNUMBER, number, @@ -58,18 +71,191 @@ /* thread-local file pointer to an ongoing request */ static __thread TFILE *protoentfp; +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_setprotoent(nss_backend_t *proto_context,void *fakeargs) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_setprotoent(int UNUSED(stayopen)) +#endif /* HAVE_NSSWITCH_H */ { NSS_SETENT(protoentfp); } -nss_status_t _nss_ldap_getprotoent_r(struct protoent *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getprotoent_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getprotoent_r( +#endif /* HAVE_NSSWITCH_H */ + struct protoent *result,char *buffer,size_t buflen,int *errnop) { NSS_GETENT(protoentfp,NSLCD_ACTION_PROTOCOL_ALL, read_protoent(protoentfp,result,buffer,buflen,errnop)); } +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_endprotoent(nss_backend_t *proto_context,void *fakeargs) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_endprotoent(void) +#endif /* HAVE_NSSWITCH_H */ + { NSS_ENDENT(protoentfp); } + +#ifdef HAVE_NSSWITCH_H + +static nss_status_t _nss_ldap_getprotobyname_r(nss_backend_t *be,void *args) +{ + struct protoent priv_proto; + struct protoent *proto=NSS_ARGS(args)->buf.result?(struct protoent *)NSS_ARGS(args)->buf.result:&priv_proto; + char *name=(char *)NSS_ARGS(args)->key.name; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getprotobyname_r(name,proto ,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s\t\t%d",proto->p_name,proto->p_proto); + if (proto->p_aliases) + { + int i; + for (i=0; proto->p_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,proto->p_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getprotobynumber_r(nss_backend_t *be,void *args) +{ + struct protoent priv_proto; + struct protoent *proto=NSS_ARGS(args)->buf.result?(struct protoent *)NSS_ARGS(args)->buf.result:&priv_proto; + int number=NSS_ARGS(args)->key.number; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen<0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getprotobynumber_r(number,proto,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s\t\t%d",proto->p_name,proto->p_proto); + if (proto->p_aliases) + { + int i; + for (i=0; proto->p_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,proto->p_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getprotoent_r(nss_backend_t *proto_context,void *args) +{ + struct protoent priv_proto; + struct protoent *proto=NSS_ARGS(args)->buf.result?(struct protoent *)NSS_ARGS(args)->buf.result:&priv_proto; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getprotoent_r(proto,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s\t\t%d",proto->p_name,proto->p_proto); + if (proto->p_aliases) + { + int i; + for (i=0; proto->p_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,proto->p_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_protocols_destr(nss_backend_t *proto_context,void *args) +{ + return _nss_ldap_default_destr(proto_context,args); +} + +static nss_backend_op_t proto_ops[]={ + _nss_ldap_protocols_destr, + _nss_ldap_endprotoent, + _nss_ldap_setprotoent, + _nss_ldap_getprotoent_r, + _nss_ldap_getprotobyname_r, + _nss_ldap_getprotobynumber_r +}; + +nss_backend_t *_nss_ldap_protocols_constr(const char *db_name, + const char *src_name,const char *cfg_args) +{ + nss_ldap_backend_t *be; + if (!(be=(nss_ldap_backend_t *)malloc(sizeof(*be)))) + return NULL; + be->ops=proto_ops; + be->n_ops=sizeof(proto_ops)/sizeof(nss_backend_op_t); + if (_nss_ldap_default_constr(be)!=NSS_STATUS_SUCCESS) + return NULL; + return (nss_backend_t *)be; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/rpc.c =================================================================== --- nss/rpc.c (revision 1227) +++ nss/rpc.c (working copy) @@ -2,7 +2,8 @@ rpc.c - NSS lookup functions for rpc database Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008 Arthur de Jong + Copyright (C) 2006, 2007,2008,2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -41,14 +42,26 @@ return NSS_STATUS_SUCCESS; } -nss_status_t _nss_ldap_getrpcbyname_r(const char *name,struct rpcent *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getrpcbyname_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getrpcbyname_r( +#endif /* HAVE_NSSWITCH_H */ + const char *name,struct rpcent *result,char *buffer, + size_t buflen,int *errnop) { NSS_BYNAME(NSLCD_ACTION_RPC_BYNAME, name, read_rpcent(fp,result,buffer,buflen,errnop)); } -nss_status_t _nss_ldap_getrpcbynumber_r(int number,struct rpcent *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getrpcbynumber_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getrpcbynumber_r( +#endif /* HAVE_NSSWITCH_H */ + int number,struct rpcent *result,char *buffer, + size_t buflen,int *errnop) { NSS_BYINT32(NSLCD_ACTION_RPC_BYNUMBER, number, @@ -58,18 +71,190 @@ /* thread-local file pointer to an ongoing request */ static __thread TFILE *protoentfp; +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_setrpcent(nss_backend_t *rpc_context,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_setrpcent(int UNUSED(stayopen)) +#endif /* HAVE_NSSWITCH_H */ { NSS_SETENT(protoentfp); } -nss_status_t _nss_ldap_getrpcent_r(struct rpcent *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getrpcent_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getrpcent_r( +#endif /* HAVE_NSSWITCH_H */ + struct rpcent *result,char *buffer,size_t buflen,int *errnop) { NSS_GETENT(protoentfp,NSLCD_ACTION_RPC_ALL, read_rpcent(protoentfp,result,buffer,buflen,errnop)); } +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_endrpcent(nss_backend_t *rpc_context,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_endrpcent(void) +#endif /* HAVE_NSSWITCH_H */ { NSS_ENDENT(protoentfp); } + +#ifdef HAVE_NSSWITCH_H + +static nss_status_t _nss_ldap_getrpcbyname_r(nss_backend_t *be,void *args) +{ + struct rpcent priv_rpc; + struct rpcent *rpc=NSS_ARGS(args)->buf.result?(struct rpcent *)NSS_ARGS(args)->buf.result:&priv_rpc; + char *name=NSS_ARGS(args)->key.name; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getrpcbyname_r(name,rpc,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s %d",rpc->r_name,rpc->r_number); + if (rpc->r_aliases) + { + int i; + for (i=0; rpc->r_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,rpc->r_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getrpcbynumber_r(nss_backend_t *be,void *args) +{ + struct rpcent priv_rpc; + struct rpcent *rpc=NSS_ARGS(args)->buf.result?(struct rpcent *)NSS_ARGS(args)->buf.result:&priv_rpc; + int number=NSS_ARGS(args)->key.number; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getrpcbynumber_r(number,rpc,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s %d",rpc->r_name,rpc->r_number); + if (rpc->r_aliases) + { + int i; + for (i=0; rpc->r_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,rpc->r_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getrpcent_r(nss_backend_t *rpc_context,void *args) +{ + struct rpcent priv_rpc; + struct rpcent *rpc=NSS_ARGS(args)->buf.result?(struct rpcent *)NSS_ARGS(args)->buf.result:&priv_rpc; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getrpcent_r(rpc,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s %d",rpc->r_name,rpc->r_number); + if (rpc->r_aliases) + { + int i; + for (i=0; rpc->r_aliases[i]; i++) + { + strcat(data_ptr," "); + strcat(data_ptr,rpc->r_aliases[i]); + } + } + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_rpc_destr(nss_backend_t *rpc_context,void *args) +{ + return _nss_ldap_default_destr(rpc_context,args); +} + +static nss_backend_op_t rpc_ops[]={ + _nss_ldap_rpc_destr, + _nss_ldap_endrpcent, + _nss_ldap_setrpcent, + _nss_ldap_getrpcent_r, + _nss_ldap_getrpcbyname_r, + _nss_ldap_getrpcbynumber_r +}; + +nss_backend_t *_nss_ldap_rpc_constr(const char *db_name, + const char *src_name,const char *cfg_args) +{ + nss_ldap_backend_t *be; + if (!(be=(nss_ldap_backend_t *)malloc(sizeof(*be)))) + return NULL; + be->ops=rpc_ops; + be->n_ops=sizeof(rpc_ops)/sizeof(nss_backend_op_t); + if (_nss_ldap_default_constr(be)!=NSS_STATUS_SUCCESS) + return NULL; + return (nss_backend_t *)be; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/shadow.c =================================================================== --- nss/shadow.c (revision 1227) +++ nss/shadow.c (working copy) @@ -2,7 +2,8 @@ shadow.c - NSS lookup functions for shadow database Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008 Arthur de Jong + Copyright (C) 2006, 2007,2008,2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -47,7 +48,13 @@ return NSS_STATUS_SUCCESS; } -nss_status_t _nss_ldap_getspnam_r(const char *name,struct spwd *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getspnam_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getspnam_r( +#endif /* HAVE_NSSWITCH_H */ + const char *name,struct spwd *result,char *buffer, + size_t buflen,int *errnop) { NSS_BYNAME(NSLCD_ACTION_SHADOW_BYNAME, name, @@ -57,18 +64,199 @@ /* thread-local file pointer to an ongoing request */ static __thread TFILE *spentfp; +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_setspent(nss_backend_t *be,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_setspent(int UNUSED(stayopen)) +#endif /* HAVE_NSSWITCH_H */ { NSS_SETENT(spentfp); } -nss_status_t _nss_ldap_getspent_r(struct spwd *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getspent_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getspent_r( +#endif /* HAVE_NSSWITCH_H */ + struct spwd *result,char *buffer,size_t buflen,int *errnop) { NSS_GETENT(spentfp,NSLCD_ACTION_SHADOW_ALL, read_spwd(spentfp,result,buffer,buflen,errnop)); } +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_endspent(nss_backend_t *sp_context,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_endspent(void) +#endif /* HAVE_NSSWITCH_H */ { NSS_ENDENT(spentfp); } + +#ifdef HAVE_NSSWITCH_H +static nss_status_t _nss_ldap_getspnam_r(nss_backend_t *be,void *args) +{ + struct spwd priv_spwd; + struct spwd *sp=NSS_ARGS(args)->buf.result?(struct spwd *)NSS_ARGS(args)->buf.result:&priv_spwd; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *name=(char *)NSS_ARGS(args)->key.name; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getspnam_r(name,sp,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + char field_buf[128]; + sprintf(data_ptr,"%s:%s:",sp->sp_namp,sp->sp_pwdp); + if (sp->sp_lstchg >= 0) + sprintf(field_buf,"%d:",sp->sp_lstchg); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_min >= 0) + sprintf(field_buf,"%d:",sp->sp_min); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_max >= 0) + sprintf(field_buf,"%d:",sp->sp_max); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_warn >= 0) + sprintf(field_buf,"%d:",sp->sp_warn); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_inact >= 0) + sprintf(field_buf,"%d:",sp->sp_inact); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_expire >= 0) + sprintf(field_buf,"%d:",sp->sp_expire); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_flag >= 0) + sprintf(field_buf,"%x",sp->sp_flag); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getspent_r(nss_backend_t *sp_context,void *args) +{ + struct spwd priv_spwd; + struct spwd *sp=NSS_ARGS(args)->buf.result?(struct spwd *)NSS_ARGS(args)->buf.result:&priv_spwd; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + char *data_ptr; + nss_status_t status; + if (NSS_ARGS(args)->buf.buflen < 0) + { + NSS_ARGS(args)->erange=1; + return NSS_STATUS_TRYAGAIN; + } + status=_nss_nslcd_getspent_r(sp,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + char field_buf[128]; + sprintf(data_ptr,"%s:%s:",sp->sp_namp,sp->sp_pwdp); + if (sp->sp_lstchg >= 0) + sprintf(field_buf,"%d:",sp->sp_lstchg); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_min >= 0) + sprintf(field_buf,"%d:",sp->sp_min); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_max >= 0) + sprintf(field_buf,"%d:",sp->sp_max); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_warn >= 0) + sprintf(field_buf,"%d:",sp->sp_warn); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_inact >= 0) + sprintf(field_buf,"%d:",sp->sp_inact); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_expire >= 0) + sprintf(field_buf,"%d:",sp->sp_expire); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + if (sp->sp_flag >= 0) + sprintf(field_buf,"%x",sp->sp_flag); + else + sprintf(field_buf,":"); + strcat(data_ptr,field_buf); + strcpy(buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_shadow_destr(nss_backend_t *sp_context,void *args) +{ + return _nss_ldap_default_destr(sp_context,args); +} + +static nss_backend_op_t shadow_ops[]={ + _nss_ldap_shadow_destr, + _nss_ldap_endspent, /* NSS_DBOP_ENDENT */ + _nss_ldap_setspent, /* NSS_DBOP_SETENT */ + _nss_ldap_getspent_r, /* NSS_DBOP_GETENT */ + _nss_ldap_getspnam_r /* NSS_DBOP_SHADOW_BYNAME */ +}; + +nss_backend_t *_nss_ldap_shadow_constr(const char *db_name, + const char *src_name,const char *cfg_args) +{ + nss_ldap_backend_t *be; + if (!(be=(nss_ldap_backend_t *)malloc(sizeof(*be)))) + return NULL; + be->ops=shadow_ops; + be->n_ops=sizeof(shadow_ops)/sizeof(nss_backend_op_t); + if (_nss_ldap_default_constr(be)!=NSS_STATUS_SUCCESS) + return NULL; + return (nss_backend_t *)be; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/ldap-nss.h =================================================================== --- nss/ldap-nss.h (revision 0) +++ nss/ldap-nss.h (revision 0) @@ -0,0 +1,123 @@ +/* Copyright (C) 1997-2005 Luke Howard. + This file is part of the nss_ldap library. + Contributed by Luke Howard,,1997. + + The nss_ldap library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The nss_ldap library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the nss_ldap library; see the file COPYING.LIB. If not, + write to the Free Software Foundation,Inc.,59 Temple Place - Suite 330, + Boston,MA 02111-1307,USA. + + $Id: ldap-nss.h,v 1.1 2010-08-07 00:24:21 tedcheng Exp $ + */ + +#ifndef _LDAP_NSS_LDAP_LDAP_NSS_H +#define _LDAP_NSS_LDAP_LDAP_NSS_H + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_NSSWITCH_H +#include +#include +#include +#elif defined(HAVE_NSS_H) +#include +#elif defined(HAVE_IRS_H) +#include "irs-nss.h" +#endif + +/* from ldap-parse.h */ +#define NSS_ARGS(args)((nss_XbyY_args_t *)args) + +#ifndef NSS_BUFSIZ +#define NSS_BUFSIZ 1024 +#endif + +#ifndef HAVE_NSSWITCH_H +#define NSS_BUFLEN_NETGROUP(MAXHOSTNAMELEN *2 + LOGNAME_MAX + 3) +#define NSS_BUFLEN_ETHERS NSS_BUFSIZ +#endif /* HAVE_NSSWITCH_H */ + +#ifdef HAVE_NSSWITCH_H +/* + *thread specific context: result chain,and state data + */ +struct ent_context +{ + void *first_entry; + void *curr_entry; +}; + +typedef struct ent_context ent_context_t; + +#endif /* HAVE_NSSWITCH_H */ + +struct name_list +{ + char *name; + struct name_list *next; +}; + +#ifdef HAVE_NSSWITCH_H + +struct nss_ldap_backend +{ + nss_backend_op_t *ops; + int n_ops; + ent_context_t *state; +}; + +typedef struct nss_ldap_backend nss_ldap_backend_t; + +struct nss_ldap_netgr_backend +{ + nss_backend_op_t *ops; + int n_ops; + ent_context_t *state; + struct name_list *known_groups; /* netgroups seen,for loop detection */ + struct name_list *needed_groups; /* nested netgroups to chase */ +}; + +typedef struct nss_ldap_netgr_backend nss_ldap_netgr_backend_t; + +#elif defined(HAVE_IRS_H) + +struct nss_ldap_netgr_backend +{ + char buffer[NSS_BUFLEN_NETGROUP]; + ent_context_t *state; + struct name_list *known_groups; /* netgroups seen,for loop detection */ + struct name_list *needed_groups; /* nested netgroups to chase */ +}; + +typedef struct nss_ldap_netgr_backend nss_ldap_netgr_backend_t; + +#endif /* HAVE_NSSWITCH_H */ + +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_default_destr(nss_backend_t *,void *); +#endif + +/* + *context management routines. + *_nss_ldap_default_constr() is called once in the constructor + */ +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_default_constr(nss_ldap_backend_t *be); +#endif + +#endif /* _LDAP_NSS_LDAP_LDAP_NSS_H */ Index: nss/common.c =================================================================== --- nss/common.c (revision 1227) +++ nss/common.c (working copy) @@ -1,7 +1,8 @@ /* - common.c - common definitions + common.c - common functions for NSS lookups Copyright (C) 2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,4 +20,113 @@ 02110-1301 USA */ +#include "config.h" + +#ifdef HAVE_STDINT_H +#include +#endif /* HAVE_STDINT_H */ +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_NSS_H +#include +#endif /* HAVE_NSS_H */ +#include + +#include "nslcd.h" +#include "common.h" +#include "common/tio.h" + +/* flag used to disable NSS lookups using this module */ int _nss_ldap_enablelookups=1; + +#ifdef HAVE_NSSWITCH_H +/* Adapted from PADL */ +/* + *Default destructor. + *The entry point for this function is the destructor in the dispatch + *table for the switch. Thus,it's safe to grab the mutex from this + *function. + */ +nss_status_t _nss_ldap_default_destr(nss_backend_t *be,void *args) +{ + /* Ditch the backend. */ + free(be); + return NSS_STATUS_SUCCESS; +} + +/* + *This is the default "constructor" which gets called from each + *constructor,in the NSS dispatch table. + */ +nss_status_t _nss_ldap_default_constr(nss_ldap_backend_t *be) +{ + return NSS_STATUS_SUCCESS; +} + +/* add a nested netgroup or group to the namelist */ +nss_status_t _nss_ldap_namelist_push(struct name_list **head,const char *name) +{ + struct name_list *nl; + nl=(struct name_list *)malloc(sizeof(*nl)); + if (nl==NULL) + return NSS_STATUS_TRYAGAIN; + nl->name=strdup(name); + if (nl->name==NULL) + { + free(nl); + return NSS_STATUS_TRYAGAIN; + } + nl->next=*head; + *head=nl; + return NSS_STATUS_SUCCESS; +} + +/* remove last nested netgroup or group from the namelist */ +void _nss_ldap_namelist_pop(struct name_list **head) +{ + struct name_list *nl; + nl=*head; + *head=nl->next; + free(nl->name); + free(nl); +} + +/* cleanup nested netgroup or group namelist */ +void _nss_ldap_namelist_destroy(struct name_list **head) +{ + struct name_list *p,*next; + for (p=*head;p!=NULL;p=next) + { + next=p->next; + if (p->name!=NULL) + free(p->name); + free(p); + } + *head=NULL; +} + +/* + *Check whether we have already seen a netgroup or group, + *to avoid loops in nested netgroup traversal + */ +int _nss_ldap_namelist_find(struct name_list *head,const char *netgroup) +{ + struct name_list *p; + int found=0; + for (p=head;p!=NULL;p=p->next) + { + if (strcasecmp(p->name,netgroup)==0) + { + found++; + break; + } + } + return found; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/Makefile.am =================================================================== --- nss/Makefile.am (revision 1227) +++ nss/Makefile.am (working copy) @@ -27,23 +27,30 @@ nss_ldap_so_SOURCES = common.c common.h prototypes.h \ ../nslcd.h ../common/nslcd-prot.h \ ../compat/attrs.h -EXTRA_nss_ldap_so_SOURCES = aliases.c ethers.c group.c hosts.c netgroup.c \ - networks.c passwd.c protocols.c rpc.c services.c \ - shadow.c -nss_ldap_so_LDFLAGS = -shared -Wl,-h,$(NSS_LDAP_SONAME) +nss_ldap_so_LDFLAGS = @nss_ldap_so_LDFLAGS@ if HAVE_VERSION_SCRIPT_FLAG nss_ldap_so_LDFLAGS += $(VERSION_SCRIPT_FLAG)\$(srcdir)/nss_ldap.map endif -nss_ldap_so_LDADD = ../common/libtio.a ../common/libprot.a $(NSS_MODULE_OBJS) nss_ldap_so_DEPENDENCIES = $(NSS_MODULE_OBJS) +EXTRA_nss_ldap_so_SOURCES = aliases.c ethers.c group.c hosts.c netgroup.c \ + networks.c passwd.c protocols.c rpc.c services.c \ + shadow.c +if USE_NATIVE_LINKER +nss_ldap_so_LINK = @nss_ldap_so_LD@ @nss_ldap_so_LDFLAGS@ -o $@ +else +nss_ldap_so_LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAG) -o $@ +endif + EXTRA_DIST = nss_ldap.map install-exec-local: install-nss_ldap_so uninstall-local: uninstall-nss_ldap_so -# install libnss_ldap.so.2 install-nss_ldap_so: nss_ldap.so - $(INSTALL_PROGRAM) -D nss_ldap.so $(DESTDIR)$(libdir)/$(NSS_LDAP_SONAME) + -rm -f $(DESTDIR)$(libdir)/$(NSS_LDAP_SONAME) + $(mkinstalldirs) $(DESTDIR)$(libdir) + $(INSTALL_PROGRAM) nss_ldap.so $(DESTDIR)$(libdir)/$(NSS_LDAP_SONAME) + uninstall-nss_ldap_so: -rm -f $(DESTDIR)$(libdir)/$(NSS_LDAP_SONAME) Index: nss/ethers.c =================================================================== --- nss/ethers.c (revision 1227) +++ nss/ethers.c (working copy) @@ -2,7 +2,8 @@ ethers.c - NSS lookup functions for ethers database Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008 Arthur de Jong + Copyright (C) 2006, 2007,2008,2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -41,7 +42,11 @@ } /* map a hostname to the corresponding ethernet address */ +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_gethostton_r( +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_gethostton_r( +#endif /* HAVE_NSSWITCH_H */ const char *name,struct etherent *result, char *buffer,size_t buflen,int *errnop) { @@ -51,7 +56,11 @@ } /* map an ethernet address to the corresponding hostname */ +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getntohost_r( +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_getntohost_r( +#endif /* HAVE_NSSWITCH_H */ const struct ether_addr *addr,struct etherent *result, char *buffer,size_t buflen,int *errnop) { @@ -63,12 +72,21 @@ /* thread-local file pointer to an ongoing request */ static __thread TFILE *etherentfp; +#ifdef HAVE_NSSWITCH_H +static nss_status_t _nss_ldap_setetherent( + nss_backend_t *be,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_setetherent(int UNUSED(stayopen)) +#endif /* HAVE_NSSWITCH_H */ { NSS_SETENT(etherentfp); } +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getetherent_r( +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_getetherent_r( +#endif /* HAVE_NSSWITCH_H */ struct etherent *result, char *buffer,size_t buflen,int *errnop) { @@ -76,7 +94,118 @@ read_etherent(etherentfp,result,buffer,buflen,errnop)); } +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_endetherent(nss_backend_t *be,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_endetherent(void) +#endif /* HAVE_NSSWITCH_H */ { NSS_ENDENT(etherentfp); } + +#ifdef HAVE_NSSWITCH_H + +/* Solaris wrapper around _nss_nslcd_gethsotton_r */ +static nss_status_t _nss_ldap_gethostton_r(nss_backend_t *be,void *args) +{ + struct etherent result; + char buffer[NSS_BUFLEN_ETHERS]; + nss_status_t status; + char *name=(char *)(NSS_ARGS(args)->key.name); + status=_nss_nslcd_gethostton_r(name,&result,buffer,sizeof(buffer),&errno); + if (status==NSS_STATUS_SUCCESS) + { + /* if (NSS_ARGS(args)->buf.buffer!=NULL) { */ + if (NSS_ARGS(args)->buf.result==NULL) + { + strcpy(NSS_ARGS(args)->buf.buffer,ether_ntoa(&result.e_addr)); + NSS_ARGS(args)->buf.buflen=strlen(NSS_ARGS(args)->buf.buffer); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + return status; + } + memcpy(NSS_ARGS(args)->buf.result,&result.e_addr,sizeof(result.e_addr)); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +/* Solaris wrapper around _nss_nslcd_getntohost_r */ +static nss_status_t _nss_ldap_getntohost_r(nss_backend_t *be,void *args) +{ + struct etherent result; + struct ether_addr *addr; + char buffer[NSS_BUFLEN_ETHERS]; + size_t buflen=sizeof(buffer); + nss_status_t status; + addr=(struct ether_addr *)(NSS_ARGS(args)->key.ether); + status=_nss_nslcd_getntohost_r(addr,&result,buffer,buflen,&errno); + if (status==NSS_STATUS_SUCCESS) + { + if (NSS_ARGS(args)->buf.buffer!=NULL) + { + /* TODO: OpenSolaris expects " " */ + /* This output is handled correctly by NSCD,but not */ + /* when NSCD is off. Not an issue with NSS_LDAP,but */ + /* with the frontend. */ + sprintf(NSS_ARGS(args)->buf.buffer,"%s %s",ether_ntoa(addr),result.e_name); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + return status; + } + memcpy(NSS_ARGS(args)->buf.buffer,result.e_name,strlen(result.e_name)+1); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->buf.buflen=strlen(result.e_name); + } + else + { + NSS_ARGS(args)->returnval=NULL; + } + return status; +} + +static nss_status_t _nss_ldap_getetherent_r(nss_backend_t *be,void *args) +{ + /* TODO: cns3 uses struct ether,verify */ + struct etherent result; + char *buffer; + size_t buflen; + int errnop; + nss_status_t status; + buffer=NSS_ARGS(args)->buf.buffer; + buflen=NSS_ARGS(args)->buf.buflen; + status=_nss_nslcd_getetherent_r(&result,buffer,buflen,&errnop); + if (status==NSS_STATUS_SUCCESS) + { + memcpy(NSS_ARGS(args)->buf.result,&result.e_addr,sizeof(result.e_addr)); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + else + NSS_ARGS(args)->returnval=NULL; + return status; +} + +static nss_status_t _nss_ldap_ethers_destr(nss_backend_t *ether_context,void *args) +{ + return _nss_ldap_default_destr(ether_context,args); +} + +static nss_backend_op_t ethers_ops[]={ + _nss_ldap_ethers_destr, + _nss_ldap_gethostton_r, + _nss_ldap_getntohost_r +}; + +nss_backend_t *_nss_ldap_ethers_constr(const char *db_name,const char *src_name,const char *cfg_args) +{ + nss_ldap_backend_t *be; + if (!(be=(nss_ldap_backend_t *)malloc(sizeof(*be)))) + return NULL; + be->ops=ethers_ops; + be->n_ops=sizeof(ethers_ops)/sizeof(nss_backend_op_t); + if (_nss_ldap_default_constr(be)!=NSS_STATUS_SUCCESS) + return NULL; + return (nss_backend_t *)be; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/group.c =================================================================== --- nss/group.c (revision 1227) +++ nss/group.c (working copy) @@ -2,7 +2,8 @@ group.c - NSS lookup functions for group database Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008, 2009 Arthur de Jong + Copyright (C) 2006, 2007,2008,2009,2010 Arthur de Jong + Copyright (C) 2010 Symas Corporation This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -46,7 +47,10 @@ /* read all group entries from the stream and add gids of these groups to the list */ static nss_status_t read_gids( - TFILE *fp,gid_t skipgroup,long int *start,long int *size, + TFILE *fp,gid_t skipgroup,long int *start, +#ifndef HAVE_NSSWITCH_H + long int *size, +#endif /* HAVE_NSSWITCH_H */ gid_t **groupsp,long int limit,int *errnop) { int32_t res=(int32_t)NSLCD_RESULT_BEGIN; @@ -72,6 +76,7 @@ if ( (limit>0) && (*start>=limit) ) return NSS_STATUS_TRYAGAIN; /* check if our buffer is large enough */ +#ifndef HAVE_NSSWITCH_H if ((*start)>=(*size)) { /* for some reason Glibc expects us to grow the array (completely @@ -88,6 +93,7 @@ *size=newsize; } /* add gid to list */ +#endif /* HAVE_NSSWITCH_H */ (*groupsp)[(*start)++]=gid; } /* read next response code @@ -99,14 +105,26 @@ return NSS_STATUS_SUCCESS; } -nss_status_t _nss_ldap_getgrnam_r(const char *name,struct group *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getgrnam_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getgrnam_r( +#endif /* HAVE_NSSWITCH_H */ + const char *name,struct group *result,char *buffer, + size_t buflen,int *errnop) { NSS_BYNAME(NSLCD_ACTION_GROUP_BYNAME, name, read_group(fp,result,buffer,buflen,errnop)); } -nss_status_t _nss_ldap_getgrgid_r(gid_t gid,struct group *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getgrgid_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getgrgid_r( +#endif /* HAVE_NSSWITCH_H */ + gid_t gid,struct group *result,char *buffer, + size_t buflen,int *errnop) { NSS_BYTYPE(NSLCD_ACTION_GROUP_BYGID, gid,gid_t, @@ -127,16 +145,29 @@ */ nss_status_t _nss_ldap_initgroups_dyn( const char *user,gid_t skipgroup,long int *start, - long int *size,gid_t **groupsp,long int limit,int *errnop) +#ifndef HAVE_NSSWITCH_H + long int *size, +#endif /* HAVE_NSSWITCH_H */ + gid_t **groupsp,long int limit,int *errnop) { +#ifdef HAVE_NSSWITCH_H + long int buffer_size=limit; + long int *size=&buffer_size; +#endif /* HAVE_NSSWITCH_H */ /* temporarily map the buffer and buflen names so the check in NSS_BYNAME for validity of the buffer works (renaming the parameters may cause confusion) */ #define buffer groupsp #define buflen *size +#ifdef HAVE_NSSWITCH_H NSS_BYNAME(NSLCD_ACTION_GROUP_BYMEMBER, user, + read_gids(fp,skipgroup,start,groupsp,limit,errnop)); +#else /* not HAVE_NSSWITCH_H */ + NSS_BYNAME(NSLCD_ACTION_GROUP_BYMEMBER, + user, read_gids(fp,skipgroup,start,size,groupsp,limit,errnop)); +#endif /* not HAVE_NSSWITCH_H */ #undef buffer #undef buflen } @@ -144,18 +175,209 @@ /* thread-local file pointer to an ongoing request */ static __thread TFILE *grentfp; +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_setgrent(nss_backend_t *gr_context,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_setgrent(int UNUSED(stayopen)) +#endif /* HAVE_NSSWITCH_H */ { NSS_SETENT(grentfp); } -nss_status_t _nss_ldap_getgrent_r(struct group *result,char *buffer,size_t buflen,int *errnop) +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_nslcd_getgrent_r( +#else /* not HAVE_NSSWITCH_H */ +nss_status_t _nss_ldap_getgrent_r( +#endif /* HAVE_NSSWITCH_H */ + struct group *result,char *buffer,size_t buflen,int *errnop) { NSS_GETENT(grentfp,NSLCD_ACTION_GROUP_ALL, read_group(grentfp,result,buffer,buflen,errnop)); } +#ifdef HAVE_NSSWITCH_H +nss_status_t _nss_ldap_endgrent(nss_backend_t *gr_context,void *args) +#else /* not HAVE_NSSWITCH_H */ nss_status_t _nss_ldap_endgrent(void) +#endif /* HAVE_NSSWITCH_H */ { NSS_ENDENT(grentfp); } + +#ifdef HAVE_NSSWITCH_H + +static nss_status_t _nss_ldap_getgrnam_r(nss_backend_t *be,void *args) +{ + char *name=(char *)NSS_ARGS(args)->key.name; + struct group priv_gr; + struct group *gr=NSS_ARGS(args)->buf.result?(struct group *)NSS_ARGS(args)->buf.result:&priv_gr; + char *data_ptr; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + nss_status_t status; + status=_nss_nslcd_getgrnam_r(name,gr,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s:%s:%d:",gr->gr_name,gr->gr_passwd,(int) gr->gr_gid); + if (gr->gr_mem) + { + int i; + for (i=0; gr->gr_mem[i]; i++) + { + if (i) + strcat(data_ptr,","); + strcat(data_ptr,gr->gr_mem[i]); + } + } + strcpy(NSS_ARGS(args)->buf.buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { /* result!=NULL */ + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getgrgid_r(nss_backend_t *be,void *args) +{ + gid_t gid=NSS_ARGS(args)->key.gid; + struct group priv_gr; + struct group *gr=NSS_ARGS(args)->buf.result?(struct group *)NSS_ARGS(args)->buf.result:&priv_gr; + char *data_ptr; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + nss_status_t status; + status=_nss_nslcd_getgrgid_r(gid,gr,buffer,buflen,&errno); + if (status!=NSS_STATUS_SUCCESS) + return status; + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s:%s:%d:",gr->gr_name,gr->gr_passwd,(int) gr->gr_gid); + if (gr->gr_mem) + { + int i; + for (i=0; gr->gr_mem[i]; i++) + { + if (i) + strcat(data_ptr,","); + strcat(data_ptr,gr->gr_mem[i]); + } + } + strcpy(NSS_ARGS(args)->buf.buffer,data_ptr); + free(data_ptr); + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { /* result!=NULL */ + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_getgrent_r(nss_backend_t *gr_context,void *args) +{ + struct group priv_gr; + struct group *gr=NSS_ARGS(args)->buf.result?(struct group *)NSS_ARGS(args)->buf.result:&priv_gr; + char *data_ptr; + char *buffer=NSS_ARGS(args)->buf.buffer; + size_t buflen=NSS_ARGS(args)->buf.buflen; + nss_status_t status; + + status=_nss_nslcd_getgrent_r(gr,buffer,buflen,&errno); + + if (status!=NSS_STATUS_SUCCESS) + return status; + + if (!NSS_ARGS(args)->buf.result) + { + /* result==NULL, return file format */ + data_ptr=(char *)malloc(buflen); + sprintf(data_ptr,"%s:%s:%d:",gr->gr_name,gr->gr_passwd,(int)gr->gr_gid); + if (gr->gr_mem) + { + int i; + for (i=0; gr->gr_mem[i]; i++) + { + if (i) + strcat(data_ptr,","); + strcat(data_ptr,gr->gr_mem[i]); + } + } + strcpy(NSS_ARGS(args)->buf.buffer,data_ptr); + free(data_ptr); + + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.buffer; + NSS_ARGS(args)->returnlen=strlen(NSS_ARGS(args)->buf.buffer); + } + else + { /* result!=NULL */ + NSS_ARGS(args)->returnval=NSS_ARGS(args)->buf.result; + } + return status; +} + +static nss_status_t _nss_ldap_group_destr(nss_backend_t *gr_context,void *args) +{ + return _nss_ldap_default_destr(gr_context,args); +} + +static nss_status_t _nss_ldap_getgroupsbymember_r(nss_backend_t *gr_context,void *args) +{ + struct nss_groupsbymem *argp=(struct nss_groupsbymem *)args; + char *user=(char *)argp->username; + nss_status_t status; + long int limit=(long int) argp->maxgids; + long int start=(long int) argp->numgids; + gid_t skipgroup; + int i; + + if (start > 0) + skipgroup=argp->gid_array[0]; + + status=_nss_ldap_initgroups_dyn( + user, + (start > 0)?skipgroup:-1, + &start, + (gid_t **)&argp->gid_array, + limit, + &errno); + argp->numgids=(int)start; + + return status; +} + +static nss_backend_op_t group_ops[]={ + _nss_ldap_group_destr, + _nss_ldap_endgrent, + _nss_ldap_setgrent, + _nss_ldap_getgrent_r, + _nss_ldap_getgrnam_r, + _nss_ldap_getgrgid_r, + _nss_ldap_getgroupsbymember_r +}; + +nss_backend_t *_nss_ldap_group_constr(const char *db_name, + const char *src_name,const char *cfg_args) +{ + nss_ldap_backend_t *be; + if (!(be=(nss_ldap_backend_t *)malloc(sizeof(*be)))) + return NULL; + be->ops=group_ops; + be->n_ops=sizeof(group_ops)/sizeof(nss_backend_op_t); + /* a NOOP at the moment */ + if (_nss_ldap_default_constr(be)!=NSS_STATUS_SUCCESS) + return NULL; + return (nss_backend_t *)be; +} + +#endif /* HAVE_NSSWITCH_H */ Index: nss/prototypes.h =================================================================== --- nss/prototypes.h (revision 1227) +++ nss/prototypes.h (working copy) @@ -43,78 +43,100 @@ extern int _nss_ldap_enablelookups; /* aliases - mail aliases */ +#ifdef HAVE_ALIASES_H nss_status_t _nss_ldap_getaliasbyname_r(const char *name,struct aliasent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_setaliasent(void); nss_status_t _nss_ldap_getaliasent_r(struct aliasent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_endaliasent(void); +#endif /* HAVE_ALIASES_H */ /* ethers - ethernet numbers */ +#ifndef HAVE_NSSWITCH_H nss_status_t _nss_ldap_gethostton_r(const char *name,struct etherent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_getntohost_r(const struct ether_addr *addr,struct etherent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_setetherent(int stayopen); nss_status_t _nss_ldap_getetherent_r(struct etherent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_endetherent(void); +#endif /* not HAVE_NSSWITCH_H */ /* group - groups of users */ +#ifndef HAVE_NSSWITCH_H nss_status_t _nss_ldap_getgrnam_r(const char *name,struct group *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_getgrgid_r(gid_t gid,struct group *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_initgroups_dyn(const char *user,gid_t group,long int *start,long int *size,gid_t **groupsp,long int limit,int *errnop); nss_status_t _nss_ldap_setgrent(int stayopen); nss_status_t _nss_ldap_getgrent_r(struct group *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_endgrent(void); +#endif /* not HAVE_NSSWITCH_H */ /* hosts - host names and numbers */ +#ifndef HAVE_NSSWITCH_H nss_status_t _nss_ldap_gethostbyname_r(const char *name,struct hostent *result,char *buffer,size_t buflen,int *errnop,int *h_errnop); nss_status_t _nss_ldap_gethostbyname2_r(const char *name,int af,struct hostent *result,char *buffer,size_t buflen,int *errnop,int *h_errnop); nss_status_t _nss_ldap_gethostbyaddr_r(const void *addr,socklen_t len,int af,struct hostent *result,char *buffer,size_t buflen,int *errnop,int *h_errnop); nss_status_t _nss_ldap_sethostent(int stayopen); nss_status_t _nss_ldap_gethostent_r(struct hostent *result,char *buffer,size_t buflen,int *errnop,int *h_errnop); nss_status_t _nss_ldap_endhostent(void); +#endif /* not HAVE_NSSWITCH_H */ /* netgroup - list of host and users */ +#ifndef HAVE_NSSWITCH_H nss_status_t _nss_ldap_setnetgrent(const char *group,struct __netgrent *result); nss_status_t _nss_ldap_getnetgrent_r(struct __netgrent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_endnetgrent(struct __netgrent *result); +#endif /* not HAVE_NSSWITCH_H */ /* networks - network names and numbers */ +#ifndef HAVE_NSSWITCH_H nss_status_t _nss_ldap_getnetbyname_r(const char *name,struct netent *result,char *buffer,size_t buflen,int *errnop,int *h_errnop); nss_status_t _nss_ldap_getnetbyaddr_r(uint32_t addr,int af,struct netent *result,char *buffer,size_t buflen,int *errnop,int *h_errnop); nss_status_t _nss_ldap_setnetent(int stayopen); nss_status_t _nss_ldap_getnetent_r(struct netent *result,char *buffer,size_t buflen,int *errnop,int *h_errnop); nss_status_t _nss_ldap_endnetent(void); +#endif /* not HAVE_NSSWITCH_H */ /* passwd - user database and passwords */ +#ifndef HAVE_NSSWITCH_H nss_status_t _nss_ldap_getpwnam_r(const char *name,struct passwd *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_getpwuid_r(uid_t uid,struct passwd *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_setpwent(int stayopen); nss_status_t _nss_ldap_getpwent_r(struct passwd *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_endpwent(void); +#endif /* not HAVE_NSSWITCH_H */ /* protocols - network protocols */ +#ifndef HAVE_NSSWITCH_H nss_status_t _nss_ldap_getprotobyname_r(const char *name,struct protoent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_getprotobynumber_r(int number,struct protoent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_setprotoent(int stayopen); nss_status_t _nss_ldap_getprotoent_r(struct protoent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_endprotoent(void); +#endif /* not HAVE_NSSWITCH_H */ /* rpc - remote procedure call names and numbers */ +#ifndef HAVE_NSSWITCH_H nss_status_t _nss_ldap_getrpcbyname_r(const char *name,struct rpcent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_getrpcbynumber_r(int number,struct rpcent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_setrpcent(int stayopen); nss_status_t _nss_ldap_getrpcent_r(struct rpcent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_endrpcent(void); +#endif /* not HAVE_NSSWITCH_H */ /* services - network services */ +#ifndef HAVE_NSSWITCH_H nss_status_t _nss_ldap_getservbyname_r(const char *name,const char *protocol,struct servent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_getservbyport_r(int port,const char *protocol,struct servent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_setservent(int stayopen); nss_status_t _nss_ldap_getservent_r(struct servent *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_endservent(void); +#endif /* not HAVE_NSSWITCH_H */ /* shadow - extended user information */ +#ifndef HAVE_NSSWITCH_H nss_status_t _nss_ldap_getspnam_r(const char *name,struct spwd *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_setspent(int stayopen); nss_status_t _nss_ldap_getspent_r(struct spwd *result,char *buffer,size_t buflen,int *errnop); nss_status_t _nss_ldap_endspent(void); +#endif /* not HAVE_NSSWITCH_H */ #endif /* not NSS__PROTOTYPES_H */ Index: nss/common.h =================================================================== --- nss/common.h (revision 1227) +++ nss/common.h (working copy) @@ -30,6 +30,19 @@ #include "compat/attrs.h" #include "compat/nss_compat.h" +#ifdef HAVE_NSSWITCH_H +#include "ldap-nss.h" +#endif /* HAVE_NSSWITCH_H */ + +#ifdef HAVE_NSSWITCH_H +/* Adapted from PADL */ +/* Routines for managing namelists */ +nss_status_t _nss_ldap_namelist_push(struct name_list **head,const char *name); +void _nss_ldap_namelist_pop(struct name_list **head); +int _nss_ldap_namelist_find(struct name_list *head,const char *netgroup); +void _nss_ldap_namelist_destroy(struct name_list **head); +#endif /* HAVE_NSSWITCH_H */ + /* These are macros for handling read and write problems, they are NSS specific due to the return code so are defined here. They genrally close the open file, set an error code and return with