Adding a Service to Name Service Switch
Asked Answered
C

1

13

So I am trying to add a service to NSS (Name Service Switch). Please note the GNU guide on how to do it here. I have been following that guide. I need to implement a service that works with the passwd database.

The problem I am having is my module is not being called for certain functions. Let me reproduce some of my code here...

enum nss_status
_nss_myservice_setpwent (void) {
 printf( "@ %s\n", __FUNCTION__ ) ;
 return NSS_STATUS_SUCCESS ;
} ;

enum nss_status
_nss_myservice_endpwent (void) {
 printf( "@ %s\n", __FUNCTION__ ) ;
 return NSS_STATUS_SUCCESS ;
} ;

enum nss_status
_nss_myservice_getpwent_r (struct passwd *result, char *buffer,
   size_t buflen, int *errnop) {

 static int i = 0 ;

 if( i++ == 0 ) {
   printf( "@ %s\n", __FUNCTION__ ) ;
   return init_result( result, buffer, buflen, errnop ) ;
 } else {
   i = 0 ;
   return NSS_STATUS_NOTFOUND ;
 }
} ;

enum nss_status
_nss_myservice_getpwbynam (const char *nam, struct passwd *result, char *buffer,
   size_t buflen, int *errnop) {
 printf( "@ %s with name %s\n", __FUNCTION__, nam ) ;
 return init_result( result, buffer, buflen, errnop ) ;
} ;

enum nss_status
_nss_myservice_getpwbynam_r (const char *nam, struct passwd *result, char *buffer,
   size_t buflen, int *errnop) {
 printf( "@ %s with name_r %s\n", __FUNCTION__, nam ) ;
 return init_result( result, buffer, buflen, errnop ) ;
} ;

Init_result is an inline function that simply fills in the result with a dummy user no matter what the PARAMS are.

Now I have my /etc/nsswitch.conf setup as follows:

passwd:         myservice compat

And for completeness here is my Makefile.

all:
       gcc -fPIC -shared -o libnss_myservice.so.2 -Wl,-soname,libnss_myservice.so.2 myservice.c
install:
       sudo install -m 0644 libnss_myservice.so.2 /lib
       sudo /sbin/ldconfig -n /lib /usr/lib
clean:
       /bin/rf -rf libnss_myservice.so.2

Now after installing this nss module I run getent on the command line and here is my output:

username@host:~/nss$ getent passwd
@ _nss_myservice_setpwent
@ _nss_myservice_getpwent_r
myuser:mypass:1:1:realname::
root:x:0:0:root:/root:/bin/bash
...
@ _nss_myservice_endpwent

So as you can see that is working as I would expect. The iterative call is made which returns the user and then the compat service is called which returns all the user from /etc/passwd.

The problem is when I make this call, "getent passwd myuser", I get a return value of 2, "Key not found in database". This shows me my _nss_myservice_getpwbynam_r function is not being called. Any ideas why? I can provide the complete code if that would help.

Carrelli answered 3/5, 2013 at 19:55 Comment(2)
What if you call it _nss_myservice_getpwnam_r instead? Just a guess, but I see there's a pwd.h function called getpwnam_rAymer
How you figure out the uid for mypass? Is it statically defined as 1?Sprung
A
9

You need to call the function _nss_myservice_getpwnam_r instead of _nss_myservice_getpwbynam_r.

After looking at ftp://ftp.acer-euro.com/gpl/Utility/glibc/glibc-2.2.5.tar/include/pwd.h :

#define DECLARE_NSS_PROTOTYPES(service)                 \
extern enum nss_status _nss_ ## service ## _setpwent (int);     \
extern enum nss_status _nss_ ## service ## _endpwent (void);        \
extern enum nss_status _nss_ ## service ## _getpwnam_r          \        <<< this line
                       (const char *name, struct passwd *pwd,       \
            char *buffer, size_t buflen, int *errnop);  \
extern enum nss_status _nss_ ## service ## _getpwuid_r          \
                       (uid_t uid, struct passwd *pwd,          \
            char *buffer, size_t buflen, int *errnop);  \
extern enum nss_status _nss_ ## service ##_getpwent_r           \
                       (struct passwd *result, char *buffer,        \
            size_t buflen, int *errnop);
Aymer answered 3/5, 2013 at 23:7 Comment(4)
Thanks, that works. Which makes me wonder why the GNU documentation is worded as it is. (enum nss_status _nss_DATABASE_getdbbyXX_r (PARAMS, STRUCTURE *result, char *buffer, size_t buflen, int *errnop)) Am I missing something? If not I'll send them a note...Carrelli
Here's a direct link to this code in the glibc source repository: repo.or.cz/w/glibc.git/blob/HEAD:/include/pwd.h#l35Lullaby
@DavidMokonBond you ever send those guys that note? because the documentation is still apparently incorrect.Liuka
@IanHunter honestly no idea as its been a whileCarrelli

© 2022 - 2024 — McMap. All rights reserved.