root/source4/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         _ldb_nss_ctx->ldb = ldb_init(_ldb_nss_ctx, NULL);
  49         if (_ldb_nss_ctx->ldb == NULL) {
  50                 goto failed;
  51         }
  52 
  53         ret = ldb_connect(_ldb_nss_ctx->ldb, _LDB_NSS_URL, LDB_FLG_RDONLY, NULL);
  54         if (ret != LDB_SUCCESS) {
  55                 goto failed;
  56         }
  57 
  58         _ldb_nss_ctx->base = ldb_dn_new(_ldb_nss_ctx, _ldb_nss_ctx->ldb, _LDB_NSS_BASEDN);
  59         if ( ! ldb_dn_validate(_ldb_nss_ctx->base)) {
  60                 goto failed;
  61         }
  62 
  63         _ldb_nss_ctx->pw_cur = 0;
  64         _ldb_nss_ctx->pw_res = NULL;
  65         _ldb_nss_ctx->gr_cur = 0;
  66         _ldb_nss_ctx->gr_res = NULL;
  67 
  68         return NSS_STATUS_SUCCESS;
  69 
  70 failed:
  71         /* talloc_free(_ldb_nss_ctx); */
  72         _ldb_nss_ctx = NULL;
  73         return NSS_STATUS_UNAVAIL;
  74 }
  75 
  76 NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result,
     /* [<][>][^][v][top][bottom][index][help] */
  77                                 char *buffer,
  78                                 int buflen,
  79                                 int *errnop,
  80                                 struct ldb_message *msg)
  81 {
  82         int len;
  83         int bufpos;
  84         const char *tmp;
  85 
  86         bufpos = 0;
  87 
  88         /* get username */
  89         tmp = ldb_msg_find_attr_as_string(msg, "uid", NULL);
  90         if (tmp == NULL) {
  91                 /* this is a fatal error */
  92                 *errnop = errno = ENOENT;
  93                 return NSS_STATUS_UNAVAIL;
  94         }
  95         len = strlen(tmp)+1;
  96         if (bufpos + len > buflen) {
  97                 /* buffer too small */
  98                 *errnop = errno = EAGAIN;
  99                 return NSS_STATUS_TRYAGAIN;
 100         }
 101         memcpy(&buffer[bufpos], tmp, len);
 102         result->pw_name = &buffer[bufpos];
 103         bufpos += len;
 104 
 105         /* get userPassword */
 106         tmp = ldb_msg_find_attr_as_string(msg, "userPassword", NULL);
 107         if (tmp == NULL) {
 108                 tmp = "LDB";
 109         }
 110         len = strlen(tmp)+1;
 111         if (bufpos + len > buflen) {
 112                 /* buffer too small */
 113                 *errnop = errno = EAGAIN;
 114                 return NSS_STATUS_TRYAGAIN;
 115         }
 116         memcpy(&buffer[bufpos], tmp, len);
 117         result->pw_passwd = &buffer[bufpos];
 118         bufpos += len;
 119 
 120         /* this backend never serves an uid 0 user */
 121         result->pw_uid = ldb_msg_find_attr_as_int(msg, "uidNumber", 0);
 122         if (result->pw_uid == 0) {
 123                 /* this is a fatal error */
 124                 *errnop = errno = ENOENT;
 125                 return NSS_STATUS_UNAVAIL;
 126         }
 127 
 128         result->pw_gid = ldb_msg_find_attr_as_int(msg, "gidNumber", 0);
 129         if (result->pw_gid == 0) {
 130                 /* this is a fatal error */
 131                 *errnop = errno = ENOENT;
 132                 return NSS_STATUS_UNAVAIL;
 133         }
 134 
 135         /* get gecos */
 136         tmp = ldb_msg_find_attr_as_string(msg, "gecos", NULL);
 137         if (tmp == NULL) {
 138                 tmp = "";
 139         }
 140         len = strlen(tmp)+1;
 141         if (bufpos + len > buflen) {
 142                 /* buffer too small */
 143                 *errnop = errno = EAGAIN;
 144                 return NSS_STATUS_TRYAGAIN;
 145         }
 146         memcpy(&buffer[bufpos], tmp, len);
 147         result->pw_gecos = &buffer[bufpos];
 148         bufpos += len;
 149 
 150         /* get homeDirectory */
 151         tmp = ldb_msg_find_attr_as_string(msg, "homeDirectory", NULL);
 152         if (tmp == NULL) {
 153                 tmp = "";
 154         }
 155         len = strlen(tmp)+1;
 156         if (bufpos + len > buflen) {
 157                 /* buffer too small */
 158                 *errnop = errno = EAGAIN;
 159                 return NSS_STATUS_TRYAGAIN;
 160         }
 161         memcpy(&buffer[bufpos], tmp, len);
 162         result->pw_dir = &buffer[bufpos];
 163         bufpos += len;
 164 
 165         /* get shell */
 166         tmp = ldb_msg_find_attr_as_string(msg, "loginShell", NULL);
 167         if (tmp == NULL) {
 168                 tmp = "";
 169         }
 170         len = strlen(tmp)+1;
 171         if (bufpos + len > buflen) {
 172                 /* buffer too small */
 173                 *errnop = errno = EAGAIN;
 174                 return NSS_STATUS_TRYAGAIN;
 175         }
 176         memcpy(&buffer[bufpos], tmp, len);
 177         result->pw_shell = &buffer[bufpos];
 178         bufpos += len;
 179 
 180         return NSS_STATUS_SUCCESS;
 181 }
 182 
 183 NSS_STATUS _ldb_nss_fill_group(struct group *result,
     /* [<][>][^][v][top][bottom][index][help] */
 184                                 char *buffer,
 185                                 int buflen,
 186                                 int *errnop,
 187                                 struct ldb_message *group,
 188                                 struct ldb_result *members)
 189 {
 190         const char *tmp;
 191         size_t len;
 192         size_t bufpos;
 193         size_t lsize;
 194         int i;
 195 
 196         bufpos = 0;
 197 
 198         /* get group name */
 199         tmp = ldb_msg_find_attr_as_string(group, "cn", NULL);
 200         if (tmp == NULL) {
 201                 /* this is a fatal error */
 202                 *errnop = errno = ENOENT;
 203                 return NSS_STATUS_UNAVAIL;
 204         }
 205         len = strlen(tmp)+1;
 206         if (bufpos + len > buflen) {
 207                 /* buffer too small */
 208                 *errnop = errno = EAGAIN;
 209                 return NSS_STATUS_TRYAGAIN;
 210         }
 211         memcpy(&buffer[bufpos], tmp, len);
 212         result->gr_name = &buffer[bufpos];
 213         bufpos += len;
 214 
 215         /* get userPassword */
 216         tmp = ldb_msg_find_attr_as_string(group, "userPassword", NULL);
 217         if (tmp == NULL) {
 218                 tmp = "LDB";
 219         }
 220         len = strlen(tmp)+1;
 221         if (bufpos + len > buflen) {
 222                 /* buffer too small */
 223                 *errnop = errno = EAGAIN;
 224                 return NSS_STATUS_TRYAGAIN;
 225         }
 226         memcpy(&buffer[bufpos], tmp, len);
 227         result->gr_passwd = &buffer[bufpos];
 228         bufpos += len;
 229 
 230         result->gr_gid = ldb_msg_find_attr_as_int(group, "gidNumber", 0);
 231         if (result->gr_gid == 0) {
 232                 /* this is a fatal error */
 233                 *errnop = errno = ENOENT;
 234                 return NSS_STATUS_UNAVAIL;
 235         }
 236 
 237         /* check if there is enough memory for the list of pointers */
 238         lsize = (members->count + 1) * sizeof(char *);
 239 
 240         /* align buffer on pointer boundary */
 241         bufpos += (sizeof(char*) - ((unsigned long)(buffer) % sizeof(char*)));
 242         if ((buflen - bufpos) < lsize) {
 243                 /* buffer too small */
 244                 *errnop = errno = EAGAIN;
 245                 return NSS_STATUS_TRYAGAIN;
 246         } 
 247 
 248         result->gr_mem = (char **)&buffer[bufpos];
 249         bufpos += lsize;
 250 
 251         for (i = 0; i < members->count; i++) {
 252                 tmp = ldb_msg_find_attr_as_string(members->msgs[i], "uid", NULL);
 253                 if (tmp == NULL) {
 254                         /* this is a fatal error */
 255                         *errnop = errno = ENOENT;
 256                         return NSS_STATUS_UNAVAIL;
 257                 }
 258                 len = strlen(tmp)+1;
 259                 if (bufpos + len > buflen) {
 260                         /* buffer too small */
 261                         *errnop = errno = EAGAIN;
 262                         return NSS_STATUS_TRYAGAIN;
 263                 }
 264                 memcpy(&buffer[bufpos], tmp, len);
 265                 result->gr_mem[i] = &buffer[bufpos];
 266                 bufpos += len;
 267         }
 268 
 269         result->gr_mem[i] = NULL;
 270 
 271         return NSS_STATUS_SUCCESS;
 272 }
 273 
 274 NSS_STATUS _ldb_nss_fill_initgr(gid_t group,
     /* [<][>][^][v][top][bottom][index][help] */
 275                                 long int limit,
 276                                 long int *start,
 277                                 long int *size,
 278                                 gid_t **groups,
 279                                 int *errnop,
 280                                 struct ldb_result *grlist)
 281 {
 282         NSS_STATUS ret;
 283         int i;
 284 
 285         for (i = 0; i < grlist->count; i++) {
 286 
 287                 if (limit && (*start > limit)) {
 288                         /* TODO: warn no all groups were reported */
 289                         *errnop = 0;
 290                         ret = NSS_STATUS_SUCCESS;
 291                         goto done;
 292                 }
 293 
 294                 if (*start == *size) {
 295                         /* buffer full, enlarge it */
 296                         long int gs;
 297                         gid_t *gm;
 298 
 299                         gs = (*size) + 32;
 300                         if (limit && (gs > limit)) {
 301                                 gs = limit;
 302                         }
 303 
 304                         gm = (gid_t *)realloc((*groups), gs * sizeof(gid_t));
 305                         if ( ! gm) {
 306                                 *errnop = ENOMEM;
 307                                 ret = NSS_STATUS_UNAVAIL;
 308                                 goto done;
 309                         }
 310 
 311                         *groups = gm;
 312                         *size = gs;
 313                 }
 314 
 315                 (*groups)[*start] = ldb_msg_find_attr_as_int(grlist->msgs[i], "gidNumber", 0);
 316                 if ((*groups)[*start] == 0 || (*groups)[*start] == group) {
 317                         /* skip root group or primary group */
 318                         continue;
 319                 }
 320                 (*start)++;
 321 
 322         }
 323 
 324         *errnop = 0;
 325         ret = NSS_STATUS_SUCCESS;
 326 done:
 327         return ret;
 328 }
 329 
 330 #define _LDB_NSS_ALLOC_CHECK(mem) do { if (!mem) { errno = ENOMEM; return NSS_STATUS_UNAVAIL; } } while(0)
 331 
 332 NSS_STATUS _ldb_nss_group_request(struct ldb_result **_res,
     /* [<][>][^][v][top][bottom][index][help] */
 333                                         struct ldb_dn *group_dn,
 334                                         const char * const *attrs,
 335                                         const char *mattr)
 336 {
 337         struct ldb_control **ctrls;
 338         struct ldb_control *ctrl;
 339         struct ldb_asq_control *asqc;
 340         struct ldb_request *req;
 341         int ret;
 342         struct ldb_result *res = *_res;
 343 
 344         ctrls = talloc_array(res, struct ldb_control *, 2);
 345         _LDB_NSS_ALLOC_CHECK(ctrls);
 346 
 347         ctrl = talloc(ctrls, struct ldb_control);
 348         _LDB_NSS_ALLOC_CHECK(ctrl);
 349 
 350         asqc = talloc(ctrl, struct ldb_asq_control);
 351         _LDB_NSS_ALLOC_CHECK(asqc);
 352 
 353         asqc->source_attribute = talloc_strdup(asqc, mattr);
 354         _LDB_NSS_ALLOC_CHECK(asqc->source_attribute);
 355 
 356         asqc->request = 1;
 357         asqc->src_attr_len = strlen(asqc->source_attribute);
 358         ctrl->oid = LDB_CONTROL_ASQ_OID;
 359         ctrl->critical = 1;
 360         ctrl->data = asqc;
 361         ctrls[0] = ctrl;
 362         ctrls[1] = NULL;
 363 
 364         ret = ldb_build_search_req(
 365                                 &req,
 366                                 _ldb_nss_ctx->ldb,
 367                                 res,
 368                                 group_dn,
 369                                 LDB_SCOPE_BASE,
 370                                 "(objectClass=*)",
 371                                 attrs,
 372                                 ctrls,
 373                                 res,
 374                                 ldb_search_default_callback);
 375         
 376         if (ret != LDB_SUCCESS) {
 377                 errno = ENOENT;
 378                 return NSS_STATUS_UNAVAIL;
 379         }
 380 
 381         ldb_set_timeout(_ldb_nss_ctx->ldb, req, 0);
 382 
 383         ret = ldb_request(_ldb_nss_ctx->ldb, req);
 384 
 385         if (ret == LDB_SUCCESS) {
 386                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
 387         } else {
 388                 talloc_free(req);
 389                 return NSS_STATUS_UNAVAIL;
 390         }
 391 
 392         talloc_free(req);
 393         return NSS_STATUS_SUCCESS;
 394 }
 395 

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