2 nss sample code for extended winbindd functionality
4 Copyright (C) Andrew Tridgell (tridge@samba.org)
6 you are free to use this code in any way you see fit, including
7 without restriction, using this code in your own products. You do
8 not need to give any attribution.
14 cc -o wbtest wbtest.c -ldl
18 ./wbtest /lib/libnss_winbind.so
31 #include <sys/types.h>
33 typedef enum nss_status NSS_STATUS
;
42 find a function in the nss library
44 static void *find_fn(struct nss_state
*nss
, const char *name
)
49 asprintf(&s
, "_nss_%s_%s", nss
->nss_name
, name
);
54 res
= dlsym(nss
->dl_handle
, s
);
64 establish a link to the nss library
65 Return 0 on success and -1 on error
67 int nss_open(struct nss_state
*nss
, const char *nss_path
)
70 p
= strrchr(nss_path
, '_');
76 nss
->nss_name
= strdup(p
+1);
77 p
= strchr(nss
->nss_name
, '.');
80 nss
->dl_handle
= dlopen(nss_path
, RTLD_LAZY
);
81 if (!nss
->dl_handle
) {
90 close and cleanup a nss state
92 void nss_close(struct nss_state
*nss
)
95 dlclose(nss
->dl_handle
);
100 Return 0 on success and -1 on error
102 int nss_getpwent(struct nss_state
*nss
, struct passwd
*pwd
)
104 NSS_STATUS (*_nss_getpwent_r
)(struct passwd
*, char *,
105 size_t , int *) = find_fn(nss
, "getpwent_r");
109 if (!_nss_getpwent_r
) {
113 status
= _nss_getpwent_r(pwd
, nss
->pwnam_buf
, sizeof(nss
->pwnam_buf
), &nss_errno
);
114 if (status
== NSS_STATUS_NOTFOUND
) {
118 if (status
!= NSS_STATUS_SUCCESS
) {
127 make a setpwent call.
128 Return 0 on success and -1 on error
130 int nss_setpwent(struct nss_state
*nss
)
132 NSS_STATUS (*_nss_setpwent
)(void) = find_fn(nss
, "setpwent");
134 if (!_nss_setpwent
) {
137 status
= _nss_setpwent();
138 if (status
!= NSS_STATUS_SUCCESS
) {
146 make a endpwent call.
147 Return 0 on success and -1 on error
149 int nss_endpwent(struct nss_state
*nss
)
151 NSS_STATUS (*_nss_endpwent
)(void) = find_fn(nss
, "endpwent");
153 if (!_nss_endpwent
) {
156 status
= _nss_endpwent();
157 if (status
!= NSS_STATUS_SUCCESS
) {
166 convert a name to a SID
168 Return 0 on success and -1 on error
170 int nss_nametosid(struct nss_state
*nss
, const char *name
, char **sid
)
172 NSS_STATUS (*_nss_nametosid
)(const char *, char **, char *, size_t, int *) =
173 find_fn(nss
, "nametosid");
178 if (!_nss_nametosid
) {
182 status
= _nss_nametosid(name
, sid
, buf
, sizeof(buf
), &nss_errno
);
183 if (status
== NSS_STATUS_NOTFOUND
) {
187 if (status
!= NSS_STATUS_SUCCESS
) {
198 convert a SID to a name
200 Return 0 on success and -1 on error
202 int nss_sidtoname(struct nss_state
*nss
, char *sid
, char **name
)
204 NSS_STATUS (*_nss_sidtoname
)(const char *, char **, char *, size_t, int *) =
205 find_fn(nss
, "sidtoname");
210 if (!_nss_sidtoname
) {
214 status
= _nss_sidtoname(sid
, name
, buf
, sizeof(buf
), &nss_errno
);
215 if (status
== NSS_STATUS_NOTFOUND
) {
219 if (status
!= NSS_STATUS_SUCCESS
) {
224 *name
= strdup(*name
);
230 return a list of group SIDs for a user SID
231 the returned list is NULL terminated
232 Return 0 on success and -1 on error
234 int nss_getusersids(struct nss_state
*nss
, const char *user_sid
, char ***sids
)
236 NSS_STATUS (*_nss_getusersids
)(const char *, char **, int *, char *, size_t, int *) =
237 find_fn(nss
, "getusersids");
241 int i
, num_groups
= 0;
242 unsigned bufsize
= 10;
245 if (!_nss_getusersids
) {
250 buf
= malloc(bufsize
);
256 status
= _nss_getusersids(user_sid
, &s
, &num_groups
, buf
, bufsize
, &nss_errno
);
257 if (status
== NSS_STATUS_NOTFOUND
) {
263 if (status
== NSS_STATUS_TRYAGAIN
) {
269 if (status
!= NSS_STATUS_SUCCESS
) {
275 if (num_groups
== 0) {
280 *sids
= (char **)malloc(sizeof(char *) * (num_groups
+1));
287 for (i
=0;i
<num_groups
;i
++) {
288 (*sids
)[i
] = strdup(s
);
299 static int nss_test_users(struct nss_state
*nss
)
303 if (nss_setpwent(nss
) != 0) {
308 /* loop over all users */
309 while ((nss_getpwent(nss
, &pwd
) == 0)) {
310 char *sid
, **group_sids
, *name2
;
313 printf("User %s\n", pwd
.pw_name
);
314 if (nss_nametosid(nss
, pwd
.pw_name
, &sid
) != 0) {
318 printf("\tSID %s\n", sid
);
320 if (nss_sidtoname(nss
, sid
, &name2
) != 0) {
324 printf("\tSID->name %s\n", name2
);
326 if (nss_getusersids(nss
, sid
, &group_sids
) != 0) {
327 perror("getusersids");
331 printf("\tGroups:\n");
332 for (i
=0; group_sids
[i
]; i
++) {
333 printf("\t\t%s\n", group_sids
[i
]);
343 if (nss_endpwent(nss
) != 0) {
353 main program. It lists all users, listing user SIDs for each user
355 int main(int argc
, char *argv
[])
357 struct nss_state nss
;
358 const char *so_path
= "/lib/libnss_winbind.so";
365 if (nss_open(&nss
, so_path
) != 0) {
370 ret
= nss_test_users(&nss
);