root/source3/lib/ldb/nssldb/ldb-nss.c

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

DEFINITIONS

This source file includes following definitions.
  1. _ldb_nss_init
  2. _ldb_nss_fill_passwd
  3. _ldb_nss_fill_group
  4. _ldb_nss_fill_initgr
  5. _ldb_nss_group_request

   1 /* 
   2    LDB nsswitch module
   3 
   4    Copyright (C) Simo Sorce 2006
   5    
   6    This library is free software; you can redistribute it and/or
   7    modify it under the terms of the GNU Lesser General Public
   8    License as published by the Free Software Foundation; either
   9    version 3 of the License, or (at your option) any later version.
  10    
  11    This library is distributed in the hope that it will be useful,
  12    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14    Library General Public License for more details.
  15    
  16    You should have received a copy of the GNU Lesser General Public License
  17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19 
  20 #include "ldb-nss.h"
  21 
  22 struct _ldb_nss_context *_ldb_nss_ctx = NULL;
  23 
  24 NSS_STATUS _ldb_nss_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
  25 {
  26         int ret;
  27 
  28         pid_t mypid = getpid();
  29 
  30         if (_ldb_nss_ctx != NULL) {
  31                 if (_ldb_nss_ctx->pid == mypid) {
  32                         /* already initialized */
  33                         return NSS_STATUS_SUCCESS;
  34                 } else {
  35                         /* we are in a forked child now, reinitialize */
  36                         talloc_free(_ldb_nss_ctx);
  37                         _ldb_nss_ctx = NULL;
  38                 }
  39         }
  40                 
  41         _ldb_nss_ctx = talloc_named(NULL, 0, "_ldb_nss_ctx(%u)", mypid);
  42         if (_ldb_nss_ctx == NULL) {
  43                 return NSS_STATUS_UNAVAIL;
  44         }
  45 
  46         _ldb_nss_ctx->pid = mypid;
  47 
  48         ret = ldb_global_init();
  49         if (ret != 0) {
  50                 goto failed;
  51         }
  52 
  53         _ldb_nss_ctx->ldb = ldb_init(_ldb_nss_ctx);
  54         if (_ldb_nss_ctx->ldb == NULL) {
  55                 goto failed;
  56         }
  57 
  58         ret = ldb_connect(_ldb_nss_ctx->ldb, _LDB_NSS_URL, LDB_FLG_RDONLY, NULL);
  59         if (ret != LDB_SUCCESS) {
  60                 goto failed;
  61         }
  62 
  63         _ldb_nss_ctx->base = ldb_dn_explode(_ldb_nss_ctx, _LDB_NSS_BASEDN);
  64         if (_ldb_nss_ctx->base == NULL) {
  65                 goto failed;
  66         }
  67 
  68         _ldb_nss_ctx->pw_cur = 0;
  69         _ldb_nss_ctx->pw_res = NULL;
  70         _ldb_nss_ctx->gr_cur = 0;
  71         _ldb_nss_ctx->gr_res = NULL;
  72 
  73         return NSS_STATUS_SUCCESS;
  74 
  75 failed:
  76         /* talloc_free(_ldb_nss_ctx); */
  77         _ldb_nss_ctx = NULL;
  78         return NSS_STATUS_UNAVAIL;
  79 }
  80 
  81 NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result,
     /* [<][>][^][v][top][bottom][index][help] */
  82                                 char *buffer,
  83                                 int buflen,
  84                                 int *errnop,
  85                                 struct ldb_message *msg)
  86 {
  87         int len;
  88         int bufpos;
  89         const char *tmp;
  90 
  91         bufpos = 0;
  92 
  93         /* get username */
  94         tmp = ldb_msg_find_attr_as_string(msg, "uid", NULL);
  95         if (tmp == NULL) {
  96                 /* this is a fatal error */
  97                 *errnop = errno = ENOENT;
  98                 return NSS_STATUS_UNAVAIL;
  99         }
 100         len = strlen(tmp)+1;
 101         if (bufpos + len > buflen) {
 102                 /* buffer too small */
 103                 *errnop = errno = EAGAIN;
 104                 return NSS_STATUS_TRYAGAIN;
 105         }
 106         memcpy(&buffer[bufpos], tmp, len);
 107         result->pw_name = &buffer[bufpos];
 108         bufpos += len;
 109 
 110         /* get userPassword */
 111         tmp = ldb_msg_find_attr_as_string(msg, "userPassword", NULL);
 112         if (tmp == NULL) {
 113                 tmp = "LDB";
 114         }
 115         len = strlen(tmp)+1;
 116         if (bufpos + len > buflen) {
 117                 /* buffer too small */
 118                 *errnop = errno = EAGAIN;
 119                 return NSS_STATUS_TRYAGAIN;
 120         }
 121         memcpy(&buffer[bufpos], tmp, len);
 122         result->pw_passwd = &buffer[bufpos];
 123         bufpos += len;
 124 
 125         /* this backend never serves an uid 0 user */
 126         result->pw_uid = ldb_msg_find_attr_as_int(msg, "uidNumber", 0);
 127         if (result->pw_uid == 0) {
 128                 /* this is a fatal error */
 129                 *errnop = errno = ENOENT;
 130                 return NSS_STATUS_UNAVAIL;
 131         }
 132 
 133         result->pw_gid = ldb_msg_find_attr_as_int(msg, "gidNumber", 0);
 134         if (result->pw_gid == 0) {
 135                 /* this is a fatal error */
 136                 *errnop = errno = ENOENT;
 137                 return NSS_STATUS_UNAVAIL;
 138         }
 139 
 140         /* get gecos */
 141         tmp = ldb_msg_find_attr_as_string(msg, "gecos", NULL);
 142         if (tmp == NULL) {
 143                 tmp = "";
 144         }
 145         len = strlen(tmp)+1;
 146         if (bufpos + len > buflen) {
 147                 /* buffer too small */
 148                 *errnop = errno = EAGAIN;
 149                 return NSS_STATUS_TRYAGAIN;
 150         }
 151         memcpy(&buffer[bufpos], tmp, len);
 152         result->pw_gecos = &buffer[bufpos];
 153         bufpos += len;
 154 
 155         /* get homeDirectory */
 156         tmp = ldb_msg_find_attr_as_string(msg, "homeDirectory", NULL);
 157         if (tmp == NULL) {
 158                 tmp = "";
 159         }
 160         len = strlen(tmp)+1;
 161         if (bufpos + len > buflen) {
 162                 /* buffer too small */
 163                 *errnop = errno = EAGAIN;
 164                 return NSS_STATUS_TRYAGAIN;
 165         }
 166         memcpy(&buffer[bufpos], tmp, len);
 167         result->pw_dir = &buffer[bufpos];
 168         bufpos += len;
 169 
 170         /* get shell */
 171         tmp = ldb_msg_find_attr_as_string(msg, "loginShell", NULL);
 172         if (tmp == NULL) {
 173                 tmp = "";
 174         }
 175         len = strlen(tmp)+1;
 176         if (bufpos + len > buflen) {
 177                 /* buffer too small */
 178                 *errnop = errno = EAGAIN;
 179                 return NSS_STATUS_TRYAGAIN;
 180         }
 181         memcpy(&buffer[bufpos], tmp, len);
 182         result->pw_shell = &buffer[bufpos];
 183         bufpos += len;
 184 
 185         return NSS_STATUS_SUCCESS;
 186 }
 187 
 188 NSS_STATUS _ldb_nss_fill_group(struct group *result,
     /* [<][>][^][v][top][bottom][index][help] */
 189                                 char *buffer,
 190                                 int buflen,
 191                                 int *errnop,
 192                                 struct ldb_message *group,
 193                                 struct ldb_result *members)
 194 {
 195         const char *tmp;
 196         size_t len;
 197         size_t bufpos;
 198         size_t lsize;
 199         int i;
 200 
 201         bufpos = 0;
 202 
 203         /* get group name */
 204         tmp = ldb_msg_find_attr_as_string(group, "cn", NULL);
 205         if (tmp == NULL) {
 206                 /* this is a fatal error */
 207                 *errnop = errno = ENOENT;
 208                 return NSS_STATUS_UNAVAIL;
 209         }
 210         len = strlen(tmp)+1;
 211         if (bufpos + len > buflen) {
 212                 /* buffer too small */
 213                 *errnop = errno = EAGAIN;
 214                 return NSS_STATUS_TRYAGAIN;
 215         }
 216         memcpy(&buffer[bufpos], tmp, len);
 217         result->gr_name = &buffer[bufpos];
 218         bufpos += len;
 219 
 220         /* get userPassword */
 221         tmp = ldb_msg_find_attr_as_string(group, "userPassword", NULL);
 222         if (tmp == NULL) {
 223                 tmp = "LDB";
 224         }
 225         len = strlen(tmp)+1;
 226         if (bufpos + len > buflen) {
 227                 /* buffer too small */
 228                 *errnop = errno = EAGAIN;
 229                 return NSS_STATUS_TRYAGAIN;
 230         }
 231         memcpy(&buffer[bufpos], tmp, len);
 232         result->gr_passwd = &buffer[bufpos];
 233         bufpos += len;
 234 
 235         result->gr_gid = ldb_msg_find_attr_as_int(group, "gidNumber", 0);
 236         if (result->gr_gid == 0) {
 237                 /* this is a fatal error */
 238                 *errnop = errno = ENOENT;
 239                 return NSS_STATUS_UNAVAIL;
 240         }
 241 
 242         /* check if there is enough memory for the list of pointers */
 243         lsize = (members->count + 1) * sizeof(char *);
 244 
 245         /* align buffer on pointer boundary */
 246         bufpos += (sizeof(char*) - ((unsigned long)(buffer) % sizeof(char*)));
 247         if ((buflen - bufpos) < lsize) {
 248                 /* buffer too small */
 249                 *errnop = errno = EAGAIN;
 250                 return NSS_STATUS_TRYAGAIN;
 251         } 
 252 
 253         result->gr_mem = (char **)&buffer[bufpos];
 254         bufpos += lsize;
 255 
 256         for (i = 0; i < members->count; i++) {
 257                 tmp = ldb_msg_find_attr_as_string(members->msgs[i], "uid", NULL);
 258                 if (tmp == NULL) {
 259                         /* this is a fatal error */
 260                         *errnop = errno = ENOENT;
 261                         return NSS_STATUS_UNAVAIL;
 262                 }
 263                 len = strlen(tmp)+1;
 264                 if (bufpos + len > buflen) {
 265                         /* buffer too small */
 266                         *errnop = errno = EAGAIN;
 267                         return NSS_STATUS_TRYAGAIN;
 268                 }
 269                 memcpy(&buffer[bufpos], tmp, len);
 270                 result->gr_mem[i] = &buffer[bufpos];
 271                 bufpos += len;
 272         }
 273 
 274         result->gr_mem[i] = NULL;
 275 
 276         return NSS_STATUS_SUCCESS;
 277 }
 278 
 279 NSS_STATUS _ldb_nss_fill_initgr(gid_t group,
     /* [<][>][^][v][top][bottom][index][help] */
 280                                 long int limit,
 281                                 long int *start,
 282                                 long int *size,
 283                                 gid_t **groups,
 284                                 int *errnop,
 285                                 struct ldb_result *grlist)
 286 {
 287         NSS_STATUS ret;
 288         int i;
 289 
 290         for (i = 0; i < grlist->count; i++) {
 291 
 292                 if (limit && (*start > limit)) {
 293                         /* TODO: warn no all groups were reported */
 294                         *errnop = 0;
 295                         ret = NSS_STATUS_SUCCESS;
 296                         goto done;
 297                 }
 298 
 299                 if (*start == *size) {
 300                         /* buffer full, enlarge it */
 301                         long int gs;
 302                         gid_t *gm;
 303 
 304                         gs = (*size) + 32;
 305                         if (limit && (gs > limit)) {
 306                                 gs = limit;
 307                         }
 308 
 309                         gm = (gid_t *)realloc((*groups), gs * sizeof(gid_t));
 310                         if ( ! gm) {
 311                                 *errnop = ENOMEM;
 312                                 ret = NSS_STATUS_UNAVAIL;
 313                                 goto done;
 314                         }
 315 
 316                         *groups = gm;
 317                         *size = gs;
 318                 }
 319 
 320                 (*groups)[*start] = ldb_msg_find_attr_as_int(grlist->msgs[i], "gidNumber", 0);
 321                 if ((*groups)[*start] == 0 || (*groups)[*start] == group) {
 322                         /* skip root group or primary group */
 323                         continue;
 324                 }
 325                 (*start)++;
 326 
 327         }
 328 
 329         *errnop = 0;
 330         ret = NSS_STATUS_SUCCESS;
 331 done:
 332         return ret;
 333 }
 334 
 335 #define _LDB_NSS_ALLOC_CHECK(mem) do { if (!mem) { errno = ENOMEM; return NSS_STATUS_UNAVAIL; } } while(0)
 336 
 337 NSS_STATUS _ldb_nss_group_request(struct ldb_result **_res,
     /* [<][>][^][v][top][bottom][index][help] */
 338                                         struct ldb_dn *group_dn,
 339                                         const char * const *attrs,
 340                                         const char *mattr)
 341 {
 342         struct ldb_control **ctrls;
 343         struct ldb_control *ctrl;
 344         struct ldb_asq_control *asqc;
 345         struct ldb_request *req;
 346         int ret;
 347         struct ldb_result *res = *_res;
 348 
 349         ctrls = talloc_array(res, struct ldb_control *, 2);
 350         _LDB_NSS_ALLOC_CHECK(ctrls);
 351 
 352         ctrl = talloc(ctrls, struct ldb_control);
 353         _LDB_NSS_ALLOC_CHECK(ctrl);
 354 
 355         asqc = talloc(ctrl, struct ldb_asq_control);
 356         _LDB_NSS_ALLOC_CHECK(asqc);
 357 
 358         asqc->source_attribute = talloc_strdup(asqc, mattr);
 359         _LDB_NSS_ALLOC_CHECK(asqc->source_attribute);
 360 
 361         asqc->request = 1;
 362         asqc->src_attr_len = strlen(asqc->source_attribute);
 363         ctrl->oid = LDB_CONTROL_ASQ_OID;
 364         ctrl->critical = 1;
 365         ctrl->data = asqc;
 366         ctrls[0] = ctrl;
 367         ctrls[1] = NULL;
 368 
 369         ret = ldb_build_search_req(
 370                                 &req,
 371                                 _ldb_nss_ctx->ldb,
 372                                 res,
 373                                 group_dn,
 374                                 LDB_SCOPE_BASE,
 375                                 "(objectClass=*)",
 376                                 attrs,
 377                                 ctrls,
 378                                 res,
 379                                 ldb_search_default_callback);
 380         
 381         if (ret != LDB_SUCCESS) {
 382                 errno = ENOENT;
 383                 return NSS_STATUS_UNAVAIL;
 384         }
 385 
 386         ldb_set_timeout(_ldb_nss_ctx->ldb, req, 0);
 387 
 388         ret = ldb_request(_ldb_nss_ctx->ldb, req);
 389 
 390         if (ret == LDB_SUCCESS) {
 391                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
 392         } else {
 393                 talloc_free(req);
 394                 return NSS_STATUS_UNAVAIL;
 395         }
 396 
 397         talloc_free(req);
 398         return NSS_STATUS_SUCCESS;
 399 }
 400 

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