source: vendor/3.6.23/examples/nss/nss_winbind.c

Last change on this file was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

File size: 7.4 KB
Line 
1/*
2 nss sample code for extended winbindd functionality
3
4 Copyright (C) Andrew Tridgell (tridge@samba.org)
5
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.
9*/
10
11#define _GNU_SOURCE
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <nss.h>
16#include <dlfcn.h>
17#include <errno.h>
18#include <string.h>
19#include <sys/types.h>
20
21#include "nss_winbind.h"
22
23/*
24 find a function in the nss library
25*/
26static void *find_fn(struct nss_state *nss, const char *name)
27{
28 void *res;
29 char *s = NULL;
30
31 asprintf(&s, "_nss_%s_%s", nss->nss_name, name);
32 if (!s) {
33 errno = ENOMEM;
34 return NULL;
35 }
36 res = dlsym(nss->dl_handle, s);
37 free(s);
38 if (!res) {
39 errno = ENOENT;
40 return NULL;
41 }
42 return res;
43}
44
45/*
46 establish a link to the nss library
47 Return 0 on success and -1 on error
48*/
49int nss_open(struct nss_state *nss, const char *nss_path)
50{
51 char *p;
52 p = strrchr(nss_path, '_');
53 if (!p) {
54 errno = EINVAL;
55 return -1;
56 }
57
58 nss->nss_name = strdup(p+1);
59 p = strchr(nss->nss_name, '.');
60 if (p) *p = 0;
61
62 nss->dl_handle = dlopen(nss_path, RTLD_LAZY);
63 if (!nss->dl_handle) {
64 free(nss->nss_name);
65 return -1;
66 }
67
68 return 0;
69}
70
71/*
72 close and cleanup a nss state
73*/
74void nss_close(struct nss_state *nss)
75{
76 free(nss->nss_name);
77 dlclose(nss->dl_handle);
78}
79
80/*
81 make a getpwnam call.
82 Return 0 on success and -1 on error
83*/
84int nss_getpwent(struct nss_state *nss, struct passwd *pwd)
85{
86 enum nss_status (*_nss_getpwent_r)(struct passwd *, char *,
87 size_t , int *);
88 enum nss_status status;
89 int nss_errno = 0;
90
91 _nss_getpwent_r = find_fn(nss, "getpwent_r");
92
93 if (!_nss_getpwent_r) {
94 return -1;
95 }
96
97 status = _nss_getpwent_r(pwd, nss->pwnam_buf, sizeof(nss->pwnam_buf),
98 &nss_errno);
99 if (status == NSS_STATUS_NOTFOUND) {
100 errno = ENOENT;
101 return -1;
102 }
103 if (status != NSS_STATUS_SUCCESS) {
104 errno = nss_errno;
105 return -1;
106 }
107
108 return 0;
109}
110
111/*
112 make a setpwent call.
113 Return 0 on success and -1 on error
114*/
115int nss_setpwent(struct nss_state *nss)
116{
117 enum nss_status (*_nss_setpwent)(void) = find_fn(nss, "setpwent");
118 enum nss_status status;
119 if (!_nss_setpwent) {
120 return -1;
121 }
122 status = _nss_setpwent();
123 if (status != NSS_STATUS_SUCCESS) {
124 errno = EINVAL;
125 return -1;
126 }
127 return 0;
128}
129
130/*
131 make a endpwent call.
132 Return 0 on success and -1 on error
133*/
134int nss_endpwent(struct nss_state *nss)
135{
136 enum nss_status (*_nss_endpwent)(void) = find_fn(nss, "endpwent");
137 enum nss_status status;
138 if (!_nss_endpwent) {
139 return -1;
140 }
141 status = _nss_endpwent();
142 if (status != NSS_STATUS_SUCCESS) {
143 errno = EINVAL;
144 return -1;
145 }
146 return 0;
147}
148
149
150/*
151 convert a name to a SID
152 caller frees
153 Return 0 on success and -1 on error
154*/
155int nss_nametosid(struct nss_state *nss, const char *name, char **sid)
156{
157 enum nss_status (*_nss_nametosid)(const char *, char **, char *,
158 size_t, int *);
159 enum nss_status status;
160 int nss_errno = 0;
161 char buf[200];
162
163 _nss_nametosid = find_fn(nss, "nametosid");
164
165 if (!_nss_nametosid) {
166 return -1;
167 }
168
169 status = _nss_nametosid(name, sid, buf, sizeof(buf), &nss_errno);
170 if (status == NSS_STATUS_NOTFOUND) {
171 errno = ENOENT;
172 return -1;
173 }
174 if (status != NSS_STATUS_SUCCESS) {
175 errno = nss_errno;
176 return -1;
177 }
178
179 *sid = strdup(*sid);
180
181 return 0;
182}
183
184/*
185 convert a SID to a name
186 caller frees
187 Return 0 on success and -1 on error
188*/
189int nss_sidtoname(struct nss_state *nss, const char *sid, char **name)
190{
191 enum nss_status (*_nss_sidtoname)(const char *, char **, char *,
192 size_t, int *);
193 enum nss_status status;
194 int nss_errno = 0;
195 char buf[200];
196
197 _nss_sidtoname = find_fn(nss, "sidtoname");
198
199 if (!_nss_sidtoname) {
200 return -1;
201 }
202
203 status = _nss_sidtoname(sid, name, buf, sizeof(buf), &nss_errno);
204 if (status == NSS_STATUS_NOTFOUND) {
205 errno = ENOENT;
206 return -1;
207 }
208 if (status != NSS_STATUS_SUCCESS) {
209 errno = nss_errno;
210 return -1;
211 }
212
213 *name = strdup(*name);
214
215 return 0;
216}
217
218/*
219 return a list of group SIDs for a user SID
220 the returned list is NULL terminated
221 Return 0 on success and -1 on error
222*/
223int nss_getusersids(struct nss_state *nss, const char *user_sid, char ***sids)
224{
225 enum nss_status (*_nss_getusersids)(const char *, char **, int *,
226 char *, size_t, int *);
227 enum nss_status status;
228 int nss_errno = 0;
229 char *s;
230 int i, num_groups = 0;
231 unsigned bufsize = 10;
232 char *buf;
233
234 _nss_getusersids = find_fn(nss, "getusersids");
235
236 if (!_nss_getusersids) {
237 return -1;
238 }
239
240again:
241 buf = malloc(bufsize);
242 if (!buf) {
243 errno = ENOMEM;
244 return -1;
245 }
246
247 status = _nss_getusersids(user_sid, &s, &num_groups, buf, bufsize,
248 &nss_errno);
249
250 if (status == NSS_STATUS_NOTFOUND) {
251 errno = ENOENT;
252 free(buf);
253 return -1;
254 }
255
256 if (status == NSS_STATUS_TRYAGAIN) {
257 bufsize *= 2;
258 free(buf);
259 goto again;
260 }
261
262 if (status != NSS_STATUS_SUCCESS) {
263 free(buf);
264 errno = nss_errno;
265 return -1;
266 }
267
268 if (num_groups == 0) {
269 free(buf);
270 return 0;
271 }
272
273 *sids = (char **)malloc(sizeof(char *) * (num_groups+1));
274 if (! *sids) {
275 errno = ENOMEM;
276 free(buf);
277 return -1;
278 }
279
280 for (i=0;i<num_groups;i++) {
281 (*sids)[i] = strdup(s);
282 s += strlen(s) + 1;
283 }
284 (*sids)[i] = NULL;
285
286 free(buf);
287
288 return 0;
289}
290
291/*
292 convert a sid to a uid
293 Return 0 on success and -1 on error
294*/
295int nss_sidtouid(struct nss_state *nss, const char *sid, uid_t *uid)
296{
297 enum nss_status (*_nss_sidtouid)(const char*, uid_t *, int*);
298
299 enum nss_status status;
300 int nss_errno = 0;
301
302 _nss_sidtouid = find_fn(nss, "sidtouid");
303
304 if (!_nss_sidtouid) {
305 return -1;
306 }
307
308 status = _nss_sidtouid(sid, uid, &nss_errno);
309
310 if (status == NSS_STATUS_NOTFOUND) {
311 errno = ENOENT;
312 return -1;
313 }
314
315 if (status != NSS_STATUS_SUCCESS) {
316 errno = nss_errno;
317 return -1;
318 }
319
320 return 0;
321}
322
323/*
324 convert a sid to a gid
325 Return 0 on success and -1 on error
326*/
327int nss_sidtogid(struct nss_state *nss, const char *sid, gid_t *gid)
328{
329 enum nss_status (*_nss_sidtogid)(const char*, gid_t *, int*);
330
331 enum nss_status status;
332 int nss_errno = 0;
333
334 _nss_sidtogid = find_fn(nss, "sidtogid");
335
336 if (!_nss_sidtogid) {
337 return -1;
338 }
339
340 status = _nss_sidtogid(sid, gid, &nss_errno);
341
342 if (status == NSS_STATUS_NOTFOUND) {
343 errno = ENOENT;
344 return -1;
345 }
346
347 if (status != NSS_STATUS_SUCCESS) {
348 errno = nss_errno;
349 return -1;
350 }
351
352 return 0;
353}
354
355/*
356 convert a uid to a sid
357 caller frees
358 Return 0 on success and -1 on error
359*/
360int nss_uidtosid(struct nss_state *nss, uid_t uid, char **sid)
361{
362 enum nss_status (*_nss_uidtosid)(uid_t, char **, char *,
363 size_t, int *);
364 enum nss_status status;
365 int nss_errno = 0;
366 char buf[200];
367
368 _nss_uidtosid = find_fn(nss, "uidtosid");
369
370 if (!_nss_uidtosid) {
371 return -1;
372 }
373
374 status = _nss_uidtosid(uid, sid, buf, sizeof(buf), &nss_errno);
375 if (status == NSS_STATUS_NOTFOUND) {
376 errno = ENOENT;
377 return -1;
378 }
379 if (status != NSS_STATUS_SUCCESS) {
380 errno = nss_errno;
381 return -1;
382 }
383
384 *sid = strdup(*sid);
385
386 return 0;
387}
388
389/*
390 convert a gid to a sid
391 caller frees
392 Return 0 on success and -1 on error
393*/
394int nss_gidtosid(struct nss_state *nss, gid_t gid, char **sid)
395{
396 enum nss_status (*_nss_gidtosid)(gid_t, char **, char *,
397 size_t, int *);
398 enum nss_status status;
399 int nss_errno = 0;
400 char buf[200];
401
402 _nss_gidtosid = find_fn(nss, "gidtosid");
403
404 if (!_nss_gidtosid) {
405 return -1;
406 }
407
408 status = _nss_gidtosid(gid, sid, buf, sizeof(buf), &nss_errno);
409 if (status == NSS_STATUS_NOTFOUND) {
410 errno = ENOENT;
411 return -1;
412 }
413 if (status != NSS_STATUS_SUCCESS) {
414 errno = nss_errno;
415 return -1;
416 }
417
418 *sid = strdup(*sid);
419
420 return 0;
421}
422
Note: See TracBrowser for help on using the repository browser.