root/examples/nss/nss_winbind.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. find_fn
  2. nss_open
  3. nss_close
  4. nss_getpwent
  5. nss_setpwent
  6. nss_endpwent
  7. nss_nametosid
  8. nss_sidtoname
  9. nss_getusersids
  10. nss_sidtouid
  11. nss_sidtogid
  12. nss_uidtosid
  13. nss_gidtosid

   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 */
  26 static void *find_fn(struct nss_state *nss, const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
  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 */
  49 int nss_open(struct nss_state *nss, const char *nss_path)
     /* [<][>][^][v][top][bottom][index][help] */
  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 */
  74 void nss_close(struct nss_state *nss)
     /* [<][>][^][v][top][bottom][index][help] */
  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 */
  84 int nss_getpwent(struct nss_state *nss, struct passwd *pwd)
     /* [<][>][^][v][top][bottom][index][help] */
  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 */
 115 int nss_setpwent(struct nss_state *nss)
     /* [<][>][^][v][top][bottom][index][help] */
 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 */
 134 int nss_endpwent(struct nss_state *nss)
     /* [<][>][^][v][top][bottom][index][help] */
 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 */
 155 int nss_nametosid(struct nss_state *nss, const char *name, char **sid)
     /* [<][>][^][v][top][bottom][index][help] */
 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 */
 189 int nss_sidtoname(struct nss_state *nss, const char *sid, char **name)
     /* [<][>][^][v][top][bottom][index][help] */
 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 */
 223 int nss_getusersids(struct nss_state *nss, const char *user_sid, char ***sids)
     /* [<][>][^][v][top][bottom][index][help] */
 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 
 240 again:
 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 */
 295 int nss_sidtouid(struct nss_state *nss, const char *sid, uid_t *uid)
     /* [<][>][^][v][top][bottom][index][help] */
 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 */
 327 int nss_sidtogid(struct nss_state *nss, const char *sid, gid_t *gid)
     /* [<][>][^][v][top][bottom][index][help] */
 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 */
 360 int nss_uidtosid(struct nss_state *nss, uid_t uid, char **sid)
     /* [<][>][^][v][top][bottom][index][help] */
 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 */
 394 int nss_gidtosid(struct nss_state *nss, gid_t gid, char **sid)
     /* [<][>][^][v][top][bottom][index][help] */
 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 

/* [<][>][^][v][top][bottom][index][help] */